Whamcloud - gitweb
branch: b_new_cmd
authorericm <ericm>
Fri, 13 Oct 2006 23:57:13 +0000 (23:57 +0000)
committerericm <ericm>
Fri, 13 Oct 2006 23:57:13 +0000 (23:57 +0000)
from fanyong: re-enable mapping database lookup in lsvcgss.

lustre/utils/gss/.cvsignore
lustre/utils/gss/Makefile.am
lustre/utils/gss/gssd_proc.c
lustre/utils/gss/l_idmap.c [new file with mode: 0644]
lustre/utils/gss/lsupport.c
lustre/utils/gss/lsupport.h
lustre/utils/gss/nfs-utils-1.0.10-lustre.diff
lustre/utils/gss/svcgssd_proc.c

index 65a8e0a..15f680f 100644 (file)
@@ -6,5 +6,6 @@ tags
 TAGS
 lgssd
 lsvcgssd
+l_idmap
 .*.cmd
 .*.d
index 479e28d..34ccfaa 100644 (file)
@@ -8,7 +8,7 @@ AM_LDFLAGS := -L$(top_builddir)/lnet/utils
 
 LIBPTLCTL := $(top_builddir)/lnet/utils/libptlctl.a
 
-sbin_PROGRAMS = lgssd lsvcgssd
+sbin_PROGRAMS = lgssd lsvcgssd l_idmap
 
 COMMON_SRCS = \
         context.c \
@@ -56,4 +56,11 @@ lsvcgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
 lsvcgssd_LDFLAGS = $(KRBLDFLAGS)
 lsvcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(KRBCFLAGS)
 
+l_idmap_SOURCES = \
+       l_idmap.c \
+       lsupport.c \
+       err_util.c \
+       \
+       lsupport.h
+
 EXTRA_DIST =
index 2aabf19..53150da 100644 (file)
@@ -876,7 +876,7 @@ int construct_service_name(struct clnt_info *clp,
                 clp->servicename = NULL;
         }
 
-        if (ptl_nid2hostname(ud->nid, name, buflen))
+        if (lnet_nid2hostname(ud->nid, name, buflen))
                 return -1;
 
         clp->servicename = malloc(32 + strlen(name));
diff --git a/lustre/utils/gss/l_idmap.c b/lustre/utils/gss/l_idmap.c
new file mode 100644 (file)
index 0000000..eada85c
--- /dev/null
@@ -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;
+}
index e6d86bf..b82d380 100644 (file)
 #include <signal.h>
 #include <unistd.h>
 #include <errno.h>
-#include <netdb.h>
 #include <assert.h>
+#ifdef HAVE_GETHOSTBYNAME
+# include <netdb.h>
+#endif
 
 #include "err_util.h"
 #include "gssd.h"
@@ -131,17 +133,17 @@ void gssd_exit_unique(int type)
 
 /****************************************
  * client side resolvation:             *
- *    nal/netid/nid => hostname         *
+ *    lnd/netid/nid => hostname         *
  ****************************************/
 
 char gethostname_ex[PATH_MAX] = GSSD_DEFAULT_GETHOSTNAME_EX;
 
-typedef int ptl_nid2hostname_t(char *nal, uint32_t net, uint32_t addr,
+typedef int lnd_nid2hostname_t(char *lnd, uint32_t net, uint32_t addr,
                                char *buf, int buflen);
 
 /* FIXME what about IPv6? */
 static
-int socknal_nid2hostname(char *nal, uint32_t net, uint32_t addr,
+int socklnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
                          char *buf, int buflen)
 {
         struct hostent  *ent;
@@ -149,51 +151,51 @@ int socknal_nid2hostname(char *nal, uint32_t net, uint32_t addr,
         addr = htonl(addr);
         ent = gethostbyaddr(&addr, sizeof(addr), AF_INET);
         if (!ent) {
-                printerr(0, "%s: can't resolve 0x%x\n", nal, addr);
+                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", nal, ent->h_name);
+                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",
-                 nal, net, addr, buf);
+                 lnd, net, addr, buf);
         return 0;
 }
 
 static
-int lonal_nid2hostname(char *nal, uint32_t net, uint32_t addr,
+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", nal, 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", nal);
+                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",
-                         nal, uts.nodename);
+                         lnd, uts.nodename);
                 return -1;
         }
 
         if (strlen(ent->h_name) >= buflen) {
-                printerr(0, "%s: name too long: %s\n", nal, ent->h_name);
+                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", nal, addr, buf);
+        printerr(2, "%s: addr 0x%x => %s\n", lnd, addr, buf);
         return 0;
 }
 
@@ -203,14 +205,14 @@ static int is_space(char c)
 }
 
 static
-int external_nid2hostname(char *nal, uint32_t net, uint32_t addr,
-                           char *namebuf, int namebuflen)
+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, nal, net, addr);
+        sprintf(buf, "%s %s 0x%x 0x%x", gethostname_ex, lnd, net, addr);
         printerr(2, "cmd: %s\n", buf);
 
         fghn = popen(buf, "r");
@@ -221,7 +223,7 @@ int external_nid2hostname(char *nal, uint32_t net, uint32_t addr,
 
         head = fgets(buf, bufsize, fghn);
         if (head == NULL) {
-                printerr(0, "can't read\n");
+                printerr(0, "can't read from %s\n", gethostname_ex);
                 return -1;
         }
         if (pclose(fghn) == -1)
@@ -233,187 +235,337 @@ int external_nid2hostname(char *nal, uint32_t net, uint32_t addr,
 
         tail = head + strlen(head);
         if (tail <= head) {
-                printerr(0, "no output\n");
+                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\n");
+                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, "%s\n", &head[1]);
+                printerr(0, "error from %s: %s\n", gethostname_ex, &head[1]);
                 return -1;
         }
 
         if (tail - head > namebuflen) {
-                printerr(0, "hostname too long: %s\n", head);
+                printerr(0, "external hostname too long: %s\n", head);
                 return -1;
         }
 
         printerr(2, "%s: net 0x%x, addr 0x%x => %s\n",
-                 nal, net, addr, head);
+                 lnd, net, addr, head);
         strcpy(namebuf, head);
         return 0;
 }
 
-enum {
-        QSWNAL    = 1,
-        SOCKNAL   = 2,
-        GMNAL     = 3,
-        /*          4 unused */
-        TCPNAL    = 5,
-        ROUTER    = 6,
-        OPENIBNAL = 7,
-        IIBNAL    = 8,
-        LONAL     = 9,
-        RANAL     = 10,
-        VIBNAL    = 11,
-        NAL_ENUM_END_MARKER
-};
-
 static struct {
         char                    *name;
-        ptl_nid2hostname_t      *nid2name;
-} converter[NAL_ENUM_END_MARKER] = {
+        lnd_nid2hostname_t      *nid2name;
+} converter[LND_ENUM_END_MARKER] = {
         {"UNUSED0",     NULL},
-        {"QSWNAL",      external_nid2hostname},
-        {"SOCKNAL",     socknal_nid2hostname},
-        {"GMNAL",       external_nid2hostname},
-        {"UNUSED4",     NULL},
-        {"TCPNAL",      NULL},
-        {"ROUTER",      NULL},
-        {"OPENIBNAL",   external_nid2hostname},
-        {"IIBNAL",      external_nid2hostname},
-        {"LONAL",       lonal_nid2hostname},
-        {"RANAL",       NULL},
-        {"VIBNAL",      external_nid2hostname},
+        [QSWLND]        = { "QSWLND",   external_nid2hostname},
+        [SOCKLND]       = { "SOCKLND",  socklnd_nid2hostname},
+        [GMLND]         = { "GMLND",    external_nid2hostname},
+        [PTLLND]        = { "PTLLND",   external_nid2hostname },
+        [O2IBLND]       = { "O2IBLND",  external_nid2hostname },
+        [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 ptl_nid2hostname(uint64_t nid, char *buf, int buflen)
+int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen)
 {
-        uint32_t nal, net, addr;
+        uint32_t lnd, net, addr;
 
         addr = LNET_NIDADDR(nid);
         net = LNET_NIDNET(nid);
-        nal = LNET_NETTYP(net);
+        lnd = LNET_NETTYP(net);
 
-        if (nal >= NAL_ENUM_END_MARKER) {
-                printerr(0, "ERROR: Unrecognized NAL %u\n", nal);
+        if (lnd >= LND_ENUM_END_MARKER) {
+                printerr(0, "ERROR: Unrecognized LND %u\n", lnd);
                 return -1;
         }
 
-        if (converter[nal].nid2name == NULL) {
-                printerr(0, "ERROR: NAL %s converter not ready\n",
-                        converter[nal].name);
+        if (converter[lnd].nid2name == NULL) {
+                printerr(0, "ERROR: %s converter not ready\n",
+                        converter[lnd].name);
                 return -1;
         }
 
-        return converter[nal].nid2name(converter[nal].name, net, addr,
+        return converter[lnd].nid2name(converter[lnd].name, net, addr,
                                        buf, buflen);
 }
 
 
 /****************************************
- * portals support routine              *
+ * lnet support routine                 *
+ * (from lnet/libcfs/nidstrings.c       *
  ****************************************/
 
-static struct hostent *
-ptl_gethostbyname(char * hname) {
-        struct hostent *he;
-
-        he = gethostbyname(hname);
-        if (!he) {
-                switch(h_errno) {
-                case HOST_NOT_FOUND:
-                case NO_ADDRESS:
-                        printerr(0, "Unable to resolve hostname: %s\n",
-                                 hname);
-                        break;
-                default:
-                        printerr(0, "gethostbyname %s: %s\n",
-                                 hname, strerror(h_errno));
-                        break;
-                }
-                return NULL;
-        }
-        return he;
+#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;
 }
 
-int
-ptl_parse_ipquad (uint32_t *ipaddrp, char *str)
+static void
+libcfs_ip_addr2str(uint32_t addr, char *str)
 {
-        int             a;
-        int             b;
-        int             c;
-        int             d;
+        snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u",
+                 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
+                 (addr >> 8) & 0xff, addr & 0xff);
+}
 
-        if (sscanf(str, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 &&
+/* 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)
-        {
-                *ipaddrp = (a<<24)|(b<<16)|(c<<8)|d;
-                return (0);
+            (c & ~0xff) == 0 && (d & ~0xff) == 0) {
+                *addr = ((a<<24)|(b<<16)|(c<<8)|d);
+                return 1;
         }
 
-        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;
 }
 
-int
-ptl_parse_ipaddr (uint32_t *ipaddrp, char *str)
+static void
+libcfs_decnum_addr2str(uint32_t addr, char *str)
 {
-        struct hostent *he;
+        snprintf(str, LNET_NIDSTR_SIZE, "%u", addr);
+}
 
-        if (!strcmp (str, "_all_")) {
-                *ipaddrp = 0;
-                return (0);
-        }
+static void
+libcfs_hexnum_addr2str(uint32_t addr, char *str)
+{
+        snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr);
+}
 
-        if (ptl_parse_ipquad(ipaddrp, str) == 0)
-                return (0);
+static int
+libcfs_num_str2addr(char *str, int nob, uint32_t *addr)
+{
+        int     n;
 
-        if ((('a' <= str[0] && str[0] <= 'z') ||
-             ('A' <= str[0] && str[0] <= 'Z')) &&
-             (he = ptl_gethostbyname (str)) != NULL) {
-                uint32_t addr = *(uint32_t *)he->h_addr;
+        n = nob;
+        if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
+                return 1;
 
-                *ipaddrp = ntohl(addr);         /* HOST byte order */
-                return (0);
-        }
+        n = nob;
+        if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
+                return 1;
 
-        return (-1);
+        n = nob;
+        if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
+                return 1;
+        
+        return 0;
 }
 
-int
-ptl_parse_nid (ptl_nid_t *nidp, char *str)
+static struct netstrfns *
+libcfs_lnd2netstrfns(int lnd)
 {
-        uint32_t            ipaddr;
-        char               *end;
-        unsigned long long  ullval;
-
-        if (ptl_parse_ipaddr (&ipaddr, str) == 0) {
-#if !CRAY_PORTALS
-                *nidp = (ptl_nid_t)ipaddr;
-#else
-                *nidp = (((ptl_nid_t)ipaddr & PNAL_HOSTID_MASK) << PNAL_VNODE_SHIFT);
-#endif
-                return (0);
+        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;
         }
 
-        ullval = strtoull(str, &end, 0);
-        if (end != str && *end == 0) {
-                /* parsed whole non-empty string */
-                *nidp = (ptl_nid_t)ullval;
-                return (0);
+        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;
         }
 
-        return (-1);
+        *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       *
@@ -425,8 +577,7 @@ ptl_parse_nid (ptl_nid_t *nidp, char *str)
 
 struct user_map_item {
         char        *principal; /* NULL means match all */
-        ptl_netid_t  netid;
-        ptl_nid_t    nid;
+        lnet_nid_t   nid;
         uid_t        uid;
 };
 
@@ -438,7 +589,7 @@ struct user_mapping {
 
 static struct user_mapping mapping = {0, 0, NULL};
 /* FIXME to be finished: monitor change of mapping database */
-static int mapping_changed = 1;
+static int mapping_mtime = 0;
 
 static
 void cleanup_mapping(void)
@@ -446,8 +597,8 @@ void cleanup_mapping(void)
         int n;
 
         for (n = 0; n < mapping.nitems; n++) {
-                assert(mapping.items[n].principal);
-                free(mapping.items[n].principal);
+                if (mapping.items[n].principal)
+                        free(mapping.items[n].principal);
         }
         mapping.nitems = 0;
 }
@@ -500,7 +651,7 @@ int read_mapping_db(void)
         char princ[MAX_LINE_LEN];
         char nid_str[MAX_LINE_LEN];
         char dest[MAX_LINE_LEN];
-        ptl_nid_t ptl_nid;
+        lnet_nid_t nid;
         uid_t dest_uid;
         FILE *f;
         char *line, linebuf[MAX_LINE_LEN];
@@ -547,10 +698,15 @@ int read_mapping_db(void)
                                 return -1;
                         }
                 }
-                if (ptl_parse_nid(&ptl_nid, nid_str)) {
-                        printerr(0, "fail to parse nid %s\n", nid_str);
-                        fclose(f);
-                        return -1;
+                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);
+                                fclose(f);
+                                return -1;
+                        }
                 }
                 dest_uid = parse_uid(dest);
                 if (dest_uid == -1) {
@@ -561,33 +717,47 @@ int read_mapping_db(void)
                 }
 
                 mapping.items[mapping.nitems].principal = name;
