Whamcloud - gitweb
LU-16751 gss: remove old patches for nfs-utils 1.0.* 03/51003/3
authorTimothy Day <timday@amazon.com>
Mon, 15 May 2023 20:34:01 +0000 (20:34 +0000)
committerOleg Drokin <green@whamcloud.com>
Wed, 31 May 2023 19:15:27 +0000 (19:15 +0000)
Remove patches for an old version of nfs-utils. Remove the README
that suggests using them. lustre/utils/gss has an entire fork of
nfs-utils utils/gssd directory already.

Also, sk_utils.c shouldn't be executable.

Test-Parameters: trivial
Signed-off-by: Timothy Day <timday@amazon.com>
Change-Id: Ia47193073d2403125043d51db889d0ded41ea9b7
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/51003
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Sebastien Buisson <sbuisson@ddn.com>
Reviewed-by: Aurelien Degremont <adegremont@nvidia.com>
lustre/utils/gss/README [deleted file]
lustre/utils/gss/nfs-utils-1.0.10-lustre.diff [deleted file]
lustre/utils/gss/nfs-utils-1.0.11-lustre.diff [deleted file]
lustre/utils/gss/sk_utils.c [changed mode: 0755->0644]

diff --git a/lustre/utils/gss/README b/lustre/utils/gss/README
deleted file mode 100644 (file)
index 576c45c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-lustre/utils/gss: client & server side gss daemons for Lustre.
-
-All files came from standard nfs-utils package, applied with patches
-created by Sun Microsystems, Inc.
-
-1. Stock nfs-utils-1.0.11.tgz
-2. Apply nfs-utils-1.0.11-CITI_NFS4_ALL-1.dif from Center for Information
-   Technology Integration, University of Michigan
-   (http://www.citi.umich.edu/projects/nfsv4/linux/)
-3. Apply lustre patch: nfs-utils-1.0.11-lustre.diff
-4. Copy nfs-utils-1.0.10/aclocal/kerberos5.m4 to lustre/autoconf
-5. Copy nfs-utils-1.0.10/utils/gssd/*.[ch] to here
diff --git a/lustre/utils/gss/nfs-utils-1.0.10-lustre.diff b/lustre/utils/gss/nfs-utils-1.0.10-lustre.diff
deleted file mode 100644 (file)
index 366d2d2..0000000
+++ /dev/null
@@ -1,4771 +0,0 @@
-diff -rNup nfs-utils-1.0.10/configure.in nfs-utils-1.0.10.lustre/configure.in
---- nfs-utils-1.0.10/configure.in      2007-05-15 13:02:26.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/configure.in       2007-05-15 13:00:53.000000000 -0600
-@@ -17,61 +17,14 @@ AC_ARG_WITH(release,
-       RELEASE=$withval,
-       RELEASE=1)
-       AC_SUBST(RELEASE)
--AC_ARG_WITH(statedir,
--      [  --with-statedir=/foo    use state dir /foo [/var/lib/nfs]],
--      statedir=$withval,
--      statedir=/var/lib/nfs)
--      AC_SUBST(statedir)
--AC_ARG_WITH(statduser,
--      [AC_HELP_STRING([--with-statduser=rpcuser],
--                        [statd to run under @<:@rpcuser or nobody@:>@]
--      )],
--      statduser=$withval,
--      if test "x$cross_compiling" = "xno"; then
--              if grep -s '^rpcuser:' /etc/passwd > /dev/null; then
--                      statduser=rpcuser
--              else
--                      statduser=nobody
--              fi
--      else
--              statduser=nobody
--      fi)
--      AC_SUBST(statduser)
--AC_ARG_ENABLE(nfsv3,
--      [AC_HELP_STRING([--enable-nfsv3],
--                        [enable support for NFSv3 @<:@default=yes@:>@])],
--      enable_nfsv3=$enableval,
--      enable_nfsv3=yes)
--      if test "$enable_nfsv3" = yes; then
--              AC_DEFINE(NFS3_SUPPORTED, 1, [Define this if you want NFSv3 support compiled in])
--      else
--              enable_nfsv3=
--      fi
--      AC_SUBST(enable_nfsv3)
--AC_ARG_ENABLE(nfsv4,
--      [AC_HELP_STRING([--enable-nfsv4],
--                        [enable support for NFSv4 @<:@default=yes@:>@])],
--      enable_nfsv4=$enableval,
--      enable_nfsv4=yes)
--      if test "$enable_nfsv4" = yes; then
--              AC_DEFINE(NFS4_SUPPORTED, 1, [Define this if you want NFSv4 support compiled in])
--              IDMAPD=idmapd
--      else
--              enable_nfsv4=
--              IDMAPD=
--      fi
--      AC_SUBST(IDMAPD)
--      AC_SUBST(enable_nfsv4)
--      AM_CONDITIONAL(CONFIG_NFSV4, [test "$enable_nfsv4" = "yes"])
- AC_ARG_ENABLE(gss,
-       [AC_HELP_STRING([--enable-gss],
-                         [enable support for rpcsec_gss @<:@default=yes@:>@])],
-       enable_gss=$enableval,
-       enable_gss=yes)
-       if test "$enable_gss" = yes; then
--              AC_DEFINE(GSS_SUPPORTED, 1, [Define this if you want rpcsec_gss support compiled in])
--              GSSD=gssd
--              SVCGSSD=svcgssd
-+              GSSD=lgssd
-+              SVCGSSD=lsvcgssd
-       else
-               enable_gss=
-               GSSD=
-@@ -81,38 +34,6 @@ AC_ARG_ENABLE(gss,
-       AC_SUBST(SVCGSSD)
-       AC_SUBST(enable_gss)
-       AM_CONDITIONAL(CONFIG_GSS, [test "$enable_gss" = "yes"])
--AC_ARG_ENABLE(kprefix,
--      [AC_HELP_STRING([--enable-kprefix], [install progs as rpc.knfsd etc])],
--      test "$enableval" = "yes" && kprefix=k,
--      kprefix=)
--      AC_SUBST(kprefix)
--AC_ARG_ENABLE(secure-statd,
--      [AC_HELP_STRING([--enable-secure-statd],
--                        [Only lockd can use statd (security)])],
--      test "$enableval" = "yes" && secure_statd=yes,
--      secure_statd=no)
--      if test "$secure_statd" = yes; then
--              AC_DEFINE(RESTRICTED_STATD, 1, [Define this if you want to enable various security checks in statd. These checks basically keep anyone but lockd from using this service.])
--      fi
--      AC_SUBST(secure_statd)
--AC_ARG_ENABLE(rquotad,
--      [AC_HELP_STRING([--enable-rquotad],
--                        [enable rquotad @<:@default=yes@:>@])],
--      enable_rquotad=$enableval,
--      enable_rquotad=yes)
--      if test "$enable_rquotad" = yes; then
--              RQUOTAD=rquotad
--      else
--              RQUOTAD=
--      fi
--      AM_CONDITIONAL(CONFIG_RQUOTAD, [test "$enable_rquotad" = "yes"])
--
--AC_ARG_ENABLE(mount,
--      [AC_HELP_STRING([--enable-mount],
--                      [Create mount.nfs and don't use the util-linux mount(8) functionality. @<:@default=no@:>@])],
--      enable_mount=$enableval,
--      enable_mount=no)
--      AM_CONDITIONAL(CONFIG_MOUNT, [test "$enable_mount" = "yes"])
- # Check whether user wants TCP wrappers support
- AC_TCP_WRAPPERS
-@@ -155,47 +76,17 @@ AC_CHECK_FUNC(connect, , 
-                 AC_MSG_ERROR(Function 'socket' not found.), $LIBNSL))
- AC_CHECK_LIB(crypt, crypt, [LIBCRYPT="-lcrypt"])
--if test "$enable_nfsv4" = yes; then
--    AC_CHECK_LIB(event, event_dispatch, [libevent=1], AC_MSG_ERROR([libevent needed for nfsv4 support]))
--    AC_CHECK_LIB(nfsidmap, nfs4_init_name_mapping, [libnfsidmap=1], AC_MSG_ERROR([libnfsidmap needed for nfsv4 support]))
--    AC_CHECK_HEADERS(event.h, ,AC_MSG_ERROR([libevent needed for nfsv4 support]))
--    AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for nfsv4 support]))
--    dnl librpcsecgss already has a dependency on libgssapi,
--    dnl but we need to make sure we get the right version
-     if test "$enable_gss" = yes; then
--     PKG_CHECK_MODULES(RPCSECGSS, librpcsecgss >= 0.10, ,
--      [AC_MSG_ERROR([Unable to locate information required to use librpcsecgss.  If you have pkgconfig installed, you might try setting environment variable PKG_CONFIG_PATH to /usr/local/lib/pkgconfig])
--      ]
--     )
-     PKG_CHECK_MODULES(GSSAPI, libgssapi >= 0.9)
-     fi
--fi
--if test "$knfsd_cv_glibc2" = no; then
--    AC_CHECK_LIB(bsd, daemon, [LIBBSD="-lbsd"])
--fi
- AC_SUBST(LIBSOCKET)
- AC_SUBST(LIBCRYPT)
- AC_SUBST(LIBBSD)
- if test "$enable_gss" = yes; then
--  dnl 'gss' also depends on nfsidmap.h - at least for svcgssd_proc.c
--  AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for gss support]))
--  AC_CHECK_HEADERS(spkm3.h, ,AC_MSG_WARN([could not locate SPKM3 header; will not have SPKM3 support]))
--  dnl the nfs4_set_debug function doesn't appear in all version of the library
--  AC_CHECK_LIB(nfsidmap, nfs4_set_debug,
--             AC_DEFINE(HAVE_NFS4_SET_DEBUG,1,
--                       [Whether nfs4_set_debug() is present in libnfsidmap]),)
--
-   dnl Check for Kerberos V5
-   AC_KERBEROS_V5
--
--  dnl This is not done until here because we need to have KRBLIBS set
--  dnl ("librpcsecgss=1" is so that it doesn't get added to LIBS)
--  AC_CHECK_LIB(rpcsecgss, authgss_create_default, [librpcsecgss=1], AC_MSG_ERROR([librpcsecgss needed for nfsv4 support]), -lgssapi -ldl)
--  AC_CHECK_LIB(rpcsecgss, authgss_set_debug_level,
--             AC_DEFINE(HAVE_AUTHGSS_SET_DEBUG_LEVEL, 1, [Define this if the rpcsec_gss library has the function authgss_set_debug_level]),, -lgssapi -ldl)
--
- fi
- dnl *************************************************************
-@@ -307,35 +198,7 @@ AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_mac
- AC_CONFIG_FILES([
-       Makefile
--      linux-nfs/Makefile
--      support/Makefile
--      support/export/Makefile
--      support/include/nfs/Makefile
--      support/include/rpcsvc/Makefile
--      support/include/sys/fs/Makefile
--      support/include/sys/Makefile
--      support/include/Makefile
--      support/misc/Makefile
--      support/nfs/Makefile
--      tools/Makefile
--      tools/getiversion/Makefile
--      tools/getkversion/Makefile
--      tools/locktest/Makefile
--      tools/nlmtest/Makefile
--      tools/rpcdebug/Makefile
--      tools/rpcgen/Makefile
-       utils/Makefile
--      utils/exportfs/Makefile
--      utils/gssd/Makefile
--      utils/idmapd/Makefile
--      utils/lockd/Makefile
--      utils/mount/Makefile
--      utils/mountd/Makefile
--      utils/nfsd/Makefile
--      utils/nfsstat/Makefile
--      utils/nhfsstone/Makefile
--      utils/rquotad/Makefile
--      utils/showmount/Makefile
--      utils/statd/Makefile])
-+      utils/gssd/Makefile])
- AC_OUTPUT
-diff -rNup nfs-utils-1.0.10/Makefile.am nfs-utils-1.0.10.lustre/Makefile.am
---- nfs-utils-1.0.10/Makefile.am       2007-05-15 13:02:26.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/Makefile.am        2007-05-15 13:00:53.000000000 -0600
-@@ -1,6 +1,6 @@
- ## Process this file with automake to produce Makefile.in
--SUBDIRS = tools support utils linux-nfs
-+SUBDIRS = utils
- MAINTAINERCLEANFILES = Makefile.in
-diff -rNup nfs-utils-1.0.10/utils/gssd/cacheio.c nfs-utils-1.0.10.lustre/utils/gssd/cacheio.c
---- nfs-utils-1.0.10/utils/gssd/cacheio.c      2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/cacheio.c       2007-05-15 13:01:35.000000000 -0600
-@@ -227,7 +227,8 @@ int qword_get(char **bpp, char *dest, in
-               return -1;
-       while (*bp == ' ') bp++;
-       *bpp = bp;
--      *dest = '\0';
-+// why should we clear *dest???
-+//    *dest = '\0';
-       return len;
- }
-diff -rNup nfs-utils-1.0.10/utils/gssd/context.c nfs-utils-1.0.10.lustre/utils/gssd/context.c
---- nfs-utils-1.0.10/utils/gssd/context.c      2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/context.c       2007-05-15 13:01:35.000000000 -0600
-@@ -33,8 +33,6 @@
- #include <syslog.h>
- #include <string.h>
- #include <gssapi/gssapi.h>
--#include <rpc/rpc.h>
--#include <rpc/auth_gss.h>
- #include "gss_util.h"
- #include "gss_oids.h"
- #include "err_util.h"
-diff -rNup nfs-utils-1.0.10/utils/gssd/context.h nfs-utils-1.0.10.lustre/utils/gssd/context.h
---- nfs-utils-1.0.10/utils/gssd/context.h      2007-05-15 13:02:26.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/context.h       2007-05-15 13:01:35.000000000 -0600
-@@ -31,8 +31,6 @@
- #ifndef _CONTEXT_H_
- #define _CONTEXT_H_
--#include <rpc/rpc.h>
--
- /* Hopefully big enough to hold any serialized context */
- #define MAX_CTX_LEN 4096
-diff -rNup nfs-utils-1.0.10/utils/gssd/context_lucid.c nfs-utils-1.0.10.lustre/utils/gssd/context_lucid.c
---- nfs-utils-1.0.10/utils/gssd/context_lucid.c        2007-05-15 13:02:26.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/context_lucid.c 2007-05-15 13:01:35.000000000 -0600
-@@ -41,11 +41,7 @@
- #include <syslog.h>
- #include <string.h>
- #include <errno.h>
--#include "gss_util.h"
--#include "gss_oids.h"
--#include "err_util.h"
--#include "context.h"
--
-+#include <stdint.h>
- #include <krb5.h>
- #include <gssapi/gssapi.h>
- #ifndef OM_uint64
-@@ -53,6 +49,11 @@ typedef uint64_t OM_uint64;
- #endif
- #include <gssapi/gssapi_krb5.h>
-+#include "gss_util.h"
-+#include "gss_oids.h"
-+#include "err_util.h"
-+#include "context.h"
-+
- static int
- write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key)
- {
-@@ -354,6 +355,7 @@ static int
- prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
-                           gss_buffer_desc *buf)
- {
-+      static int constant_two = 2;
-       char *p, *end;
-       uint32_t v2_flags = 0;
-       gss_krb5_lucid_key_t enc_key;
-@@ -372,7 +374,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
-       end = buf->value + MAX_CTX_LEN;
-       /* Version 2 */
--      if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err;
-+      if (WRITE_BYTES(&p, end, constant_two)) goto out_err;
-       if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
-       if (lctx->initiate)
-@@ -434,14 +436,25 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
-                       goto out_err;
-               /* Kc */
--              if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
--                              &derived_key,
--                              KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
--                      goto out_err;
--              if (write_bytes(&p, end, derived_key.data,
--                              derived_key.length))
--                      goto out_err;
--              free(derived_key.data);
-+              /*
-+               * RC4 is special, it dosen't need key derivation. Actually
-+               * the Ke is based on plain text. Here we just let all three
-+               * key identical, kernel will handle everything. --ericm
-+               */
-+              if (lctx->rfc1964_kd.ctx_key.type == ENCTYPE_ARCFOUR_HMAC) {
-+                      if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
-+                                      lctx->rfc1964_kd.ctx_key.length))
-+                              goto out_err;
-+              } else {
-+                      if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
-+                                      &derived_key,
-+                                      KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
-+                              goto out_err;
-+                      if (write_bytes(&p, end, derived_key.data,
-+                                      derived_key.length))
-+                              goto out_err;
-+                      free(derived_key.data);
-+              }
-       } else {
-               gss_krb5_lucid_key_t *keyptr;
-               uint32_t sign_usage, seal_usage;
-@@ -451,6 +464,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
-               else
-                       keyptr = &lctx->cfx_kd.ctx_key;
-+#if 0
-               if (lctx->initiate == 1) {
-                       sign_usage = KG_USAGE_INITIATOR_SIGN;
-                       seal_usage = KG_USAGE_INITIATOR_SEAL;
-@@ -458,6 +472,19 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
-                       sign_usage = KG_USAGE_ACCEPTOR_SIGN;
-                       seal_usage = KG_USAGE_ACCEPTOR_SEAL;
-               }
-+#else
-+              /* FIXME
-+               * These are from rfc4142, but I don't understand: if we supply
-+               * different 'usage' value for client & server, then the peers
-+               * will have different derived keys. How could this work?
-+               *
-+               * Here we simply use old SIGN/SEAL values until we find the
-+               * answer.  --ericm
-+               * FIXME
-+               */
-+              sign_usage = KG_USAGE_SIGN;
-+              seal_usage = KG_USAGE_SEAL;
-+#endif
-               /* derive and send down: Ke, Ki, and Kc */
-diff -rNup nfs-utils-1.0.10/utils/gssd/context_mit.c nfs-utils-1.0.10.lustre/utils/gssd/context_mit.c
---- nfs-utils-1.0.10/utils/gssd/context_mit.c  2007-05-15 13:02:26.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/context_mit.c   2007-05-15 13:01:35.000000000 -0600
-@@ -39,7 +39,6 @@
- #include <errno.h>
- #include <gssapi/gssapi.h>
- #include <rpc/rpc.h>
--#include <rpc/auth_gss.h>
- #include "gss_util.h"
- #include "gss_oids.h"
- #include "err_util.h"
-@@ -333,12 +332,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
-                * keydata-2;                (  Ki  (Kseq for DES3) )
-                * keydata-3;                (  Kc (derived checksum key) )
-                */
--              if (kctx->initiate) {
--                      if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
--              }
--              else {
--                      if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
--              }
-+              if (WRITE_BYTES(&p, end, constant_two)) goto out_err;
-               if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
-               /* Only applicable flag for this is initiator */
-diff -rNup nfs-utils-1.0.10/utils/gssd/context_spkm3.c nfs-utils-1.0.10.lustre/utils/gssd/context_spkm3.c
---- nfs-utils-1.0.10/utils/gssd/context_spkm3.c        2007-05-15 13:02:26.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/context_spkm3.c 2007-05-15 13:01:35.000000000 -0600
-@@ -33,8 +33,6 @@
- #include <syslog.h>
- #include <string.h>
- #include <gssapi/gssapi.h>
--#include <rpc/rpc.h>
--#include <rpc/auth_gss.h>
- #include "gss_util.h"
- #include "gss_oids.h"
- #include "err_util.h"
-diff -rNup nfs-utils-1.0.10/utils/gssd/err_util.c nfs-utils-1.0.10.lustre/utils/gssd/err_util.c
---- nfs-utils-1.0.10/utils/gssd/err_util.c     2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/err_util.c      2007-05-15 13:01:35.000000000 -0600
-@@ -32,6 +32,8 @@
- #include <stdarg.h>
- #include <syslog.h>
- #include <string.h>
-+#include <fcntl.h>
-+#include <ctype.h>
- #include "err_util.h"
- static int verbosity = 0;
-@@ -91,3 +93,40 @@ printit:
-       /* reset the buffer */
-       memset(message_buf, 0, sizeof(message_buf));
- }
-+
-+void print_hexl(int pri, unsigned char *cp, int length)
-+{
-+      int i, j, jm;
-+      unsigned char c;
-+
-+      printerr(pri, "length %d\n",length);
-+      printerr(pri, "\n");
-+
-+      for (i = 0; i < length; i += 0x10) {
-+              printerr(pri, "  %04x: ", (u_int)i);
-+              jm = length - i;
-+              jm = jm > 16 ? 16 : jm;
-+
-+              for (j = 0; j < jm; j++) {
-+                      if ((j % 2) == 1)
-+                              printerr(pri,"%02x ", (u_int)cp[i+j]);
-+                      else
-+                              printerr(pri,"%02x", (u_int)cp[i+j]);
-+              }
-+              for (; j < 16; j++) {
-+                      if ((j % 2) == 1)
-+                              printerr(pri,"   ");
-+                      else
-+                              printerr(pri,"  ");
-+              }
-+              printerr(pri," ");
-+
-+              for (j = 0; j < jm; j++) {
-+                      c = cp[i+j];
-+                      c = isprint(c) ? c : '.';
-+                      printerr(pri,"%c", c);
-+              }
-+              printerr(pri,"\n");
-+      }
-+}
-+
-diff -rNup nfs-utils-1.0.10/utils/gssd/err_util.h nfs-utils-1.0.10.lustre/utils/gssd/err_util.h
---- nfs-utils-1.0.10/utils/gssd/err_util.h     2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/err_util.h      2007-05-15 13:01:35.000000000 -0600
-@@ -33,5 +33,6 @@
- void initerr(char *progname, int verbosity, int fg);
- void printerr(int priority, char *format, ...);
-+void print_hexl(int pri, unsigned char *cp, int length);
- #endif /* _ERR_UTIL_H_ */
-diff -rNup nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c nfs-utils-1.0.10.lustre/utils/gssd/gss_clnt_send_err.c
---- nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c    2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/gss_clnt_send_err.c     2007-05-15 13:00:53.000000000 -0600
-@@ -47,6 +47,7 @@
- #include "gssd.h"
- #include "write_bytes.h"
-+#if 0
- char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
- static void
-@@ -102,3 +103,4 @@ main(int argc, char *argv[])
-       }
-       exit(0);
- }
-+#endif
-diff -rNup nfs-utils-1.0.10/utils/gssd/gssd.c nfs-utils-1.0.10.lustre/utils/gssd/gssd.c
---- nfs-utils-1.0.10/utils/gssd/gssd.c 2007-05-15 13:02:26.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/gssd.c  2007-05-15 13:01:35.000000000 -0600
-@@ -38,9 +38,12 @@
- #include "config.h"
-+#include <sys/types.h>
- #include <sys/param.h>
- #include <sys/socket.h>
--#include <rpc/rpc.h>
-+#include <sys/wait.h>
-+#include <sys/ipc.h>
-+#include <sys/sem.h>
- #include <unistd.h>
- #include <err.h>
-@@ -48,23 +51,107 @@
- #include <stdlib.h>
- #include <string.h>
- #include <signal.h>
-+#include <errno.h>
- #include "gssd.h"
- #include "err_util.h"
- #include "gss_util.h"
- #include "krb5_util.h"
-+#include "lsupport.h"
- char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR;
- char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
- char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
- char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR;
- int  use_memcache = 0;
-+int  lgssd_mutex_downcall = -1;
--void
--sig_die(int signal)
-+static int lgssd_create_mutex(int *semid)
-+{
-+      int             id;
-+      int             arg;
-+
-+      id = semget(IPC_PRIVATE, 1, IPC_CREAT);
-+      if (id == -1) {
-+              printerr(0, "semget: %s\n", strerror(errno));
-+              return -1;
-+      }
-+
-+      arg = 1;
-+      if (semctl(id, 0, SETVAL, arg) != 0) {
-+              printerr(0, "semctl: %s\n", strerror(errno));
-+              semctl(id, 1, IPC_RMID, arg);
-+              return -1;
-+      }
-+
-+      *semid = id;
-+      return 0;
-+}
-+
-+void lgssd_init_mutexs(void)
-+{
-+      if (lgssd_create_mutex(&lgssd_mutex_downcall)) {
-+              printerr(0, "can't create downcall mutex\n");
-+              exit(1);
-+      }
-+}
-+
-+void lgssd_fini_mutexs(void)
-+{
-+      int     arg = 0;
-+
-+      if (lgssd_mutex_downcall != -1)
-+              semctl(lgssd_mutex_downcall, 1, IPC_RMID, arg);
-+}
-+
-+void lgssd_mutex_get(int semid)
-+{
-+      struct sembuf   op[1] = { {0, -1, SEM_UNDO} };
-+      int             rc;
-+
-+      rc = semop(semid, op, 1);
-+      if (rc != 0) {
-+              printerr(0, "exit on mutex_get err %d: %s\n",
-+                       rc, strerror(errno));
-+              exit(1);
-+      }
-+}
-+
-+void lgssd_mutex_put(int semid)
- {
-+      struct sembuf   op[1] = { {0, 1, 0} };
-+      int             rc;
-+
-+      rc = semop(semid, op, 1);
-+      if (rc != 0) {
-+              printerr(0, "ignore mutex_put err %d: %s\n",
-+                       rc, strerror(errno));
-+      }
-+}
-+
-+static void lgssd_cleanup(void)
-+{
-+      pid_t   child_pid;
-+
-+      /* make sure all children finished */
-+      while (1) {
-+              child_pid = waitpid(-1, NULL, 0);
-+              if (child_pid < 0)
-+                      break;
-+
-+              printerr(3, "cleanup: child %d terminated\n", child_pid);
-+      }
-+
-+      lgssd_fini_mutexs();
-+
-       /* destroy krb5 machine creds */
-       gssd_destroy_krb5_machine_creds();
-+}
-+
-+void
-+sig_die(int signal)
-+{
-       printerr(1, "exiting on signal %d\n", signal);
-+      lgssd_cleanup();
-       exit(1);
- }
-@@ -79,7 +166,7 @@ sig_hup(int signal)
- static void
- usage(char *progname)
- {
--      fprintf(stderr, "usage: %s [-f] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir]\n",
-+      fprintf(stderr, "usage: %s [-f] [-v] [-p pipefsdir] [-k keytab] [-d ccachedir]\n",
-               progname);
-       exit(1);
- }
-@@ -89,7 +176,6 @@ main(int argc, char *argv[])
- {
-       int fg = 0;
-       int verbosity = 0;
--      int rpc_verbosity = 0;
-       int opt;
-       extern char *optarg;
-       char *progname;
-@@ -99,18 +185,12 @@ main(int argc, char *argv[])
-                       case 'f':
-                               fg = 1;
-                               break;
--                      case 'm':
--                              /* Accept but ignore this. Now the default. */
--                              break;
-                       case 'M':
-                               use_memcache = 1;
-                               break;
-                       case 'v':
-                               verbosity++;
-                               break;
--                      case 'r':
--                              rpc_verbosity++;
--                              break;
-                       case 'p':
-                               strncpy(pipefs_dir, optarg, sizeof(pipefs_dir));
-                               if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0')
-@@ -131,10 +211,6 @@ main(int argc, char *argv[])
-                               break;
-               }
-       }
--      snprintf(pipefs_nfsdir, sizeof(pipefs_nfsdir), "%s/%s",
--               pipefs_dir, GSSD_SERVICE_NAME);
--      if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0')
--              errx(1, "pipefs_nfsdir path name too long");
-       if ((progname = strrchr(argv[0], '/')))
-               progname++;
-@@ -142,30 +218,42 @@ main(int argc, char *argv[])
-               progname = argv[0];
-       initerr(progname, verbosity, fg);
--#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
--      authgss_set_debug_level(rpc_verbosity);
--#else
--        if (rpc_verbosity > 0)
--              printerr(0, "Warning: rpcsec_gss library does not "
--                          "support setting debug level\n");
--#endif
-       if (gssd_check_mechs() != 0)
-               errx(1, "Problem with gssapi library");
-+      if (gssd_get_local_realm())
-+              errx(1, "get local realm");
-+
-       if (!fg && daemon(0, 0) < 0)
-               errx(1, "fork");
-+      /* This should be checked _after_ daemon(), because we need to own
-+       * the undo-able semaphore by this process
-+       */
-+      gssd_init_unique(GSSD_CLI);
-+
-+      /* Process keytab file and get machine credentials. This will modify
-+       * disk status so do it after we are sure we are the only instance
-+       */
-+      if (gssd_refresh_krb5_machine_creds())
-+              return -1;
-+
-       signal(SIGINT, sig_die);
-       signal(SIGTERM, sig_die);
-       signal(SIGHUP, sig_hup);
--      /* Process keytab file and get machine credentials */
--      gssd_refresh_krb5_machine_creds();
-+#if 0
-       /* Determine Kerberos information from the kernel */
-       gssd_obtain_kernel_krb5_info();
-+#endif
-+
-+      lgssd_init_mutexs();
-+
-+      printerr(0, "lgssd initialized and ready to serve\n");
-+      lgssd_run();
--      gssd_run();
--      printerr(0, "gssd_run returned!\n");
--      abort();
-+      lgssd_cleanup();
-+      printerr(0, "lgssd exiting\n");
-+      return 0;
- }
-diff -rNup nfs-utils-1.0.10/utils/gssd/gssd.h nfs-utils-1.0.10.lustre/utils/gssd/gssd.h
---- nfs-utils-1.0.10/utils/gssd/gssd.h 2007-05-15 13:02:26.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/gssd.h  2007-05-15 13:01:35.000000000 -0600
-@@ -48,8 +48,13 @@
- #define GSSD_DEFAULT_CRED_PREFIX              "krb5cc_"
- #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX      "machine"
- #define GSSD_DEFAULT_KEYTAB_FILE              "/etc/krb5.keytab"
--#define GSSD_SERVICE_NAME                     "nfs"
--#define GSSD_SERVICE_NAME_LEN                 3
-+#define GSSD_SERVICE_MDS                      "lustre_mds"
-+#define GSSD_SERVICE_OSS                      "lustre_oss"
-+#define GSSD_SERVICE_MDS_NAMELEN              10
-+#define GSSD_SERVICE_OSS_NAMELEN              10
-+
-+#define LUSTRE_ROOT_NAME                      "lustre_root"
-+#define LUSTRE_ROOT_NAMELEN                   11
- /*
-  * The gss mechanisms that we can handle
-@@ -59,9 +64,9 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT
- extern char                   pipefs_dir[PATH_MAX];
--extern char                   pipefs_nfsdir[PATH_MAX];
- extern char                   keytabfile[PATH_MAX];
- extern char                   ccachedir[PATH_MAX];
-+extern char                   gethostname_ex[PATH_MAX];
- extern int                    use_memcache;
- TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list;
-@@ -71,10 +76,6 @@ struct clnt_info {
-       char                    *dirname;
-       int                     dir_fd;
-       char                    *servicename;
--      char                    *servername;
--      int                     prog;
--      int                     vers;
--      char                    *protocol;
-       int                     krb5_fd;
-       int                     krb5_poll_index;
-       int                     spkm3_fd;
-@@ -85,8 +86,14 @@ void init_client_list(void);
- int update_client_list(void);
- void handle_krb5_upcall(struct clnt_info *clp);
- void handle_spkm3_upcall(struct clnt_info *clp);
--int gssd_acquire_cred(char *server_name);
--void gssd_run(void);
-+void lgssd_run(void);
-+
-+
-+extern int lgssd_mutex_downcall;
-+void lgssd_init_mutexs(void);
-+void lgssd_fini_mutexs(void);
-+void lgssd_mutex_get(int semid);
-+void lgssd_mutex_put(int semid);
- #endif /* _RPC_GSSD_H_ */
-diff -rNup nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c nfs-utils-1.0.10.lustre/utils/gssd/gssd_main_loop.c
---- nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c       2007-05-15 13:02:26.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/gssd_main_loop.c        2007-05-15 13:01:35.000000000 -0600
-@@ -94,11 +94,13 @@ scan_poll_results(int ret)
- };
- void
--gssd_run()
-+lgssd_run()
- {
-       int                     ret;
-       struct sigaction        dn_act;
-       int                     fd;
-+      time_t                  child_check = 0;
-+      pid_t                   child_pid;
-       /* Taken from linux/Documentation/dnotify.txt: */
-       dn_act.sa_sigaction = dir_notify_handler;
-@@ -106,10 +108,10 @@ gssd_run()
-       dn_act.sa_flags = SA_SIGINFO;
-       sigaction(DNOTIFY_SIGNAL, &dn_act, NULL);
--      if ((fd = open(pipefs_nfsdir, O_RDONLY)) == -1) {
-+      if ((fd = open(pipefs_dir, O_RDONLY)) == -1) {
-               printerr(0, "ERROR: failed to open %s: %s\n",
--                       pipefs_nfsdir, strerror(errno));
--              exit(1);
-+                       pipefs_dir, strerror(errno));
-+              return;
-       }
-       fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL);
-       fcntl(fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
-@@ -119,12 +121,30 @@ gssd_run()
-       while (1) {
-               while (dir_changed) {
-                       dir_changed = 0;
-+                      printerr(2, "pipefs root dir changed\n");
-                       if (update_client_list()) {
-                               printerr(0, "ERROR: couldn't update "
-                                        "client list\n");
--                              exit(1);
-+                              goto out;
-                       }
-               }
-+
-+              /* every 5s cleanup possible zombies of child processes */
-+              if (time(NULL) - child_check >= 5) {
-+                      printerr(3, "check zombie children...\n");
-+
-+                      while (1) {
-+                              child_pid = waitpid(-1, NULL, WNOHANG);
-+                              if (child_pid <= 0)
-+                                      break;
-+
-+                              printerr(2, "terminate zombie child: %d\n",
-+                                       child_pid);
-+                      }
-+
-+                      child_check = time(NULL);
-+              }
-+
-               /* race condition here: dir_changed could be set before we
-                * enter the poll, and we'd never notice if it weren't for the
-                * timeout. */
-@@ -139,6 +159,7 @@ gssd_run()
-                       scan_poll_results(ret);
-               }
-       }
-+out:
-       close(fd);
-       return;
- }
-diff -rNup nfs-utils-1.0.10/utils/gssd/gssd_proc.c nfs-utils-1.0.10.lustre/utils/gssd/gssd_proc.c
---- nfs-utils-1.0.10/utils/gssd/gssd_proc.c    2007-05-15 13:02:26.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/gssd_proc.c     2007-05-15 13:21:06.000000000 -0600
-@@ -43,7 +43,6 @@
- #endif
- #include "config.h"
- #include <sys/param.h>
--#include <rpc/rpc.h>
- #include <sys/stat.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
-@@ -69,6 +68,7 @@
- #include "gss_oids.h"
- #include "krb5_util.h"
- #include "context.h"
-+#include "lsupport.h"
- /*
-  * pollarray:
-@@ -99,86 +99,10 @@ struct pollfd * pollarray;
- int pollsize;  /* the size of pollaray (in pollfd's) */
--/* XXX buffer problems: */
--static int
--read_service_info(char *info_file_name, char **servicename, char **servername,
--                int *prog, int *vers, char **protocol) {
--#define INFOBUFLEN 256
--      char            buf[INFOBUFLEN];
--      static char     dummy[128];
--      int             nbytes;
--      static char     service[128];
--      static char     address[128];
--      char            program[16];
--      char            version[16];
--      char            protoname[16];
--      in_addr_t       inaddr;
--      int             fd = -1;
--      struct hostent  *ent = NULL;
--      int             numfields;
--
--      *servicename = *servername = *protocol = NULL;
--
--      if ((fd = open(info_file_name, O_RDONLY)) == -1) {
--              printerr(0, "ERROR: can't open %s: %s\n", info_file_name,
--                       strerror(errno));
--              goto fail;
--      }
--      if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1)
--              goto fail;
--      close(fd);
--
--      numfields = sscanf(buf,"RPC server: %127s\n"
--                 "service: %127s %15s version %15s\n"
--                 "address: %127s\n"
--                 "protocol: %15s\n",
--                 dummy,
--                 service, program, version,
--                 address,
--                 protoname);
--
--      if (numfields == 5) {
--              strcpy(protoname, "tcp");
--      } else if (numfields != 6) {
--              goto fail;
--      }
--
--      /* check service, program, and version */
--      if(memcmp(service, "nfs", 3)) return -1;
--      *prog = atoi(program + 1); /* skip open paren */
--      *vers = atoi(version);
--      if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4)))
--              goto fail;
--
--      /* create service name */
--      inaddr = inet_addr(address);
--      if (!(ent = gethostbyaddr(&inaddr, sizeof(inaddr), AF_INET))) {
--              printerr(0, "ERROR: can't resolve server %s name\n", address);
--              goto fail;
--      }
--      if (!(*servername = calloc(strlen(ent->h_name) + 1, 1)))
--              goto fail;
--      memcpy(*servername, ent->h_name, strlen(ent->h_name));
--      snprintf(buf, INFOBUFLEN, "%s@%s", service, ent->h_name);
--      if (!(*servicename = calloc(strlen(buf) + 1, 1)))
--              goto fail;
--      memcpy(*servicename, buf, strlen(buf));
--
--      if (!(*protocol = strdup(protoname)))
--              goto fail;
--      return 0;
--fail:
--      printerr(0, "ERROR: failed to read service info\n");
--      if (fd != -1) close(fd);
--      if (*servername) free(*servername);
--      if (*servicename) free(*servicename);
--      if (*protocol) free(*protocol);
--      return -1;
--}
--
- static void
- destroy_client(struct clnt_info *clp)
- {
-+      printerr(3, "clp %p: dirname %s, krb5fd %d\n", clp, clp->dirname, clp->krb5_fd);
-       if (clp->krb5_poll_index != -1)
-               memset(&pollarray[clp->krb5_poll_index], 0,
-                                       sizeof(struct pollfd));
-@@ -190,8 +114,6 @@ destroy_client(struct clnt_info *clp)
-       if (clp->spkm3_fd != -1) close(clp->spkm3_fd);
-       if (clp->dirname) free(clp->dirname);
-       if (clp->servicename) free(clp->servicename);
--      if (clp->servername) free(clp->servername);
--      if (clp->protocol) free(clp->protocol);
-       free(clp);
- }
-@@ -221,7 +143,6 @@ process_clnt_dir_files(struct clnt_info 
- {
-       char    kname[32];
-       char    sname[32];
--      char    info_file_name[32];
-       if (clp->krb5_fd == -1) {
-               snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname);
-@@ -233,13 +154,6 @@ process_clnt_dir_files(struct clnt_info 
-       }
-       if((clp->krb5_fd == -1) && (clp->spkm3_fd == -1))
-               return -1;
--      snprintf(info_file_name, sizeof(info_file_name), "%s/info",
--                      clp->dirname);
--      if ((clp->servicename == NULL) &&
--           read_service_info(info_file_name, &clp->servicename,
--                              &clp->servername, &clp->prog, &clp->vers,
--                              &clp->protocol))
--              return -1;
-       return 0;
- }
-@@ -273,6 +187,8 @@ insert_clnt_poll(struct clnt_info *clp)
-               }
-               pollarray[clp->krb5_poll_index].fd = clp->krb5_fd;
-               pollarray[clp->krb5_poll_index].events |= POLLIN;
-+              printerr(2, "monitoring krb5 channel under %s\n",
-+                       clp->dirname);
-       }
-       if ((clp->spkm3_fd != -1) && (clp->spkm3_poll_index == -1)) {
-@@ -386,67 +302,106 @@ find_client(char *dirname)
- int
- update_client_list(void)
- {
--      struct dirent **namelist;
-+      char lustre_dir[PATH_MAX];
-+      struct dirent lustre_dirent = { .d_name = "lustre" };
-+      struct dirent *namelist[1];
-+      struct stat statbuf;
-       int i, j;
--      if (chdir(pipefs_nfsdir) < 0) {
-+      if (chdir(pipefs_dir) < 0) {
-               printerr(0, "ERROR: can't chdir to %s: %s\n",
--                       pipefs_nfsdir, strerror(errno));
-+                       pipefs_dir, strerror(errno));
-               return -1;
-       }
--      j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort);
--      if (j < 0) {
--              printerr(0, "ERROR: can't scandir %s: %s\n",
--                       pipefs_nfsdir, strerror(errno));
--              return -1;
-+      snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefs_dir, "lustre");
-+      if (stat(lustre_dir, &statbuf) == 0) {
-+              namelist[0] = &lustre_dirent;
-+              j = 1;
-+              printerr(2, "re-processing lustre directory\n");
-+      } else {
-+              namelist[0] = NULL;
-+              j = 0;
-+              printerr(2, "lustre directory not exist\n");
-       }
-+
-       update_old_clients(namelist, j);
-       for (i=0; i < j; i++) {
--              if (i < FD_ALLOC_BLOCK
--                              && !strncmp(namelist[i]->d_name, "clnt", 4)
--                              && !find_client(namelist[i]->d_name))
-+              if (i < FD_ALLOC_BLOCK && !find_client(namelist[i]->d_name))
-                       process_clnt_dir(namelist[i]->d_name);
--              free(namelist[i]);
-       }
--      free(namelist);
-+      chdir("/");
-       return 0;
- }
-+/* Context creation response. */
-+struct lustre_gss_init_res {
-+        gss_buffer_desc gr_ctx;         /* context handle */
-+        u_int           gr_major;       /* major status */
-+        u_int           gr_minor;       /* minor status */
-+        u_int           gr_win;         /* sequence window */
-+        gss_buffer_desc gr_token;       /* token */
-+};
-+
-+struct lustre_gss_data {
-+        int             lgd_established;
-+        int             lgd_lustre_svc; /* mds/oss */
-+        int             lgd_uid;        /* uid */
-+        char           *lgd_uuid;       /* client device uuid */
-+        gss_name_t      lgd_name;       /* service name */
-+
-+        gss_OID         lgd_mech;       /* mech OID */
-+        u_int           lgd_req_flags;  /* request flags */
-+        gss_cred_id_t   lgd_cred;       /* credential */
-+        gss_ctx_id_t    lgd_ctx;        /* session context */
-+        gss_buffer_desc lgd_rmt_ctx;    /* remote handle of context */
-+        uint32_t        lgd_seq_win;    /* sequence window */
-+
-+        int             lgd_rpc_err;
-+        int             lgd_gss_err;
-+};
-+
- static int
--do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
--          gss_buffer_desc *context_token)
-+do_downcall(int k5_fd, struct lgssd_upcall_data *updata,
-+            struct lustre_gss_data *lgd, gss_buffer_desc *context_token)
- {
-       char    *buf = NULL, *p = NULL, *end = NULL;
-       unsigned int timeout = 0; /* XXX decide on a reasonable value */
-       unsigned int buf_size = 0;
--      printerr(1, "doing downcall\n");
--      buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) +
--              sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length +
-+      printerr(2, "doing downcall\n");
-+      buf_size = sizeof(updata->seq) + sizeof(timeout) +
-+              sizeof(lgd->lgd_seq_win) +
-+              sizeof(lgd->lgd_rmt_ctx.length) + lgd->lgd_rmt_ctx.length +
-               sizeof(context_token->length) + context_token->length;
-       p = buf = malloc(buf_size);
-       end = buf + buf_size;
--      if (WRITE_BYTES(&p, end, uid)) goto out_err;
-+      if (WRITE_BYTES(&p, end, updata->seq)) goto out_err;
-       /* Not setting any timeout for now: */
-       if (WRITE_BYTES(&p, end, timeout)) goto out_err;
--      if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err;
--      if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err;
-+      if (WRITE_BYTES(&p, end, lgd->lgd_seq_win)) goto out_err;
-+      if (write_buffer(&p, end, &lgd->lgd_rmt_ctx)) goto out_err;
-       if (write_buffer(&p, end, context_token)) goto out_err;
--      if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
-+      lgssd_mutex_get(lgssd_mutex_downcall);
-+      if (write(k5_fd, buf, p - buf) < p - buf) {
-+              lgssd_mutex_put(lgssd_mutex_downcall);
-+              goto out_err;
-+      }
-+      lgssd_mutex_put(lgssd_mutex_downcall);
-+
-       if (buf) free(buf);
-       return 0;
- out_err:
-       if (buf) free(buf);
--      printerr(0, "Failed to write downcall!\n");
-+      printerr(0, "ERROR: Failed to write downcall!\n");
-       return -1;
- }
- static int
--do_error_downcall(int k5_fd, uid_t uid, int err)
-+do_error_downcall(int k5_fd, uint32_t seq, int rpc_err, int gss_err)
- {
-       char    buf[1024];
-       char    *p = buf, *end = buf + 1024;
-@@ -455,19 +410,26 @@ do_error_downcall(int k5_fd, uid_t uid, 
-       printerr(1, "doing error downcall\n");
--      if (WRITE_BYTES(&p, end, uid)) goto out_err;
-+      if (WRITE_BYTES(&p, end, seq)) goto out_err;
-       if (WRITE_BYTES(&p, end, timeout)) goto out_err;
-       /* use seq_win = 0 to indicate an error: */
-       if (WRITE_BYTES(&p, end, zero)) goto out_err;
--      if (WRITE_BYTES(&p, end, err)) goto out_err;
-+      if (WRITE_BYTES(&p, end, rpc_err)) goto out_err;
-+      if (WRITE_BYTES(&p, end, gss_err)) goto out_err;
--      if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
-+      lgssd_mutex_get(lgssd_mutex_downcall);
-+      if (write(k5_fd, buf, p - buf) < p - buf) {
-+              lgssd_mutex_put(lgssd_mutex_downcall);
-+              goto out_err;
-+      }
-+      lgssd_mutex_put(lgssd_mutex_downcall);
-       return 0;
- out_err:
-       printerr(0, "Failed to write error downcall!\n");
-       return -1;
- }
-+#if 0
- /*
-  * Create an RPC connection and establish an authenticated
-  * gss context with a server.
-@@ -659,7 +621,287 @@ int create_auth_rpc_client(struct clnt_i
-       goto out;
- }
-+#endif
-+
-+static
-+int do_negotiation(struct lustre_gss_data *lgd,
-+                 gss_buffer_desc *gss_token,
-+                 struct lustre_gss_init_res *gr,
-+                 int timeout)
-+{
-+      char *file = "/proc/fs/lustre/sptlrpc/gss/init_channel";
-+      struct lgssd_ioctl_param param;
-+      struct passwd *pw;
-+      int fd, ret;
-+      char outbuf[8192];
-+      unsigned int *p;
-+      int res;
-+
-+      pw = getpwuid(lgd->lgd_uid);
-+      if (!pw) {
-+              printerr(0, "no uid %u in local user database\n",
-+                       lgd->lgd_uid);
-+              return -1;
-+      }
-+
-+      param.version = GSSD_INTERFACE_VERSION;
-+      param.uuid = lgd->lgd_uuid;
-+      param.lustre_svc = lgd->lgd_lustre_svc;
-+      param.uid = lgd->lgd_uid;
-+      param.gid = pw->pw_gid;
-+      param.send_token_size = gss_token->length;
-+      param.send_token = (char *) gss_token->value;
-+      param.reply_buf_size = sizeof(outbuf);
-+      param.reply_buf = outbuf;
-+
-+      fd = open(file, O_RDWR);
-+      if (fd < 0) {
-+              printerr(0, "can't open file %s\n", file);
-+              return -1;
-+      }
-+
-+      ret = write(fd, &param, sizeof(param));
-+
-+      if (ret != sizeof(param)) {
-+              printerr(0, "lustre ioctl err: %d\n", strerror(errno));
-+              close(fd);
-+              return -1;
-+      }
-+      if (param.status) {
-+              close(fd);
-+              printerr(0, "status: %d (%s)\n",
-+                       param.status, strerror((int)param.status));
-+              if (param.status == -ETIMEDOUT) {
-+                      /* kernel return -ETIMEDOUT means the rpc timedout,
-+                       * we should notify the caller to reinitiate the
-+                       * gss negotiation, by return -ERESTART
-+                       */
-+                      lgd->lgd_rpc_err = -ERESTART;
-+                      lgd->lgd_gss_err = 0;
-+              } else {
-+                      lgd->lgd_rpc_err = param.status;
-+                      lgd->lgd_gss_err = 0;
-+              }
-+              return -1;
-+      }
-+      p = (unsigned int *)outbuf;
-+      res = *p++;
-+      gr->gr_major = *p++;
-+      gr->gr_minor = *p++;
-+      gr->gr_win = *p++;
-+
-+      gr->gr_ctx.length = *p++;
-+      gr->gr_ctx.value = malloc(gr->gr_ctx.length);
-+      memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length);
-+      p += (((gr->gr_ctx.length + 3) & ~3) / 4);
-+
-+      gr->gr_token.length = *p++;
-+      gr->gr_token.value = malloc(gr->gr_token.length);
-+      memcpy(gr->gr_token.value, p, gr->gr_token.length);
-+      p += (((gr->gr_token.length + 3) & ~3) / 4);
-+
-+      printerr(2, "do_negotiation: receive handle len %d, token len %d\n",
-+               gr->gr_ctx.length, gr->gr_token.length);
-+      close(fd);
-+      return 0;
-+}
-+
-+static
-+int gssd_refresh_lgd(struct lustre_gss_data *lgd)
-+{
-+      struct lustre_gss_init_res gr;
-+      gss_buffer_desc         *recv_tokenp, send_token;
-+      OM_uint32                maj_stat, min_stat, call_stat, ret_flags;
-+
-+      /* GSS context establishment loop. */
-+      memset(&gr, 0, sizeof(gr));
-+      recv_tokenp = GSS_C_NO_BUFFER;
-+
-+      for (;;) {
-+              /* print the token we just received */
-+              if (recv_tokenp != GSS_C_NO_BUFFER) {
-+                      printerr(3, "The received token length %d\n",
-+                               recv_tokenp->length);
-+                      print_hexl(3, recv_tokenp->value, recv_tokenp->length);
-+              }
-+
-+              maj_stat = gss_init_sec_context(&min_stat,
-+                                              lgd->lgd_cred,
-+                                              &lgd->lgd_ctx,
-+                                              lgd->lgd_name,
-+                                              lgd->lgd_mech,
-+                                              lgd->lgd_req_flags,
-+                                              0,              /* time req */
-+                                              NULL,           /* channel */
-+                                              recv_tokenp,
-+                                              NULL,           /* used mech */
-+                                              &send_token,
-+                                              &ret_flags,
-+                                              NULL);          /* time rec */
-+
-+              if (recv_tokenp != GSS_C_NO_BUFFER) {
-+                      gss_release_buffer(&min_stat, &gr.gr_token);
-+                      recv_tokenp = GSS_C_NO_BUFFER;
-+              }
-+              if (maj_stat != GSS_S_COMPLETE &&
-+                  maj_stat != GSS_S_CONTINUE_NEEDED) {
-+                      pgsserr("gss_init_sec_context", maj_stat, min_stat,
-+                              lgd->lgd_mech);
-+                      break;
-+              }
-+              if (send_token.length != 0) {
-+                      memset(&gr, 0, sizeof(gr));
-+
-+                      /* print the token we are about to send */
-+                      printerr(3, "token being sent length %d\n",
-+                               send_token.length);
-+                      print_hexl(3, send_token.value, send_token.length);
-+
-+                      call_stat = do_negotiation(lgd, &send_token, &gr, 0);
-+                      gss_release_buffer(&min_stat, &send_token);
-+
-+                      if (call_stat != 0 ||
-+                          (gr.gr_major != GSS_S_COMPLETE &&
-+                           gr.gr_major != GSS_S_CONTINUE_NEEDED)) {
-+                              printerr(0, "call stat %d, major stat 0x%x\n",
-+                                       (int)call_stat, gr.gr_major);
-+                              return -1;
-+                      }
-+
-+                      if (gr.gr_ctx.length != 0) {
-+                              if (lgd->lgd_rmt_ctx.value)
-+                                      gss_release_buffer(&min_stat,
-+                                                         &lgd->lgd_rmt_ctx);
-+                              lgd->lgd_rmt_ctx = gr.gr_ctx;
-+                      }
-+                      if (gr.gr_token.length != 0) {
-+                              if (maj_stat != GSS_S_CONTINUE_NEEDED)
-+                                      break;
-+                              recv_tokenp = &gr.gr_token;
-+                      }
-+              }
-+
-+              /* GSS_S_COMPLETE => check gss header verifier,
-+               * usually checked in gss_validate
-+               */
-+              if (maj_stat == GSS_S_COMPLETE) {
-+                      lgd->lgd_established = 1;
-+                      lgd->lgd_seq_win = gr.gr_win;
-+                      break;
-+              }
-+      }
-+      /* End context negotiation loop. */
-+      if (!lgd->lgd_established) {
-+              if (gr.gr_token.length != 0)
-+                      gss_release_buffer(&min_stat, &gr.gr_token);
-+
-+              printerr(0, "context negotiation failed\n");
-+              return -1;
-+      }
-+
-+      printerr(2, "successfully refreshed lgd\n");
-+      return 0;
-+}
-+static
-+int gssd_create_lgd(struct clnt_info *clp,
-+                  struct lustre_gss_data *lgd,
-+                  struct lgssd_upcall_data *updata,
-+                  int authtype)
-+{
-+      gss_buffer_desc         sname;
-+      OM_uint32               maj_stat, min_stat;
-+      int                     retval = -1;
-+
-+      lgd->lgd_established = 0;
-+      lgd->lgd_lustre_svc = updata->svc;
-+      lgd->lgd_uid = updata->uid;
-+      lgd->lgd_uuid = updata->obd;
-+
-+      switch (authtype) {
-+      case AUTHTYPE_KRB5:
-+              lgd->lgd_mech = (gss_OID) &krb5oid;
-+              lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG;
-+              break;
-+      case AUTHTYPE_SPKM3:
-+              lgd->lgd_mech = (gss_OID) &spkm3oid;
-+              /* XXX sec.req_flags = GSS_C_ANON_FLAG;
-+               * Need a way to switch....
-+               */
-+              lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG;
-+              break;
-+      default:
-+              printerr(0, "Invalid authentication type (%d)\n", authtype);
-+              return -1;
-+      }
-+
-+      lgd->lgd_cred = GSS_C_NO_CREDENTIAL;
-+      lgd->lgd_ctx = GSS_C_NO_CONTEXT;
-+      lgd->lgd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER;
-+      lgd->lgd_seq_win = 0;
-+
-+      sname.value = clp->servicename;
-+      sname.length = strlen(clp->servicename);
-+
-+      maj_stat = gss_import_name(&min_stat, &sname,
-+                                 (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
-+                                 &lgd->lgd_name);
-+      if (maj_stat != GSS_S_COMPLETE) {
-+              pgsserr(0, maj_stat, min_stat, lgd->lgd_mech);
-+              goto out_fail;
-+      }
-+
-+      retval = gssd_refresh_lgd(lgd);
-+
-+      if (lgd->lgd_name != GSS_C_NO_NAME)
-+              gss_release_name(&min_stat, &lgd->lgd_name);
-+
-+      if (lgd->lgd_cred != GSS_C_NO_CREDENTIAL)
-+              gss_release_cred(&min_stat, &lgd->lgd_cred);
-+
-+  out_fail:
-+      return retval;
-+}
-+
-+static
-+void gssd_free_lgd(struct lustre_gss_data *lgd)
-+{
-+      gss_buffer_t            token = GSS_C_NO_BUFFER;
-+      OM_uint32               maj_stat, min_stat;
-+
-+      if (lgd->lgd_ctx == GSS_C_NO_CONTEXT)
-+              return;
-+
-+      maj_stat = gss_delete_sec_context(&min_stat, &lgd->lgd_ctx, token);
-+}
-+
-+static
-+int construct_service_name(struct clnt_info *clp,
-+                           struct lgssd_upcall_data *ud)
-+{
-+        const int buflen = 256;
-+        char name[buflen];
-+
-+        if (clp->servicename) {
-+                free(clp->servicename);
-+                clp->servicename = NULL;
-+        }
-+
-+        if (lnet_nid2hostname(ud->nid, name, buflen))
-+                return -1;
-+
-+        clp->servicename = malloc(32 + strlen(name));
-+        if (!clp->servicename) {
-+                printerr(0, "can't alloc memory\n");
-+                return -1;
-+        }
-+        sprintf(clp->servicename, "%s@%s",
-+                ud->svc == LUSTRE_GSS_SVC_MDS ?
-+              GSSD_SERVICE_MDS : GSSD_SERVICE_OSS,
-+                name);
-+        printerr(2, "constructed servicename: %s\n", clp->servicename);
-+        return 0;
-+}
- /*
-  * this code uses the userland rpcsec gss library to create a krb5
-@@ -668,103 +910,145 @@ int create_auth_rpc_client(struct clnt_i
- void
- handle_krb5_upcall(struct clnt_info *clp)
- {
--      uid_t                   uid;
--      CLIENT                  *rpc_clnt = NULL;
--      AUTH                    *auth = NULL;
--      struct authgss_private_data pd;
--      gss_buffer_desc         token;
-+      pid_t                   pid;
-+      gss_buffer_desc         token = { 0, NULL };
-+      struct lgssd_upcall_data updata;
-+      struct lustre_gss_data  lgd;
-       char                    **credlist = NULL;
-       char                    **ccname;
-+      int                     read_rc;
--      printerr(1, "handling krb5 upcall\n");
-+      printerr(2, "handling krb5 upcall\n");
--      token.length = 0;
--      token.value = NULL;
--      memset(&pd, 0, sizeof(struct authgss_private_data));
-+      memset(&lgd, 0, sizeof(lgd));
-+      lgd.lgd_rpc_err = -EPERM; /* default error code */
--      if (read(clp->krb5_fd, &uid, sizeof(uid)) < sizeof(uid)) {
--              printerr(0, "WARNING: failed reading uid from krb5 "
-+      read_rc = read(clp->krb5_fd, &updata, sizeof(updata));
-+      if (read_rc < 0) {
-+              printerr(0, "WARNING: failed reading from krb5 "
-                           "upcall pipe: %s\n", strerror(errno));
--              goto out;
-+              return;
-+      } else if (read_rc != sizeof(updata)) {
-+              printerr(0, "upcall data mismatch: length %d, expect %d\n",
-+                       read_rc, sizeof(updata));
-+
-+              /* the sequence number must be the first field. if read >= 4
-+               * bytes then we know at least sequence is fine, try to send
-+               * error notification nicely.
-+               */
-+              if (read_rc >= 4)
-+                      do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
-+              return;
-+      }
-+
-+      /* FIXME temporary fix, do this before fork.
-+       * in case of errors could have memory leak!!!
-+       */
-+      if (updata.uid == 0) {
-+              if (gssd_get_krb5_machine_cred_list(&credlist)) {
-+                      printerr(0, "ERROR: Failed to obtain machine "
-+                                  "credentials\n");
-+                      do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
-+                      return;
-+              }
-+      }
-+
-+      /* fork child process */
-+      pid = fork();
-+      if (pid < 0) {
-+              printerr(0, "can't fork: %s\n", strerror(errno));
-+              do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
-+              return;
-+      } else if (pid > 0) {
-+              printerr(2, "forked child process: %d\n", pid);
-+              return;
-+      }
-+
-+      printerr(1, "krb5 upcall: seq %u, uid %u, svc %u, nid 0x%llx, obd %s\n",
-+               updata.seq, updata.uid, updata.svc, updata.nid, updata.obd);
-+
-+      if (updata.svc != LUSTRE_GSS_SVC_MDS &&
-+          updata.svc != LUSTRE_GSS_SVC_OSS) {
-+              printerr(0, "invalid svc %d\n", updata.svc);
-+              lgd.lgd_rpc_err = -EPROTO;
-+              goto out_return_error;
-+      }
-+      updata.obd[sizeof(updata.obd)-1] = '\0';
-+
-+      if (construct_service_name(clp, &updata)) {
-+              printerr(0, "failed to construct service name\n");
-+              goto out_return_error;
-       }
--      if (uid == 0) {
-+      if (updata.uid == 0) {
-               int success = 0;
-               /*
-                * Get a list of credential cache names and try each
-                * of them until one works or we've tried them all
-                */
-+/*
-               if (gssd_get_krb5_machine_cred_list(&credlist)) {
--                      printerr(0, "WARNING: Failed to obtain machine "
--                                  "credentials for connection to "
--                                  "server %s\n", clp->servername);
--                              goto out_return_error;
-+                      printerr(0, "ERROR: Failed to obtain machine "
-+                                  "credentials for %s\n", clp->servicename);
-+                      goto out_return_error;
-               }
-+*/
-               for (ccname = credlist; ccname && *ccname; ccname++) {
-                       gssd_setup_krb5_machine_gss_ccache(*ccname);
--                      if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
--                                                  AUTHTYPE_KRB5)) == 0) {
-+                      if ((gssd_create_lgd(clp, &lgd, &updata,
-+                                           AUTHTYPE_KRB5)) == 0) {
-                               /* Success! */
-                               success++;
-                               break;
-                       }
-                       printerr(2, "WARNING: Failed to create krb5 context "
-                                   "for user with uid %d with credentials "
--                                  "cache %s for server %s\n",
--                               uid, *ccname, clp->servername);
-+                                  "cache %s for service %s\n",
-+                               updata.uid, *ccname, clp->servicename);
-               }
-               gssd_free_krb5_machine_cred_list(credlist);
-               if (!success) {
--                      printerr(0, "WARNING: Failed to create krb5 context "
-+                      printerr(0, "ERROR: Failed to create krb5 context "
-                                   "for user with uid %d with any "
--                                  "credentials cache for server %s\n",
--                               uid, clp->servername);
-+                                  "credentials cache for service %s\n",
-+                               updata.uid, clp->servicename);
-                       goto out_return_error;
-               }
-       }
-       else {
-               /* Tell krb5 gss which credentials cache to use */
--              gssd_setup_krb5_user_gss_ccache(uid, clp->servername);
-+              gssd_setup_krb5_user_gss_ccache(updata.uid, clp->servicename);
--              if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
--                                                      AUTHTYPE_KRB5)) != 0) {
-+              if ((gssd_create_lgd(clp, &lgd, &updata, AUTHTYPE_KRB5)) != 0) {
-                       printerr(0, "WARNING: Failed to create krb5 context "
--                                  "for user with uid %d for server %s\n",
--                               uid, clp->servername);
-+                                  "for user with uid %d for service %s\n",
-+                               updata.uid, clp->servicename);
-                       goto out_return_error;
-               }
-       }
--      if (!authgss_get_private_data(auth, &pd)) {
--              printerr(0, "WARNING: Failed to obtain authentication "
--                          "data for user with uid %d for server %s\n",
--                       uid, clp->servername);
--              goto out_return_error;
--      }
--
--      if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid)) {
-+      if (serialize_context_for_kernel(lgd.lgd_ctx, &token, &krb5oid)) {
-               printerr(0, "WARNING: Failed to serialize krb5 context for "
--                          "user with uid %d for server %s\n",
--                       uid, clp->servername);
-+                          "user with uid %d for service %s\n",
-+                       updata.uid, clp->servicename);
-               goto out_return_error;
-       }
--      do_downcall(clp->krb5_fd, uid, &pd, &token);
-+      printerr(1, "refreshed: %u@%s for %s\n",
-+               updata.uid, updata.obd, clp->servicename);
-+      do_downcall(clp->krb5_fd, &updata, &lgd, &token);
- out:
-       if (token.value)
-               free(token.value);
--      if (pd.pd_ctx_hndl.length != 0)
--              authgss_free_private_data(&pd);
--      if (auth)
--              AUTH_DESTROY(auth);
--      if (rpc_clnt)
--              clnt_destroy(rpc_clnt);
--      return;
-+
-+      gssd_free_lgd(&lgd);
-+      exit(0); /* i'm child process */
- out_return_error:
--      do_error_downcall(clp->krb5_fd, uid, -1);
-+      do_error_downcall(clp->krb5_fd, updata.seq,
-+                        lgd.lgd_rpc_err, lgd.lgd_gss_err);
-       goto out;
- }
-@@ -775,6 +1059,7 @@ out_return_error:
- void
- handle_spkm3_upcall(struct clnt_info *clp)
- {
-+#if 0
-       uid_t                   uid;
-       CLIENT                  *rpc_clnt = NULL;
-       AUTH                    *auth = NULL;
-@@ -826,4 +1111,5 @@ out:
- out_return_error:
-       do_error_downcall(clp->spkm3_fd, uid, -1);
-       goto out;
-+#endif
- }
-diff -rNup nfs-utils-1.0.10/utils/gssd/gss_util.c nfs-utils-1.0.10.lustre/utils/gssd/gss_util.c
---- nfs-utils-1.0.10/utils/gssd/gss_util.c     2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/gss_util.c      2007-05-15 13:01:35.000000000 -0600
-@@ -87,9 +87,16 @@
- #ifdef HAVE_COM_ERR_H
- #include <com_err.h>
- #endif
-+#include "lsupport.h"
- /* Global gssd_credentials handle */
--gss_cred_id_t gssd_creds;
-+gss_cred_id_t  gssd_cred_mds;
-+gss_cred_id_t  gssd_cred_oss;
-+int            gssd_cred_mds_valid = 0;
-+int            gssd_cred_oss_valid = 0;
-+
-+char *mds_local_realm = NULL;
-+char *oss_local_realm = NULL;
- gss_OID g_mechOid = GSS_C_NULL_OID;;
-@@ -183,15 +190,56 @@ pgsserr(char *msg, u_int32_t maj_stat, u
-       display_status_2(msg, maj_stat, min_stat, mech);
- }
--int
--gssd_acquire_cred(char *server_name)
-+static
-+int extract_realm_name(gss_buffer_desc *name, char **realm)
-+{
-+        char *sname, *c;
-+      int   rc = 0;
-+
-+        sname = malloc(name->length + 1);
-+        if (!sname) {
-+                printerr(0, "out of memory\n");
-+                return -ENOMEM;
-+        }
-+
-+        memcpy(sname, name->value, name->length);
-+        sname[name->length] = '\0';
-+        printerr(1, "service principal: %s\n", sname);
-+
-+        c = strchr(sname, '@');
-+        if (!c) {
-+              printerr(2, "no realm found in principal, use default\n");
-+              *realm = strdup(this_realm);
-+                if (!*realm) {
-+                        printerr(0, "failed to duplicate default realm\n");
-+                        rc = -ENOMEM;
-+                }
-+        } else {
-+                c++;
-+                *realm = strdup(c);
-+                if (!*realm) {
-+                        printerr(0, "failed to duplicated realm\n");
-+                        rc = -ENOMEM;
-+                }
-+        }
-+        free(sname);
-+
-+        return rc;
-+}
-+
-+static
-+int gssd_acquire_cred(char *server_name, gss_cred_id_t *cred,
-+                    char **local_realm, int *valid)
- {
-       gss_buffer_desc name;
-       gss_name_t target_name;
-       u_int32_t maj_stat, min_stat;
-       u_int32_t ignore_maj_stat, ignore_min_stat;
-+      gss_OID name_type;
-       gss_buffer_desc pbuf;
-+      *valid = 0;
-+
-       name.value = (void *)server_name;
-       name.length = strlen(server_name);
-@@ -201,12 +249,20 @@ gssd_acquire_cred(char *server_name)
-       if (maj_stat != GSS_S_COMPLETE) {
-               pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid);
--              return (FALSE);
-+              return -1;
-+      }
-+
-+      maj_stat = gss_display_name(&min_stat, target_name, &name, &name_type);
-+      if (maj_stat != GSS_S_COMPLETE) {
-+              pgsserr(0, maj_stat, min_stat, g_mechOid);
-+              return -1;
-       }
-+      if (extract_realm_name(&name, local_realm))
-+              return -1;
-       maj_stat = gss_acquire_cred(&min_stat, target_name, 0,
-                       GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
--                      &gssd_creds, NULL, NULL);
-+                      cred, NULL, NULL);
-       if (maj_stat != GSS_S_COMPLETE) {
-               pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid);
-@@ -218,11 +274,67 @@ gssd_acquire_cred(char *server_name)
-                       ignore_maj_stat = gss_release_buffer(&ignore_min_stat,
-                                                            &pbuf);
-               }
--      }
-+      } else
-+              *valid = 1;
-       ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name);
--      return (maj_stat == GSS_S_COMPLETE);
-+      if (maj_stat != GSS_S_COMPLETE)
-+              return -1;
-+      return 0;
-+}
-+
-+int gssd_prepare_creds(int must_srv_mds, int must_srv_oss)
-+{
-+        if (gssd_acquire_cred(GSSD_SERVICE_MDS, &gssd_cred_mds,
-+                              &mds_local_realm, &gssd_cred_mds_valid)) {
-+                if (must_srv_mds)
-+                        return -1;
-+        }
-+
-+        if (gssd_acquire_cred(GSSD_SERVICE_OSS, &gssd_cred_oss,
-+                              &oss_local_realm, &gssd_cred_oss_valid)) {
-+                if (must_srv_oss)
-+                        return -1;
-+        }
-+
-+        if (!gssd_cred_mds_valid && !gssd_cred_oss_valid) {
-+                printerr(0, "can't obtain both mds & oss creds, exit\n");
-+                return -1;
-+        }
-+
-+      if (gssd_cred_mds_valid)
-+              printerr(0, "Ready to serve Lustre MDS in realm %s\n",
-+                       mds_local_realm ? mds_local_realm : "N/A");
-+      if (gssd_cred_oss_valid)
-+              printerr(0, "Ready to serve Lustre OSS in realm %s\n",
-+                       oss_local_realm ? oss_local_realm : "N/A");
-+
-+        return 0;
-+}
-+
-+gss_cred_id_t gssd_select_svc_cred(int lustre_svc)
-+{
-+        switch (lustre_svc) {
-+        case LUSTRE_GSS_SVC_MDS:
-+                if (!gssd_cred_mds_valid) {
-+                        printerr(0, "ERROR: service cred for mds not ready\n");
-+                        return NULL;
-+                }
-+              printerr(2, "select mds service cred\n");
-+                return gssd_cred_mds;
-+        case LUSTRE_GSS_SVC_OSS:
-+                if (!gssd_cred_oss_valid) {
-+                        printerr(0, "ERROR: service cred for oss not ready\n");
-+                        return NULL;
-+                }
-+              printerr(2, "select oss service cred\n");
-+                return gssd_cred_oss;
-+        default:
-+                printerr(0, "ERROR: invalid lustre svc id %d\n", lustre_svc);
-+        }
-+
-+        return NULL;
- }
- int gssd_check_mechs(void)
-@@ -249,3 +361,42 @@ out:
-       return retval;
- }
-+/*********************************
-+ * FIXME should be in krb5_util.c
-+ *********************************/
-+
-+#include "krb5_util.h"
-+
-+/* realm of this node */
-+char *this_realm = NULL;
-+
-+int gssd_get_local_realm(void)
-+{
-+      krb5_context context = NULL;
-+      krb5_error_code code;
-+      int retval = -1;
-+
-+      if (this_realm != NULL)
-+              return 0;
-+
-+      code = krb5_init_context(&context);
-+      if (code) {
-+              printerr(0, "ERROR: get default realm: init ctx: %s\n",
-+                       error_message(code));
-+              goto out;
-+      }
-+
-+      code = krb5_get_default_realm(context, &this_realm);
-+      if (code) {
-+              printerr(0, "ERROR: get default realm: %s\n",
-+                       error_message(code));
-+              goto out;
-+      }
-+      retval = 0;
-+
-+      printerr(1, "Local realm: %s\n", this_realm);
-+out:
-+      krb5_free_context(context);
-+      return retval;
-+}
-+
-diff -rNup nfs-utils-1.0.10/utils/gssd/gss_util.h nfs-utils-1.0.10.lustre/utils/gssd/gss_util.h
---- nfs-utils-1.0.10/utils/gssd/gss_util.h     2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/gss_util.h      2007-05-15 13:01:35.000000000 -0600
-@@ -32,14 +32,14 @@
- #define _GSS_UTIL_H_
- #include <stdlib.h>
--#include <rpc/rpc.h>
- #include "write_bytes.h"
-+char *this_realm;
- extern gss_cred_id_t  gssd_creds;
--int gssd_acquire_cred(char *server_name);
- void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat,
-       const gss_OID mech);
- int gssd_check_mechs(void);
-+int gssd_get_local_realm(void);
- #endif /* _GSS_UTIL_H_ */
-diff -rNup nfs-utils-1.0.10/utils/gssd/krb5_util.c nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.c
---- nfs-utils-1.0.10/utils/gssd/krb5_util.c    2007-05-15 13:02:26.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.c     2007-05-15 13:01:35.000000000 -0600
-@@ -99,12 +99,15 @@
- #include <rpc/rpc.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-+#include <sys/utsname.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
-+#include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-+#include <netdb.h>
- #include <dirent.h>
- #include <fcntl.h>
- #include <errno.h>
-@@ -114,7 +117,6 @@
- #include <gssapi/gssapi_krb5.h>
- #endif
- #include <krb5.h>
--#include <rpc/auth_gss.h>
- #include "gssd.h"
- #include "err_util.h"
-@@ -129,6 +131,9 @@ struct gssd_k5_kt_princ *gssd_k5_kt_prin
- int num_krb5_enctypes = 0;
- krb5_enctype *krb5_enctypes = NULL;
-+/* credential expire time in advance */
-+unsigned long machine_cred_expire_advance = 300; /* 5 mins */
-+
- /*==========================*/
- /*===  Internal routines ===*/
- /*==========================*/
-@@ -137,11 +142,55 @@ static int select_krb5_ccache(const stru
- static int gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d);
- static int gssd_get_single_krb5_cred(krb5_context context,
-               krb5_keytab kt, struct gssd_k5_kt_princ *ple);
--static int gssd_have_realm_ple(void *realm);
- static int gssd_process_krb5_keytab(krb5_context context, krb5_keytab kt,
-               char *kt_name);
- /*
-+ * convenient macros, these perhaps need further cleanup
-+ */
-+#ifdef HAVE_KRB5
-+
-+#define KEYTAB_ENTRY_MATCH(kte, name)                                        \
-+      (                                                                      \
-+       (kte).principal->data[0].length == (sizeof(name)-1) &&                \
-+       strncmp((kte).principal->data[0].data, (name), sizeof(name)-1) == 0   \
-+      )
-+#define KRB5_FREE_UNPARSED_NAME(ctx, name)                                   \
-+              krb5_free_unparsed_name((ctx), (name));
-+#define KRB5_STRDUP(str)                                                     \
-+              strndup((str).data, (str).length)
-+#define KRB5_STRCMP(str, name)                                                       \
-+      (                                                                      \
-+       (str)->length != strlen(name) ||                                      \
-+       strncmp((str)->data, (name), (str)->length) != 0                      \
-+      )
-+#define KRB5_STRCASECMP(str, name)                                           \
-+      (                                                                      \
-+       (str)->length != strlen(name) ||                                      \
-+       strncasecmp((str)->data, (name), (str)->length) != 0                  \
-+      )
-+
-+#else /* !HAVE_KRB5 */
-+
-+#define KEYTAB_ENTRY_MATCH(kte, name)                                        \
-+      (                                                                      \
-+       strlen((kte).principal->name.name_string.val[0]) ==                   \
-+       (sizeof(name)-1) &&                                                   \
-+       strncmp(kte.principal->name.name_string.val[0], (name),               \
-+               sizeof(name)-1) == 0                                          \
-+      )
-+#define KRB5_FREE_UNPARSED_NAME(ctx, name)                                   \
-+              free(pname);
-+#define KRB5_STRDUP(str)                                                     \
-+              strdup(str)
-+#define KRB5_STRCMP(str, name)                                                       \
-+              strcmp((str), (name))
-+#define KRB5_STRCASECMP(str, name)                                           \
-+              strcmp((str), (name))
-+
-+#endif /* HAVE_KRB5 */
-+
-+/*
-  * Called from the scandir function to weed out potential krb5
-  * credentials cache files
-  *
-@@ -294,7 +343,7 @@ gssd_get_single_krb5_cred(krb5_context c
-       memset(&my_creds, 0, sizeof(my_creds));
--      if (ple->ccname && ple->endtime > now) {
-+      if (ple->ccname && ple->endtime > now + machine_cred_expire_advance) {
-               printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
-                        ple->ccname, ple->endtime);
-               code = 0;
-@@ -314,6 +363,12 @@ gssd_get_single_krb5_cred(krb5_context c
-       /* set a short lifetime (for debugging only!) */
-       printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
-       krb5_get_init_creds_opt_set_tkt_life(&options, 5*60);
-+#else
-+      /* FIXME try to get the ticket with lifetime as long as possible,
-+       * to work around ticket-expiry + recovery problem in cmd3-11
-+       * remove this!!!
-+       */
-+      krb5_get_init_creds_opt_set_tkt_life(&options, 30*24*60*60);
- #endif
-         if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ,
-                                         kt, 0, NULL, &options))) {
-@@ -325,11 +380,7 @@ gssd_get_single_krb5_cred(krb5_context c
-                           "principal '%s' from keytab '%s'\n",
-                        error_message(code),
-                        pname ? pname : "<unparsable>", kt_name);
--#ifdef HAVE_KRB5
--              if (pname) krb5_free_unparsed_name(context, pname);
--#else
--              if (pname) free(pname);
--#endif
-+              if (pname) KRB5_FREE_UNPARSED_NAME(context, pname);
-               goto out;
-       }
-@@ -378,15 +429,7 @@ gssd_get_single_krb5_cred(krb5_context c
-       return (code);
- }
--/*
-- * Determine if we already have a ple for the given realm
-- *
-- * Returns:
-- *    0 => no ple found for given realm
-- *    1 => found ple for given realm
-- */
--static int
--gssd_have_realm_ple(void *r)
-+static struct gssd_k5_kt_princ * gssd_get_realm_ple(void *r)
- {
-       struct gssd_k5_kt_princ *ple;
- #ifdef HAVE_KRB5
-@@ -396,18 +439,76 @@ gssd_have_realm_ple(void *r)
- #endif
-       for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
--#ifdef HAVE_KRB5
--              if ((realm->length == strlen(ple->realm)) &&
--                  (strncmp(realm->data, ple->realm, realm->length) == 0)) {
--#else
--              if (strcmp(realm, ple->realm) == 0) {
--#endif
--                  return 1;
--              }
-+              if (KRB5_STRCMP(realm, ple->realm) == 0)
-+                  return ple;
-+      }
-+      return NULL;
-+}
-+
-+static void gssd_free_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
-+{
-+      if (ple->princ)
-+              krb5_free_principal(kctx, ple->princ);
-+      if (ple->realm)
-+              free(ple->realm);
-+      if (ple->ccname)
-+              free(ple->ccname);
-+      free(ple);
-+}
-+
-+static int gssd_remove_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
-+{
-+      struct gssd_k5_kt_princ **prev = &gssd_k5_kt_princ_list;
-+      struct gssd_k5_kt_princ  *ent = gssd_k5_kt_princ_list;
-+
-+      for (; ent; prev = &ent->next, ent = ent->next) {
-+              if (ent != ple)
-+                      continue;
-+
-+              *prev = ent->next;
-+              gssd_free_ple(kctx, ent);
-+              return 1;
-       }
-       return 0;
- }
-+static
-+struct gssd_k5_kt_princ *gssd_create_ple(krb5_context kctx,
-+                                       krb5_principal principal)
-+{
-+      struct gssd_k5_kt_princ *ple;
-+      krb5_error_code          code;
-+
-+      ple = malloc(sizeof(*ple));
-+      if (ple == NULL) {
-+              printerr(0, "ERROR: could not allocate storage "
-+                          "for principal list entry\n");
-+              return NULL;
-+      }
-+
-+      memset(ple, 0, sizeof(*ple));
-+
-+      ple->realm = KRB5_STRDUP(principal->realm);
-+      if (ple->realm == NULL) {
-+              printerr(0, "ERROR: not enough memory while copying realm to "
-+                          "principal list entry\n");
-+              goto err_free;
-+      }
-+
-+      code = krb5_copy_principal(kctx, principal, &ple->princ);
-+      if (code) {
-+              printerr(0, "ERROR: %s while copying principal "
-+                          "to principal list entry\n",
-+                       error_message(code));
-+              goto err_free;
-+      }
-+
-+      return ple;
-+err_free:
-+      gssd_free_ple(kctx, ple);
-+      return NULL;
-+}
-+
- /*
-  * Process the given keytab file and create a list of principals we
-  * might use to perform mount operations.
-@@ -451,82 +552,106 @@ gssd_process_krb5_keytab(krb5_context co
-               }
-               printerr(2, "Processing keytab entry for principal '%s'\n",
-                        pname);
--#ifdef HAVE_KRB5
--              if ( (kte.principal->data[0].length == GSSD_SERVICE_NAME_LEN) &&
--                   (strncmp(kte.principal->data[0].data, GSSD_SERVICE_NAME,
--                            GSSD_SERVICE_NAME_LEN) == 0) &&
--#else
--              if ( (strlen(kte.principal->name.name_string.val[0]) == GSSD_SERVICE_NAME_LEN) &&
--                   (strncmp(kte.principal->name.name_string.val[0], GSSD_SERVICE_NAME,
--                            GSSD_SERVICE_NAME_LEN) == 0) &&
--                            
--#endif
--                   (!gssd_have_realm_ple((void *)&kte.principal->realm)) ) {
--                      printerr(2, "We will use this entry (%s)\n", pname);
--                      ple = malloc(sizeof(struct gssd_k5_kt_princ));
--                      if (ple == NULL) {
--                              printerr(0, "ERROR: could not allocate storage "
--                                          "for principal list entry\n");
--#ifdef HAVE_KRB5
--                              krb5_free_unparsed_name(context, pname);
--#else
--                              free(pname);
--#endif
--                              retval = ENOMEM;
--                              goto out;
-+
-+              /* mds service entry:
-+               *   - hostname and realm should match this node
-+               *   - replace existing non-mds entry of this realm
-+               */
-+              if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS)) {
-+                      krb5_principal princ = kte.principal;
-+                      krb5_data *princ_host;
-+                      struct utsname utsbuf;
-+                      struct hostent *host;
-+
-+                      if (KRB5_STRCASECMP(krb5_princ_realm(context, princ),
-+                                          this_realm) != 0) {
-+                              printerr(2, "alien mds service entry, skip\n");
-+                              goto next;
-                       }
--                      /* These will be filled in later */
--                      ple->next = NULL;
--                      ple->ccname = NULL;
--                      ple->endtime = 0;
--                      if ((ple->realm =
--#ifdef HAVE_KRB5
--                              strndup(kte.principal->realm.data,
--                                      kte.principal->realm.length))
--#else
--                              strdup(kte.principal->realm))
--#endif
--                                      == NULL) {
--                              printerr(0, "ERROR: %s while copying realm to "
--                                          "principal list entry\n",
--                                       "not enough memory");
--#ifdef HAVE_KRB5
--                              krb5_free_unparsed_name(context, pname);
--#else
--                              free(pname);
--#endif
--                              retval = ENOMEM;
--                              goto out;
-+
-+                      princ_host = krb5_princ_component(context, princ, 1);
-+                      if (princ_host == NULL) {
-+                              printerr(2, "mds service entry: no hostname in "
-+                                       "principal, skip\n");
-+                              goto next;
-                       }
--                      if ((code = krb5_copy_principal(context,
--                                      kte.principal, &ple->princ))) {
--                              printerr(0, "ERROR: %s while copying principal "
--                                          "to principal list entry\n",
--                                      error_message(code));
--#ifdef HAVE_KRB5
--                              krb5_free_unparsed_name(context, pname);
--#else
--                              free(pname);
--#endif
--                              retval = code;
--                              goto out;
-+
-+                      if (uname(&utsbuf)) {
-+                              printerr(2, "mds service entry: unable to get "
-+                                       "UTS name, skip\n");
-+                              goto next;
-                       }
--                      if (gssd_k5_kt_princ_list == NULL)
--                              gssd_k5_kt_princ_list = ple;
--                      else {
--                              ple->next = gssd_k5_kt_princ_list;
--                              gssd_k5_kt_princ_list = ple;
-+                      host = gethostbyname(utsbuf.nodename);
-+                      if (host == NULL) {
-+                              printerr(2, "mds service entry: unable to get "
-+                                       "local hostname, skip\n");
-+                              goto next;
-                       }
--              }
--              else {
-+
-+                      if (KRB5_STRCASECMP(princ_host, host->h_name) != 0) {
-+                              printerr(2, "mds service entry: hostname "
-+                                       "doesn't match: %s - %.*s, skip\n",
-+                                       host->h_name,
-+                                       princ_host->length, princ_host->data);
-+                              goto next;
-+                      }
-+
-+                      ple = gssd_get_realm_ple((void *)&kte.principal->realm);
-+                      if (ple) {
-+                              if (ple->fl_mds) {
-+                                      printerr(2,"mds service entry: found a "
-+                                               "duplicated one, it's like a "
-+                                               "mis-configuration, skip\n");
-+                                      goto next;
-+                              }
-+
-+                              gssd_remove_ple(context, ple);
-+                              printerr(2, "mds service entry: replace an "
-+                                       "existed non-mds one\n");
-+                      }
-+              } else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME)) {
-+                      ple = gssd_get_realm_ple((void *)&kte.principal->realm);
-+                      if (ple) {
-+                              if (ple->fl_mds || ple->fl_root) {
-+                                      printerr(2, "root entry: found a "
-+                                               "existed %s entry, skip\n",
-+                                               ple->fl_mds ? "mds" : "root");
-+                                      goto next;
-+                              }
-+
-+                              gssd_remove_ple(context, ple);
-+                              printerr(2, "root entry: replace an existed "
-+                                       "non-mds non-root one\n");
-+                      }
-+              } else {
-                       printerr(2, "We will NOT use this entry (%s)\n",
-                               pname);
-+                      goto next;
-               }
--#ifdef HAVE_KRB5
--              krb5_free_unparsed_name(context, pname);
--#else
--              free(pname);
--#endif
-+
-+              /* construct ple */
-+              printerr(2, "We will use this entry (%s)\n", pname);
-+              ple = gssd_create_ple(context, kte.principal);
-+              if (ple == NULL) {
-+                      KRB5_FREE_UNPARSED_NAME(context, pname);
-+                      goto out;
-+              }
-+
-+              /* add proper flags */
-+              if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS))
-+                      ple->fl_mds = 1;
-+              else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME))
-+                      ple->fl_root = 1;
-+
-+              /* enqueue */
-+              if (gssd_k5_kt_princ_list == NULL)
-+                      gssd_k5_kt_princ_list = ple;
-+              else {
-+                      ple->next = gssd_k5_kt_princ_list;
-+                      gssd_k5_kt_princ_list = ple;
-+              }
-+ next:
-+              KRB5_FREE_UNPARSED_NAME(context, pname);
-       }
-       if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) {
-@@ -642,6 +767,7 @@ gssd_setup_krb5_user_gss_ccache(uid_t ui
-       printerr(2, "getting credentials for client with uid %u for "
-                   "server %s\n", uid, servername);
-       memset(buf, 0, sizeof(buf));
-+
-       if (gssd_find_existing_krb5_ccache(uid, &d)) {
-               snprintf(buf, sizeof(buf), "FILE:%s/%s",
-                       ccachedir, d->d_name);
-@@ -702,7 +828,7 @@ gssd_refresh_krb5_machine_creds(void)
-               goto out;
-       }
--      printerr(1, "Using keytab file '%s'\n", keytabfile);
-+      printerr(2, "Using keytab file '%s'\n", keytabfile);
-       if ((code = krb5_kt_resolve(context, keytabfile, &kt))) {
-               printerr(0, "ERROR: %s while resolving keytab '%s'\n",
-@@ -717,12 +843,12 @@ gssd_refresh_krb5_machine_creds(void)
-               if (gssd_k5_kt_princ_list == NULL) {
-                       printerr(0, "ERROR: No usable keytab entries found in "
-                                   "keytab '%s'\n", keytabfile);
--                      printerr(0, "Do you have a valid keytab entry for "
--                                  "%s/<your.host>@<YOUR.REALM> in "
-+                      printerr(0, "You must have a valid keytab entry for "
-+                                  "%s/<your.host>@<YOUR.REALM> on MDT nodes, "
-+                                  "and %s@<YOUR.REALM> on client nodes, in "
-                                   "keytab file %s ?\n",
--                                  GSSD_SERVICE_NAME, keytabfile);
--                      printerr(0, "Continuing without (machine) credentials "
--                                  "- nfs4 mounts with Kerberos will fail\n");
-+                                  GSSD_SERVICE_MDS, LUSTRE_ROOT_NAME,
-+                                  keytabfile);
-               }
-       }
-@@ -872,6 +998,7 @@ gssd_destroy_krb5_machine_creds(void)
-       krb5_free_context(context);
- }
-+#if 0
- #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
- /*
-  * this routine obtains a credentials handle via gss_acquire_cred()
-@@ -927,6 +1054,7 @@ limit_krb5_enctypes(struct rpc_gss_sec *
-       return 0;
- }
- #endif        /* HAVE_SET_ALLOWABLE_ENCTYPES */
-+#endif
- /*
-  * Obtain supported enctypes from kernel.
-diff -rNup nfs-utils-1.0.10/utils/gssd/krb5_util.h nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.h
---- nfs-utils-1.0.10/utils/gssd/krb5_util.h    2007-05-15 13:02:26.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.h     2007-05-15 13:01:35.000000000 -0600
-@@ -10,6 +10,8 @@
- struct gssd_k5_kt_princ {
-       struct gssd_k5_kt_princ *next;
-       krb5_principal princ;
-+      unsigned int    fl_root:1,
-+                      fl_mds:1;
-       char *ccname;
-       char *realm;
-       krb5_timestamp endtime;
-@@ -25,8 +27,4 @@ void gssd_destroy_krb5_machine_creds(voi
- void gssd_obtain_kernel_krb5_info(void);
--#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
--int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
--#endif
--
- #endif /* KRB5_UTIL_H */
-diff -rNup nfs-utils-1.0.10/utils/gssd/lgss_keyring.c nfs-utils-1.0.10.lustre/utils/gssd/lgss_keyring.c
---- nfs-utils-1.0.10/utils/gssd/lgss_keyring.c 1969-12-31 17:00:00.000000000 -0700
-+++ nfs-utils-1.0.10.lustre/utils/gssd/lgss_keyring.c  2007-05-15 13:01:35.000000000 -0600
-@@ -0,0 +1,776 @@
-+/*
-+ *  lucall_keyring.c
-+ *  user-space upcall to create GSS context, using keyring interface to kernel
-+ *
-+ *  Copyright (c) 2007 Cluster File Systems, Inc.
-+ *   Author: Eric Mei <ericm@clusterfs.com>
-+ *
-+ *   This file is part of the Lustre file system, http://www.lustre.org
-+ *   Lustre is a trademark of Cluster File Systems, Inc.
-+ *
-+ *   You may have signed or agreed to another license before downloading
-+ *   this software.  If so, you are bound by the terms and conditions
-+ *   of that agreement, and the following does not apply to you.  See the
-+ *   LICENSE file included with this distribution for more information.
-+ *
-+ *   If you did not agree to a different license, then this copy of Lustre
-+ *   is open source software; you can redistribute it and/or modify it
-+ *   under the terms of version 2 of the GNU General Public License as
-+ *   published by the Free Software Foundation.
-+ *
-+ *   In either case, Lustre is distributed in the hope that it will be
-+ *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-+ *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *   license text for more details.
-+ */
-+
-+#include <unistd.h>
-+#include <stdlib.h>
-+#include <stdio.h>
-+#include <fcntl.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <stdarg.h>
-+#include <syslog.h>
-+#include <assert.h>
-+#include <pwd.h>
-+#include <keyutils.h>
-+#include <gssapi/gssapi.h>
-+
-+#include <libcfs/libcfs.h>
-+
-+#include "lsupport.h"
-+#include "write_bytes.h"
-+#include "krb5_util.h"
-+#include "gss_oids.h"
-+#include "context.h"
-+
-+/*
-+ * XXX TEMP to satisfy link. should be removed!!!
-+ */
-+char ccachedir[PATH_MAX] = "/tmp";
-+char keytabfile[PATH_MAX] = "/etc/krb5.keytab";
-+int  use_memcache = 0;
-+
-+/****************************************
-+ * log facilities                       *
-+ ****************************************/
-+
-+/*
-+ * log level:
-+ * 0: critical error messages
-+ * 1: warning included
-+ * 2: debugging
-+ * 3: excessive messages
-+ */
-+typedef enum {
-+        LL_ERR          = 0,
-+        LL_WARN         = 1,
-+        LL_INFO         = 2,
-+        LL_TRACE        = 3,
-+} loglevel_t;
-+
-+loglevel_t g_log_level = LL_TRACE;
-+
-+static void logmsg(loglevel_t level, const char *format, ...)
-+{
-+        char    buf[1024];
-+        int     offset;
-+        va_list ap;
-+
-+        if (level > g_log_level)
-+                return;
-+
-+        offset = snprintf(buf, sizeof(buf), "[%d]: ", getpid());
-+
-+        va_start(ap, format);
-+        vsnprintf(buf + offset, sizeof(buf) - offset, format, ap);
-+        va_end(ap);
-+
-+        syslog(LOG_INFO, "%s", buf);
-+}
-+
-+static void logmsg_gss(loglevel_t level, const gss_OID mech,
-+                       u_int32_t major, u_int32_t minor,
-+                       const char *format, ...)
-+{
-+        va_list         ap;
-+        u_int32_t       maj_stat1, min_stat1;
-+        u_int32_t       maj_stat2, min_stat2;
-+        gss_buffer_desc maj_gss_buf = GSS_C_EMPTY_BUFFER;
-+        gss_buffer_desc min_gss_buf = GSS_C_EMPTY_BUFFER;
-+        char            maj_buf[30], min_buf[30];
-+        char           *maj, *min;
-+        uint32_t        msg_ctx = 0;
-+
-+        if (level > g_log_level)
-+                return;
-+
-+        /* Get major status message */
-+        maj_stat1 = gss_display_status(&min_stat1, major,
-+                GSS_C_GSS_CODE, mech, &msg_ctx, &maj_gss_buf);
-+
-+        if (maj_stat1 != GSS_S_COMPLETE) {
-+                snprintf(maj_buf, sizeof(maj_buf), "(0x%08x)", major);
-+                maj = &maj_buf[0];
-+        } else {
-+                maj = maj_gss_buf.value;
-+        }
-+
-+        /* Get minor status message */
-+        maj_stat2 = gss_display_status(&min_stat2, minor,
-+                GSS_C_MECH_CODE, mech, &msg_ctx, &min_gss_buf);
-+
-+        if (maj_stat2 != GSS_S_COMPLETE) {
-+                snprintf(min_buf, sizeof(min_buf), "(0x%08x)", minor);
-+                min = &min_buf[0];
-+        } else {
-+                min = min_gss_buf.value;
-+        }
-+
-+        syslog(LOG_INFO, "GSS-API: %s - %s\n", maj, min);
-+
-+        va_start(ap, format);
-+        vsyslog(LOG_INFO, format, ap);
-+        va_end(ap);
-+
-+        if (maj_gss_buf.length != 0)
-+                (void) gss_release_buffer(&min_stat1, &maj_gss_buf);
-+        if (min_gss_buf.length != 0)
-+                (void) gss_release_buffer(&min_stat2, &min_gss_buf);
-+}
-+
-+#define lassert(exp)                                                    \
-+        {                                                               \
-+                if ((int)(exp) == 0) {                                  \
-+                        logmsg(LL_ERR, "ASSERTION FAILED: #exp");       \
-+                        exit(-1);                                       \
-+                }                                                       \
-+        }
-+
-+/****************************************
-+ * global declaration                   *
-+ ****************************************/
-+
-+typedef enum {
-+        LGSS_SVC_MDS    = 0,
-+        LGSS_SVC_OSS    = 1,
-+        LGSS_SVC_MAX
-+} lgss_svc_t;
-+
-+const char *lgss_svc_name[LGSS_SVC_MAX] = {
-+        [LGSS_SVC_MDS] = "lustre_mds",
-+        [LGSS_SVC_OSS] = "lustre_oss",
-+};
-+
-+typedef enum {
-+        LGSS_AUTH_KRB5,
-+} lgss_auth_t;
-+
-+/*
-+ * all data about negotiation
-+ */
-+struct lgss_nego_data {
-+        uint32_t        lnd_established:1;
-+        uint32_t        lnd_uid;
-+        uint32_t        lnd_lsvc;
-+        char           *lnd_uuid;
-+
-+        gss_OID         lnd_mech;               /* mech OID */
-+        gss_name_t      lnd_svc_name;           /* service name */
-+        u_int           lnd_req_flags;          /* request flags */
-+        gss_cred_id_t   lnd_cred;               /* credential */
-+        gss_ctx_id_t    lnd_ctx;                /* session context */
-+        gss_buffer_desc lnd_rmt_ctx;            /* remote handle of context */
-+        uint32_t        lnd_seq_win;            /* sequence window */
-+
-+        int             lnd_rpc_err;
-+        int             lnd_gss_err;
-+};
-+
-+/*
-+ * context creation response
-+ */
-+struct lgss_init_res {
-+        gss_buffer_desc gr_ctx;         /* context handle */
-+        u_int           gr_major;       /* major status */
-+        u_int           gr_minor;       /* minor status */
-+        u_int           gr_win;         /* sequence window */
-+        gss_buffer_desc gr_token;       /* token */
-+};
-+
-+struct keyring_upcall_param {
-+        uint32_t        kup_ver;
-+        uint32_t        kup_uid;
-+        uint32_t        kup_gid;
-+        uint32_t        kup_svc;
-+        uint64_t        kup_nid;
-+        char            kup_tgt[64];
-+};
-+
-+/*
-+ * gss target string of lustre service we are negotiating for
-+ */
-+char *g_service = NULL;
-+
-+/****************************************
-+ * child process: gss negotiation       *
-+ ****************************************/
-+
-+#define INIT_CHANNEL    "/proc/fs/lustre/sptlrpc/gss/init_channel"
-+
-+int do_nego_rpc(struct lgss_nego_data *lnd,
-+                gss_buffer_desc *gss_token,
-+                struct lgss_init_res *gr)
-+{
-+        struct lgssd_ioctl_param  param;
-+        struct passwd            *pw;
-+        int                       fd, ret, res;
-+        char                      outbuf[8192];
-+        unsigned int             *p;
-+
-+        logmsg(LL_TRACE, "do_nego_rpc: get started\n");
-+
-+        pw = getpwuid(lnd->lnd_uid);
-+        if (!pw) {
-+                logmsg(LL_ERR, "no uid %u in local user database\n",
-+                       lnd->lnd_uid);
-+                return -1;
-+        }
-+
-+        param.version = GSSD_INTERFACE_VERSION;
-+        param.uuid = lnd->lnd_uuid;
-+        param.lustre_svc = lnd->lnd_lsvc;
-+        param.uid = lnd->lnd_uid;
-+        param.gid = pw->pw_gid;
-+        param.send_token_size = gss_token->length;
-+        param.send_token = (char *) gss_token->value;
-+        param.reply_buf_size = sizeof(outbuf);
-+        param.reply_buf = outbuf;
-+
-+        logmsg(LL_TRACE, "to open " INIT_CHANNEL "\n");
-+
-+        fd = open(INIT_CHANNEL, O_WRONLY);
-+        if (fd < 0) {
-+                logmsg(LL_ERR, "can't open " INIT_CHANNEL "\n");
-+                return -1;
-+        }
-+
-+        logmsg(LL_TRACE, "to down-write\n");
-+
-+        ret = write(fd, &param, sizeof(param));
-+        if (ret != sizeof(param)) {
-+                logmsg(LL_ERR, "lustre ioctl err: %d\n", strerror(errno));
-+                close(fd);
-+                return -1;
-+        }
-+        close(fd);
-+
-+        logmsg(LL_TRACE, "do_nego_rpc: to parse reply\n");
-+        if (param.status) {
-+                logmsg(LL_ERR, "status: %d (%s)\n",
-+                       param.status, strerror((int)param.status));
-+
-+                if (param.status == -ETIMEDOUT) {
-+                        /* kernel return -ETIMEDOUT means the rpc timedout,
-+                         * we should notify the caller to reinitiate the
-+                         * gss negotiation, by return -ERESTART
-+                         */
-+                        lnd->lnd_rpc_err = -ERESTART;
-+                        lnd->lnd_gss_err = 0;
-+                } else {
-+                        lnd->lnd_rpc_err = param.status;
-+                        lnd->lnd_gss_err = 0;
-+                }
-+
-+                return -1;
-+        }
-+
-+        p = (unsigned int *)outbuf;
-+        res = *p++;
-+        gr->gr_major = *p++;
-+        gr->gr_minor = *p++;
-+        gr->gr_win = *p++;
-+
-+        gr->gr_ctx.length = *p++;
-+        gr->gr_ctx.value = malloc(gr->gr_ctx.length);
-+        memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length);
-+        p += (((gr->gr_ctx.length + 3) & ~3) / 4);
-+
-+        gr->gr_token.length = *p++;
-+        gr->gr_token.value = malloc(gr->gr_token.length);
-+        memcpy(gr->gr_token.value, p, gr->gr_token.length);
-+        p += (((gr->gr_token.length + 3) & ~3) / 4);
-+
-+        logmsg(LL_INFO, "do_nego_rpc: receive handle len %d, token len %d\n",
-+               gr->gr_ctx.length, gr->gr_token.length);
-+        return 0;
-+}
-+
-+/*
-+ * if return error, the lnd_rpc_err or lnd_gss_err is set.
-+ */
-+int lgssc_negotiation(struct lgss_nego_data *lnd)
-+{
-+        struct lgss_init_res    gr;
-+        gss_buffer_desc        *recv_tokenp, send_token;
-+        OM_uint32               maj_stat, min_stat, ret_flags;
-+        int                     call_stat;
-+
-+        logmsg(LL_TRACE, "start negotiation\n");
-+
-+        /* GSS context establishment loop. */
-+        memset(&gr, 0, sizeof(gr));
-+        recv_tokenp = GSS_C_NO_BUFFER;
-+
-+        for (;;) {
-+#if 0
-+                /* print the token we just received */
-+                if (recv_tokenp != GSS_C_NO_BUFFER) {
-+                        printerr(3, "The received token length %d\n",
-+                                 recv_tokenp->length);
-+                        print_hexl(3, recv_tokenp->value, recv_tokenp->length);
-+                }
-+#endif
-+
-+                maj_stat = gss_init_sec_context(&min_stat,
-+                                                lnd->lnd_cred,
-+                                                &lnd->lnd_ctx,
-+                                                lnd->lnd_svc_name,
-+                                                lnd->lnd_mech,
-+                                                lnd->lnd_req_flags,
-+                                                0,            /* time req */
-+                                                NULL,         /* channel */
-+                                                recv_tokenp,
-+                                                NULL,         /* used mech */
-+                                                &send_token,
-+                                                &ret_flags,
-+                                                NULL);        /* time rec */
-+
-+                if (recv_tokenp != GSS_C_NO_BUFFER) {
-+                        gss_release_buffer(&min_stat, &gr.gr_token);
-+                        recv_tokenp = GSS_C_NO_BUFFER;
-+                }
-+
-+                if (maj_stat != GSS_S_COMPLETE &&
-+                    maj_stat != GSS_S_CONTINUE_NEEDED) {
-+                        lnd->lnd_gss_err = maj_stat;
-+
-+                        logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
-+                                   "failed init context\n");
-+                        break;
-+                }
-+
-+                if (send_token.length != 0) {
-+                        memset(&gr, 0, sizeof(gr));
-+#if 0
-+                        /* print the token we are about to send */
-+                        printerr(3, "token being sent length %d\n",
-+                                 send_token.length);
-+                        print_hexl(3, send_token.value, send_token.length);
-+#endif
-+                        call_stat = do_nego_rpc(lnd, &send_token, &gr);
-+                        gss_release_buffer(&min_stat, &send_token);
-+
-+                        if (call_stat != 0 ||
-+                            (gr.gr_major != GSS_S_COMPLETE &&
-+                             gr.gr_major != GSS_S_CONTINUE_NEEDED)) {
-+                                lnd->lnd_rpc_err = call_stat;
-+                                lnd->lnd_gss_err = gr.gr_major;
-+
-+                                logmsg(LL_ERR, "call stat %d, major stat %x\n",
-+                                       call_stat, gr.gr_major);
-+                                return -1;
-+                        }
-+
-+                        if (gr.gr_ctx.length != 0) {
-+                                if (lnd->lnd_rmt_ctx.value)
-+                                        gss_release_buffer(&min_stat,
-+                                                           &lnd->lnd_rmt_ctx);
-+                                lnd->lnd_rmt_ctx = gr.gr_ctx;
-+                        }
-+
-+                        if (gr.gr_token.length != 0) {
-+                                if (maj_stat != GSS_S_CONTINUE_NEEDED)
-+                                        break;
-+                                recv_tokenp = &gr.gr_token;
-+                        }
-+                }
-+
-+                /* GSS_S_COMPLETE => check gss header verifier,
-+                 * usually checked in gss_validate
-+                 */
-+                if (maj_stat == GSS_S_COMPLETE) {
-+                        lnd->lnd_established = 1;
-+                        lnd->lnd_seq_win = gr.gr_win;
-+                        break;
-+                }
-+        }
-+
-+        /* End context negotiation loop. */
-+        if (!lnd->lnd_established) {
-+                if (gr.gr_token.length != 0)
-+                        gss_release_buffer(&min_stat, &gr.gr_token);
-+
-+                if (lnd->lnd_gss_err == GSS_S_COMPLETE)
-+                        lnd->lnd_rpc_err = -EACCES;
-+
-+                logmsg(LL_ERR, "context negotiation failed\n");
-+                return -1;
-+        }
-+
-+        logmsg(LL_INFO, "successfully negotiated context\n");
-+        return 0;
-+}
-+
-+int construct_service(struct keyring_upcall_param *kup)
-+{
-+        const int       max_namelen = 512;
-+        char            namebuf[max_namelen];
-+        int             alloc_size;
-+
-+        lassert(g_service == NULL);
-+
-+        if (kup->kup_svc >= LGSS_SVC_MAX) {
-+                logmsg(LL_ERR, "invalid lgss service %d\n", kup->kup_svc);
-+                return 1;
-+        }
-+
-+        if (lnet_nid2hostname(kup->kup_nid, namebuf, max_namelen))
-+                return 1;
-+
-+        alloc_size = 32 + strlen(namebuf);
-+
-+        g_service = malloc(alloc_size);
-+        if (g_service == NULL) {
-+                logmsg(LL_ERR, "can't malloc %d bytes\n", alloc_size);
-+                return 1;
-+        }
-+
-+        snprintf(g_service, alloc_size, "%s@%s",
-+                 lgss_svc_name[kup->kup_svc], namebuf);
-+
-+        logmsg(LL_INFO, "constructed service: %s\n", g_service);
-+        return 0;
-+}
-+
-+/*
-+ * if return error, the lnd_rpc_err or lnd_gss_err is set.
-+ */
-+int lgssc_init_nego_data(struct lgss_nego_data *lnd,
-+                         struct keyring_upcall_param *kup,
-+                         lgss_auth_t authtype)
-+{
-+        gss_buffer_desc         sname;
-+        OM_uint32               maj_stat, min_stat;
-+
-+        memset(lnd, 0, sizeof(*lnd));
-+
-+        lnd->lnd_uid = kup->kup_uid;
-+        lnd->lnd_lsvc = kup->kup_svc;
-+        lnd->lnd_uuid = kup->kup_tgt;
-+
-+        lnd->lnd_established = 0;
-+        lnd->lnd_svc_name = GSS_C_NO_NAME;
-+        lnd->lnd_cred = GSS_C_NO_CREDENTIAL;
-+        lnd->lnd_ctx = GSS_C_NO_CONTEXT;
-+        lnd->lnd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER;
-+        lnd->lnd_seq_win = 0;
-+
-+        switch (authtype) {
-+        case LGSS_AUTH_KRB5:
-+                lnd->lnd_mech = (gss_OID) &krb5oid;
-+                lnd->lnd_req_flags = GSS_C_MUTUAL_FLAG;
-+                break;
-+        default:
-+                logmsg(LL_ERR, "invalid auth type: %d\n", authtype);
-+                lnd->lnd_rpc_err = -EACCES;
-+                return -1;
-+        }
-+
-+        sname.value = g_service;
-+        sname.length = strlen(g_service);
-+
-+        maj_stat = gss_import_name(&min_stat, &sname,
-+                                   (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
-+                                   &lnd->lnd_svc_name);
-+        if (maj_stat != GSS_S_COMPLETE) {
-+                logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
-+                           "can't import svc name\n");
-+                lnd->lnd_gss_err = maj_stat;
-+                return -1;
-+        }
-+
-+        return 0;
-+}
-+
-+void lgssc_fini_nego_data(struct lgss_nego_data *lnd)
-+{
-+        OM_uint32       maj_stat, min_stat;
-+
-+        if (lnd->lnd_svc_name != GSS_C_NO_NAME) {
-+                maj_stat = gss_release_name(&min_stat, &lnd->lnd_svc_name);
-+                if (maj_stat != GSS_S_COMPLETE)
-+                        logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
-+                                   "can't release service name\n");
-+        }
-+
-+        if (lnd->lnd_cred != GSS_C_NO_CREDENTIAL) {
-+                maj_stat = gss_release_cred(&min_stat, &lnd->lnd_cred);
-+                if (maj_stat != GSS_S_COMPLETE)
-+                        logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat,
-+                                   "can't release credential\n");
-+        }
-+}
-+
-+static
-+int error_kernel_key(key_serial_t keyid, int rpc_error, int gss_error)
-+{
-+        int      seqwin = 0;
-+        char     buf[32];
-+        char    *p, *end;
-+
-+        logmsg(LL_TRACE, "revoking kernel key 0x%x\n", keyid);
-+
-+        p = buf;
-+        end = buf + sizeof(buf);
-+
-+        WRITE_BYTES(&p, end, seqwin);
-+        WRITE_BYTES(&p, end, rpc_error);
-+        WRITE_BYTES(&p, end, gss_error);
-+
-+again:
-+        if (keyctl_update(keyid, buf, p - buf)) {
-+                if (errno != EAGAIN) {
-+                        logmsg(LL_ERR, "failed to revoke key 0x%x: %s\n",
-+                               keyid, strerror(errno));
-+                        return -1;
-+                }
-+
-+                logmsg(LL_WARN, "revoke key 0x%x too soon, try again\n", keyid);
-+                sleep(2);
-+                goto again;
-+        }
-+
-+        logmsg(LL_INFO, "successfully revoke key 0x%x\n", keyid);
-+        return 0;
-+}
-+
-+static
-+int update_kernel_key(key_serial_t keyid,
-+                      struct lgss_nego_data *lnd,
-+                      gss_buffer_desc *ctx_token)
-+{
-+        char        *buf = NULL, *p = NULL, *end = NULL;
-+        unsigned int buf_size = 0;
-+        int          rc;
-+
-+        logmsg(LL_TRACE, "updating kernel key 0x%x\n", keyid);
-+
-+        buf_size = sizeof(lnd->lnd_seq_win) +
-+                   sizeof(lnd->lnd_rmt_ctx.length) + lnd->lnd_rmt_ctx.length +
-+                   sizeof(ctx_token->length) + ctx_token->length;
-+        buf = malloc(buf_size);
-+        if (buf == NULL) {
-+                logmsg(LL_ERR, "failed to alloc key update buf: size %d\n",
-+                       buf_size);
-+                return 1;
-+        }
-+
-+        p = buf;
-+        end = buf + buf_size;
-+        rc = -1;
-+
-+        if (WRITE_BYTES(&p, end, lnd->lnd_seq_win))
-+                goto out;
-+        if (write_buffer(&p, end, &lnd->lnd_rmt_ctx))
-+                goto out;
-+        if (write_buffer(&p, end, ctx_token))
-+                goto out;
-+
-+again:
-+        if (keyctl_update(keyid, buf, p - buf)) {
-+                if (errno != EAGAIN) {
-+                        logmsg(LL_ERR, "failed to update key 0x%x: %s\n",
-+                               keyid, strerror(errno));
-+                        goto out;
-+                }
-+
-+                logmsg(LL_WARN, "update key 0x%x too soon, try again\n", keyid);
-+                sleep(2);
-+                goto again;
-+        }
-+
-+        rc = 0;
-+        logmsg(LL_INFO, "successfully updated key 0x%x\n", keyid);
-+out:
-+        free(buf);
-+        return rc;
-+}
-+
-+/*
-+ * note we can't assume authority in child process
-+ */
-+int lgssc_kr_negotiate(key_serial_t keyid, struct keyring_upcall_param *kup)
-+{
-+        struct lgss_nego_data   lnd;
-+        gss_buffer_desc         token = GSS_C_EMPTY_BUFFER;
-+        OM_uint32               min_stat;
-+        int                     rc;
-+
-+        logmsg(LL_TRACE, "child start on behalf of key 0x%x\n", keyid);
-+
-+        if (kup->kup_gid != 0 && setregid(kup->kup_gid, kup->kup_gid)) {
-+                logmsg(LL_ERR, "key 0x%x, failed set gids to %u: %s\n",
-+                       keyid, kup->kup_gid, strerror(errno));
-+        }
-+
-+        if (kup->kup_uid != 0 && setreuid(kup->kup_uid, kup->kup_uid)) {
-+                logmsg(LL_ERR, "key 0x%x, failed set uids to %u: %s\n",
-+                       keyid, kup->kup_uid, strerror(errno));
-+        }
-+
-+        /*
-+         * link to session keyring, allow the key to be found.
-+         */
-+        if (keyctl_link(keyid, KEY_SPEC_SESSION_KEYRING)) {
-+                logmsg(LL_ERR, "key 0x%x, failed to link to session "
-+                       "keyring: %s\n", keyid, strerror(errno));
-+                error_kernel_key(keyid, -EACCES, 0);
-+                return -1;
-+        }
-+
-+        rc = -1;
-+        if (construct_service(kup)) {
-+                error_kernel_key(keyid, -EACCES, 0);
-+                goto out_unlink;
-+        }
-+
-+        if (1/* kup->kup_uid == 0 FIXME */) {
-+                gssd_setup_krb5_user_gss_ccache(kup->kup_uid, g_service);
-+        }
-+
-+        if (lgssc_init_nego_data(&lnd, kup, LGSS_AUTH_KRB5)) {
-+                error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
-+                goto out_unlink;
-+        }
-+
-+        rc = lgssc_negotiation(&lnd);
-+        if (rc) {
-+                error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
-+                goto out;
-+        }
-+
-+        rc = serialize_context_for_kernel(lnd.lnd_ctx, &token, lnd.lnd_mech);
-+        if (rc) {
-+                error_kernel_key(keyid, rc, lnd.lnd_gss_err);
-+
-+                logmsg(LL_ERR, "failed to export context\n");
-+                goto out;
-+        }
-+
-+        rc = update_kernel_key(keyid,  &lnd, &token);
-+        if (rc)
-+                goto out;
-+
-+        rc = 0;
-+        logmsg(LL_INFO, "key update OK!\n");
-+out:
-+        if (token.length != 0)
-+                gss_release_buffer(&min_stat, &token);
-+
-+        lgssc_fini_nego_data(&lnd);
-+
-+out_unlink:
-+        if (keyctl_unlink(keyid, KEY_SPEC_SESSION_KEYRING)) {
-+                logmsg(LL_ERR, "failed to unlink key %d: %s\n",
-+                       keyid, strerror(errno));
-+        }
-+
-+        return rc;
-+}
-+
-+/****************************************
-+ * main process                         *
-+ ****************************************/
-+
-+int main(int argc, char *argv[])
-+{
-+        struct keyring_upcall_param     uparam;
-+        key_serial_t                    keyid;
-+        key_serial_t                    /*tring, pring, */sring;
-+        key_serial_t                    inst_keyring;
-+        int                             is_root;
-+        pid_t                           child;
-+
-+        if (argc != 10 + 1) {
-+                logmsg(LL_ERR, "Invalid parameter number %d\n", argc);
-+                return 1;
-+        }
-+
-+#if 0
-+        logmsg(LL_TRACE, "OP:       %s\n", argv[1]);
-+        logmsg(LL_TRACE, "KeyID:    %s\n", argv[2]);
-+        logmsg(LL_TRACE, "KeyType:  %s\n", argv[3]);
-+        logmsg(LL_TRACE, "KeyDesc:  %s\n", argv[4]);
-+        logmsg(LL_TRACE, "COInfo:   %s\n", argv[5]);
-+        logmsg(LL_TRACE, "UID:      %s\n", argv[6]);
-+        logmsg(LL_TRACE, "GID:      %s\n", argv[7]);
-+        logmsg(LL_TRACE, "TKeyring: %s\n", argv[8]);
-+        logmsg(LL_TRACE, "PKeyring: %s\n", argv[9]);
-+        logmsg(LL_TRACE, "SKeyring: %s\n", argv[10]);
-+#endif
-+        logmsg(LL_INFO, "[%u/%u]: key %s, desc %s, uid %s, sring %s\n",
-+               getuid(), geteuid(),
-+               argv[2], argv[4], argv[6], argv[10]);
-+
-+        memset(&uparam, 0, sizeof(uparam));
-+
-+        if (strcmp(argv[1], "create") != 0) {
-+                logmsg(LL_ERR, "invalid OP %s\n", argv[1]);
-+                return 1;
-+        }
-+
-+        if (sscanf(argv[2], "%d", &keyid) != 1) {
-+                logmsg(LL_ERR, "can't extract KeyID\n");
-+                return 1;
-+        }
-+
-+        if (sscanf(argv[6], "%d", &uparam.kup_uid) != 1) {
-+                logmsg(LL_ERR, "can't extract uid\n");
-+                return 1;
-+        }
-+
-+        if (sscanf(argv[10], "%d", &sring) != 1) {
-+                logmsg(LL_ERR, "can't extract session keyring\n");
-+                return 1;
-+        }
-+
-+        if (sscanf(argv[5], "%d:%d:%Lx:%s", &is_root, &uparam.kup_svc,
-+                   &uparam.kup_nid, uparam.kup_tgt) != 4) {
-+                logmsg(LL_ERR, "can't extract callout info: %s\n", argv[5]);
-+                return 1;
-+        }
-+        logmsg(LL_INFO, "coinfo: fl %d, svc %d, nid 0x%Lx, tgt %s\n",
-+               is_root, uparam.kup_svc, uparam.kup_nid, uparam.kup_tgt);
-+
-+        if (is_root)
-+                inst_keyring = 0;
-+        else
-+                inst_keyring = KEY_SPEC_SESSION_KEYRING;
-+
-+        if (keyctl_instantiate(keyid, NULL, 0, inst_keyring)) {
-+                logmsg(LL_ERR, "key instantiate: %s\n", strerror(errno));
-+                return 1;
-+        }
-+
-+        child = fork();
-+        if (child == -1) {
-+                logmsg(LL_ERR, "can't create child: %s\n", strerror(errno));
-+                return 1;
-+        } else if (child == 0) {
-+                return lgssc_kr_negotiate(keyid, &uparam);
-+        }
-+
-+        return 0;
-+}
-diff -rNup nfs-utils-1.0.10/utils/gssd/l_idmap.c nfs-utils-1.0.10.lustre/utils/gssd/l_idmap.c
---- nfs-utils-1.0.10/utils/gssd/l_idmap.c      1969-12-31 17:00:00.000000000 -0700
-+++ nfs-utils-1.0.10.lustre/utils/gssd/l_idmap.c       2007-05-15 13:01:35.000000000 -0600
-@@ -0,0 +1,37 @@
-+#include <sys/types.h>
-+#include <stdlib.h>
-+#include <stdio.h>
-+
-+#include "lsupport.h"
-+
-+int main(int argc, char **argv)
-+{
-+      lnet_nid_t nid;
-+      uid_t uid;
-+      int rc;
-+
-+      if (argc < 3) {
-+              printf("Usage:\n"
-+                     "%s <princ> <nid>\n",
-+                     basename(argv[0]));
-+              return 1;
-+      }
-+
-+      nid = libcfs_str2nid(argv[2]);
-+      if (nid == LNET_NID_ANY) {
-+              printf("parse nid %s failed\n", argv[2]);
-+              return 1;
-+      }
-+      rc = lookup_mapping(argv[1], nid, &uid);
-+      if (rc == -1) {
-+              printf("lookup mapping failed\n");
-+              return 1;
-+      }
-+
-+      printf("principal: %s\n"
-+             "nid:       %#llx\n"
-+             "uid:       %u\n",
-+             argv[1], nid, uid);
-+
-+      return 0;
-+}
-diff -rNup nfs-utils-1.0.10/utils/gssd/lsupport.c nfs-utils-1.0.10.lustre/utils/gssd/lsupport.c
---- nfs-utils-1.0.10/utils/gssd/lsupport.c     1969-12-31 17:00:00.000000000 -0700
-+++ nfs-utils-1.0.10.lustre/utils/gssd/lsupport.c      2007-05-15 13:01:35.000000000 -0600
-@@ -0,0 +1,781 @@
-+/*
-+ *  Copyright (c) 2005 Cluster File Systems, Inc.
-+ *
-+ *   This file is part of Lustre, http://www.lustre.org.
-+ *
-+ *   Lustre is free software; you can redistribute it and/or
-+ *   modify it under the terms of version 2 of the GNU General Public
-+ *   License as published by the Free Software Foundation.
-+ *
-+ *   Lustre is distributed in the hope that it will be useful,
-+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *   GNU General Public License for more details.
-+ *
-+ *   You should have received a copy of the GNU General Public License
-+ *   along with Lustre; if not, write to the Free Software
-+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+#ifndef _GNU_SOURCE
-+#define _GNU_SOURCE
-+#endif
-+#include "config.h"
-+#include <sys/param.h>
-+#include <sys/utsname.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <arpa/inet.h>
-+#include <sys/types.h>
-+#include <sys/ipc.h>
-+#include <sys/sem.h>
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <pwd.h>
-+#include <grp.h>
-+#include <string.h>
-+#include <dirent.h>
-+#include <poll.h>
-+#include <fcntl.h>
-+#include <signal.h>
-+#include <unistd.h>
-+#include <errno.h>
-+#include <assert.h>
-+#ifdef HAVE_GETHOSTBYNAME
-+# include <netdb.h>
-+#endif
-+
-+#include "err_util.h"
-+#include "gssd.h"
-+#include "lsupport.h"
-+
-+/****************************************
-+ * exclusive startup                    *
-+ ****************************************/
-+
-+static struct __sem_s {
-+        char           *name;
-+        key_t           sem_key;
-+        int             sem_id;
-+} sems[2] = {
-+        [GSSD_CLI] = { "client",  0x3a92d473, 0 },
-+        [GSSD_SVC] = { "server",  0x3b92d473, 0 },
-+};
-+
-+void gssd_init_unique(int type)
-+{
-+        struct __sem_s *sem = &sems[type];
-+        struct sembuf   sembuf;
-+
-+        assert(type == GSSD_CLI || type == GSSD_SVC);
-+
-+again:
-+        sem->sem_id = semget(sem->sem_key, 1, IPC_CREAT | IPC_EXCL | 0700);
-+        if (sem->sem_id == -1) {
-+                if (errno != EEXIST) {
-+                        printerr(0, "Create sem: %s\n", strerror(errno));
-+                        exit(-1);
-+                }
-+
-+                /* already exist. Note there's still a small window racing
-+                 * with other processes, due to the stupid semaphore semantics.
-+                 */
-+                sem->sem_id = semget(sem->sem_key, 0, 0700);
-+                if (sem->sem_id == -1) {
-+                        if (errno == ENOENT) {
-+                                printerr(0, "another instance just exit, "
-+                                         "try again\n");
-+                                goto again;
-+                        }
-+
-+                        printerr(0, "Obtain sem: %s\n", strerror(errno));
-+                        exit(-1);
-+                }
-+        } else {
-+                int val = 1;
-+
-+                if (semctl(sem->sem_id, 0, SETVAL, val) == -1) {
-+                        printerr(0, "Initialize sem: %s\n",
-+                                 strerror(errno));
-+                        exit(-1);
-+                }
-+        }
-+
-+        sembuf.sem_num = 0;
-+        sembuf.sem_op = -1;
-+        sembuf.sem_flg = IPC_NOWAIT | SEM_UNDO;
-+
-+        if (semop(sem->sem_id, &sembuf, 1) != 0) {
-+                if (errno == EAGAIN) {
-+                        printerr(0, "Another instance is running, exit\n");
-+                        exit(0);
-+                }
-+                printerr(0, "Grab sem: %s\n", strerror(errno));
-+                exit(0);
-+        }
-+
-+        printerr(2, "Successfully created %s global identity\n", sem->name);
-+}
-+
-+void gssd_exit_unique(int type)
-+{
-+        assert(type == GSSD_CLI || type == GSSD_SVC);
-+
-+        /*
-+         * do nothing. we can't remove the sem here, otherwise the race
-+         * window would be much bigger. So it's sad we have to leave the
-+         * sem in the system forever.
-+         */
-+}
-+
-+/****************************************
-+ * client side resolvation:             *
-+ *    lnd/netid/nid => hostname         *
-+ ****************************************/
-+
-+char gethostname_ex[PATH_MAX] = GSSD_DEFAULT_GETHOSTNAME_EX;
-+
-+typedef int lnd_nid2hostname_t(char *lnd, uint32_t net, uint32_t addr,
-+                               char *buf, int buflen);
-+
-+/* FIXME what about IPv6? */
-+static
-+int socklnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
-+                         char *buf, int buflen)
-+{
-+        struct hostent  *ent;
-+
-+        addr = htonl(addr);
-+        ent = gethostbyaddr(&addr, sizeof(addr), AF_INET);
-+        if (!ent) {
-+                printerr(0, "%s: can't resolve 0x%x\n", lnd, addr);
-+                return -1;
-+        }
-+        if (strlen(ent->h_name) >= buflen) {
-+                printerr(0, "%s: name too long: %s\n", lnd, ent->h_name);
-+                return -1;
-+        }
-+        strcpy(buf, ent->h_name);
-+
-+        printerr(2, "%s: net 0x%x, addr 0x%x => %s\n",
-+                 lnd, net, addr, buf);
-+        return 0;
-+}
-+
-+static
-+int lolnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
-+                       char *buf, int buflen)
-+{
-+        struct utsname   uts;
-+        struct hostent  *ent;
-+
-+        if (addr) {
-+                printerr(0, "%s: addr is 0x%x, we expect 0\n", lnd, addr);
-+                return -1;
-+        }
-+
-+        if (uname(&uts)) {
-+                printerr(0, "%s: failed obtain local machine name\n", lnd);
-+                return -1;
-+        }
-+
-+        ent = gethostbyname(uts.nodename);
-+        if (!ent) {
-+                printerr(0, "%s: failed obtain canonical name of %s\n",
-+                         lnd, uts.nodename);
-+                return -1;
-+        }
-+
-+        if (strlen(ent->h_name) >= buflen) {
-+                printerr(0, "%s: name too long: %s\n", lnd, ent->h_name);
-+                return -1;
-+        }
-+        strcpy(buf, ent->h_name);
-+
-+        printerr(2, "%s: addr 0x%x => %s\n", lnd, addr, buf);
-+        return 0;
-+}
-+
-+static int is_space(char c)
-+{
-+        return (c == ' ' || c == '\t' || c == '\n');
-+}
-+
-+static
-+int external_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
-+                          char *namebuf, int namebuflen)
-+{
-+        const int bufsize = PATH_MAX + 256;
-+        char buf[bufsize], *head, *tail;
-+        FILE *fghn;
-+
-+        sprintf(buf, "%s %s 0x%x 0x%x", gethostname_ex, lnd, net, addr);
-+        printerr(2, "cmd: %s\n", buf);
-+
-+        fghn = popen(buf, "r");
-+        if (fghn == NULL) {
-+                printerr(0, "failed to call %s\n", gethostname_ex);
-+                return -1;
-+        }
-+
-+        head = fgets(buf, bufsize, fghn);
-+        if (head == NULL) {
-+                printerr(0, "can't read from %s\n", gethostname_ex);
-+                return -1;
-+        }
-+        if (pclose(fghn) == -1)
-+                printerr(1, "pclose failed, continue\n");
-+
-+        /* trim head/tail space */
-+        while (is_space(*head))
-+                head++;
-+
-+        tail = head + strlen(head);
-+        if (tail <= head) {
-+                printerr(0, "no output from %s\n", gethostname_ex);
-+                return -1;
-+        }
-+        while (is_space(*(tail - 1)))
-+                tail--;
-+        if (tail <= head) {
-+                printerr(0, "output are all space from %s\n", gethostname_ex);
-+                return -1;
-+        }
-+        *tail = '\0';
-+
-+        /* start with '@' means error msg */
-+        if (head[0] == '@') {
-+                printerr(0, "error from %s: %s\n", gethostname_ex, &head[1]);
-+                return -1;
-+        }
-+
-+        if (tail - head > namebuflen) {
-+                printerr(0, "external hostname too long: %s\n", head);
-+                return -1;
-+        }
-+
-+        printerr(2, "%s: net 0x%x, addr 0x%x => %s\n",
-+                 lnd, net, addr, head);
-+        strcpy(namebuf, head);
-+        return 0;
-+}
-+
-+static struct {
-+        char                    *name;
-+        lnd_nid2hostname_t      *nid2name;
-+} converter[LND_ENUM_END_MARKER] = {
-+        {"UNUSED0",     NULL},
-+        [QSWLND]        = { "QSWLND",   external_nid2hostname},
-+        [SOCKLND]       = { "SOCKLND",  socklnd_nid2hostname },
-+        [GMLND]         = { "GMLND",    external_nid2hostname},
-+        [PTLLND]        = { "PTLLND",   external_nid2hostname },
-+        [O2IBLND]       = { "O2IBLND",  socklnd_nid2hostname }, /* XXX */
-+        [CIBLND]        = { "CIBLND",   external_nid2hostname },
-+        [OPENIBLND]     = { "OPENIBLND",external_nid2hostname },
-+        [IIBLND]        = { "IIBLND",   external_nid2hostname },
-+        [LOLND]         = { "LOLND",    lolnd_nid2hostname },
-+        [RALND]         = { "RALND",    external_nid2hostname },
-+        [VIBLND]        = { "VIBLND",   external_nid2hostname },
-+};
-+
-+int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen)
-+{
-+        uint32_t lnd, net, addr;
-+
-+        addr = LNET_NIDADDR(nid);
-+        net = LNET_NIDNET(nid);
-+        lnd = LNET_NETTYP(net);
-+
-+        if (lnd >= LND_ENUM_END_MARKER) {
-+                printerr(0, "ERROR: Unrecognized LND %u\n", lnd);
-+                return -1;
-+        }
-+
-+        if (converter[lnd].nid2name == NULL) {
-+                printerr(0, "ERROR: %s converter not ready\n",
-+                        converter[lnd].name);
-+                return -1;
-+        }
-+
-+        return converter[lnd].nid2name(converter[lnd].name, net, addr,
-+                                       buf, buflen);
-+}
-+
-+
-+/****************************************
-+ * lnet support routine                 *
-+ * (from lnet/libcfs/nidstrings.c       *
-+ ****************************************/
-+
-+#define LNET_NIDSTR_SIZE   32      /* size of each one (see below for usage) */
-+
-+static int  libcfs_lo_str2addr(char *str, int nob, uint32_t *addr);
-+static void libcfs_ip_addr2str(uint32_t addr, char *str);
-+static int  libcfs_ip_str2addr(char *str, int nob, uint32_t *addr);
-+static void libcfs_decnum_addr2str(uint32_t addr, char *str);
-+static void libcfs_hexnum_addr2str(uint32_t addr, char *str);
-+static int  libcfs_num_str2addr(char *str, int nob, uint32_t *addr);
-+
-+struct netstrfns {
-+        int          nf_type;
-+        char        *nf_name;
-+        char        *nf_modname;
-+        void       (*nf_addr2str)(uint32_t addr, char *str);
-+        int        (*nf_str2addr)(char *str, int nob, uint32_t *addr);
-+};
-+
-+static struct netstrfns  libcfs_netstrfns[] = {
-+        {/* .nf_type      */  LOLND,
-+         /* .nf_name      */  "lo",
-+         /* .nf_modname   */  "klolnd",
-+         /* .nf_addr2str  */  libcfs_decnum_addr2str,
-+         /* .nf_str2addr  */  libcfs_lo_str2addr},
-+        {/* .nf_type      */  SOCKLND,
-+         /* .nf_name      */  "tcp",
-+         /* .nf_modname   */  "ksocklnd",
-+         /* .nf_addr2str  */  libcfs_ip_addr2str,
-+         /* .nf_str2addr  */  libcfs_ip_str2addr},
-+        {/* .nf_type      */  O2IBLND,
-+         /* .nf_name      */  "o2ib",
-+         /* .nf_modname   */  "ko2iblnd",
-+         /* .nf_addr2str  */  libcfs_ip_addr2str,
-+         /* .nf_str2addr  */  libcfs_ip_str2addr},
-+        {/* .nf_type      */  CIBLND,
-+         /* .nf_name      */  "cib",
-+         /* .nf_modname   */  "kciblnd",
-+         /* .nf_addr2str  */  libcfs_ip_addr2str,
-+         /* .nf_str2addr  */  libcfs_ip_str2addr},
-+        {/* .nf_type      */  OPENIBLND,
-+         /* .nf_name      */  "openib",
-+         /* .nf_modname   */  "kopeniblnd",
-+         /* .nf_addr2str  */  libcfs_ip_addr2str,
-+         /* .nf_str2addr  */  libcfs_ip_str2addr},
-+        {/* .nf_type      */  IIBLND,
-+         /* .nf_name      */  "iib",
-+         /* .nf_modname   */  "kiiblnd",
-+         /* .nf_addr2str  */  libcfs_ip_addr2str,
-+         /* .nf_str2addr  */  libcfs_ip_str2addr},
-+        {/* .nf_type      */  VIBLND,
-+         /* .nf_name      */  "vib",
-+         /* .nf_modname   */  "kviblnd",
-+         /* .nf_addr2str  */  libcfs_ip_addr2str,
-+         /* .nf_str2addr  */  libcfs_ip_str2addr},
-+        {/* .nf_type      */  RALND,
-+         /* .nf_name      */  "ra",
-+         /* .nf_modname   */  "kralnd",
-+         /* .nf_addr2str  */  libcfs_ip_addr2str,
-+         /* .nf_str2addr  */  libcfs_ip_str2addr},
-+        {/* .nf_type      */  QSWLND,
-+         /* .nf_name      */  "elan",
-+         /* .nf_modname   */  "kqswlnd",
-+         /* .nf_addr2str  */  libcfs_decnum_addr2str,
-+         /* .nf_str2addr  */  libcfs_num_str2addr},
-+        {/* .nf_type      */  GMLND,
-+         /* .nf_name      */  "gm",
-+         /* .nf_modname   */  "kgmlnd",
-+         /* .nf_addr2str  */  libcfs_hexnum_addr2str,
-+         /* .nf_str2addr  */  libcfs_num_str2addr},
-+        {/* .nf_type      */  PTLLND,
-+         /* .nf_name      */  "ptl",
-+         /* .nf_modname   */  "kptllnd",
-+         /* .nf_addr2str  */  libcfs_decnum_addr2str,
-+         /* .nf_str2addr  */  libcfs_num_str2addr},
-+        /* placeholder for net0 alias.  It MUST BE THE LAST ENTRY */
-+        {/* .nf_type      */  -1},
-+};
-+
-+const int libcfs_nnetstrfns = sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]);
-+
-+static int
-+libcfs_lo_str2addr(char *str, int nob, uint32_t *addr)
-+{
-+        *addr = 0;
-+        return 1;
-+}
-+
-+static void
-+libcfs_ip_addr2str(uint32_t addr, char *str)
-+{
-+        snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u",
-+                 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
-+                 (addr >> 8) & 0xff, addr & 0xff);
-+}
-+
-+/* CAVEAT EMPTOR XscanfX
-+ * I use "%n" at the end of a sscanf format to detect trailing junk.  However
-+ * sscanf may return immediately if it sees the terminating '0' in a string, so
-+ * I initialise the %n variable to the expected length.  If sscanf sets it;
-+ * fine, if it doesn't, then the scan ended at the end of the string, which is
-+ * fine too :) */
-+
-+static int
-+libcfs_ip_str2addr(char *str, int nob, uint32_t *addr)
-+{
-+        int   a;
-+        int   b;
-+        int   c;
-+        int   d;
-+        int   n = nob;                          /* XscanfX */
-+
-+        /* numeric IP? */
-+        if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
-+            n == nob &&
-+            (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
-+            (c & ~0xff) == 0 && (d & ~0xff) == 0) {
-+                *addr = ((a<<24)|(b<<16)|(c<<8)|d);
-+                return 1;
-+        }
-+
-+#ifdef HAVE_GETHOSTBYNAME
-+        /* known hostname? */
-+        if (('a' <= str[0] && str[0] <= 'z') ||
-+            ('A' <= str[0] && str[0] <= 'Z')) {
-+                char *tmp;
-+
-+                tmp = malloc(nob + 1);
-+                if (tmp != NULL) {
-+                        struct hostent *he;
-+
-+                        memcpy(tmp, str, nob);
-+                        tmp[nob] = 0;
-+
-+                        he = gethostbyname(tmp);
-+
-+                        free(tmp);
-+                        tmp = NULL;
-+
-+                        if (he != NULL) {
-+                                uint32_t ip = *(uint32_t *)he->h_addr;
-+
-+                                *addr = ntohl(ip);
-+                                return 1;
-+                        }
-+                }
-+        }
-+#endif
-+        return 0;
-+}
-+
-+static void
-+libcfs_decnum_addr2str(uint32_t addr, char *str)
-+{
-+        snprintf(str, LNET_NIDSTR_SIZE, "%u", addr);
-+}
-+
-+static void
-+libcfs_hexnum_addr2str(uint32_t addr, char *str)
-+{
-+        snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr);
-+}
-+
-+static int
-+libcfs_num_str2addr(char *str, int nob, uint32_t *addr)
-+{
-+        int     n;
-+
-+        n = nob;
-+        if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
-+                return 1;
-+
-+        n = nob;
-+        if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
-+                return 1;
-+
-+        n = nob;
-+        if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
-+                return 1;
-+        
-+        return 0;
-+}
-+
-+static struct netstrfns *
-+libcfs_lnd2netstrfns(int lnd)
-+{
-+        int    i;
-+
-+        if (lnd >= 0)
-+                for (i = 0; i < libcfs_nnetstrfns; i++)
-+                        if (lnd == libcfs_netstrfns[i].nf_type)
-+                                return &libcfs_netstrfns[i];
-+
-+        return NULL;
-+}
-+
-+static struct netstrfns *
-+libcfs_str2net_internal(char *str, uint32_t *net)
-+{
-+        struct netstrfns *nf;
-+        int               nob;
-+        int               netnum;
-+        int               i;
-+
-+        for (i = 0; i < libcfs_nnetstrfns; i++) {
-+                nf = &libcfs_netstrfns[i];
-+                if (nf->nf_type >= 0 &&
-+                    !strncmp(str, nf->nf_name, strlen(nf->nf_name)))
-+                        break;
-+        }
-+
-+        if (i == libcfs_nnetstrfns)
-+                return NULL;
-+
-+        nob = strlen(nf->nf_name);
-+
-+        if (strlen(str) == (unsigned int)nob) {
-+                netnum = 0;
-+        } else {
-+                if (nf->nf_type == LOLND) /* net number not allowed */
-+                        return NULL;
-+
-+                str += nob;
-+                i = strlen(str);
-+                if (sscanf(str, "%u%n", &netnum, &i) < 1 ||
-+                    i != (int)strlen(str))
-+                        return NULL;
-+        }
-+
-+        *net = LNET_MKNET(nf->nf_type, netnum);
-+        return nf;
-+}
-+
-+lnet_nid_t
-+libcfs_str2nid(char *str)
-+{
-+        char             *sep = strchr(str, '@');
-+        struct netstrfns *nf;
-+        uint32_t             net;
-+        uint32_t             addr;
-+
-+        if (sep != NULL) {
-+                nf = libcfs_str2net_internal(sep + 1, &net);
-+                if (nf == NULL)
-+                        return LNET_NID_ANY;
-+        } else {
-+                sep = str + strlen(str);
-+                net = LNET_MKNET(SOCKLND, 0);
-+                nf = libcfs_lnd2netstrfns(SOCKLND);
-+                if (!nf)
-+                        return LNET_NID_ANY;
-+        }
-+
-+        if (!nf->nf_str2addr(str, sep - str, &addr))
-+                return LNET_NID_ANY;
-+
-+        return LNET_MKNID(net, addr);
-+}
-+
-+/****************************************
-+ * user mapping database handling       *
-+ * (very rudiment)                      *
-+ ****************************************/
-+
-+#define MAPPING_GROW_SIZE       512
-+#define MAX_LINE_LEN            256
-+
-+struct user_map_item {
-+        char        *principal; /* NULL means match all, will cause multi->single mapped, FORBID */
-+        lnet_nid_t   nid;
-+        uid_t        uid;
-+};
-+
-+struct user_mapping {
-+        int                   nitems;
-+        struct user_map_item *items;
-+};
-+
-+static struct user_mapping mapping = {0, NULL};
-+/* FIXME to be finished: monitor change of mapping database */
-+static int mapping_mtime = 0;
-+
-+void cleanup_mapping(void)
-+{
-+        if (mapping.items) {
-+                for (; mapping.nitems > 0; mapping.nitems--)
-+                        free(mapping.items[mapping.nitems - 1].principal);
-+                free(mapping.items);
-+                mapping.items = NULL;
-+        }
-+}
-+
-+static int grow_mapping(int nitems)
-+{
-+        struct user_map_item *new;
-+        int oldsize, newsize;
-+
-+        oldsize = (mapping.nitems * sizeof(struct user_map_item) +
-+                   MAPPING_GROW_SIZE - 1) / MAPPING_GROW_SIZE;
-+        newsize = (nitems * sizeof(struct user_map_item) +
-+                   MAPPING_GROW_SIZE - 1) / MAPPING_GROW_SIZE;
-+        while (newsize <= oldsize)
-+                return 0;
-+
-+        newsize *= MAPPING_GROW_SIZE;
-+        new = malloc(newsize);
-+        if (!new) {
-+                printerr(0, "can't alloc mapping size %d\n", newsize);
-+                return -1;
-+        }
-+
-+        if (mapping.items) {
-+                memcpy(new, mapping.items, mapping.nitems * sizeof(struct user_map_item));
-+                free(mapping.items);
-+        }
-+        mapping.items = new;
-+        return 0;
-+}
-+
-+uid_t parse_uid(char *uidstr)
-+{
-+        struct passwd *pw;
-+        char *p = NULL;
-+        long uid;
-+
-+        pw = getpwnam(uidstr);
-+        if (pw)
-+                return pw->pw_uid;
-+
-+        uid = strtol(uidstr, &p, 0);
-+        if (*p == '\0')
-+                return (uid_t) uid;
-+
-+        return -1;
-+}
-+
-+static int read_mapping_db(void)
-+{
-+        char princ[MAX_LINE_LEN];
-+        char nid_str[MAX_LINE_LEN];
-+        char dest[MAX_LINE_LEN];
-+        char linebuf[MAX_LINE_LEN];
-+        char *line;
-+        lnet_nid_t nid;
-+        uid_t dest_uid;
-+        FILE *f;
-+
-+        /* cleanup old mappings */
-+        cleanup_mapping();
-+
-+        f = fopen(MAPPING_DATABASE_FILE, "r");
-+        if (!f) {
-+                printerr(0, "can't open mapping database: %s\n",
-+                         MAPPING_DATABASE_FILE);
-+                return -1;
-+        }
-+
-+        while ((line = fgets(linebuf, MAX_LINE_LEN, f)) != NULL) {
-+                char *name;
-+
-+                if (strlen(line) >= MAX_LINE_LEN) {
-+                        printerr(0, "invalid mapping db: line too long (%d)\n",
-+                                 strlen(line));
-+                        continue;
-+                }
-+
-+                if (sscanf(line, "%s %s %s", princ, nid_str, dest) != 3) {
-+                        printerr(0, "mapping db: syntax error\n");
-+                        continue;
-+                }
-+
-+                if (!strcmp(princ, "*")) {
-+                        printerr(0, "NOT permit \"*\" princ, it will cause multi->single mapped\n");
-+                        continue;
-+                } else {
-+                        name = strdup(princ);
-+                        if (!name) {
-+                                printerr(0, "fail to dup str %s\n", princ);
-+                                continue;
-+                        }
-+                }
-+
-+                if (!strcmp(nid_str, "*")) {
-+                        nid = LNET_NID_ANY;
-+                } else {
-+                        nid = libcfs_str2nid(nid_str);
-+                        if (nid == LNET_NID_ANY) {
-+                                printerr(0, "fail to parse nid %s\n", nid_str);
-+                                free(name);
-+                                continue;
-+                        }
-+                }
-+
-+                dest_uid = parse_uid(dest);
-+                if (dest_uid == -1) {
-+                        printerr(0, "no valid user: %s\n", dest);
-+                        free(name);
-+                        continue;
-+                }
-+
-+                if (grow_mapping(mapping.nitems + 1)) {
-+                        printerr(0, "fail to grow mapping to %d\n",
-+                                 mapping.nitems + 1);
-+                        free(name);
-+                        fclose(f);
-+                        return -1;
-+                }
-+
-+                mapping.items[mapping.nitems].principal = name;
-+                mapping.items[mapping.nitems].nid = nid;
-+                mapping.items[mapping.nitems].uid = dest_uid;
-+                mapping.nitems++;
-+                printerr(1, "add mapping: %s(%s/0x%llx) ==> %d\n",
-+                         name, nid_str, nid, dest_uid);
-+        }
-+
-+        fclose(f);
-+        return 0;
-+}
-+
-+static inline int mapping_changed(void)
-+{
-+        struct stat st;
-+
-+        if (stat(MAPPING_DATABASE_FILE, &st) == -1) {
-+                /* stat failed, treat it like doesn't exist or be removed */
-+                if (mapping_mtime == 0) {
-+                        return 0;
-+                } else {
-+                        printerr(0, "Warning: stat %s failed: %s\n",
-+                                 MAPPING_DATABASE_FILE, strerror(errno));
-+
-+                        mapping_mtime = 0;
-+                        return 1;
-+                }
-+        }
-+
-+        if (st.st_mtime != mapping_mtime) {
-+                mapping_mtime = st.st_mtime;
-+                return 1;
-+        }
-+
-+        return 0;
-+}
-+
-+int lookup_mapping(char *princ, lnet_nid_t nid, uid_t *uid)
-+{
-+        int n;
-+
-+        *uid = -1;
-+
-+        /* FIXME race condition here */
-+        if (mapping_changed()) {
-+                if (read_mapping_db())
-+                        printerr(0, "all remote users will be denied\n");
-+        }
-+
-+        for (n = 0; n < mapping.nitems; n++) {
-+                struct user_map_item *entry = &mapping.items[n];
-+
-+                if (entry->nid != LNET_NID_ANY && entry->nid != nid)
-+                        continue;
-+                if (!strcasecmp(entry->principal, princ)) {
-+                        printerr(1, "found mapping: %s ==> %d\n",
-+                                 princ, entry->uid);
-+                        *uid = entry->uid;
-+                        return 0;
-+                }
-+        }
-+
-+        printerr(2, "no mapping for %s/%#Lx\n", princ, nid);
-+        return -1;
-+}
-diff -rNup nfs-utils-1.0.10/utils/gssd/lsupport.h nfs-utils-1.0.10.lustre/utils/gssd/lsupport.h
---- nfs-utils-1.0.10/utils/gssd/lsupport.h     1969-12-31 17:00:00.000000000 -0700
-+++ nfs-utils-1.0.10.lustre/utils/gssd/lsupport.h      2007-05-15 13:01:35.000000000 -0600
-@@ -0,0 +1,85 @@
-+#ifndef __LIBCFS_H__
-+#define __LIBCFS_H__
-+
-+#include <unistd.h>
-+#include <stdint.h>
-+
-+#define GSSD_CLI        (0)
-+#define GSSD_SVC        (1)
-+
-+void gssd_init_unique(int type);
-+void gssd_exit_unique(int type);
-+
-+/*
-+ * copied from lustre source
-+ */
-+
-+#define LUSTRE_GSS_SVC_MDS      0
-+#define LUSTRE_GSS_SVC_OSS      1
-+
-+struct lgssd_upcall_data {
-+        uint32_t        seq;
-+        uint32_t        uid;
-+        uint32_t        gid;
-+        uint32_t        svc;
-+        uint64_t        nid;
-+        char            obd[64];
-+};
-+
-+#define GSSD_INTERFACE_VERSION        (1)
-+
-+struct lgssd_ioctl_param {
-+        int             version;        /* in   */
-+        char           *uuid;           /* in   */
-+        int             lustre_svc;     /* in   */
-+        uid_t           uid;            /* in   */
-+        gid_t           gid;            /* in   */
-+        long            send_token_size;/* in   */
-+        char           *send_token;     /* in   */
-+        long            reply_buf_size; /* in   */
-+        char           *reply_buf;      /* in   */
-+        long            status;         /* out  */
-+        long            reply_length;   /* out  */
-+};
-+
-+#define GSSD_DEFAULT_GETHOSTNAME_EX     "/etc/lustre/nid2hostname"
-+#define MAPPING_DATABASE_FILE           "/etc/lustre/idmap.conf"
-+
-+typedef uint64_t lnet_nid_t;
-+typedef uint32_t lnet_netid_t;
-+
-+#define LNET_NID_ANY      ((lnet_nid_t) -1)
-+#define LNET_PID_ANY      ((lnet_pid_t) -1)
-+
-+enum {
-+        /* Only add to these values (i.e. don't ever change or redefine them):
-+         * network addresses depend on them... */
-+        QSWLND    = 1,
-+        SOCKLND   = 2,
-+        GMLND     = 3,
-+        PTLLND    = 4,
-+        O2IBLND   = 5,
-+        CIBLND    = 6,
-+        OPENIBLND = 7,
-+        IIBLND    = 8,
-+        LOLND     = 9,
-+        RALND     = 10,
-+        VIBLND    = 11,
-+        LND_ENUM_END_MARKER
-+};
-+
-+int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen);
-+void cleanup_mapping(void);
-+int lookup_mapping(char *princ, uint64_t nid, uid_t *uid);
-+lnet_nid_t libcfs_str2nid(char *str);
-+
-+/* how an LNET NID encodes net:address */
-+#define LNET_NIDADDR(nid)      ((uint32_t)((nid) & 0xffffffff))
-+#define LNET_NIDNET(nid)       ((uint32_t)(((nid) >> 32)) & 0xffffffff)
-+#define LNET_MKNID(net,addr)   ((((uint64_t)(net))<<32)|((uint64_t)(addr)))
-+/* how net encodes type:number */
-+#define LNET_NETNUM(net)       ((net) & 0xffff)
-+#define LNET_NETTYP(net)       (((net) >> 16) & 0xffff)
-+#define LNET_MKNET(typ,num)    ((((uint32_t)(typ))<<16)|((uint32_t)(num)))
-+
-+#endif /* __LIBCFS_H__ */
-diff -rNup nfs-utils-1.0.10/utils/gssd/Makefile.am nfs-utils-1.0.10.lustre/utils/gssd/Makefile.am
---- nfs-utils-1.0.10/utils/gssd/Makefile.am    2007-05-15 13:02:26.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/Makefile.am     2007-05-15 13:00:53.000000000 -0600
-@@ -1,17 +1,11 @@
- ## Process this file with automake to produce Makefile.in
--man8_MANS     = gssd.man svcgssd.man
--
--RPCPREFIX     = rpc.
-+RPCPREFIX     = 
- KPREFIX               = @kprefix@
--sbin_PREFIXED = gssd svcgssd
--sbin_PROGRAMS = $(sbin_PREFIXED) gss_clnt_send_err
-+sbin_PREFIXED = lgssd lsvcgssd
-+sbin_PROGRAMS = $(sbin_PREFIXED)
- sbin_SCRIPTS  = gss_destroy_creds
--EXTRA_DIST = \
--      gss_destroy_creds \
--      $(man8_MANS)
--
- COMMON_SRCS = \
-       context.c \
-       context_mit.c \
-@@ -21,13 +15,15 @@ COMMON_SRCS = \
-       gss_util.c \
-       gss_oids.c \
-       err_util.c \
-+      lsupport.c \
-       \
-       context.h \
-       err_util.h \
-       gss_oids.h \
--      gss_util.h
-+      gss_util.h \
-+      lsupport.h
--gssd_SOURCES = \
-+lgssd_SOURCES = \
-       $(COMMON_SRCS) \
-       gssd.c \
-       gssd_main_loop.c \
-@@ -38,13 +34,12 @@ gssd_SOURCES = \
-       krb5_util.h \
-       write_bytes.h
--gssd_LDADD = $(RPCSECGSS_LIBS) $(KRBLIBS)
--gssd_LDFLAGS = $(KRBLDFLAGS)
-+lgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
-+lgssd_LDFLAGS = $(KRBLDFLAGS)
--gssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
--            $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
-+lgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
--svcgssd_SOURCES = \
-+lsvcgssd_SOURCES = \
-       $(COMMON_SRCS) \
-       cacheio.c \
-       svcgssd.c \
-@@ -55,20 +50,11 @@ svcgssd_SOURCES = \
-       cacheio.h \
-       svcgssd.h
--svcgssd_LDADD = \
--      ../../support/nfs/libnfs.a \
--      $(RPCSECGSS_LIBS) -lnfsidmap \
--      $(KRBLIBS)
--
--svcgssd_LDFLAGS = $(KRBLDFLAGS)
--
--svcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
--               $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
-+lsvcgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
--gss_clnt_send_err_SOURCES = gss_clnt_send_err.c
-+lsvcgssd_LDFLAGS = $(KRBLDFLAGS)
--gss_clnt_send_err_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
--               $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
-+lsvcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
- MAINTAINERCLEANFILES = Makefile.in
-@@ -92,23 +78,3 @@ uninstall-hook:
-         done)
--# XXX This makes some assumptions about what automake does.
--# XXX But there is no install-man-hook or install-man-local.
--install-man: install-man8 install-man-links
--uninstall-man: uninstall-man8 uninstall-man-links
--
--install-man-links:
--      (cd $(DESTDIR)$(man8dir) && \
--        for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
--          inst=`echo $$m | sed -e 's/man$$/8/'`; \
--          rm -f $(RPCPREFIX)$$inst ; \
--          $(LN_S) $$inst $(RPCPREFIX)$$inst ; \
--        done)
--
--uninstall-man-links:
--      (cd $(DESTDIR)$(man8dir) && \
--        for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
--          inst=`echo $$m | sed -e 's/man$$/8/'`; \
--          rm -f $(RPCPREFIX)$$inst ; \
--        done)
--
-diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd.c nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.c
---- nfs-utils-1.0.10/utils/gssd/svcgssd.c      2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.c       2007-05-15 13:01:35.000000000 -0600
-@@ -43,7 +43,6 @@
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/socket.h>
--#include <rpc/rpc.h>
- #include <fcntl.h>
- #include <errno.h>
-@@ -54,11 +53,33 @@
- #include <stdlib.h>
- #include <string.h>
- #include <signal.h>
--#include "nfslib.h"
-+#include <dirent.h>
- #include "svcgssd.h"
- #include "gss_util.h"
- #include "err_util.h"
-+#include "lsupport.h"
-+void
-+closeall(int min)
-+{
-+      DIR *dir = opendir("/proc/self/fd");
-+      if (dir != NULL) {
-+              int dfd = dirfd(dir);
-+              struct dirent *d;
-+
-+              while ((d = readdir(dir)) != NULL) {
-+                      char *endp;
-+                      long n = strtol(d->d_name, &endp, 10);
-+                      if (*endp != '\0' && n >= min && n != dfd)
-+                              (void) close(n);
-+              }
-+              closedir(dir);
-+      } else {
-+              int fd = sysconf(_SC_OPEN_MAX);
-+              while (--fd >= min)
-+                      (void) close(fd);
-+      }
-+}
- /*
-  * mydaemon creates a pipe between the partent and child
-  * process. The parent process will wait until the
-@@ -139,6 +160,7 @@ void
- sig_die(int signal)
- {
-       /* destroy krb5 machine creds */
-+      cleanup_mapping();
-       printerr(1, "exiting on signal %d\n", signal);
-       exit(1);
- }
-@@ -165,8 +187,8 @@ main(int argc, char *argv[])
-       int get_creds = 1;
-       int fg = 0;
-       int verbosity = 0;
--      int rpc_verbosity = 0;
-       int opt;
-+      int must_srv_mds = 0, must_srv_oss = 0;
-       extern char *optarg;
-       char *progname;
-@@ -181,8 +203,13 @@ main(int argc, char *argv[])
-                       case 'v':
-                               verbosity++;
-                               break;
--                      case 'r':
--                              rpc_verbosity++;
-+                      case 'm':
-+                              get_creds = 1;
-+                              must_srv_mds = 1;
-+                              break;
-+                      case 'o':
-+                              get_creds = 1;
-+                              must_srv_oss = 1;
-                               break;
-                       default:
-                               usage(argv[0]);
-@@ -196,27 +223,18 @@ main(int argc, char *argv[])
-               progname = argv[0];
-       initerr(progname, verbosity, fg);
--#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
--      authgss_set_debug_level(rpc_verbosity);
--#else
--      if (rpc_verbosity > 0)
--              printerr(0, "Warning: rpcsec_gss library does not "
--                          "support setting debug level\n");
--#endif
-       if (gssd_check_mechs() != 0) {
-               printerr(0, "ERROR: Problem with gssapi library\n");
-               exit(1);
-       }
--      if (!fg)
--              mydaemon(0, 0);
--
--      signal(SIGINT, sig_die);
--      signal(SIGTERM, sig_die);
--      signal(SIGHUP, sig_hup);
-+      if (gssd_get_local_realm()) {
-+              printerr(0, "ERROR: Can't get Local Kerberos realm\n");
-+              exit(1);
-+      }
--      if (get_creds && !gssd_acquire_cred(GSSD_SERVICE_NAME)) {
-+      if (get_creds && gssd_prepare_creds(must_srv_mds, must_srv_oss)) {
-                 printerr(0, "unable to obtain root (machine) credentials\n");
-                 printerr(0, "do you have a keytab entry for "
-                           "nfs/<your.host>@<YOUR.REALM> in "
-@@ -225,9 +243,23 @@ main(int argc, char *argv[])
-       }
-       if (!fg)
-+              mydaemon(0, 0);
-+
-+      /*
-+       * XXX: There is risk of memory leak for missing call
-+       *      cleanup_mapping() for SIGKILL and SIGSTOP.
-+       */
-+      signal(SIGINT, sig_die);
-+      signal(SIGTERM, sig_die);
-+      signal(SIGHUP, sig_hup);
-+
-+      if (!fg)
-               release_parent();
--      gssd_run();
-+      gssd_init_unique(GSSD_SVC);
-+
-+      svcgssd_run();
-+      cleanup_mapping();
-       printerr(0, "gssd_run returned!\n");
-       abort();
- }
-diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd.h nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.h
---- nfs-utils-1.0.10/utils/gssd/svcgssd.h      2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.h       2007-05-15 13:01:35.000000000 -0600
-@@ -35,9 +35,20 @@
- #include <sys/queue.h>
- #include <gssapi/gssapi.h>
--void handle_nullreq(FILE *f);
--void gssd_run(void);
-+int handle_nullreq(FILE *f);
-+void svcgssd_run(void);
-+int gssd_prepare_creds(int must_srv_mds, int must_srv_oss);
-+gss_cred_id_t gssd_select_svc_cred(int lustre_svc);
--#define GSSD_SERVICE_NAME     "nfs"
-+extern char *mds_local_realm;
-+extern char *oss_local_realm;
-+
-+#define GSSD_SERVICE_NAME     "lustre"
-+
-+/* XXX */
-+#define GSSD_SERVICE_MDS                      "lustre_mds"
-+#define GSSD_SERVICE_OSS                      "lustre_oss"
-+#define LUSTRE_ROOT_NAME                      "lustre_root"
-+#define LUSTRE_ROOT_NAMELEN                   11
- #endif /* _RPC_SVCGSSD_H_ */
-diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_main_loop.c
---- nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c    2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_main_loop.c     2007-05-15 13:01:35.000000000 -0600
-@@ -46,46 +46,66 @@
- #include "svcgssd.h"
- #include "err_util.h"
-+/*
-+ * nfs4 in-kernel cache implementation make upcall failed directly
-+ * if there's no listener detected. so here we should keep the init
-+ * channel file open as possible as we can.
-+ *
-+ * unfortunately the proc doesn't support dir change notification.
-+ * and when an entry get unlinked, we only got POLLIN event once,
-+ * it's the only oppotunity we can close the file and startover.
-+ */
- void
--gssd_run()
-+svcgssd_run()
- {
-       int                     ret;
--      FILE                    *f;
-+      FILE                    *f = NULL;
-       struct pollfd           pollfd;
-+      struct timespec         halfsec = { .tv_sec = 0, .tv_nsec = 500000000 };
--#define NULLRPC_FILE "/proc/net/rpc/auth.rpcsec.init/channel"
-+#define NULLRPC_FILE "/proc/net/rpc/auth.ptlrpcs.init/channel"
--      f = fopen(NULLRPC_FILE, "rw");
--
--      if (!f) {
--              printerr(0, "failed to open %s: %s\n",
--                       NULLRPC_FILE, strerror(errno));
--              exit(1);
--      }
--      pollfd.fd = fileno(f);
--      pollfd.events = POLLIN;
-       while (1) {
-               int save_err;
-+              while (f == NULL) {
-+                      f = fopen(NULLRPC_FILE, "rw");
-+                      if (f == NULL) {
-+                              printerr(4, "failed to open %s: %s\n",
-+                                       NULLRPC_FILE, strerror(errno));
-+                              nanosleep(&halfsec, NULL);
-+                      } else {
-+                              printerr(1, "successfully open %s\n",
-+                                       NULLRPC_FILE);
-+                              break;
-+                      }
-+              }
-+              pollfd.fd = fileno(f);
-+              pollfd.events = POLLIN;
-+
-               pollfd.revents = 0;
--              printerr(1, "entering poll\n");
--              ret = poll(&pollfd, 1, -1);
-+              ret = poll(&pollfd, 1, 1000);
-               save_err = errno;
--              printerr(1, "leaving poll\n");
-+
-               if (ret < 0) {
--                      if (save_err != EINTR)
--                              printerr(0, "error return from poll: %s\n",
--                                       strerror(save_err));
-+                      printerr(0, "error return from poll: %s\n",
-+                               strerror(save_err));
-+                      fclose(f);
-+                      f = NULL;
-               } else if (ret == 0) {
--                      /* timeout; shouldn't happen. */
-+                      printerr(3, "poll timeout\n");
-               } else {
-                       if (ret != 1) {
-                               printerr(0, "bug: unexpected poll return %d\n",
-                                               ret);
-                               exit(1);
-                       }
--                      if (pollfd.revents & POLLIN)
--                              handle_nullreq(f);
-+                      if (pollfd.revents & POLLIN) {
-+                              if (handle_nullreq(f) < 0) {
-+                                      fclose(f);
-+                                      f = NULL;
-+                              }
-+                      }
-               }
-       }
- }
-diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_proc.c
---- nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c 2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_proc.c  2007-05-15 13:01:35.000000000 -0600
-@@ -35,7 +35,6 @@
- #include <sys/param.h>
- #include <sys/stat.h>
--#include <rpc/rpc.h>
- #include <pwd.h>
- #include <stdio.h>
-@@ -44,25 +43,28 @@
- #include <string.h>
- #include <fcntl.h>
- #include <errno.h>
--#include <nfsidmap.h>
-+#include <netdb.h>
- #include "svcgssd.h"
- #include "gss_util.h"
- #include "err_util.h"
- #include "context.h"
- #include "cacheio.h"
-+#include "lsupport.h"
- extern char * mech2file(gss_OID mech);
--#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel"
--#define SVCGSSD_INIT_CHANNEL    "/proc/net/rpc/auth.rpcsec.init/channel"
-+#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.ptlrpcs.context/channel"
-+#define SVCGSSD_INIT_CHANNEL    "/proc/net/rpc/auth.ptlrpcs.init/channel"
- #define TOKEN_BUF_SIZE                8192
- struct svc_cred {
--      uid_t   cr_uid;
--      gid_t   cr_gid;
--      int     cr_ngroups;
--      gid_t   cr_groups[NGROUPS];
-+      uint32_t cr_remote;
-+      uint32_t cr_usr_root;
-+      uint32_t cr_usr_mds;
-+      uid_t    cr_uid;
-+      uid_t    cr_mapped_uid;
-+      uid_t    cr_gid;
- };
- static int
-@@ -70,10 +72,9 @@ do_svc_downcall(gss_buffer_desc *out_han
-               gss_OID mech, gss_buffer_desc *context_token)
- {
-       FILE *f;
--      int i;
-       char *fname = NULL;
--      printerr(1, "doing downcall\n");
-+      printerr(2, "doing downcall\n");
-       if ((fname = mech2file(mech)) == NULL)
-               goto out_err;
-       f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w");
-@@ -86,11 +87,12 @@ do_svc_downcall(gss_buffer_desc *out_han
-       qword_printhex(f, out_handle->value, out_handle->length);
-       /* XXX are types OK for the rest of this? */
-       qword_printint(f, 0x7fffffff); /*XXX need a better timeout */
-+      qword_printint(f, cred->cr_remote);
-+      qword_printint(f, cred->cr_usr_root);
-+      qword_printint(f, cred->cr_usr_mds);
-+      qword_printint(f, cred->cr_mapped_uid);
-       qword_printint(f, cred->cr_uid);
-       qword_printint(f, cred->cr_gid);
--      qword_printint(f, cred->cr_ngroups);
--      for (i=0; i < cred->cr_ngroups; i++)
--              qword_printint(f, cred->cr_groups[i]);
-       qword_print(f, fname);
-       qword_printhex(f, context_token->value, context_token->length);
-       qword_eol(f);
-@@ -119,7 +121,7 @@ send_response(FILE *f, gss_buffer_desc *
-       /* XXXARG: */
-       int g;
--      printerr(1, "sending null reply\n");
-+      printerr(2, "sending null reply\n");
-       qword_addhex(&bp, &blen, in_handle->value, in_handle->length);
-       qword_addhex(&bp, &blen, in_token->value, in_token->length);
-@@ -159,6 +161,7 @@ send_response(FILE *f, gss_buffer_desc *
- #define rpcsec_gsserr_credproblem     13
- #define rpcsec_gsserr_ctxproblem      14
-+#if 0
- static void
- add_supplementary_groups(char *secname, char *name, struct svc_cred *cred)
- {
-@@ -182,7 +185,9 @@ add_supplementary_groups(char *secname, 
-               }
-       }
- }
-+#endif
-+#if 0
- static int
- get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred)
- {
-@@ -248,7 +253,9 @@ out_free:
- out:
-       return res;
- }
-+#endif
-+#if 0
- void
- print_hexl(int pri, unsigned char *cp, int length)
- {
-@@ -285,12 +292,121 @@ print_hexl(int pri, unsigned char *cp, i
-               printerr(pri,"\n");
-       }
- }
-+#endif
--void
-+static int
-+get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
-+      lnet_nid_t nid, uint32_t lustre_svc)
-+{
-+      u_int32_t       maj_stat, min_stat;
-+      gss_buffer_desc name;
-+      char            *sname, *realm, *slash;
-+      int             res = -1;
-+      gss_OID         name_type = GSS_C_NO_OID;
-+      struct passwd   *pw;
-+
-+      cred->cr_remote = cred->cr_usr_root = cred->cr_usr_mds = 0;
-+      cred->cr_uid = cred->cr_mapped_uid = cred->cr_gid = -1;
-+
-+      maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
-+      if (maj_stat != GSS_S_COMPLETE) {
-+              pgsserr("get_ids: gss_display_name",
-+                      maj_stat, min_stat, mech);
-+              return -1;
-+      }
-+      if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */
-+          !(sname = calloc(name.length + 1, 1))) {
-+              printerr(0, "WARNING: get_ids: error allocating %d bytes "
-+                      "for sname\n", name.length + 1);
-+              gss_release_buffer(&min_stat, &name);
-+              return -1;
-+      }
-+      memcpy(sname, name.value, name.length);
-+      printerr(1, "authenticated %s from %016llx\n", sname, nid);
-+      gss_release_buffer(&min_stat, &name);
-+
-+      if (lustre_svc == LUSTRE_GSS_SVC_MDS)
-+              lookup_mapping(sname, nid, &cred->cr_mapped_uid);
-+      else
-+              cred->cr_mapped_uid = -1;
-+
-+        realm = strchr(sname, '@');
-+        if (!realm) {
-+                printerr(0, "WARNNING: principal %s contains no realm name\n",
-+                       sname);
-+                cred->cr_remote = (mds_local_realm != NULL);
-+        } else {
-+                *realm++ = '\0';
-+                if (!mds_local_realm)
-+                        cred->cr_remote = 1;
-+                else
-+                        cred->cr_remote =
-+                                (strcasecmp(mds_local_realm, realm) != 0);
-+        }
-+
-+        if (cred->cr_remote) {
-+                if (cred->cr_mapped_uid != -1)
-+                        res = 0;
-+              else if (lustre_svc == LUSTRE_GSS_SVC_OSS &&
-+                       strcmp(sname, "lustre_root") == 0)
-+                        res = 0;
-+                else
-+                        printerr(0, "principal %s is remote without mapping\n",
-+                                 sname);
-+              goto out_free;
-+        }
-+
-+        slash = strchr(sname, '/');
-+        if (slash)
-+                *slash = '\0';
-+
-+        if (!(pw = getpwnam(sname))) {
-+                /* If client use machine credential, we map it to root, which
-+                 * will subject to further mapping by root-squash in kernel.
-+                 *
-+                 * MDS service keytab is treated as special user, also mapped
-+                 * to root. OSS service keytab can't be used as a user.
-+                 */
-+                if (!strcmp(sname, LUSTRE_ROOT_NAME)) {
-+                        printerr(2, "lustre_root principal, resolve to uid 0\n");
-+                        cred->cr_uid = 0;
-+                        cred->cr_usr_root = 1;
-+                } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
-+                        printerr(2, "mds service principal, resolve to uid 0\n");
-+                        cred->cr_uid = 0;
-+                        cred->cr_usr_mds = 1;
-+                } else {
-+                        cred->cr_uid = -1;
-+                        if (cred->cr_mapped_uid == -1) {
-+                                printerr(0, "invalid user %s\n", sname);
-+                                goto out_free;
-+                        }
-+                        printerr(2, "user %s mapped to %u\n",
-+                                 sname, cred->cr_mapped_uid);
-+                }
-+        } else {
-+                cred->cr_uid = pw->pw_uid;
-+                printerr(2, "%s resolve to uid %u\n", sname, cred->cr_uid);
-+        }
-+
-+        res = 0;
-+out_free:
-+        free(sname);
-+        return res;
-+}
-+
-+typedef struct gss_union_ctx_id_t {
-+      gss_OID         mech_type;
-+      gss_ctx_id_t    internal_ctx_id;
-+} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
-+
-+/*
-+ * return -1 only if we detect error during reading from upcall channel,
-+ * all other cases return 0.
-+ */
-+int
- handle_nullreq(FILE *f) {
--      /* XXX initialize to a random integer to reduce chances of unnecessary
--       * invalidation of existing ctx's on restarting svcgssd. */
--      static u_int32_t        handle_seq = 0;
-+      uint64_t                handle_seq;
-       char                    in_tok_buf[TOKEN_BUF_SIZE];
-       char                    in_handle_buf[15];
-       char                    out_handle_buf[15];
-@@ -302,10 +418,13 @@ handle_nullreq(FILE *f) {
-                               ignore_out_tok = {.value = NULL},
-       /* XXX isn't there a define for this?: */
-                               null_token = {.value = NULL};
-+      uint32_t                lustre_svc;
-+      lnet_nid_t              nid;
-       u_int32_t               ret_flags;
-       gss_ctx_id_t            ctx = GSS_C_NO_CONTEXT;
-       gss_name_t              client_name;
-       gss_OID                 mech = GSS_C_NO_OID;
-+      gss_cred_id_t           svc_cred;
-       u_int32_t               maj_stat = GSS_S_FAILURE, min_stat = 0;
-       u_int32_t               ignore_min_stat;
-       struct svc_cred         cred;
-@@ -313,25 +432,31 @@ handle_nullreq(FILE *f) {
-       static int              lbuflen = 0;
-       static char             *cp;
--      printerr(1, "handling null request\n");
-+      printerr(2, "handling null request\n");
-       if (readline(fileno(f), &lbuf, &lbuflen) != 1) {
-               printerr(0, "WARNING: handle_nullreq: "
-                           "failed reading request\n");
--              return;
-+              return -1;
-       }
-       cp = lbuf;
-+      qword_get(&cp, (char *) &lustre_svc, sizeof(lustre_svc));
-+      qword_get(&cp, (char *) &nid, sizeof(nid));
-+      qword_get(&cp, (char *) &handle_seq, sizeof(handle_seq));
-+      printerr(1, "handling req: svc %u, nid %016llx, idx %llx\n",
-+               lustre_svc, nid, handle_seq);
-+
-       in_handle.length = (size_t) qword_get(&cp, in_handle.value,
-                                             sizeof(in_handle_buf));
--      printerr(2, "in_handle: \n");
--      print_hexl(2, in_handle.value, in_handle.length);
-+      printerr(3, "in_handle: \n");
-+      print_hexl(3, in_handle.value, in_handle.length);
-       in_tok.length = (size_t) qword_get(&cp, in_tok.value,
-                                          sizeof(in_tok_buf));
--      printerr(2, "in_tok: \n");
--      print_hexl(2, in_tok.value, in_tok.length);
-+      printerr(3, "in_tok: \n");
-+      print_hexl(3, in_tok.value, in_tok.length);
-       if (in_tok.length < 0) {
-               printerr(0, "WARNING: handle_nullreq: "
-@@ -351,7 +476,13 @@ handle_nullreq(FILE *f) {
-               memcpy(&ctx, in_handle.value, in_handle.length);
-       }
--      maj_stat = gss_accept_sec_context(&min_stat, &ctx, gssd_creds,
-+      svc_cred = gssd_select_svc_cred(lustre_svc);
-+      if (!svc_cred) {
-+              printerr(0, "no service credential for svc %u\n", lustre_svc);
-+              goto out_err;
-+      }
-+
-+      maj_stat = gss_accept_sec_context(&min_stat, &ctx, svc_cred,
-                       &in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name,
-                       &mech, &out_tok, &ret_flags, NULL, NULL);
-@@ -369,7 +500,8 @@ handle_nullreq(FILE *f) {
-                       maj_stat, min_stat, mech);
-               goto out_err;
-       }
--      if (get_ids(client_name, mech, &cred)) {
-+
-+      if (get_ids(client_name, mech, &cred, nid, lustre_svc)) {
-               /* get_ids() prints error msg */
-               maj_stat = GSS_S_BAD_NAME; /* XXX ? */
-               gss_release_name(&ignore_min_stat, &client_name);
-@@ -377,10 +509,8 @@ handle_nullreq(FILE *f) {
-       }
-       gss_release_name(&ignore_min_stat, &client_name);
--
-       /* Context complete. Pass handle_seq in out_handle to use
-        * for context lookup in the kernel. */
--      handle_seq++;
-       out_handle.length = sizeof(handle_seq);
-       memcpy(out_handle.value, &handle_seq, sizeof(handle_seq));
-@@ -404,8 +534,7 @@ out:
-               free(ctx_token.value);
-       if (out_tok.value != NULL)
-               gss_release_buffer(&ignore_min_stat, &out_tok);
--      printerr(1, "finished handling null request\n");
--      return;
-+      return 0;
- out_err:
-       if (ctx != GSS_C_NO_CONTEXT)
-diff -rNup nfs-utils-1.0.10/utils/Makefile.am nfs-utils-1.0.10.lustre/utils/Makefile.am
---- nfs-utils-1.0.10/utils/Makefile.am 2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10.lustre/utils/Makefile.am  2007-05-15 13:00:53.000000000 -0600
-@@ -2,31 +2,6 @@
- OPTDIRS =
--if CONFIG_RQUOTAD
--OPTDIRS += rquotad
--endif
--
--if CONFIG_NFSV4
--OPTDIRS += idmapd
--endif
--
--if CONFIG_GSS
--OPTDIRS += gssd
--endif
--
--if CONFIG_MOUNT
--OPTDIRS += mount
--endif
--
--SUBDIRS = \
--      exportfs \
--      lockd \
--      mountd \
--      nfsd \
--      nfsstat \
--      nhfsstone \
--      showmount \
--      statd \
--      $(OPTDIRS)
-+SUBDIRS = gssd
- MAINTAINERCLEANFILES = Makefile.in
diff --git a/lustre/utils/gss/nfs-utils-1.0.11-lustre.diff b/lustre/utils/gss/nfs-utils-1.0.11-lustre.diff
deleted file mode 100644 (file)
index cf3a40c..0000000
+++ /dev/null
@@ -1,3237 +0,0 @@
-diff -Nrup nfs-utils-1.0.11.lustre/configure.in nfs-utils-1.0.11/configure.in
---- nfs-utils-1.0.11.lustre/configure.in       2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/configure.in      2008-01-02 18:10:29.000000000 -0700
-@@ -18,61 +18,14 @@ AC_ARG_WITH(release,
-       RELEASE=$withval,
-       RELEASE=1)
-       AC_SUBST(RELEASE)
--AC_ARG_WITH(statedir,
--      [  --with-statedir=/foo    use state dir /foo [/var/lib/nfs]],
--      statedir=$withval,
--      statedir=/var/lib/nfs)
--      AC_SUBST(statedir)
--AC_ARG_WITH(statduser,
--      [AC_HELP_STRING([--with-statduser=rpcuser],
--                        [statd to run under @<:@rpcuser or nobody@:>@]
--      )],
--      statduser=$withval,
--      if test "x$cross_compiling" = "xno"; then
--              if grep -s '^rpcuser:' /etc/passwd > /dev/null; then
--                      statduser=rpcuser
--              else
--                      statduser=nobody
--              fi
--      else
--              statduser=nobody
--      fi)
--      AC_SUBST(statduser)
--AC_ARG_ENABLE(nfsv3,
--      [AC_HELP_STRING([--enable-nfsv3],
--                        [enable support for NFSv3 @<:@default=yes@:>@])],
--      enable_nfsv3=$enableval,
--      enable_nfsv3=yes)
--      if test "$enable_nfsv3" = yes; then
--              AC_DEFINE(NFS3_SUPPORTED, 1, [Define this if you want NFSv3 support compiled in])
--      else
--              enable_nfsv3=
--      fi
--      AC_SUBST(enable_nfsv3)
--AC_ARG_ENABLE(nfsv4,
--      [AC_HELP_STRING([--enable-nfsv4],
--                        [enable support for NFSv4 @<:@default=yes@:>@])],
--      enable_nfsv4=$enableval,
--      enable_nfsv4=yes)
--      if test "$enable_nfsv4" = yes; then
--              AC_DEFINE(NFS4_SUPPORTED, 1, [Define this if you want NFSv4 support compiled in])
--              IDMAPD=idmapd
--      else
--              enable_nfsv4=
--              IDMAPD=
--      fi
--      AC_SUBST(IDMAPD)
--      AC_SUBST(enable_nfsv4)
--      AM_CONDITIONAL(CONFIG_NFSV4, [test "$enable_nfsv4" = "yes"])
- AC_ARG_ENABLE(gss,
-       [AC_HELP_STRING([--enable-gss],
-                         [enable support for rpcsec_gss @<:@default=yes@:>@])],
-       enable_gss=$enableval,
-       enable_gss=yes)
-       if test "$enable_gss" = yes; then
--              AC_DEFINE(GSS_SUPPORTED, 1, [Define this if you want rpcsec_gss support compiled in])
--              GSSD=gssd
--              SVCGSSD=svcgssd
-+              GSSD=lgssd
-+              SVCGSSD=lsvcgssd
-       else
-               enable_gss=
-               GSSD=
-@@ -82,38 +35,6 @@ AC_ARG_ENABLE(gss,
-       AC_SUBST(SVCGSSD)
-       AC_SUBST(enable_gss)
-       AM_CONDITIONAL(CONFIG_GSS, [test "$enable_gss" = "yes"])
--AC_ARG_ENABLE(kprefix,
--      [AC_HELP_STRING([--enable-kprefix], [install progs as rpc.knfsd etc])],
--      test "$enableval" = "yes" && kprefix=k,
--      kprefix=)
--      AC_SUBST(kprefix)
--AC_ARG_ENABLE(secure-statd,
--      [AC_HELP_STRING([--enable-secure-statd],
--                        [Only lockd can use statd (security)])],
--      test "$enableval" = "yes" && secure_statd=yes,
--      secure_statd=no)
--      if test "$secure_statd" = yes; then
--              AC_DEFINE(RESTRICTED_STATD, 1, [Define this if you want to enable various security checks in statd. These checks basically keep anyone but lockd from using this service.])
--      fi
--      AC_SUBST(secure_statd)
--AC_ARG_ENABLE(rquotad,
--      [AC_HELP_STRING([--enable-rquotad],
--                        [enable rquotad @<:@default=yes@:>@])],
--      enable_rquotad=$enableval,
--      enable_rquotad=yes)
--      if test "$enable_rquotad" = yes; then
--              RQUOTAD=rquotad
--      else
--              RQUOTAD=
--      fi
--      AM_CONDITIONAL(CONFIG_RQUOTAD, [test "$enable_rquotad" = "yes"])
--
--AC_ARG_ENABLE(mount,
--      [AC_HELP_STRING([--enable-mount],
--                      [Create mount.nfs and don't use the util-linux mount(8) functionality. @<:@default=no@:>@])],
--      enable_mount=$enableval,
--      enable_mount=no)
--      AM_CONDITIONAL(CONFIG_MOUNT, [test "$enable_mount" = "yes"])
- # Check whether user wants TCP wrappers support
- AC_TCP_WRAPPERS
-@@ -156,50 +77,15 @@ AC_CHECK_FUNC(connect, ,
-                 AC_MSG_ERROR(Function 'socket' not found.), $LIBNSL))
- AC_CHECK_LIB(crypt, crypt, [LIBCRYPT="-lcrypt"])
--if test "$enable_nfsv4" = yes; then
--    AC_CHECK_LIB(event, event_dispatch, [libevent=1], AC_MSG_ERROR([libevent needed for nfsv4 support]))
--    AC_CHECK_LIB(nfsidmap, nfs4_init_name_mapping, [libnfsidmap=1], AC_MSG_ERROR([libnfsidmap needed for nfsv4 support]))
--    AC_CHECK_HEADERS(event.h, ,AC_MSG_ERROR([libevent needed for nfsv4 support]))
--    AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for nfsv4 support]))
--    dnl librpcsecgss already has a dependency on libgssapi,
--    dnl but we need to make sure we get the right version
--    if test "$enable_gss" = yes; then
--     PKG_CHECK_MODULES(RPCSECGSS, librpcsecgss >= 0.10, ,
--      [AC_MSG_ERROR([Unable to locate information required to use librpcsecgss.  If you have pkgconfig installed, you might try setting environment variable PKG_CONFIG_PATH to /usr/local/lib/pkgconfig])
--      ]
--     )
--    PKG_CHECK_MODULES(GSSAPI, libgssapi >= 0.9)
--    fi
--
--fi
--if test "$knfsd_cv_glibc2" = no; then
--    AC_CHECK_LIB(bsd, daemon, [LIBBSD="-lbsd"])
--fi
--AC_CHECK_LIB(blkid, blkid_get_cache, [LIBBLKID="-lblkid"], AC_MSG_ERROR([libblkid needed]))
--AC_CHECK_HEADER(blkid/blkid.h, , AC_MSG_ERROR([Cannot file libblkid header file blkid/blkid.h]))
-+PKG_CHECK_MODULES(GSSAPI, libgssapi >= 0.9)
- AC_SUBST(LIBSOCKET)
- AC_SUBST(LIBCRYPT)
- AC_SUBST(LIBBSD)
- AC_SUBST(LIBBLKID)
- if test "$enable_gss" = yes; then
--  dnl 'gss' also depends on nfsidmap.h - at least for svcgssd_proc.c
--  AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for gss support]))
--  AC_CHECK_HEADERS(spkm3.h, ,AC_MSG_WARN([could not locate SPKM3 header; will not have SPKM3 support]))
--  dnl the nfs4_set_debug function doesn't appear in all version of the library
--  AC_CHECK_LIB(nfsidmap, nfs4_set_debug,
--             AC_DEFINE(HAVE_NFS4_SET_DEBUG,1,
--                       [Whether nfs4_set_debug() is present in libnfsidmap]),)
--
-   dnl Check for Kerberos V5
-   AC_KERBEROS_V5
--
--  dnl This is not done until here because we need to have KRBLIBS set
--  dnl ("librpcsecgss=1" is so that it doesn't get added to LIBS)
--  AC_CHECK_LIB(rpcsecgss, authgss_create_default, [librpcsecgss=1], AC_MSG_ERROR([librpcsecgss needed for nfsv4 support]), -lgssapi -ldl)
--  AC_CHECK_LIB(rpcsecgss, authgss_set_debug_level,
--             AC_DEFINE(HAVE_AUTHGSS_SET_DEBUG_LEVEL, 1, [Define this if the rpcsec_gss library has the function authgss_set_debug_level]),, -lgssapi -ldl)
--
- fi
- dnl *************************************************************
-@@ -311,33 +197,7 @@ AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_mac
- AC_CONFIG_FILES([
-       Makefile
--      linux-nfs/Makefile
--      support/Makefile
--      support/export/Makefile
--      support/include/nfs/Makefile
--      support/include/rpcsvc/Makefile
--      support/include/sys/fs/Makefile
--      support/include/sys/Makefile
--      support/include/Makefile
--      support/misc/Makefile
--      support/nfs/Makefile
--      tools/Makefile
--      tools/getiversion/Makefile
--      tools/locktest/Makefile
--      tools/nlmtest/Makefile
--      tools/rpcdebug/Makefile
--      tools/rpcgen/Makefile
-       utils/Makefile
--      utils/exportfs/Makefile
--      utils/gssd/Makefile
--      utils/idmapd/Makefile
--      utils/lockd/Makefile
--      utils/mount/Makefile
--      utils/mountd/Makefile
--      utils/nfsd/Makefile
--      utils/nfsstat/Makefile
--      utils/rquotad/Makefile
--      utils/showmount/Makefile
--      utils/statd/Makefile])
-+      utils/gssd/Makefile])
- AC_OUTPUT
-diff -Nrup nfs-utils-1.0.11.lustre/Makefile.am nfs-utils-1.0.11/Makefile.am
---- nfs-utils-1.0.11.lustre/Makefile.am        2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/Makefile.am       2008-01-02 18:10:29.000000000 -0700
-@@ -1,6 +1,6 @@
- ## Process this file with automake to produce Makefile.in
--SUBDIRS = tools support utils linux-nfs
-+SUBDIRS = utils
- MAINTAINERCLEANFILES = Makefile.in
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/cacheio.c nfs-utils-1.0.11/utils/gssd/cacheio.c
---- nfs-utils-1.0.11.lustre/utils/gssd/cacheio.c       2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/cacheio.c      2008-01-02 18:11:38.000000000 -0700
-@@ -240,7 +240,8 @@ int qword_get(char **bpp, char *dest, in
-               return -1;
-       while (*bp == ' ') bp++;
-       *bpp = bp;
--      *dest = '\0';
-+// why should we clear *dest???
-+//    *dest = '\0';
-       return len;
- }
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context.c nfs-utils-1.0.11/utils/gssd/context.c
---- nfs-utils-1.0.11.lustre/utils/gssd/context.c       2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/context.c      2008-01-02 18:11:38.000000000 -0700
-@@ -33,11 +33,14 @@
- #include <syslog.h>
- #include <string.h>
- #include <gssapi/gssapi.h>
--#include <rpc/rpc.h>
--#include <rpc/auth_gss.h>
--#include "gss_util.h"
--#include "gss_oids.h"
--#include "err_util.h"
-+
-+#ifdef _NEW_BUILD_
-+# include "lgss_utils.h"
-+#else
-+# include "gss_util.h"
-+# include "gss_oids.h"
-+# include "err_util.h"
-+#endif
- #include "context.h"
- int
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context.h nfs-utils-1.0.11/utils/gssd/context.h
---- nfs-utils-1.0.11.lustre/utils/gssd/context.h       2008-01-02 17:22:48.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/context.h      2008-01-02 18:11:38.000000000 -0700
-@@ -31,8 +31,6 @@
- #ifndef _CONTEXT_H_
- #define _CONTEXT_H_
--#include <rpc/rpc.h>
--
- /* Hopefully big enough to hold any serialized context */
- #define MAX_CTX_LEN 4096
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_heimdal.c nfs-utils-1.0.11/utils/gssd/context_heimdal.c
---- nfs-utils-1.0.11.lustre/utils/gssd/context_heimdal.c       2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/context_heimdal.c      2008-01-02 18:11:38.000000000 -0700
-@@ -43,8 +43,13 @@
- #ifdef HAVE_COM_ERR_H
- #include <com_err.h>
- #endif
--#include "err_util.h"
--#include "gss_oids.h"
-+
-+#ifdef _NEW_BUILD_
-+# include "lgss_utils.h"
-+#else
-+# include "err_util.h"
-+# include "gss_oids.h"
-+#endif
- #include "write_bytes.h"
- int write_heimdal_keyblock(char **p, char *end, krb5_keyblock *key)
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_lucid.c nfs-utils-1.0.11/utils/gssd/context_lucid.c
---- nfs-utils-1.0.11.lustre/utils/gssd/context_lucid.c 2008-01-02 17:22:48.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/context_lucid.c        2008-01-02 18:11:38.000000000 -0700
-@@ -41,11 +41,7 @@
- #include <syslog.h>
- #include <string.h>
- #include <errno.h>
--#include "gss_util.h"
--#include "gss_oids.h"
--#include "err_util.h"
--#include "context.h"
--
-+#include <stdint.h>
- #include <krb5.h>
- #include <gssapi/gssapi.h>
- #ifndef OM_uint64
-@@ -53,6 +49,16 @@ typedef uint64_t OM_uint64;
- #endif
- #include <gssapi/gssapi_krb5.h>
-+#ifdef _NEW_BUILD_
-+# include "lgss_utils.h"
-+#else
-+# include "gss_util.h"
-+# include "gss_oids.h"
-+# include "err_util.h"
-+#endif
-+#include "write_bytes.h"
-+#include "context.h"
-+
- static int
- write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key)
- {
-@@ -354,6 +360,7 @@ static int
- prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
-                           gss_buffer_desc *buf)
- {
-+      static int constant_two = 2;
-       char *p, *end;
-       uint32_t v2_flags = 0;
-       gss_krb5_lucid_key_t enc_key;
-@@ -372,7 +379,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
-       end = buf->value + MAX_CTX_LEN;
-       /* Version 2 */
--      if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err;
-+      if (WRITE_BYTES(&p, end, constant_two)) goto out_err;
-       if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
-       if (lctx->initiate)
-@@ -387,7 +394,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
-       if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
-       /* Protocol 0 here implies DES3 or RC4 */
--      printerr(2, "%s: protocol %d\n", __FUNCTION__, lctx->protocol);
-+      printerr(3, "protocol %d\n", lctx->protocol);
-       if (lctx->protocol == 0) {
-               enctype = lctx->rfc1964_kd.ctx_key.type;
- #ifdef HAVE_HEIMDAL
-@@ -415,8 +422,8 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
-               }
-               numkeys = 3;
-       }
--      printerr(2, "%s: serializing %d keys with enctype %d and size %d\n",
--               __FUNCTION__, numkeys, enctype, keysize);
-+      printerr(3, "serializing %d keys with enctype %d and size %d\n",
-+               numkeys, enctype, keysize);
-       if (WRITE_BYTES(&p, end, enctype)) goto out_err;
-       if (WRITE_BYTES(&p, end, keysize)) goto out_err;
-       if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
-@@ -434,14 +441,25 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
-                       goto out_err;
-               /* Kc */
--              if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
--                              &derived_key,
--                              KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
--                      goto out_err;
--              if (write_bytes(&p, end, derived_key.data,
--                              derived_key.length))
--                      goto out_err;
--              free(derived_key.data);
-+              /*
-+               * RC4 is special, it dosen't need key derivation. Actually
-+               * the Ke is based on plain text. Here we just let all three
-+               * key identical, kernel will handle everything. --ericm
-+               */
-+              if (lctx->rfc1964_kd.ctx_key.type == ENCTYPE_ARCFOUR_HMAC) {
-+                      if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
-+                                      lctx->rfc1964_kd.ctx_key.length))
-+                              goto out_err;
-+              } else {
-+                      if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
-+                                      &derived_key,
-+                                      KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
-+                              goto out_err;
-+                      if (write_bytes(&p, end, derived_key.data,
-+                                      derived_key.length))
-+                              goto out_err;
-+                      free(derived_key.data);
-+              }
-       } else {
-               gss_krb5_lucid_key_t *keyptr;
-               uint32_t sign_usage, seal_usage;
-@@ -451,6 +469,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
-               else
-                       keyptr = &lctx->cfx_kd.ctx_key;
-+#if 0
-               if (lctx->initiate == 1) {
-                       sign_usage = KG_USAGE_INITIATOR_SIGN;
-                       seal_usage = KG_USAGE_INITIATOR_SEAL;
-@@ -458,6 +477,19 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
-                       sign_usage = KG_USAGE_ACCEPTOR_SIGN;
-                       seal_usage = KG_USAGE_ACCEPTOR_SEAL;
-               }
-+#else
-+              /* FIXME
-+               * These are from rfc4142, but I don't understand: if we supply
-+               * different 'usage' value for client & server, then the peers
-+               * will have different derived keys. How could this work?
-+               *
-+               * Here we simply use old SIGN/SEAL values until we find the
-+               * answer.  --ericm
-+               * FIXME
-+               */
-+              sign_usage = KG_USAGE_SIGN;
-+              seal_usage = KG_USAGE_SEAL;
-+#endif
-               /* derive and send down: Ke, Ki, and Kc */
-@@ -515,7 +547,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
-       gss_krb5_lucid_context_v1_t *lctx = 0;
-       int retcode = 0;
--      printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__);
-+      printerr(3, "lucid version!\n");
-       maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx,
-                                               1, &return_ctx);
-       if (maj_stat != GSS_S_COMPLETE) {
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_mit.c nfs-utils-1.0.11/utils/gssd/context_mit.c
---- nfs-utils-1.0.11.lustre/utils/gssd/context_mit.c   2008-01-02 17:22:48.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/context_mit.c  2008-01-02 18:11:38.000000000 -0700
-@@ -39,10 +39,15 @@
- #include <errno.h>
- #include <gssapi/gssapi.h>
- #include <rpc/rpc.h>
--#include <rpc/auth_gss.h>
--#include "gss_util.h"
--#include "gss_oids.h"
--#include "err_util.h"
-+
-+#ifdef _NEW_BUILD_
-+# include "lgss_utils.h"
-+# include "write_bytes.h"
-+#else
-+# include "gss_util.h"
-+# include "gss_oids.h"
-+# include "err_util.h"
-+#endif
- #include "context.h"
- #include <krb5.h>
-@@ -333,12 +338,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
-                * keydata-2;                (  Ki  (Kseq for DES3) )
-                * keydata-3;                (  Kc (derived checksum key) )
-                */
--              if (kctx->initiate) {
--                      if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
--              }
--              else {
--                      if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
--              }
-+              if (WRITE_BYTES(&p, end, constant_two)) goto out_err;
-               if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
-               /* Only applicable flag for this is initiator */
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_spkm3.c nfs-utils-1.0.11/utils/gssd/context_spkm3.c
---- nfs-utils-1.0.11.lustre/utils/gssd/context_spkm3.c 2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/context_spkm3.c        2008-01-02 18:11:38.000000000 -0700
-@@ -33,8 +33,6 @@
- #include <syslog.h>
- #include <string.h>
- #include <gssapi/gssapi.h>
--#include <rpc/rpc.h>
--#include <rpc/auth_gss.h>
- #include "gss_util.h"
- #include "gss_oids.h"
- #include "err_util.h"
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/err_util.c nfs-utils-1.0.11/utils/gssd/err_util.c
---- nfs-utils-1.0.11.lustre/utils/gssd/err_util.c      2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/err_util.c     2008-01-02 18:11:38.000000000 -0700
-@@ -32,6 +32,8 @@
- #include <stdarg.h>
- #include <syslog.h>
- #include <string.h>
-+#include <fcntl.h>
-+#include <ctype.h>
- #include "err_util.h"
- static int verbosity = 0;
-@@ -91,3 +93,40 @@ printit:
-       /* reset the buffer */
-       memset(message_buf, 0, sizeof(message_buf));
- }
-+
-+void print_hexl(int pri, unsigned char *cp, int length)
-+{
-+      int i, j, jm;
-+      unsigned char c;
-+
-+      printerr(pri, "length %d\n",length);
-+      printerr(pri, "\n");
-+
-+      for (i = 0; i < length; i += 0x10) {
-+              printerr(pri, "  %04x: ", (u_int)i);
-+              jm = length - i;
-+              jm = jm > 16 ? 16 : jm;
-+
-+              for (j = 0; j < jm; j++) {
-+                      if ((j % 2) == 1)
-+                              printerr(pri,"%02x ", (u_int)cp[i+j]);
-+                      else
-+                              printerr(pri,"%02x", (u_int)cp[i+j]);
-+              }
-+              for (; j < 16; j++) {
-+                      if ((j % 2) == 1)
-+                              printerr(pri,"   ");
-+                      else
-+                              printerr(pri,"  ");
-+              }
-+              printerr(pri," ");
-+
-+              for (j = 0; j < jm; j++) {
-+                      c = cp[i+j];
-+                      c = isprint(c) ? c : '.';
-+                      printerr(pri,"%c", c);
-+              }
-+              printerr(pri,"\n");
-+      }
-+}
-+
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/err_util.h nfs-utils-1.0.11/utils/gssd/err_util.h
---- nfs-utils-1.0.11.lustre/utils/gssd/err_util.h      2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/err_util.h     2008-01-02 18:11:38.000000000 -0700
-@@ -33,5 +33,6 @@
- void initerr(char *progname, int verbosity, int fg);
- void printerr(int priority, char *format, ...);
-+void print_hexl(int pri, unsigned char *cp, int length);
- #endif /* _ERR_UTIL_H_ */
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gss_clnt_send_err.c nfs-utils-1.0.11/utils/gssd/gss_clnt_send_err.c
---- nfs-utils-1.0.11.lustre/utils/gssd/gss_clnt_send_err.c     2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/gss_clnt_send_err.c    2008-01-02 18:10:29.000000000 -0700
-@@ -47,6 +47,7 @@
- #include "gssd.h"
- #include "write_bytes.h"
-+#if 0
- char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
- static void
-@@ -102,3 +103,4 @@ main(int argc, char *argv[])
-       }
-       exit(0);
- }
-+#endif
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd.c nfs-utils-1.0.11/utils/gssd/gssd.c
---- nfs-utils-1.0.11.lustre/utils/gssd/gssd.c  2008-01-02 17:22:48.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/gssd.c 2008-01-02 18:11:38.000000000 -0700
-@@ -38,9 +38,12 @@
- #include "config.h"
-+#include <sys/types.h>
- #include <sys/param.h>
- #include <sys/socket.h>
--#include <rpc/rpc.h>
-+#include <sys/wait.h>
-+#include <sys/ipc.h>
-+#include <sys/sem.h>
- #include <unistd.h>
- #include <err.h>
-@@ -48,23 +51,107 @@
- #include <stdlib.h>
- #include <string.h>
- #include <signal.h>
-+#include <errno.h>
- #include "gssd.h"
- #include "err_util.h"
- #include "gss_util.h"
- #include "krb5_util.h"
-+#include "lsupport.h"
- char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR;
- char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
- char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
- char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR;
- int  use_memcache = 0;
-+int  lgssd_mutex_downcall = -1;
--void
--sig_die(int signal)
-+static int lgssd_create_mutex(int *semid)
-+{
-+      int             id;
-+      int             arg;
-+
-+      id = semget(IPC_PRIVATE, 1, IPC_CREAT);
-+      if (id == -1) {
-+              printerr(0, "semget: %s\n", strerror(errno));
-+              return -1;
-+      }
-+
-+      arg = 1;
-+      if (semctl(id, 0, SETVAL, arg) != 0) {
-+              printerr(0, "semctl: %s\n", strerror(errno));
-+              semctl(id, 1, IPC_RMID, arg);
-+              return -1;
-+      }
-+
-+      *semid = id;
-+      return 0;
-+}
-+
-+void lgssd_init_mutexs(void)
-+{
-+      if (lgssd_create_mutex(&lgssd_mutex_downcall)) {
-+              printerr(0, "can't create downcall mutex\n");
-+              exit(1);
-+      }
-+}
-+
-+void lgssd_fini_mutexs(void)
-+{
-+      int     arg = 0;
-+
-+      if (lgssd_mutex_downcall != -1)
-+              semctl(lgssd_mutex_downcall, 1, IPC_RMID, arg);
-+}
-+
-+void lgssd_mutex_get(int semid)
-+{
-+      struct sembuf   op[1] = { {0, -1, SEM_UNDO} };
-+      int             rc;
-+
-+      rc = semop(semid, op, 1);
-+      if (rc != 0) {
-+              printerr(0, "exit on mutex_get err %d: %s\n",
-+                       rc, strerror(errno));
-+              exit(1);
-+      }
-+}
-+
-+void lgssd_mutex_put(int semid)
- {
-+      struct sembuf   op[1] = { {0, 1, 0} };
-+      int             rc;
-+
-+      rc = semop(semid, op, 1);
-+      if (rc != 0) {
-+              printerr(0, "ignore mutex_put err %d: %s\n",
-+                       rc, strerror(errno));
-+      }
-+}
-+
-+static void lgssd_cleanup(void)
-+{
-+      pid_t   child_pid;
-+
-+      /* make sure all children finished */
-+      while (1) {
-+              child_pid = waitpid(-1, NULL, 0);
-+              if (child_pid < 0)
-+                      break;
-+
-+              printerr(3, "cleanup: child %d terminated\n", child_pid);
-+      }
-+
-+      lgssd_fini_mutexs();
-+
-       /* destroy krb5 machine creds */
-       gssd_destroy_krb5_machine_creds();
-+}
-+
-+void
-+sig_die(int signal)
-+{
-       printerr(1, "exiting on signal %d\n", signal);
-+      lgssd_cleanup();
-       exit(1);
- }
-@@ -79,7 +166,7 @@ sig_hup(int signal)
- static void
- usage(char *progname)
- {
--      fprintf(stderr, "usage: %s [-f] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir]\n",
-+      fprintf(stderr, "usage: %s [-f] [-v] [-p pipefsdir] [-k keytab] [-d ccachedir]\n",
-               progname);
-       exit(1);
- }
-@@ -89,7 +176,6 @@ main(int argc, char *argv[])
- {
-       int fg = 0;
-       int verbosity = 0;
--      int rpc_verbosity = 0;
-       int opt;
-       extern char *optarg;
-       char *progname;
-@@ -99,18 +185,12 @@ main(int argc, char *argv[])
-                       case 'f':
-                               fg = 1;
-                               break;
--                      case 'm':
--                              /* Accept but ignore this. Now the default. */
--                              break;
-                       case 'M':
-                               use_memcache = 1;
-                               break;
-                       case 'v':
-                               verbosity++;
-                               break;
--                      case 'r':
--                              rpc_verbosity++;
--                              break;
-                       case 'p':
-                               strncpy(pipefs_dir, optarg, sizeof(pipefs_dir));
-                               if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0')
-@@ -131,10 +211,6 @@ main(int argc, char *argv[])
-                               break;
-               }
-       }
--      snprintf(pipefs_nfsdir, sizeof(pipefs_nfsdir), "%s/%s",
--               pipefs_dir, GSSD_SERVICE_NAME);
--      if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0')
--              errx(1, "pipefs_nfsdir path name too long");
-       if ((progname = strrchr(argv[0], '/')))
-               progname++;
-@@ -142,30 +218,42 @@ main(int argc, char *argv[])
-               progname = argv[0];
-       initerr(progname, verbosity, fg);
--#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
--      authgss_set_debug_level(rpc_verbosity);
--#else
--        if (rpc_verbosity > 0)
--              printerr(0, "Warning: rpcsec_gss library does not "
--                          "support setting debug level\n");
--#endif
-       if (gssd_check_mechs() != 0)
-               errx(1, "Problem with gssapi library");
-+      if (gssd_get_local_realm())
-+              errx(1, "get local realm");
-+
-       if (!fg && daemon(0, 0) < 0)
-               errx(1, "fork");
-+      /* This should be checked _after_ daemon(), because we need to own
-+       * the undo-able semaphore by this process
-+       */
-+      gssd_init_unique(GSSD_CLI);
-+
-+      /* Process keytab file and get machine credentials. This will modify
-+       * disk status so do it after we are sure we are the only instance
-+       */
-+      if (gssd_refresh_krb5_machine_creds())
-+              return -1;
-+
-       signal(SIGINT, sig_die);
-       signal(SIGTERM, sig_die);
-       signal(SIGHUP, sig_hup);
--      /* Process keytab file and get machine credentials */
--      gssd_refresh_krb5_machine_creds();
-+#if 0
-       /* Determine Kerberos information from the kernel */
-       gssd_obtain_kernel_krb5_info();
-+#endif
-+
-+      lgssd_init_mutexs();
-+
-+      printerr(0, "lgssd initialized and ready to serve\n");
-+      lgssd_run();
--      gssd_run();
--      printerr(0, "gssd_run returned!\n");
--      abort();
-+      lgssd_cleanup();
-+      printerr(0, "lgssd exiting\n");
-+      return 0;
- }
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd.h nfs-utils-1.0.11/utils/gssd/gssd.h
---- nfs-utils-1.0.11.lustre/utils/gssd/gssd.h  2008-01-02 17:22:48.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/gssd.h 2008-01-02 18:11:38.000000000 -0700
-@@ -48,8 +48,13 @@
- #define GSSD_DEFAULT_CRED_PREFIX              "krb5cc_"
- #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX      "machine"
- #define GSSD_DEFAULT_KEYTAB_FILE              "/etc/krb5.keytab"
--#define GSSD_SERVICE_NAME                     "nfs"
--#define GSSD_SERVICE_NAME_LEN                 3
-+#define GSSD_SERVICE_MDS                      "lustre_mds"
-+#define GSSD_SERVICE_OSS                      "lustre_oss"
-+#define GSSD_SERVICE_MDS_NAMELEN              10
-+#define GSSD_SERVICE_OSS_NAMELEN              10
-+
-+#define LUSTRE_ROOT_NAME                      "lustre_root"
-+#define LUSTRE_ROOT_NAMELEN                   11
- /*
-  * The gss mechanisms that we can handle
-@@ -59,9 +64,9 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT
- extern char                   pipefs_dir[PATH_MAX];
--extern char                   pipefs_nfsdir[PATH_MAX];
- extern char                   keytabfile[PATH_MAX];
- extern char                   ccachedir[PATH_MAX];
-+extern char                   gethostname_ex[PATH_MAX];
- extern int                    use_memcache;
- TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list;
-@@ -71,10 +76,6 @@ struct clnt_info {
-       char                    *dirname;
-       int                     dir_fd;
-       char                    *servicename;
--      char                    *servername;
--      int                     prog;
--      int                     vers;
--      char                    *protocol;
-       int                     krb5_fd;
-       int                     krb5_poll_index;
-       int                     spkm3_fd;
-@@ -85,8 +86,14 @@ void init_client_list(void);
- int update_client_list(void);
- void handle_krb5_upcall(struct clnt_info *clp);
- void handle_spkm3_upcall(struct clnt_info *clp);
--int gssd_acquire_cred(char *server_name);
--void gssd_run(void);
-+void lgssd_run(void);
-+
-+
-+extern int lgssd_mutex_downcall;
-+void lgssd_init_mutexs(void);
-+void lgssd_fini_mutexs(void);
-+void lgssd_mutex_get(int semid);
-+void lgssd_mutex_put(int semid);
- #endif /* _RPC_GSSD_H_ */
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd_main_loop.c nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c
---- nfs-utils-1.0.11.lustre/utils/gssd/gssd_main_loop.c        2008-01-02 17:22:48.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c       2008-01-02 18:11:38.000000000 -0700
-@@ -44,6 +44,10 @@
- #include <fcntl.h>
- #include <signal.h>
- #include <unistd.h>
-+/* For time() */
-+#include <time.h>
-+/* For waitpid() */
-+#include <wait.h>
- #include "gssd.h"
- #include "err_util.h"
-@@ -94,11 +98,13 @@ scan_poll_results(int ret)
- };
- void
--gssd_run()
-+lgssd_run()
- {
-       int                     ret;
-       struct sigaction        dn_act;
-       int                     fd;
-+      time_t                  child_check = 0;
-+      pid_t                   child_pid;
-       /* Taken from linux/Documentation/dnotify.txt: */
-       dn_act.sa_sigaction = dir_notify_handler;
-@@ -106,10 +112,10 @@ gssd_run()
-       dn_act.sa_flags = SA_SIGINFO;
-       sigaction(DNOTIFY_SIGNAL, &dn_act, NULL);
--      if ((fd = open(pipefs_nfsdir, O_RDONLY)) == -1) {
-+      if ((fd = open(pipefs_dir, O_RDONLY)) == -1) {
-               printerr(0, "ERROR: failed to open %s: %s\n",
--                       pipefs_nfsdir, strerror(errno));
--              exit(1);
-+                       pipefs_dir, strerror(errno));
-+              return;
-       }
-       fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL);
-       fcntl(fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
-@@ -119,12 +125,30 @@ gssd_run()
-       while (1) {
-               while (dir_changed) {
-                       dir_changed = 0;
-+                      printerr(2, "pipefs root dir changed\n");
-                       if (update_client_list()) {
-                               printerr(0, "ERROR: couldn't update "
-                                        "client list\n");
--                              exit(1);
-+                              goto out;
-                       }
-               }
-+
-+              /* every 5s cleanup possible zombies of child processes */
-+              if (time(NULL) - child_check >= 5) {
-+                      printerr(3, "check zombie children...\n");
-+
-+                      while (1) {
-+                              child_pid = waitpid(-1, NULL, WNOHANG);
-+                              if (child_pid <= 0)
-+                                      break;
-+
-+                              printerr(2, "terminate zombie child: %d\n",
-+                                       child_pid);
-+                      }
-+
-+                      child_check = time(NULL);
-+              }
-+
-               /* race condition here: dir_changed could be set before we
-                * enter the poll, and we'd never notice if it weren't for the
-                * timeout. */
-@@ -139,6 +163,7 @@ gssd_run()
-                       scan_poll_results(ret);
-               }
-       }
-+out:
-       close(fd);
-       return;
- }
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd_proc.c nfs-utils-1.0.11/utils/gssd/gssd_proc.c
---- nfs-utils-1.0.11.lustre/utils/gssd/gssd_proc.c     2008-01-02 17:22:48.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/gssd_proc.c    2008-01-02 18:11:38.000000000 -0700
-@@ -43,7 +43,6 @@
- #endif
- #include "config.h"
- #include <sys/param.h>
--#include <rpc/rpc.h>
- #include <sys/stat.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
-@@ -69,6 +68,7 @@
- #include "gss_oids.h"
- #include "krb5_util.h"
- #include "context.h"
-+#include "lsupport.h"
- /*
-  * pollarray:
-@@ -99,86 +99,10 @@ struct pollfd * pollarray;
- int pollsize;  /* the size of pollaray (in pollfd's) */
--/* XXX buffer problems: */
--static int
--read_service_info(char *info_file_name, char **servicename, char **servername,
--                int *prog, int *vers, char **protocol) {
--#define INFOBUFLEN 256
--      char            buf[INFOBUFLEN];
--      static char     dummy[128];
--      int             nbytes;
--      static char     service[128];
--      static char     address[128];
--      char            program[16];
--      char            version[16];
--      char            protoname[16];
--      in_addr_t       inaddr;
--      int             fd = -1;
--      struct hostent  *ent = NULL;
--      int             numfields;
--
--      *servicename = *servername = *protocol = NULL;
--
--      if ((fd = open(info_file_name, O_RDONLY)) == -1) {
--              printerr(0, "ERROR: can't open %s: %s\n", info_file_name,
--                       strerror(errno));
--              goto fail;
--      }
--      if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1)
--              goto fail;
--      close(fd);
--
--      numfields = sscanf(buf,"RPC server: %127s\n"
--                 "service: %127s %15s version %15s\n"
--                 "address: %127s\n"
--                 "protocol: %15s\n",
--                 dummy,
--                 service, program, version,
--                 address,
--                 protoname);
--
--      if (numfields == 5) {
--              strcpy(protoname, "tcp");
--      } else if (numfields != 6) {
--              goto fail;
--      }
--
--      /* check service, program, and version */
--      if(memcmp(service, "nfs", 3)) return -1;
--      *prog = atoi(program + 1); /* skip open paren */
--      *vers = atoi(version);
--      if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4)))
--              goto fail;
--
--      /* create service name */
--      inaddr = inet_addr(address);
--      if (!(ent = gethostbyaddr(&inaddr, sizeof(inaddr), AF_INET))) {
--              printerr(0, "ERROR: can't resolve server %s name\n", address);
--              goto fail;
--      }
--      if (!(*servername = calloc(strlen(ent->h_name) + 1, 1)))
--              goto fail;
--      memcpy(*servername, ent->h_name, strlen(ent->h_name));
--      snprintf(buf, INFOBUFLEN, "%s@%s", service, ent->h_name);
--      if (!(*servicename = calloc(strlen(buf) + 1, 1)))
--              goto fail;
--      memcpy(*servicename, buf, strlen(buf));
--
--      if (!(*protocol = strdup(protoname)))
--              goto fail;
--      return 0;
--fail:
--      printerr(0, "ERROR: failed to read service info\n");
--      if (fd != -1) close(fd);
--      if (*servername) free(*servername);
--      if (*servicename) free(*servicename);
--      if (*protocol) free(*protocol);
--      return -1;
--}
--
- static void
- destroy_client(struct clnt_info *clp)
- {
-+      printerr(3, "clp %p: dirname %s, krb5fd %d\n", clp, clp->dirname, clp->krb5_fd);
-       if (clp->krb5_poll_index != -1)
-               memset(&pollarray[clp->krb5_poll_index], 0,
-                                       sizeof(struct pollfd));
-@@ -190,8 +114,6 @@ destroy_client(struct clnt_info *clp)
-       if (clp->spkm3_fd != -1) close(clp->spkm3_fd);
-       if (clp->dirname) free(clp->dirname);
-       if (clp->servicename) free(clp->servicename);
--      if (clp->servername) free(clp->servername);
--      if (clp->protocol) free(clp->protocol);
-       free(clp);
- }
-@@ -221,7 +143,6 @@ process_clnt_dir_files(struct clnt_info 
- {
-       char    kname[32];
-       char    sname[32];
--      char    info_file_name[32];
-       if (clp->krb5_fd == -1) {
-               snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname);
-@@ -233,13 +154,6 @@ process_clnt_dir_files(struct clnt_info 
-       }
-       if((clp->krb5_fd == -1) && (clp->spkm3_fd == -1))
-               return -1;
--      snprintf(info_file_name, sizeof(info_file_name), "%s/info",
--                      clp->dirname);
--      if ((clp->servicename == NULL) &&
--           read_service_info(info_file_name, &clp->servicename,
--                              &clp->servername, &clp->prog, &clp->vers,
--                              &clp->protocol))
--              return -1;
-       return 0;
- }
-@@ -273,6 +187,8 @@ insert_clnt_poll(struct clnt_info *clp)
-               }
-               pollarray[clp->krb5_poll_index].fd = clp->krb5_fd;
-               pollarray[clp->krb5_poll_index].events |= POLLIN;
-+              printerr(2, "monitoring krb5 channel under %s\n",
-+                       clp->dirname);
-       }
-       if ((clp->spkm3_fd != -1) && (clp->spkm3_poll_index == -1)) {
-@@ -386,67 +302,106 @@ find_client(char *dirname)
- int
- update_client_list(void)
- {
--      struct dirent **namelist;
-+      char lustre_dir[PATH_MAX];
-+      struct dirent lustre_dirent = { .d_name = "lustre" };
-+      struct dirent *namelist[1];
-+      struct stat statbuf;
-       int i, j;
--      if (chdir(pipefs_nfsdir) < 0) {
-+      if (chdir(pipefs_dir) < 0) {
-               printerr(0, "ERROR: can't chdir to %s: %s\n",
--                       pipefs_nfsdir, strerror(errno));
-+                       pipefs_dir, strerror(errno));
-               return -1;
-       }
--      j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort);
--      if (j < 0) {
--              printerr(0, "ERROR: can't scandir %s: %s\n",
--                       pipefs_nfsdir, strerror(errno));
--              return -1;
-+      snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefs_dir, "lustre");
-+      if (stat(lustre_dir, &statbuf) == 0) {
-+              namelist[0] = &lustre_dirent;
-+              j = 1;
-+              printerr(2, "re-processing lustre directory\n");
-+      } else {
-+              namelist[0] = NULL;
-+              j = 0;
-+              printerr(2, "lustre directory not exist\n");
-       }
-+
-       update_old_clients(namelist, j);
-       for (i=0; i < j; i++) {
--              if (i < FD_ALLOC_BLOCK
--                              && !strncmp(namelist[i]->d_name, "clnt", 4)
--                              && !find_client(namelist[i]->d_name))
-+              if (i < FD_ALLOC_BLOCK && !find_client(namelist[i]->d_name))
-                       process_clnt_dir(namelist[i]->d_name);
--              free(namelist[i]);
-       }
--      free(namelist);
-+      chdir("/");
-       return 0;
- }
-+/* Context creation response. */
-+struct lustre_gss_init_res {
-+        gss_buffer_desc gr_ctx;         /* context handle */
-+        u_int           gr_major;       /* major status */
-+        u_int           gr_minor;       /* minor status */
-+        u_int           gr_win;         /* sequence window */
-+        gss_buffer_desc gr_token;       /* token */
-+};
-+
-+struct lustre_gss_data {
-+        int             lgd_established;
-+        int             lgd_lustre_svc; /* mds/oss */
-+        int             lgd_uid;        /* uid */
-+        char           *lgd_uuid;       /* client device uuid */
-+        gss_name_t      lgd_name;       /* service name */
-+
-+        gss_OID         lgd_mech;       /* mech OID */
-+        u_int           lgd_req_flags;  /* request flags */
-+        gss_cred_id_t   lgd_cred;       /* credential */
-+        gss_ctx_id_t    lgd_ctx;        /* session context */
-+        gss_buffer_desc lgd_rmt_ctx;    /* remote handle of context */
-+        uint32_t        lgd_seq_win;    /* sequence window */
-+
-+        int             lgd_rpc_err;
-+        int             lgd_gss_err;
-+};
-+
- static int
--do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
--          gss_buffer_desc *context_token)
-+do_downcall(int k5_fd, struct lgssd_upcall_data *updata,
-+            struct lustre_gss_data *lgd, gss_buffer_desc *context_token)
- {
-       char    *buf = NULL, *p = NULL, *end = NULL;
-       unsigned int timeout = 0; /* XXX decide on a reasonable value */
-       unsigned int buf_size = 0;
--      printerr(1, "doing downcall\n");
--      buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) +
--              sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length +
-+      printerr(2, "doing downcall\n");
-+      buf_size = sizeof(updata->seq) + sizeof(timeout) +
-+              sizeof(lgd->lgd_seq_win) +
-+              sizeof(lgd->lgd_rmt_ctx.length) + lgd->lgd_rmt_ctx.length +
-               sizeof(context_token->length) + context_token->length;
-       p = buf = malloc(buf_size);
-       end = buf + buf_size;
--      if (WRITE_BYTES(&p, end, uid)) goto out_err;
-+      if (WRITE_BYTES(&p, end, updata->seq)) goto out_err;
-       /* Not setting any timeout for now: */
-       if (WRITE_BYTES(&p, end, timeout)) goto out_err;
--      if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err;
--      if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err;
-+      if (WRITE_BYTES(&p, end, lgd->lgd_seq_win)) goto out_err;
-+      if (write_buffer(&p, end, &lgd->lgd_rmt_ctx)) goto out_err;
-       if (write_buffer(&p, end, context_token)) goto out_err;
--      if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
-+      lgssd_mutex_get(lgssd_mutex_downcall);
-+      if (write(k5_fd, buf, p - buf) < p - buf) {
-+              lgssd_mutex_put(lgssd_mutex_downcall);
-+              goto out_err;
-+      }
-+      lgssd_mutex_put(lgssd_mutex_downcall);
-+
-       if (buf) free(buf);
-       return 0;
- out_err:
-       if (buf) free(buf);
--      printerr(0, "Failed to write downcall!\n");
-+      printerr(0, "ERROR: Failed to write downcall!\n");
-       return -1;
- }
- static int
--do_error_downcall(int k5_fd, uid_t uid, int err)
-+do_error_downcall(int k5_fd, uint32_t seq, int rpc_err, int gss_err)
- {
-       char    buf[1024];
-       char    *p = buf, *end = buf + 1024;
-@@ -455,19 +410,26 @@ do_error_downcall(int k5_fd, uid_t uid, 
-       printerr(1, "doing error downcall\n");
--      if (WRITE_BYTES(&p, end, uid)) goto out_err;
-+      if (WRITE_BYTES(&p, end, seq)) goto out_err;
-       if (WRITE_BYTES(&p, end, timeout)) goto out_err;
-       /* use seq_win = 0 to indicate an error: */
-       if (WRITE_BYTES(&p, end, zero)) goto out_err;
--      if (WRITE_BYTES(&p, end, err)) goto out_err;
-+      if (WRITE_BYTES(&p, end, rpc_err)) goto out_err;
-+      if (WRITE_BYTES(&p, end, gss_err)) goto out_err;
--      if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
-+      lgssd_mutex_get(lgssd_mutex_downcall);
-+      if (write(k5_fd, buf, p - buf) < p - buf) {
-+              lgssd_mutex_put(lgssd_mutex_downcall);
-+              goto out_err;
-+      }
-+      lgssd_mutex_put(lgssd_mutex_downcall);
-       return 0;
- out_err:
-       printerr(0, "Failed to write error downcall!\n");
-       return -1;
- }
-+#if 0
- /*
-  * Create an RPC connection and establish an authenticated
-  * gss context with a server.
-@@ -659,7 +621,287 @@ int create_auth_rpc_client(struct clnt_i
-       goto out;
- }
-+#endif
-+
-+static
-+int do_negotiation(struct lustre_gss_data *lgd,
-+                 gss_buffer_desc *gss_token,
-+                 struct lustre_gss_init_res *gr,
-+                 int timeout)
-+{
-+      char *file = "/proc/fs/lustre/sptlrpc/gss/init_channel";
-+      struct lgssd_ioctl_param param;
-+      struct passwd *pw;
-+      int fd, ret;
-+      char outbuf[8192];
-+      unsigned int *p;
-+      int res;
-+
-+      pw = getpwuid(lgd->lgd_uid);
-+      if (!pw) {
-+              printerr(0, "no uid %u in local user database\n",
-+                       lgd->lgd_uid);
-+              return -1;
-+      }
-+
-+      param.version = GSSD_INTERFACE_VERSION;
-+      param.uuid = lgd->lgd_uuid;
-+      param.lustre_svc = lgd->lgd_lustre_svc;
-+      param.uid = lgd->lgd_uid;
-+      param.gid = pw->pw_gid;
-+      param.send_token_size = gss_token->length;
-+      param.send_token = (char *) gss_token->value;
-+      param.reply_buf_size = sizeof(outbuf);
-+      param.reply_buf = outbuf;
-+
-+      fd = open(file, O_RDWR);
-+      if (fd < 0) {
-+              printerr(0, "can't open file %s\n", file);
-+              return -1;
-+      }
-+
-+      ret = write(fd, &param, sizeof(param));
-+
-+      if (ret != sizeof(param)) {
-+              printerr(0, "lustre ioctl err: %d\n", strerror(errno));
-+              close(fd);
-+              return -1;
-+      }
-+      if (param.status) {
-+              close(fd);
-+              printerr(0, "status: %d (%s)\n",
-+                       param.status, strerror((int)param.status));
-+              if (param.status == -ETIMEDOUT) {
-+                      /* kernel return -ETIMEDOUT means the rpc timedout,
-+                       * we should notify the caller to reinitiate the
-+                       * gss negotiation, by return -ERESTART
-+                       */
-+                      lgd->lgd_rpc_err = -ERESTART;
-+                      lgd->lgd_gss_err = 0;
-+              } else {
-+                      lgd->lgd_rpc_err = param.status;
-+                      lgd->lgd_gss_err = 0;
-+              }
-+              return -1;
-+      }
-+      p = (unsigned int *)outbuf;
-+      res = *p++;
-+      gr->gr_major = *p++;
-+      gr->gr_minor = *p++;
-+      gr->gr_win = *p++;
-+
-+      gr->gr_ctx.length = *p++;
-+      gr->gr_ctx.value = malloc(gr->gr_ctx.length);
-+      memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length);
-+      p += (((gr->gr_ctx.length + 3) & ~3) / 4);
-+
-+      gr->gr_token.length = *p++;
-+      gr->gr_token.value = malloc(gr->gr_token.length);
-+      memcpy(gr->gr_token.value, p, gr->gr_token.length);
-+      p += (((gr->gr_token.length + 3) & ~3) / 4);
-+
-+      printerr(2, "do_negotiation: receive handle len %d, token len %d\n",
-+               gr->gr_ctx.length, gr->gr_token.length);
-+      close(fd);
-+      return 0;
-+}
-+
-+static
-+int gssd_refresh_lgd(struct lustre_gss_data *lgd)
-+{
-+      struct lustre_gss_init_res gr;
-+      gss_buffer_desc         *recv_tokenp, send_token;
-+      OM_uint32                maj_stat, min_stat, call_stat, ret_flags;
-+
-+      /* GSS context establishment loop. */
-+      memset(&gr, 0, sizeof(gr));
-+      recv_tokenp = GSS_C_NO_BUFFER;
-+
-+      for (;;) {
-+              /* print the token we just received */
-+              if (recv_tokenp != GSS_C_NO_BUFFER) {
-+                      printerr(3, "The received token length %d\n",
-+                               recv_tokenp->length);
-+                      print_hexl(3, recv_tokenp->value, recv_tokenp->length);
-+              }
-+
-+              maj_stat = gss_init_sec_context(&min_stat,
-+                                              lgd->lgd_cred,
-+                                              &lgd->lgd_ctx,
-+                                              lgd->lgd_name,
-+                                              lgd->lgd_mech,
-+                                              lgd->lgd_req_flags,
-+                                              0,              /* time req */
-+                                              NULL,           /* channel */
-+                                              recv_tokenp,
-+                                              NULL,           /* used mech */
-+                                              &send_token,
-+                                              &ret_flags,
-+                                              NULL);          /* time rec */
-+
-+              if (recv_tokenp != GSS_C_NO_BUFFER) {
-+                      gss_release_buffer(&min_stat, &gr.gr_token);
-+                      recv_tokenp = GSS_C_NO_BUFFER;
-+              }
-+              if (maj_stat != GSS_S_COMPLETE &&
-+                  maj_stat != GSS_S_CONTINUE_NEEDED) {
-+                      pgsserr("gss_init_sec_context", maj_stat, min_stat,
-+                              lgd->lgd_mech);
-+                      break;
-+              }
-+              if (send_token.length != 0) {
-+                      memset(&gr, 0, sizeof(gr));
-+
-+                      /* print the token we are about to send */
-+                      printerr(3, "token being sent length %d\n",
-+                               send_token.length);
-+                      print_hexl(3, send_token.value, send_token.length);
-+
-+                      call_stat = do_negotiation(lgd, &send_token, &gr, 0);
-+                      gss_release_buffer(&min_stat, &send_token);
-+
-+                      if (call_stat != 0 ||
-+                          (gr.gr_major != GSS_S_COMPLETE &&
-+                           gr.gr_major != GSS_S_CONTINUE_NEEDED)) {
-+                              printerr(0, "call stat %d, major stat 0x%x\n",
-+                                       (int)call_stat, gr.gr_major);
-+                              return -1;
-+                      }
-+
-+                      if (gr.gr_ctx.length != 0) {
-+                              if (lgd->lgd_rmt_ctx.value)
-+                                      gss_release_buffer(&min_stat,
-+                                                         &lgd->lgd_rmt_ctx);
-+                              lgd->lgd_rmt_ctx = gr.gr_ctx;
-+                      }
-+                      if (gr.gr_token.length != 0) {
-+                              if (maj_stat != GSS_S_CONTINUE_NEEDED)
-+                                      break;
-+                              recv_tokenp = &gr.gr_token;
-+                      }
-+              }
-+
-+              /* GSS_S_COMPLETE => check gss header verifier,
-+               * usually checked in gss_validate
-+               */
-+              if (maj_stat == GSS_S_COMPLETE) {
-+                      lgd->lgd_established = 1;
-+                      lgd->lgd_seq_win = gr.gr_win;
-+                      break;
-+              }
-+      }
-+      /* End context negotiation loop. */
-+      if (!lgd->lgd_established) {
-+              if (gr.gr_token.length != 0)
-+                      gss_release_buffer(&min_stat, &gr.gr_token);
-+
-+              printerr(0, "context negotiation failed\n");
-+              return -1;
-+      }
-+
-+      printerr(2, "successfully refreshed lgd\n");
-+      return 0;
-+}
-+static
-+int gssd_create_lgd(struct clnt_info *clp,
-+                  struct lustre_gss_data *lgd,
-+                  struct lgssd_upcall_data *updata,
-+                  int authtype)
-+{
-+      gss_buffer_desc         sname;
-+      OM_uint32               maj_stat, min_stat;
-+      int                     retval = -1;
-+
-+      lgd->lgd_established = 0;
-+      lgd->lgd_lustre_svc = updata->svc;
-+      lgd->lgd_uid = updata->uid;
-+      lgd->lgd_uuid = updata->obd;
-+
-+      switch (authtype) {
-+      case AUTHTYPE_KRB5:
-+              lgd->lgd_mech = (gss_OID) &krb5oid;
-+              lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG;
-+              break;
-+      case AUTHTYPE_SPKM3:
-+              lgd->lgd_mech = (gss_OID) &spkm3oid;
-+              /* XXX sec.req_flags = GSS_C_ANON_FLAG;
-+               * Need a way to switch....
-+               */
-+              lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG;
-+              break;
-+      default:
-+              printerr(0, "Invalid authentication type (%d)\n", authtype);
-+              return -1;
-+      }
-+
-+      lgd->lgd_cred = GSS_C_NO_CREDENTIAL;
-+      lgd->lgd_ctx = GSS_C_NO_CONTEXT;
-+      lgd->lgd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER;
-+      lgd->lgd_seq_win = 0;
-+
-+      sname.value = clp->servicename;
-+      sname.length = strlen(clp->servicename);
-+
-+      maj_stat = gss_import_name(&min_stat, &sname,
-+                                 (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
-+                                 &lgd->lgd_name);
-+      if (maj_stat != GSS_S_COMPLETE) {
-+              pgsserr(0, maj_stat, min_stat, lgd->lgd_mech);
-+              goto out_fail;
-+      }
-+
-+      retval = gssd_refresh_lgd(lgd);
-+
-+      if (lgd->lgd_name != GSS_C_NO_NAME)
-+              gss_release_name(&min_stat, &lgd->lgd_name);
-+
-+      if (lgd->lgd_cred != GSS_C_NO_CREDENTIAL)
-+              gss_release_cred(&min_stat, &lgd->lgd_cred);
-+
-+  out_fail:
-+      return retval;
-+}
-+
-+static
-+void gssd_free_lgd(struct lustre_gss_data *lgd)
-+{
-+      gss_buffer_t            token = GSS_C_NO_BUFFER;
-+      OM_uint32               maj_stat, min_stat;
-+
-+      if (lgd->lgd_ctx == GSS_C_NO_CONTEXT)
-+              return;
-+
-+      maj_stat = gss_delete_sec_context(&min_stat, &lgd->lgd_ctx, token);
-+}
-+
-+static
-+int construct_service_name(struct clnt_info *clp,
-+                           struct lgssd_upcall_data *ud)
-+{
-+        const int buflen = 256;
-+        char name[buflen];
-+
-+        if (clp->servicename) {
-+                free(clp->servicename);
-+                clp->servicename = NULL;
-+        }
-+
-+        if (lnet_nid2hostname(ud->nid, name, buflen))
-+                return -1;
-+
-+        clp->servicename = malloc(32 + strlen(name));
-+        if (!clp->servicename) {
-+                printerr(0, "can't alloc memory\n");
-+                return -1;
-+        }
-+        sprintf(clp->servicename, "%s@%s",
-+                ud->svc == LUSTRE_GSS_SVC_MDS ?
-+              GSSD_SERVICE_MDS : GSSD_SERVICE_OSS,
-+                name);
-+        printerr(2, "constructed servicename: %s\n", clp->servicename);
-+        return 0;
-+}
- /*
-  * this code uses the userland rpcsec gss library to create a krb5
-@@ -668,103 +910,145 @@ int create_auth_rpc_client(struct clnt_i
- void
- handle_krb5_upcall(struct clnt_info *clp)
- {
--      uid_t                   uid;
--      CLIENT                  *rpc_clnt = NULL;
--      AUTH                    *auth = NULL;
--      struct authgss_private_data pd;
--      gss_buffer_desc         token;
-+      pid_t                   pid;
-+      gss_buffer_desc         token = { 0, NULL };
-+      struct lgssd_upcall_data updata;
-+      struct lustre_gss_data  lgd;
-       char                    **credlist = NULL;
-       char                    **ccname;
-+      int                     read_rc;
--      printerr(1, "handling krb5 upcall\n");
-+      printerr(2, "handling krb5 upcall\n");
--      token.length = 0;
--      token.value = NULL;
--      memset(&pd, 0, sizeof(struct authgss_private_data));
-+      memset(&lgd, 0, sizeof(lgd));
-+      lgd.lgd_rpc_err = -EPERM; /* default error code */
--      if (read(clp->krb5_fd, &uid, sizeof(uid)) < sizeof(uid)) {
--              printerr(0, "WARNING: failed reading uid from krb5 "
-+      read_rc = read(clp->krb5_fd, &updata, sizeof(updata));
-+      if (read_rc < 0) {
-+              printerr(0, "WARNING: failed reading from krb5 "
-                           "upcall pipe: %s\n", strerror(errno));
--              goto out;
-+              return;
-+      } else if (read_rc != sizeof(updata)) {
-+              printerr(0, "upcall data mismatch: length %d, expect %d\n",
-+                       read_rc, sizeof(updata));
-+
-+              /* the sequence number must be the first field. if read >= 4
-+               * bytes then we know at least sequence is fine, try to send
-+               * error notification nicely.
-+               */
-+              if (read_rc >= 4)
-+                      do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
-+              return;
-+      }
-+
-+      /* FIXME temporary fix, do this before fork.
-+       * in case of errors could have memory leak!!!
-+       */
-+      if (updata.uid == 0) {
-+              if (gssd_get_krb5_machine_cred_list(&credlist)) {
-+                      printerr(0, "ERROR: Failed to obtain machine "
-+                                  "credentials\n");
-+                      do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
-+                      return;
-+              }
-+      }
-+
-+      /* fork child process */
-+      pid = fork();
-+      if (pid < 0) {
-+              printerr(0, "can't fork: %s\n", strerror(errno));
-+              do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
-+              return;
-+      } else if (pid > 0) {
-+              printerr(2, "forked child process: %d\n", pid);
-+              return;
-+      }
-+
-+      printerr(1, "krb5 upcall: seq %u, uid %u, svc %u, nid 0x%llx, obd %s\n",
-+               updata.seq, updata.uid, updata.svc, updata.nid, updata.obd);
-+
-+      if (updata.svc != LUSTRE_GSS_SVC_MDS &&
-+          updata.svc != LUSTRE_GSS_SVC_OSS) {
-+              printerr(0, "invalid svc %d\n", updata.svc);
-+              lgd.lgd_rpc_err = -EPROTO;
-+              goto out_return_error;
-+      }
-+      updata.obd[sizeof(updata.obd)-1] = '\0';
-+
-+      if (construct_service_name(clp, &updata)) {
-+              printerr(0, "failed to construct service name\n");
-+              goto out_return_error;
-       }
--      if (uid == 0) {
-+      if (updata.uid == 0) {
-               int success = 0;
-               /*
-                * Get a list of credential cache names and try each
-                * of them until one works or we've tried them all
-                */
-+/*
-               if (gssd_get_krb5_machine_cred_list(&credlist)) {
--                      printerr(0, "WARNING: Failed to obtain machine "
--                                  "credentials for connection to "
--                                  "server %s\n", clp->servername);
--                              goto out_return_error;
-+                      printerr(0, "ERROR: Failed to obtain machine "
-+                                  "credentials for %s\n", clp->servicename);
-+                      goto out_return_error;
-               }
-+*/
-               for (ccname = credlist; ccname && *ccname; ccname++) {
-                       gssd_setup_krb5_machine_gss_ccache(*ccname);
--                      if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
--                                                  AUTHTYPE_KRB5)) == 0) {
-+                      if ((gssd_create_lgd(clp, &lgd, &updata,
-+                                           AUTHTYPE_KRB5)) == 0) {
-                               /* Success! */
-                               success++;
-                               break;
-                       }
-                       printerr(2, "WARNING: Failed to create krb5 context "
-                                   "for user with uid %d with credentials "
--                                  "cache %s for server %s\n",
--                               uid, *ccname, clp->servername);
-+                                  "cache %s for service %s\n",
-+                               updata.uid, *ccname, clp->servicename);
-               }
-               gssd_free_krb5_machine_cred_list(credlist);
-               if (!success) {
--                      printerr(0, "WARNING: Failed to create krb5 context "
-+                      printerr(0, "ERROR: Failed to create krb5 context "
-                                   "for user with uid %d with any "
--                                  "credentials cache for server %s\n",
--                               uid, clp->servername);
-+                                  "credentials cache for service %s\n",
-+                               updata.uid, clp->servicename);
-                       goto out_return_error;
-               }
-       }
-       else {
-               /* Tell krb5 gss which credentials cache to use */
--              gssd_setup_krb5_user_gss_ccache(uid, clp->servername);
-+              gssd_setup_krb5_user_gss_ccache(updata.uid, clp->servicename);
--              if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
--                                                      AUTHTYPE_KRB5)) != 0) {
-+              if ((gssd_create_lgd(clp, &lgd, &updata, AUTHTYPE_KRB5)) != 0) {
-                       printerr(0, "WARNING: Failed to create krb5 context "
--                                  "for user with uid %d for server %s\n",
--                               uid, clp->servername);
-+                                  "for user with uid %d for service %s\n",
-+                               updata.uid, clp->servicename);
-                       goto out_return_error;
-               }
-       }
--      if (!authgss_get_private_data(auth, &pd)) {
--              printerr(0, "WARNING: Failed to obtain authentication "
--                          "data for user with uid %d for server %s\n",
--                       uid, clp->servername);
--              goto out_return_error;
--      }
--
--      if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid)) {
-+      if (serialize_context_for_kernel(lgd.lgd_ctx, &token, &krb5oid)) {
-               printerr(0, "WARNING: Failed to serialize krb5 context for "
--                          "user with uid %d for server %s\n",
--                       uid, clp->servername);
-+                          "user with uid %d for service %s\n",
-+                       updata.uid, clp->servicename);
-               goto out_return_error;
-       }
--      do_downcall(clp->krb5_fd, uid, &pd, &token);
-+      printerr(1, "refreshed: %u@%s for %s\n",
-+               updata.uid, updata.obd, clp->servicename);
-+      do_downcall(clp->krb5_fd, &updata, &lgd, &token);
- out:
-       if (token.value)
-               free(token.value);
--      if (pd.pd_ctx_hndl.length != 0)
--              authgss_free_private_data(&pd);
--      if (auth)
--              AUTH_DESTROY(auth);
--      if (rpc_clnt)
--              clnt_destroy(rpc_clnt);
--      return;
-+
-+      gssd_free_lgd(&lgd);
-+      exit(0); /* i'm child process */
- out_return_error:
--      do_error_downcall(clp->krb5_fd, uid, -1);
-+      do_error_downcall(clp->krb5_fd, updata.seq,
-+                        lgd.lgd_rpc_err, lgd.lgd_gss_err);
-       goto out;
- }
-@@ -775,6 +1059,7 @@ out_return_error:
- void
- handle_spkm3_upcall(struct clnt_info *clp)
- {
-+#if 0
-       uid_t                   uid;
-       CLIENT                  *rpc_clnt = NULL;
-       AUTH                    *auth = NULL;
-@@ -826,4 +1111,5 @@ out:
- out_return_error:
-       do_error_downcall(clp->spkm3_fd, uid, -1);
-       goto out;
-+#endif
- }
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gss_util.c nfs-utils-1.0.11/utils/gssd/gss_util.c
---- nfs-utils-1.0.11.lustre/utils/gssd/gss_util.c      2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/gss_util.c     2008-01-02 18:11:38.000000000 -0700
-@@ -87,9 +87,16 @@
- #ifdef HAVE_COM_ERR_H
- #include <com_err.h>
- #endif
-+#include "lsupport.h"
- /* Global gssd_credentials handle */
--gss_cred_id_t gssd_creds;
-+gss_cred_id_t  gssd_cred_mds;
-+gss_cred_id_t  gssd_cred_oss;
-+int            gssd_cred_mds_valid = 0;
-+int            gssd_cred_oss_valid = 0;
-+
-+char *mds_local_realm = NULL;
-+char *oss_local_realm = NULL;
- gss_OID g_mechOid = GSS_C_NULL_OID;;
-@@ -183,15 +190,56 @@ pgsserr(char *msg, u_int32_t maj_stat, u
-       display_status_2(msg, maj_stat, min_stat, mech);
- }
--int
--gssd_acquire_cred(char *server_name)
-+static
-+int extract_realm_name(gss_buffer_desc *name, char **realm)
-+{
-+        char *sname, *c;
-+      int   rc = 0;
-+
-+        sname = malloc(name->length + 1);
-+        if (!sname) {
-+                printerr(0, "out of memory\n");
-+                return -ENOMEM;
-+        }
-+
-+        memcpy(sname, name->value, name->length);
-+        sname[name->length] = '\0';
-+        printerr(1, "service principal: %s\n", sname);
-+
-+        c = strchr(sname, '@');
-+        if (!c) {
-+              printerr(2, "no realm found in principal, use default\n");
-+              *realm = strdup(this_realm);
-+                if (!*realm) {
-+                        printerr(0, "failed to duplicate default realm\n");
-+                        rc = -ENOMEM;
-+                }
-+        } else {
-+                c++;
-+                *realm = strdup(c);
-+                if (!*realm) {
-+                        printerr(0, "failed to duplicated realm\n");
-+                        rc = -ENOMEM;
-+                }
-+        }
-+        free(sname);
-+
-+        return rc;
-+}
-+
-+static
-+int gssd_acquire_cred(char *server_name, gss_cred_id_t *cred,
-+                    char **local_realm, int *valid)
- {
-       gss_buffer_desc name;
-       gss_name_t target_name;
-       u_int32_t maj_stat, min_stat;
-       u_int32_t ignore_maj_stat, ignore_min_stat;
-+      gss_OID name_type;
-       gss_buffer_desc pbuf;
-+      *valid = 0;
-+
-       name.value = (void *)server_name;
-       name.length = strlen(server_name);
-@@ -201,12 +249,20 @@ gssd_acquire_cred(char *server_name)
-       if (maj_stat != GSS_S_COMPLETE) {
-               pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid);
--              return (FALSE);
-+              return -1;
-+      }
-+
-+      maj_stat = gss_display_name(&min_stat, target_name, &name, &name_type);
-+      if (maj_stat != GSS_S_COMPLETE) {
-+              pgsserr(0, maj_stat, min_stat, g_mechOid);
-+              return -1;
-       }
-+      if (extract_realm_name(&name, local_realm))
-+              return -1;
-       maj_stat = gss_acquire_cred(&min_stat, target_name, 0,
-                       GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
--                      &gssd_creds, NULL, NULL);
-+                      cred, NULL, NULL);
-       if (maj_stat != GSS_S_COMPLETE) {
-               pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid);
-@@ -218,11 +274,67 @@ gssd_acquire_cred(char *server_name)
-                       ignore_maj_stat = gss_release_buffer(&ignore_min_stat,
-                                                            &pbuf);
-               }
--      }
-+      } else
-+              *valid = 1;
-       ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name);
--      return (maj_stat == GSS_S_COMPLETE);
-+      if (maj_stat != GSS_S_COMPLETE)
-+              return -1;
-+      return 0;
-+}
-+
-+int gssd_prepare_creds(int must_srv_mds, int must_srv_oss)
-+{
-+        if (gssd_acquire_cred(GSSD_SERVICE_MDS, &gssd_cred_mds,
-+                              &mds_local_realm, &gssd_cred_mds_valid)) {
-+                if (must_srv_mds)
-+                        return -1;
-+        }
-+
-+        if (gssd_acquire_cred(GSSD_SERVICE_OSS, &gssd_cred_oss,
-+                              &oss_local_realm, &gssd_cred_oss_valid)) {
-+                if (must_srv_oss)
-+                        return -1;
-+        }
-+
-+        if (!gssd_cred_mds_valid && !gssd_cred_oss_valid) {
-+                printerr(0, "can't obtain both mds & oss creds, exit\n");
-+                return -1;
-+        }
-+
-+      if (gssd_cred_mds_valid)
-+              printerr(0, "Ready to serve Lustre MDS in realm %s\n",
-+                       mds_local_realm ? mds_local_realm : "N/A");
-+      if (gssd_cred_oss_valid)
-+              printerr(0, "Ready to serve Lustre OSS in realm %s\n",
-+                       oss_local_realm ? oss_local_realm : "N/A");
-+
-+        return 0;
-+}
-+
-+gss_cred_id_t gssd_select_svc_cred(int lustre_svc)
-+{
-+        switch (lustre_svc) {
-+        case LUSTRE_GSS_SVC_MDS:
-+                if (!gssd_cred_mds_valid) {
-+                        printerr(0, "ERROR: service cred for mds not ready\n");
-+                        return NULL;
-+                }
-+              printerr(2, "select mds service cred\n");
-+                return gssd_cred_mds;
-+        case LUSTRE_GSS_SVC_OSS:
-+                if (!gssd_cred_oss_valid) {
-+                        printerr(0, "ERROR: service cred for oss not ready\n");
-+                        return NULL;
-+                }
-+              printerr(2, "select oss service cred\n");
-+                return gssd_cred_oss;
-+        default:
-+                printerr(0, "ERROR: invalid lustre svc id %d\n", lustre_svc);
-+        }
-+
-+        return NULL;
- }
- int gssd_check_mechs(void)
-@@ -249,3 +361,42 @@ out:
-       return retval;
- }
-+/*********************************
-+ * FIXME should be in krb5_util.c
-+ *********************************/
-+
-+#include "krb5_util.h"
-+
-+/* realm of this node */
-+char *this_realm = NULL;
-+
-+int gssd_get_local_realm(void)
-+{
-+      krb5_context context = NULL;
-+      krb5_error_code code;
-+      int retval = -1;
-+
-+      if (this_realm != NULL)
-+              return 0;
-+
-+      code = krb5_init_context(&context);
-+      if (code) {
-+              printerr(0, "ERROR: get default realm: init ctx: %s\n",
-+                       error_message(code));
-+              goto out;
-+      }
-+
-+      code = krb5_get_default_realm(context, &this_realm);
-+      if (code) {
-+              printerr(0, "ERROR: get default realm: %s\n",
-+                       error_message(code));
-+              goto out;
-+      }
-+      retval = 0;
-+
-+      printerr(1, "Local realm: %s\n", this_realm);
-+out:
-+      krb5_free_context(context);
-+      return retval;
-+}
-+
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gss_util.h nfs-utils-1.0.11/utils/gssd/gss_util.h
---- nfs-utils-1.0.11.lustre/utils/gssd/gss_util.h      2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/gss_util.h     2008-01-02 18:11:38.000000000 -0700
-@@ -32,14 +32,14 @@
- #define _GSS_UTIL_H_
- #include <stdlib.h>
--#include <rpc/rpc.h>
- #include "write_bytes.h"
-+char *this_realm;
- extern gss_cred_id_t  gssd_creds;
--int gssd_acquire_cred(char *server_name);
- void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat,
-       const gss_OID mech);
- int gssd_check_mechs(void);
-+int gssd_get_local_realm(void);
- #endif /* _GSS_UTIL_H_ */
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.c nfs-utils-1.0.11/utils/gssd/krb5_util.c
---- nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.c     2008-01-02 17:22:48.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/krb5_util.c    2008-01-02 18:11:38.000000000 -0700
-@@ -99,12 +99,15 @@
- #include <rpc/rpc.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-+#include <sys/utsname.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
-+#include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-+#include <netdb.h>
- #include <dirent.h>
- #include <fcntl.h>
- #include <errno.h>
-@@ -114,7 +117,6 @@
- #include <gssapi/gssapi_krb5.h>
- #endif
- #include <krb5.h>
--#include <rpc/auth_gss.h>
- #include "gssd.h"
- #include "err_util.h"
-@@ -129,6 +131,9 @@ struct gssd_k5_kt_princ *gssd_k5_kt_prin
- int num_krb5_enctypes = 0;
- krb5_enctype *krb5_enctypes = NULL;
-+/* credential expire time in advance */
-+unsigned long machine_cred_expire_advance = 300; /* 5 mins */
-+
- /*==========================*/
- /*===  Internal routines ===*/
- /*==========================*/
-@@ -137,11 +142,55 @@ static int select_krb5_ccache(const stru
- static int gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d);
- static int gssd_get_single_krb5_cred(krb5_context context,
-               krb5_keytab kt, struct gssd_k5_kt_princ *ple);
--static int gssd_have_realm_ple(void *realm);
- static int gssd_process_krb5_keytab(krb5_context context, krb5_keytab kt,
-               char *kt_name);
- /*
-+ * convenient macros, these perhaps need further cleanup
-+ */
-+#ifdef HAVE_KRB5
-+
-+#define KEYTAB_ENTRY_MATCH(kte, name)                                        \
-+      (                                                                      \
-+       (kte).principal->data[0].length == (sizeof(name)-1) &&                \
-+       strncmp((kte).principal->data[0].data, (name), sizeof(name)-1) == 0   \
-+      )
-+#define KRB5_FREE_UNPARSED_NAME(ctx, name)                                   \
-+              krb5_free_unparsed_name((ctx), (name));
-+#define KRB5_STRDUP(str)                                                     \
-+              strndup((str).data, (str).length)
-+#define KRB5_STRCMP(str, name)                                                       \
-+      (                                                                      \
-+       (str)->length != strlen(name) ||                                      \
-+       strncmp((str)->data, (name), (str)->length) != 0                      \
-+      )
-+#define KRB5_STRCASECMP(str, name)                                           \
-+      (                                                                      \
-+       (str)->length != strlen(name) ||                                      \
-+       strncasecmp((str)->data, (name), (str)->length) != 0                  \
-+      )
-+
-+#else /* !HAVE_KRB5 */
-+
-+#define KEYTAB_ENTRY_MATCH(kte, name)                                        \
-+      (                                                                      \
-+       strlen((kte).principal->name.name_string.val[0]) ==                   \
-+       (sizeof(name)-1) &&                                                   \
-+       strncmp(kte.principal->name.name_string.val[0], (name),               \
-+               sizeof(name)-1) == 0                                          \
-+      )
-+#define KRB5_FREE_UNPARSED_NAME(ctx, name)                                   \
-+              free(pname);
-+#define KRB5_STRDUP(str)                                                     \
-+              strdup(str)
-+#define KRB5_STRCMP(str, name)                                                       \
-+              strcmp((str), (name))
-+#define KRB5_STRCASECMP(str, name)                                           \
-+              strcmp((str), (name))
-+
-+#endif /* HAVE_KRB5 */
-+
-+/*
-  * Called from the scandir function to weed out potential krb5
-  * credentials cache files
-  *
-@@ -288,7 +337,7 @@ gssd_get_single_krb5_cred(krb5_context c
-       memset(&my_creds, 0, sizeof(my_creds));
--      if (ple->ccname && ple->endtime > now) {
-+      if (ple->ccname && ple->endtime > now + machine_cred_expire_advance) {
-               printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
-                        ple->ccname, ple->endtime);
-               code = 0;
-@@ -308,6 +357,12 @@ gssd_get_single_krb5_cred(krb5_context c
-       /* set a short lifetime (for debugging only!) */
-       printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
-       krb5_get_init_creds_opt_set_tkt_life(&options, 5*60);
-+#else
-+      /* FIXME try to get the ticket with lifetime as long as possible,
-+       * to work around ticket-expiry + recovery problem in cmd3-11
-+       * remove this!!!
-+       */
-+      krb5_get_init_creds_opt_set_tkt_life(&options, 30*24*60*60);
- #endif
-         if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ,
-                                         kt, 0, NULL, &options))) {
-@@ -319,11 +374,7 @@ gssd_get_single_krb5_cred(krb5_context c
-                           "principal '%s' from keytab '%s'\n",
-                        error_message(code),
-                        pname ? pname : "<unparsable>", kt_name);
--#ifdef HAVE_KRB5
--              if (pname) krb5_free_unparsed_name(context, pname);
--#else
--              if (pname) free(pname);
--#endif
-+              if (pname) KRB5_FREE_UNPARSED_NAME(context, pname);
-               goto out;
-       }
-@@ -372,15 +423,7 @@ gssd_get_single_krb5_cred(krb5_context c
-       return (code);
- }
--/*
-- * Determine if we already have a ple for the given realm
-- *
-- * Returns:
-- *    0 => no ple found for given realm
-- *    1 => found ple for given realm
-- */
--static int
--gssd_have_realm_ple(void *r)
-+static struct gssd_k5_kt_princ * gssd_get_realm_ple(void *r)
- {
-       struct gssd_k5_kt_princ *ple;
- #ifdef HAVE_KRB5
-@@ -390,18 +433,76 @@ gssd_have_realm_ple(void *r)
- #endif
-       for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
--#ifdef HAVE_KRB5
--              if ((realm->length == strlen(ple->realm)) &&
--                  (strncmp(realm->data, ple->realm, realm->length) == 0)) {
--#else
--              if (strcmp(realm, ple->realm) == 0) {
--#endif
--                  return 1;
--              }
-+              if (KRB5_STRCMP(realm, ple->realm) == 0)
-+                  return ple;
-+      }
-+      return NULL;
-+}
-+
-+static void gssd_free_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
-+{
-+      if (ple->princ)
-+              krb5_free_principal(kctx, ple->princ);
-+      if (ple->realm)
-+              free(ple->realm);
-+      if (ple->ccname)
-+              free(ple->ccname);
-+      free(ple);
-+}
-+
-+static int gssd_remove_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
-+{
-+      struct gssd_k5_kt_princ **prev = &gssd_k5_kt_princ_list;
-+      struct gssd_k5_kt_princ  *ent = gssd_k5_kt_princ_list;
-+
-+      for (; ent; prev = &ent->next, ent = ent->next) {
-+              if (ent != ple)
-+                      continue;
-+
-+              *prev = ent->next;
-+              gssd_free_ple(kctx, ent);
-+              return 1;
-       }
-       return 0;
- }
-+static
-+struct gssd_k5_kt_princ *gssd_create_ple(krb5_context kctx,
-+                                       krb5_principal principal)
-+{
-+      struct gssd_k5_kt_princ *ple;
-+      krb5_error_code          code;
-+
-+      ple = malloc(sizeof(*ple));
-+      if (ple == NULL) {
-+              printerr(0, "ERROR: could not allocate storage "
-+                          "for principal list entry\n");
-+              return NULL;
-+      }
-+
-+      memset(ple, 0, sizeof(*ple));
-+
-+      ple->realm = KRB5_STRDUP(principal->realm);
-+      if (ple->realm == NULL) {
-+              printerr(0, "ERROR: not enough memory while copying realm to "
-+                          "principal list entry\n");
-+              goto err_free;
-+      }
-+
-+      code = krb5_copy_principal(kctx, principal, &ple->princ);
-+      if (code) {
-+              printerr(0, "ERROR: %s while copying principal "
-+                          "to principal list entry\n",
-+                       error_message(code));
-+              goto err_free;
-+      }
-+
-+      return ple;
-+err_free:
-+      gssd_free_ple(kctx, ple);
-+      return NULL;
-+}
-+
- /*
-  * Process the given keytab file and create a list of principals we
-  * might use to perform mount operations.
-@@ -445,82 +546,106 @@ gssd_process_krb5_keytab(krb5_context co
-               }
-               printerr(2, "Processing keytab entry for principal '%s'\n",
-                        pname);
--#ifdef HAVE_KRB5
--              if ( (kte.principal->data[0].length == GSSD_SERVICE_NAME_LEN) &&
--                   (strncmp(kte.principal->data[0].data, GSSD_SERVICE_NAME,
--                            GSSD_SERVICE_NAME_LEN) == 0) &&
--#else
--              if ( (strlen(kte.principal->name.name_string.val[0]) == GSSD_SERVICE_NAME_LEN) &&
--                   (strncmp(kte.principal->name.name_string.val[0], GSSD_SERVICE_NAME,
--                            GSSD_SERVICE_NAME_LEN) == 0) &&
--                            
--#endif
--                   (!gssd_have_realm_ple((void *)&kte.principal->realm)) ) {
--                      printerr(2, "We will use this entry (%s)\n", pname);
--                      ple = malloc(sizeof(struct gssd_k5_kt_princ));
--                      if (ple == NULL) {
--                              printerr(0, "ERROR: could not allocate storage "
--                                          "for principal list entry\n");
--#ifdef HAVE_KRB5
--                              krb5_free_unparsed_name(context, pname);
--#else
--                              free(pname);
--#endif
--                              retval = ENOMEM;
--                              goto out;
--                      }
--                      /* These will be filled in later */
--                      ple->next = NULL;
--                      ple->ccname = NULL;
--                      ple->endtime = 0;
--                      if ((ple->realm =
--#ifdef HAVE_KRB5
--                              strndup(kte.principal->realm.data,
--                                      kte.principal->realm.length))
--#else
--                              strdup(kte.principal->realm))
--#endif
--                                      == NULL) {
--                              printerr(0, "ERROR: %s while copying realm to "
--                                          "principal list entry\n",
--                                       "not enough memory");
--#ifdef HAVE_KRB5
--                              krb5_free_unparsed_name(context, pname);
--#else
--                              free(pname);
--#endif
--                              retval = ENOMEM;
--                              goto out;
--                      }
--                      if ((code = krb5_copy_principal(context,
--                                      kte.principal, &ple->princ))) {
--                              printerr(0, "ERROR: %s while copying principal "
--                                          "to principal list entry\n",
--                                      error_message(code));
--#ifdef HAVE_KRB5
--                              krb5_free_unparsed_name(context, pname);
--#else
--                              free(pname);
--#endif
--                              retval = code;
--                              goto out;
--                      }
--                      if (gssd_k5_kt_princ_list == NULL)
--                              gssd_k5_kt_princ_list = ple;
--                      else {
--                              ple->next = gssd_k5_kt_princ_list;
--                              gssd_k5_kt_princ_list = ple;
-+
-+              /* mds service entry:
-+               *   - hostname and realm should match this node
-+               *   - replace existing non-mds entry of this realm
-+               */
-+              if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS)) {
-+                      krb5_principal princ = kte.principal;
-+                      krb5_data *princ_host;
-+                      struct utsname utsbuf;
-+                      struct hostent *host;
-+
-+                      if (KRB5_STRCASECMP(krb5_princ_realm(context, princ),
-+                                          this_realm) != 0) {
-+                              printerr(2, "alien mds service entry, skip\n");
-+                              goto next;
-+                      }
-+
-+                      princ_host = krb5_princ_component(context, princ, 1);
-+                      if (princ_host == NULL) {
-+                              printerr(2, "mds service entry: no hostname in "
-+                                       "principal, skip\n");
-+                              goto next;
-+                      }
-+
-+                      if (uname(&utsbuf)) {
-+                              printerr(2, "mds service entry: unable to get "
-+                                       "UTS name, skip\n");
-+                              goto next;
-+                      }
-+                      host = gethostbyname(utsbuf.nodename);
-+                      if (host == NULL) {
-+                              printerr(2, "mds service entry: unable to get "
-+                                       "local hostname, skip\n");
-+                              goto next;
-+                      }
-+
-+                      if (KRB5_STRCASECMP(princ_host, host->h_name) != 0) {
-+                              printerr(2, "mds service entry: hostname "
-+                                       "doesn't match: %s - %.*s, skip\n",
-+                                       host->h_name,
-+                                       princ_host->length, princ_host->data);
-+                              goto next;
-+                      }
-+
-+                      ple = gssd_get_realm_ple((void *)&kte.principal->realm);
-+                      if (ple) {
-+                              if (ple->fl_mds) {
-+                                      printerr(2,"mds service entry: found a "
-+                                               "duplicated one, it's like a "
-+                                               "mis-configuration, skip\n");
-+                                      goto next;
-+                              }
-+
-+                              gssd_remove_ple(context, ple);
-+                              printerr(2, "mds service entry: replace an "
-+                                       "existed non-mds one\n");
-+                      }
-+              } else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME)) {
-+                      ple = gssd_get_realm_ple((void *)&kte.principal->realm);
-+                      if (ple) {
-+                              if (ple->fl_mds || ple->fl_root) {
-+                                      printerr(2, "root entry: found a "
-+                                               "existed %s entry, skip\n",
-+                                               ple->fl_mds ? "mds" : "root");
-+                                      goto next;
-+                              }
-+
-+                              gssd_remove_ple(context, ple);
-+                              printerr(2, "root entry: replace an existed "
-+                                       "non-mds non-root one\n");
-                       }
--              }
--              else {
-+              } else {
-                       printerr(2, "We will NOT use this entry (%s)\n",
-                               pname);
-+                      goto next;
-               }
--#ifdef HAVE_KRB5
--              krb5_free_unparsed_name(context, pname);
--#else
--              free(pname);
--#endif
-+
-+              /* construct ple */
-+              printerr(2, "We will use this entry (%s)\n", pname);
-+              ple = gssd_create_ple(context, kte.principal);
-+              if (ple == NULL) {
-+                      KRB5_FREE_UNPARSED_NAME(context, pname);
-+                      goto out;
-+              }
-+
-+              /* add proper flags */
-+              if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS))
-+                      ple->fl_mds = 1;
-+              else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME))
-+                      ple->fl_root = 1;
-+
-+              /* enqueue */
-+              if (gssd_k5_kt_princ_list == NULL)
-+                      gssd_k5_kt_princ_list = ple;
-+              else {
-+                      ple->next = gssd_k5_kt_princ_list;
-+                      gssd_k5_kt_princ_list = ple;
-+              }
-+ next:
-+              KRB5_FREE_UNPARSED_NAME(context, pname);
-       }
-       if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) {
-@@ -636,6 +761,7 @@ gssd_setup_krb5_user_gss_ccache(uid_t ui
-       printerr(2, "getting credentials for client with uid %u for "
-                   "server %s\n", uid, servername);
-       memset(buf, 0, sizeof(buf));
-+
-       if (gssd_find_existing_krb5_ccache(uid, &d)) {
-               snprintf(buf, sizeof(buf), "FILE:%s/%s",
-                       ccachedir, d->d_name);
-@@ -696,7 +822,7 @@ gssd_refresh_krb5_machine_creds(void)
-               goto out;
-       }
--      printerr(1, "Using keytab file '%s'\n", keytabfile);
-+      printerr(2, "Using keytab file '%s'\n", keytabfile);
-       if ((code = krb5_kt_resolve(context, keytabfile, &kt))) {
-               printerr(0, "ERROR: %s while resolving keytab '%s'\n",
-@@ -711,12 +837,12 @@ gssd_refresh_krb5_machine_creds(void)
-               if (gssd_k5_kt_princ_list == NULL) {
-                       printerr(0, "ERROR: No usable keytab entries found in "
-                                   "keytab '%s'\n", keytabfile);
--                      printerr(0, "Do you have a valid keytab entry for "
--                                  "%s/<your.host>@<YOUR.REALM> in "
-+                      printerr(0, "You must have a valid keytab entry for "
-+                                  "%s/<your.host>@<YOUR.REALM> on MDT nodes, "
-+                                  "and %s@<YOUR.REALM> on client nodes, in "
-                                   "keytab file %s ?\n",
--                                  GSSD_SERVICE_NAME, keytabfile);
--                      printerr(0, "Continuing without (machine) credentials "
--                                  "- nfs4 mounts with Kerberos will fail\n");
-+                                  GSSD_SERVICE_MDS, LUSTRE_ROOT_NAME,
-+                                  keytabfile);
-               }
-       }
-@@ -866,6 +992,7 @@ gssd_destroy_krb5_machine_creds(void)
-       krb5_free_context(context);
- }
-+#if 0
- #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
- /*
-  * this routine obtains a credentials handle via gss_acquire_cred()
-@@ -921,7 +1048,9 @@ limit_krb5_enctypes(struct rpc_gss_sec *
-       return 0;
- }
- #endif        /* HAVE_SET_ALLOWABLE_ENCTYPES */
-+#endif
-+#if 0
- /*
-  * Obtain supported enctypes from kernel.
-  * Set defaults if info is not available.
-@@ -988,3 +1117,4 @@ gssd_obtain_kernel_krb5_info(void)
-                        code);
-       }
- }
-+#endif
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.h nfs-utils-1.0.11/utils/gssd/krb5_util.h
---- nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.h     2008-01-02 17:22:48.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/krb5_util.h    2008-01-02 18:11:38.000000000 -0700
-@@ -10,6 +10,8 @@
- struct gssd_k5_kt_princ {
-       struct gssd_k5_kt_princ *next;
-       krb5_principal princ;
-+      unsigned int    fl_root:1,
-+                      fl_mds:1;
-       char *ccname;
-       char *realm;
-       krb5_timestamp endtime;
-@@ -25,8 +27,4 @@ void gssd_destroy_krb5_machine_creds(voi
- void gssd_obtain_kernel_krb5_info(void);
--#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
--int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
--#endif
--
- #endif /* KRB5_UTIL_H */
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/Makefile.am nfs-utils-1.0.11/utils/gssd/Makefile.am
---- nfs-utils-1.0.11.lustre/utils/gssd/Makefile.am     2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/Makefile.am    2008-01-02 18:10:29.000000000 -0700
-@@ -1,17 +1,11 @@
- ## Process this file with automake to produce Makefile.in
--man8_MANS     = gssd.man svcgssd.man
--
--RPCPREFIX     = rpc.
-+RPCPREFIX     = 
- KPREFIX               = @kprefix@
--sbin_PREFIXED = gssd svcgssd
--sbin_PROGRAMS = $(sbin_PREFIXED) gss_clnt_send_err
-+sbin_PREFIXED = lgssd lsvcgssd
-+sbin_PROGRAMS = $(sbin_PREFIXED)
- sbin_SCRIPTS  = gss_destroy_creds
--EXTRA_DIST = \
--      gss_destroy_creds \
--      $(man8_MANS)
--
- COMMON_SRCS = \
-       context.c \
-       context_mit.c \
-@@ -21,13 +15,15 @@ COMMON_SRCS = \
-       gss_util.c \
-       gss_oids.c \
-       err_util.c \
-+      lsupport.c \
-       \
-       context.h \
-       err_util.h \
-       gss_oids.h \
--      gss_util.h
-+      gss_util.h \
-+      lsupport.h
--gssd_SOURCES = \
-+lgssd_SOURCES = \
-       $(COMMON_SRCS) \
-       gssd.c \
-       gssd_main_loop.c \
-@@ -38,13 +34,12 @@ gssd_SOURCES = \
-       krb5_util.h \
-       write_bytes.h
--gssd_LDADD = $(RPCSECGSS_LIBS) $(KRBLIBS)
--gssd_LDFLAGS = $(KRBLDFLAGS)
-+lgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
-+lgssd_LDFLAGS = $(KRBLDFLAGS)
--gssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
--            $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
-+lgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
--svcgssd_SOURCES = \
-+lsvcgssd_SOURCES = \
-       $(COMMON_SRCS) \
-       cacheio.c \
-       svcgssd.c \
-@@ -55,20 +50,11 @@ svcgssd_SOURCES = \
-       cacheio.h \
-       svcgssd.h
--svcgssd_LDADD = \
--      ../../support/nfs/libnfs.a \
--      $(RPCSECGSS_LIBS) -lnfsidmap \
--      $(KRBLIBS)
--
--svcgssd_LDFLAGS = $(KRBLDFLAGS)
--
--svcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
--               $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
-+lsvcgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
--gss_clnt_send_err_SOURCES = gss_clnt_send_err.c
-+lsvcgssd_LDFLAGS = $(KRBLDFLAGS)
--gss_clnt_send_err_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
--               $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
-+lsvcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
- MAINTAINERCLEANFILES = Makefile.in
-@@ -92,23 +78,3 @@ uninstall-hook:
-         done)
--# XXX This makes some assumptions about what automake does.
--# XXX But there is no install-man-hook or install-man-local.
--install-man: install-man8 install-man-links
--uninstall-man: uninstall-man8 uninstall-man-links
--
--install-man-links:
--      (cd $(DESTDIR)$(man8dir) && \
--        for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
--          inst=`echo $$m | sed -e 's/man$$/8/'`; \
--          rm -f $(RPCPREFIX)$$inst ; \
--          $(LN_S) $$inst $(RPCPREFIX)$$inst ; \
--        done)
--
--uninstall-man-links:
--      (cd $(DESTDIR)$(man8dir) && \
--        for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
--          inst=`echo $$m | sed -e 's/man$$/8/'`; \
--          rm -f $(RPCPREFIX)$$inst ; \
--        done)
--
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.c nfs-utils-1.0.11/utils/gssd/svcgssd.c
---- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.c       2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/svcgssd.c      2008-01-02 18:11:38.000000000 -0700
-@@ -43,7 +43,6 @@
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/socket.h>
--#include <rpc/rpc.h>
- #include <fcntl.h>
- #include <errno.h>
-@@ -54,11 +53,33 @@
- #include <stdlib.h>
- #include <string.h>
- #include <signal.h>
--#include <nfsidmap.h>
--#include "nfslib.h"
-+#include <dirent.h>
- #include "svcgssd.h"
- #include "gss_util.h"
- #include "err_util.h"
-+#include "lsupport.h"
-+
-+void
-+closeall(int min)
-+{
-+      DIR *dir = opendir("/proc/self/fd");
-+      if (dir != NULL) {
-+              int dfd = dirfd(dir);
-+              struct dirent *d;
-+
-+              while ((d = readdir(dir)) != NULL) {
-+                      char *endp;
-+                      long n = strtol(d->d_name, &endp, 10);
-+                      if (*endp != '\0' && n >= min && n != dfd)
-+                              (void) close(n);
-+              }
-+              closedir(dir);
-+      } else {
-+              int fd = sysconf(_SC_OPEN_MAX);
-+              while (--fd >= min)
-+                      (void) close(fd);
-+      }
-+}
- /*
-  * mydaemon creates a pipe between the partent and child
-@@ -140,6 +161,7 @@ void
- sig_die(int signal)
- {
-       /* destroy krb5 machine creds */
-+      cleanup_mapping();
-       printerr(1, "exiting on signal %d\n", signal);
-       exit(1);
- }
-@@ -155,7 +177,7 @@ sig_hup(int signal)
- static void
- usage(char *progname)
- {
--      fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-i]\n",
-+      fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-m] [-o]\n",
-               progname);
-       exit(1);
- }
-@@ -166,9 +188,8 @@ main(int argc, char *argv[])
-       int get_creds = 1;
-       int fg = 0;
-       int verbosity = 0;
--      int rpc_verbosity = 0;
--      int idmap_verbosity = 0;
-       int opt;
-+      int must_srv_mds = 0, must_srv_oss = 0;
-       extern char *optarg;
-       char *progname;
-@@ -177,17 +198,19 @@ main(int argc, char *argv[])
-                       case 'f':
-                               fg = 1;
-                               break;
--                      case 'i':
--                              idmap_verbosity++;
--                              break;
-                       case 'n':
-                               get_creds = 0;
-                               break;
-                       case 'v':
-                               verbosity++;
-                               break;
--                      case 'r':
--                              rpc_verbosity++;
-+                      case 'm':
-+                              get_creds = 1;
-+                              must_srv_mds = 1;
-+                              break;
-+                      case 'o':
-+                              get_creds = 1;
-+                              must_srv_oss = 1;
-                               break;
-                       default:
-                               usage(argv[0]);
-@@ -201,34 +224,18 @@ main(int argc, char *argv[])
-               progname = argv[0];
-       initerr(progname, verbosity, fg);
--#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
--      authgss_set_debug_level(rpc_verbosity);
--#else
--      if (rpc_verbosity > 0)
--              printerr(0, "Warning: rpcsec_gss library does not "
--                          "support setting debug level\n");
--#endif
--#ifdef HAVE_NFS4_SET_DEBUG
--        nfs4_set_debug(idmap_verbosity, NULL);
--#else
--      if (idmap_verbosity > 0)
--              printerr(0, "Warning: your nfsidmap library does not "
--                          "support setting debug level\n");
--#endif
-       if (gssd_check_mechs() != 0) {
-               printerr(0, "ERROR: Problem with gssapi library\n");
-               exit(1);
-       }
--      if (!fg)
--              mydaemon(0, 0);
--
--      signal(SIGINT, sig_die);
--      signal(SIGTERM, sig_die);
--      signal(SIGHUP, sig_hup);
--
--      if (get_creds && !gssd_acquire_cred(GSSD_SERVICE_NAME)) {
-+      if (gssd_get_local_realm()) {
-+              printerr(0, "ERROR: Can't get Local Kerberos realm\n");
-+              exit(1);
-+      }
-+  
-+      if (get_creds && gssd_prepare_creds(must_srv_mds, must_srv_oss)) {
-                 printerr(0, "unable to obtain root (machine) credentials\n");
-                 printerr(0, "do you have a keytab entry for "
-                           "nfs/<your.host>@<YOUR.REALM> in "
-@@ -237,9 +244,23 @@ main(int argc, char *argv[])
-       }
-       if (!fg)
-+              mydaemon(0, 0);
-+
-+      /*
-+       * XXX: There is risk of memory leak for missing call
-+       *      cleanup_mapping() for SIGKILL and SIGSTOP.
-+       */
-+      signal(SIGINT, sig_die);
-+      signal(SIGTERM, sig_die);
-+      signal(SIGHUP, sig_hup);
-+
-+      if (!fg)
-               release_parent();
--      gssd_run();
-+      gssd_init_unique(GSSD_SVC);
-+
-+      svcgssd_run();
-+      cleanup_mapping();
-       printerr(0, "gssd_run returned!\n");
-       abort();
- }
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.h nfs-utils-1.0.11/utils/gssd/svcgssd.h
---- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.h       2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/svcgssd.h      2008-01-02 18:11:38.000000000 -0700
-@@ -35,9 +35,20 @@
- #include <sys/queue.h>
- #include <gssapi/gssapi.h>
--void handle_nullreq(FILE *f);
--void gssd_run(void);
-+int handle_nullreq(FILE *f);
-+void svcgssd_run(void);
-+int gssd_prepare_creds(int must_srv_mds, int must_srv_oss);
-+gss_cred_id_t gssd_select_svc_cred(int lustre_svc);
--#define GSSD_SERVICE_NAME     "nfs"
-+extern char *mds_local_realm;
-+extern char *oss_local_realm;
-+
-+#define GSSD_SERVICE_NAME     "lustre"
-+
-+/* XXX */
-+#define GSSD_SERVICE_MDS                      "lustre_mds"
-+#define GSSD_SERVICE_OSS                      "lustre_oss"
-+#define LUSTRE_ROOT_NAME                      "lustre_root"
-+#define LUSTRE_ROOT_NAMELEN                   11
- #endif /* _RPC_SVCGSSD_H_ */
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_main_loop.c nfs-utils-1.0.11/utils/gssd/svcgssd_main_loop.c
---- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_main_loop.c     2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/svcgssd_main_loop.c    2008-01-02 18:11:38.000000000 -0700
-@@ -42,50 +42,72 @@
- #include <fcntl.h>
- #include <errno.h>
- #include <unistd.h>
-+/* For nanosleep() */
-+#include <time.h>
- #include "svcgssd.h"
- #include "err_util.h"
-+/*
-+ * nfs4 in-kernel cache implementation make upcall failed directly
-+ * if there's no listener detected. so here we should keep the init
-+ * channel file open as possible as we can.
-+ *
-+ * unfortunately the proc doesn't support dir change notification.
-+ * and when an entry get unlinked, we only got POLLIN event once,
-+ * it's the only oppotunity we can close the file and startover.
-+ */
- void
--gssd_run()
-+svcgssd_run()
- {
-       int                     ret;
--      FILE                    *f;
-+      FILE                    *f = NULL;
-       struct pollfd           pollfd;
-+      struct timespec         halfsec = { .tv_sec = 0, .tv_nsec = 500000000 };
--#define NULLRPC_FILE "/proc/net/rpc/auth.rpcsec.init/channel"
-+#define NULLRPC_FILE "/proc/net/rpc/auth.sptlrpc.init/channel"
--      f = fopen(NULLRPC_FILE, "rw");
--
--      if (!f) {
--              printerr(0, "failed to open %s: %s\n",
--                       NULLRPC_FILE, strerror(errno));
--              exit(1);
--      }
--      pollfd.fd = fileno(f);
--      pollfd.events = POLLIN;
-       while (1) {
-               int save_err;
-+              while (f == NULL) {
-+                      f = fopen(NULLRPC_FILE, "rw");
-+                      if (f == NULL) {
-+                              printerr(4, "failed to open %s: %s\n",
-+                                       NULLRPC_FILE, strerror(errno));
-+                              nanosleep(&halfsec, NULL);
-+                      } else {
-+                              printerr(1, "successfully open %s\n",
-+                                       NULLRPC_FILE);
-+                              break;
-+                      }
-+              }
-+              pollfd.fd = fileno(f);
-+              pollfd.events = POLLIN;
-+
-               pollfd.revents = 0;
--              printerr(1, "entering poll\n");
--              ret = poll(&pollfd, 1, -1);
-+              ret = poll(&pollfd, 1, 1000);
-               save_err = errno;
--              printerr(1, "leaving poll\n");
-+
-               if (ret < 0) {
--                      if (save_err != EINTR)
--                              printerr(0, "error return from poll: %s\n",
--                                       strerror(save_err));
-+                      printerr(0, "error return from poll: %s\n",
-+                               strerror(save_err));
-+                      fclose(f);
-+                      f = NULL;
-               } else if (ret == 0) {
--                      /* timeout; shouldn't happen. */
-+                      printerr(3, "poll timeout\n");
-               } else {
-                       if (ret != 1) {
-                               printerr(0, "bug: unexpected poll return %d\n",
-                                               ret);
-                               exit(1);
-                       }
--                      if (pollfd.revents & POLLIN)
--                              handle_nullreq(f);
-+                      if (pollfd.revents & POLLIN) {
-+                              if (handle_nullreq(f) < 0) {
-+                                      fclose(f);
-+                                      f = NULL;
-+                              }
-+                      }
-               }
-       }
- }
-diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c
---- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_proc.c  2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c 2008-01-02 18:11:38.000000000 -0700
-@@ -35,7 +35,6 @@
- #include <sys/param.h>
- #include <sys/stat.h>
--#include <rpc/rpc.h>
- #include <pwd.h>
- #include <stdio.h>
-@@ -44,25 +43,28 @@
- #include <string.h>
- #include <fcntl.h>
- #include <errno.h>
--#include <nfsidmap.h>
-+#include <netdb.h>
- #include "svcgssd.h"
- #include "gss_util.h"
- #include "err_util.h"
- #include "context.h"
- #include "cacheio.h"
-+#include "lsupport.h"
- extern char * mech2file(gss_OID mech);
--#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel"
--#define SVCGSSD_INIT_CHANNEL    "/proc/net/rpc/auth.rpcsec.init/channel"
-+#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.sptlrpc.context/channel"
-+#define SVCGSSD_INIT_CHANNEL    "/proc/net/rpc/auth.sptlrpc.init/channel"
- #define TOKEN_BUF_SIZE                8192
- struct svc_cred {
--      uid_t   cr_uid;
--      gid_t   cr_gid;
--      int     cr_ngroups;
--      gid_t   cr_groups[NGROUPS];
-+      uint32_t cr_remote;
-+      uint32_t cr_usr_root;
-+      uint32_t cr_usr_mds;
-+      uid_t    cr_uid;
-+      uid_t    cr_mapped_uid;
-+      uid_t    cr_gid;
- };
- static int
-@@ -70,11 +72,10 @@ do_svc_downcall(gss_buffer_desc *out_han
-               gss_OID mech, gss_buffer_desc *context_token)
- {
-       FILE *f;
--      int i;
-       char *fname = NULL;
-       int err;
--      printerr(1, "doing downcall\n");
-+      printerr(2, "doing downcall\n");
-       if ((fname = mech2file(mech)) == NULL)
-               goto out_err;
-       f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w");
-@@ -87,11 +88,12 @@ do_svc_downcall(gss_buffer_desc *out_han
-       qword_printhex(f, out_handle->value, out_handle->length);
-       /* XXX are types OK for the rest of this? */
-       qword_printint(f, 0x7fffffff); /*XXX need a better timeout */
-+      qword_printint(f, cred->cr_remote);
-+      qword_printint(f, cred->cr_usr_root);
-+      qword_printint(f, cred->cr_usr_mds);
-+      qword_printint(f, cred->cr_mapped_uid);
-       qword_printint(f, cred->cr_uid);
-       qword_printint(f, cred->cr_gid);
--      qword_printint(f, cred->cr_ngroups);
--      for (i=0; i < cred->cr_ngroups; i++)
--              qword_printint(f, cred->cr_groups[i]);
-       qword_print(f, fname);
-       qword_printhex(f, context_token->value, context_token->length);
-       err = qword_eol(f);
-@@ -120,7 +122,7 @@ send_response(FILE *f, gss_buffer_desc *
-       /* XXXARG: */
-       int g;
--      printerr(1, "sending null reply\n");
-+      printerr(2, "sending null reply\n");
-       qword_addhex(&bp, &blen, in_handle->value, in_handle->length);
-       qword_addhex(&bp, &blen, in_token->value, in_token->length);
-@@ -160,6 +162,7 @@ send_response(FILE *f, gss_buffer_desc *
- #define rpcsec_gsserr_credproblem     13
- #define rpcsec_gsserr_ctxproblem      14
-+#if 0
- static void
- add_supplementary_groups(char *secname, char *name, struct svc_cred *cred)
- {
-@@ -183,7 +186,9 @@ add_supplementary_groups(char *secname, 
-               }
-       }
- }
-+#endif
-+#if 0
- static int
- get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred)
- {
-@@ -249,7 +254,9 @@ out_free:
- out:
-       return res;
- }
-+#endif
-+#if 0
- void
- print_hexl(int pri, unsigned char *cp, int length)
- {
-@@ -286,12 +293,149 @@ print_hexl(int pri, unsigned char *cp, i
-               printerr(pri,"\n");
-       }
- }
-+#endif
--void
-+static int
-+get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
-+      lnet_nid_t nid, uint32_t lustre_svc)
-+{
-+      u_int32_t       maj_stat, min_stat;
-+      gss_buffer_desc name;
-+      char            *sname, *host, *realm;
-+      const int       namebuf_size = 512;
-+      char            namebuf[namebuf_size];
-+      int             res = -1;
-+      gss_OID         name_type = GSS_C_NO_OID;
-+      struct passwd   *pw;
-+
-+      cred->cr_remote = cred->cr_usr_root = cred->cr_usr_mds = 0;
-+      cred->cr_uid = cred->cr_mapped_uid = cred->cr_gid = -1;
-+
-+      maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
-+      if (maj_stat != GSS_S_COMPLETE) {
-+              pgsserr("get_ids: gss_display_name",
-+                      maj_stat, min_stat, mech);
-+              return -1;
-+      }
-+      if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */
-+          !(sname = calloc(name.length + 1, 1))) {
-+              printerr(0, "WARNING: get_ids: error allocating %d bytes "
-+                      "for sname\n", name.length + 1);
-+              gss_release_buffer(&min_stat, &name);
-+              return -1;
-+      }
-+      memcpy(sname, name.value, name.length);
-+      gss_release_buffer(&min_stat, &name);
-+
-+      if (lustre_svc == LUSTRE_GSS_SVC_MDS)
-+              lookup_mapping(sname, nid, &cred->cr_mapped_uid);
-+      else
-+              cred->cr_mapped_uid = -1;
-+
-+        realm = strchr(sname, '@');
-+      if (realm)
-+                *realm++ = '\0';
-+
-+        host = strchr(sname, '/');
-+        if (host)
-+                *host++ = '\0';
-+
-+      if (strcmp(sname, GSSD_SERVICE_OSS) == 0) {
-+              printerr(0, "forbid "GSSD_SERVICE_OSS" as user name\n");
-+              goto out_free;
-+      }
-+
-+      /* 1. check host part */
-+      if (host) {
-+              if (lnet_nid2hostname(nid, namebuf, namebuf_size)) {
-+                      printerr(0, "ERROR: failed to resolve hostname for "
-+                               "%s/%s@%s from %016llx\n",
-+                               sname, host, realm, nid);
-+                      goto out_free;
-+              }
-+
-+              if (strcasecmp(host, namebuf)) {
-+                      printerr(0, "ERROR: %s/%s@s claimed hostname doesn't "
-+                               "match %s, nid %016llx\n", sname, host, realm,
-+                               namebuf, nid);
-+                      goto out_free;
-+              }
-+      } else {
-+              if (!strcmp(sname, GSSD_SERVICE_MDS)) {
-+                      printerr(0, "ERROR: "GSSD_SERVICE_MDS"@%s from %016llx "
-+                               "doesn't bind with hostname\n",
-+                               realm ? realm : "", nid);
-+                      goto out_free;
-+              }
-+      }
-+
-+      /* 2. check realm */
-+      if (!realm) {
-+              /* just deny it
-+                cred->cr_remote = (mds_local_realm != NULL);
-+              */
-+                printerr(0, "ERROR: %s%s%s have no realm name\n",
-+                       sname, host ? "/" : "", host ? "host" : "");
-+              goto out_free;
-+      }
-+
-+      if (!mds_local_realm || strcasecmp(mds_local_realm, realm)) {
-+              cred->cr_remote = 1;
-+
-+              if (cred->cr_mapped_uid == -1)
-+                        printerr(0, "ERROR: %s from %016llx is remote but "
-+                               "without mapping\n", sname, nid);
-+              /* mapped, skip user checking */
-+              goto out_free;
-+      }
-+
-+      /* 3. check user */
-+        if (!(pw = getpwnam(sname))) {
-+                /* map lustre_root/lustre_mds to root user, which is subject
-+               * to further mapping by root-squash in kernel. */
-+                if (!strcmp(sname, LUSTRE_ROOT_NAME)) {
-+                        cred->cr_uid = 0;
-+                        cred->cr_usr_root = 1;
-+                } else if (!strcmp(sname, GSSD_SERVICE_MDS)) {
-+                        cred->cr_uid = 0;
-+                        cred->cr_usr_mds = 1;
-+                } else {
-+                        if (cred->cr_mapped_uid == -1) {
-+                                printerr(0, "ERROR: invalid user, %s/%s@%s "
-+                                       "from %016llx\n", sname, host,
-+                                       realm, nid);
-+                                goto out_free;
-+                        }
-+                }
-+              printerr(2, "user %s from %016llx is mapped to %u\n",
-+                       sname, nid, cred->cr_mapped_uid);
-+        } else {
-+              /* note: a mapped local user will go to here too */
-+                cred->cr_uid = pw->pw_uid;
-+                printerr(2, "%s resolve to uid %u\n", sname, cred->cr_uid);
-+        }
-+
-+      printerr(1, "%s: authenticated %s%s%s@%s from %016llx\n",
-+               lustre_svc_name[lustre_svc], sname,
-+               host ? "/" : "", host ? host : "", realm, nid);
-+        res = 0;
-+out_free:
-+        free(sname);
-+        return res;
-+}
-+
-+typedef struct gss_union_ctx_id_t {
-+      gss_OID         mech_type;
-+      gss_ctx_id_t    internal_ctx_id;
-+} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
-+
-+/*
-+ * return -1 only if we detect error during reading from upcall channel,
-+ * all other cases return 0.
-+ */
-+int
- handle_nullreq(FILE *f) {
--      /* XXX initialize to a random integer to reduce chances of unnecessary
--       * invalidation of existing ctx's on restarting svcgssd. */
--      static u_int32_t        handle_seq = 0;
-+      uint64_t                handle_seq;
-       char                    in_tok_buf[TOKEN_BUF_SIZE];
-       char                    in_handle_buf[15];
-       char                    out_handle_buf[15];
-@@ -303,10 +447,13 @@ handle_nullreq(FILE *f) {
-                               ignore_out_tok = {.value = NULL},
-       /* XXX isn't there a define for this?: */
-                               null_token = {.value = NULL};
-+      uint32_t                lustre_svc;
-+      lnet_nid_t              nid;
-       u_int32_t               ret_flags;
-       gss_ctx_id_t            ctx = GSS_C_NO_CONTEXT;
-       gss_name_t              client_name;
-       gss_OID                 mech = GSS_C_NO_OID;
-+      gss_cred_id_t           svc_cred;
-       u_int32_t               maj_stat = GSS_S_FAILURE, min_stat = 0;
-       u_int32_t               ignore_min_stat;
-       struct svc_cred         cred;
-@@ -314,25 +461,31 @@ handle_nullreq(FILE *f) {
-       static int              lbuflen = 0;
-       static char             *cp;
--      printerr(1, "handling null request\n");
-+      printerr(2, "handling null request\n");
-       if (readline(fileno(f), &lbuf, &lbuflen) != 1) {
-               printerr(0, "WARNING: handle_nullreq: "
-                           "failed reading request\n");
--              return;
-+              return -1;
-       }
-       cp = lbuf;
-+      qword_get(&cp, (char *) &lustre_svc, sizeof(lustre_svc));
-+      qword_get(&cp, (char *) &nid, sizeof(nid));
-+      qword_get(&cp, (char *) &handle_seq, sizeof(handle_seq));
-+      printerr(2, "handling req: svc %u, nid %016llx, idx %llx\n",
-+               lustre_svc, nid, handle_seq);
-+
-       in_handle.length = (size_t) qword_get(&cp, in_handle.value,
-                                             sizeof(in_handle_buf));
--      printerr(2, "in_handle: \n");
--      print_hexl(2, in_handle.value, in_handle.length);
-+      printerr(3, "in_handle: \n");
-+      print_hexl(3, in_handle.value, in_handle.length);
-       in_tok.length = (size_t) qword_get(&cp, in_tok.value,
-                                          sizeof(in_tok_buf));
--      printerr(2, "in_tok: \n");
--      print_hexl(2, in_tok.value, in_tok.length);
-+      printerr(3, "in_tok: \n");
-+      print_hexl(3, in_tok.value, in_tok.length);
-       if (in_tok.length < 0) {
-               printerr(0, "WARNING: handle_nullreq: "
-@@ -352,7 +505,13 @@ handle_nullreq(FILE *f) {
-               memcpy(&ctx, in_handle.value, in_handle.length);
-       }
--      maj_stat = gss_accept_sec_context(&min_stat, &ctx, gssd_creds,
-+      svc_cred = gssd_select_svc_cred(lustre_svc);
-+      if (!svc_cred) {
-+              printerr(0, "no service credential for svc %u\n", lustre_svc);
-+              goto out_err;
-+      }
-+
-+      maj_stat = gss_accept_sec_context(&min_stat, &ctx, svc_cred,
-                       &in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name,
-                       &mech, &out_tok, &ret_flags, NULL, NULL);
-@@ -370,7 +529,8 @@ handle_nullreq(FILE *f) {
-                       maj_stat, min_stat, mech);
-               goto out_err;
-       }
--      if (get_ids(client_name, mech, &cred)) {
-+
-+      if (get_ids(client_name, mech, &cred, nid, lustre_svc)) {
-               /* get_ids() prints error msg */
-               maj_stat = GSS_S_BAD_NAME; /* XXX ? */
-               gss_release_name(&ignore_min_stat, &client_name);
-@@ -378,10 +538,8 @@ handle_nullreq(FILE *f) {
-       }
-       gss_release_name(&ignore_min_stat, &client_name);
--
-       /* Context complete. Pass handle_seq in out_handle to use
-        * for context lookup in the kernel. */
--      handle_seq++;
-       out_handle.length = sizeof(handle_seq);
-       memcpy(out_handle.value, &handle_seq, sizeof(handle_seq));
-@@ -405,8 +563,7 @@ out:
-               free(ctx_token.value);
-       if (out_tok.value != NULL)
-               gss_release_buffer(&ignore_min_stat, &out_tok);
--      printerr(1, "finished handling null request\n");
--      return;
-+      return 0;
- out_err:
-       if (ctx != GSS_C_NO_CONTEXT)
-diff -Nrup nfs-utils-1.0.11.lustre/utils/Makefile.am nfs-utils-1.0.11/utils/Makefile.am
---- nfs-utils-1.0.11.lustre/utils/Makefile.am  2007-02-21 21:50:03.000000000 -0700
-+++ nfs-utils-1.0.11/utils/Makefile.am 2008-01-02 18:10:29.000000000 -0700
-@@ -2,30 +2,6 @@
- OPTDIRS =
--if CONFIG_RQUOTAD
--OPTDIRS += rquotad
--endif
--
--if CONFIG_NFSV4
--OPTDIRS += idmapd
--endif
--
--if CONFIG_GSS
--OPTDIRS += gssd
--endif
--
--if CONFIG_MOUNT
--OPTDIRS += mount
--endif
--
--SUBDIRS = \
--      exportfs \
--      lockd \
--      mountd \
--      nfsd \
--      nfsstat \
--      showmount \
--      statd \
--      $(OPTDIRS)
-+SUBDIRS = gssd
- MAINTAINERCLEANFILES = Makefile.in
old mode 100755 (executable)
new mode 100644 (file)