1116 lines
32 KiB
Diff
1116 lines
32 KiB
Diff
|
diff --git a/aclocal/ipv6.m4 b/aclocal/ipv6.m4
|
||
|
index 5ee8fb6..4e39fbe 100644
|
||
|
--- a/aclocal/ipv6.m4
|
||
|
+++ b/aclocal/ipv6.m4
|
||
|
@@ -2,11 +2,6 @@ dnl Checks for IPv6 support
|
||
|
dnl
|
||
|
AC_DEFUN([AC_IPV6], [
|
||
|
|
||
|
- AC_CHECK_DECL([AI_ADDRCONFIG],
|
||
|
- [AC_DEFINE([HAVE_DECL_AI_ADDRCONFIG], 1,
|
||
|
- [Define this to 1 if AI_ADDRCONFIG macro is defined])], ,
|
||
|
- [ #include <netdb.h> ])
|
||
|
-
|
||
|
if test "$enable_ipv6" = yes; then
|
||
|
|
||
|
dnl TI-RPC required for IPv6
|
||
|
@@ -18,12 +13,6 @@ AC_DEFUN([AC_IPV6], [
|
||
|
AC_CHECK_FUNCS([getifaddrs getnameinfo bindresvport_sa], ,
|
||
|
[AC_MSG_ERROR([Missing library functions needed for IPv6.])])
|
||
|
|
||
|
- dnl Need to detect presence of IPv6 networking at run time via
|
||
|
- dnl getaddrinfo(3); old versions of glibc do not support ADDRCONFIG
|
||
|
- AC_CHECK_DECL([AI_ADDRCONFIG], ,
|
||
|
- [AC_MSG_ERROR([full getaddrinfo(3) implementation needed for IPv6 support])],
|
||
|
- [ #include <netdb.h> ])
|
||
|
-
|
||
|
fi
|
||
|
|
||
|
])dnl
|
||
|
diff --git a/aclocal/libevent.m4 b/aclocal/libevent.m4
|
||
|
index 3c962b3..b5ac00f 100644
|
||
|
--- a/aclocal/libevent.m4
|
||
|
+++ b/aclocal/libevent.m4
|
||
|
@@ -2,8 +2,9 @@ dnl Checks for libevent
|
||
|
AC_DEFUN([AC_LIBEVENT], [
|
||
|
|
||
|
dnl Check for libevent, but do not add -levent to LIBS
|
||
|
- AC_CHECK_LIB([event], [event_dispatch], [libevent=1],
|
||
|
+ AC_CHECK_LIB([event], [event_dispatch], [LIBEVENT=-levent],
|
||
|
[AC_MSG_ERROR([libevent not found.])])
|
||
|
+ AC_SUBST(LIBEVENT)
|
||
|
|
||
|
AC_CHECK_HEADERS([event.h], ,
|
||
|
[AC_MSG_ERROR([libevent headers not found.])])
|
||
|
diff --git a/aclocal/libnfsidmap.m4 b/aclocal/libnfsidmap.m4
|
||
|
index 484b1ec..ae697e8 100644
|
||
|
--- a/aclocal/libnfsidmap.m4
|
||
|
+++ b/aclocal/libnfsidmap.m4
|
||
|
@@ -3,7 +3,7 @@ dnl
|
||
|
AC_DEFUN([AC_LIBNFSIDMAP], [
|
||
|
|
||
|
dnl Check for libnfsidmap, but do not add -lnfsidmap to LIBS
|
||
|
- AC_CHECK_LIB([nfsidmap], [nfs4_init_name_mapping], [libnfsidmap=1],
|
||
|
+ AC_CHECK_LIB([nfsidmap], [nfs4_init_name_mapping], [LIBNFSIDMAP=-lnfsidmap],
|
||
|
[AC_MSG_ERROR([libnfsidmap not found.])])
|
||
|
|
||
|
AC_CHECK_HEADERS([nfsidmap.h], ,
|
||
|
@@ -14,7 +14,10 @@ AC_DEFUN([AC_LIBNFSIDMAP], [
|
||
|
[AC_DEFINE([HAVE_NFS4_SET_DEBUG], 1,
|
||
|
[Define to 1 if you have the `nfs4_set_debug' function.])])
|
||
|
|
||
|
- dnl only enable nfsidmap when libnfsidmap supports it
|
||
|
- AC_CHECK_LIB([nfsidmap], [nfs4_owner_to_uid])
|
||
|
+ dnl nfs4_owner_to_uid() doesn't appear in all versions of libnfsidmap
|
||
|
+ dnl We just need this test to set $ac_cv_lib_nfsidmap_nfs4_owner_to_uid
|
||
|
+ AC_CHECK_LIB([nfsidmap], [nfs4_owner_to_uid], [:])
|
||
|
+
|
||
|
+ AC_SUBST(LIBNFSIDMAP)
|
||
|
|
||
|
])dnl
|
||
|
diff --git a/configure.ac b/configure.ac
|
||
|
index 80fb39d..920e8da 100644
|
||
|
--- a/configure.ac
|
||
|
+++ b/configure.ac
|
||
|
@@ -24,9 +24,8 @@ AC_ARG_WITH(statedir,
|
||
|
statedir=/var/lib/nfs)
|
||
|
AC_SUBST(statedir)
|
||
|
AC_ARG_WITH(statdpath,
|
||
|
- [AC_HELP_STRING([--with-statdpath=/foo @<:@default=/var/lib/nfs@:>@],
|
||
|
- [define statd's state dir as /foo instead of the NFS statedir]
|
||
|
- )],
|
||
|
+ [AC_HELP_STRING([--with-statdpath=/foo],
|
||
|
+ [define the statd state dir as /foo instead of the NFS statedir @<:@default=/var/lib/nfs@:>@])],
|
||
|
statdpath=$withval,
|
||
|
statdpath=$statedir
|
||
|
)
|
||
|
@@ -249,6 +248,8 @@ AC_CHECK_FUNC([getservbyname], ,
|
||
|
|
||
|
AC_CHECK_LIB([crypt], [crypt], [LIBCRYPT="-lcrypt"])
|
||
|
|
||
|
+AC_CHECK_LIB([dl], [dlclose], [LIBDL="-ldl"])
|
||
|
+
|
||
|
if test "$enable_nfsv4" = yes; then
|
||
|
dnl check for libevent libraries and headers
|
||
|
AC_LIBEVENT
|
||
|
@@ -265,6 +266,12 @@ if test "$enable_nfsv4" = yes; then
|
||
|
AC_RPCSEC_VERSION
|
||
|
fi
|
||
|
fi
|
||
|
+
|
||
|
+if test "$enable_nfsv41" = yes; then
|
||
|
+ AC_CHECK_LIB([devmapper], [dm_task_create], [LIBDEVMAPPER="-ldevmapper"], AC_MSG_ERROR([libdevmapper needed]))
|
||
|
+ AC_CHECK_HEADER(libdevmapper.h, , AC_MSG_ERROR([Cannot find devmapper header file libdevmapper.h]))
|
||
|
+fi
|
||
|
+
|
||
|
dnl enable nfsidmap when its support by libnfsidmap
|
||
|
AM_CONDITIONAL(CONFIG_NFSIDMAP, [test "$ac_cv_header_keyutils_h$ac_cv_lib_nfsidmap_nfs4_owner_to_uid" = "yesyes"])
|
||
|
|
||
|
@@ -293,6 +300,7 @@ AC_SUBST(LIBSOCKET)
|
||
|
AC_SUBST(LIBCRYPT)
|
||
|
AC_SUBST(LIBBSD)
|
||
|
AC_SUBST(LIBBLKID)
|
||
|
+AC_SUBST(LIBDL)
|
||
|
|
||
|
if test "$enable_libmount" != no; then
|
||
|
AC_CHECK_LIB(mount, mnt_context_do_mount, [LIBMOUNT="-lmount"], AC_MSG_ERROR([libmount needed]))
|
||
|
@@ -330,7 +338,7 @@ AC_CHECK_HEADERS([arpa/inet.h fcntl.h libintl.h limits.h \
|
||
|
stdlib.h string.h sys/file.h sys/ioctl.h sys/mount.h \
|
||
|
sys/param.h sys/socket.h sys/time.h sys/vfs.h \
|
||
|
syslog.h unistd.h com_err.h et/com_err.h \
|
||
|
- ifaddrs.h])
|
||
|
+ ifaddrs.h nfs-plugin.h])
|
||
|
|
||
|
dnl *************************************************************
|
||
|
dnl Checks for typedefs, structures, and compiler characteristics
|
||
|
diff --git a/support/include/nfs/debug.h b/support/include/nfs/debug.h
|
||
|
index d391e91..dbec5ba 100644
|
||
|
--- a/support/include/nfs/debug.h
|
||
|
+++ b/support/include/nfs/debug.h
|
||
|
@@ -76,6 +76,9 @@ enum {
|
||
|
#define NFSDBG_CALLBACK 0x0100
|
||
|
#define NFSDBG_CLIENT 0x0200
|
||
|
#define NFSDBG_MOUNT 0x0400
|
||
|
+#define NFSDBG_FSCACHE 0x0800
|
||
|
+#define NFSDBG_PNFS 0x1000
|
||
|
+#define NFSDBG_PNFS_LD 0x2000
|
||
|
#define NFSDBG_ALL 0xFFFF
|
||
|
|
||
|
#endif /* _NFS_DEBUG_H */
|
||
|
diff --git a/support/nfs/conffile.c b/support/nfs/conffile.c
|
||
|
index fa0dc6b..3990578 100644
|
||
|
--- a/support/nfs/conffile.c
|
||
|
+++ b/support/nfs/conffile.c
|
||
|
@@ -256,13 +256,14 @@ conf_parse_line(int trans, char *line, size_t sz)
|
||
|
val++, j++;
|
||
|
if (*val)
|
||
|
i = j;
|
||
|
- section = malloc(i);
|
||
|
+ section = malloc(i+1);
|
||
|
if (!section) {
|
||
|
xlog_warn("conf_parse_line: %d: malloc (%lu) failed", ln,
|
||
|
(unsigned long)i);
|
||
|
return;
|
||
|
}
|
||
|
strncpy(section, line, i);
|
||
|
+ section[i] = '\0';
|
||
|
|
||
|
if (arg)
|
||
|
free(arg);
|
||
|
diff --git a/support/nfs/nfsctl.c b/support/nfs/nfsctl.c
|
||
|
index 89fa1a4..fec775f 100644
|
||
|
--- a/support/nfs/nfsctl.c
|
||
|
+++ b/support/nfs/nfsctl.c
|
||
|
@@ -11,16 +11,22 @@
|
||
|
#endif
|
||
|
|
||
|
#include <unistd.h>
|
||
|
+#include <errno.h>
|
||
|
#include <asm/unistd.h>
|
||
|
#include "nfslib.h"
|
||
|
|
||
|
/* compatibility hack... */
|
||
|
-#ifndef __NR_nfsctl
|
||
|
+#if !defined(__NR_nfsctl) && defined(__NR_nfsservctl)
|
||
|
#define __NR_nfsctl __NR_nfsservctl
|
||
|
#endif
|
||
|
|
||
|
int
|
||
|
nfsctl (int cmd, struct nfsctl_arg * argp, union nfsctl_res * resp)
|
||
|
{
|
||
|
+#ifdef __NR_nfsctl
|
||
|
return syscall (__NR_nfsctl, cmd, argp, resp);
|
||
|
+#else
|
||
|
+ errno = ENOSYS;
|
||
|
+ return -1;
|
||
|
+#endif
|
||
|
}
|
||
|
diff --git a/tools/rpcdebug/rpcdebug.c b/tools/rpcdebug/rpcdebug.c
|
||
|
index 275a491..444616d 100644
|
||
|
--- a/tools/rpcdebug/rpcdebug.c
|
||
|
+++ b/tools/rpcdebug/rpcdebug.c
|
||
|
@@ -167,6 +167,9 @@ static struct flagmap {
|
||
|
FLAG(NFS, CALLBACK),
|
||
|
FLAG(NFS, CLIENT),
|
||
|
FLAG(NFS, MOUNT),
|
||
|
+ FLAG(NFS, FSCACHE),
|
||
|
+ FLAG(NFS, PNFS),
|
||
|
+ FLAG(NFS, PNFS_LD),
|
||
|
FLAG(NFS, ALL),
|
||
|
|
||
|
/* nfsd */
|
||
|
diff --git a/utils/blkmapd/device-process.c b/utils/blkmapd/device-process.c
|
||
|
index 27ff374..652a7a8 100644
|
||
|
--- a/utils/blkmapd/device-process.c
|
||
|
+++ b/utils/blkmapd/device-process.c
|
||
|
@@ -296,7 +296,7 @@ decode_blk_volume(uint32_t **pp, uint32_t *end, struct bl_volume *vols, int voln
|
||
|
off_t stripe_unit = vol->param.bv_stripe_unit;
|
||
|
/* Check limitations imposed by device-mapper */
|
||
|
if ((stripe_unit & (stripe_unit - 1)) != 0
|
||
|
- || stripe_unit < (off_t) (PAGE_SIZE >> 9))
|
||
|
+ || stripe_unit < (off_t) (sysconf(_SC_PAGE_SIZE) >> 9))
|
||
|
return -EIO;
|
||
|
BLK_READBUF(p, end, 4);
|
||
|
READ32(vol->bv_vol_n);
|
||
|
diff --git a/utils/exportfs/exportfs.man b/utils/exportfs/exportfs.man
|
||
|
index 364f247..8853486 100644
|
||
|
--- a/utils/exportfs/exportfs.man
|
||
|
+++ b/utils/exportfs/exportfs.man
|
||
|
@@ -177,7 +177,7 @@ In this way
|
||
|
.B exportfs
|
||
|
can be used to modify the export options of an already exported directory.
|
||
|
.SS Unexporting Directories
|
||
|
-The third synopsis shows how to unexported a currently exported directory.
|
||
|
+The third synopsis shows how to unexport a currently exported directory.
|
||
|
When using
|
||
|
.BR "exportfs -ua" ,
|
||
|
all entries listed in
|
||
|
diff --git a/utils/exportfs/nfsd.man b/utils/exportfs/nfsd.man
|
||
|
index 7365a1b..47b73be 100644
|
||
|
--- a/utils/exportfs/nfsd.man
|
||
|
+++ b/utils/exportfs/nfsd.man
|
||
|
@@ -12,7 +12,7 @@ nfsd \- special filesystem for controlling Linux NFS server
|
||
|
.SH DESCRIPTION
|
||
|
The
|
||
|
.B nfsd
|
||
|
-filesytem is a special filesystem which provides access to the Linux
|
||
|
+filesystem is a special filesystem which provides access to the Linux
|
||
|
NFS server. The filesystem consists of a single directory which
|
||
|
contains a number of files. These files are actually gateways into
|
||
|
the NFS server. Writing to them can affect the server. Reading from
|
||
|
@@ -86,7 +86,7 @@ should be followed by a newline, with white-space separating the
|
||
|
fields, and octal quoting of special characters.
|
||
|
|
||
|
On writing this, the program will be able to read back a filehandle
|
||
|
-for that path as exported to the given client. The filehandles length
|
||
|
+for that path as exported to the given client. The filehandle's length
|
||
|
will be at most the number of bytes given.
|
||
|
|
||
|
The filehandle will be represented in hex with a leading '\ex'.
|
||
|
@@ -165,7 +165,7 @@ file. The user-space program might then write
|
||
|
.ti +5
|
||
|
nfsd 127.0.0.1 1057206953 localhost
|
||
|
.br
|
||
|
-to indicate that 127.0.0.1 should map to localhost, atleast for now.
|
||
|
+to indicate that 127.0.0.1 should map to localhost, at least for now.
|
||
|
|
||
|
If the program uses select(2) or poll(2) to discover if it can read
|
||
|
from the
|
||
|
diff --git a/utils/gssd/Makefile.am b/utils/gssd/Makefile.am
|
||
|
index d7888ad..9136189 100644
|
||
|
--- a/utils/gssd/Makefile.am
|
||
|
+++ b/utils/gssd/Makefile.am
|
||
|
@@ -58,7 +58,7 @@ svcgssd_SOURCES = \
|
||
|
|
||
|
svcgssd_LDADD = \
|
||
|
../../support/nfs/libnfs.a \
|
||
|
- $(RPCSECGSS_LIBS) $(GSSGLUE_LIBS) -lnfsidmap \
|
||
|
+ $(RPCSECGSS_LIBS) $(GSSGLUE_LIBS) $(LIBNFSIDMAP) \
|
||
|
$(KRBLIBS)
|
||
|
|
||
|
svcgssd_LDFLAGS = $(KRBLDFLAGS)
|
||
|
diff --git a/utils/gssd/context_lucid.c b/utils/gssd/context_lucid.c
|
||
|
index 3e695ab..64146d7 100644
|
||
|
--- a/utils/gssd/context_lucid.c
|
||
|
+++ b/utils/gssd/context_lucid.c
|
||
|
@@ -80,6 +80,7 @@ prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx,
|
||
|
uint32_t i;
|
||
|
char *skd, *dkd;
|
||
|
gss_buffer_desc fakeoid;
|
||
|
+ int err;
|
||
|
|
||
|
/*
|
||
|
* The new Kerberos interface to get the gss context
|
||
|
@@ -138,11 +139,10 @@ prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx,
|
||
|
dkd = (char *) enc_key.data;
|
||
|
for (i = 0; i < enc_key.length; i++)
|
||
|
dkd[i] = skd[i] ^ 0xf0;
|
||
|
- if (write_lucid_keyblock(&p, end, &enc_key)) {
|
||
|
- free(enc_key.data);
|
||
|
- goto out_err;
|
||
|
- }
|
||
|
+ err = write_lucid_keyblock(&p, end, &enc_key);
|
||
|
free(enc_key.data);
|
||
|
+ if (err)
|
||
|
+ goto out_err;
|
||
|
|
||
|
if (write_lucid_keyblock(&p, end, &lctx->rfc1964_kd.ctx_key))
|
||
|
goto out_err;
|
||
|
@@ -153,7 +153,6 @@ out_err:
|
||
|
printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
|
||
|
if (buf->value) free(buf->value);
|
||
|
buf->length = 0;
|
||
|
- if (enc_key.data) free(enc_key.data);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
diff --git a/utils/idmapd/Makefile.am b/utils/idmapd/Makefile.am
|
||
|
index 4328e41..58b33ec 100644
|
||
|
--- a/utils/idmapd/Makefile.am
|
||
|
+++ b/utils/idmapd/Makefile.am
|
||
|
@@ -16,7 +16,7 @@ idmapd_SOURCES = \
|
||
|
nfs_idmap.h \
|
||
|
queue.h
|
||
|
|
||
|
-idmapd_LDADD = -levent -lnfsidmap ../../support/nfs/libnfs.a
|
||
|
+idmapd_LDADD = $(LIBEVENT) $(LIBNFSIDMAP) ../../support/nfs/libnfs.a
|
||
|
|
||
|
MAINTAINERCLEANFILES = Makefile.in
|
||
|
|
||
|
diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
|
||
|
index 19d9114..e80efb4 100644
|
||
|
--- a/utils/idmapd/idmapd.c
|
||
|
+++ b/utils/idmapd/idmapd.c
|
||
|
@@ -778,8 +778,8 @@ nfsopen(struct idmap_client *ic)
|
||
|
} else {
|
||
|
event_set(&ic->ic_event, ic->ic_fd, EV_READ, nfscb, ic);
|
||
|
event_add(&ic->ic_event, NULL);
|
||
|
- fcntl(ic->ic_dirfd, F_SETSIG, 0);
|
||
|
fcntl(ic->ic_dirfd, F_NOTIFY, 0);
|
||
|
+ fcntl(ic->ic_dirfd, F_SETSIG, 0);
|
||
|
if (verbose > 0)
|
||
|
xlog_warn("Opened %s", ic->ic_path);
|
||
|
}
|
||
|
diff --git a/utils/mount/mount_libmount.c b/utils/mount/mount_libmount.c
|
||
|
index e450d79..e8f17a9 100644
|
||
|
--- a/utils/mount/mount_libmount.c
|
||
|
+++ b/utils/mount/mount_libmount.c
|
||
|
@@ -346,6 +346,21 @@ static int mount_main(struct libmnt_context *cxt, int argc, char **argv)
|
||
|
|
||
|
if (chk_mountpoint(mount_point))
|
||
|
goto err;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * The libmount strictly uses only options from fstab if running in
|
||
|
+ * restricted mode (suid, non-root user). This is done in
|
||
|
+ * mnt_context_prepare_mount() by default.
|
||
|
+ *
|
||
|
+ * We have to read fstab before nfsmount.conf, otherwise the options
|
||
|
+ * from nfsmount.conf will be ignored (overwrited).
|
||
|
+ */
|
||
|
+ rc = mnt_context_apply_fstab(cxt);
|
||
|
+ if (rc) {
|
||
|
+ nfs_error(_("%s: failed to apply fstab options\n"), progname);
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
/*
|
||
|
* Concatenate mount options from the configuration file
|
||
|
*/
|
||
|
diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man
|
||
|
index ce40933..2ad92d1 100644
|
||
|
--- a/utils/mount/nfs.man
|
||
|
+++ b/utils/mount/nfs.man
|
||
|
@@ -1561,10 +1561,10 @@ To ensure that the saved mount options are not erased during a remount,
|
||
|
specify either the local mount directory, or the server hostname and
|
||
|
export pathname, but not both, during a remount. For example,
|
||
|
.P
|
||
|
-.NF
|
||
|
-.TA 2.5i
|
||
|
+.nf
|
||
|
+.ta 8n
|
||
|
mount -o remount,ro /mnt
|
||
|
-.FI
|
||
|
+.fi
|
||
|
.P
|
||
|
merges the mount option
|
||
|
.B ro
|
||
|
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
|
||
|
index 314a806..d52e21a 100644
|
||
|
--- a/utils/mount/stropts.c
|
||
|
+++ b/utils/mount/stropts.c
|
||
|
@@ -540,6 +540,8 @@ nfs_rewrite_pmap_mount_options(struct mount_options *options)
|
||
|
errno = EOPNOTSUPP;
|
||
|
else if (rpc_createerr.cf_stat == RPC_AUTHERROR)
|
||
|
errno = EACCES;
|
||
|
+ else if (rpc_createerr.cf_stat == RPC_TIMEDOUT)
|
||
|
+ errno = ETIMEDOUT;
|
||
|
else if (rpc_createerr.cf_error.re_errno != 0)
|
||
|
errno = rpc_createerr.cf_error.re_errno;
|
||
|
return 0;
|
||
|
@@ -665,9 +667,10 @@ static int nfs_try_mount_v3v2(struct nfsmount_info *mi)
|
||
|
case EHOSTUNREACH:
|
||
|
continue;
|
||
|
default:
|
||
|
- break;
|
||
|
+ goto out;
|
||
|
}
|
||
|
}
|
||
|
+out:
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
@@ -751,9 +754,10 @@ static int nfs_try_mount_v4(struct nfsmount_info *mi)
|
||
|
case EHOSTUNREACH:
|
||
|
continue;
|
||
|
default:
|
||
|
- break;
|
||
|
+ goto out;
|
||
|
}
|
||
|
}
|
||
|
+out:
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
diff --git a/utils/mountd/Makefile.am b/utils/mountd/Makefile.am
|
||
|
index eba81fc..5a2d1b6 100644
|
||
|
--- a/utils/mountd/Makefile.am
|
||
|
+++ b/utils/mountd/Makefile.am
|
||
|
@@ -12,7 +12,7 @@ mountd_SOURCES = mountd.c mount_dispatch.c auth.c rmtab.c cache.c \
|
||
|
mountd_LDADD = ../../support/export/libexport.a \
|
||
|
../../support/nfs/libnfs.a \
|
||
|
../../support/misc/libmisc.a \
|
||
|
- $(LIBBSD) $(LIBWRAP) $(LIBNSL) $(LIBBLKID)
|
||
|
+ $(LIBBSD) $(LIBWRAP) $(LIBNSL) $(LIBBLKID) $(LIBDL)
|
||
|
mountd_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||
|
-I$(top_builddir)/support/include \
|
||
|
-I$(top_srcdir)/support/export
|
||
|
diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
|
||
|
index d2ae456..ac9cdbd 100644
|
||
|
--- a/utils/mountd/cache.c
|
||
|
+++ b/utils/mountd/cache.c
|
||
|
@@ -802,6 +802,229 @@ lookup_export(char *dom, char *path, struct addrinfo *ai)
|
||
|
return found;
|
||
|
}
|
||
|
|
||
|
+#ifdef HAVE_NFS_PLUGIN_H
|
||
|
+#include <dlfcn.h>
|
||
|
+#include <nfs-plugin.h>
|
||
|
+
|
||
|
+/*
|
||
|
+ * Walk through a set of FS locations and build a set of export options.
|
||
|
+ * Returns true if all went to plan; otherwise, false.
|
||
|
+ */
|
||
|
+static _Bool
|
||
|
+locations_to_options(struct jp_ops *ops, nfs_fsloc_set_t locations,
|
||
|
+ char *options, size_t remaining, int *ttl)
|
||
|
+{
|
||
|
+ char *server, *last_path, *rootpath, *ptr;
|
||
|
+ _Bool seen = false;
|
||
|
+
|
||
|
+ last_path = NULL;
|
||
|
+ rootpath = NULL;
|
||
|
+ server = NULL;
|
||
|
+ ptr = options;
|
||
|
+ *ttl = 0;
|
||
|
+
|
||
|
+ for (;;) {
|
||
|
+ enum jp_status status;
|
||
|
+ int len;
|
||
|
+
|
||
|
+ status = ops->jp_get_next_location(locations, &server,
|
||
|
+ &rootpath, ttl);
|
||
|
+ if (status == JP_EMPTY)
|
||
|
+ break;
|
||
|
+ if (status != JP_OK) {
|
||
|
+ xlog(D_GENERAL, "%s: failed to parse location: %s",
|
||
|
+ __func__, ops->jp_error(status));
|
||
|
+ goto out_false;
|
||
|
+ }
|
||
|
+ xlog(D_GENERAL, "%s: Location: %s:%s",
|
||
|
+ __func__, server, rootpath);
|
||
|
+
|
||
|
+ if (last_path && strcmp(rootpath, last_path) == 0) {
|
||
|
+ len = snprintf(ptr, remaining, "+%s", server);
|
||
|
+ if (len < 0) {
|
||
|
+ xlog(D_GENERAL, "%s: snprintf: %m", __func__);
|
||
|
+ goto out_false;
|
||
|
+ }
|
||
|
+ if ((size_t)len >= remaining) {
|
||
|
+ xlog(D_GENERAL, "%s: options buffer overflow", __func__);
|
||
|
+ goto out_false;
|
||
|
+ }
|
||
|
+ remaining -= (size_t)len;
|
||
|
+ ptr += len;
|
||
|
+ } else {
|
||
|
+ if (last_path == NULL)
|
||
|
+ len = snprintf(ptr, remaining, "refer=%s@%s",
|
||
|
+ rootpath, server);
|
||
|
+ else
|
||
|
+ len = snprintf(ptr, remaining, ":%s@%s",
|
||
|
+ rootpath, server);
|
||
|
+ if (len < 0) {
|
||
|
+ xlog(D_GENERAL, "%s: snprintf: %m", __func__);
|
||
|
+ goto out_false;
|
||
|
+ }
|
||
|
+ if ((size_t)len >= remaining) {
|
||
|
+ xlog(D_GENERAL, "%s: options buffer overflow",
|
||
|
+ __func__);
|
||
|
+ goto out_false;
|
||
|
+ }
|
||
|
+ remaining -= (size_t)len;
|
||
|
+ ptr += len;
|
||
|
+ last_path = rootpath;
|
||
|
+ }
|
||
|
+
|
||
|
+ seen = true;
|
||
|
+ free(rootpath);
|
||
|
+ free(server);
|
||
|
+ }
|
||
|
+
|
||
|
+ xlog(D_CALL, "%s: options='%s', ttl=%d",
|
||
|
+ __func__, options, *ttl);
|
||
|
+ return seen;
|
||
|
+
|
||
|
+out_false:
|
||
|
+ free(rootpath);
|
||
|
+ free(server);
|
||
|
+ return false;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * Walk through the set of FS locations and build an exportent.
|
||
|
+ * Returns pointer to an exportent if "junction" refers to a junction.
|
||
|
+ *
|
||
|
+ * Returned exportent points to static memory.
|
||
|
+ */
|
||
|
+static struct exportent *do_locations_to_export(struct jp_ops *ops,
|
||
|
+ nfs_fsloc_set_t locations, const char *junction,
|
||
|
+ char *options, size_t options_len)
|
||
|
+{
|
||
|
+ struct exportent *exp;
|
||
|
+ int ttl;
|
||
|
+
|
||
|
+ if (!locations_to_options(ops, locations, options, options_len, &ttl))
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ exp = mkexportent("*", (char *)junction, options);
|
||
|
+ if (exp == NULL) {
|
||
|
+ xlog(L_ERROR, "%s: Failed to construct exportent", __func__);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ exp->e_uuid = NULL;
|
||
|
+ exp->e_ttl = ttl;
|
||
|
+ return exp;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * Convert set of FS locations to an exportent. Returns pointer to
|
||
|
+ * an exportent if "junction" refers to a junction.
|
||
|
+ *
|
||
|
+ * Returned exportent points to static memory.
|
||
|
+ */
|
||
|
+static struct exportent *locations_to_export(struct jp_ops *ops,
|
||
|
+ nfs_fsloc_set_t locations, const char *junction)
|
||
|
+{
|
||
|
+ struct exportent *exp;
|
||
|
+ char *options;
|
||
|
+
|
||
|
+ options = malloc(BUFSIZ);
|
||
|
+ if (options == NULL) {
|
||
|
+ xlog(D_GENERAL, "%s: failed to allocate options buffer",
|
||
|
+ __func__);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+ options[0] = '\0';
|
||
|
+
|
||
|
+ exp = do_locations_to_export(ops, locations, junction,
|
||
|
+ options, BUFSIZ);
|
||
|
+
|
||
|
+ free(options);
|
||
|
+ return exp;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * Retrieve locations information in "junction" and dump it to the
|
||
|
+ * kernel. Returns pointer to an exportent if "junction" refers
|
||
|
+ * to a junction.
|
||
|
+ *
|
||
|
+ * Returned exportent points to static memory.
|
||
|
+ */
|
||
|
+static struct exportent *invoke_junction_ops(void *handle,
|
||
|
+ const char *junction)
|
||
|
+{
|
||
|
+ nfs_fsloc_set_t locations;
|
||
|
+ struct exportent *exp;
|
||
|
+ enum jp_status status;
|
||
|
+ struct jp_ops *ops;
|
||
|
+ char *error;
|
||
|
+
|
||
|
+ ops = (struct jp_ops *)dlsym(handle, "nfs_junction_ops");
|
||
|
+ error = dlerror();
|
||
|
+ if (error != NULL) {
|
||
|
+ xlog(D_GENERAL, "%s: dlsym(jp_junction_ops): %s",
|
||
|
+ __func__, error);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+ if (ops->jp_api_version != JP_API_VERSION) {
|
||
|
+ xlog(D_GENERAL, "%s: unrecognized junction API version: %u",
|
||
|
+ __func__, ops->jp_api_version);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ status = ops->jp_init(false);
|
||
|
+ if (status != JP_OK) {
|
||
|
+ xlog(D_GENERAL, "%s: failed to resolve %s: %s",
|
||
|
+ __func__, junction, ops->jp_error(status));
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ status = ops->jp_get_locations(junction, &locations);
|
||
|
+ if (status != JP_OK) {
|
||
|
+ xlog(D_GENERAL, "%s: failed to resolve %s: %s",
|
||
|
+ __func__, junction, ops->jp_error(status));
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ exp = locations_to_export(ops, locations, junction);
|
||
|
+
|
||
|
+ ops->jp_put_locations(locations);
|
||
|
+ ops->jp_done();
|
||
|
+ return exp;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * Load the junction plug-in, then try to resolve "pathname".
|
||
|
+ * Returns pointer to an initialized exportent if "junction"
|
||
|
+ * refers to a junction, or NULL if not.
|
||
|
+ *
|
||
|
+ * Returned exportent points to static memory.
|
||
|
+ */
|
||
|
+static struct exportent *lookup_junction(const char *pathname)
|
||
|
+{
|
||
|
+ struct exportent *exp;
|
||
|
+ void *handle;
|
||
|
+
|
||
|
+ handle = dlopen("libnfsjunct.so", RTLD_NOW);
|
||
|
+ if (handle == NULL) {
|
||
|
+ xlog(D_GENERAL, "%s: dlopen: %s", __func__, dlerror());
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+ (void)dlerror(); /* Clear any error */
|
||
|
+
|
||
|
+ exp = invoke_junction_ops(handle, pathname);
|
||
|
+
|
||
|
+ /* We could leave it loaded to make junction resolution
|
||
|
+ * faster next time. However, if we want to replace the
|
||
|
+ * library, that would require restarting mountd. */
|
||
|
+ (void)dlclose(handle);
|
||
|
+ return exp;
|
||
|
+}
|
||
|
+#else /* !HAVE_NFS_PLUGIN_H */
|
||
|
+static inline struct exportent *lookup_junction(const char *UNUSED(pathname))
|
||
|
+{
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+#endif /* !HAVE_NFS_PLUGIN_H */
|
||
|
+
|
||
|
static void nfsd_export(FILE *f)
|
||
|
{
|
||
|
/* requests are:
|
||
|
@@ -854,7 +1077,7 @@ static void nfsd_export(FILE *f)
|
||
|
dump_to_cache(f, dom, path, NULL);
|
||
|
}
|
||
|
} else {
|
||
|
- dump_to_cache(f, dom, path, NULL);
|
||
|
+ dump_to_cache(f, dom, path, lookup_junction(path));
|
||
|
}
|
||
|
out:
|
||
|
xlog(D_CALL, "nfsd_export: found %p path %s", found, path ? path : NULL);
|
||
|
diff --git a/utils/mountd/fsloc.c b/utils/mountd/fsloc.c
|
||
|
index e2add2d..704b7a0 100644
|
||
|
--- a/utils/mountd/fsloc.c
|
||
|
+++ b/utils/mountd/fsloc.c
|
||
|
@@ -40,12 +40,12 @@ static void replicas_print(struct servers *sp)
|
||
|
{
|
||
|
int i;
|
||
|
if (!sp) {
|
||
|
- xlog(L_NOTICE, "NULL replicas pointer\n");
|
||
|
+ xlog(L_NOTICE, "NULL replicas pointer");
|
||
|
return;
|
||
|
}
|
||
|
- xlog(L_NOTICE, "replicas listsize=%i\n", sp->h_num);
|
||
|
+ xlog(L_NOTICE, "replicas listsize=%i", sp->h_num);
|
||
|
for (i=0; i<sp->h_num; i++) {
|
||
|
- xlog(L_NOTICE, " %s:%s\n",
|
||
|
+ xlog(L_NOTICE, " %s:%s",
|
||
|
sp->h_mp[i]->h_host, sp->h_mp[i]->h_path);
|
||
|
}
|
||
|
}
|
||
|
@@ -125,13 +125,13 @@ static struct servers *method_list(char *data)
|
||
|
int i, listsize;
|
||
|
struct servers *rv=NULL;
|
||
|
|
||
|
- xlog(L_NOTICE, "method_list(%s)\n", data);
|
||
|
+ xlog(L_NOTICE, "method_list(%s)", data);
|
||
|
for (ptr--, listsize=1; ptr; ptr=index(ptr, ':'), listsize++)
|
||
|
ptr++;
|
||
|
list = malloc(listsize * sizeof(char *));
|
||
|
copy = strdup(data);
|
||
|
if (copy)
|
||
|
- xlog(L_NOTICE, "converted to %s\n", copy);
|
||
|
+ xlog(L_NOTICE, "converted to %s", copy);
|
||
|
if (list && copy) {
|
||
|
ptr = copy;
|
||
|
for (i=0; i<listsize; i++) {
|
||
|
diff --git a/utils/mountd/v4root.c b/utils/mountd/v4root.c
|
||
|
index c33a5a9..81f813b 100644
|
||
|
--- a/utils/mountd/v4root.c
|
||
|
+++ b/utils/mountd/v4root.c
|
||
|
@@ -83,7 +83,7 @@ v4root_create(char *path, nfs_export *export)
|
||
|
struct exportent *curexp = &export->m_export;
|
||
|
|
||
|
dupexportent(&eep, &pseudo_root.m_export);
|
||
|
- eep.e_hostname = strdup(curexp->e_hostname);
|
||
|
+ eep.e_hostname = curexp->e_hostname;
|
||
|
strncpy(eep.e_path, path, sizeof(eep.e_path));
|
||
|
if (strcmp(path, "/") != 0)
|
||
|
eep.e_flags &= ~NFSEXP_FSID;
|
||
|
diff --git a/utils/nfsd/nfsd.man b/utils/nfsd/nfsd.man
|
||
|
index d8988d2..1cf9296 100644
|
||
|
--- a/utils/nfsd/nfsd.man
|
||
|
+++ b/utils/nfsd/nfsd.man
|
||
|
@@ -38,7 +38,7 @@ request on all known network addresses. This may change in future
|
||
|
releases of the Linux Kernel.
|
||
|
.TP
|
||
|
.B \-p " or " \-\-port port
|
||
|
-specify a diferent port to listen on for NFS requests. By default,
|
||
|
+specify a different port to listen on for NFS requests. By default,
|
||
|
.B rpc.nfsd
|
||
|
will listen on port 2049.
|
||
|
.TP
|
||
|
diff --git a/utils/nfsidmap/Makefile.am b/utils/nfsidmap/Makefile.am
|
||
|
index f837b91..c0675c4 100644
|
||
|
--- a/utils/nfsidmap/Makefile.am
|
||
|
+++ b/utils/nfsidmap/Makefile.am
|
||
|
@@ -4,6 +4,6 @@ man8_MANS = nfsidmap.man
|
||
|
|
||
|
sbin_PROGRAMS = nfsidmap
|
||
|
nfsidmap_SOURCES = nfsidmap.c
|
||
|
-nfsidmap_LDADD = -lnfsidmap -lkeyutils
|
||
|
+nfsidmap_LDADD = $(LIBNFSIDMAP) -lkeyutils ../../support/nfs/libnfs.a
|
||
|
|
||
|
MAINTAINERCLEANFILES = Makefile.in
|
||
|
diff --git a/utils/nfsidmap/nfsidmap.c b/utils/nfsidmap/nfsidmap.c
|
||
|
index 2d87381..ce8cf3e 100644
|
||
|
--- a/utils/nfsidmap/nfsidmap.c
|
||
|
+++ b/utils/nfsidmap/nfsidmap.c
|
||
|
@@ -9,15 +9,25 @@
|
||
|
#include <keyutils.h>
|
||
|
#include <nfsidmap.h>
|
||
|
|
||
|
-#include <syslog.h>
|
||
|
+#include <unistd.h>
|
||
|
+#include "xlog.h"
|
||
|
|
||
|
-/* gcc nfsidmap.c -o nfsidmap -l nfsidmap -l keyutils */
|
||
|
+int verbose = 0;
|
||
|
+char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]";
|
||
|
|
||
|
#define MAX_ID_LEN 11
|
||
|
#define IDMAP_NAMESZ 128
|
||
|
#define USER 1
|
||
|
#define GROUP 0
|
||
|
|
||
|
+#define PROCKEYS "/proc/keys"
|
||
|
+#ifndef DEFAULT_KEYRING
|
||
|
+#define DEFAULT_KEYRING "id_resolver"
|
||
|
+#endif
|
||
|
+
|
||
|
+
|
||
|
+#define UIDKEYS 0x1
|
||
|
+#define GIDKEYS 0x2
|
||
|
|
||
|
/*
|
||
|
* Find either a user or group id based on the name@domain string
|
||
|
@@ -36,9 +46,15 @@ int id_lookup(char *name_at_domain, key_serial_t key, int type)
|
||
|
rc = nfs4_group_owner_to_gid(name_at_domain, &gid);
|
||
|
sprintf(id, "%u", gid);
|
||
|
}
|
||
|
+ if (rc < 0)
|
||
|
+ xlog_err("id_lookup: %s: failed: %m",
|
||
|
+ (type == USER ? "nfs4_owner_to_uid" : "nfs4_group_owner_to_gid"));
|
||
|
|
||
|
- if (rc == 0)
|
||
|
+ if (rc == 0) {
|
||
|
rc = keyctl_instantiate(key, id, strlen(id) + 1, 0);
|
||
|
+ if (rc < 0)
|
||
|
+ xlog_err("id_lookup: keyctl_instantiate failed: %m");
|
||
|
+ }
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
@@ -57,6 +73,7 @@ int name_lookup(char *id, key_serial_t key, int type)
|
||
|
rc = nfs4_get_default_domain(NULL, domain, NFS4_MAX_DOMAIN_LEN);
|
||
|
if (rc != 0) {
|
||
|
rc = -1;
|
||
|
+ xlog_err("name_lookup: nfs4_get_default_domain failed: %m");
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
@@ -67,39 +84,206 @@ int name_lookup(char *id, key_serial_t key, int type)
|
||
|
gid = atoi(id);
|
||
|
rc = nfs4_gid_to_name(gid, domain, name, IDMAP_NAMESZ);
|
||
|
}
|
||
|
+ if (rc < 0)
|
||
|
+ xlog_err("name_lookup: %s: failed: %m",
|
||
|
+ (type == USER ? "nfs4_uid_to_name" : "nfs4_gid_to_name"));
|
||
|
|
||
|
- if (rc == 0)
|
||
|
+ if (rc == 0) {
|
||
|
rc = keyctl_instantiate(key, &name, strlen(name), 0);
|
||
|
-
|
||
|
+ if (rc < 0)
|
||
|
+ xlog_err("name_lookup: keyctl_instantiate failed: %m");
|
||
|
+ }
|
||
|
out:
|
||
|
return rc;
|
||
|
}
|
||
|
+/*
|
||
|
+ * Clear all the keys on the given keyring
|
||
|
+ */
|
||
|
+static int keyring_clear(char *keyring)
|
||
|
+{
|
||
|
+ FILE *fp;
|
||
|
+ char buf[BUFSIZ];
|
||
|
+ key_serial_t key;
|
||
|
+
|
||
|
+ xlog_syslog(0);
|
||
|
+ if (keyring == NULL)
|
||
|
+ keyring = DEFAULT_KEYRING;
|
||
|
+
|
||
|
+ if ((fp = fopen(PROCKEYS, "r")) == NULL) {
|
||
|
+ xlog_err("fopen(%s) failed: %m", PROCKEYS);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ while(fgets(buf, BUFSIZ, fp) != NULL) {
|
||
|
+ if (strstr(buf, "keyring") == NULL)
|
||
|
+ continue;
|
||
|
+ if (strstr(buf, keyring) == NULL)
|
||
|
+ continue;
|
||
|
+ if (verbose) {
|
||
|
+ *(strchr(buf, '\n')) = '\0';
|
||
|
+ xlog_warn("clearing '%s'", buf);
|
||
|
+ }
|
||
|
+ /*
|
||
|
+ * The key is the first arugment in the string
|
||
|
+ */
|
||
|
+ *(strchr(buf, ' ')) = '\0';
|
||
|
+ sscanf(buf, "%x", &key);
|
||
|
+ if (keyctl_clear(key) < 0) {
|
||
|
+ xlog_err("keyctl_clear(0x%x) failed: %m", key);
|
||
|
+ fclose(fp);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+ fclose(fp);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+ xlog_err("'%s' keyring was not found.", keyring);
|
||
|
+ fclose(fp);
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+/*
|
||
|
+ * Revoke a key
|
||
|
+ */
|
||
|
+static int key_revoke(char *keystr, int keymask)
|
||
|
+{
|
||
|
+ FILE *fp;
|
||
|
+ char buf[BUFSIZ], *ptr;
|
||
|
+ key_serial_t key;
|
||
|
+ int mask;
|
||
|
+
|
||
|
+ xlog_syslog(0);
|
||
|
+
|
||
|
+ if ((fp = fopen(PROCKEYS, "r")) == NULL) {
|
||
|
+ xlog_err("fopen(%s) failed: %m", PROCKEYS);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ while(fgets(buf, BUFSIZ, fp) != NULL) {
|
||
|
+ if (strstr(buf, "keyring") != NULL)
|
||
|
+ continue;
|
||
|
+
|
||
|
+ mask = 0;
|
||
|
+ if ((ptr = strstr(buf, "uid:")) != NULL)
|
||
|
+ mask = UIDKEYS;
|
||
|
+ else if ((ptr = strstr(buf, "gid:")) != NULL)
|
||
|
+ mask = GIDKEYS;
|
||
|
+ else
|
||
|
+ continue;
|
||
|
+
|
||
|
+ if ((keymask & mask) == 0)
|
||
|
+ continue;
|
||
|
+
|
||
|
+ if (strncmp(ptr+4, keystr, strlen(keystr)) != NULL)
|
||
|
+ continue;
|
||
|
+
|
||
|
+ if (verbose) {
|
||
|
+ *(strchr(buf, '\n')) = '\0';
|
||
|
+ xlog_warn("revoking '%s'", buf);
|
||
|
+ }
|
||
|
+ /*
|
||
|
+ * The key is the first arugment in the string
|
||
|
+ */
|
||
|
+ *(strchr(buf, ' ')) = '\0';
|
||
|
+ sscanf(buf, "%x", &key);
|
||
|
+
|
||
|
+ if (keyctl_revoke(key) < 0) {
|
||
|
+ xlog_err("keyctl_revoke(0x%x) failed: %m", key);
|
||
|
+ fclose(fp);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ keymask &= ~mask;
|
||
|
+ if (keymask == 0) {
|
||
|
+ fclose(fp);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ xlog_err("'%s' key was not found.", keystr);
|
||
|
+ fclose(fp);
|
||
|
+ return 1;
|
||
|
+}
|
||
|
|
||
|
int main(int argc, char **argv)
|
||
|
{
|
||
|
char *arg;
|
||
|
char *value;
|
||
|
char *type;
|
||
|
- int rc = 1;
|
||
|
+ int rc = 1, opt;
|
||
|
int timeout = 600;
|
||
|
key_serial_t key;
|
||
|
+ char *progname, *keystr = NULL;
|
||
|
+ int clearing = 0, keymask = 0;
|
||
|
+
|
||
|
+ /* Set the basename */
|
||
|
+ if ((progname = strrchr(argv[0], '/')) != NULL)
|
||
|
+ progname++;
|
||
|
+ else
|
||
|
+ progname = argv[0];
|
||
|
|
||
|
- if (argc < 3)
|
||
|
+ xlog_open(progname);
|
||
|
+
|
||
|
+ while ((opt = getopt(argc, argv, "u:g:r:ct:v")) != -1) {
|
||
|
+ switch (opt) {
|
||
|
+ case 'u':
|
||
|
+ keymask = UIDKEYS;
|
||
|
+ keystr = strdup(optarg);
|
||
|
+ break;
|
||
|
+ case 'g':
|
||
|
+ keymask = GIDKEYS;
|
||
|
+ keystr = strdup(optarg);
|
||
|
+ break;
|
||
|
+ case 'r':
|
||
|
+ keymask = GIDKEYS|UIDKEYS;
|
||
|
+ keystr = strdup(optarg);
|
||
|
+ break;
|
||
|
+ case 'c':
|
||
|
+ clearing++;
|
||
|
+ break;
|
||
|
+ case 'v':
|
||
|
+ verbose++;
|
||
|
+ break;
|
||
|
+ case 't':
|
||
|
+ timeout = atoi(optarg);
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ xlog_warn(usage, progname);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (keystr) {
|
||
|
+ rc = key_revoke(keystr, keymask);
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+ if (clearing) {
|
||
|
+ rc = keyring_clear(DEFAULT_KEYRING);
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ xlog_stderr(0);
|
||
|
+ if ((argc - optind) != 2) {
|
||
|
+ xlog_err("Bad arg count. Check /etc/request-key.conf");
|
||
|
+ xlog_warn(usage, progname);
|
||
|
return 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (verbose)
|
||
|
+ nfs4_set_debug(verbose, NULL);
|
||
|
+
|
||
|
+ key = strtol(argv[optind++], NULL, 10);
|
||
|
|
||
|
- arg = malloc(sizeof(char) * strlen(argv[2]) + 1);
|
||
|
- strcpy(arg, argv[2]);
|
||
|
+ arg = strdup(argv[optind]);
|
||
|
+ if (arg == NULL) {
|
||
|
+ xlog_err("strdup failed: %m");
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
type = strtok(arg, ":");
|
||
|
value = strtok(NULL, ":");
|
||
|
|
||
|
- if (argc == 4) {
|
||
|
- timeout = atoi(argv[3]);
|
||
|
- if (timeout < 0)
|
||
|
- timeout = 0;
|
||
|
+ if (verbose) {
|
||
|
+ xlog_warn("key: %ld type: %s value: %s timeout %ld",
|
||
|
+ key, type, value, timeout);
|
||
|
}
|
||
|
|
||
|
- key = strtol(argv[1], NULL, 10);
|
||
|
-
|
||
|
if (strcmp(type, "uid") == 0)
|
||
|
rc = id_lookup(value, key, USER);
|
||
|
else if (strcmp(type, "gid") == 0)
|
||
|
@@ -109,7 +293,7 @@ int main(int argc, char **argv)
|
||
|
else if (strcmp(type, "group") == 0)
|
||
|
rc = name_lookup(value, key, GROUP);
|
||
|
|
||
|
- /* Set timeout to 5 (600 seconds) minutes */
|
||
|
+ /* Set timeout to 10 (600 seconds) minutes */
|
||
|
if (rc == 0)
|
||
|
keyctl_set_timeout(key, timeout);
|
||
|
|
||
|
diff --git a/utils/nfsidmap/nfsidmap.man b/utils/nfsidmap/nfsidmap.man
|
||
|
index 2381908..3a3a523 100644
|
||
|
--- a/utils/nfsidmap/nfsidmap.man
|
||
|
+++ b/utils/nfsidmap/nfsidmap.man
|
||
|
@@ -5,6 +5,12 @@
|
||
|
.TH nfsidmap 5 "1 October 2010"
|
||
|
.SH NAME
|
||
|
nfsidmap \- The NFS idmapper upcall program
|
||
|
+.SH SYNOPSIS
|
||
|
+.B "nfsidmap [-v] [-t timeout] key desc"
|
||
|
+.br
|
||
|
+.B "nfsidmap [-v] [-c]"
|
||
|
+.br
|
||
|
+.B "nfsidmap [-v] [-u|-g|-r user]"
|
||
|
.SH DESCRIPTION
|
||
|
The file
|
||
|
.I /usr/sbin/nfsidmap
|
||
|
@@ -12,11 +18,36 @@ is used by the NFS idmapper to translate user and group ids into names, and to
|
||
|
translate user and group names into ids. Idmapper uses request-key to perform
|
||
|
the upcall and cache the result.
|
||
|
.I /usr/sbin/nfsidmap
|
||
|
-should only be called by request-key, and will perform the translation and
|
||
|
+is called by /sbin/request-key, and will perform the translation and
|
||
|
initialize a key with the resulting information.
|
||
|
.PP
|
||
|
-NFS_USE_NEW_IDMAPPER must be selected when configuring the kernel to use this
|
||
|
-feature.
|
||
|
+.I nfsidmap
|
||
|
+can also used to clear the keyring of all the keys or
|
||
|
+revoke one particular key.
|
||
|
+This is useful when the id mappings have failed to due
|
||
|
+to a lookup error resulting in all the cached uids/gids to be set
|
||
|
+to the user id nobody.
|
||
|
+.SH OPTIONS
|
||
|
+.TP
|
||
|
+.B -c
|
||
|
+Clear the keyring of all the keys.
|
||
|
+.TP
|
||
|
+.B -g user
|
||
|
+Revoke the gid key of the given user.
|
||
|
+.TP
|
||
|
+.B -r user
|
||
|
+Revoke both the uid and gid key of the given user.
|
||
|
+.TP
|
||
|
+.B -t timeout
|
||
|
+Set the expiration timer, in seconds, on the key.
|
||
|
+The default is 600 seconds (10 mins).
|
||
|
+.TP
|
||
|
+.B -u user
|
||
|
+Revoke the uid key of the given user.
|
||
|
+.TP
|
||
|
+.B -v
|
||
|
+Increases the verbosity of the output to syslog
|
||
|
+(can be specified multiple times).
|
||
|
.SH CONFIGURING
|
||
|
The file
|
||
|
.I /etc/request-key.conf
|
||
|
@@ -25,11 +56,13 @@ will need to be modified so
|
||
|
can properly direct the upcall. The following line should be added before a call
|
||
|
to keyctl negate:
|
||
|
.PP
|
||
|
-create id_resolver * * /usr/sbin/nfsidmap %k %d 600
|
||
|
+create id_resolver * * /usr/sbin/nfsidmap -t 600 %k %d
|
||
|
.PP
|
||
|
This will direct all id_resolver requests to the program
|
||
|
-.I /usr/sbin/nfsidmap
|
||
|
-The last parameter, 600, defines how many seconds into the future the key will
|
||
|
+.I /usr/sbin/nfsidmap.
|
||
|
+The
|
||
|
+.B -t 600
|
||
|
+defines how many seconds into the future the key will
|
||
|
expire. This is an optional parameter for
|
||
|
.I /usr/sbin/nfsidmap
|
||
|
and will default to 600 seconds when not specified.
|
||
|
@@ -48,9 +81,9 @@ You can choose to handle any of these individually, rather than using the
|
||
|
generic upcall program. If you would like to use your own program for a uid
|
||
|
lookup then you would edit your request-key.conf so it looks similar to this:
|
||
|
.PP
|
||
|
-create id_resolver uid:* * /some/other/program %k %d 600
|
||
|
+create id_resolver uid:* * /some/other/program %k %d
|
||
|
.br
|
||
|
-create id_resolver * * /usr/sbin/nfsidmap %k %d 600
|
||
|
+create id_resolver * * /usr/sbin/nfsidmap %k %d
|
||
|
.PP
|
||
|
Notice that the new line was added above the line for the generic program.
|
||
|
request-key will find the first matching line and run the corresponding program.
|