-                mapping.items[mapping.nitems].netid = 0;
-                mapping.items[mapping.nitems].nid = ptl_nid;
+                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 ? name : "*", nid_str, ptl_nid, dest_uid);
+                         name ? name : "*", nid_str, nid, dest_uid);
+        }
+
+        return 0;
+}
+
+static inline int mapping_changed(void)
+{
+        struct stat st;
+
+        if (stat(MAPPING_DATABASE_FILE, &st) == -1) {
+                printerr(0, "stat %s failed\n");
+                return 1;
+        }
+
+        if (st.st_mtime != mapping_mtime) {
+                mapping_mtime = st.st_mtime;
+                return 1;
         }
 
         return 0;
 }
 
-int lookup_mapping(char *princ, uint32_t nal, ptl_netid_t netid,
-                   ptl_nid_t nid, uid_t *uid)
+int lookup_mapping(char *princ, lnet_nid_t nid, uid_t *uid)
 {
         int n;
 
         /* FIXME race condition here */
-        if (mapping_changed) {
+        if (mapping_changed()) {
                 if (read_mapping_db())
                         printerr(0, "all remote users will be denied\n");
-                mapping_changed = 0;
         }
 
         for (n = 0; n < mapping.nitems; n++) {
                 struct user_map_item *entry = &mapping.items[n];
 
-                if (entry->netid != netid || entry->nid != nid)
+                if (entry->nid != LNET_NID_ANY && entry->nid != nid)
                         continue;
                 if (!entry->principal ||
                     !strcasecmp(entry->principal, princ)) {
@@ -597,7 +767,7 @@ int lookup_mapping(char *princ, uint32_t nal, ptl_netid_t netid,
                         return 0;
                 }
         }
-        printerr(1, "no mapping for %s\n", princ);
+        printerr(1, "no mapping for %s/%#Lx\n", princ, nid);
         *uid = -1;
         return -1;
 }
index 4945da8..1a15384 100644 (file)
@@ -18,9 +18,6 @@ void gssd_exit_unique(int type);
  * copied from lustre source
  */
 
-typedef uint64_t ptl_nid_t;
-typedef uint32_t ptl_netid_t;
-
 #define LUSTRE_GSS_SVC_MDS      0
 #define LUSTRE_GSS_SVC_OSS      1
 
@@ -52,9 +49,32 @@ struct lgssd_ioctl_param {
 #define GSSD_DEFAULT_GETHOSTNAME_EX     "/etc/lustre/nid2hostname"
 #define MAPPING_DATABASE_FILE           "/etc/lustre/idmap.conf"
 
-int ptl_nid2hostname(uint64_t nid, char *buf, int buflen);
-int lookup_mapping(char *princ, uint32_t nal, ptl_netid_t netid,
-                   ptl_nid_t nid, uid_t *uid);
+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);
+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))
index 262a554..3892cbc 100644 (file)
---- nfs-utils-1.0.10/utils/gssd/context.c.lustre       2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/context.c      2006-08-14 10:32:30.000000000 -0600
-@@ -33,8 +33,6 @@
- #include <syslog.h>
- #include <string.h>
- #include <gssapi/gssapi.h>
+--- nfs-utils-1.0.10/utils/gssd/gssd_proc.c.lustre     2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/gssd_proc.c    2006-10-13 17:25:01.000000000 -0600
+@@ -43,7 +43,6 @@
+ #endif
+ #include "config.h"
+ #include <sys/param.h>
 -#include <rpc/rpc.h>
--#include <rpc/auth_gss.h>
- #include "gss_util.h"
+ #include <sys/stat.h>
+ #include <sys/socket.h>
+ #include <arpa/inet.h>
+@@ -68,6 +67,7 @@
  #include "gss_oids.h"
- #include "err_util.h"
---- nfs-utils-1.0.10/utils/gssd/context.h.lustre       2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/context.h      2006-08-14 10:32:30.000000000 -0600
-@@ -31,8 +31,6 @@
- #ifndef _CONTEXT_H_
- #define _CONTEXT_H_
+ #include "krb5_util.h"
+ #include "context.h"
++#include "lsupport.h"
  
--#include <rpc/rpc.h>
+ /*
+  * pollarray:
+@@ -98,83 +98,6 @@
+ 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;
 -
- int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf,
-                                gss_OID mech);
- int serialize_spkm3_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf);
---- nfs-utils-1.0.10/utils/gssd/context_mit.c.lustre   2006-08-14 10:32:04.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/context_mit.c  2006-08-14 10:32:30.000000000 -0600
-@@ -34,8 +34,6 @@
- #include <string.h>
- #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"
-@@ -468,6 +466,7 @@
-               else
-                       keyptr = &lctx->cfx_kd.ctx_key;
+-      *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)
+ {
+@@ -189,8 +112,6 @@
+       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);
+ }
  
-+#if 0
-               if (lctx->initiate == 1) {
-                       sign_usage = KG_USAGE_INITIATOR_SIGN;
-                       seal_usage = KG_USAGE_INITIATOR_SEAL;
-@@ -475,6 +474,19 @@
-                       sign_usage = KG_USAGE_ACCEPTOR_SIGN;
-                       seal_usage = KG_USAGE_ACCEPTOR_SEAL;
+@@ -220,7 +141,6 @@
+ {
+       char    kname[32];
+       char    sname[32];
+-      char    info_file_name[32];
+       if (clp->krb5_fd == -1) {
+               snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname);
+@@ -232,13 +152,6 @@
+       }
+       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;
+ }
+@@ -272,6 +185,8 @@
                }
-+#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
+               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);
+       }
  
-               /* derive and send down: Ke, Ki, and Kc */
+       if ((clp->spkm3_fd != -1) && (clp->spkm3_poll_index == -1)) {
+@@ -385,7 +300,10 @@
+ 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;
  
-@@ -793,7 +805,10 @@
+       if (chdir(pipefsdir) < 0) {
+@@ -394,45 +312,76 @@
+               return -1;
+       }
  
- out_err:
-       printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
--      if (buf->value) free(buf->value);
-+      if (buf->value) {
-+              free(buf->value);
-+              buf->value = NULL;
-+      }
-       buf->length = 0;
-       return -1;
+-      j = scandir(pipefsdir, &namelist, NULL, alphasort);
+-      if (j < 0) {
+-              printerr(0, "ERROR: can't scandir %s: %s\n",
+-                       pipefsdir, strerror(errno));
+-              return -1;
++      snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefsdir, "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;
  }
---- nfs-utils-1.0.10/utils/gssd/context_spkm3.c.lustre 2006-08-14 10:32:04.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/context_spkm3.c        2006-08-14 10:32:30.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"
---- nfs-utils-1.0.10/utils/gssd/err_util.c.lustre      2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/err_util.c     2006-08-14 10:32:30.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 @@
-       /* 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");
++/* 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 */
++};
 +
