* and listen for requests (using my_svc_run)
*
*/
-#include "config.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
#include <sys/types.h>
#include <sys/select.h>
if (inet_aton(ipaddr, &addr)==0)
return;
+ auth_reload();
+
/* addr is a valid, interesting address, find the domain name... */
client = client_compose(addr);
qword_print(f, *client?client:"DEFAULT");
qword_eol(f);
+ if (client && strcmp(ipaddr, client))
+ mountlist_add(ipaddr, *client?client:"DEFAULT");
+
if (client) free(client);
}
struct exportent *found = NULL;
nfs_export *exp;
int i;
+ int dev_missing = 0;
if (readline(fileno(f), &lbuf, &lbuflen) != 1)
return;
goto out;
if (qword_get_int(&cp, &fsidtype) != 0)
goto out;
- if (fsidtype < 0 || fsidtype > 1)
+ if (fsidtype < 0 || fsidtype > 3)
goto out; /* unknown type */
if ((fsidlen = qword_get(&cp, fsid, 32)) <= 0)
goto out;
goto out;
memcpy(&fsidnum, fsid, 4);
break;
+
+ case 2: /* 12 bytes: 4 major, 4 minor, 4 inode
+ * This format is never actually used but was
+ * an historical accident
+ */
+ if (fsidlen != 12)
+ goto out;
+ memcpy(&dev, fsid, 4); major = ntohl(dev);
+ memcpy(&dev, fsid+4, 4); minor = ntohl(dev);
+ memcpy(&inode, fsid+8, 4);
+ break;
+
+ case 3: /* 8 bytes: 4 byte packed device number, 4 inode */
+ /* This is *host* endian, not net-byte-order, because
+ * no-one outside this host has any business interpreting it
+ */
+ if (fsidlen != 8)
+ goto out;
+ memcpy(&dev, fsid, 4);
+ memcpy(&inode, fsid+4, 4);
+ major = (dev & 0xfff00) >> 8;
+ minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
+ break;
+
}
+ auth_reload();
+
/* Now determine export point for this fsid/domain */
for (i=0 ; i < MCL_MAXTYPES; i++) {
for (exp = exportlist[i]; exp; exp = exp->m_next) {
+ struct stat stb;
+
if (!client_member(dom, exp->m_client->m_hostname))
continue;
+ if (exp->m_export.e_mountpoint &&
+ !is_mountpoint(exp->m_export.e_mountpoint[0]?
+ exp->m_export.e_mountpoint:
+ exp->m_export.e_path))
+ dev_missing ++;
+ if (stat(exp->m_export.e_path, &stb) != 0)
+ continue;
if (fsidtype == 1 &&
((exp->m_export.e_flags & NFSEXP_FSID) == 0 ||
exp->m_export.e_fsid != fsidnum))
continue;
- if (fsidtype == 0) {
- struct stat stb;
- if (stat(exp->m_export.e_path, &stb) != 0)
- continue;
+ if (fsidtype != 1) {
if (stb.st_ino != inode)
continue;
if (major != major(stb.st_dev) ||
found = &exp->m_export;
else if (strcmp(found->e_path, exp->m_export.e_path)!= 0)
{
- xlog(L_WARNING, "%s and %s have name filehandle for %s, using first",
+ xlog(L_WARNING, "%s and %s have same filehandle for %s, using first",
found->e_path, exp->m_export.e_path, dom);
}
}
}
- cache_export_ent(dom, found);
+ if (found &&
+ found->e_mountpoint &&
+ !is_mountpoint(found->e_mountpoint[0]?
+ found->e_mountpoint:
+ found->e_path)) {
+ /* Cannot export this yet
+ * should log a warning, but need to rate limit
+ xlog(L_WARNING, "%s not exported as %d not a mountpoint",
+ found->e_path, found->e_mountpoint);
+ */
+ /* FIXME we need to make sure we re-visit this later */
+ goto out;
+ }
+ if (!found && dev_missing) {
+ /* The missing dev could be what we want, so just be
+ * quite rather than returning stale yet
+ */
+ goto out;
+ }
+
+ if (found)
+ cache_export_ent(dom, found);
qword_print(f, dom);
qword_printint(f, fsidtype);
if (qword_get(&cp, path, strlen(lbuf)) <= 0)
goto out;
+ auth_reload();
+
/* now find flags for this export point in this domain */
for (i=0 ; i < MCL_MAXTYPES; i++) {
for (exp = exportlist[i]; exp; exp = exp->m_next) {
qword_printint(f, found->m_export.e_anonuid);
qword_printint(f, found->m_export.e_anongid);
qword_printint(f, found->m_export.e_fsid);
+ mountlist_add(dom, path);
}
qword_eol(f);
out:
FD_ISSET(fileno(cachelist[i].f), readfds)) {
cnt++;
cachelist[i].cache_handle(cachelist[i].f);
+ FD_CLR(fileno(cachelist[i].f), readfds);
}
}
return cnt;
void cache_export_ent(char *domain, struct exportent *exp)
{
- FILE *f = fopen("/proc/net/rpc/nfsd.export/channel", "r+");
+ FILE *f = fopen("/proc/net/rpc/nfsd.export/channel", "w");
if (!f)
return;
qword_eol(f);
fclose(f);
+
+ mountlist_add(domain, exp->e_path);
}
void cache_export(nfs_export *exp)
{
FILE *f;
- f = fopen("/proc/net/rpc/auth.unix.ip/channel", "r+");
+ f = fopen("/proc/net/rpc/auth.unix.ip/channel", "w");
if (!f)
return;
fclose(f);
+ if (strcmp(inet_ntoa(exp->m_client->m_addrlist[0]), exp->m_client->m_hostname))
+ mountlist_add(inet_ntoa(exp->m_client->m_addrlist[0]), exp->m_client->m_hostname);
+
cache_export_ent(exp->m_client->m_hostname, &exp->m_export);
}
* {
* echo $domain $path $length
* read filehandle <&0
- * } <> /proc/fs/nfs/filehandle
+ * } <> /proc/fs/nfsd/filehandle
*/
struct nfs_fh_len *
-cache_get_filehandle(nfs_export *exp, int len)
+cache_get_filehandle(nfs_export *exp, int len, char *p)
{
- FILE *f = fopen("/proc/fs/nfs/filehandle", "r+");
+ FILE *f = fopen("/proc/fs/nfsd/filehandle", "r+");
char buf[200];
char *bp = buf;
+ int failed;
static struct nfs_fh_len fh;
+
+ if (!f)
+ f = fopen("/proc/fs/nfs/filehandle", "r+");
if (!f)
return NULL;
qword_print(f, exp->m_client->m_hostname);
- qword_print(f, exp->m_export.e_path);
+ qword_print(f, p);
qword_printint(f, len);
qword_eol(f);
- if (fgets(buf, sizeof(buf), f) == NULL)
+ failed = (fgets(buf, sizeof(buf), f) == NULL);
+ fclose(f);
+ if (failed)
return NULL;
memset(fh.fh_handle, 0, sizeof(fh.fh_handle));
fh.fh_size = qword_get(&bp, fh.fh_handle, NFS3_FHSIZE);