diff options
Diffstat (limited to 'support')
47 files changed, 5223 insertions, 0 deletions
diff --git a/support/Makefile b/support/Makefile new file mode 100644 index 0000000..6b8598b --- /dev/null +++ b/support/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for linux-nfs/support +# + +SUBDIRS = include nfs export lib +.DEFAULT: all + +include $(TOP)rules.mk + 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; +} + diff --git a/support/include/Makefile b/support/include/Makefile new file mode 100644 index 0000000..e1cbfc4 --- /dev/null +++ b/support/include/Makefile @@ -0,0 +1,16 @@ +# +# Makefile for linux-nfs/support +# + +include $(TOP)rules.mk + +all install:: mount.h + @: + +distclean:: + $(RM) mount.h config.h + +mount.h: + $(LN_S) ../export/mount.h . + +# .EXPORT_ALL_VARIABLES: diff --git a/support/include/config.h.in b/support/include/config.h.in new file mode 100644 index 0000000..f8c1497 --- /dev/null +++ b/support/include/config.h.in @@ -0,0 +1,25 @@ +/* Define this if you have standard C headers + */ +#undef STDC_HEADERS + +/* Define this if you have string.h */ +#undef HAVE_STRING_H + +/* Define this if you have netgroup support + */ +#undef HAVE_INNETGR + +/* Define this if you want NFSv3 support compiled in + */ +#undef NFS3_SUPPORTED + +/* This defines the location of the NFS state files + * Warning: these must match definitions in config.mk! + */ +#define NFS_STATEDIR "/var/lib/nfs" + +/* Define this if you want to enable various security + * checks in statd. These checks basically keep anyone + * but lockd from using this service. + */ +#undef RESTRICTED_STATD diff --git a/support/include/exportfs.h b/support/include/exportfs.h new file mode 100644 index 0000000..d440dc1 --- /dev/null +++ b/support/include/exportfs.h @@ -0,0 +1,80 @@ +/* + * support/include/exportfs.h + * + * Declarations for exportfs and mountd + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef EXPORTFS_H +#define EXPORTFS_H + +#include <netdb.h> +#include "nfslib.h" + +enum { + MCL_FQDN = 0, + MCL_SUBNETWORK, + MCL_IPADDR = MCL_SUBNETWORK, + MCL_WILDCARD, + MCL_NETGROUP, + MCL_ANONYMOUS, + MCL_MAXTYPES +}; + +typedef struct mclient { + struct mclient * m_next; + char m_hostname[NFSCLNT_IDMAX+1]; + int m_type; + int m_naddr; + struct in_addr m_addrlist[NFSCLNT_ADDRMAX]; + int m_exported; /* exported to nfsd */ + int m_count; +} nfs_client; + +typedef struct mexport { + struct mexport * m_next; + struct mclient * m_client; + struct exportent m_export; + int m_exported : 1, /* known to knfsd */ + m_xtabent : 1, /* xtab entry exists */ + m_mayexport: 1, /* derived from xtabbed */ + m_changed : 1; /* options (may) have changed */ +} nfs_export; + +extern nfs_client * clientlist[MCL_MAXTYPES]; +extern nfs_export * exportlist[MCL_MAXTYPES]; + +nfs_client * client_lookup(char *hname); +nfs_client * client_find(struct hostent *); +void client_add(nfs_client *); +nfs_client * client_dup(nfs_client *, struct hostent *); +int client_gettype(char *hname); +int client_check(nfs_client *, struct hostent *); +int client_match(nfs_client *, char *hname); +void client_release(nfs_client *); +void client_freeall(void); + +int export_read(char *fname); +void export_add(nfs_export *); +void export_reset(nfs_export *); +nfs_export * export_lookup(char *hname, char *path); +nfs_export * export_find(struct hostent *, char *path); +struct exportent * export_allowed(struct hostent *, char *path); +nfs_export * export_create(struct exportent *); +nfs_export * export_dup(nfs_export *, struct hostent *); +void export_freeall(void); +int export_export(nfs_export *); +int export_unexport(nfs_export *); + +int xtab_mount_read(void); +int xtab_export_read(void); +int xtab_mount_write(void); +int xtab_export_write(void); +void xtab_append(nfs_export *); + +int rmtab_read(void); + +struct nfskey * key_lookup(char *hname); + +#endif /* EXPORTFS_H */ diff --git a/support/include/misc.h b/support/include/misc.h new file mode 100644 index 0000000..a3cdcfd --- /dev/null +++ b/support/include/misc.h @@ -0,0 +1,24 @@ +/* + * misc.h All that didn't fit elsewhere. + * + * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef MISC_H +#define MISC_H + +/* + * Generate random key, returning the length of the result. Currently, + * weakrandomkey generates a maximum of 20 bytes are generated, but this + * may change with future implementations. + */ +int randomkey(unsigned char *keyout, int len); +int weakrandomkey(unsigned char *keyout, int len); + +int matchhostname(const char *h1, const char *h2); + +struct hostent; +struct hostent *hostent_dup(struct hostent *hp); +struct hostent *get_hostent (const char *addr, int len, int type); + +#endif /* MISC_H */ diff --git a/support/include/nfs/debug.h b/support/include/nfs/debug.h new file mode 100644 index 0000000..876b5db --- /dev/null +++ b/support/include/nfs/debug.h @@ -0,0 +1,75 @@ +#ifndef _NFS_DEBUG_H +#define _NFS_DEBUG_H + +/* + * RPC debug facilities + */ +#define RPCDBG_XPRT 0x0001 +#define RPCDBG_CALL 0x0002 +#define RPCDBG_DEBUG 0x0004 +#define RPCDBG_NFS 0x0008 +#define RPCDBG_AUTH 0x0010 +#define RPCDBG_PMAP 0x0020 +#define RPCDBG_SCHED 0x0040 +#define RPCDBG_SVCSOCK 0x0100 +#define RPCDBG_SVCDSP 0x0200 +#define RPCDBG_MISC 0x0400 +#define RPCDBG_ALL 0x7fff + +/* + * Declarations for the sysctl debug interface, which allows to read or + * change the debug flags for rpc, nfs, nfsd, and lockd. Since the sunrpc + * module currently registers its sysctl table dynamically, the sysctl path + * for module FOO is <CTL_SUNRPC, CTL_FOODEBUG>. + */ +#define CTL_SUNRPC 7249 /* arbitrary and hopefully unused */ + +enum { + CTL_RPCDEBUG = 1, + CTL_NFSDEBUG, + CTL_NFSDDEBUG, + CTL_NLMDEBUG, +}; + + +/* + * knfsd debug flags + */ +#define NFSDDBG_SOCK 0x0001 +#define NFSDDBG_FH 0x0002 +#define NFSDDBG_EXPORT 0x0004 +#define NFSDDBG_SVC 0x0008 +#define NFSDDBG_PROC 0x0010 +#define NFSDDBG_FILEOP 0x0020 +#define NFSDDBG_AUTH 0x0040 +#define NFSDDBG_REPCACHE 0x0080 +#define NFSDDBG_XDR 0x0100 +#define NFSDDBG_LOCKD 0x0200 +#define NFSDDBG_ALL 0x7FFF +#define NFSDDBG_NOCHANGE 0xFFFF + +/* + * Debug flags + */ +#define NLMDBG_SVC 0x0001 +#define NLMDBG_CLIENT 0x0002 +#define NLMDBG_CLNTLOCK 0x0004 +#define NLMDBG_SVCLOCK 0x0008 +#define NLMDBG_MONITOR 0x0010 +#define NLMDBG_CLNTSUBS 0x0020 +#define NLMDBG_SVCSUBS 0x0040 +#define NLMDBG_HOSTCACHE 0x0080 +#define NLMDBG_ALL 0x7fff + + +#define NFSDBG_VFS 0x0001 +#define NFSDBG_DIRCACHE 0x0002 +#define NFSDBG_LOOKUPCACHE 0x0004 +#define NFSDBG_PAGECACHE 0x0008 +#define NFSDBG_PROC 0x0010 +#define NFSDBG_XDR 0x0020 +#define NFSDBG_FILE 0x0040 +#define NFSDBG_ROOT 0x0080 +#define NFSDBG_ALL 0xFFFF + +#endif /* _NFS_DEBUG_H */ diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h new file mode 100644 index 0000000..80d23fd --- /dev/null +++ b/support/include/nfs/export.h @@ -0,0 +1,26 @@ +#ifndef _NSF_EXPORT_H +#define _NSF_EXPORT_H + +/* + * Important limits for the exports stuff. + */ +#define NFSCLNT_IDMAX 1024 +#define NFSCLNT_ADDRMAX 16 +#define NFSCLNT_KEYMAX 32 + +/* + * Export flags. + */ +#define NFSEXP_READONLY 0x0001 +#define NFSEXP_INSECURE_PORT 0x0002 +#define NFSEXP_ROOTSQUASH 0x0004 +#define NFSEXP_ALLSQUASH 0x0008 +#define NFSEXP_ASYNC 0x0010 +#define NFSEXP_GATHERED_WRITES 0x0020 +#define NFSEXP_UIDMAP 0x0040 +#define NFSEXP_KERBEROS 0x0080 /* not available */ +#define NFSEXP_SUNSECURE 0x0100 +#define NFSEXP_CROSSMNT 0x0200 /* not available */ +#define NFSEXP_ALLFLAGS 0x03FF + +#endif /* _NSF_EXPORT_H */ diff --git a/support/include/nfs/nfs.h b/support/include/nfs/nfs.h new file mode 100644 index 0000000..0cfed07 --- /dev/null +++ b/support/include/nfs/nfs.h @@ -0,0 +1,145 @@ +#ifndef _NFS_NFS_H +#define _NFS_NFS_H + +#include <linux/posix_types.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <rpcsvc/nfs_prot.h> +#include <nfs/export.h> + +struct dentry; + +/* + * This is the new "dentry style" Linux NFSv2 file handle. + * + * The xino and xdev fields are currently used to transport the + * ino/dev of the exported inode. + */ +struct nfs_fhbase { + struct dentry * fb_dentry; /* dentry cookie */ + u_int32_t fb_ino; /* our inode number */ + u_int32_t fb_dirino; /* dir inode number */ + u_int32_t fb_dev; /* our device */ + u_int32_t fb_xdev; + u_int32_t fb_xino; +}; + +#define NFS_FH_PADDING (NFS_FHSIZE - sizeof(struct nfs_fhbase)) +struct knfs_fh { + struct nfs_fhbase fh_base; + u_int8_t fh_cookie[NFS_FH_PADDING]; +}; + +#define fh_dcookie fh_base.fb_dentry +#define fh_ino fh_base.fb_ino +#define fh_dirino fh_base.fb_dirino +#define fh_dev fh_base.fb_dev +#define fh_xdev fh_base.fb_xdev +#define fh_xino fh_base.fb_xino + +/* + * Version of the syscall interface + */ +#define NFSCTL_VERSION 0x0201 + +/* + * These are the commands understood by nfsctl(). + */ +#define NFSCTL_SVC 0 /* This is a server process. */ +#define NFSCTL_ADDCLIENT 1 /* Add an NFS client. */ +#define NFSCTL_DELCLIENT 2 /* Remove an NFS client. */ +#define NFSCTL_EXPORT 3 /* export a file system. */ +#define NFSCTL_UNEXPORT 4 /* unexport a file system. */ +#define NFSCTL_UGIDUPDATE 5 /* update a client's uid/gid map. */ +#define NFSCTL_GETFH 6 /* get an fh (used by mountd) */ +#define NFSCTL_GETFD 7 /* get an fh by path (used by mountd) */ + +/* Above this is for lockd. */ +#define NFSCTL_LOCKD 0x10000 +#define LOCKDCTL_SVC NFSCTL_LOCKD + + + +/* SVC */ +struct nfsctl_svc { + unsigned short svc_port; + int svc_nthreads; +}; + +/* ADDCLIENT/DELCLIENT */ +struct nfsctl_client { + char cl_ident[NFSCLNT_IDMAX+1]; + int cl_naddr; + struct in_addr cl_addrlist[NFSCLNT_ADDRMAX]; + int cl_fhkeytype; + int cl_fhkeylen; + unsigned char cl_fhkey[NFSCLNT_KEYMAX]; +}; + +/* EXPORT/UNEXPORT */ +struct nfsctl_export { + char ex_client[NFSCLNT_IDMAX+1]; + char ex_path[NFS_MAXPATHLEN+1]; + __kernel_dev_t ex_dev; + __kernel_ino_t ex_ino; + int ex_flags; + __kernel_uid_t ex_anon_uid; + __kernel_gid_t ex_anon_gid; +}; + +/* UGIDUPDATE */ +struct nfsctl_uidmap { + char * ug_ident; + __kernel_uid_t ug_uidbase; + int ug_uidlen; + __kernel_uid_t * ug_udimap; + __kernel_gid_t ug_gidbase; + int ug_gidlen; + __kernel_gid_t * ug_gdimap; +}; + +/* GETFH */ +struct nfsctl_fhparm { + struct sockaddr gf_addr; + __kernel_dev_t gf_dev; + __kernel_ino_t gf_ino; + int gf_version; +}; + +/* GETFD */ +struct nfsctl_fdparm { + struct sockaddr gd_addr; + char gd_path[NFS_MAXPATHLEN+1]; + int gd_version; +}; + +/* + * This is the argument union. + */ +struct nfsctl_arg { + int ca_version; /* safeguard */ + union { + struct nfsctl_svc u_svc; + struct nfsctl_client u_client; + struct nfsctl_export u_export; + struct nfsctl_uidmap u_umap; + struct nfsctl_fhparm u_getfh; + struct nfsctl_fdparm u_getfd; + unsigned int u_debug; + } u; +#define ca_svc u.u_svc +#define ca_client u.u_client +#define ca_export u.u_export +#define ca_umap u.u_umap +#define ca_getfh u.u_getfh +#define ca_getfd u.u_getfd +#define ca_authd u.u_authd +#define ca_debug u.u_debug +}; + +union nfsctl_res { + struct knfs_fh cr_getfh; + unsigned int cr_debug; +}; + +#endif /* _NFS_NFS_H */ diff --git a/support/include/nfslib.h b/support/include/nfslib.h new file mode 100644 index 0000000..d8be926 --- /dev/null +++ b/support/include/nfslib.h @@ -0,0 +1,125 @@ +/* + * support/include/nfslib.h + * + * General support functions for NFS user-space programs. + * + * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef NFSLIB_H +#define NFSLIB_H + +#include "config.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <stdio.h> +#include <paths.h> +#include <rpcsvc/nfs_prot.h> +#include <nfs/nfs.h> +#include "xlog.h" + +#ifndef _PATH_EXPORTS +#define _PATH_EXPORTS "/etc/exports" +#endif +#ifndef _PATH_XTAB +#define _PATH_XTAB NFS_STATEDIR "/xtab" +#endif +#ifndef _PATH_XTABTMP +#define _PATH_XTABTMP NFS_STATEDIR "/xtab.tmp" +#endif +#ifndef _PATH_ETAB +#define _PATH_ETAB NFS_STATEDIR "/etab" +#endif +#ifndef _PATH_ETABTMP +#define _PATH_ETABTMP NFS_STATEDIR "/etab.tmp" +#endif +#ifndef _PATH_RMTAB +#define _PATH_RMTAB NFS_STATEDIR "/rmtab" +#endif +#ifndef _PATH_RMTABTMP +#define _PATH_RMTABTMP _PATH_RMTAB ".tmp" +#endif +#ifndef _PATH_PROC_EXPORTS +#define _PATH_PROC_EXPORTS "/proc/fs/nfs/exports" +#endif + +enum cle_maptypes { + CLE_MAP_IDENT = 0, + CLE_MAP_FILE, + CLE_MAP_UGIDD, +}; + +/* + * Data related to a single exports entry as returned by getexportent. + * FIXME: export options should probably be parsed at a later time to + * allow overrides when using exportfs. + */ +struct exportent { + char e_hostname[NFSCLNT_IDMAX+1]; + char e_path[NFS_MAXPATHLEN+1]; + /* The mount path may be different from the exported path due + to submount. It may change for every mount. The idea is we + set m_path every time when we process a mount. We should not + use it for anything else. */ + char m_path[NFS_MAXPATHLEN+1]; + int e_flags; + int e_maptype; + int e_anonuid; + int e_anongid; + int * e_squids; + int e_nsquids; + int * e_sqgids; + int e_nsqgids; +}; + +struct rmtabent { + char r_client[NFSCLNT_IDMAX+1]; + char r_path[NFS_MAXPATHLEN+1]; +}; + +/* + * configuration file parsing + */ +void setexportent(char *fname, char *type); +struct exportent * getexportent(void); +void putexportent(struct exportent *xep); +void endexportent(void); +struct exportent * mkexportent(char *hname, char *path, char *opts); +void dupexportent(struct exportent *dst, + struct exportent *src); +int updateexportent(struct exportent *eep, char *options); + +int setrmtabent(char *type); +struct rmtabent * getrmtabent(int log); +void putrmtabent(struct rmtabent *xep); +void endrmtabent(void); +void rewindrmtabent(void); +FILE * fsetrmtabent(char *fname, char *type); +struct rmtabent * fgetrmtabent(FILE *fp, int log); +void fputrmtabent(FILE *fp, struct rmtabent *xep); +void fendrmtabent(FILE *fp); +void frewindrmtabent(FILE *fp); + +/* + * wildmat borrowed from INN + */ +int wildmat(char *text, char *pattern); + +/* + * nfsd library functions. + */ +int nfsctl(int, struct nfsctl_arg *, union nfsctl_res *); +int nfssvc(int port, int nrservs); +int nfsaddclient(struct nfsctl_client *clp); +int nfsdelclient(struct nfsctl_client *clp); +int nfsexport(struct nfsctl_export *exp); +int nfsunexport(struct nfsctl_export *exp); +struct knfs_fh * getfh_old(struct sockaddr *addr, dev_t dev, ino_t ino); +struct knfs_fh * getfh(struct sockaddr *addr, const char *); + +/* lockd. */ +int lockdsvc(); + +#endif /* NFSLIB_H */ diff --git a/support/include/rpcdispatch.h b/support/include/rpcdispatch.h new file mode 100644 index 0000000..866d4bf --- /dev/null +++ b/support/include/rpcdispatch.h @@ -0,0 +1,57 @@ +/* + * nlm_dispatch This is a generic RPC call dispatcher. + * It is loosely based on the dispatch mechanism I + * first encountered in the UNFSD source. + * + * Cyopright (C) 1995, Olaf Kirch <okir@monad.swb.de> + * + * 24.05.95 okir + * + */ + +#ifndef RPCDISPATCH_H +#define RPCDISPATCH_H + +#include <rpc/rpc.h> + +#ifdef __STDC__ +# define CONCAT(a,b) a##b +# define CONCAT3(a,b,c) a##b##c +# define STRING(a) #a +#else +# define CONCAT(a,b) a/**/b +# define CONCAT3(a,b,c) a/**/b/**/c +# define STRING(a) "a" +#endif + +#ifdef __STDC__ +typedef bool_t (*rpcsvc_fn_t)(struct svc_req *, void *argp, void *resp); +#else +typedef bool_t (*rpcsvc_fn_t)(); +#endif + +#define table_ent(func, vers, arg_type, res_type) \ + { STRING(func), \ + (rpcsvc_fn_t)CONCAT(func,_svc), vers,\ + (xdrproc_t)CONCAT(xdr_, arg_type), sizeof(arg_type), \ + (xdrproc_t)CONCAT(xdr_, res_type), sizeof(res_type), \ + } +#define nlm_undef_svc NULL +#define xdr_nlm_void xdr_void + +struct dispatch_entry { + const char *name; + rpcsvc_fn_t func; + unsigned int versions; /* bitmap of versions */ + xdrproc_t xdr_arg_fn; /* argument XDR */ + size_t xdr_arg_size; + xdrproc_t xdr_res_fn; /* result XDR */ + size_t xdr_res_size; +}; + +void rpc_dispatch(struct svc_req *rq, SVCXPRT *tp, + struct dispatch_entry *dtable, int nproc, + void *argp, void *resp); +void rpc_svcrun(void); + +#endif /* RPCDISPATCH_H */ diff --git a/support/include/rpcmisc.h b/support/include/rpcmisc.h new file mode 100644 index 0000000..06970cd --- /dev/null +++ b/support/include/rpcmisc.h @@ -0,0 +1,58 @@ +/* + * rpcmisc Support for RPC startup, dispatching and logging. + * + * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef RPCMISC_H +#define RPCMISC_H + +#include <rpc/rpc.h> +#include <rpc/pmap_clnt.h> + +#ifdef __STDC__ +# define CONCAT(a,b) a##b +# define STRING(a) #a +#else +# define CONCAT(a,b) a/**/b +# define STRING(a) "a" +#endif + +typedef bool_t (*rpcsvc_fn_t)(struct svc_req *, void *argp, void *resp); + +struct rpc_dentry { + const char *name; + rpcsvc_fn_t func; + xdrproc_t xdr_arg_fn; /* argument XDR */ + size_t xdr_arg_size; + xdrproc_t xdr_res_fn; /* result XDR */ + size_t xdr_res_size; +}; + +struct rpc_dtable { + struct rpc_dentry *entries; + int nproc; +}; + +#define dtable_ent(func, vers, arg_type, res_type) \ + { STRING(func), \ + (rpcsvc_fn_t)func##_##vers##_svc, \ + (xdrproc_t)xdr_##arg_type, sizeof(arg_type), \ + (xdrproc_t)xdr_##res_type, sizeof(res_type), \ + } + +void rpc_init(char *name, int prog, int vers, + void (*dispatch)(struct svc_req *, SVCXPRT *), + int defport, int bufsize); +void rpc_svcrun(void); +void rpc_dispatch(struct svc_req *rq, SVCXPRT *xprt, + struct rpc_dtable *dtable, int nvers, + void *argp, void *resp); +void rpc_logcall(struct svc_req *, char *xname, char *args); + +extern int _rpcpmstart; +extern int _rpcfdtype; +extern int _rpcsvcdirty; + + +#endif /* RPCMISC_H */ diff --git a/support/include/rpcsec.h b/support/include/rpcsec.h new file mode 100644 index 0000000..84d4497 --- /dev/null +++ b/support/include/rpcsec.h @@ -0,0 +1,39 @@ +/* + * Declarations needed for the authdes library. Some of the functions + * mentioned herein have been omitted from the Linux libc header files + */ + +#ifndef RPCSEC_H +#define RPCSEC_H + +int netname2user(char *netname, int *uidp, int *gidp, + int *gidlenp, int *gidlist); +int netname2host(char *netname, char *hostname, int hostlen); +int getnetname(char *name); +int user2netname(char *netname, int uid, char *domain); +int host2netname(char *netname, char *hostname, char *domain); +void passwd2des(char *pw, char *key); +int getsecretkey(char *netname, char *secretkey, char *passwd); +int getpublickey(char *hostname, char *publickey); +int yp_update(char *domain, char *map, unsigned int ypop, + char *key, int keylen, char *data, int datalen); +int key_setsecret(char *secret); +int xencrypt(char *secret, char *passwd); +int xdecrypt(char *secret, char *passwd); + + +#define PUBLICKEY_MAP "publickey.byname" +#define NETID_MAP "netid.byname" + +#ifndef DEBUG +#define RPCSEC_BASE "/etc/" +#else +#define RPCSEC_BASE "/tmp/" +#endif + +#define PUBLICKEY_FILE RPCSEC_BASE "publickey" +#define PUBLICKEY_LOCK RPCSEC_BASE "publickey.lock" +#define ROOTKEY_FILE RPCSEC_BASE ".rootkey" +#define KEYSTORE_FILE RPCSEC_BASE "keystore" + +#endif /* RPCSEC_H */ diff --git a/support/include/rpcsvc/nfs_prot.h b/support/include/rpcsvc/nfs_prot.h new file mode 100644 index 0000000..9311341 --- /dev/null +++ b/support/include/rpcsvc/nfs_prot.h @@ -0,0 +1,661 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _NFS_PROT_H_RPCGEN +#define _NFS_PROT_H_RPCGEN + +#include <rpc/rpc.h> + +#define NFS_PORT 2049 +#define NFS_MAXDATA 8192 +#define NFS_MAXPATHLEN 1024 +#define NFS_MAXNAMLEN 255 +#define NFS_FHSIZE 32 +#define NFS_COOKIESIZE 4 +#define NFS_FIFO_DEV -1 +#define NFSMODE_FMT 0170000 +#define NFSMODE_DIR 0040000 +#define NFSMODE_CHR 0020000 +#define NFSMODE_BLK 0060000 +#define NFSMODE_REG 0100000 +#define NFSMODE_LNK 0120000 +#define NFSMODE_SOCK 0140000 +#define NFSMODE_FIFO 0010000 + +enum nfsstat { + NFS_OK = 0, + NFSERR_PERM = 1, + NFSERR_NOENT = 2, + NFSERR_IO = 5, + NFSERR_NXIO = 6, + NFSERR_ACCES = 13, + NFSERR_EXIST = 17, + NFSERR_NODEV = 19, + NFSERR_NOTDIR = 20, + NFSERR_ISDIR = 21, + NFSERR_FBIG = 27, + NFSERR_NOSPC = 28, + NFSERR_ROFS = 30, + NFSERR_NAMETOOLONG = 63, + NFSERR_NOTEMPTY = 66, + NFSERR_DQUOT = 69, + NFSERR_STALE = 70, + NFSERR_WFLUSH = 99, +}; +typedef enum nfsstat nfsstat; +#ifdef __cplusplus +extern "C" bool_t xdr_nfsstat(XDR *, nfsstat*); +#elif __STDC__ +extern bool_t xdr_nfsstat(XDR *, nfsstat*); +#else /* Old Style C */ +bool_t xdr_nfsstat(); +#endif /* Old Style C */ + + +enum ftype { + NFNON = 0, + NFREG = 1, + NFDIR = 2, + NFBLK = 3, + NFCHR = 4, + NFLNK = 5, + NFSOCK = 6, + NFBAD = 7, + NFFIFO = 8, +}; +typedef enum ftype ftype; +#ifdef __cplusplus +extern "C" bool_t xdr_ftype(XDR *, ftype*); +#elif __STDC__ +extern bool_t xdr_ftype(XDR *, ftype*); +#else /* Old Style C */ +bool_t xdr_ftype(); +#endif /* Old Style C */ + + +struct nfs_fh { + char data[NFS_FHSIZE]; +}; +typedef struct nfs_fh nfs_fh; +#ifdef __cplusplus +extern "C" bool_t xdr_nfs_fh(XDR *, nfs_fh*); +#elif __STDC__ +extern bool_t xdr_nfs_fh(XDR *, nfs_fh*); +#else /* Old Style C */ +bool_t xdr_nfs_fh(); +#endif /* Old Style C */ + + +struct nfstime { + u_int seconds; + u_int useconds; +}; +typedef struct nfstime nfstime; +#ifdef __cplusplus +extern "C" bool_t xdr_nfstime(XDR *, nfstime*); +#elif __STDC__ +extern bool_t xdr_nfstime(XDR *, nfstime*); +#else /* Old Style C */ +bool_t xdr_nfstime(); +#endif /* Old Style C */ + + +struct fattr { + ftype type; + u_int mode; + u_int nlink; + u_int uid; + u_int gid; + u_int size; + u_int blocksize; + u_int rdev; + u_int blocks; + u_int fsid; + u_int fileid; + nfstime atime; + nfstime mtime; + nfstime ctime; +}; +typedef struct fattr fattr; +#ifdef __cplusplus +extern "C" bool_t xdr_fattr(XDR *, fattr*); +#elif __STDC__ +extern bool_t xdr_fattr(XDR *, fattr*); +#else /* Old Style C */ +bool_t xdr_fattr(); +#endif /* Old Style C */ + + +struct sattr { + u_int mode; + u_int uid; + u_int gid; + u_int size; + nfstime atime; + nfstime mtime; +}; +typedef struct sattr sattr; +#ifdef __cplusplus +extern "C" bool_t xdr_sattr(XDR *, sattr*); +#elif __STDC__ +extern bool_t xdr_sattr(XDR *, sattr*); +#else /* Old Style C */ +bool_t xdr_sattr(); +#endif /* Old Style C */ + + +typedef char *filename; +#ifdef __cplusplus +extern "C" bool_t xdr_filename(XDR *, filename*); +#elif __STDC__ +extern bool_t xdr_filename(XDR *, filename*); +#else /* Old Style C */ +bool_t xdr_filename(); +#endif /* Old Style C */ + + +typedef char *nfspath; +#ifdef __cplusplus +extern "C" bool_t xdr_nfspath(XDR *, nfspath*); +#elif __STDC__ +extern bool_t xdr_nfspath(XDR *, nfspath*); +#else /* Old Style C */ +bool_t xdr_nfspath(); +#endif /* Old Style C */ + + +struct attrstat { + nfsstat status; + union { + fattr attributes; + } attrstat_u; +}; +typedef struct attrstat attrstat; +#ifdef __cplusplus +extern "C" bool_t xdr_attrstat(XDR *, attrstat*); +#elif __STDC__ +extern bool_t xdr_attrstat(XDR *, attrstat*); +#else /* Old Style C */ +bool_t xdr_attrstat(); +#endif /* Old Style C */ + + +struct sattrargs { + nfs_fh file; + sattr attributes; +}; +typedef struct sattrargs sattrargs; +#ifdef __cplusplus +extern "C" bool_t xdr_sattrargs(XDR *, sattrargs*); +#elif __STDC__ +extern bool_t xdr_sattrargs(XDR *, sattrargs*); +#else /* Old Style C */ +bool_t xdr_sattrargs(); +#endif /* Old Style C */ + + +struct diropargs { + nfs_fh dir; + filename name; +}; +typedef struct diropargs diropargs; +#ifdef __cplusplus +extern "C" bool_t xdr_diropargs(XDR *, diropargs*); +#elif __STDC__ +extern bool_t xdr_diropargs(XDR *, diropargs*); +#else /* Old Style C */ +bool_t xdr_diropargs(); +#endif /* Old Style C */ + + +struct diropokres { + nfs_fh file; + fattr attributes; +}; +typedef struct diropokres diropokres; +#ifdef __cplusplus +extern "C" bool_t xdr_diropokres(XDR *, diropokres*); +#elif __STDC__ +extern bool_t xdr_diropokres(XDR *, diropokres*); +#else /* Old Style C */ +bool_t xdr_diropokres(); +#endif /* Old Style C */ + + +struct diropres { + nfsstat status; + union { + diropokres diropres; + } diropres_u; +}; +typedef struct diropres diropres; +#ifdef __cplusplus +extern "C" bool_t xdr_diropres(XDR *, diropres*); +#elif __STDC__ +extern bool_t xdr_diropres(XDR *, diropres*); +#else /* Old Style C */ +bool_t xdr_diropres(); +#endif /* Old Style C */ + + +struct readlinkres { + nfsstat status; + union { + nfspath data; + } readlinkres_u; +}; +typedef struct readlinkres readlinkres; +#ifdef __cplusplus +extern "C" bool_t xdr_readlinkres(XDR *, readlinkres*); +#elif __STDC__ +extern bool_t xdr_readlinkres(XDR *, readlinkres*); +#else /* Old Style C */ +bool_t xdr_readlinkres(); +#endif /* Old Style C */ + + +struct readargs { + nfs_fh file; + u_int offset; + u_int count; + u_int totalcount; +}; +typedef struct readargs readargs; +#ifdef __cplusplus +extern "C" bool_t xdr_readargs(XDR *, readargs*); +#elif __STDC__ +extern bool_t xdr_readargs(XDR *, readargs*); +#else /* Old Style C */ +bool_t xdr_readargs(); +#endif /* Old Style C */ + + +struct readokres { + fattr attributes; + struct { + u_int data_len; + char *data_val; + } data; +}; +typedef struct readokres readokres; +#ifdef __cplusplus +extern "C" bool_t xdr_readokres(XDR *, readokres*); +#elif __STDC__ +extern bool_t xdr_readokres(XDR *, readokres*); +#else /* Old Style C */ +bool_t xdr_readokres(); +#endif /* Old Style C */ + + +struct readres { + nfsstat status; + union { + readokres reply; + } readres_u; +}; +typedef struct readres readres; +#ifdef __cplusplus +extern "C" bool_t xdr_readres(XDR *, readres*); +#elif __STDC__ +extern bool_t xdr_readres(XDR *, readres*); +#else /* Old Style C */ +bool_t xdr_readres(); +#endif /* Old Style C */ + + +struct writeargs { + nfs_fh file; + u_int beginoffset; + u_int offset; + u_int totalcount; + struct { + u_int data_len; + char *data_val; + } data; +}; +typedef struct writeargs writeargs; +#ifdef __cplusplus +extern "C" bool_t xdr_writeargs(XDR *, writeargs*); +#elif __STDC__ +extern bool_t xdr_writeargs(XDR *, writeargs*); +#else /* Old Style C */ +bool_t xdr_writeargs(); +#endif /* Old Style C */ + + +struct createargs { + diropargs where; + sattr attributes; +}; +typedef struct createargs createargs; +#ifdef __cplusplus +extern "C" bool_t xdr_createargs(XDR *, createargs*); +#elif __STDC__ +extern bool_t xdr_createargs(XDR *, createargs*); +#else /* Old Style C */ +bool_t xdr_createargs(); +#endif /* Old Style C */ + + +struct renameargs { + diropargs from; + diropargs to; +}; +typedef struct renameargs renameargs; +#ifdef __cplusplus +extern "C" bool_t xdr_renameargs(XDR *, renameargs*); +#elif __STDC__ +extern bool_t xdr_renameargs(XDR *, renameargs*); +#else /* Old Style C */ +bool_t xdr_renameargs(); +#endif /* Old Style C */ + + +struct linkargs { + nfs_fh from; + diropargs to; +}; +typedef struct linkargs linkargs; +#ifdef __cplusplus +extern "C" bool_t xdr_linkargs(XDR *, linkargs*); +#elif __STDC__ +extern bool_t xdr_linkargs(XDR *, linkargs*); +#else /* Old Style C */ +bool_t xdr_linkargs(); +#endif /* Old Style C */ + + +struct symlinkargs { + diropargs from; + nfspath to; + sattr attributes; +}; +typedef struct symlinkargs symlinkargs; +#ifdef __cplusplus +extern "C" bool_t xdr_symlinkargs(XDR *, symlinkargs*); +#elif __STDC__ +extern bool_t xdr_symlinkargs(XDR *, symlinkargs*); +#else /* Old Style C */ +bool_t xdr_symlinkargs(); +#endif /* Old Style C */ + + +typedef char nfscookie[NFS_COOKIESIZE]; +#ifdef __cplusplus +extern "C" bool_t xdr_nfscookie(XDR *, nfscookie); +#elif __STDC__ +extern bool_t xdr_nfscookie(XDR *, nfscookie); +#else /* Old Style C */ +bool_t xdr_nfscookie(); +#endif /* Old Style C */ + + +struct readdirargs { + nfs_fh dir; + nfscookie cookie; + u_int count; +}; +typedef struct readdirargs readdirargs; +#ifdef __cplusplus +extern "C" bool_t xdr_readdirargs(XDR *, readdirargs*); +#elif __STDC__ +extern bool_t xdr_readdirargs(XDR *, readdirargs*); +#else /* Old Style C */ +bool_t xdr_readdirargs(); +#endif /* Old Style C */ + + +struct entry { + u_int fileid; + filename name; + nfscookie cookie; + struct entry *nextentry; +}; +typedef struct entry entry; +#ifdef __cplusplus +extern "C" bool_t xdr_entry(XDR *, entry*); +#elif __STDC__ +extern bool_t xdr_entry(XDR *, entry*); +#else /* Old Style C */ +bool_t xdr_entry(); +#endif /* Old Style C */ + + +struct dirlist { + entry *entries; + bool_t eof; +}; +typedef struct dirlist dirlist; +#ifdef __cplusplus +extern "C" bool_t xdr_dirlist(XDR *, dirlist*); +#elif __STDC__ +extern bool_t xdr_dirlist(XDR *, dirlist*); +#else /* Old Style C */ +bool_t xdr_dirlist(); +#endif /* Old Style C */ + + +struct readdirres { + nfsstat status; + union { + dirlist reply; + } readdirres_u; +}; +typedef struct readdirres readdirres; +#ifdef __cplusplus +extern "C" bool_t xdr_readdirres(XDR *, readdirres*); +#elif __STDC__ +extern bool_t xdr_readdirres(XDR *, readdirres*); +#else /* Old Style C */ +bool_t xdr_readdirres(); +#endif /* Old Style C */ + + +struct statfsokres { + u_int tsize; + u_int bsize; + u_int blocks; + u_int bfree; + u_int bavail; +}; +typedef struct statfsokres statfsokres; +#ifdef __cplusplus +extern "C" bool_t xdr_statfsokres(XDR *, statfsokres*); +#elif __STDC__ +extern bool_t xdr_statfsokres(XDR *, statfsokres*); +#else /* Old Style C */ +bool_t xdr_statfsokres(); +#endif /* Old Style C */ + + +struct statfsres { + nfsstat status; + union { + statfsokres reply; + } statfsres_u; +}; +typedef struct statfsres statfsres; +#ifdef __cplusplus +extern "C" bool_t xdr_statfsres(XDR *, statfsres*); +#elif __STDC__ +extern bool_t xdr_statfsres(XDR *, statfsres*); +#else /* Old Style C */ +bool_t xdr_statfsres(); +#endif /* Old Style C */ + + +#define NFS_PROGRAM ((u_long)100003) +#define NFS_VERSION ((u_long)2) + +#ifdef __cplusplus +#define NFSPROC_NULL ((u_long)0) +extern "C" void * nfsproc_null_2(void *, CLIENT *); +extern "C" void * nfsproc_null_2_svc(void *, struct svc_req *); +#define NFSPROC_GETATTR ((u_long)1) +extern "C" attrstat * nfsproc_getattr_2(nfs_fh *, CLIENT *); +extern "C" attrstat * nfsproc_getattr_2_svc(nfs_fh *, struct svc_req *); +#define NFSPROC_SETATTR ((u_long)2) +extern "C" attrstat * nfsproc_setattr_2(sattrargs *, CLIENT *); +extern "C" attrstat * nfsproc_setattr_2_svc(sattrargs *, struct svc_req *); +#define NFSPROC_ROOT ((u_long)3) +extern "C" void * nfsproc_root_2(void *, CLIENT *); +extern "C" void * nfsproc_root_2_svc(void *, struct svc_req *); +#define NFSPROC_LOOKUP ((u_long)4) +extern "C" diropres * nfsproc_lookup_2(diropargs *, CLIENT *); +extern "C" diropres * nfsproc_lookup_2_svc(diropargs *, struct svc_req *); +#define NFSPROC_READLINK ((u_long)5) +extern "C" readlinkres * nfsproc_readlink_2(nfs_fh *, CLIENT *); +extern "C" readlinkres * nfsproc_readlink_2_svc(nfs_fh *, struct svc_req *); +#define NFSPROC_READ ((u_long)6) +extern "C" readres * nfsproc_read_2(readargs *, CLIENT *); +extern "C" readres * nfsproc_read_2_svc(readargs *, struct svc_req *); +#define NFSPROC_WRITECACHE ((u_long)7) +extern "C" void * nfsproc_writecache_2(void *, CLIENT *); +extern "C" void * nfsproc_writecache_2_svc(void *, struct svc_req *); +#define NFSPROC_WRITE ((u_long)8) +extern "C" attrstat * nfsproc_write_2(writeargs *, CLIENT *); +extern "C" attrstat * nfsproc_write_2_svc(writeargs *, struct svc_req *); +#define NFSPROC_CREATE ((u_long)9) +extern "C" diropres * nfsproc_create_2(createargs *, CLIENT *); +extern "C" diropres * nfsproc_create_2_svc(createargs *, struct svc_req *); +#define NFSPROC_REMOVE ((u_long)10) +extern "C" nfsstat * nfsproc_remove_2(diropargs *, CLIENT *); +extern "C" nfsstat * nfsproc_remove_2_svc(diropargs *, struct svc_req *); +#define NFSPROC_RENAME ((u_long)11) +extern "C" nfsstat * nfsproc_rename_2(renameargs *, CLIENT *); +extern "C" nfsstat * nfsproc_rename_2_svc(renameargs *, struct svc_req *); +#define NFSPROC_LINK ((u_long)12) +extern "C" nfsstat * nfsproc_link_2(linkargs *, CLIENT *); +extern "C" nfsstat * nfsproc_link_2_svc(linkargs *, struct svc_req *); +#define NFSPROC_SYMLINK ((u_long)13) +extern "C" nfsstat * nfsproc_symlink_2(symlinkargs *, CLIENT *); +extern "C" nfsstat * nfsproc_symlink_2_svc(symlinkargs *, struct svc_req *); +#define NFSPROC_MKDIR ((u_long)14) +extern "C" diropres * nfsproc_mkdir_2(createargs *, CLIENT *); +extern "C" diropres * nfsproc_mkdir_2_svc(createargs *, struct svc_req *); +#define NFSPROC_RMDIR ((u_long)15) +extern "C" nfsstat * nfsproc_rmdir_2(diropargs *, CLIENT *); +extern "C" nfsstat * nfsproc_rmdir_2_svc(diropargs *, struct svc_req *); +#define NFSPROC_READDIR ((u_long)16) +extern "C" readdirres * nfsproc_readdir_2(readdirargs *, CLIENT *); +extern "C" readdirres * nfsproc_readdir_2_svc(readdirargs *, struct svc_req *); +#define NFSPROC_STATFS ((u_long)17) +extern "C" statfsres * nfsproc_statfs_2(nfs_fh *, CLIENT *); +extern "C" statfsres * nfsproc_statfs_2_svc(nfs_fh *, struct svc_req *); + +#elif __STDC__ +#define NFSPROC_NULL ((u_long)0) +extern void * nfsproc_null_2(void *, CLIENT *); +extern void * nfsproc_null_2_svc(void *, struct svc_req *); +#define NFSPROC_GETATTR ((u_long)1) +extern attrstat * nfsproc_getattr_2(nfs_fh *, CLIENT *); +extern attrstat * nfsproc_getattr_2_svc(nfs_fh *, struct svc_req *); +#define NFSPROC_SETATTR ((u_long)2) +extern attrstat * nfsproc_setattr_2(sattrargs *, CLIENT *); +extern attrstat * nfsproc_setattr_2_svc(sattrargs *, struct svc_req *); +#define NFSPROC_ROOT ((u_long)3) +extern void * nfsproc_root_2(void *, CLIENT *); +extern void * nfsproc_root_2_svc(void *, struct svc_req *); +#define NFSPROC_LOOKUP ((u_long)4) +extern diropres * nfsproc_lookup_2(diropargs *, CLIENT *); +extern diropres * nfsproc_lookup_2_svc(diropargs *, struct svc_req *); +#define NFSPROC_READLINK ((u_long)5) +extern readlinkres * nfsproc_readlink_2(nfs_fh *, CLIENT *); +extern readlinkres * nfsproc_readlink_2_svc(nfs_fh *, struct svc_req *); +#define NFSPROC_READ ((u_long)6) +extern readres * nfsproc_read_2(readargs *, CLIENT *); +extern readres * nfsproc_read_2_svc(readargs *, struct svc_req *); +#define NFSPROC_WRITECACHE ((u_long)7) +extern void * nfsproc_writecache_2(void *, CLIENT *); +extern void * nfsproc_writecache_2_svc(void *, struct svc_req *); +#define NFSPROC_WRITE ((u_long)8) +extern attrstat * nfsproc_write_2(writeargs *, CLIENT *); +extern attrstat * nfsproc_write_2_svc(writeargs *, struct svc_req *); +#define NFSPROC_CREATE ((u_long)9) +extern diropres * nfsproc_create_2(createargs *, CLIENT *); +extern diropres * nfsproc_create_2_svc(createargs *, struct svc_req *); +#define NFSPROC_REMOVE ((u_long)10) +extern nfsstat * nfsproc_remove_2(diropargs *, CLIENT *); +extern nfsstat * nfsproc_remove_2_svc(diropargs *, struct svc_req *); +#define NFSPROC_RENAME ((u_long)11) +extern nfsstat * nfsproc_rename_2(renameargs *, CLIENT *); +extern nfsstat * nfsproc_rename_2_svc(renameargs *, struct svc_req *); +#define NFSPROC_LINK ((u_long)12) +extern nfsstat * nfsproc_link_2(linkargs *, CLIENT *); +extern nfsstat * nfsproc_link_2_svc(linkargs *, struct svc_req *); +#define NFSPROC_SYMLINK ((u_long)13) +extern nfsstat * nfsproc_symlink_2(symlinkargs *, CLIENT *); +extern nfsstat * nfsproc_symlink_2_svc(symlinkargs *, struct svc_req *); +#define NFSPROC_MKDIR ((u_long)14) +extern diropres * nfsproc_mkdir_2(createargs *, CLIENT *); +extern diropres * nfsproc_mkdir_2_svc(createargs *, struct svc_req *); +#define NFSPROC_RMDIR ((u_long)15) +extern nfsstat * nfsproc_rmdir_2(diropargs *, CLIENT *); +extern nfsstat * nfsproc_rmdir_2_svc(diropargs *, struct svc_req *); +#define NFSPROC_READDIR ((u_long)16) +extern readdirres * nfsproc_readdir_2(readdirargs *, CLIENT *); +extern readdirres * nfsproc_readdir_2_svc(readdirargs *, struct svc_req *); +#define NFSPROC_STATFS ((u_long)17) +extern statfsres * nfsproc_statfs_2(nfs_fh *, CLIENT *); +extern statfsres * nfsproc_statfs_2_svc(nfs_fh *, struct svc_req *); + +#else /* Old Style C */ +#define NFSPROC_NULL ((u_long)0) +extern void * nfsproc_null_2(); +extern void * nfsproc_null_2_svc(); +#define NFSPROC_GETATTR ((u_long)1) +extern attrstat * nfsproc_getattr_2(); +extern attrstat * nfsproc_getattr_2_svc(); +#define NFSPROC_SETATTR ((u_long)2) +extern attrstat * nfsproc_setattr_2(); +extern attrstat * nfsproc_setattr_2_svc(); +#define NFSPROC_ROOT ((u_long)3) +extern void * nfsproc_root_2(); +extern void * nfsproc_root_2_svc(); +#define NFSPROC_LOOKUP ((u_long)4) +extern diropres * nfsproc_lookup_2(); +extern diropres * nfsproc_lookup_2_svc(); +#define NFSPROC_READLINK ((u_long)5) +extern readlinkres * nfsproc_readlink_2(); +extern readlinkres * nfsproc_readlink_2_svc(); +#define NFSPROC_READ ((u_long)6) +extern readres * nfsproc_read_2(); +extern readres * nfsproc_read_2_svc(); +#define NFSPROC_WRITECACHE ((u_long)7) +extern void * nfsproc_writecache_2(); +extern void * nfsproc_writecache_2_svc(); +#define NFSPROC_WRITE ((u_long)8) +extern attrstat * nfsproc_write_2(); +extern attrstat * nfsproc_write_2_svc(); +#define NFSPROC_CREATE ((u_long)9) +extern diropres * nfsproc_create_2(); +extern diropres * nfsproc_create_2_svc(); +#define NFSPROC_REMOVE ((u_long)10) +extern nfsstat * nfsproc_remove_2(); +extern nfsstat * nfsproc_remove_2_svc(); +#define NFSPROC_RENAME ((u_long)11) +extern nfsstat * nfsproc_rename_2(); +extern nfsstat * nfsproc_rename_2_svc(); +#define NFSPROC_LINK ((u_long)12) +extern nfsstat * nfsproc_link_2(); +extern nfsstat * nfsproc_link_2_svc(); +#define NFSPROC_SYMLINK ((u_long)13) +extern nfsstat * nfsproc_symlink_2(); +extern nfsstat * nfsproc_symlink_2_svc(); +#define NFSPROC_MKDIR ((u_long)14) +extern diropres * nfsproc_mkdir_2(); +extern diropres * nfsproc_mkdir_2_svc(); +#define NFSPROC_RMDIR ((u_long)15) +extern nfsstat * nfsproc_rmdir_2(); +extern nfsstat * nfsproc_rmdir_2_svc(); +#define NFSPROC_READDIR ((u_long)16) +extern readdirres * nfsproc_readdir_2(); +extern readdirres * nfsproc_readdir_2_svc(); +#define NFSPROC_STATFS ((u_long)17) +extern statfsres * nfsproc_statfs_2(); +extern statfsres * nfsproc_statfs_2_svc(); +#endif /* Old Style C */ + +#endif /* !_NFS_PROT_H_RPCGEN */ diff --git a/support/include/sys/fs/ext2fs.h b/support/include/sys/fs/ext2fs.h new file mode 100644 index 0000000..93b3e2b --- /dev/null +++ b/support/include/sys/fs/ext2fs.h @@ -0,0 +1,42 @@ +#ifndef _SYS_FS_EXT2FS_H +#define _SYS_FS_EXT2FS_H + +/* + * ioctl commands + */ +#define EXT2_IOC_GETFLAGS _IOR('f', 1, long) +#define EXT2_IOC_SETFLAGS _IOW('f', 2, long) +#define EXT2_IOC_GETVERSION _IOR('v', 1, long) +#define EXT2_IOC_SETVERSION _IOW('v', 2, long) + +/* + * File system states + */ +#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */ +#define EXT2_ERROR_FS 0x0002 /* Errors detected */ + +/* + * Mount flags + */ +#define EXT2_MOUNT_CHECK_NORMAL 0x0001 /* Do some more checks */ +#define EXT2_MOUNT_CHECK_STRICT 0x0002 /* Do again more checks */ +#define EXT2_MOUNT_CHECK (EXT2_MOUNT_CHECK_NORMAL | \ + EXT2_MOUNT_CHECK_STRICT) +#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */ +#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */ +#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */ +#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ +#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ +#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ + +#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt +#define set_opt(o, opt) o |= EXT2_MOUNT_##opt +#define test_opt(sb, opt) ((sb)->u.ext2_sb.s_mount_opt & \ + EXT2_MOUNT_##opt) +/* + * Maximal mount counts between two filesystem checks + */ +#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */ +#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */ + +#endif /* _SYS_FS_EXT2FS_H */ diff --git a/support/include/version.h b/support/include/version.h new file mode 100644 index 0000000..a74ec35 --- /dev/null +++ b/support/include/version.h @@ -0,0 +1 @@ +#define VERSION "1.4.7 (0.4.22)" diff --git a/support/include/xio.h b/support/include/xio.h new file mode 100644 index 0000000..858f5bb --- /dev/null +++ b/support/include/xio.h @@ -0,0 +1,26 @@ +/* + * xio.h Declarations for simple parsing functions. + * + */ + +#ifndef XIO_H +#define XIO_H + +#include <stdio.h> + +typedef struct XFILE { + FILE *x_fp; + int x_line; +} XFILE; + +XFILE *xfopen(char *fname, char *type); +int xflock(char *fname, char *type); +void xfunlock(int lockid); +void xfclose(XFILE *xfp); +int xgettok(XFILE *xfp, char sepa, char *tok, int len); +char xgetc(XFILE *xfp); +void xungetc(char c, XFILE *xfp); +void xskip(XFILE *xfp, char *str); +char xskipcomment(XFILE *xfp); + +#endif /* XIO_H */ diff --git a/support/include/xlog.h b/support/include/xlog.h new file mode 100644 index 0000000..2a839c7 --- /dev/null +++ b/support/include/xlog.h @@ -0,0 +1,40 @@ +/* + * xlog Logging functionality + * + * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef XLOG_H +#define XLOG_H + +#define L_FATAL 0x0100 +#define L_ERROR 0x0200 +#define L_WARNING 0x0400 +#define L_NOTICE 0x0800 +#define L_ALL 0xFF00 + +#define D_GENERAL 0x0001 /* general debug info */ +#define D_CALL 0x0002 +#define D_AUTH 0x0004 +#define D_FAC3 0x0008 +#define D_FAC4 0x0010 +#define D_FAC5 0x0020 +#define D_PARSE 0x0040 +#define D_FAC7 0x0080 +#define D_ALL 0x00FF + +/* This can be used to define symbolic log names that can be passed to + * xlog_config. */ +struct xlog_debugfac { + char *df_name; + int df_fac; +}; + +void xlog_open(char *progname); +void xlog_background(void); +void xlog_config(int fac, int on); +void xlog_sconfig(char *, int on); +int xlog_enabled(int fac); +void xlog(int fac, const char *fmt, ...); + +#endif /* XLOG_H */ diff --git a/support/include/xmalloc.h b/support/include/xmalloc.h new file mode 100644 index 0000000..866cfd8 --- /dev/null +++ b/support/include/xmalloc.h @@ -0,0 +1,16 @@ +/* + * xmalloc Module for memory allocation. Drop in your + * debugging malloc module if you feel like it. + * + * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef XMALLOC_H +#define XMALLOC_H + +void *xmalloc(size_t size); +void *xrealloc(void *ptr, size_t size); +char *xstrdup(const char *s); +void xfree(void *ptr); + +#endif /* XMALLOC_H */ diff --git a/support/include/ypupdate.h b/support/include/ypupdate.h new file mode 100644 index 0000000..e0cee15 --- /dev/null +++ b/support/include/ypupdate.h @@ -0,0 +1,16 @@ +/* + * ypupdate.h This file contains the public declarations for the + * ypupdate client side RPC stubs. + * + * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef YPUPDATE_H +#define YPUPDATE_H + +#include <rpcsvc/ypclnt.h> + +int yp_update(char *domain, char *map, unsigned int ypop, + char *key, int keylen, char *data, int datalen); + +#endif YPUPDATE_H diff --git a/support/lib/Makefile b/support/lib/Makefile new file mode 100644 index 0000000..b5fa14a --- /dev/null +++ b/support/lib/Makefile @@ -0,0 +1,13 @@ + +include $(TOP)rules.mk + +LIBS = libnfs.a libexport.a + +all install:: $(LIBS) + @: + +clean distclean:: + rm -f $(LIBS) + +lib%.a: + ln -sf ../$*/$@ . diff --git a/support/nfs/Makefile b/support/nfs/Makefile new file mode 100644 index 0000000..ed1e1ff --- /dev/null +++ b/support/nfs/Makefile @@ -0,0 +1,13 @@ +# +# linux-nfs/support/nfs/Makefile +# + +LIBNAME = libnfs.a +OBJS = exports.o rmtab.o xio.o \ + rpcmisc.o rpcdispatch.o xlog.o xmalloc.o wildmat.o \ + nfssvc.o nfsclient.o nfsexport.o getfh.o nfsctl.o lockdsvc.o + +include $(TOP)rules.mk + +install:: + @: diff --git a/support/nfs/clients.c b/support/nfs/clients.c new file mode 100644 index 0000000..b1970e0 --- /dev/null +++ b/support/nfs/clients.c @@ -0,0 +1,324 @@ +/* + * support/nfs/nfsclient.c + * + * Parse the nfsclients file. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <syslog.h> +#include <ctype.h> +#include "xmalloc.h" +#include "nfslib.h" +#include "exportfs.h" +#include "xio.h" + +static XFILE *cfp = NULL; +static int *squash_uids = NULL, + *squash_gids = NULL; +static int squash_uidlen = 0, + squash_gidlen = 0; +static char *hosts = NULL; + +static int parsesquash(char *list, int **idp, int *lenp); +static int parsenum(char **cpp); +static int parsekey(struct nfskey *keyp, char *str); +static int hexdigit(char c); +static int gettag(char *tag, int len); +static int getattr(char *attr, int alen, char *value, int vlen); +static void syntaxerr(char *msg); + +#ifndef isblank +#define isblank(c) ((c) == ' ' || (c) == '\t') +#endif + +void +setnfsclntent(char *fname) +{ + if (cfp) + xfclose(cfp); + if (!fname) + fname = _PATH_NFSCLIENTS; + if ((cfp = xfopen(fname)) == NULL) + xlog(L_ERROR, "can't open %s for reading", fname); +} + +struct nfsclntent * +getnfsclntent(void) +{ + static struct nfsclntent cle; + static char *hostptr = NULL; + char attr[32], val[512], *sp; + int ok; + + if (!cfp) + endnfsclntent(); + +again: + if (hosts) { + if (hostptr) + goto nexthost; + xfree(hosts); + hosts = NULL; + } + + if ((ok = gettag(cle.c_tag, sizeof(cle.c_tag))) < 0) + syntaxerr("expected tag"); + if (ok <= 0) + return NULL; + + cle.c_hostname[0] = '\0'; + cle.c_fhkey.k_type = CLE_KEY_NONE; + cle.c_mapping = CLE_MAP_IDENT; + cle.c_anonuid = -2; + cle.c_anongid = -2; + + if (squash_uids) + xfree(squash_uids); + if (squash_gids) + xfree(squash_gids); + squash_uids = squash_gids = NULL; + squash_uidlen = squash_gidlen = 0; + + while (ok) { + if ((ok = getattr(attr, sizeof(attr), val, sizeof(val))) < 0) + return NULL; + if (!ok) + break; + if (attr[0] == 'h' && !strcmp(attr, "hosts")) { + int l0 = hosts? strlen(hosts) : 0; + + hosts = (char *) xrealloc(hosts, l0+strlen(val)+2); + if (l0) + hosts[l0++] = ':'; + strcpy(hosts+l0, val); + } else + if (attr[0] == 'f' && !strcmp(attr, "fhmac")) { + if (!parsekey(&cle.c_fhkey, val)) + return NULL; + } else + if (attr[0] == 'm' && !strcmp(attr, "mapping")) { + if (!strcmp(val, "identity")) + cle.c_mapping = CLE_MAP_IDENT; + else if (!strcmp(val, "file")) + cle.c_mapping = CLE_MAP_FILE; + else if (!strcmp(val, "daemon")) + cle.c_mapping = CLE_MAP_UGIDD; + else { + syntaxerr("invalid mapping type"); + return NULL; + } + } else + if (attr[0] == 's' && !strcmp(attr, "squash_uids")) { + if (!parsesquash(val, &squash_uids, &squash_uidlen)) + return NULL; + } else + if (attr[0] == 's' && !strcmp(attr, "squash_gids")) { + if (!parsesquash(val, &squash_gids, &squash_gidlen)) + return NULL; + } else + if (attr[0] == 'a' && !strcmp(attr, "anonuid")) + cle.c_anonuid = atoi(val); + else + if (attr[0] == 'a' && !strcmp(attr, "anongid")) + cle.c_anongid = atoi(val); + else + syntaxerr("unknown attribute"); + } + + cle.c_squashuids = squash_uids; + cle.c_squashgids = squash_gids; + + /* This is the anon entry */ + if (!hosts) { + if (strcmp(cle.c_tag, "anonymous")) { + xlog(L_ERROR, "nfsclients entry %s allows anonymous " + "access. Ignored.", cle.c_tag); + goto again; + } + return &cle; + } + hostptr = hosts; + +nexthost: + if (*hostptr == ':' && strcmp(cle.c_tag, "anonymous")) { + xlog(L_ERROR, "nfsclients entry %s allows anonymous " + "access. Ignored.", cle.c_tag); + while (*hostptr == ':') + hostptr++; + } + + /* Ignore trailing colons */ + if (!*hostptr) { + hostptr = NULL; + goto again; + } + + sp = hostptr; + hostptr = strchr(hostptr, ':'); + if (hostptr) + *hostptr++ = '\0'; + strncpy(cle.c_hostname, sp, sizeof(cle.c_hostname) - 1); + cle.c_hostname [sizeof(cle.c_hostname) - 1] = '\0'; + return &cle; +} + +void +endnfsclntent(void) +{ + if (cfp) + xfclose(cfp); + if (squash_uids) + xfree(squash_uids); + if (squash_gids) + xfree(squash_gids); + if (hosts) + xfree(hosts); + cfp = NULL; + squash_uids = NULL; + squash_gids = NULL; + hosts = NULL; +} + +static int +parsekey(struct nfskey *keyp, char *str) +{ + char *sp; + int i, l, x0, x1; + + + if ((sp = strchr(str, ':')) != NULL) + *sp++ = '\0'; + if (!strcmp(str, "null")) + keyp->k_type = CLE_KEY_NULL; + else if (!strcmp(str, "md5")) + keyp->k_type = CLE_KEY_MD5; + else if (!strcmp(str, "sha")) + keyp->k_type = CLE_KEY_SHA; + else { + syntaxerr("unknown key type"); + return 0; + } + if (keyp->k_type == CLE_KEY_NULL) { + keyp->k_len = 0; + if (sp) + syntaxerr("unexpected key data for null key"); + return sp? 0 : 1; + } else if (sp) { + if ((l = strlen(sp)) & 1) { + syntaxerr("odd key length"); + return 0; + } + + l >>= 1; + for (i = 0; i < l && i < sizeof(keyp->k_key); i++, sp += 2) { + if ((x0 = hexdigit(sp[0])) == 0xff || + (x1 = hexdigit(sp[1])) == 0xff) { + syntaxerr("bad key digit"); + return 0; + } + keyp->k_key[i] = (x0 << 4) | x1; + } + keyp->k_len = i; + return 1; + } + return 0; +} + +static int +hexdigit(char c) +{ + if ((c = tolower(c)) >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + return 0xff; +} + +static int +parsesquash(char *list, int **idp, int *lenp) +{ + char *cp = list; + int id0, id1; + int len = *lenp; + int *id = *idp; + + do { + id0 = parsenum(&cp); + if (*cp == '-') { + cp++; + id1 = parsenum(&cp); + } else { + id1 = id0; + } + if (id0 == -1 || id1 == -1) { + syntaxerr("uid/gid -1 not permitted"); + return 0; + } + if ((len % 8) == 0) + id = (int *) xrealloc(id, (len + 9) * sizeof(*id)); + id[len++] = id0; + id[len++] = id1; + if (!*cp) + break; + if (*cp != ',') { + syntaxerr("bad uid/gid list"); + return 0; + } + cp++; + } while(1); + + id[len] = -1; + *lenp = len; + *idp = id; + return 1; +} + +static int +parsenum(char **cpp) +{ + char *cp = *cpp, c; + int num = 0; + + if (**cpp == '-') + (*cpp)++; + while (isdigit(**cpp)) + (*cpp)++; + c = **cpp; **cpp = '\0'; num = atoi(cp); **cpp = c; + return num; +} + +static int +gettag(char *tag, int len) +{ + xskip(cfp, " \t\n"); + return xgettok(cfp, ':', tag, len); +} + +static int +getattr(char *attr, int alen, char *value, int vlen) +{ + int ok; + + xskip(cfp, " \t"); + if ((ok = xgettok(cfp, '=', attr, alen)) < 0) + xlog(L_ERROR, "error parsing attribute"); + if (ok <= 0) + return ok; + xskip(cfp, " \t="); + + return xgettok(cfp, 0, value, vlen); +} + +static void +syntaxerr(char *msg) +{ + xlog(L_ERROR, "syntax error in nfsclients file (line %d): %s", + cfp->x_line, msg); +} + diff --git a/support/nfs/exports.c b/support/nfs/exports.c new file mode 100644 index 0000000..21b85be --- /dev/null +++ b/support/nfs/exports.c @@ -0,0 +1,440 @@ +/* + * support/nfs/export.c + * + * Parse the exports file. Derived from the unfsd implementation. + * + * Authors: Donald J. Becker, <becker@super.org> + * Rick Sladkey, <jrs@world.std.com> + * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> + * Olaf Kirch, <okir@monad.swb.de> + * Alexander O. Yuriev, <alex@bach.cis.temple.edu> + * + * This software maybe be used for any purpose provided + * the above copyright notice is retained. It is supplied + * as is, with no warranty expressed or implied. + */ + +#include "config.h" + +#include <sys/param.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <ctype.h> +#include <unistd.h> +#include "nfslib.h" +#include "exportfs.h" +#include "xmalloc.h" +#include "xlog.h" +#include "xio.h" + +#define EXPORT_DEFAULT_FLAGS \ + (NFSEXP_ASYNC|NFSEXP_READONLY|NFSEXP_ROOTSQUASH|NFSEXP_GATHERED_WRITES) + +static XFILE *efp = NULL; +static int first; +static int *squids = NULL, nsquids = 0, + *sqgids = NULL, nsqgids = 0; + +static int getexport(char *exp, int len); +static int getpath(char *path, int len); +static int parseopts(char *cp, struct exportent *ep); +static int parsesquash(char *list, int **idp, int *lenp, char **ep); +static int parsenum(char **cpp); +static int parsemaptype(char *type); +static void freesquash(void); +static void syntaxerr(char *msg); + +void +setexportent(char *fname, char *type) +{ + if (efp) + endexportent(); + if (!fname) + fname = _PATH_EXPORTS; + if (!(efp = xfopen(fname, type))) + xlog(L_ERROR, "can't open %s for %sing", + fname, strcmp(type, "r")? "writ" : "read"); + first = 1; +} + +struct exportent * +getexportent(void) +{ + static struct exportent ee; + char exp[512]; + char rpath[MAXPATHLEN+1]; + char *opt, *sp; + int ok; + + if (!efp) + return NULL; + + freesquash(); + ee.e_flags = EXPORT_DEFAULT_FLAGS; + ee.e_maptype = CLE_MAP_IDENT; + ee.e_anonuid = -2; + ee.e_anongid = -2; + ee.e_squids = NULL; + ee.e_sqgids = NULL; + ee.e_nsquids = 0; + ee.e_nsqgids = 0; + + if (first || (ok = getexport(exp, sizeof(exp))) == 0) { + ok = getpath(ee.e_path, sizeof(ee.e_path)); + if (ok <= 0) + return NULL; + strncpy (ee.m_path, ee.e_path, sizeof (ee.m_path) - 1); + ee.m_path [sizeof (ee.m_path) - 1] = '\0'; + ok = getexport(exp, sizeof(exp)); + } + if (ok < 0) { + xlog(L_ERROR, "expected client(options...)"); + return NULL; + } + first = 0; + + /* Check for default client */ + if (ok == 0) + exp[0] = '\0'; + if ((opt = strchr(exp, '(')) != NULL) { + *opt++ = '\0'; + if (!(sp = strchr(opt, ')')) || sp[1] != '\0') { + syntaxerr("bad option list"); + return NULL; + } + *sp = '\0'; + if (parseopts(opt, &ee) < 0) + return NULL; + } + if (strlen(exp) >= sizeof(ee.e_hostname)) { + syntaxerr("client name too long"); + return NULL; + } + strncpy(ee.e_hostname, exp, sizeof (ee.e_hostname) - 1); + ee.e_hostname[sizeof (ee.e_hostname) - 1] = '\0'; + + /* resolve symlinks */ + if (realpath(ee.e_path, rpath) != NULL) { + rpath[sizeof (rpath) - 1] = '\0'; + strncpy(ee.e_path, rpath, sizeof (ee.e_path) - 1); + ee.e_path[sizeof (ee.e_path) - 1] = '\0'; + strncpy (ee.m_path, ee.e_path, sizeof (ee.m_path) - 1); + ee.m_path [sizeof (ee.m_path) - 1] = '\0'; + } + + return ⅇ +} + +void +putexportent(struct exportent *ep) +{ + FILE *fp; + int *id, i; + + if (!efp) + return; + + fp = efp->x_fp; + fprintf(fp, "%s\t%s(", ep->e_path, ep->e_hostname); + fprintf(fp, "%s,", (ep->e_flags & NFSEXP_READONLY)? "ro" : "rw"); + fprintf(fp, "%ssync,", (ep->e_flags & NFSEXP_ASYNC)? "a" : ""); + fprintf(fp, "%swdelay,", (ep->e_flags & NFSEXP_GATHERED_WRITES)? + "" : "no_"); + fprintf(fp, "%ssecure,", (ep->e_flags & NFSEXP_INSECURE_PORT)? + "in" : ""); + fprintf(fp, "%sroot_squash,", (ep->e_flags & NFSEXP_ROOTSQUASH)? + "" : "no_"); + fprintf(fp, "%sall_squash,", (ep->e_flags & NFSEXP_ALLSQUASH)? + "" : "no_"); + + fprintf(fp, "mapping="); + switch (ep->e_maptype) { + case CLE_MAP_IDENT: + fprintf(fp, "identity,"); + break; + case CLE_MAP_UGIDD: + fprintf(fp, "ugidd,"); + break; + case CLE_MAP_FILE: + fprintf(fp, "file,"); + break; + default: + xlog(L_ERROR, "unknown mapping type for %s:%s", + ep->e_hostname, ep->e_path); + } + if ((id = ep->e_squids) != NULL) { + fprintf(fp, "squash_uids="); + for (i = 0; i < ep->e_nsquids; i += 2) + if (id[i] != id[i+1]) + fprintf(fp, "%d-%d,", id[i], id[i+1]); + else + fprintf(fp, "%d,", id[i]); + } + if ((id = ep->e_sqgids) != NULL) { + fprintf(fp, "squash_gids="); + for (i = 0; i < ep->e_nsquids; i += 2) + if (id[i] != id[i+1]) + fprintf(fp, "%d-%d,", id[i], id[i+1]); + else + fprintf(fp, "%d,", id[i]); + } + fprintf(fp, "anonuid=%d,anongid=%d)\n", ep->e_anonuid, ep->e_anongid); +} + +void +endexportent(void) +{ + if (efp) + xfclose(efp); + efp = NULL; + freesquash(); +} + +void +dupexportent(struct exportent *dst, struct exportent *src) +{ + int n; + + *dst = *src; + if ((n = src->e_nsquids) != 0) { + dst->e_squids = (int *) xmalloc(n * sizeof(int)); + memcpy(dst->e_squids, src->e_squids, n * sizeof(int)); + } + if ((n = src->e_nsqgids) != 0) { + dst->e_sqgids = (int *) xmalloc(n * sizeof(int)); + memcpy(dst->e_sqgids, src->e_sqgids, n * sizeof(int)); + } +} + +struct exportent * +mkexportent(char *hname, char *path, char *options) +{ + static struct exportent ee; + + ee.e_flags = EXPORT_DEFAULT_FLAGS; + ee.e_maptype = CLE_MAP_IDENT; + ee.e_anonuid = -2; + ee.e_anongid = -2; + ee.e_squids = NULL; + ee.e_sqgids = NULL; + ee.e_nsquids = 0; + ee.e_nsqgids = 0; + + if (strlen(hname) >= sizeof(ee.e_hostname)) { + xlog(L_WARNING, "client name %s too long", hname); + return NULL; + } + strncpy(ee.e_hostname, hname, sizeof (ee.e_hostname) - 1); + ee.e_hostname[sizeof (ee.e_hostname) - 1] = '\0'; + if (strlen(path) >= sizeof(ee.e_path)) { + xlog(L_WARNING, "path name %s too long", path); + return NULL; + } + strncpy(ee.e_path, path, sizeof (ee.e_path)); + ee.e_path[sizeof (ee.e_path) - 1] = '\0'; + strncpy (ee.m_path, ee.e_path, sizeof (ee.m_path) - 1); + ee.m_path [sizeof (ee.m_path) - 1] = '\0'; + if (options && parseopts(options, &ee) < 0) + return NULL; + return ⅇ +} + +int +updateexportent(struct exportent *eep, char *options) +{ + if (options && parseopts(options, eep) < 0) + return 0; + return 1; +} + +/* + * Parse option string pointed to by s and set mount options accordingly. + */ +static int +parseopts(char *cp, struct exportent *ep) +{ + char *opt; + + squids = ep->e_squids; nsquids = ep->e_nsquids; + sqgids = ep->e_sqgids; nsqgids = ep->e_nsqgids; + + while (isblank(*cp)) + cp++; + while (*cp) { + opt = cp; + while (*cp && *cp != ',') + cp++; + if (*cp) + *cp++ = '\0'; + + /* process keyword */ + if (strcmp(opt, "ro") == 0) + ep->e_flags |= NFSEXP_READONLY; + else if (strcmp(opt, "rw") == 0) + ep->e_flags &= ~NFSEXP_READONLY; + else if (!strcmp(opt, "secure")) + ep->e_flags &= ~NFSEXP_INSECURE_PORT; + else if (!strcmp(opt, "insecure")) + ep->e_flags |= NFSEXP_INSECURE_PORT; + else if (!strcmp(opt, "sync")) + ep->e_flags &= ~NFSEXP_ASYNC; + else if (!strcmp(opt, "async")) + ep->e_flags |= NFSEXP_ASYNC; + else if (!strcmp(opt, "wdelay")) + ep->e_flags |= NFSEXP_GATHERED_WRITES; + else if (!strcmp(opt, "no_wdelay")) + ep->e_flags &= ~NFSEXP_GATHERED_WRITES; + else if (strcmp(opt, "root_squash") == 0) + ep->e_flags |= NFSEXP_ROOTSQUASH; + else if (!strcmp(opt, "no_root_squash")) + ep->e_flags &= ~NFSEXP_ROOTSQUASH; + else if (strcmp(opt, "all_squash") == 0) + ep->e_flags |= NFSEXP_ALLSQUASH; + else if (strcmp(opt, "no_all_squash") == 0) + ep->e_flags &= ~NFSEXP_ALLSQUASH; + else if (strncmp(opt, "mapping=", 8) == 0) + ep->e_maptype = parsemaptype(opt+8); + else if (strcmp(opt, "map_identity") == 0) /* old style */ + ep->e_maptype = CLE_MAP_IDENT; + else if (strcmp(opt, "map_daemon") == 0) /* old style */ + ep->e_maptype = CLE_MAP_UGIDD; + else if (strncmp(opt, "anonuid=", 8) == 0) + ep->e_anonuid = atoi(opt+8); + else if (strncmp(opt, "anongid=", 8) == 0) + ep->e_anongid = atoi(opt+8); + else if (strncmp(opt, "squash_uids=", 12) == 0) { + if (parsesquash(opt+12, &squids, &nsquids, &cp) < 0) + return -1; + } else if (strncmp(opt, "squash_gids=", 12) == 0) { + if (parsesquash(opt+12, &sqgids, &nsqgids, &cp) < 0) + return -1; + } else { + xlog(L_ERROR, + "Unknown keyword \"%s\" in export file\n", + opt); + ep->e_flags |= NFSEXP_ALLSQUASH | NFSEXP_READONLY; + return -1; + } + while (isblank(*cp)) + cp++; + } + + ep->e_squids = squids; + ep->e_sqgids = sqgids; + ep->e_nsquids = nsquids; + ep->e_nsqgids = nsqgids; + + return 1; +} + +static int +parsesquash(char *list, int **idp, int *lenp, char **ep) +{ + char *cp = list; + int id0, id1; + int len = *lenp; + int *id = *idp; + + if (**ep) + *--(*ep) = ','; + + do { + id0 = parsenum(&cp); + if (*cp == '-') { + cp++; + id1 = parsenum(&cp); + } else { + id1 = id0; + } + if (id0 == -1 || id1 == -1) { + syntaxerr("uid/gid -1 not permitted"); + return -1; + } + if ((len % 8) == 0) + id = (int *) xrealloc(id, (len + 8) * sizeof(*id)); + id[len++] = id0; + id[len++] = id1; + if (!*cp || *cp == ')' || (*cp == ',' && !isdigit(cp[1]))) + break; + if (*cp != ',') { + syntaxerr("bad uid/gid list"); + return -1; + } + cp++; + } while(1); + + if (*cp == ',') *ep = cp+1; + + *lenp = len; + *idp = id; + return 1; +} + +static void +freesquash(void) +{ + if (squids) { + xfree (squids); + squids = NULL; + nsquids = 0; + } + if (sqgids) { + xfree (sqgids); + sqgids = NULL; + nsqgids = 0; + } +} + +static int +parsenum(char **cpp) +{ + char *cp = *cpp, c; + int num = 0; + + if (**cpp == '-') + (*cpp)++; + while (isdigit(**cpp)) + (*cpp)++; + c = **cpp; **cpp = '\0'; num = atoi(cp); **cpp = c; + return num; +} + +static int +parsemaptype(char *type) +{ + if (!strcmp(type, "identity")) + return CLE_MAP_IDENT; + if (!strcmp(type, "ugidd")) + return CLE_MAP_UGIDD; + if (!strcmp(type, "file")) + return CLE_MAP_FILE; + syntaxerr("invalid map type"); + return CLE_MAP_IDENT; /* default */ +} + +static int +getpath(char *path, int len) +{ + xskip(efp, " \t\n"); + return xgettok(efp, 0, path, len); +} + +static int +getexport(char *exp, int len) +{ + int ok; + + xskip(efp, " \t"); + if ((ok = xgettok(efp, 0, exp, len)) < 0) + xlog(L_ERROR, "error parsing export entry"); + return ok; +} + +static void +syntaxerr(char *msg) +{ + xlog(L_ERROR, "syntax error in exports file (line %d): %s", + efp->x_line, msg); +} + diff --git a/support/nfs/getfh.c b/support/nfs/getfh.c new file mode 100644 index 0000000..5a6f1a4 --- /dev/null +++ b/support/nfs/getfh.c @@ -0,0 +1,55 @@ +/* + * support/nfs/getfh.c + * + * Get the FH for a given client and directory. This function takes + * the NFS protocol version number as an additional argument. + * + * This function has nothing in common with the SunOS getfh function, + * which is a front-end to the RPC mount call. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <string.h> +#include <sys/types.h> +#include <errno.h> +#include "nfslib.h" + +struct knfs_fh * +getfh_old (struct sockaddr *addr, dev_t dev, ino_t ino) +{ + static union nfsctl_res res; + struct nfsctl_arg arg; + + arg.ca_version = NFSCTL_VERSION; + arg.ca_getfh.gf_version = 2; /* obsolete */ + arg.ca_getfh.gf_dev = dev; + arg.ca_getfh.gf_ino = ino; + memcpy(&arg.ca_getfh.gf_addr, addr, sizeof(struct sockaddr_in)); + + if (nfsctl(NFSCTL_GETFH, &arg, &res) < 0) + return NULL; + + return &res.cr_getfh; +} + +struct knfs_fh * +getfh(struct sockaddr *addr, const char *path) +{ + static union nfsctl_res res; + struct nfsctl_arg arg; + + arg.ca_version = NFSCTL_VERSION; + arg.ca_getfd.gd_version = 2; /* obsolete */ + strncpy(arg.ca_getfd.gd_path, path, + sizeof(arg.ca_getfd.gd_path) - 1); + arg.ca_getfd.gd_path[sizeof (arg.ca_getfd.gd_path) - 1] = '\0'; + memcpy(&arg.ca_getfd.gd_addr, addr, sizeof(struct sockaddr_in)); + + if (nfsctl(NFSCTL_GETFD, &arg, &res) < 0) + return NULL; + + return &res.cr_getfh; +} diff --git a/support/nfs/keytab.c b/support/nfs/keytab.c new file mode 100644 index 0000000..e33dded --- /dev/null +++ b/support/nfs/keytab.c @@ -0,0 +1,129 @@ +/* + * support/nfs/keytab.c + * + * Manage the nfskeys database. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <syslog.h> +#include <ctype.h> +#include "xmalloc.h" +#include "nfslib.h" +#include "exportfs.h" +#include "xio.h" + +static FILE *cfp = NULL; + +int +setnfskeyent(char *fname) +{ + if (cfp) + fclose(cfp); + if (!fname) + fname = _PATH_NFSKEYS; + cfp = fsetnfskeyent(fname, "r"); + return cfp != NULL; +} + +FILE * +fsetnfskeyent(char *fname, char *type) +{ +#if 0 + FILE *fp; + + if ((fp = fopen(fname, type)) == NULL) + xlog(L_ERROR, "can't open %s for %sing\n", + fname, type[0] == 'r'? "read" : "writ"); + return fp; +#else + return fopen(fname, type); +#endif +} + +struct nfskeyent * +getnfskeyent(void) +{ + return fgetnfskeyent(cfp); +} + +struct nfskeyent * +fgetnfskeyent(FILE *fp) +{ + static struct nfskeyent ke; + + if (!fp) + return NULL; + + do { + if (fread(&ke, sizeof(ke), 1, fp) != 1) + return NULL; + } while(ke.k_hostname[0] == '\0'); + return &ke; +} + +void +endnfskeyent(void) +{ + if (cfp) + fclose(cfp); + cfp = NULL; +} + +void +fendnfskeyent(FILE *fp) +{ + if (fp) + fclose(fp); +} + +void +fputnfskeyent(FILE *fp, struct nfskeyent *kep) +{ + fwrite(kep, sizeof(*kep), 1, fp); +} + +int +getnfskeytype(char *st) +{ + if (!strcasecmp(st, "null")) + return CLE_KEY_NULL; + if (!strcasecmp(st, "md5")) + return CLE_KEY_MD5; + if (!strcasecmp(st, "sha")) + return CLE_KEY_SHA; + return CLE_KEY_NONE; +} + +char * +getnfskeyname(int type) +{ + switch (type) { + case CLE_KEY_NONE: + return "none"; + case CLE_KEY_NULL: + return "null"; + case CLE_KEY_MD5: + return "md5"; + case CLE_KEY_SHA: + return "sha"; + } + return "unk"; +} + +int +getnfskeysize(int type) +{ + switch (type) { + case CLE_KEY_MD5: + return 16; + case CLE_KEY_SHA: + return 20; + } + return 0; +} diff --git a/support/nfs/lockdsvc.c b/support/nfs/lockdsvc.c new file mode 100644 index 0000000..532e721 --- /dev/null +++ b/support/nfs/lockdsvc.c @@ -0,0 +1,20 @@ +/* + * support/nfs/nfssvc.c + * + * Run an NFS daemon. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include "nfslib.h" + +int +lockdsvc() +{ + struct nfsctl_arg arg; + + arg.ca_version = NFSCTL_VERSION; + return nfsctl(LOCKDCTL_SVC, &arg, NULL); +} diff --git a/support/nfs/nfsclient.c b/support/nfs/nfsclient.c new file mode 100644 index 0000000..5886484 --- /dev/null +++ b/support/nfs/nfsclient.c @@ -0,0 +1,32 @@ +/* + * support/nfs/client.c + * + * Add or delete an NFS client in knfsd. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <string.h> +#include "nfslib.h" + +int +nfsaddclient(struct nfsctl_client *clp) +{ + struct nfsctl_arg arg; + + arg.ca_version = NFSCTL_VERSION; + memcpy(&arg.ca_client, clp, sizeof(arg.ca_client)); + return nfsctl(NFSCTL_ADDCLIENT, &arg, NULL); +} + +int +nfsdelclient(struct nfsctl_client *clp) +{ + struct nfsctl_arg arg; + + arg.ca_version = NFSCTL_VERSION; + memcpy(&arg.ca_client, clp, sizeof(arg.ca_client)); + return nfsctl(NFSCTL_DELCLIENT, &arg, NULL); +} diff --git a/support/nfs/nfsctl.c b/support/nfs/nfsctl.c new file mode 100644 index 0000000..c04588f --- /dev/null +++ b/support/nfs/nfsctl.c @@ -0,0 +1,24 @@ +/* + * support/nfs/nfsctl.c + * + * Central syscall to the nfsd kernel module. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <unistd.h> +#include <asm/unistd.h> +#include "nfslib.h" + +/* compatibility hack... */ +#ifndef __NR_nfsctl +#define __NR_nfsctl __NR_nfsservctl +#endif + +int +nfsctl (int cmd, struct nfsctl_arg * argp, union nfsctl_res * resp) +{ + return syscall (__NR_nfsctl, cmd, argp, resp); +} diff --git a/support/nfs/nfsexport.c b/support/nfs/nfsexport.c new file mode 100644 index 0000000..ce8b867 --- /dev/null +++ b/support/nfs/nfsexport.c @@ -0,0 +1,32 @@ +/* + * support/nfs/export.c + * + * Add or delete an NFS export in knfsd. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <string.h> +#include "nfslib.h" + +int +nfsexport(struct nfsctl_export *exp) +{ + struct nfsctl_arg arg; + + arg.ca_version = NFSCTL_VERSION; + memcpy(&arg.ca_export, exp, sizeof(arg.ca_export)); + return nfsctl(NFSCTL_EXPORT, &arg, NULL); +} + +int +nfsunexport(struct nfsctl_export *exp) +{ + struct nfsctl_arg arg; + + arg.ca_version = NFSCTL_VERSION; + memcpy(&arg.ca_export, exp, sizeof(arg.ca_export)); + return nfsctl(NFSCTL_UNEXPORT, &arg, NULL); +} diff --git a/support/nfs/nfssvc.c b/support/nfs/nfssvc.c new file mode 100644 index 0000000..7419baf --- /dev/null +++ b/support/nfs/nfssvc.c @@ -0,0 +1,22 @@ +/* + * support/nfs/nfssvc.c + * + * Run an NFS daemon. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include "nfslib.h" + +int +nfssvc(int port, int nrservs) +{ + struct nfsctl_arg arg; + + arg.ca_version = NFSCTL_VERSION; + arg.ca_svc.svc_nthreads = nrservs; + arg.ca_svc.svc_port = port; + return nfsctl(NFSCTL_SVC, &arg, NULL); +} diff --git a/support/nfs/rmtab.c b/support/nfs/rmtab.c new file mode 100644 index 0000000..b9b5ff1 --- /dev/null +++ b/support/nfs/rmtab.c @@ -0,0 +1,122 @@ +/* + * support/nfs/rmtab.c + * + * Handling for rmtab. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <sys/fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <signal.h> +#include "nfslib.h" + +static FILE *rmfp = NULL; + +int +setrmtabent(char *type) +{ + if (rmfp) + fclose(rmfp); + rmfp = fsetrmtabent(_PATH_RMTAB, type); + return (rmfp != NULL); +} + +FILE * +fsetrmtabent(char *fname, char *type) +{ + int readonly = !strcmp(type, "r"); + FILE *fp; + + if (!fname) + return NULL; + if ((fp = fopen(fname, type)) == NULL) { + xlog(L_ERROR, "can't open %s for %sing", fname, + readonly ? "read" : "writ"); + return NULL; + } + return fp; +} + +struct rmtabent * +getrmtabent(int log) +{ + return fgetrmtabent(rmfp, log); +} + +struct rmtabent * +fgetrmtabent(FILE *fp, int log) +{ + static struct rmtabent re; + char buf[2048], *sp; + + errno = 0; + if (!fp) + return NULL; + do { + if (fgets(buf, sizeof(buf)-1, fp) == NULL) + return NULL; + if ((sp = strchr(buf, '\n')) != NULL) + *sp = '\0'; + if (!(sp = strchr(buf, ':'))) { + if (log) + xlog(L_ERROR, "malformed entry in rmtab file"); + errno = EINVAL; + return NULL; + } + *sp++ = '\0'; + } while (0); + strncpy(re.r_client, buf, sizeof (re.r_client) - 1); + re.r_client[sizeof (re.r_client) - 1] = '\0'; + strncpy(re.r_path, sp, sizeof (re.r_path) - 1); + re.r_path[sizeof (re.r_path) - 1] = '\0'; + return &re; +} + +void +putrmtabent(struct rmtabent *rep) +{ + fputrmtabent(rmfp, rep); +} + +void +fputrmtabent(FILE *fp, struct rmtabent *rep) +{ + if (!fp) + return; + fprintf(fp, "%s:%s\n", rep->r_client, rep->r_path); +} + +void +endrmtabent(void) +{ + fendrmtabent(rmfp); + rmfp = NULL; +} + +void +fendrmtabent(FILE *fp) +{ + if (fp) + fclose(fp); +} + +void +rewindrmtabent(void) +{ + if (rmfp) + rewind(rmfp); +} + +void +frewindrmtabent(FILE *fp) +{ + if (fp) + rewind (fp); +} diff --git a/support/nfs/rpcdispatch.c b/support/nfs/rpcdispatch.c new file mode 100644 index 0000000..e798ea5 --- /dev/null +++ b/support/nfs/rpcdispatch.c @@ -0,0 +1,112 @@ +/* + * support/nfs/rcpdispatch.c + * + * Generic RPC dispatcher. + * + * Copyright (C) 1995, 1996, Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <stdio.h> +#include <rpc/rpc.h> +#include <rpc/pmap_clnt.h> +#include <signal.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <string.h> +#include "rpcmisc.h" +#include "xlog.h" + +void +rpc_dispatch(struct svc_req *rqstp, SVCXPRT *transp, + struct rpc_dtable *dtable, int nvers, + void *argp, void *resp) +{ + struct rpc_dentry *dent; + + if (rqstp->rq_vers > nvers) { + svcerr_progvers(transp, 1, nvers); + return; + } + dtable += (rqstp->rq_vers - 1); + if (rqstp->rq_proc > dtable->nproc) { + svcerr_noproc(transp); + return; + } + + dent = dtable->entries + rqstp->rq_proc; + + if (dent->func == NULL) { + svcerr_noproc(transp); + return; + } + + memset(argp, 0, dent->xdr_arg_size); + memset(resp, 0, dent->xdr_res_size); + + if (!svc_getargs(transp, dent->xdr_arg_fn, argp)) { + svcerr_decode(transp); + return; + } + + if ((dent->func)(rqstp, argp, resp) && resp != 0) { + if (!svc_sendreply(transp, dent->xdr_res_fn, (caddr_t)resp)) + svcerr_systemerr(transp); + } + if (!svc_freeargs(transp, dent->xdr_arg_fn, argp)) { + xlog(L_ERROR, "failed to free RPC arguments"); + exit (2); + } +} + +#if 0 +/* + * This is our replacement for svc_run. It turns off some signals while + * executing the server procedures to avoid nasty race conditions. + */ +void +rpc_svcrun(fd_set *morefds, void (*func)(int fd)) +{ + sigset_t block, current; + fd_set readfds; + + for (;;) { + readfds = svc_fdset; + if (morefds) { + int i; + + /* most efficient */ + for (i = 0; i < FD_SETSIZE; i++) + if (FD_ISSET(i, morefds)) + FD_SET(i, &readfs); + } + switch (select(FD_SETSIZE, &readfds, NULL, NULL, NULL)) { + case -1: + if (errno == EINTR) + continue; + xlog(L_ERROR, "svc_run: - select failed"); + break; + case 0: + continue; + default: + if (morefds) { + int i; + + /* most efficient */ + for (i = 0; i < FD_SETSIZE; i++) + if (FD_ISSET(i, morefds) && + FD_ISSET(i, &readfds)) + func(i); + } + sigemptyset(&block); + sigaddset(&block, SIGALRM); + sigaddset(&block, SIGVTALRM); + sigaddset(&block, SIGIO); + sigprocmask(SIG_BLOCK, &block, ¤t); + svc_getreqset(&readfds); + sigprocmask(SIG_SETMASK, ¤t, NULL); + } + } +} +#endif diff --git a/support/nfs/rpcmisc.c b/support/nfs/rpcmisc.c new file mode 100644 index 0000000..7b182fd --- /dev/null +++ b/support/nfs/rpcmisc.c @@ -0,0 +1,230 @@ +/* + * support/nfs/rpcmisc.c + * + * Miscellaneous functions for RPC startup and shutdown. + * This code is partially snarfed from rpcgen -s tcp -s udp, + * partly written by Mark Shand, Donald Becker, and Rick + * Sladkey. It was tweaked slightly by Olaf Kirch to be + * usable by both unfsd and mountd. + * + * This software may be used for any purpose provided + * the above copyright notice is retained. It is supplied + * as is, with no warranty expressed or implied. + */ + +#include "config.h" + +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <rpc/rpc.h> +#include <rpc/pmap_clnt.h> +#include <netinet/in.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <fcntl.h> +#include <memory.h> +#include <errno.h> +#include <unistd.h> +#include "nfslib.h" + +static void closedown(int sig); +static int makesock(int port, int proto, int socksz); + +#define _RPCSVC_CLOSEDOWN 120 +int _rpcpmstart = 0; +int _rpcfdtype = 0; +int _rpcsvcdirty = 0; + +void +rpc_init(char *name, int prog, int vers, void (*dispatch)(), int defport, + int bufsiz) +{ + struct sockaddr_in saddr; + SVCXPRT *transp; + int sock; + int asize; + + asize = sizeof(saddr); + sock = 0; + _rpcfdtype = 0; + if (getsockname(0, (struct sockaddr *) &saddr, &asize) == 0) { + int ssize = sizeof (int); + if (saddr.sin_family != AF_INET) + xlog(L_FATAL, "init: stdin is bound to non-inet addr"); + if (getsockopt(0, SOL_SOCKET, SO_TYPE, + (char *)&_rpcfdtype, &ssize) == -1) + xlog(L_FATAL, "getsockopt failed: %s", strerror(errno)); + _rpcpmstart = 1; + } else { + pmap_unset(prog, vers); + sock = RPC_ANYSOCK; + } + + if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { + if (_rpcfdtype == 0 && defport != 0 && + ((sock = makesock(defport, IPPROTO_UDP, bufsiz)) < 0)) { + xlog(L_FATAL, "%s: could not make a UDP socket\n", + name); + } + transp = svcudp_create(sock); + if (transp == NULL) { + xlog(L_FATAL, "cannot create udp service."); + } + if (!svc_register(transp, prog, vers, dispatch, IPPROTO_UDP)) { + xlog(L_FATAL, "unable to register (%s, %d, udp).", + name, vers); + } + } + + if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { + if (_rpcfdtype == 0 && defport != 0 && + ((sock = makesock(defport, IPPROTO_TCP, bufsiz)) < 0)) { + xlog(L_FATAL, "%s: could not make a TCP socket\n", + name); + } + transp = svctcp_create(sock, 0, 0); + if (transp == NULL) { + xlog(L_FATAL, "cannot create tcp service."); + } + if (!svc_register(transp, prog, vers, dispatch, IPPROTO_TCP)) { + xlog(L_FATAL, "unable to register (%s, %d, tcp).", + name, vers); + } + } + + if (_rpcpmstart) { + signal (SIGALRM, closedown); + alarm (_RPCSVC_CLOSEDOWN); + } +} + +static void closedown(sig) +int sig; +{ + (void) signal(sig, closedown); + if (_rpcsvcdirty == 0) { + extern fd_set svc_fdset; + static int size; + int i, openfd; + + if (_rpcfdtype == SOCK_DGRAM) + exit(0); + if (size == 0) { + size = getdtablesize(); + } + for (i = 0, openfd = 0; i < size && openfd < 2; i++) + if (FD_ISSET(i, &svc_fdset)) + openfd++; + if (openfd <= 1) + exit(0); + } + (void) alarm(_RPCSVC_CLOSEDOWN); +} + +static int makesock(port, proto, socksz) +int port; +int proto; +int socksz; +{ + struct sockaddr_in sin; + int s; + int sock_type; + int val; + + sock_type = (proto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM; + s = socket(AF_INET, sock_type, proto); + if (s < 0) { + xlog(L_FATAL, "Could not make a socket: %s\n", + strerror(errno)); + return (-1); + } + memset((char *) &sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + sin.sin_port = htons(port); + + val = 1; + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) + xlog(L_ERROR, "setsockopt failed: %s\n", strerror(errno)); + +#ifdef SO_SNDBUF + { + int sblen, rblen; + + /* 1024 for rpc & transport overheads */ + sblen = rblen = socksz + 1024; + if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sblen, sizeof sblen) < 0 || + setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rblen, sizeof rblen) < 0) + xlog(L_ERROR, "setsockopt failed: %s\n", strerror(errno)); + } +#endif /* SO_SNDBUF */ + + if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) { + xlog(L_FATAL, "Could not bind name to socket: %s\n", + strerror(errno)); + return (-1); + } + return (s); +} + + +/* Log an incoming call. */ +void +rpc_logcall(struct svc_req *rqstp, char *xname, char *arg) +{ + char buff[1024]; + int buflen=sizeof(buff); + int len; + char *sp; + int i; + + if (!xlog_enabled(D_CALL)) + return; + + sp = buff; + switch (rqstp->rq_cred.oa_flavor) { + case AUTH_NULL: + sprintf(sp, "NULL"); + break; + case AUTH_UNIX: { + struct authunix_parms *unix_cred; + struct tm *tm; + + unix_cred = (struct authunix_parms *) rqstp->rq_clntcred; + tm = localtime(&unix_cred->aup_time); + snprintf(sp, buflen, "UNIX %d/%d/%d %02d:%02d:%02d %s %d.%d", + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec, + unix_cred->aup_machname, + unix_cred->aup_uid, + unix_cred->aup_gid); + sp[buflen-1] = 0; + len = strlen(sp); + sp += buflen; + buflen -= len; + if ((int) unix_cred->aup_len > 0) { + snprintf(sp, buflen, "+%d", unix_cred->aup_gids[0]); + sp[buflen-1] = 0; + len = strlen(sp); + sp += buflen; + buflen -= len; + for (i = 1; i < unix_cred->aup_len; i++) { + snprintf(sp, buflen, ",%d", + unix_cred->aup_gids[i]); + sp[buflen-1] = 0; + len = strlen(sp); + sp += buflen; + buflen -= len; + } + } + } + break; + default: + sprintf(sp, "CRED %d", rqstp->rq_cred.oa_flavor); + } + xlog(D_CALL, "%s [%s]\n\t%s\n", xname, buff, arg); +} diff --git a/support/nfs/wildmat.c b/support/nfs/wildmat.c new file mode 100644 index 0000000..8f7b760 --- /dev/null +++ b/support/nfs/wildmat.c @@ -0,0 +1,177 @@ +/* $Revision: 0.2.18.1 $ +** +** Do shell-style pattern matching for ?, \, [], and * characters. +** Might not be robust in face of malformed patterns; e.g., "foo[a-" +** could cause a segmentation violation. It is 8bit clean. +** +** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. +** Rich $alz is now <rsalz@osf.org>. +** April, 1991: Replaced mutually-recursive calls with in-line code +** for the star character. +** +** Special thanks to Lars Mathiesen <thorinn@diku.dk> for the ABORT code. +** This can greatly speed up failing wildcard patterns. For example: +** pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-* +** text 1: -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1 +** text 2: -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1 +** Text 1 matches with 51 calls, while text 2 fails with 54 calls. Without +** the ABORT code, it takes 22310 calls to fail. Ugh. The following +** explanation is from Lars: +** The precondition that must be fulfilled is that DoMatch will consume +** at least one character in text. This is true if *p is neither '*' nor +** '\0'.) The last return has ABORT instead of FALSE to avoid quadratic +** behaviour in cases like pattern "*a*b*c*d" with text "abcxxxxx". With +** FALSE, each star-loop has to run to the end of the text; with ABORT +** only the last one does. +** +** Once the control of one instance of DoMatch enters the star-loop, that +** instance will return either TRUE or ABORT, and any calling instance +** will therefore return immediately after (without calling recursively +** again). In effect, only one star-loop is ever active. It would be +** possible to modify the code to maintain this context explicitly, +** eliminating all recursive calls at the cost of some complication and +** loss of clarity (and the ABORT stuff seems to be unclear enough by +** itself). I think it would be unwise to try to get this into a +** released version unless you have a good test data base to try it out +** on. +*/ + +#include "config.h" + +#include <ctype.h> + +#define TRUE 1 +#define FALSE 0 +#define ABORT -1 + + + /* What character marks an inverted character class? */ +#define NEGATE_CLASS '^' + /* Is "*" a common pattern? */ +#define OPTIMIZE_JUST_STAR + /* Do tar(1) matching rules, which ignore a trailing slash? */ +#undef MATCH_TAR_PATTERN + + +/* +** Match text and p, return TRUE, FALSE, or ABORT. +*/ +static int +DoMatch(text, p) + register char *text; + register char *p; +{ + register int last; + register int matched; + register int reverse; + + for ( ; *p; text++, p++) { + if (*text == '\0' && *p != '*') + return ABORT; + switch (*p) { + case '\\': + /* Literal match with following character. */ + p++; + /* FALLTHROUGH */ + default: + if (toupper (*text) != toupper (*p)) + return FALSE; + continue; + case '?': + /* Match anything. */ + continue; + case '*': + while (*++p == '*') + /* Consecutive stars act just like one. */ + continue; + if (*p == '\0') + /* Trailing star matches everything. */ + return TRUE; + while (*text) + if ((matched = DoMatch(text++, p)) != FALSE) + return matched; + return ABORT; + case '[': + reverse = p[1] == NEGATE_CLASS ? TRUE : FALSE; + if (reverse) + /* Inverted character class. */ + p++; + matched = FALSE; + if (p[1] == ']' || p[1] == '-') + if (toupper (*++p) == toupper(*text)) + matched = TRUE; + for (last = *p; *++p && *p != ']'; last = *p) + /* This next line requires a good C compiler. */ + if (*p == '-' && p[1] != ']' + ? *text <= *++p && *text >= last + : toupper (*text) == toupper (*p)) + matched = TRUE; + if (matched == reverse) + return FALSE; + continue; + } + } + +#ifdef MATCH_TAR_PATTERN + if (*text == '/') + return TRUE; +#endif /* MATCH_TAR_ATTERN */ + return *text == '\0'; +} + + +/* +** User-level routine. Returns TRUE or FALSE. +*/ +int +wildmat(text, p) + char *text; + char *p; +{ +#ifdef OPTIMIZE_JUST_STAR + if (p[0] == '*' && p[1] == '\0') + return TRUE; +#endif /* OPTIMIZE_JUST_STAR */ + return DoMatch(text, p) == TRUE; +} + + + +#if defined(TEST) +#include <stdio.h> + +/* Yes, we use gets not fgets. Sue me. */ +extern char *gets(); + + +int +main() +{ + char p[80]; + char text[80]; + + printf("Wildmat tester. Enter pattern, then strings to test.\n"); + printf("A blank line gets prompts for a new pattern; a blank pattern\n"); + printf("exits the program.\n"); + + for ( ; ; ) { + printf("\nEnter pattern: "); + (void)fflush(stdout); + if (gets(p) == NULL || p[0] == '\0') + break; + for ( ; ; ) { + printf("Enter text: "); + (void)fflush(stdout); + if (gets(text) == NULL) + exit(0); + if (text[0] == '\0') + /* Blank line; go back and get a new pattern. */ + break; + printf(" %s\n", wildmat(text, p) ? "YES" : "NO"); + } + } + + exit(0); + /* NOTREACHED */ +} +#endif /* defined(TEST) */ diff --git a/support/nfs/xio.c b/support/nfs/xio.c new file mode 100644 index 0000000..1bcd41b --- /dev/null +++ b/support/nfs/xio.c @@ -0,0 +1,151 @@ +/* + * support/nfs/xio.c + * + * Simple I/O functions for the parsing of /etc/exports and /etc/nfsclients. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <sys/fcntl.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <signal.h> +#include <unistd.h> +#include "xmalloc.h" +#include "xlog.h" +#include "xio.h" + +XFILE * +xfopen(char *fname, char *type) +{ + XFILE *xfp; + FILE *fp; + + if (!(fp = fopen(fname, type))) + return NULL; + xfp = (XFILE *) xmalloc(sizeof(*xfp)); + xfp->x_fp = fp; + xfp->x_line = 0; + + return xfp; +} + +void +xfclose(XFILE *xfp) +{ + fclose(xfp->x_fp); + xfree(xfp); +} + +static void +doalarm(int sig) +{ + return; +} + +int +xflock(char *fname, char *type) +{ + struct sigaction sa, oldsa; + int readonly = !strcmp(type, "r"); + struct flock fl = { readonly? F_RDLCK : F_WRLCK, SEEK_SET, 0, 0, 0 }; + int fd; + + if ((fd = open(fname, readonly? O_RDONLY : O_RDWR)) < 0) { + xlog(L_WARNING, "could not open %s for locking", fname); + return -1; + } + sa.sa_handler = doalarm; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(SIGALRM, &sa, &oldsa); + alarm(10); + if (fcntl(fd, F_SETLKW, &fl) < 0) { + alarm(0); + xlog(L_WARNING, "failed to lock %s", fname); + close(fd); + fd = 0; + } else { + alarm(0); + } + sigaction(SIGALRM, &oldsa, NULL); + + return fd; +} + +void +xfunlock(int fd) +{ + close(fd); +} + +int +xgettok(XFILE *xfp, char sepa, char *tok, int len) +{ + int i = 0; + char c = 0; + + while (i < len && (c = xgetc(xfp)) != EOF && c != sepa && !isspace(c)) + tok[i++] = c; + if (c == '\n') + ungetc(c, xfp->x_fp); + if (!i) + return 0; + if (i >= len || (sepa && c != sepa)) + return -1; + tok[i] = '\0'; + return 1; +} + +char +xgetc(XFILE *xfp) +{ + char c = getc(xfp->x_fp); + + if (c == EOF) + return c; + if (c == '\\') { + if ((c = getc(xfp->x_fp)) != '\n') { + ungetc(c, xfp->x_fp); + return '\\'; + } + xfp->x_line++; + while ((c = getc(xfp->x_fp)) == ' ' || c == '\t'); + ungetc(c, xfp->x_fp); + return ' '; + } + if (c == '#') + c = xskipcomment(xfp); + if (c == '\n') + xfp->x_line++; + return c; +} + +void +xungetc(char c, XFILE *xfp) +{ + if (c != EOF) + ungetc(c, xfp->x_fp); +} + +void +xskip(XFILE *xfp, char *str) +{ + char c; + + while ((c = xgetc(xfp)) != EOF && strchr(str, c)); + ungetc(c, xfp->x_fp); +} + +char +xskipcomment(XFILE *xfp) +{ + char c; + + while ((c = getc(xfp->x_fp)) != EOF && c != '\n'); + return c; +} diff --git a/support/nfs/xlog.c b/support/nfs/xlog.c new file mode 100644 index 0000000..90c7e63 --- /dev/null +++ b/support/nfs/xlog.c @@ -0,0 +1,189 @@ +/* + * support/nfs/xlog.c + * + * This module handles the logging of requests. + * + * TODO: Merge the two "XXX_log() calls. + * + * Authors: Donald J. Becker, <becker@super.org> + * Rick Sladkey, <jrs@world.std.com> + * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> + * Olaf Kirch, <okir@monad.swb.de> + * + * This software maybe be used for any purpose provided + * the above copyright notice is retained. It is supplied + * as is, with no warranty expressed or implied. + */ + +#include "config.h" + +#include <unistd.h> +#include <signal.h> +#include <time.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <syslog.h> +#include "nfslib.h" + +#undef VERBOSE_PRINTF + +static int foreground = 1; /* not a daemon initially */ +static int logging = 0; /* enable/disable DEBUG logs */ +static int logmask = 0; /* What will be logged */ +static char log_name[256]; /* name of this program */ +static int log_pid = -1; /* PID of this program */ +static FILE *log_fp = (FILE *)NULL; /* fp for the log file */ + +static void xlog_toggle(int sig); +static struct xlog_debugfac debugnames[] = { + { "general", D_GENERAL, }, + { "call", D_CALL, }, + { "auth", D_AUTH, }, + { "parse", D_PARSE, }, + { "all", D_ALL, }, + { NULL, 0, }, +}; + +void +xlog_open(char *progname) +{ + openlog(progname, LOG_PID, LOG_DAEMON); + if (foreground) { + log_fp = stderr; + if (log_fp != NULL) + setbuf(log_fp, NULL); + } + + strncpy(log_name, progname, sizeof (log_name) - 1); + log_name [sizeof (log_name) - 1] = '\0'; + log_pid = getpid(); + + signal(SIGUSR1, xlog_toggle); + signal(SIGUSR2, xlog_toggle); +} + +void +xlog_background(void) +{ + foreground = 0; +} + +static void +xlog_toggle(int sig) +{ + unsigned int tmp, i; + + if (sig == SIGUSR1) { + if ((logmask & D_ALL) && !logging) { + xlog(D_GENERAL, "turned on logging"); + logging = 1; + return; + } + tmp = ~logmask; + logmask |= ((logmask & D_ALL) << 1) | D_GENERAL; + for (i = -1, tmp &= logmask; tmp; tmp >>= 1, i++) + if (tmp & 1) + xlog(D_GENERAL, + "turned on logging level %d", i); + } else { + xlog(D_GENERAL, "turned off logging"); + logging = 0; + } + signal(sig, xlog_toggle); +} + +void +xlog_config(int fac, int on) +{ + if (on) + logmask |= fac; + else + logmask &= ~fac; + if (on) + logging = 1; +} + +void +xlog_sconfig(char *kind, int on) +{ + struct xlog_debugfac *tbl = debugnames; + + while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind)) + tbl++; + if (!tbl->df_name) { + xlog (L_WARNING, "Invalid debug facility: %s\n", kind); + return; + } + xlog_config(tbl->df_fac, on); +} + +int +xlog_enabled(int fac) +{ + return (logging && (fac & logmask)); +} + + +/* Write something to the system logfile. */ +void +xlog(int kind, const char *fmt, ...) +{ + char buff[1024]; + va_list args; + int logged = 1, n; +#ifdef VERBOSE_PRINTF + time_t now; + struct tm *tm; +#endif + + if (!(kind & (L_ALL)) && !(logging && (kind & logmask))) + return; + + va_start(args, fmt); + vsnprintf(buff, sizeof (buff), fmt, args); + va_end(args); + buff[sizeof (buff) - 1] = 0; + + if ((n = strlen(buff)) > 0 && buff[n-1] != '\n') { + buff[n++] = '\n'; buff[n++] = '\0'; + } + + switch (kind) { + case L_FATAL: + syslog(LOG_ERR, "%s", buff); + break; + case L_ERROR: + syslog(LOG_ERR, "%s", buff); + break; + case L_WARNING: + syslog(LOG_WARNING, "%s", buff); + break; + case L_NOTICE: + syslog(LOG_NOTICE, "%s", buff); + break; + default: + logged = 0; + break; + } + if (!logged || foreground) { + if (!logged && log_fp == NULL) { + syslog(LOG_DEBUG, "%s", buff); + } else if (log_fp != NULL) { +#ifdef VERBOSE_PRINTF + time(&now); + tm = localtime(&now); + fprintf(log_fp, "%s[%d] %02d/%02d/%02d %02d:%02d %s\n", + log_name, log_pid, + tm->tm_mon + 1, tm->tm_mday, + tm->tm_year, tm->tm_hour, tm->tm_min, + buff); +#else + fprintf(log_fp, "%s: %s", log_name, buff); +#endif + } + } + if (kind == L_FATAL) + exit(1); +} diff --git a/support/nfs/xmalloc.c b/support/nfs/xmalloc.c new file mode 100644 index 0000000..9523afc --- /dev/null +++ b/support/nfs/xmalloc.c @@ -0,0 +1,48 @@ +/* + * support/nfs/xmalloc.c + * + * malloc with NULL checking. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <stdlib.h> +#include <string.h> +#include "xmalloc.h" +#include "xlog.h" + +void * +xmalloc(size_t size) +{ + void *ptr; + + if (!(ptr = malloc(size))) + xlog(L_FATAL, "malloc: out of memory"); + return ptr; +} + +void * +xrealloc(void *ptr, size_t size) +{ + if (!(ptr = realloc(ptr, size))) + xlog(L_FATAL, "realloc: out of memory"); + return ptr; +} + +void +xfree(void *ptr) +{ + free(ptr); +} + +char * +xstrdup(const char *str) +{ + char *ret; + + if (!(ret = strdup(str))) + xlog(L_FATAL, "strdup: out of memory"); + return ret; +} diff --git a/support/nfs/ypupdate_xdr.c b/support/nfs/ypupdate_xdr.c new file mode 100644 index 0000000..9fe1098 --- /dev/null +++ b/support/nfs/ypupdate_xdr.c @@ -0,0 +1,29 @@ +/* + * support/nfs/ypupdate_xdr.c + * + * This file contains the XDR code for the ypupdate protocol. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <ypupdate.h> + +bool_t +xdr_ypupdate_args(XDR *xdrs, ypupdate_args *objp) +{ + return xdr_string(xdrs, &objp->mapname, MAXMAPNAMELEN) && + xdr_bytes(xdrs, &objp->key.yp_buf_val, + &objp->key.yp_buf_len, MAXYPDATALEN) && + xdr_bytes(xdrs, &objp->datum.yp_buf_val, + &objp->datum.yp_buf_len, MAXYPDATALEN); +} + +bool_t +xdr_ypdelete_args(XDR *xdrs, ypdelete_args *objp) +{ + return xdr_string(xdrs, &objp->mapname, MAXMAPNAMELEN) && + xdr_bytes(xdrs, &objp->key.yp_buf_val, + &objp->key.yp_buf_len, MAXYPDATALEN); +} |