-+      for (i = 0; i < length; i += 0x10) {
-+              printerr(pri, "  %04x: ", (u_int)i);
-+              jm = length - i;
-+              jm = jm > 16 ? 16 : jm;
++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 */
 +
-+              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," ");
++        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 */
 +
-+              for (j = 0; j < jm; j++) {
-+                      c = cp[i+j];
-+                      c = isprint(c) ? c : '.';
-+                      printerr(pri,"%c", c);
-+              }
-+              printerr(pri,"\n");
-+      }
-+}
++        int             lgd_rpc_err;
++        int             lgd_gss_err;
++};
 +
---- nfs-utils-1.0.10/utils/gssd/err_util.h.lustre      2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/err_util.h     2006-08-14 10:32:30.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);
+ 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;
  
- #endif /* _ERR_UTIL_H_ */
---- nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c.lustre     2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c    2006-08-14 10:32:30.000000000 -0600
-@@ -47,6 +47,7 @@
- #include "gssd.h"
- #include "write_bytes.h"
+-      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 0
- char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
+-      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;
  
- static void
-@@ -102,3 +103,4 @@
-       }
-       exit(0);
+       if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
+@@ -440,12 +389,13 @@
+       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;
  }
-+#endif
---- nfs-utils-1.0.10/utils/gssd/gssd.c.lustre  2006-08-14 10:32:04.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/gssd.c 2006-08-14 10:32:30.000000000 -0600
-@@ -40,7 +40,6 @@
- #include <sys/param.h>
- #include <sys/socket.h>
--#include <rpc/rpc.h>
- #include <unistd.h>
- #include <err.h>
-@@ -52,6 +51,7 @@
- #include "err_util.h"
- #include "gss_util.h"
- #include "krb5_util.h"
-+#include "lsupport.h"
  
- char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
- char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
-@@ -77,7 +77,7 @@
- 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);
- }
-@@ -87,7 +87,6 @@
+ static int
+-do_error_downcall(int k5_fd, uid_t uid, int err)
++do_error_downcall(int k5_fd, struct lgssd_upcall_data *updata,
++                int rpc_err, int gss_err)
  {
-       int fg = 0;
-       int verbosity = 0;
--      int rpc_verbosity = 0;
-       int opt;
-       extern char *optarg;
-       char *progname;
-@@ -97,15 +96,9 @@
-                       case 'f':
-                               fg = 1;
-                               break;
--                      case 'm':
--                              /* Accept but ignore this. Now the default. */
--                              break;
-                       case 'v':
-                               verbosity++;
-                               break;
--                      case 'r':
--                              rpc_verbosity++;
--                              break;
-                       case 'p':
-                               strncpy(pipefsdir, optarg, sizeof(pipefsdir));
-                               if (pipefsdir[sizeof(pipefsdir)-1] != '\0')
-@@ -126,10 +119,6 @@
-                               break;
-               }
-       }
--      strncat(pipefsdir + strlen(pipefsdir), "/" GSSD_SERVICE_NAME,
--              sizeof(pipefsdir)-strlen(pipefsdir));
--      if (pipefsdir[sizeof(pipefsdir)-1] != '\0')
--              errx(1, "pipefs path name too long");
+       char    buf[1024];
+       char    *p = buf, *end = buf + 1024;
+@@ -454,11 +404,12 @@
  
-       if ((progname = strrchr(argv[0], '/')))
-               progname++;
-@@ -137,30 +126,34 @@
-               progname = argv[0];
+       printerr(1, "doing error downcall\n");
  
-       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 (WRITE_BYTES(&p, end, uid)) goto out_err;
++      if (WRITE_BYTES(&p, end, updata->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 (gssd_check_mechs() != 0)
-               errx(1, "Problem with gssapi library");
+       if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
+       return 0;
+@@ -467,6 +418,7 @@
+       return -1;
+ }
  
 +#if 0
-+      /* Determine Kerberos information from the kernel */
-+      gssd_obtain_kernel_krb5_info();
+ /*
+  * Create an RPC connection and establish an authenticated
+  * gss context with a server.
+@@ -658,7 +610,287 @@
+       goto out;
+ }
 +#endif
 +
-       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);
++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;
 +
-+      /* 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())
++      pw = getpwuid(lgd->lgd_uid);
++      if (!pw) {
++              printerr(0, "no uid %u in local user database\n",
++                       lgd->lgd_uid);
 +              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();
--      /* Determine Kerberos information from the kernel */
--      gssd_obtain_kernel_krb5_info();
--
--      gssd_run();
-+      lgssd_run();
-       printerr(0, "gssd_run returned!\n");
-       abort();
- }
---- nfs-utils-1.0.10/utils/gssd/gssd.h.lustre  2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/gssd.h 2006-08-14 10:32:30.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
-@@ -61,6 +66,7 @@
- extern char                   pipefsdir[PATH_MAX];
- extern char                   keytabfile[PATH_MAX];
- extern char                   ccachedir[PATH_MAX];
-+extern char                   gethostname_ex[PATH_MAX];
- TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list;
-@@ -69,10 +75,6 @@
-       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;
-@@ -83,8 +85,7 @@
- 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);
- #endif /* _RPC_GSSD_H_ */
---- nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c.lustre        2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c       2006-08-14 10:32:30.000000000 -0600
-@@ -94,7 +94,7 @@
- };
- void
--gssd_run()
-+lgssd_run()
- {
-       int                     ret;
-       struct sigaction        dn_act;
-@@ -118,6 +118,7 @@
-       while (1) {
-               while (dir_changed) {
-+                      printerr(2, "pipefs root dir changed\n");
-                       dir_changed = 0;
-                       if (update_client_list()) {
-                               printerr(0, "ERROR: couldn't update "
---- nfs-utils-1.0.10/utils/gssd/gssd_proc.c.lustre     2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/gssd_proc.c    2006-08-14 10:32:30.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>
-@@ -68,6 +67,7 @@
- #include "gss_oids.h"
- #include "krb5_util.h"
- #include "context.h"
-+#include "lsupport.h"
- /*
-  * pollarray:
-@@ -98,83 +98,6 @@
- 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)
- {
-@@ -189,8 +112,6 @@
-       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);
- }
-@@ -220,7 +141,6 @@
- {
-       char    kname[32];
-       char    sname[32];
--      char    info_file_name[32];
-       if (clp->krb5_fd == -1) {
-               snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname);
-@@ -232,13 +152,6 @@
-       }
-       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;
- }
-@@ -272,6 +185,8 @@
-               }
-               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)) {
-@@ -385,7 +300,10 @@
- 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(pipefsdir) < 0) {
-@@ -394,45 +312,76 @@
-               return -1;
-       }
--      j = scandir(pipefsdir, &namelist, NULL, alphasort);
--      if (j < 0) {
--              printerr(0, "ERROR: can't scandir %s: %s\n",
--                       pipefsdir, strerror(errno));
--              return -1;
-+      snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefsdir, "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;
-@@ -440,12 +389,13 @@
-       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, struct lgssd_upcall_data *updata,
-+                int rpc_err, int gss_err)
- {
-       char    buf[1024];
-       char    *p = buf, *end = buf + 1024;
-@@ -454,11 +404,12 @@
-       printerr(1, "doing error downcall\n");
--      if (WRITE_BYTES(&p, end, uid)) goto out_err;
-+      if (WRITE_BYTES(&p, end, updata->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;
-       return 0;
-@@ -467,6 +418,7 @@
-       return -1;
- }
-+#if 0
- /*
-  * Create an RPC connection and establish an authenticated
-  * gss context with a server.
-@@ -658,7 +610,287 @@
-       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;
 +                clp->servicename = NULL;
 +        }
 +
-+        if (ptl_nid2hostname(ud->nid, name, buflen))
++        if (lnet_nid2hostname(ud->nid, name, buflen))
 +                return -1;
 +
 +        clp->servicename = malloc(32 + strlen(name));
        goto out;
 +#endif
  }
---- nfs-utils-1.0.10/utils/gssd/gss_util.c.lustre      2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/gss_util.c     2006-08-14 10:32:30.000000000 -0600
-@@ -87,9 +87,16 @@
- #ifdef HAVE_COM_ERR_H
- #include <com_err.h>
- #endif
-+#include "lsupport.h"
+--- nfs-utils-1.0.10/utils/gssd/context_mit.c.lustre   2006-10-13 16:02:38.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/context_mit.c  2006-10-13 16:03:33.000000000 -0600
+@@ -34,8 +34,6 @@
+ #include <string.h>
+ #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"
+@@ -468,6 +466,7 @@
+               else
+                       keyptr = &lctx->cfx_kd.ctx_key;
  
- /* 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;
++#if 0
+               if (lctx->initiate == 1) {
+                       sign_usage = KG_USAGE_INITIATOR_SIGN;
+                       seal_usage = KG_USAGE_INITIATOR_SEAL;
+@@ -475,6 +474,19 @@
+                       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
  
- gss_OID g_mechOid = GSS_C_NULL_OID;;
+               /* derive and send down: Ke, Ki, and Kc */
  
-@@ -183,15 +190,51 @@
-       display_status_2(msg, maj_stat, min_stat, mech);
+@@ -793,7 +805,10 @@
+ out_err:
+       printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
+-      if (buf->value) free(buf->value);
++      if (buf->value) {
++              free(buf->value);
++              buf->value = NULL;
++      }
+       buf->length = 0;
+       return -1;
  }
+--- nfs-utils-1.0.10/utils/gssd/context.h.lustre       2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/context.h      2006-10-13 16:03:33.000000000 -0600
+@@ -31,8 +31,6 @@
+ #ifndef _CONTEXT_H_
+ #define _CONTEXT_H_
  
--int
--gssd_acquire_cred(char *server_name)
-+static
-+int extract_realm_name(gss_buffer_desc *name, char **realm)
-+{
-+        char *sname, *c;
-+
-+        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 (!realm)
-+                *realm = NULL;
-+        else {
-+                c++;
-+                *realm = malloc(strlen(c) + 1);
-+                if (!*realm) {
-+                        printerr(0, "out of memory\n");
-+                        return -ENOMEM;
-+                }
-+                strcpy(*realm, c);
-+        }
-+        free(sname);
-+
-+        return 0;
-+}
-+
-+static
-+int gssd_acquire_cred(char *server_name, gss_cred_id_t *cred,
-+                    char **local_realm, int *valid)
+-#include <rpc/rpc.h>
+-
+ int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf,
+                                gss_OID mech);
+ int serialize_spkm3_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf);
+--- nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c.lustre        2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c       2006-10-13 16:03:33.000000000 -0600
+@@ -94,7 +94,7 @@
+ };
+ void
+-gssd_run()
++lgssd_run()
  {
-       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;
+       int                     ret;
+       struct sigaction        dn_act;
+@@ -118,6 +118,7 @@
  
-+      *valid = 0;
-+
-       name.value = (void *)server_name;
-       name.length = strlen(server_name);
+       while (1) {
+               while (dir_changed) {
++                      printerr(2, "pipefs root dir changed\n");
+                       dir_changed = 0;
+                       if (update_client_list()) {
+                               printerr(0, "ERROR: couldn't update "
+--- nfs-utils-1.0.10/utils/gssd/svcgssd.c.lustre       2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/svcgssd.c      2006-10-13 16:03:33.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>
  
-@@ -201,12 +244,20 @@
+@@ -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"
  
-       if (maj_stat != GSS_S_COMPLETE) {
-               pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid);
--              return (FALSE);
-+              return -1;
-+      }
++void
++closeall(int min)
++{
++      DIR *dir = opendir("/proc/self/fd");
++      if (dir != NULL) {
++              int dfd = dirfd(dir);
++              struct dirent *d;
 +
-+      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;
++              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
+@@ -165,8 +186,8 @@
+       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;
  
-       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);
+@@ -181,8 +202,13 @@
+                       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 +222,13 @@
+               progname = argv[0];
  
-       if (maj_stat != GSS_S_COMPLETE) {
-               pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid);
-@@ -218,11 +269,65 @@
-                       ignore_maj_stat = gss_release_buffer(&ignore_min_stat,
-                                                            &pbuf);
-               }
--      }
-+      } else
-+              *valid = 1;
+       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
  
-       ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name);
+       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 (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 +237,18 @@
+       }
  
--      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;
-+        }
-+
-+        printerr(0, "Ready to serve %s\n",
-+                 gssd_cred_mds_valid && !gssd_cred_oss_valid ? "Lustre MDS" :
-+                 (!gssd_cred_mds_valid && gssd_cred_oss_valid ? "Lustre OSS" :
-+                 "Lustre MDS and OSS"));
+       if (!fg)
++              mydaemon(0, 0);
 +
-+        return 0;
-+}
++      signal(SIGINT, sig_die);
++      signal(SIGTERM, sig_die);
++      signal(SIGHUP, sig_hup);
 +
-+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);
-+        }
++      if (!fg)
+               release_parent();
+-      gssd_run();
++      gssd_init_unique(GSSD_SVC);
 +
-+        return NULL;
++      svcgssd_run();
+       printerr(0, "gssd_run returned!\n");
+       abort();
  }
+--- nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c.lustre  2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c 2006-10-13 16:48:03.000000000 -0600
+@@ -35,7 +35,6 @@
  
- int gssd_check_mechs(void)
---- nfs-utils-1.0.10/utils/gssd/gss_util.h.lustre      2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/gss_util.h     2006-08-14 10:32:30.000000000 -0600
-@@ -32,12 +32,10 @@
- #define _GSS_UTIL_H_
- #include <stdlib.h>
--#include <rpc/rpc.h>
- #include "write_bytes.h"
- 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);
---- nfs-utils-1.0.10/utils/gssd/krb5_util.c.lustre     2006-08-14 10:32:04.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/krb5_util.c    2006-08-14 10:32:30.000000000 -0600
-@@ -99,12 +99,14 @@
- #include <rpc/rpc.h>
- #include <sys/types.h>
+ #include <sys/param.h>
  #include <sys/stat.h>
-+#include <sys/utsname.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
+-#include <rpc/rpc.h>
  
+ #include <pwd.h>
  #include <stdio.h>
- #include <stdlib.h>
+@@ -44,25 +43,28 @@
  #include <string.h>
-+#include <netdb.h>
- #include <dirent.h>
  #include <fcntl.h>
  #include <errno.h>
-@@ -114,7 +116,6 @@
- #include <gssapi/gssapi_krb5.h>
- #endif
- #include <krb5.h>
--#include <rpc/auth_gss.h>
+-#include <nfsidmap.h>
++#include <netdb.h>
  
- #include "gssd.h"
+ #include "svcgssd.h"
+ #include "gss_util.h"
  #include "err_util.h"
-@@ -129,6 +130,12 @@
- int num_krb5_enctypes = 0;
- krb5_enctype *krb5_enctypes = NULL;
+ #include "context.h"
+ #include "cacheio.h"
++#include "lsupport.h"
  
-+/* realm of this node */
-+char *this_realm = NULL;
-+
-+/* credential expire time in advance */
-+unsigned long machine_cred_expire_advance = 300; /* 5 mins */
-+
- /*==========================*/
- /*===  Internal routines ===*/
- /*==========================*/
-@@ -137,11 +144,55 @@
- 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);
+ 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"
  
- /*
-+ * 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
-  *
-@@ -292,7 +343,7 @@
+ #define TOKEN_BUF_SIZE                8192
  
-       memset(&my_creds, 0, sizeof(my_creds));
+ 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;
+ };
  
--      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;
-@@ -323,11 +374,7 @@
-                           "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;
-       }
+ static int
+@@ -70,10 +72,9 @@
+               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 @@
+       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 @@
+       /* XXXARG: */
+       int g;
  
-@@ -371,15 +418,7 @@
-       return (code);
+-      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 @@
+ #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 @@
+               }
+       }
  }
++#endif
  
--/*
-- * 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)
++#if 0
+ static int
+ get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred)
  {
-       struct gssd_k5_kt_princ *ple;
- #ifdef HAVE_KRB5
-@@ -389,18 +428,76 @@
- #endif
+@@ -248,7 +253,9 @@
+ out:
+       return res;
+ }
++#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;
++#if 0
+ void
+ print_hexl(int pri, unsigned char *cp, int length)
+ {
+@@ -285,12 +292,110 @@
+               printerr(pri,"\n");
        }
-       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;
++#endif
 +
-+      ple = malloc(sizeof(*ple));
-+      if (ple == NULL) {
-+              printerr(0, "ERROR: could not allocate storage "
-+                          "for principal list entry\n");
-+              return NULL;
-+      }
++static int
++get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
++      lnet_nid_t nid)
++{
++      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;
 +
-+      memset(ple, 0, sizeof(*ple));
++      memset(cred, 0, sizeof(*cred));
 +
-+      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;
++      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;
 +      }
-+
-+      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;
++      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, "authenticate user %s\n", sname);
++      gss_release_buffer(&min_stat, &name);
 +
-+      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.
-@@ -444,82 +541,106 @@
-               }
-               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;
-+                      }
++      lookup_mapping(sname, nid, &cred->cr_mapped_uid);
 +
-+                      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;
-+                              }
++        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);
++        }
 +
-+                              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;
-+                              }
++        if (cred->cr_remote) {
++                if (cred->cr_mapped_uid != -1)
++                        res = 0;
++                else
++                        printerr(0, "principal %s is remote without mapping\n",
++                                 sname);
++              goto out_free;
++        }
 +
-+                              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
++        slash = strchr(sname, '/');
++        if (slash)
++                *slash = '\0';
 +
-+              /* 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;
-+              }
++        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);
++        }
 +
-+              /* 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;
++        res = 0;
++out_free:
++        free(sname);
++        return res;
++}
 +
-+              /* 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);
-       }
++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;
  
-       if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) {
-@@ -695,7 +816,18 @@
-               goto out;
+ void
+ 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 +407,13 @@
+                               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,7 +421,7 @@
+       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: "
+@@ -323,15 +431,21 @@
+       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 +465,13 @@
+               memcpy(&ctx, in_handle.value, in_handle.length);
        }
  
--      printerr(1, "Using keytab file '%s'\n", keytabfile);
-+      if (this_realm == NULL) {
-+              code = krb5_get_default_realm(context, &this_realm);
-+              if (code) {
-+                      printerr(0, "ERROR: get default realm: %s\n",
-+                               error_message(code));
-+                      retval = code;
-+                      goto out;
-+              }
-+              printerr(1, "Local realm: %s\n", this_realm);
+-      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;
 +      }
 +
-+      printerr(2, "Using keytab file '%s'\n", keytabfile);
++      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);
  
-       if ((code = krb5_kt_resolve(context, keytabfile, &kt))) {
-               printerr(0, "ERROR: %s while resolving keytab '%s'\n",
-@@ -710,12 +842,12 @@
-               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);
-               }
+@@ -369,7 +489,7 @@
+                       maj_stat, min_stat, mech);
+               goto out_err;
+       }
+-      if (get_ids(client_name, mech, &cred)) {
++      if (get_ids(client_name, mech, &cred, nid)) {
+               /* get_ids() prints error msg */
+               maj_stat = GSS_S_BAD_NAME; /* XXX ? */
+               gss_release_name(&ignore_min_stat, &client_name);
+@@ -377,10 +497,8 @@
        }
+       gss_release_name(&ignore_min_stat, &client_name);
  
-@@ -865,6 +997,7 @@
-       krb5_free_context(context);
- }
+-
+       /* 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));
  
-+#if 0
- #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
- /*
-  * this routine obtains a credentials handle via gss_acquire_cred()
-@@ -920,6 +1053,7 @@
-       return 0;
- }
- #endif        /* HAVE_SET_ALLOWABLE_ENCTYPES */
-+#endif
+@@ -404,7 +522,6 @@
+               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;
+ out_err:
+--- nfs-utils-1.0.10/utils/gssd/gss_util.c.lustre      2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/gss_util.c     2006-10-13 16:03:33.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;
  
- /*
-  * Obtain supported enctypes from kernel.
---- nfs-utils-1.0.10/utils/gssd/krb5_util.h.lustre     2006-08-14 10:32:04.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/krb5_util.h    2006-08-14 10:32:30.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,32 @@
- void gssd_obtain_kernel_krb5_info(void);
+ gss_OID g_mechOid = GSS_C_NULL_OID;;
  
+@@ -183,15 +190,51 @@
+       display_status_2(msg, maj_stat, min_stat, mech);
+ }
  
--#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
--int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
--#endif
-+#endif /* KRB5_UTIL_H */
-+#ifndef KRB5_UTIL_H
-+#define KRB5_UTIL_H
+-int
+-gssd_acquire_cred(char *server_name)
++static
++int extract_realm_name(gss_buffer_desc *name, char **realm)
++{
++        char *sname, *c;
 +
-+#include <krb5.h>
++        sname = malloc(name->length + 1);
++        if (!sname) {
++                printerr(0, "out of memory\n");
++                return -ENOMEM;
++        }
 +
-+/*
-+ * List of principals from our keytab that we
-+ * may try to get credentials for
-+ */
-+struct gssd_k5_kt_princ {
-+      struct gssd_k5_kt_princ *next;
-+      krb5_principal princ;
-+      char *ccname;
-+      char *realm;
-+      krb5_timestamp endtime;
-+};
++        memcpy(sname, name->value, name->length);
++        sname[name->length] = '\0';
++        printerr(1, "service principal: %s\n", sname);
 +
++        c = strchr(sname, '@');
++        if (!realm)
++                *realm = NULL;
++        else {
++                c++;
++                *realm = malloc(strlen(c) + 1);
++                if (!*realm) {
++                        printerr(0, "out of memory\n");
++                        return -ENOMEM;
++                }
++                strcpy(*realm, c);
++        }
++        free(sname);
 +
-+void gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername);
-+int  gssd_get_krb5_machine_cred_list(char ***list);
-+int  gssd_refresh_krb5_machine_creds(void);
-+void gssd_free_krb5_machine_cred_list(char **list);
-+void gssd_setup_krb5_machine_gss_ccache(char *servername);
-+void gssd_destroy_krb5_machine_creds(void);
-+void gssd_obtain_kernel_krb5_info(void);
++        return 0;
++}
 +
++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;
  
- #endif /* KRB5_UTIL_H */
---- nfs-utils-1.0.10/utils/gssd/Makefile.am.lustre     2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/Makefile.am    2006-08-14 10:32:30.000000000 -0600
-@@ -1,17 +1,11 @@
- ## Process this file with automake to produce Makefile.in
++      *valid = 0;
++
+       name.value = (void *)server_name;
+       name.length = strlen(server_name);
  
--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
+@@ -201,12 +244,20 @@
  
--EXTRA_DIST = \
--      gss_destroy_creds \
--      $(man8_MANS)
--
- COMMON_SRCS = \
-       context.c \
-       context_mit.c \
-@@ -20,13 +14,15 @@
-       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
+       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;
  
--gssd_SOURCES = \
-+lgssd_SOURCES = \
-       $(COMMON_SRCS) \
-       gssd.c \
-       gssd_main_loop.c \
-@@ -37,13 +33,12 @@
-       krb5_util.h \
-       write_bytes.h
+       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);
  
--gssd_LDADD = $(RPCSECGSS_LIBS) $(KRBLIBS)
--gssd_LDFLAGS = $(KRBLDFLAGS)
-+lgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS)
-+lgssd_LDFLAGS = $(KRBLDFLAGS)
+       if (maj_stat != GSS_S_COMPLETE) {
+               pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid);
+@@ -218,11 +269,65 @@
+                       ignore_maj_stat = gss_release_buffer(&ignore_min_stat,
+                                                            &pbuf);
+               }
+-      }
++      } else
++              *valid = 1;
  
--gssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
--            $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
-+lgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
+       ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name);
  
--svcgssd_SOURCES = \
-+lsvcgssd_SOURCES = \
-       $(COMMON_SRCS) \
-       cacheio.c \
-       svcgssd.c \
-@@ -54,20 +49,11 @@
-       cacheio.h \
-       svcgssd.h
+-      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;
++        }
++
++        printerr(0, "Ready to serve %s\n",
++                 gssd_cred_mds_valid && !gssd_cred_oss_valid ? "Lustre MDS" :
++                 (!gssd_cred_mds_valid && gssd_cred_oss_valid ? "Lustre OSS" :
++                 "Lustre MDS and OSS"));
++
++        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;
+ }
  
--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)
+ int gssd_check_mechs(void)
+--- nfs-utils-1.0.10/utils/gssd/gss_util.h.lustre      2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/gss_util.h     2006-10-13 16:03:33.000000000 -0600
+@@ -32,12 +32,10 @@
+ #define _GSS_UTIL_H_
  
--gss_clnt_send_err_SOURCES = gss_clnt_send_err.c
-+lsvcgssd_LDFLAGS = $(KRBLDFLAGS)
+ #include <stdlib.h>
+-#include <rpc/rpc.h>
+ #include "write_bytes.h"
  
--gss_clnt_send_err_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
--               $(RPCSECGSS_CFLAGS) $(KRBCFLAGS)
-+lsvcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS)
+ extern gss_cred_id_t  gssd_creds;
  
- MAINTAINERCLEANFILES = Makefile.in
+-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);
+--- nfs-utils-1.0.10/utils/gssd/krb5_util.h.lustre     2006-10-13 16:02:38.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/krb5_util.h    2006-10-13 16:03:33.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,32 @@
+ void gssd_obtain_kernel_krb5_info(void);
  
-@@ -91,23 +77,3 @@
-         done)
  
+-#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+-int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
+-#endif
++#endif /* KRB5_UTIL_H */
++#ifndef KRB5_UTIL_H
++#define KRB5_UTIL_H
++
++#include <krb5.h>
++
++/*
++ * List of principals from our keytab that we
++ * may try to get credentials for
++ */
++struct gssd_k5_kt_princ {
++      struct gssd_k5_kt_princ *next;
++      krb5_principal princ;
++      char *ccname;
++      char *realm;
++      krb5_timestamp endtime;
++};
++
++
++void gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername);
++int  gssd_get_krb5_machine_cred_list(char ***list);
++int  gssd_refresh_krb5_machine_creds(void);
++void gssd_free_krb5_machine_cred_list(char **list);
++void gssd_setup_krb5_machine_gss_ccache(char *servername);
++void gssd_destroy_krb5_machine_creds(void);
++void gssd_obtain_kernel_krb5_info(void);
++
  
--# 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)
--
---- nfs-utils-1.0.10/utils/gssd/svcgssd.c.lustre       2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/svcgssd.c      2006-08-14 10:32:45.000000000 -0600
-@@ -43,7 +43,6 @@
+ #endif /* KRB5_UTIL_H */
+--- nfs-utils-1.0.10/utils/gssd/krb5_util.c.lustre     2006-10-13 16:02:38.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/krb5_util.c    2006-10-13 16:03:33.000000000 -0600
+@@ -99,12 +99,14 @@
+ #include <rpc/rpc.h>
  #include <sys/types.h>
  #include <sys/stat.h>
++#include <sys/utsname.h>
  #include <sys/socket.h>
--#include <rpc/rpc.h>
- #include <fcntl.h>
- #include <errno.h>
+ #include <arpa/inet.h>
  
-@@ -54,11 +53,33 @@
+ #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
- #include <signal.h>
--#include "nfslib.h"
-+#include <dirent.h>
- #include "svcgssd.h"
- #include "gss_util.h"
++#include <netdb.h>
+ #include <dirent.h>
+ #include <fcntl.h>
+ #include <errno.h>
+@@ -114,7 +116,6 @@
+ #include <gssapi/gssapi_krb5.h>
+ #endif
+ #include <krb5.h>
+-#include <rpc/auth_gss.h>
+ #include "gssd.h"
  #include "err_util.h"
-+#include "lsupport.h"
+@@ -129,6 +130,12 @@
+ int num_krb5_enctypes = 0;
+ krb5_enctype *krb5_enctypes = NULL;
  
-+void
-+closeall(int min)
++/* realm of this node */
++char *this_realm = NULL;
++
++/* credential expire time in advance */
++unsigned long machine_cred_expire_advance = 300; /* 5 mins */
++
+ /*==========================*/
+ /*===  Internal routines ===*/
+ /*==========================*/
+@@ -137,11 +144,55 @@
+ 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
+  *
+@@ -292,7 +343,7 @@
+       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;
+@@ -323,11 +374,7 @@
+                           "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;
+       }
+@@ -371,15 +418,7 @@
+       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
+@@ -389,18 +428,76 @@
+ #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)
 +{
-+      DIR *dir = opendir("/proc/self/fd");
-+      if (dir != NULL) {
-+              int dfd = dirfd(dir);
-+              struct dirent *d;
++      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;
 +
-+              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);
++      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;
 +}
++
  /*
-  * mydaemon creates a pipe between the partent and child
-  * process. The parent process will wait until the
-@@ -165,8 +186,8 @@
-       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 +202,13 @@
-                       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 +222,13 @@
-               progname = argv[0];
-       initerr(progname, verbosity, fg);
--#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
--      authgss_set_debug_level(rpc_verbosity);
+  * Process the given keytab file and create a list of principals we
+  * might use to perform mount operations.
+@@ -444,82 +541,106 @@
+               }
+               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 (rpc_verbosity > 0)
--              printerr(0, "Warning: rpcsec_gss library does not "
--                          "support setting debug level\n");
+-              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
-       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 (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 +237,18 @@
-       }
-       if (!fg)
-+              mydaemon(0, 0);
+-                   (!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;
 +
-+      signal(SIGINT, sig_die);
-+      signal(SIGTERM, sig_die);
-+      signal(SIGHUP, sig_hup);
++              /* 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 (!fg)
-               release_parent();
--      gssd_run();
-+      gssd_init_unique(GSSD_SVC);
++                      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;
 +
-+      svcgssd_run();
-       printerr(0, "gssd_run returned!\n");
-       abort();
- }
---- nfs-utils-1.0.10/utils/gssd/svcgssd.h.lustre       2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/svcgssd.h      2006-08-14 10:32:30.000000000 -0600
-@@ -36,8 +36,19 @@
- #include <gssapi/gssapi.h>
- void handle_nullreq(FILE *f);
--void gssd_run(void);
-+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;
++                      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;
++                              }
 +
-+#define GSSD_SERVICE_NAME     "lustre"
++                              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
 +
-+/* 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_ */
---- nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c.lustre     2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c    2006-08-14 10:32:30.000000000 -0600
-@@ -47,31 +47,31 @@
- #include "err_util.h"
- void
--gssd_run()
-+svcgssd_run()
- {
-       int                     ret;
-       FILE                    *f;
-       struct pollfd           pollfd;
--#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 = fopen(NULLRPC_FILE, "rw")) == NULL) {
-+                      printerr(3, "failed to open %s: %s\n",
-+                               NULLRPC_FILE, strerror(errno));
-+                      sleep(1);
++              /* 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;
 +              }
-+              pollfd.fd = fileno(f);
-+              pollfd.events = POLLIN;
 +
-               pollfd.revents = 0;
--              printerr(1, "entering poll\n");
--              ret = poll(&pollfd, 1, -1);
-+              printerr(3, "entering poll\n");
-+              ret = poll(&pollfd, 1, 1000);
-               save_err = errno;
--              printerr(1, "leaving poll\n");
-+              printerr(3, "leaving poll\n");
++              /* 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;
 +
-               if (ret < 0) {
-                       if (save_err != EINTR)
-                               printerr(0, "error return from poll: %s\n",
-@@ -87,5 +87,6 @@
-                       if (pollfd.revents & POLLIN)
-                               handle_nullreq(f);
-               }
-+              fclose(f);
++              /* 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);
        }
- }
---- nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c.lustre  2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c 2006-08-14 10:32:30.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 @@
-               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 @@
-       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 @@
-       /* XXXARG: */
-       int g;
  
--      printerr(1, "sending null reply\n");
-+      printerr(2, "sending null reply\n");
+       if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) {
+@@ -695,7 +816,18 @@
+               goto out;
+       }
  
-       qword_addhex(&bp, &blen, in_handle->value, in_handle->length);
-       qword_addhex(&bp, &blen, in_token->value, in_token->length);
-@@ -159,6 +161,7 @@
- #define rpcsec_gsserr_credproblem     13
- #define rpcsec_gsserr_ctxproblem      14
+-      printerr(1, "Using keytab file '%s'\n", keytabfile);
++      if (this_realm == NULL) {
++              code = krb5_get_default_realm(context, &this_realm);
++              if (code) {
++                      printerr(0, "ERROR: get default realm: %s\n",
++                               error_message(code));
++                      retval = code;
++                      goto out;
++              }
++              printerr(1, "Local realm: %s\n", this_realm);
++      }
++
++      printerr(2, "Using keytab file '%s'\n", keytabfile);
  
-+#if 0
- static void
- add_supplementary_groups(char *secname, char *name, struct svc_cred *cred)
- {
-@@ -182,7 +185,9 @@
+       if ((code = krb5_kt_resolve(context, keytabfile, &kt))) {
+               printerr(0, "ERROR: %s while resolving keytab '%s'\n",
+@@ -710,12 +842,12 @@
+               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);
                }
        }
+@@ -865,6 +997,7 @@
+       krb5_free_context(context);
  }
-+#endif
  
 +#if 0
- static int
- get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred)
- {
-@@ -248,7 +253,9 @@
- out:
-       return res;
+ #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+ /*
+  * this routine obtains a credentials handle via gss_acquire_cred()
+@@ -920,6 +1053,7 @@
+       return 0;
  }
+ #endif        /* HAVE_SET_ALLOWABLE_ENCTYPES */
 +#endif
  
+ /*
+  * Obtain supported enctypes from kernel.
+--- nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c.lustre     2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c    2006-10-13 16:03:33.000000000 -0600
+@@ -47,6 +47,7 @@
+ #include "gssd.h"
+ #include "write_bytes.h"
 +#if 0
- void
- print_hexl(int pri, unsigned char *cp, int length)
- {
-@@ -285,12 +292,114 @@
-               printerr(pri,"\n");
+ char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
+ static void
+@@ -102,3 +103,4 @@
        }
+       exit(0);
  }
 +#endif
+--- nfs-utils-1.0.10/utils/gssd/context.c.lustre       2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/context.c      2006-10-13 16:03:33.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"
+--- nfs-utils-1.0.10/utils/gssd/lsupport.h.lustre      2006-10-13 16:03:33.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/lsupport.h     2006-10-13 17:24:45.000000000 -0600
+@@ -0,0 +1,88 @@
++/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
++ * vim:expandtab:shiftwidth=8:tabstop=8:
++ */
 +
-+static int
-+get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
-+      ptl_nid_t ptl_nid)
-+{
-+      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;
++#ifndef __LIBCFS_H__
++#define __LIBCFS_H__
 +
-+      memset(cred, 0, sizeof(*cred));
++#include <unistd.h>
++#include <stdint.h>
 +
-+      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, "authenticate user %s\n", sname);
-+      gss_release_buffer(&min_stat, &name);
++#define GSSD_CLI        (0)
++#define GSSD_SVC        (1)
 +
-+#if 0
-+      lookup_mapping(sname, ptl_nal, ptl_netid, ptl_nid, &cred->cr_mapped_uid);
-+#else
-+      cred->cr_mapped_uid = -1;
-+#endif
++void gssd_init_unique(int type);
++void gssd_exit_unique(int type);
 +
-+        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);
-+        }
++/*
++ * copied from lustre source
++ */
 +
-+        if (cred->cr_remote) {
-+                if (cred->cr_mapped_uid != -1)
-+                        res = 0;
-+                else
-+                        printerr(0, "principal %s is remote without mapping\n",
-+                                 sname);
-+              goto out_free;
-+        }
++#define LUSTRE_GSS_SVC_MDS      0
++#define LUSTRE_GSS_SVC_OSS      1
 +
-+        slash = strchr(sname, '/');
-+        if (slash)
-+                *slash = '\0';
++struct lgssd_upcall_data {
++        uint32_t        seq;
++        uint32_t        uid;
++        uint32_t        gid;
++        uint32_t        svc;
++        uint64_t        nid;
++        char            obd[64];
++};
 +
-+        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);
-+        }
++#define GSSD_INTERFACE_VERSION        (1)
 +
-+        res = 0;
-+out_free:
-+        free(sname);
-+        return res;
++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);
++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__ */
+--- nfs-utils-1.0.10/utils/gssd/err_util.c.lustre      2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/err_util.c     2006-10-13 16:03:33.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 @@
+       /* 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");
++      }
 +}
 +
-+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;
+--- nfs-utils-1.0.10/utils/gssd/context_spkm3.c.lustre 2006-10-13 16:02:38.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/context_spkm3.c        2006-10-13 16:03:33.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"
+--- nfs-utils-1.0.10/utils/gssd/gssd.c.lustre  2006-10-13 16:02:38.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/gssd.c 2006-10-13 16:03:33.000000000 -0600
+@@ -40,7 +40,6 @@
  
- void
- 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 +411,13 @@
-                               ignore_out_tok = {.value = NULL},
-       /* XXX isn't there a define for this?: */
-                               null_token = {.value = NULL};
-+      uint32_t                lustre_svc;
-+      uint64_t                ptl_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,7 +425,7 @@
-       static int              lbuflen = 0;
-       static char             *cp;
+ #include <sys/param.h>
+ #include <sys/socket.h>
+-#include <rpc/rpc.h>
+ #include <unistd.h>
+ #include <err.h>
+@@ -52,6 +51,7 @@
+ #include "err_util.h"
+ #include "gss_util.h"
+ #include "krb5_util.h"
++#include "lsupport.h"
+ char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
+ char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
+@@ -77,7 +77,7 @@
+ 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);
+ }
+@@ -87,7 +87,6 @@
+ {
+       int fg = 0;
+       int verbosity = 0;
+-      int rpc_verbosity = 0;
+       int opt;
+       extern char *optarg;
+       char *progname;
+@@ -97,15 +96,9 @@
+                       case 'f':
+                               fg = 1;
+                               break;
+-                      case 'm':
+-                              /* Accept but ignore this. Now the default. */
+-                              break;
+                       case 'v':
+                               verbosity++;
+                               break;
+-                      case 'r':
+-                              rpc_verbosity++;
+-                              break;
+                       case 'p':
+                               strncpy(pipefsdir, optarg, sizeof(pipefsdir));
+                               if (pipefsdir[sizeof(pipefsdir)-1] != '\0')
+@@ -126,10 +119,6 @@
+                               break;
+               }
+       }
+-      strncat(pipefsdir + strlen(pipefsdir), "/" GSSD_SERVICE_NAME,
+-              sizeof(pipefsdir)-strlen(pipefsdir));
+-      if (pipefsdir[sizeof(pipefsdir)-1] != '\0')
+-              errx(1, "pipefs path name too long");
  
--      printerr(1, "handling null request\n");
-+      printerr(2, "handling null request\n");
+       if ((progname = strrchr(argv[0], '/')))
+               progname++;
+@@ -137,30 +126,34 @@
+               progname = argv[0];
  
-       if (readline(fileno(f), &lbuf, &lbuflen) != 1) {
-               printerr(0, "WARNING: handle_nullreq: "
-@@ -323,15 +435,21 @@
+       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
  
-       cp = lbuf;
+       if (gssd_check_mechs() != 0)
+               errx(1, "Problem with gssapi library");
  
-+      qword_get(&cp, (char *) &lustre_svc, sizeof(lustre_svc));
-+      qword_get(&cp, (char *) &ptl_nid, sizeof(ptl_nid));
-+      qword_get(&cp, (char *) &handle_seq, sizeof(handle_seq));
-+      printerr(1, "handling req: svc %u, nid %016llx, idx %llx\n",
-+               lustre_svc, ptl_nid, handle_seq);
++#if 0
++      /* Determine Kerberos information from the kernel */
++      gssd_obtain_kernel_krb5_info();
++#endif
 +
-       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 +469,13 @@
-               memcpy(&ctx, in_handle.value, in_handle.length);
-       }
+       if (!fg && daemon(0, 0) < 0)
+               errx(1, "fork");
  
--      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;
-+      }
++      /* This should be checked _after_ daemon(), because we need to own
++       * the undo-able semaphore by this process
++       */
++      gssd_init_unique(GSSD_CLI);
 +
-+      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 +493,7 @@
-                       maj_stat, min_stat, mech);
-               goto out_err;
-       }
--      if (get_ids(client_name, mech, &cred)) {
-+      if (get_ids(client_name, mech, &cred, ptl_nid)) {
-               /* get_ids() prints error msg */
-               maj_stat = GSS_S_BAD_NAME; /* XXX ? */
-               gss_release_name(&ignore_min_stat, &client_name);
-@@ -377,10 +501,8 @@
-       }
-       gss_release_name(&ignore_min_stat, &client_name);
++      /* 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();
+-      /* Determine Kerberos information from the kernel */
+-      gssd_obtain_kernel_krb5_info();
 -
-       /* 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,7 +526,6 @@
-               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;
+-      gssd_run();
++      lgssd_run();
+       printerr(0, "gssd_run returned!\n");
+       abort();
+ }
+--- nfs-utils-1.0.10/utils/gssd/cacheio.c.lustre       2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/cacheio.c      2006-10-13 16:03:33.000000000 -0600
+@@ -227,7 +227,8 @@
+               return -1;
+       while (*bp == ' ') bp++;
+       *bpp = bp;
+-      *dest = '\0';
++// why should we clear *dest???
++//    *dest = '\0';
+       return len;
+ }
  
- out_err:
---- nfs-utils-1.0.10/utils/gssd/lsupport.c.lustre      2006-08-14 10:32:30.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/lsupport.c     2006-08-14 10:32:30.000000000 -0600
-@@ -0,0 +1,604 @@
+--- nfs-utils-1.0.10/utils/gssd/lsupport.c.lustre      2006-10-13 16:03:33.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/lsupport.c     2006-10-13 17:40:51.000000000 -0600
+@@ -0,0 +1,774 @@
 +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
 + * vim:expandtab:shiftwidth=8:tabstop=8:
 + *
 +#include <signal.h>
 +#include <unistd.h>
 +#include <errno.h>
-+#include <netdb.h>
 +#include <assert.h>
++#ifdef HAVE_GETHOSTBYNAME
++# include <netdb.h>
++#endif
 +
 +#include "err_util.h"
 +#include "gssd.h"
 +
 +/****************************************
 + * client side resolvation:             *
-+ *    nal/netid/nid => hostname         *
++ *    lnd/netid/nid => hostname         *
 + ****************************************/
 +
 +char gethostname_ex[PATH_MAX] = GSSD_DEFAULT_GETHOSTNAME_EX;
 +
-+typedef int ptl_nid2hostname_t(char *nal, uint32_t net, uint32_t addr,
++typedef int lnd_nid2hostname_t(char *lnd, uint32_t net, uint32_t addr,
 +                               char *buf, int buflen);
 +
 +/* FIXME what about IPv6? */
 +static
-+int socknal_nid2hostname(char *nal, uint32_t net, uint32_t addr,
++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", nal, addr);
++                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", nal, ent->h_name);
++                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",
-+                 nal, net, addr, buf);
++                 lnd, net, addr, buf);
 +        return 0;
 +}
 +
 +static
-+int lonal_nid2hostname(char *nal, uint32_t net, uint32_t addr,
++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", nal, 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", nal);
++                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",
-+                         nal, uts.nodename);
++                         lnd, uts.nodename);
 +                return -1;
 +        }
 +
 +        if (strlen(ent->h_name) >= buflen) {
-+                printerr(0, "%s: name too long: %s\n", nal, ent->h_name);
++                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", nal, addr, buf);
++        printerr(2, "%s: addr 0x%x => %s\n", lnd, addr, buf);
 +        return 0;
 +}
 +
 +}
 +
 +static
-+int external_nid2hostname(char *nal, uint32_t net, uint32_t addr,
-+                           char *namebuf, int namebuflen)
++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, nal, net, addr);
++        sprintf(buf, "%s %s 0x%x 0x%x", gethostname_ex, lnd, net, addr);
 +        printerr(2, "cmd: %s\n", buf);
 +
 +        fghn = popen(buf, "r");
 +
 +        head = fgets(buf, bufsize, fghn);
 +        if (head == NULL) {
-+                printerr(0, "can't read\n");
++                printerr(0, "can't read from %s\n", gethostname_ex);
 +                return -1;
 +        }
 +        if (pclose(fghn) == -1)
 +
 +        tail = head + strlen(head);
 +        if (tail <= head) {
-+                printerr(0, "no output\n");
++                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\n");
++                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, "%s\n", &head[1]);
++                printerr(0, "error from %s: %s\n", gethostname_ex, &head[1]);
 +                return -1;
 +        }
 +
 +        if (tail - head > namebuflen) {
-+                printerr(0, "hostname too long: %s\n", head);
++                printerr(0, "external hostname too long: %s\n", head);
 +                return -1;
 +        }
 +
 +        printerr(2, "%s: net 0x%x, addr 0x%x => %s\n",
-+                 nal, net, addr, head);
++                 lnd, net, addr, head);
 +        strcpy(namebuf, head);
 +        return 0;
 +}
 +
-+enum {
-+        QSWNAL    = 1,
-+        SOCKNAL   = 2,
-+        GMNAL     = 3,
-+        /*          4 unused */
-+        TCPNAL    = 5,
-+        ROUTER    = 6,
-+        OPENIBNAL = 7,
-+        IIBNAL    = 8,
-+        LONAL     = 9,
-+        RANAL     = 10,
-+        VIBNAL    = 11,
-+        NAL_ENUM_END_MARKER
-+};
-+
 +static struct {
 +        char                    *name;
-+        ptl_nid2hostname_t      *nid2name;
-+} converter[NAL_ENUM_END_MARKER] = {
++        lnd_nid2hostname_t      *nid2name;
++} converter[LND_ENUM_END_MARKER] = {
 +        {"UNUSED0",     NULL},
-+        {"QSWNAL",      external_nid2hostname},
-+        {"SOCKNAL",     socknal_nid2hostname},
-+        {"GMNAL",       external_nid2hostname},
-+        {"UNUSED4",     NULL},
-+        {"TCPNAL",      NULL},
-+        {"ROUTER",      NULL},
-+        {"OPENIBNAL",   external_nid2hostname},
-+        {"IIBNAL",      external_nid2hostname},
-+        {"LONAL",       lonal_nid2hostname},
-+        {"RANAL",       NULL},
-+        {"VIBNAL",      external_nid2hostname},
++        [QSWLND]        = { "QSWLND",   external_nid2hostname},
++        [SOCKLND]       = { "SOCKLND",  socklnd_nid2hostname},
++        [GMLND]         = { "GMLND",    external_nid2hostname},
++        [PTLLND]        = { "PTLLND",   external_nid2hostname },
++        [O2IBLND]       = { "O2IBLND",  external_nid2hostname },
++        [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 ptl_nid2hostname(uint64_t nid, char *buf, int buflen)
++int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen)
 +{
-+        uint32_t nal, net, addr;
++        uint32_t lnd, net, addr;
 +
 +        addr = LNET_NIDADDR(nid);
 +        net = LNET_NIDNET(nid);
-+        nal = LNET_NETTYP(net);
++        lnd = LNET_NETTYP(net);
 +
-+        if (nal >= NAL_ENUM_END_MARKER) {
-+                printerr(0, "ERROR: Unrecognized NAL %u\n", nal);
++        if (lnd >= LND_ENUM_END_MARKER) {
++                printerr(0, "ERROR: Unrecognized LND %u\n", lnd);
 +                return -1;
 +        }
 +
-+        if (converter[nal].nid2name == NULL) {
-+                printerr(0, "ERROR: NAL %s converter not ready\n",
-+                        converter[nal].name);
++        if (converter[lnd].nid2name == NULL) {
++                printerr(0, "ERROR: %s converter not ready\n",
++                        converter[lnd].name);
 +                return -1;
 +        }
 +
-+        return converter[nal].nid2name(converter[nal].name, net, addr,
++        return converter[lnd].nid2name(converter[lnd].name, net, addr,
 +                                       buf, buflen);
 +}
 +
 +
 +/****************************************
-+ * portals support routine              *
++ * lnet support routine                 *
++ * (from lnet/libcfs/nidstrings.c       *
 + ****************************************/
 +
-+static struct hostent *
-+ptl_gethostbyname(char * hname) {
-+        struct hostent *he;
-+
-+        he = gethostbyname(hname);
-+        if (!he) {
-+                switch(h_errno) {
-+                case HOST_NOT_FOUND:
-+                case NO_ADDRESS:
-+                        printerr(0, "Unable to resolve hostname: %s\n",
-+                                 hname);
-+                        break;
-+                default:
-+                        printerr(0, "gethostbyname %s: %s\n",
-+                                 hname, strerror(h_errno));
-+                        break;
-+                }
-+                return NULL;
-+        }
-+        return he;
++#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;
 +}
 +
-+int
-+ptl_parse_ipquad (uint32_t *ipaddrp, char *str)
++static void
++libcfs_ip_addr2str(uint32_t addr, char *str)
 +{
-+        int             a;
-+        int             b;
-+        int             c;
-+        int             d;
++        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 :) */
 +
-+        if (sscanf(str, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 &&
++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)
-+        {
-+                *ipaddrp = (a<<24)|(b<<16)|(c<<8)|d;
-+                return (0);
++            (c & ~0xff) == 0 && (d & ~0xff) == 0) {
++                *addr = ((a<<24)|(b<<16)|(c<<8)|d);
++                return 1;
 +        }
 +
-+        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;
 +}
 +
-+int
-+ptl_parse_ipaddr (uint32_t *ipaddrp, char *str)
++static void
++libcfs_decnum_addr2str(uint32_t addr, char *str)
 +{
-+        struct hostent *he;
++        snprintf(str, LNET_NIDSTR_SIZE, "%u", addr);
++}
 +
-+        if (!strcmp (str, "_all_")) {
-+                *ipaddrp = 0;
-+                return (0);
-+        }
++static void
++libcfs_hexnum_addr2str(uint32_t addr, char *str)
++{
++        snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr);
++}
 +
-+        if (ptl_parse_ipquad(ipaddrp, str) == 0)
-+                return (0);
++static int
++libcfs_num_str2addr(char *str, int nob, uint32_t *addr)
++{
++        int     n;
 +
-+        if ((('a' <= str[0] && str[0] <= 'z') ||
-+             ('A' <= str[0] && str[0] <= 'Z')) &&
-+             (he = ptl_gethostbyname (str)) != NULL) {
-+                uint32_t addr = *(uint32_t *)he->h_addr;
++        n = nob;
++        if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
++                return 1;
 +
-+                *ipaddrp = ntohl(addr);         /* HOST byte order */
-+                return (0);
-+        }
++        n = nob;
++        if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
++                return 1;
 +
-+        return (-1);
++        n = nob;
++        if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
++                return 1;
++        
++        return 0;
 +}
 +
-+int
-+ptl_parse_nid (ptl_nid_t *nidp, char *str)
++static struct netstrfns *
++libcfs_lnd2netstrfns(int lnd)
 +{
-+        uint32_t            ipaddr;
-+        char               *end;
-+        unsigned long long  ullval;
++        int    i;
 +
-+        if (ptl_parse_ipaddr (&ipaddr, str) == 0) {
-+#if !CRAY_PORTALS
-+                *nidp = (ptl_nid_t)ipaddr;
-+#else
-+                *nidp = (((ptl_nid_t)ipaddr & PNAL_HOSTID_MASK) << PNAL_VNODE_SHIFT);
-+#endif
-+                return (0);
++        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;
 +        }
 +
-+        ullval = strtoull(str, &end, 0);
-+        if (end != str && *end == 0) {
-+                /* parsed whole non-empty string */
-+                *nidp = (ptl_nid_t)ullval;
-+                return (0);
++        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;
 +        }
 +
-+        return (-1);
++        *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       *
 +
 +struct user_map_item {
 +        char        *principal; /* NULL means match all */
-+        ptl_netid_t  netid;
-+        ptl_nid_t    nid;
++        lnet_nid_t   nid;
 +        uid_t        uid;
 +};
 +
 +
 +static struct user_mapping mapping = {0, 0, NULL};
 +/* FIXME to be finished: monitor change of mapping database */
-+static int mapping_changed = 1;
++static int mapping_mtime = 0;
 +
 +static
 +void cleanup_mapping(void)
 +        int n;
 +
 +        for (n = 0; n < mapping.nitems; n++) {
-+                assert(mapping.items[n].principal);
-+                free(mapping.items[n].principal);
++                if (mapping.items[n].principal)
++                        free(mapping.items[n].principal);
 +        }
 +        mapping.nitems = 0;
 +}
 +        char princ[MAX_LINE_LEN];
 +        char nid_str[MAX_LINE_LEN];
 +        char dest[MAX_LINE_LEN];
-+        ptl_nid_t ptl_nid;
++        lnet_nid_t nid;
 +        uid_t dest_uid;
 +        FILE *f;
 +        char *line, linebuf[MAX_LINE_LEN];
 +                                return -1;
 +                        }
 +                }
-+                if (ptl_parse_nid(&ptl_nid, nid_str)) {
-+                        printerr(0, "fail to parse nid %s\n", nid_str);
-+                        fclose(f);
-+                        return -1;
++                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);
++                                fclose(f);
++                                return -1;
++                        }
 +                }
 +                dest_uid = parse_uid(dest);
 +                if (dest_uid == -1) {
 +                }
 +
 +                mapping.items[mapping.nitems].principal = name;
-+                mapping.items[mapping.nitems].netid = 0;
-+                mapping.items[mapping.nitems].nid = ptl_nid;
++                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 ? name : "*", nid_str, ptl_nid, dest_uid);
++                         name ? name : "*", nid_str, nid, dest_uid);
++        }
++
++        return 0;
++}
++
++static inline int mapping_changed(void)
++{
++        struct stat st;
++
++        if (stat(MAPPING_DATABASE_FILE, &st) == -1) {
++                printerr(0, "stat %s failed\n");
++                return 1;
++        }
++
++        if (st.st_mtime != mapping_mtime) {
++                mapping_mtime = st.st_mtime;
++                return 1;
 +        }
 +
 +        return 0;
 +}
 +
-+int lookup_mapping(char *princ, uint32_t nal, ptl_netid_t netid,
-+                   ptl_nid_t nid, uid_t *uid)
++int lookup_mapping(char *princ, lnet_nid_t nid, uid_t *uid)
 +{
 +        int n;
 +
 +        /* FIXME race condition here */
-+        if (mapping_changed) {
++        if (mapping_changed()) {
 +                if (read_mapping_db())
 +                        printerr(0, "all remote users will be denied\n");
-+                mapping_changed = 0;
 +        }
 +
 +        for (n = 0; n < mapping.nitems; n++) {
 +                struct user_map_item *entry = &mapping.items[n];
 +
-+                if (entry->netid != netid || entry->nid != nid)
++                if (entry->nid != LNET_NID_ANY && entry->nid != nid)
 +                        continue;
 +                if (!entry->principal ||
 +                    !strcasecmp(entry->principal, princ)) {
 +                        return 0;
 +                }
 +        }
-+        printerr(1, "no mapping for %s\n", princ);
++        printerr(1, "no mapping for %s/%#Lx\n", princ, nid);
 +        *uid = -1;
 +        return -1;
 +}
 +
---- nfs-utils-1.0.10/utils/gssd/lsupport.h.lustre      2006-08-14 10:32:30.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/lsupport.h     2006-08-14 10:32:30.000000000 -0600
-@@ -0,0 +1,68 @@
-+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
-+ * vim:expandtab:shiftwidth=8:tabstop=8:
-+ */
-+
-+#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
-+ */
-+
-+typedef uint64_t ptl_nid_t;
-+typedef uint32_t ptl_netid_t;
-+
-+#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)
+--- nfs-utils-1.0.10/utils/gssd/err_util.h.lustre      2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/err_util.h     2006-10-13 16:03:33.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_ */
+--- nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c.lustre     2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c    2006-10-13 16:03:33.000000000 -0600
+@@ -47,31 +47,31 @@
+ #include "err_util.h"
+ void
+-gssd_run()
++svcgssd_run()
+ {
+       int                     ret;
+       FILE                    *f;
+       struct pollfd           pollfd;
+-#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 = fopen(NULLRPC_FILE, "rw")) == NULL) {
++                      printerr(3, "failed to open %s: %s\n",
++                               NULLRPC_FILE, strerror(errno));
++                      sleep(1);
++              }
++              pollfd.fd = fileno(f);
++              pollfd.events = POLLIN;
 +
-+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  */
-+};
+               pollfd.revents = 0;
+-              printerr(1, "entering poll\n");
+-              ret = poll(&pollfd, 1, -1);
++              printerr(3, "entering poll\n");
++              ret = poll(&pollfd, 1, 1000);
+               save_err = errno;
+-              printerr(1, "leaving poll\n");
++              printerr(3, "leaving poll\n");
 +
-+#define GSSD_DEFAULT_GETHOSTNAME_EX     "/etc/lustre/nid2hostname"
-+#define MAPPING_DATABASE_FILE           "/etc/lustre/idmap.conf"
+               if (ret < 0) {
+                       if (save_err != EINTR)
+                               printerr(0, "error return from poll: %s\n",
+@@ -87,5 +87,6 @@
+                       if (pollfd.revents & POLLIN)
+                               handle_nullreq(f);
+               }
++              fclose(f);
+       }
+ }
+--- nfs-utils-1.0.10/utils/gssd/Makefile.am.lustre     2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/Makefile.am    2006-10-13 16:03:33.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 \
+@@ -20,13 +14,15 @@
+       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 \
+@@ -37,13 +33,12 @@
+       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 \
+@@ -54,20 +49,11 @@
+       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
+@@ -91,23 +77,3 @@
+         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)
+-
+--- nfs-utils-1.0.10/utils/gssd/gssd.h.lustre  2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/gssd.h 2006-10-13 16:03:33.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
 +
-+int ptl_nid2hostname(uint64_t nid, char *buf, int buflen);
-+int lookup_mapping(char *princ, uint32_t nal, ptl_netid_t netid,
-+                   ptl_nid_t nid, uid_t *uid);
++#define LUSTRE_ROOT_NAME                      "lustre_root"
++#define LUSTRE_ROOT_NAMELEN                   11
+ /*
+  * The gss mechanisms that we can handle
+@@ -61,6 +66,7 @@
+ extern char                   pipefsdir[PATH_MAX];
+ extern char                   keytabfile[PATH_MAX];
+ extern char                   ccachedir[PATH_MAX];
++extern char                   gethostname_ex[PATH_MAX];
+ TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list;
+@@ -69,10 +75,6 @@
+       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;
+@@ -83,8 +85,7 @@
+ 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);
+ #endif /* _RPC_GSSD_H_ */
+--- nfs-utils-1.0.10/utils/gssd/svcgssd.h.lustre       2006-08-07 00:40:50.000000000 -0600
++++ nfs-utils-1.0.10/utils/gssd/svcgssd.h      2006-10-13 16:03:33.000000000 -0600
+@@ -36,8 +36,19 @@
+ #include <gssapi/gssapi.h>
+ void handle_nullreq(FILE *f);
+-void gssd_run(void);
++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;
 +
-+/* 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)))
++#define GSSD_SERVICE_NAME     "lustre"
 +
-+#endif /* __LIBCFS_H__ */
---- nfs-utils-1.0.10/utils/gssd/cacheio.c.lustre       2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/cacheio.c      2006-08-14 10:32:30.000000000 -0600
-@@ -227,7 +227,8 @@
-               return -1;
-       while (*bp == ' ') bp++;
-       *bpp = bp;
--      *dest = '\0';
-+// why should we clear *dest???
-+//    *dest = '\0';
-       return len;
- }
++/* 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_ */
 --- nfs-utils-1.0.10/utils/Makefile.am.lustre  2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/Makefile.am 2006-08-14 10:32:30.000000000 -0600
++++ nfs-utils-1.0.10/utils/Makefile.am 2006-10-13 16:03:33.000000000 -0600
 @@ -2,31 +2,6 @@
  
  OPTDIRS =
  
  MAINTAINERCLEANFILES = Makefile.in
 --- nfs-utils-1.0.10/configure.in.lustre       2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/configure.in      2006-08-14 10:32:30.000000000 -0600
++++ nfs-utils-1.0.10/configure.in      2006-10-13 16:03:33.000000000 -0600
 @@ -17,61 +17,14 @@
        RELEASE=$withval,
        RELEASE=1)
  AC_OUTPUT
  
 --- nfs-utils-1.0.10/Makefile.am.lustre        2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/Makefile.am       2006-08-14 10:32:30.000000000 -0600
++++ nfs-utils-1.0.10/Makefile.am       2006-10-13 16:03:33.000000000 -0600
 @@ -1,6 +1,6 @@
  ## Process this file with automake to produce Makefile.in
  
index e799f82..3b17dca 100644 (file)
@@ -296,7 +296,7 @@ print_hexl(int pri, unsigned char *cp, int length)
 
 static int
 get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
-       ptl_nid_t ptl_nid)
+       lnet_nid_t nid)
 {
        u_int32_t       maj_stat, min_stat;
        gss_buffer_desc name;
@@ -324,11 +324,7 @@ get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
        printerr(1, "authenticate user %s\n", sname);
        gss_release_buffer(&min_stat, &name);
 
-#if 0
-       lookup_mapping(sname, ptl_nal, ptl_netid, ptl_nid, &cred->cr_mapped_uid);
-#else
-       cred->cr_mapped_uid = -1;
-#endif
+       lookup_mapping(sname, nid, &cred->cr_mapped_uid);
 
         realm = strchr(sname, '@');
         if (!realm) {
@@ -412,7 +408,7 @@ handle_nullreq(FILE *f) {
        /* XXX isn't there a define for this?: */
                                null_token = {.value = NULL};
        uint32_t                lustre_svc;
-       uint64_t                ptl_nid;
+       lnet_nid_t              nid;
        u_int32_t               ret_flags;
        gss_ctx_id_t            ctx = GSS_C_NO_CONTEXT;
        gss_name_t              client_name;
@@ -436,10 +432,10 @@ handle_nullreq(FILE *f) {
        cp = lbuf;
 
        qword_get(&cp, (char *) &lustre_svc, sizeof(lustre_svc));
-       qword_get(&cp, (char *) &ptl_nid, sizeof(ptl_nid));
+       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, ptl_nid, handle_seq);
+                lustre_svc, nid, handle_seq);
 
        in_handle.length = (size_t) qword_get(&cp, in_handle.value,
                                              sizeof(in_handle_buf));
@@ -493,7 +489,7 @@ handle_nullreq(FILE *f) {
                        maj_stat, min_stat, mech);
                goto out_err;
        }
-       if (get_ids(client_name, mech, &cred, ptl_nid)) {
+       if (get_ids(client_name, mech, &cred, nid)) {
                /* get_ids() prints error msg */
                maj_stat = GSS_S_BAD_NAME; /* XXX ? */
                gss_release_name(&ignore_min_stat, &client_name);