Whamcloud - gitweb
branch: HEAD
[fs/lustre-release.git] / lustre / utils / gss / nfs-utils-1.0.11-lustre.diff
1 diff -Nrup nfs-utils-1.0.11/configure.in nfs-utils-1.0.11.lustre/configure.in
2 --- nfs-utils-1.0.11/configure.in       2007-02-21 21:50:03.000000000 -0700
3 +++ nfs-utils-1.0.11.lustre/configure.in        2007-06-29 12:29:20.000000000 -0600
4 @@ -18,61 +18,14 @@ AC_ARG_WITH(release,
5         RELEASE=$withval,
6         RELEASE=1)
7         AC_SUBST(RELEASE)
8 -AC_ARG_WITH(statedir,
9 -       [  --with-statedir=/foo    use state dir /foo [/var/lib/nfs]],
10 -       statedir=$withval,
11 -       statedir=/var/lib/nfs)
12 -       AC_SUBST(statedir)
13 -AC_ARG_WITH(statduser,
14 -       [AC_HELP_STRING([--with-statduser=rpcuser],
15 -                        [statd to run under @<:@rpcuser or nobody@:>@]
16 -       )],
17 -       statduser=$withval,
18 -       if test "x$cross_compiling" = "xno"; then
19 -               if grep -s '^rpcuser:' /etc/passwd > /dev/null; then
20 -                       statduser=rpcuser
21 -               else
22 -                       statduser=nobody
23 -               fi
24 -       else
25 -               statduser=nobody
26 -       fi)
27 -       AC_SUBST(statduser)
28 -AC_ARG_ENABLE(nfsv3,
29 -       [AC_HELP_STRING([--enable-nfsv3],
30 -                        [enable support for NFSv3 @<:@default=yes@:>@])],
31 -       enable_nfsv3=$enableval,
32 -       enable_nfsv3=yes)
33 -       if test "$enable_nfsv3" = yes; then
34 -               AC_DEFINE(NFS3_SUPPORTED, 1, [Define this if you want NFSv3 support compiled in])
35 -       else
36 -               enable_nfsv3=
37 -       fi
38 -       AC_SUBST(enable_nfsv3)
39 -AC_ARG_ENABLE(nfsv4,
40 -       [AC_HELP_STRING([--enable-nfsv4],
41 -                        [enable support for NFSv4 @<:@default=yes@:>@])],
42 -       enable_nfsv4=$enableval,
43 -       enable_nfsv4=yes)
44 -       if test "$enable_nfsv4" = yes; then
45 -               AC_DEFINE(NFS4_SUPPORTED, 1, [Define this if you want NFSv4 support compiled in])
46 -               IDMAPD=idmapd
47 -       else
48 -               enable_nfsv4=
49 -               IDMAPD=
50 -       fi
51 -       AC_SUBST(IDMAPD)
52 -       AC_SUBST(enable_nfsv4)
53 -       AM_CONDITIONAL(CONFIG_NFSV4, [test "$enable_nfsv4" = "yes"])
54  AC_ARG_ENABLE(gss,
55         [AC_HELP_STRING([--enable-gss],
56                          [enable support for rpcsec_gss @<:@default=yes@:>@])],
57         enable_gss=$enableval,
58         enable_gss=yes)
59         if test "$enable_gss" = yes; then
60 -               AC_DEFINE(GSS_SUPPORTED, 1, [Define this if you want rpcsec_gss support compiled in])
61 -               GSSD=gssd
62 -               SVCGSSD=svcgssd
63 +               GSSD=lgssd
64 +               SVCGSSD=lsvcgssd
65         else
66                 enable_gss=
67                 GSSD=
68 @@ -82,38 +35,6 @@ AC_ARG_ENABLE(gss,
69         AC_SUBST(SVCGSSD)
70         AC_SUBST(enable_gss)
71         AM_CONDITIONAL(CONFIG_GSS, [test "$enable_gss" = "yes"])
72 -AC_ARG_ENABLE(kprefix,
73 -       [AC_HELP_STRING([--enable-kprefix], [install progs as rpc.knfsd etc])],
74 -       test "$enableval" = "yes" && kprefix=k,
75 -       kprefix=)
76 -       AC_SUBST(kprefix)
77 -AC_ARG_ENABLE(secure-statd,
78 -       [AC_HELP_STRING([--enable-secure-statd],
79 -                        [Only lockd can use statd (security)])],
80 -       test "$enableval" = "yes" && secure_statd=yes,
81 -       secure_statd=no)
82 -       if test "$secure_statd" = yes; then
83 -               AC_DEFINE(RESTRICTED_STATD, 1, [Define this if you want to enable various security checks in statd. These checks basically keep anyone but lockd from using this service.])
84 -       fi
85 -       AC_SUBST(secure_statd)
86 -AC_ARG_ENABLE(rquotad,
87 -       [AC_HELP_STRING([--enable-rquotad],
88 -                        [enable rquotad @<:@default=yes@:>@])],
89 -       enable_rquotad=$enableval,
90 -       enable_rquotad=yes)
91 -       if test "$enable_rquotad" = yes; then
92 -               RQUOTAD=rquotad
93 -       else
94 -               RQUOTAD=
95 -       fi
96 -       AM_CONDITIONAL(CONFIG_RQUOTAD, [test "$enable_rquotad" = "yes"])
97 -
98 -AC_ARG_ENABLE(mount,
99 -       [AC_HELP_STRING([--enable-mount],
100 -                       [Create mount.nfs and don't use the util-linux mount(8) functionality. @<:@default=no@:>@])],
101 -       enable_mount=$enableval,
102 -       enable_mount=no)
103 -       AM_CONDITIONAL(CONFIG_MOUNT, [test "$enable_mount" = "yes"])
104  
105  # Check whether user wants TCP wrappers support
106  AC_TCP_WRAPPERS
107 @@ -156,50 +77,15 @@ AC_CHECK_FUNC(connect, ,
108                  AC_MSG_ERROR(Function 'socket' not found.), $LIBNSL))
109  
110  AC_CHECK_LIB(crypt, crypt, [LIBCRYPT="-lcrypt"])
111 -if test "$enable_nfsv4" = yes; then
112 -    AC_CHECK_LIB(event, event_dispatch, [libevent=1], AC_MSG_ERROR([libevent needed for nfsv4 support]))
113 -    AC_CHECK_LIB(nfsidmap, nfs4_init_name_mapping, [libnfsidmap=1], AC_MSG_ERROR([libnfsidmap needed for nfsv4 support]))
114 -    AC_CHECK_HEADERS(event.h, ,AC_MSG_ERROR([libevent needed for nfsv4 support]))
115 -    AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for nfsv4 support]))
116 -    dnl librpcsecgss already has a dependency on libgssapi,
117 -    dnl but we need to make sure we get the right version
118 -    if test "$enable_gss" = yes; then
119 -     PKG_CHECK_MODULES(RPCSECGSS, librpcsecgss >= 0.10, ,
120 -      [AC_MSG_ERROR([Unable to locate information required to use librpcsecgss.  If you have pkgconfig installed, you might try setting environment variable PKG_CONFIG_PATH to /usr/local/lib/pkgconfig])
121 -      ]
122 -     )
123 -    PKG_CHECK_MODULES(GSSAPI, libgssapi >= 0.9)
124 -    fi
125 -
126 -fi
127 -if test "$knfsd_cv_glibc2" = no; then
128 -    AC_CHECK_LIB(bsd, daemon, [LIBBSD="-lbsd"])
129 -fi
130 -AC_CHECK_LIB(blkid, blkid_get_cache, [LIBBLKID="-lblkid"], AC_MSG_ERROR([libblkid needed]))
131 -AC_CHECK_HEADER(blkid/blkid.h, , AC_MSG_ERROR([Cannot file libblkid header file blkid/blkid.h]))
132 +PKG_CHECK_MODULES(GSSAPI, libgssapi >= 0.9)
133  AC_SUBST(LIBSOCKET)
134  AC_SUBST(LIBCRYPT)
135  AC_SUBST(LIBBSD)
136  AC_SUBST(LIBBLKID)
137  
138  if test "$enable_gss" = yes; then
139 -  dnl 'gss' also depends on nfsidmap.h - at least for svcgssd_proc.c
140 -  AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for gss support]))
141 -  AC_CHECK_HEADERS(spkm3.h, ,AC_MSG_WARN([could not locate SPKM3 header; will not have SPKM3 support]))
142 -  dnl the nfs4_set_debug function doesn't appear in all version of the library
143 -  AC_CHECK_LIB(nfsidmap, nfs4_set_debug,
144 -              AC_DEFINE(HAVE_NFS4_SET_DEBUG,1,
145 -                        [Whether nfs4_set_debug() is present in libnfsidmap]),)
146 -
147    dnl Check for Kerberos V5
148    AC_KERBEROS_V5
149 -
150 -  dnl This is not done until here because we need to have KRBLIBS set
151 -  dnl ("librpcsecgss=1" is so that it doesn't get added to LIBS)
152 -  AC_CHECK_LIB(rpcsecgss, authgss_create_default, [librpcsecgss=1], AC_MSG_ERROR([librpcsecgss needed for nfsv4 support]), -lgssapi -ldl)
153 -  AC_CHECK_LIB(rpcsecgss, authgss_set_debug_level,
154 -              AC_DEFINE(HAVE_AUTHGSS_SET_DEBUG_LEVEL, 1, [Define this if the rpcsec_gss library has the function authgss_set_debug_level]),, -lgssapi -ldl)
155 -
156  fi
157  
158  dnl *************************************************************
159 @@ -311,33 +197,7 @@ AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_mac
160  
161  AC_CONFIG_FILES([
162         Makefile
163 -       linux-nfs/Makefile
164 -       support/Makefile
165 -       support/export/Makefile
166 -       support/include/nfs/Makefile
167 -       support/include/rpcsvc/Makefile
168 -       support/include/sys/fs/Makefile
169 -       support/include/sys/Makefile
170 -       support/include/Makefile
171 -       support/misc/Makefile
172 -       support/nfs/Makefile
173 -       tools/Makefile
174 -       tools/getiversion/Makefile
175 -       tools/locktest/Makefile
176 -       tools/nlmtest/Makefile
177 -       tools/rpcdebug/Makefile
178 -       tools/rpcgen/Makefile
179         utils/Makefile
180 -       utils/exportfs/Makefile
181 -       utils/gssd/Makefile
182 -       utils/idmapd/Makefile
183 -       utils/lockd/Makefile
184 -       utils/mount/Makefile
185 -       utils/mountd/Makefile
186 -       utils/nfsd/Makefile
187 -       utils/nfsstat/Makefile
188 -       utils/rquotad/Makefile
189 -       utils/showmount/Makefile
190 -       utils/statd/Makefile])
191 +       utils/gssd/Makefile])
192  AC_OUTPUT
193  
194 diff -Nrup nfs-utils-1.0.11/Makefile.am nfs-utils-1.0.11.lustre/Makefile.am
195 --- nfs-utils-1.0.11/Makefile.am        2007-02-21 21:50:03.000000000 -0700
196 +++ nfs-utils-1.0.11.lustre/Makefile.am 2007-06-29 12:29:20.000000000 -0600
197 @@ -1,6 +1,6 @@
198  ## Process this file with automake to produce Makefile.in
199  
200 -SUBDIRS = tools support utils linux-nfs
201 +SUBDIRS = utils
202  
203  MAINTAINERCLEANFILES = Makefile.in
204  
205 diff -Nrup nfs-utils-1.0.11/utils/gssd/cacheio.c nfs-utils-1.0.11.lustre/utils/gssd/cacheio.c
206 --- nfs-utils-1.0.11/utils/gssd/cacheio.c       2007-02-21 21:50:03.000000000 -0700
207 +++ nfs-utils-1.0.11.lustre/utils/gssd/cacheio.c        2007-06-29 12:32:27.000000000 -0600
208 @@ -240,7 +240,8 @@ int qword_get(char **bpp, char *dest, in
209                 return -1;
210         while (*bp == ' ') bp++;
211         *bpp = bp;
212 -       *dest = '\0';
213 +// why should we clear *dest???
214 +//     *dest = '\0';
215         return len;
216  }
217  
218 diff -Nrup nfs-utils-1.0.11/utils/gssd/context.c nfs-utils-1.0.11.lustre/utils/gssd/context.c
219 --- nfs-utils-1.0.11/utils/gssd/context.c       2007-02-21 21:50:03.000000000 -0700
220 +++ nfs-utils-1.0.11.lustre/utils/gssd/context.c        2007-06-29 12:32:28.000000000 -0600
221 @@ -33,11 +33,14 @@
222  #include <syslog.h>
223  #include <string.h>
224  #include <gssapi/gssapi.h>
225 -#include <rpc/rpc.h>
226 -#include <rpc/auth_gss.h>
227 -#include "gss_util.h"
228 -#include "gss_oids.h"
229 -#include "err_util.h"
230 +
231 +#ifdef _NEW_BUILD_
232 +# include "lgss_utils.h"
233 +#else
234 +# include "gss_util.h"
235 +# include "gss_oids.h"
236 +# include "err_util.h"
237 +#endif
238  #include "context.h"
239  
240  int
241 diff -Nrup nfs-utils-1.0.11/utils/gssd/context.h nfs-utils-1.0.11.lustre/utils/gssd/context.h
242 --- nfs-utils-1.0.11/utils/gssd/context.h       2007-06-29 12:28:01.000000000 -0600
243 +++ nfs-utils-1.0.11.lustre/utils/gssd/context.h        2007-06-29 12:32:29.000000000 -0600
244 @@ -31,8 +31,6 @@
245  #ifndef _CONTEXT_H_
246  #define _CONTEXT_H_
247  
248 -#include <rpc/rpc.h>
249 -
250  /* Hopefully big enough to hold any serialized context */
251  #define MAX_CTX_LEN 4096
252  
253 diff -Nrup nfs-utils-1.0.11/utils/gssd/context_heimdal.c nfs-utils-1.0.11.lustre/utils/gssd/context_heimdal.c
254 --- nfs-utils-1.0.11/utils/gssd/context_heimdal.c       2007-02-21 21:50:03.000000000 -0700
255 +++ nfs-utils-1.0.11.lustre/utils/gssd/context_heimdal.c        2007-06-29 12:32:29.000000000 -0600
256 @@ -43,8 +43,13 @@
257  #ifdef HAVE_COM_ERR_H
258  #include <com_err.h>
259  #endif
260 -#include "err_util.h"
261 -#include "gss_oids.h"
262 +
263 +#ifdef _NEW_BUILD_
264 +# include "lgss_utils.h"
265 +#else
266 +# include "err_util.h"
267 +# include "gss_oids.h"
268 +#endif
269  #include "write_bytes.h"
270  
271  int write_heimdal_keyblock(char **p, char *end, krb5_keyblock *key)
272 diff -Nrup nfs-utils-1.0.11/utils/gssd/context_lucid.c nfs-utils-1.0.11.lustre/utils/gssd/context_lucid.c
273 --- nfs-utils-1.0.11/utils/gssd/context_lucid.c 2007-06-29 12:28:01.000000000 -0600
274 +++ nfs-utils-1.0.11.lustre/utils/gssd/context_lucid.c  2007-06-29 12:32:30.000000000 -0600
275 @@ -41,11 +41,7 @@
276  #include <syslog.h>
277  #include <string.h>
278  #include <errno.h>
279 -#include "gss_util.h"
280 -#include "gss_oids.h"
281 -#include "err_util.h"
282 -#include "context.h"
283 -
284 +#include <stdint.h>
285  #include <krb5.h>
286  #include <gssapi/gssapi.h>
287  #ifndef OM_uint64
288 @@ -53,6 +49,16 @@ typedef uint64_t OM_uint64;
289  #endif
290  #include <gssapi/gssapi_krb5.h>
291  
292 +#ifdef _NEW_BUILD_
293 +# include "lgss_utils.h"
294 +#else
295 +# include "gss_util.h"
296 +# include "gss_oids.h"
297 +# include "err_util.h"
298 +#endif
299 +#include "write_bytes.h"
300 +#include "context.h"
301 +
302  static int
303  write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key)
304  {
305 @@ -354,6 +360,7 @@ static int
306  prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
307                             gss_buffer_desc *buf)
308  {
309 +       static int constant_two = 2;
310         char *p, *end;
311         uint32_t v2_flags = 0;
312         gss_krb5_lucid_key_t enc_key;
313 @@ -372,7 +379,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
314         end = buf->value + MAX_CTX_LEN;
315  
316         /* Version 2 */
317 -       if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err;
318 +       if (WRITE_BYTES(&p, end, constant_two)) goto out_err;
319         if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
320  
321         if (lctx->initiate)
322 @@ -387,7 +394,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
323         if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
324  
325         /* Protocol 0 here implies DES3 or RC4 */
326 -       printerr(2, "%s: protocol %d\n", __FUNCTION__, lctx->protocol);
327 +       printerr(3, "protocol %d\n", lctx->protocol);
328         if (lctx->protocol == 0) {
329                 enctype = lctx->rfc1964_kd.ctx_key.type;
330  #ifdef HAVE_HEIMDAL
331 @@ -415,8 +422,8 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
332                 }
333                 numkeys = 3;
334         }
335 -       printerr(2, "%s: serializing %d keys with enctype %d and size %d\n",
336 -                __FUNCTION__, numkeys, enctype, keysize);
337 +       printerr(3, "serializing %d keys with enctype %d and size %d\n",
338 +                numkeys, enctype, keysize);
339         if (WRITE_BYTES(&p, end, enctype)) goto out_err;
340         if (WRITE_BYTES(&p, end, keysize)) goto out_err;
341         if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
342 @@ -434,14 +441,25 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
343                         goto out_err;
344  
345                 /* Kc */
346 -               if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
347 -                               &derived_key,
348 -                               KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
349 -                       goto out_err;
350 -               if (write_bytes(&p, end, derived_key.data,
351 -                               derived_key.length))
352 -                       goto out_err;
353 -               free(derived_key.data);
354 +               /*
355 +                * RC4 is special, it dosen't need key derivation. Actually
356 +                * the Ke is based on plain text. Here we just let all three
357 +                * key identical, kernel will handle everything. --ericm
358 +                */
359 +               if (lctx->rfc1964_kd.ctx_key.type == ENCTYPE_ARCFOUR_HMAC) {
360 +                       if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
361 +                                       lctx->rfc1964_kd.ctx_key.length))
362 +                               goto out_err;
363 +               } else {
364 +                       if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
365 +                                       &derived_key,
366 +                                       KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
367 +                               goto out_err;
368 +                       if (write_bytes(&p, end, derived_key.data,
369 +                                       derived_key.length))
370 +                               goto out_err;
371 +                       free(derived_key.data);
372 +               }
373         } else {
374                 gss_krb5_lucid_key_t *keyptr;
375                 uint32_t sign_usage, seal_usage;
376 @@ -451,6 +469,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
377                 else
378                         keyptr = &lctx->cfx_kd.ctx_key;
379  
380 +#if 0
381                 if (lctx->initiate == 1) {
382                         sign_usage = KG_USAGE_INITIATOR_SIGN;
383                         seal_usage = KG_USAGE_INITIATOR_SEAL;
384 @@ -458,6 +477,19 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
385                         sign_usage = KG_USAGE_ACCEPTOR_SIGN;
386                         seal_usage = KG_USAGE_ACCEPTOR_SEAL;
387                 }
388 +#else
389 +               /* FIXME
390 +                * These are from rfc4142, but I don't understand: if we supply
391 +                * different 'usage' value for client & server, then the peers
392 +                * will have different derived keys. How could this work?
393 +                *
394 +                * Here we simply use old SIGN/SEAL values until we find the
395 +                * answer.  --ericm
396 +                * FIXME
397 +                */
398 +               sign_usage = KG_USAGE_SIGN;
399 +               seal_usage = KG_USAGE_SEAL;
400 +#endif
401  
402                 /* derive and send down: Ke, Ki, and Kc */
403  
404 @@ -515,7 +547,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
405         gss_krb5_lucid_context_v1_t *lctx = 0;
406         int retcode = 0;
407  
408 -       printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__);
409 +       printerr(3, "lucid version!\n");
410         maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx,
411                                                 1, &return_ctx);
412         if (maj_stat != GSS_S_COMPLETE) {
413 diff -Nrup nfs-utils-1.0.11/utils/gssd/context_mit.c nfs-utils-1.0.11.lustre/utils/gssd/context_mit.c
414 --- nfs-utils-1.0.11/utils/gssd/context_mit.c   2007-06-29 12:28:01.000000000 -0600
415 +++ nfs-utils-1.0.11.lustre/utils/gssd/context_mit.c    2007-06-29 12:32:30.000000000 -0600
416 @@ -39,10 +39,14 @@
417  #include <errno.h>
418  #include <gssapi/gssapi.h>
419  #include <rpc/rpc.h>
420 -#include <rpc/auth_gss.h>
421 -#include "gss_util.h"
422 -#include "gss_oids.h"
423 -#include "err_util.h"
424 +
425 +#ifdef _NEW_BUILD_
426 +# include "lgss_utils.h"
427 +#else
428 +# include "gss_util.h"
429 +# include "gss_oids.h"
430 +# include "err_util.h"
431 +#endif
432  #include "context.h"
433  
434  #include <krb5.h>
435 @@ -333,12 +337,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
436                  * keydata-2;                (  Ki  (Kseq for DES3) )
437                  * keydata-3;                (  Kc (derived checksum key) )
438                  */
439 -               if (kctx->initiate) {
440 -                       if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
441 -               }
442 -               else {
443 -                       if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
444 -               }
445 +               if (WRITE_BYTES(&p, end, constant_two)) goto out_err;
446                 if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
447  
448                 /* Only applicable flag for this is initiator */
449 diff -Nrup nfs-utils-1.0.11/utils/gssd/context_spkm3.c nfs-utils-1.0.11.lustre/utils/gssd/context_spkm3.c
450 --- nfs-utils-1.0.11/utils/gssd/context_spkm3.c 2007-02-21 21:50:03.000000000 -0700
451 +++ nfs-utils-1.0.11.lustre/utils/gssd/context_spkm3.c  2007-06-29 12:32:31.000000000 -0600
452 @@ -33,8 +33,6 @@
453  #include <syslog.h>
454  #include <string.h>
455  #include <gssapi/gssapi.h>
456 -#include <rpc/rpc.h>
457 -#include <rpc/auth_gss.h>
458  #include "gss_util.h"
459  #include "gss_oids.h"
460  #include "err_util.h"
461 diff -Nrup nfs-utils-1.0.11/utils/gssd/err_util.c nfs-utils-1.0.11.lustre/utils/gssd/err_util.c
462 --- nfs-utils-1.0.11/utils/gssd/err_util.c      2007-02-21 21:50:03.000000000 -0700
463 +++ nfs-utils-1.0.11.lustre/utils/gssd/err_util.c       2007-06-29 12:32:31.000000000 -0600
464 @@ -32,6 +32,8 @@
465  #include <stdarg.h>
466  #include <syslog.h>
467  #include <string.h>
468 +#include <fcntl.h>
469 +#include <ctype.h>
470  #include "err_util.h"
471  
472  static int verbosity = 0;
473 @@ -91,3 +93,40 @@ printit:
474         /* reset the buffer */
475         memset(message_buf, 0, sizeof(message_buf));
476  }
477 +
478 +void print_hexl(int pri, unsigned char *cp, int length)
479 +{
480 +       int i, j, jm;
481 +       unsigned char c;
482 +
483 +       printerr(pri, "length %d\n",length);
484 +       printerr(pri, "\n");
485 +
486 +       for (i = 0; i < length; i += 0x10) {
487 +               printerr(pri, "  %04x: ", (u_int)i);
488 +               jm = length - i;
489 +               jm = jm > 16 ? 16 : jm;
490 +
491 +               for (j = 0; j < jm; j++) {
492 +                       if ((j % 2) == 1)
493 +                               printerr(pri,"%02x ", (u_int)cp[i+j]);
494 +                       else
495 +                               printerr(pri,"%02x", (u_int)cp[i+j]);
496 +               }
497 +               for (; j < 16; j++) {
498 +                       if ((j % 2) == 1)
499 +                               printerr(pri,"   ");
500 +                       else
501 +                               printerr(pri,"  ");
502 +               }
503 +               printerr(pri," ");
504 +
505 +               for (j = 0; j < jm; j++) {
506 +                       c = cp[i+j];
507 +                       c = isprint(c) ? c : '.';
508 +                       printerr(pri,"%c", c);
509 +               }
510 +               printerr(pri,"\n");
511 +       }
512 +}
513 +
514 diff -Nrup nfs-utils-1.0.11/utils/gssd/err_util.h nfs-utils-1.0.11.lustre/utils/gssd/err_util.h
515 --- nfs-utils-1.0.11/utils/gssd/err_util.h      2007-02-21 21:50:03.000000000 -0700
516 +++ nfs-utils-1.0.11.lustre/utils/gssd/err_util.h       2007-06-29 12:32:32.000000000 -0600
517 @@ -33,5 +33,6 @@
518  
519  void initerr(char *progname, int verbosity, int fg);
520  void printerr(int priority, char *format, ...);
521 +void print_hexl(int pri, unsigned char *cp, int length);
522  
523  #endif /* _ERR_UTIL_H_ */
524 diff -Nrup nfs-utils-1.0.11/utils/gssd/gss_clnt_send_err.c nfs-utils-1.0.11.lustre/utils/gssd/gss_clnt_send_err.c
525 --- nfs-utils-1.0.11/utils/gssd/gss_clnt_send_err.c     2007-02-21 21:50:03.000000000 -0700
526 +++ nfs-utils-1.0.11.lustre/utils/gssd/gss_clnt_send_err.c      2007-06-29 12:29:20.000000000 -0600
527 @@ -47,6 +47,7 @@
528  #include "gssd.h"
529  #include "write_bytes.h"
530  
531 +#if 0
532  char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
533  
534  static void
535 @@ -102,3 +103,4 @@ main(int argc, char *argv[])
536         }
537         exit(0);
538  }
539 +#endif
540 diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd.c nfs-utils-1.0.11.lustre/utils/gssd/gssd.c
541 --- nfs-utils-1.0.11/utils/gssd/gssd.c  2007-06-29 12:28:01.000000000 -0600
542 +++ nfs-utils-1.0.11.lustre/utils/gssd/gssd.c   2007-06-29 12:32:36.000000000 -0600
543 @@ -38,9 +38,12 @@
544  
545  #include "config.h"
546  
547 +#include <sys/types.h>
548  #include <sys/param.h>
549  #include <sys/socket.h>
550 -#include <rpc/rpc.h>
551 +#include <sys/wait.h>
552 +#include <sys/ipc.h>
553 +#include <sys/sem.h>
554  
555  #include <unistd.h>
556  #include <err.h>
557 @@ -48,23 +51,107 @@
558  #include <stdlib.h>
559  #include <string.h>
560  #include <signal.h>
561 +#include <errno.h>
562  #include "gssd.h"
563  #include "err_util.h"
564  #include "gss_util.h"
565  #include "krb5_util.h"
566 +#include "lsupport.h"
567  
568  char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR;
569  char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
570  char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
571  char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR;
572  int  use_memcache = 0;
573 +int  lgssd_mutex_downcall = -1;
574  
575 -void
576 -sig_die(int signal)
577 +static int lgssd_create_mutex(int *semid)
578 +{
579 +       int             id;
580 +       int             arg;
581 +
582 +       id = semget(IPC_PRIVATE, 1, IPC_CREAT);
583 +       if (id == -1) {
584 +               printerr(0, "semget: %s\n", strerror(errno));
585 +               return -1;
586 +       }
587 +
588 +       arg = 1;
589 +       if (semctl(id, 0, SETVAL, arg) != 0) {
590 +               printerr(0, "semctl: %s\n", strerror(errno));
591 +               semctl(id, 1, IPC_RMID, arg);
592 +               return -1;
593 +       }
594 +
595 +       *semid = id;
596 +       return 0;
597 +}
598 +
599 +void lgssd_init_mutexs(void)
600 +{
601 +       if (lgssd_create_mutex(&lgssd_mutex_downcall)) {
602 +               printerr(0, "can't create downcall mutex\n");
603 +               exit(1);
604 +       }
605 +}
606 +
607 +void lgssd_fini_mutexs(void)
608 +{
609 +       int     arg = 0;
610 +
611 +       if (lgssd_mutex_downcall != -1)
612 +               semctl(lgssd_mutex_downcall, 1, IPC_RMID, arg);
613 +}
614 +
615 +void lgssd_mutex_get(int semid)
616 +{
617 +       struct sembuf   op[1] = { {0, -1, SEM_UNDO} };
618 +       int             rc;
619 +
620 +       rc = semop(semid, op, 1);
621 +       if (rc != 0) {
622 +               printerr(0, "exit on mutex_get err %d: %s\n",
623 +                        rc, strerror(errno));
624 +               exit(1);
625 +       }
626 +}
627 +
628 +void lgssd_mutex_put(int semid)
629  {
630 +       struct sembuf   op[1] = { {0, 1, 0} };
631 +       int             rc;
632 +
633 +       rc = semop(semid, op, 1);
634 +       if (rc != 0) {
635 +               printerr(0, "ignore mutex_put err %d: %s\n",
636 +                        rc, strerror(errno));
637 +       }
638 +}
639 +
640 +static void lgssd_cleanup(void)
641 +{
642 +       pid_t   child_pid;
643 +
644 +       /* make sure all children finished */
645 +       while (1) {
646 +               child_pid = waitpid(-1, NULL, 0);
647 +               if (child_pid < 0)
648 +                       break;
649 +
650 +               printerr(3, "cleanup: child %d terminated\n", child_pid);
651 +       }
652 +
653 +       lgssd_fini_mutexs();
654 +
655         /* destroy krb5 machine creds */
656         gssd_destroy_krb5_machine_creds();
657 +}
658 +
659 +void
660 +sig_die(int signal)
661 +{
662         printerr(1, "exiting on signal %d\n", signal);
663 +       lgssd_cleanup();
664         exit(1);
665  }
666  
667 @@ -79,7 +166,7 @@ sig_hup(int signal)
668  static void
669  usage(char *progname)
670  {
671 -       fprintf(stderr, "usage: %s [-f] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir]\n",
672 +       fprintf(stderr, "usage: %s [-f] [-v] [-p pipefsdir] [-k keytab] [-d ccachedir]\n",
673                 progname);
674         exit(1);
675  }
676 @@ -89,7 +176,6 @@ main(int argc, char *argv[])
677  {
678         int fg = 0;
679         int verbosity = 0;
680 -       int rpc_verbosity = 0;
681         int opt;
682         extern char *optarg;
683         char *progname;
684 @@ -99,18 +185,12 @@ main(int argc, char *argv[])
685                         case 'f':
686                                 fg = 1;
687                                 break;
688 -                       case 'm':
689 -                               /* Accept but ignore this. Now the default. */
690 -                               break;
691                         case 'M':
692                                 use_memcache = 1;
693                                 break;
694                         case 'v':
695                                 verbosity++;
696                                 break;
697 -                       case 'r':
698 -                               rpc_verbosity++;
699 -                               break;
700                         case 'p':
701                                 strncpy(pipefs_dir, optarg, sizeof(pipefs_dir));
702                                 if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0')
703 @@ -131,10 +211,6 @@ main(int argc, char *argv[])
704                                 break;
705                 }
706         }
707 -       snprintf(pipefs_nfsdir, sizeof(pipefs_nfsdir), "%s/%s",
708 -                pipefs_dir, GSSD_SERVICE_NAME);
709 -       if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0')
710 -               errx(1, "pipefs_nfsdir path name too long");
711  
712         if ((progname = strrchr(argv[0], '/')))
713                 progname++;
714 @@ -142,30 +218,42 @@ main(int argc, char *argv[])
715                 progname = argv[0];
716  
717         initerr(progname, verbosity, fg);
718 -#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
719 -       authgss_set_debug_level(rpc_verbosity);
720 -#else
721 -        if (rpc_verbosity > 0)
722 -               printerr(0, "Warning: rpcsec_gss library does not "
723 -                           "support setting debug level\n");
724 -#endif
725  
726         if (gssd_check_mechs() != 0)
727                 errx(1, "Problem with gssapi library");
728  
729 +       if (gssd_get_local_realm())
730 +               errx(1, "get local realm");
731 +
732         if (!fg && daemon(0, 0) < 0)
733                 errx(1, "fork");
734  
735 +       /* This should be checked _after_ daemon(), because we need to own
736 +        * the undo-able semaphore by this process
737 +        */
738 +       gssd_init_unique(GSSD_CLI);
739 +
740 +       /* Process keytab file and get machine credentials. This will modify
741 +        * disk status so do it after we are sure we are the only instance
742 +        */
743 +       if (gssd_refresh_krb5_machine_creds())
744 +               return -1;
745 +
746         signal(SIGINT, sig_die);
747         signal(SIGTERM, sig_die);
748         signal(SIGHUP, sig_hup);
749  
750 -       /* Process keytab file and get machine credentials */
751 -       gssd_refresh_krb5_machine_creds();
752 +#if 0
753         /* Determine Kerberos information from the kernel */
754         gssd_obtain_kernel_krb5_info();
755 +#endif
756 +
757 +       lgssd_init_mutexs();
758 +
759 +       printerr(0, "lgssd initialized and ready to serve\n");
760 +       lgssd_run();
761  
762 -       gssd_run();
763 -       printerr(0, "gssd_run returned!\n");
764 -       abort();
765 +       lgssd_cleanup();
766 +       printerr(0, "lgssd exiting\n");
767 +       return 0;
768  }
769 diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd.h nfs-utils-1.0.11.lustre/utils/gssd/gssd.h
770 --- nfs-utils-1.0.11/utils/gssd/gssd.h  2007-06-29 12:28:01.000000000 -0600
771 +++ nfs-utils-1.0.11.lustre/utils/gssd/gssd.h   2007-06-29 12:32:37.000000000 -0600
772 @@ -48,8 +48,13 @@
773  #define GSSD_DEFAULT_CRED_PREFIX               "krb5cc_"
774  #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX       "machine"
775  #define GSSD_DEFAULT_KEYTAB_FILE               "/etc/krb5.keytab"
776 -#define GSSD_SERVICE_NAME                      "nfs"
777 -#define GSSD_SERVICE_NAME_LEN                  3
778 +#define GSSD_SERVICE_MDS                       "lustre_mds"
779 +#define GSSD_SERVICE_OSS                       "lustre_oss"
780 +#define GSSD_SERVICE_MDS_NAMELEN               10
781 +#define GSSD_SERVICE_OSS_NAMELEN               10
782 +
783 +#define LUSTRE_ROOT_NAME                       "lustre_root"
784 +#define LUSTRE_ROOT_NAMELEN                    11
785  
786  /*
787   * The gss mechanisms that we can handle
788 @@ -59,9 +64,9 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT
789  
790  
791  extern char                    pipefs_dir[PATH_MAX];
792 -extern char                    pipefs_nfsdir[PATH_MAX];
793  extern char                    keytabfile[PATH_MAX];
794  extern char                    ccachedir[PATH_MAX];
795 +extern char                    gethostname_ex[PATH_MAX];
796  extern int                     use_memcache;
797  
798  TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list;
799 @@ -71,10 +76,6 @@ struct clnt_info {
800         char                    *dirname;
801         int                     dir_fd;
802         char                    *servicename;
803 -       char                    *servername;
804 -       int                     prog;
805 -       int                     vers;
806 -       char                    *protocol;
807         int                     krb5_fd;
808         int                     krb5_poll_index;
809         int                     spkm3_fd;
810 @@ -85,8 +86,14 @@ void init_client_list(void);
811  int update_client_list(void);
812  void handle_krb5_upcall(struct clnt_info *clp);
813  void handle_spkm3_upcall(struct clnt_info *clp);
814 -int gssd_acquire_cred(char *server_name);
815 -void gssd_run(void);
816 +void lgssd_run(void);
817 +
818 +
819 +extern int lgssd_mutex_downcall;
820  
821 +void lgssd_init_mutexs(void);
822 +void lgssd_fini_mutexs(void);
823 +void lgssd_mutex_get(int semid);
824 +void lgssd_mutex_put(int semid);
825  
826  #endif /* _RPC_GSSD_H_ */
827 diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c nfs-utils-1.0.11.lustre/utils/gssd/gssd_main_loop.c
828 --- nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c        2007-06-29 12:28:01.000000000 -0600
829 +++ nfs-utils-1.0.11.lustre/utils/gssd/gssd_main_loop.c 2007-06-29 12:32:38.000000000 -0600
830 @@ -94,11 +94,13 @@ scan_poll_results(int ret)
831  };
832  
833  void
834 -gssd_run()
835 +lgssd_run()
836  {
837         int                     ret;
838         struct sigaction        dn_act;
839         int                     fd;
840 +       time_t                  child_check = 0;
841 +       pid_t                   child_pid;
842  
843         /* Taken from linux/Documentation/dnotify.txt: */
844         dn_act.sa_sigaction = dir_notify_handler;
845 @@ -106,10 +108,10 @@ gssd_run()
846         dn_act.sa_flags = SA_SIGINFO;
847         sigaction(DNOTIFY_SIGNAL, &dn_act, NULL);
848  
849 -       if ((fd = open(pipefs_nfsdir, O_RDONLY)) == -1) {
850 +       if ((fd = open(pipefs_dir, O_RDONLY)) == -1) {
851                 printerr(0, "ERROR: failed to open %s: %s\n",
852 -                        pipefs_nfsdir, strerror(errno));
853 -               exit(1);
854 +                        pipefs_dir, strerror(errno));
855 +               return;
856         }
857         fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL);
858         fcntl(fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
859 @@ -119,12 +121,30 @@ gssd_run()
860         while (1) {
861                 while (dir_changed) {
862                         dir_changed = 0;
863 +                       printerr(2, "pipefs root dir changed\n");
864                         if (update_client_list()) {
865                                 printerr(0, "ERROR: couldn't update "
866                                          "client list\n");
867 -                               exit(1);
868 +                               goto out;
869                         }
870                 }
871 +
872 +               /* every 5s cleanup possible zombies of child processes */
873 +               if (time(NULL) - child_check >= 5) {
874 +                       printerr(3, "check zombie children...\n");
875 +
876 +                       while (1) {
877 +                               child_pid = waitpid(-1, NULL, WNOHANG);
878 +                               if (child_pid <= 0)
879 +                                       break;
880 +
881 +                               printerr(2, "terminate zombie child: %d\n",
882 +                                        child_pid);
883 +                       }
884 +
885 +                       child_check = time(NULL);
886 +               }
887 +
888                 /* race condition here: dir_changed could be set before we
889                  * enter the poll, and we'd never notice if it weren't for the
890                  * timeout. */
891 @@ -139,6 +159,7 @@ gssd_run()
892                         scan_poll_results(ret);
893                 }
894         }
895 +out:
896         close(fd);
897         return;
898  }
899 diff -Nrup nfs-utils-1.0.11/utils/gssd/gssd_proc.c nfs-utils-1.0.11.lustre/utils/gssd/gssd_proc.c
900 --- nfs-utils-1.0.11/utils/gssd/gssd_proc.c     2007-06-29 12:28:01.000000000 -0600
901 +++ nfs-utils-1.0.11.lustre/utils/gssd/gssd_proc.c      2007-06-29 12:32:38.000000000 -0600
902 @@ -43,7 +43,6 @@
903  #endif
904  #include "config.h"
905  #include <sys/param.h>
906 -#include <rpc/rpc.h>
907  #include <sys/stat.h>
908  #include <sys/socket.h>
909  #include <arpa/inet.h>
910 @@ -69,6 +68,7 @@
911  #include "gss_oids.h"
912  #include "krb5_util.h"
913  #include "context.h"
914 +#include "lsupport.h"
915  
916  /*
917   * pollarray:
918 @@ -99,86 +99,10 @@ struct pollfd * pollarray;
919  
920  int pollsize;  /* the size of pollaray (in pollfd's) */
921  
922 -/* XXX buffer problems: */
923 -static int
924 -read_service_info(char *info_file_name, char **servicename, char **servername,
925 -                 int *prog, int *vers, char **protocol) {
926 -#define INFOBUFLEN 256
927 -       char            buf[INFOBUFLEN];
928 -       static char     dummy[128];
929 -       int             nbytes;
930 -       static char     service[128];
931 -       static char     address[128];
932 -       char            program[16];
933 -       char            version[16];
934 -       char            protoname[16];
935 -       in_addr_t       inaddr;
936 -       int             fd = -1;
937 -       struct hostent  *ent = NULL;
938 -       int             numfields;
939 -
940 -       *servicename = *servername = *protocol = NULL;
941 -
942 -       if ((fd = open(info_file_name, O_RDONLY)) == -1) {
943 -               printerr(0, "ERROR: can't open %s: %s\n", info_file_name,
944 -                        strerror(errno));
945 -               goto fail;
946 -       }
947 -       if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1)
948 -               goto fail;
949 -       close(fd);
950 -
951 -       numfields = sscanf(buf,"RPC server: %127s\n"
952 -                  "service: %127s %15s version %15s\n"
953 -                  "address: %127s\n"
954 -                  "protocol: %15s\n",
955 -                  dummy,
956 -                  service, program, version,
957 -                  address,
958 -                  protoname);
959 -
960 -       if (numfields == 5) {
961 -               strcpy(protoname, "tcp");
962 -       } else if (numfields != 6) {
963 -               goto fail;
964 -       }
965 -
966 -       /* check service, program, and version */
967 -       if(memcmp(service, "nfs", 3)) return -1;
968 -       *prog = atoi(program + 1); /* skip open paren */
969 -       *vers = atoi(version);
970 -       if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4)))
971 -               goto fail;
972 -
973 -       /* create service name */
974 -       inaddr = inet_addr(address);
975 -       if (!(ent = gethostbyaddr(&inaddr, sizeof(inaddr), AF_INET))) {
976 -               printerr(0, "ERROR: can't resolve server %s name\n", address);
977 -               goto fail;
978 -       }
979 -       if (!(*servername = calloc(strlen(ent->h_name) + 1, 1)))
980 -               goto fail;
981 -       memcpy(*servername, ent->h_name, strlen(ent->h_name));
982 -       snprintf(buf, INFOBUFLEN, "%s@%s", service, ent->h_name);
983 -       if (!(*servicename = calloc(strlen(buf) + 1, 1)))
984 -               goto fail;
985 -       memcpy(*servicename, buf, strlen(buf));
986 -
987 -       if (!(*protocol = strdup(protoname)))
988 -               goto fail;
989 -       return 0;
990 -fail:
991 -       printerr(0, "ERROR: failed to read service info\n");
992 -       if (fd != -1) close(fd);
993 -       if (*servername) free(*servername);
994 -       if (*servicename) free(*servicename);
995 -       if (*protocol) free(*protocol);
996 -       return -1;
997 -}
998 -
999  static void
1000  destroy_client(struct clnt_info *clp)
1001  {
1002 +       printerr(3, "clp %p: dirname %s, krb5fd %d\n", clp, clp->dirname, clp->krb5_fd);
1003         if (clp->krb5_poll_index != -1)
1004                 memset(&pollarray[clp->krb5_poll_index], 0,
1005                                         sizeof(struct pollfd));
1006 @@ -190,8 +114,6 @@ destroy_client(struct clnt_info *clp)
1007         if (clp->spkm3_fd != -1) close(clp->spkm3_fd);
1008         if (clp->dirname) free(clp->dirname);
1009         if (clp->servicename) free(clp->servicename);
1010 -       if (clp->servername) free(clp->servername);
1011 -       if (clp->protocol) free(clp->protocol);
1012         free(clp);
1013  }
1014  
1015 @@ -221,7 +143,6 @@ process_clnt_dir_files(struct clnt_info 
1016  {
1017         char    kname[32];
1018         char    sname[32];
1019 -       char    info_file_name[32];
1020  
1021         if (clp->krb5_fd == -1) {
1022                 snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname);
1023 @@ -233,13 +154,6 @@ process_clnt_dir_files(struct clnt_info 
1024         }
1025         if((clp->krb5_fd == -1) && (clp->spkm3_fd == -1))
1026                 return -1;
1027 -       snprintf(info_file_name, sizeof(info_file_name), "%s/info",
1028 -                       clp->dirname);
1029 -       if ((clp->servicename == NULL) &&
1030 -            read_service_info(info_file_name, &clp->servicename,
1031 -                               &clp->servername, &clp->prog, &clp->vers,
1032 -                               &clp->protocol))
1033 -               return -1;
1034         return 0;
1035  }
1036  
1037 @@ -273,6 +187,8 @@ insert_clnt_poll(struct clnt_info *clp)
1038                 }
1039                 pollarray[clp->krb5_poll_index].fd = clp->krb5_fd;
1040                 pollarray[clp->krb5_poll_index].events |= POLLIN;
1041 +               printerr(2, "monitoring krb5 channel under %s\n",
1042 +                        clp->dirname);
1043         }
1044  
1045         if ((clp->spkm3_fd != -1) && (clp->spkm3_poll_index == -1)) {
1046 @@ -386,67 +302,106 @@ find_client(char *dirname)
1047  int
1048  update_client_list(void)
1049  {
1050 -       struct dirent **namelist;
1051 +       char lustre_dir[PATH_MAX];
1052 +       struct dirent lustre_dirent = { .d_name = "lustre" };
1053 +       struct dirent *namelist[1];
1054 +       struct stat statbuf;
1055         int i, j;
1056  
1057 -       if (chdir(pipefs_nfsdir) < 0) {
1058 +       if (chdir(pipefs_dir) < 0) {
1059                 printerr(0, "ERROR: can't chdir to %s: %s\n",
1060 -                        pipefs_nfsdir, strerror(errno));
1061 +                        pipefs_dir, strerror(errno));
1062                 return -1;
1063         }
1064  
1065 -       j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort);
1066 -       if (j < 0) {
1067 -               printerr(0, "ERROR: can't scandir %s: %s\n",
1068 -                        pipefs_nfsdir, strerror(errno));
1069 -               return -1;
1070 +       snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefs_dir, "lustre");
1071 +       if (stat(lustre_dir, &statbuf) == 0) {
1072 +               namelist[0] = &lustre_dirent;
1073 +               j = 1;
1074 +               printerr(2, "re-processing lustre directory\n");
1075 +       } else {
1076 +               namelist[0] = NULL;
1077 +               j = 0;
1078 +               printerr(2, "lustre directory not exist\n");
1079         }
1080 +
1081         update_old_clients(namelist, j);
1082         for (i=0; i < j; i++) {
1083 -               if (i < FD_ALLOC_BLOCK
1084 -                               && !strncmp(namelist[i]->d_name, "clnt", 4)
1085 -                               && !find_client(namelist[i]->d_name))
1086 +               if (i < FD_ALLOC_BLOCK && !find_client(namelist[i]->d_name))
1087                         process_clnt_dir(namelist[i]->d_name);
1088 -               free(namelist[i]);
1089         }
1090  
1091 -       free(namelist);
1092 +       chdir("/");
1093         return 0;
1094  }
1095  
1096 +/* Context creation response. */
1097 +struct lustre_gss_init_res {
1098 +        gss_buffer_desc gr_ctx;         /* context handle */
1099 +        u_int           gr_major;       /* major status */
1100 +        u_int           gr_minor;       /* minor status */
1101 +        u_int           gr_win;         /* sequence window */
1102 +        gss_buffer_desc gr_token;       /* token */
1103 +};
1104 +
1105 +struct lustre_gss_data {
1106 +        int             lgd_established;
1107 +        int             lgd_lustre_svc; /* mds/oss */
1108 +        int             lgd_uid;        /* uid */
1109 +        char           *lgd_uuid;       /* client device uuid */
1110 +        gss_name_t      lgd_name;       /* service name */
1111 +
1112 +        gss_OID         lgd_mech;       /* mech OID */
1113 +        u_int           lgd_req_flags;  /* request flags */
1114 +        gss_cred_id_t   lgd_cred;       /* credential */
1115 +        gss_ctx_id_t    lgd_ctx;        /* session context */
1116 +        gss_buffer_desc lgd_rmt_ctx;    /* remote handle of context */
1117 +        uint32_t        lgd_seq_win;    /* sequence window */
1118 +
1119 +        int             lgd_rpc_err;
1120 +        int             lgd_gss_err;
1121 +};
1122 +
1123  static int
1124 -do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
1125 -           gss_buffer_desc *context_token)
1126 +do_downcall(int k5_fd, struct lgssd_upcall_data *updata,
1127 +            struct lustre_gss_data *lgd, gss_buffer_desc *context_token)
1128  {
1129         char    *buf = NULL, *p = NULL, *end = NULL;
1130         unsigned int timeout = 0; /* XXX decide on a reasonable value */
1131         unsigned int buf_size = 0;
1132  
1133 -       printerr(1, "doing downcall\n");
1134 -       buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) +
1135 -               sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length +
1136 +       printerr(2, "doing downcall\n");
1137 +       buf_size = sizeof(updata->seq) + sizeof(timeout) +
1138 +               sizeof(lgd->lgd_seq_win) +
1139 +               sizeof(lgd->lgd_rmt_ctx.length) + lgd->lgd_rmt_ctx.length +
1140                 sizeof(context_token->length) + context_token->length;
1141         p = buf = malloc(buf_size);
1142         end = buf + buf_size;
1143  
1144 -       if (WRITE_BYTES(&p, end, uid)) goto out_err;
1145 +       if (WRITE_BYTES(&p, end, updata->seq)) goto out_err;
1146         /* Not setting any timeout for now: */
1147         if (WRITE_BYTES(&p, end, timeout)) goto out_err;
1148 -       if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err;
1149 -       if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err;
1150 +       if (WRITE_BYTES(&p, end, lgd->lgd_seq_win)) goto out_err;
1151 +       if (write_buffer(&p, end, &lgd->lgd_rmt_ctx)) goto out_err;
1152         if (write_buffer(&p, end, context_token)) goto out_err;
1153  
1154 -       if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
1155 +       lgssd_mutex_get(lgssd_mutex_downcall);
1156 +       if (write(k5_fd, buf, p - buf) < p - buf) {
1157 +               lgssd_mutex_put(lgssd_mutex_downcall);
1158 +               goto out_err;
1159 +       }
1160 +       lgssd_mutex_put(lgssd_mutex_downcall);
1161 +
1162         if (buf) free(buf);
1163         return 0;
1164  out_err:
1165         if (buf) free(buf);
1166 -       printerr(0, "Failed to write downcall!\n");
1167 +       printerr(0, "ERROR: Failed to write downcall!\n");
1168         return -1;
1169  }
1170  
1171  static int
1172 -do_error_downcall(int k5_fd, uid_t uid, int err)
1173 +do_error_downcall(int k5_fd, uint32_t seq, int rpc_err, int gss_err)
1174  {
1175         char    buf[1024];
1176         char    *p = buf, *end = buf + 1024;
1177 @@ -455,19 +410,26 @@ do_error_downcall(int k5_fd, uid_t uid, 
1178  
1179         printerr(1, "doing error downcall\n");
1180  
1181 -       if (WRITE_BYTES(&p, end, uid)) goto out_err;
1182 +       if (WRITE_BYTES(&p, end, seq)) goto out_err;
1183         if (WRITE_BYTES(&p, end, timeout)) goto out_err;
1184         /* use seq_win = 0 to indicate an error: */
1185         if (WRITE_BYTES(&p, end, zero)) goto out_err;
1186 -       if (WRITE_BYTES(&p, end, err)) goto out_err;
1187 +       if (WRITE_BYTES(&p, end, rpc_err)) goto out_err;
1188 +       if (WRITE_BYTES(&p, end, gss_err)) goto out_err;
1189  
1190 -       if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
1191 +       lgssd_mutex_get(lgssd_mutex_downcall);
1192 +       if (write(k5_fd, buf, p - buf) < p - buf) {
1193 +               lgssd_mutex_put(lgssd_mutex_downcall);
1194 +               goto out_err;
1195 +       }
1196 +       lgssd_mutex_put(lgssd_mutex_downcall);
1197         return 0;
1198  out_err:
1199         printerr(0, "Failed to write error downcall!\n");
1200         return -1;
1201  }
1202  
1203 +#if 0
1204  /*
1205   * Create an RPC connection and establish an authenticated
1206   * gss context with a server.
1207 @@ -659,7 +621,287 @@ int create_auth_rpc_client(struct clnt_i
1208  
1209         goto out;
1210  }
1211 +#endif
1212 +
1213 +static
1214 +int do_negotiation(struct lustre_gss_data *lgd,
1215 +                  gss_buffer_desc *gss_token,
1216 +                  struct lustre_gss_init_res *gr,
1217 +                  int timeout)
1218 +{
1219 +       char *file = "/proc/fs/lustre/sptlrpc/gss/init_channel";
1220 +       struct lgssd_ioctl_param param;
1221 +       struct passwd *pw;
1222 +       int fd, ret;
1223 +       char outbuf[8192];
1224 +       unsigned int *p;
1225 +       int res;
1226 +
1227 +       pw = getpwuid(lgd->lgd_uid);
1228 +       if (!pw) {
1229 +               printerr(0, "no uid %u in local user database\n",
1230 +                        lgd->lgd_uid);
1231 +               return -1;
1232 +       }
1233 +
1234 +       param.version = GSSD_INTERFACE_VERSION;
1235 +       param.uuid = lgd->lgd_uuid;
1236 +       param.lustre_svc = lgd->lgd_lustre_svc;
1237 +       param.uid = lgd->lgd_uid;
1238 +       param.gid = pw->pw_gid;
1239 +       param.send_token_size = gss_token->length;
1240 +       param.send_token = (char *) gss_token->value;
1241 +       param.reply_buf_size = sizeof(outbuf);
1242 +       param.reply_buf = outbuf;
1243 +
1244 +       fd = open(file, O_RDWR);
1245 +       if (fd < 0) {
1246 +               printerr(0, "can't open file %s\n", file);
1247 +               return -1;
1248 +       }
1249 +
1250 +       ret = write(fd, &param, sizeof(param));
1251 +
1252 +       if (ret != sizeof(param)) {
1253 +               printerr(0, "lustre ioctl err: %d\n", strerror(errno));
1254 +               close(fd);
1255 +               return -1;
1256 +       }
1257 +       if (param.status) {
1258 +               close(fd);
1259 +               printerr(0, "status: %d (%s)\n",
1260 +                        param.status, strerror((int)param.status));
1261 +               if (param.status == -ETIMEDOUT) {
1262 +                       /* kernel return -ETIMEDOUT means the rpc timedout,
1263 +                        * we should notify the caller to reinitiate the
1264 +                        * gss negotiation, by return -ERESTART
1265 +                        */
1266 +                       lgd->lgd_rpc_err = -ERESTART;
1267 +                       lgd->lgd_gss_err = 0;
1268 +               } else {
1269 +                       lgd->lgd_rpc_err = param.status;
1270 +                       lgd->lgd_gss_err = 0;
1271 +               }
1272 +               return -1;
1273 +       }
1274 +       p = (unsigned int *)outbuf;
1275 +       res = *p++;
1276 +       gr->gr_major = *p++;
1277 +       gr->gr_minor = *p++;
1278 +       gr->gr_win = *p++;
1279 +
1280 +       gr->gr_ctx.length = *p++;
1281 +       gr->gr_ctx.value = malloc(gr->gr_ctx.length);
1282 +       memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length);
1283 +       p += (((gr->gr_ctx.length + 3) & ~3) / 4);
1284 +
1285 +       gr->gr_token.length = *p++;
1286 +       gr->gr_token.value = malloc(gr->gr_token.length);
1287 +       memcpy(gr->gr_token.value, p, gr->gr_token.length);
1288 +       p += (((gr->gr_token.length + 3) & ~3) / 4);
1289 +
1290 +       printerr(2, "do_negotiation: receive handle len %d, token len %d\n",
1291 +                gr->gr_ctx.length, gr->gr_token.length);
1292 +       close(fd);
1293 +       return 0;
1294 +}
1295 +
1296 +static
1297 +int gssd_refresh_lgd(struct lustre_gss_data *lgd)
1298 +{
1299 +       struct lustre_gss_init_res gr;
1300 +       gss_buffer_desc         *recv_tokenp, send_token;
1301 +       OM_uint32                maj_stat, min_stat, call_stat, ret_flags;
1302 +
1303 +       /* GSS context establishment loop. */
1304 +       memset(&gr, 0, sizeof(gr));
1305 +       recv_tokenp = GSS_C_NO_BUFFER;
1306 +
1307 +       for (;;) {
1308 +               /* print the token we just received */
1309 +               if (recv_tokenp != GSS_C_NO_BUFFER) {
1310 +                       printerr(3, "The received token length %d\n",
1311 +                                recv_tokenp->length);
1312 +                       print_hexl(3, recv_tokenp->value, recv_tokenp->length);
1313 +               }
1314 +
1315 +               maj_stat = gss_init_sec_context(&min_stat,
1316 +                                               lgd->lgd_cred,
1317 +                                               &lgd->lgd_ctx,
1318 +                                               lgd->lgd_name,
1319 +                                               lgd->lgd_mech,
1320 +                                               lgd->lgd_req_flags,
1321 +                                               0,              /* time req */
1322 +                                               NULL,           /* channel */
1323 +                                               recv_tokenp,
1324 +                                               NULL,           /* used mech */
1325 +                                               &send_token,
1326 +                                               &ret_flags,
1327 +                                               NULL);          /* time rec */
1328 +
1329 +               if (recv_tokenp != GSS_C_NO_BUFFER) {
1330 +                       gss_release_buffer(&min_stat, &gr.gr_token);
1331 +                       recv_tokenp = GSS_C_NO_BUFFER;
1332 +               }
1333 +               if (maj_stat != GSS_S_COMPLETE &&
1334 +                   maj_stat != GSS_S_CONTINUE_NEEDED) {
1335 +                       pgsserr("gss_init_sec_context", maj_stat, min_stat,
1336 +                               lgd->lgd_mech);
1337 +                       break;
1338 +               }
1339 +               if (send_token.length != 0) {
1340 +                       memset(&gr, 0, sizeof(gr));
1341 +
1342 +                       /* print the token we are about to send */
1343 +                       printerr(3, "token being sent length %d\n",
1344 +                                send_token.length);
1345 +                       print_hexl(3, send_token.value, send_token.length);
1346 +
1347 +                       call_stat = do_negotiation(lgd, &send_token, &gr, 0);
1348 +                       gss_release_buffer(&min_stat, &send_token);
1349 +
1350 +                       if (call_stat != 0 ||
1351 +                           (gr.gr_major != GSS_S_COMPLETE &&
1352 +                            gr.gr_major != GSS_S_CONTINUE_NEEDED)) {
1353 +                               printerr(0, "call stat %d, major stat 0x%x\n",
1354 +                                        (int)call_stat, gr.gr_major);
1355 +                               return -1;
1356 +                       }
1357 +
1358 +                       if (gr.gr_ctx.length != 0) {
1359 +                               if (lgd->lgd_rmt_ctx.value)
1360 +                                       gss_release_buffer(&min_stat,
1361 +                                                          &lgd->lgd_rmt_ctx);
1362 +                               lgd->lgd_rmt_ctx = gr.gr_ctx;
1363 +                       }
1364 +                       if (gr.gr_token.length != 0) {
1365 +                               if (maj_stat != GSS_S_CONTINUE_NEEDED)
1366 +                                       break;
1367 +                               recv_tokenp = &gr.gr_token;
1368 +                       }
1369 +               }
1370 +
1371 +               /* GSS_S_COMPLETE => check gss header verifier,
1372 +                * usually checked in gss_validate
1373 +                */
1374 +               if (maj_stat == GSS_S_COMPLETE) {
1375 +                       lgd->lgd_established = 1;
1376 +                       lgd->lgd_seq_win = gr.gr_win;
1377 +                       break;
1378 +               }
1379 +       }
1380 +       /* End context negotiation loop. */
1381 +       if (!lgd->lgd_established) {
1382 +               if (gr.gr_token.length != 0)
1383 +                       gss_release_buffer(&min_stat, &gr.gr_token);
1384 +
1385 +               printerr(0, "context negotiation failed\n");
1386 +               return -1;
1387 +       }
1388 +
1389 +       printerr(2, "successfully refreshed lgd\n");
1390 +       return 0;
1391 +}
1392  
1393 +static
1394 +int gssd_create_lgd(struct clnt_info *clp,
1395 +                   struct lustre_gss_data *lgd,
1396 +                   struct lgssd_upcall_data *updata,
1397 +                   int authtype)
1398 +{
1399 +       gss_buffer_desc         sname;
1400 +       OM_uint32               maj_stat, min_stat;
1401 +       int                     retval = -1;
1402 +
1403 +       lgd->lgd_established = 0;
1404 +       lgd->lgd_lustre_svc = updata->svc;
1405 +       lgd->lgd_uid = updata->uid;
1406 +       lgd->lgd_uuid = updata->obd;
1407 +
1408 +       switch (authtype) {
1409 +       case AUTHTYPE_KRB5:
1410 +               lgd->lgd_mech = (gss_OID) &krb5oid;
1411 +               lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG;
1412 +               break;
1413 +       case AUTHTYPE_SPKM3:
1414 +               lgd->lgd_mech = (gss_OID) &spkm3oid;
1415 +               /* XXX sec.req_flags = GSS_C_ANON_FLAG;
1416 +                * Need a way to switch....
1417 +                */
1418 +               lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG;
1419 +               break;
1420 +       default:
1421 +               printerr(0, "Invalid authentication type (%d)\n", authtype);
1422 +               return -1;
1423 +       }
1424 +
1425 +       lgd->lgd_cred = GSS_C_NO_CREDENTIAL;
1426 +       lgd->lgd_ctx = GSS_C_NO_CONTEXT;
1427 +       lgd->lgd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER;
1428 +       lgd->lgd_seq_win = 0;
1429 +
1430 +       sname.value = clp->servicename;
1431 +       sname.length = strlen(clp->servicename);
1432 +
1433 +       maj_stat = gss_import_name(&min_stat, &sname,
1434 +                                  (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
1435 +                                  &lgd->lgd_name);
1436 +       if (maj_stat != GSS_S_COMPLETE) {
1437 +               pgsserr(0, maj_stat, min_stat, lgd->lgd_mech);
1438 +               goto out_fail;
1439 +       }
1440 +
1441 +       retval = gssd_refresh_lgd(lgd);
1442 +
1443 +       if (lgd->lgd_name != GSS_C_NO_NAME)
1444 +               gss_release_name(&min_stat, &lgd->lgd_name);
1445 +
1446 +       if (lgd->lgd_cred != GSS_C_NO_CREDENTIAL)
1447 +               gss_release_cred(&min_stat, &lgd->lgd_cred);
1448 +
1449 +  out_fail:
1450 +       return retval;
1451 +}
1452 +
1453 +static
1454 +void gssd_free_lgd(struct lustre_gss_data *lgd)
1455 +{
1456 +       gss_buffer_t            token = GSS_C_NO_BUFFER;
1457 +       OM_uint32               maj_stat, min_stat;
1458 +
1459 +       if (lgd->lgd_ctx == GSS_C_NO_CONTEXT)
1460 +               return;
1461 +
1462 +       maj_stat = gss_delete_sec_context(&min_stat, &lgd->lgd_ctx, token);
1463 +}
1464 +
1465 +static
1466 +int construct_service_name(struct clnt_info *clp,
1467 +                           struct lgssd_upcall_data *ud)
1468 +{
1469 +        const int buflen = 256;
1470 +        char name[buflen];
1471 +
1472 +        if (clp->servicename) {
1473 +                free(clp->servicename);
1474 +                clp->servicename = NULL;
1475 +        }
1476 +
1477 +        if (lnet_nid2hostname(ud->nid, name, buflen))
1478 +                return -1;
1479 +
1480 +        clp->servicename = malloc(32 + strlen(name));
1481 +        if (!clp->servicename) {
1482 +                printerr(0, "can't alloc memory\n");
1483 +                return -1;
1484 +        }
1485 +        sprintf(clp->servicename, "%s@%s",
1486 +                ud->svc == LUSTRE_GSS_SVC_MDS ?
1487 +               GSSD_SERVICE_MDS : GSSD_SERVICE_OSS,
1488 +                name);
1489 +        printerr(2, "constructed servicename: %s\n", clp->servicename);
1490 +        return 0;
1491 +}
1492  
1493  /*
1494   * this code uses the userland rpcsec gss library to create a krb5
1495 @@ -668,103 +910,145 @@ int create_auth_rpc_client(struct clnt_i
1496  void
1497  handle_krb5_upcall(struct clnt_info *clp)
1498  {
1499 -       uid_t                   uid;
1500 -       CLIENT                  *rpc_clnt = NULL;
1501 -       AUTH                    *auth = NULL;
1502 -       struct authgss_private_data pd;
1503 -       gss_buffer_desc         token;
1504 +       pid_t                   pid;
1505 +       gss_buffer_desc         token = { 0, NULL };
1506 +       struct lgssd_upcall_data updata;
1507 +       struct lustre_gss_data  lgd;
1508         char                    **credlist = NULL;
1509         char                    **ccname;
1510 +       int                     read_rc;
1511  
1512 -       printerr(1, "handling krb5 upcall\n");
1513 +       printerr(2, "handling krb5 upcall\n");
1514  
1515 -       token.length = 0;
1516 -       token.value = NULL;
1517 -       memset(&pd, 0, sizeof(struct authgss_private_data));
1518 +       memset(&lgd, 0, sizeof(lgd));
1519 +       lgd.lgd_rpc_err = -EPERM; /* default error code */
1520  
1521 -       if (read(clp->krb5_fd, &uid, sizeof(uid)) < sizeof(uid)) {
1522 -               printerr(0, "WARNING: failed reading uid from krb5 "
1523 +       read_rc = read(clp->krb5_fd, &updata, sizeof(updata));
1524 +       if (read_rc < 0) {
1525 +               printerr(0, "WARNING: failed reading from krb5 "
1526                             "upcall pipe: %s\n", strerror(errno));
1527 -               goto out;
1528 +               return;
1529 +       } else if (read_rc != sizeof(updata)) {
1530 +               printerr(0, "upcall data mismatch: length %d, expect %d\n",
1531 +                        read_rc, sizeof(updata));
1532 +
1533 +               /* the sequence number must be the first field. if read >= 4
1534 +                * bytes then we know at least sequence is fine, try to send
1535 +                * error notification nicely.
1536 +                */
1537 +               if (read_rc >= 4)
1538 +                       do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1539 +               return;
1540 +       }
1541 +
1542 +       /* FIXME temporary fix, do this before fork.
1543 +        * in case of errors could have memory leak!!!
1544 +        */
1545 +       if (updata.uid == 0) {
1546 +               if (gssd_get_krb5_machine_cred_list(&credlist)) {
1547 +                       printerr(0, "ERROR: Failed to obtain machine "
1548 +                                   "credentials\n");
1549 +                       do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1550 +                       return;
1551 +               }
1552 +       }
1553 +
1554 +       /* fork child process */
1555 +       pid = fork();
1556 +       if (pid < 0) {
1557 +               printerr(0, "can't fork: %s\n", strerror(errno));
1558 +               do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0);
1559 +               return;
1560 +       } else if (pid > 0) {
1561 +               printerr(2, "forked child process: %d\n", pid);
1562 +               return;
1563 +       }
1564 +
1565 +       printerr(1, "krb5 upcall: seq %u, uid %u, svc %u, nid 0x%llx, obd %s\n",
1566 +                updata.seq, updata.uid, updata.svc, updata.nid, updata.obd);
1567 +
1568 +       if (updata.svc != LUSTRE_GSS_SVC_MDS &&
1569 +           updata.svc != LUSTRE_GSS_SVC_OSS) {
1570 +               printerr(0, "invalid svc %d\n", updata.svc);
1571 +               lgd.lgd_rpc_err = -EPROTO;
1572 +               goto out_return_error;
1573 +       }
1574 +       updata.obd[sizeof(updata.obd)-1] = '\0';
1575 +
1576 +       if (construct_service_name(clp, &updata)) {
1577 +               printerr(0, "failed to construct service name\n");
1578 +               goto out_return_error;
1579         }
1580  
1581 -       if (uid == 0) {
1582 +       if (updata.uid == 0) {
1583                 int success = 0;
1584  
1585                 /*
1586                  * Get a list of credential cache names and try each
1587                  * of them until one works or we've tried them all
1588                  */
1589 +/*
1590                 if (gssd_get_krb5_machine_cred_list(&credlist)) {
1591 -                       printerr(0, "WARNING: Failed to obtain machine "
1592 -                                   "credentials for connection to "
1593 -                                   "server %s\n", clp->servername);
1594 -                               goto out_return_error;
1595 +                       printerr(0, "ERROR: Failed to obtain machine "
1596 +                                   "credentials for %s\n", clp->servicename);
1597 +                       goto out_return_error;
1598                 }
1599 +*/
1600                 for (ccname = credlist; ccname && *ccname; ccname++) {
1601                         gssd_setup_krb5_machine_gss_ccache(*ccname);
1602 -                       if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
1603 -                                                   AUTHTYPE_KRB5)) == 0) {
1604 +                       if ((gssd_create_lgd(clp, &lgd, &updata,
1605 +                                            AUTHTYPE_KRB5)) == 0) {
1606                                 /* Success! */
1607                                 success++;
1608                                 break;
1609                         }
1610                         printerr(2, "WARNING: Failed to create krb5 context "
1611                                     "for user with uid %d with credentials "
1612 -                                   "cache %s for server %s\n",
1613 -                                uid, *ccname, clp->servername);
1614 +                                   "cache %s for service %s\n",
1615 +                                updata.uid, *ccname, clp->servicename);
1616                 }
1617                 gssd_free_krb5_machine_cred_list(credlist);
1618                 if (!success) {
1619 -                       printerr(0, "WARNING: Failed to create krb5 context "
1620 +                       printerr(0, "ERROR: Failed to create krb5 context "
1621                                     "for user with uid %d with any "
1622 -                                   "credentials cache for server %s\n",
1623 -                                uid, clp->servername);
1624 +                                   "credentials cache for service %s\n",
1625 +                                updata.uid, clp->servicename);
1626                         goto out_return_error;
1627                 }
1628         }
1629         else {
1630                 /* Tell krb5 gss which credentials cache to use */
1631 -               gssd_setup_krb5_user_gss_ccache(uid, clp->servername);
1632 +               gssd_setup_krb5_user_gss_ccache(updata.uid, clp->servicename);
1633  
1634 -               if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
1635 -                                                       AUTHTYPE_KRB5)) != 0) {
1636 +               if ((gssd_create_lgd(clp, &lgd, &updata, AUTHTYPE_KRB5)) != 0) {
1637                         printerr(0, "WARNING: Failed to create krb5 context "
1638 -                                   "for user with uid %d for server %s\n",
1639 -                                uid, clp->servername);
1640 +                                   "for user with uid %d for service %s\n",
1641 +                                updata.uid, clp->servicename);
1642                         goto out_return_error;
1643                 }
1644         }
1645  
1646 -       if (!authgss_get_private_data(auth, &pd)) {
1647 -               printerr(0, "WARNING: Failed to obtain authentication "
1648 -                           "data for user with uid %d for server %s\n",
1649 -                        uid, clp->servername);
1650 -               goto out_return_error;
1651 -       }
1652 -
1653 -       if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid)) {
1654 +       if (serialize_context_for_kernel(lgd.lgd_ctx, &token, &krb5oid)) {
1655                 printerr(0, "WARNING: Failed to serialize krb5 context for "
1656 -                           "user with uid %d for server %s\n",
1657 -                        uid, clp->servername);
1658 +                           "user with uid %d for service %s\n",
1659 +                        updata.uid, clp->servicename);
1660                 goto out_return_error;
1661         }
1662  
1663 -       do_downcall(clp->krb5_fd, uid, &pd, &token);
1664 +       printerr(1, "refreshed: %u@%s for %s\n",
1665 +                updata.uid, updata.obd, clp->servicename);
1666 +       do_downcall(clp->krb5_fd, &updata, &lgd, &token);
1667  
1668  out:
1669         if (token.value)
1670                 free(token.value);
1671 -       if (pd.pd_ctx_hndl.length != 0)
1672 -               authgss_free_private_data(&pd);
1673 -       if (auth)
1674 -               AUTH_DESTROY(auth);
1675 -       if (rpc_clnt)
1676 -               clnt_destroy(rpc_clnt);
1677 -       return;
1678 +
1679 +       gssd_free_lgd(&lgd);
1680 +       exit(0); /* i'm child process */
1681  
1682  out_return_error:
1683 -       do_error_downcall(clp->krb5_fd, uid, -1);
1684 +       do_error_downcall(clp->krb5_fd, updata.seq,
1685 +                         lgd.lgd_rpc_err, lgd.lgd_gss_err);
1686         goto out;
1687  }
1688  
1689 @@ -775,6 +1059,7 @@ out_return_error:
1690  void
1691  handle_spkm3_upcall(struct clnt_info *clp)
1692  {
1693 +#if 0
1694         uid_t                   uid;
1695         CLIENT                  *rpc_clnt = NULL;
1696         AUTH                    *auth = NULL;
1697 @@ -826,4 +1111,5 @@ out:
1698  out_return_error:
1699         do_error_downcall(clp->spkm3_fd, uid, -1);
1700         goto out;
1701 +#endif
1702  }
1703 diff -Nrup nfs-utils-1.0.11/utils/gssd/gss_util.c nfs-utils-1.0.11.lustre/utils/gssd/gss_util.c
1704 --- nfs-utils-1.0.11/utils/gssd/gss_util.c      2007-02-21 21:50:03.000000000 -0700
1705 +++ nfs-utils-1.0.11.lustre/utils/gssd/gss_util.c       2007-06-29 12:32:40.000000000 -0600
1706 @@ -87,9 +87,16 @@
1707  #ifdef HAVE_COM_ERR_H
1708  #include <com_err.h>
1709  #endif
1710 +#include "lsupport.h"
1711  
1712  /* Global gssd_credentials handle */
1713 -gss_cred_id_t gssd_creds;
1714 +gss_cred_id_t  gssd_cred_mds;
1715 +gss_cred_id_t  gssd_cred_oss;
1716 +int            gssd_cred_mds_valid = 0;
1717 +int            gssd_cred_oss_valid = 0;
1718 +
1719 +char *mds_local_realm = NULL;
1720 +char *oss_local_realm = NULL;
1721  
1722  gss_OID g_mechOid = GSS_C_NULL_OID;;
1723  
1724 @@ -183,15 +190,56 @@ pgsserr(char *msg, u_int32_t maj_stat, u
1725         display_status_2(msg, maj_stat, min_stat, mech);
1726  }
1727  
1728 -int
1729 -gssd_acquire_cred(char *server_name)
1730 +static
1731 +int extract_realm_name(gss_buffer_desc *name, char **realm)
1732 +{
1733 +        char *sname, *c;
1734 +       int   rc = 0;
1735 +
1736 +        sname = malloc(name->length + 1);
1737 +        if (!sname) {
1738 +                printerr(0, "out of memory\n");
1739 +                return -ENOMEM;
1740 +        }
1741 +
1742 +        memcpy(sname, name->value, name->length);
1743 +        sname[name->length] = '\0';
1744 +        printerr(1, "service principal: %s\n", sname);
1745 +
1746 +        c = strchr(sname, '@');
1747 +        if (!c) {
1748 +               printerr(2, "no realm found in principal, use default\n");
1749 +               *realm = strdup(this_realm);
1750 +                if (!*realm) {
1751 +                        printerr(0, "failed to duplicate default realm\n");
1752 +                        rc = -ENOMEM;
1753 +                }
1754 +        } else {
1755 +                c++;
1756 +                *realm = strdup(c);
1757 +                if (!*realm) {
1758 +                        printerr(0, "failed to duplicated realm\n");
1759 +                        rc = -ENOMEM;
1760 +                }
1761 +        }
1762 +        free(sname);
1763 +
1764 +        return rc;
1765 +}
1766 +
1767 +static
1768 +int gssd_acquire_cred(char *server_name, gss_cred_id_t *cred,
1769 +                     char **local_realm, int *valid)
1770  {
1771         gss_buffer_desc name;
1772         gss_name_t target_name;
1773         u_int32_t maj_stat, min_stat;
1774         u_int32_t ignore_maj_stat, ignore_min_stat;
1775 +       gss_OID name_type;
1776         gss_buffer_desc pbuf;
1777  
1778 +       *valid = 0;
1779 +
1780         name.value = (void *)server_name;
1781         name.length = strlen(server_name);
1782  
1783 @@ -201,12 +249,20 @@ gssd_acquire_cred(char *server_name)
1784  
1785         if (maj_stat != GSS_S_COMPLETE) {
1786                 pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid);
1787 -               return (FALSE);
1788 +               return -1;
1789 +       }
1790 +
1791 +       maj_stat = gss_display_name(&min_stat, target_name, &name, &name_type);
1792 +       if (maj_stat != GSS_S_COMPLETE) {
1793 +               pgsserr(0, maj_stat, min_stat, g_mechOid);
1794 +               return -1;
1795         }
1796 +       if (extract_realm_name(&name, local_realm))
1797 +               return -1;
1798  
1799         maj_stat = gss_acquire_cred(&min_stat, target_name, 0,
1800                         GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
1801 -                       &gssd_creds, NULL, NULL);
1802 +                       cred, NULL, NULL);
1803  
1804         if (maj_stat != GSS_S_COMPLETE) {
1805                 pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid);
1806 @@ -218,11 +274,67 @@ gssd_acquire_cred(char *server_name)
1807                         ignore_maj_stat = gss_release_buffer(&ignore_min_stat,
1808                                                              &pbuf);
1809                 }
1810 -       }
1811 +       } else
1812 +               *valid = 1;
1813  
1814         ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name);
1815  
1816 -       return (maj_stat == GSS_S_COMPLETE);
1817 +       if (maj_stat != GSS_S_COMPLETE)
1818 +               return -1;
1819 +       return 0;
1820 +}
1821 +
1822 +int gssd_prepare_creds(int must_srv_mds, int must_srv_oss)
1823 +{
1824 +        if (gssd_acquire_cred(GSSD_SERVICE_MDS, &gssd_cred_mds,
1825 +                              &mds_local_realm, &gssd_cred_mds_valid)) {
1826 +                if (must_srv_mds)
1827 +                        return -1;
1828 +        }
1829 +
1830 +        if (gssd_acquire_cred(GSSD_SERVICE_OSS, &gssd_cred_oss,
1831 +                              &oss_local_realm, &gssd_cred_oss_valid)) {
1832 +                if (must_srv_oss)
1833 +                        return -1;
1834 +        }
1835 +
1836 +        if (!gssd_cred_mds_valid && !gssd_cred_oss_valid) {
1837 +                printerr(0, "can't obtain both mds & oss creds, exit\n");
1838 +                return -1;
1839 +        }
1840 +
1841 +       if (gssd_cred_mds_valid)
1842 +               printerr(0, "Ready to serve Lustre MDS in realm %s\n",
1843 +                        mds_local_realm ? mds_local_realm : "N/A");
1844 +       if (gssd_cred_oss_valid)
1845 +               printerr(0, "Ready to serve Lustre OSS in realm %s\n",
1846 +                        oss_local_realm ? oss_local_realm : "N/A");
1847 +
1848 +        return 0;
1849 +}
1850 +
1851 +gss_cred_id_t gssd_select_svc_cred(int lustre_svc)
1852 +{
1853 +        switch (lustre_svc) {
1854 +        case LUSTRE_GSS_SVC_MDS:
1855 +                if (!gssd_cred_mds_valid) {
1856 +                        printerr(0, "ERROR: service cred for mds not ready\n");
1857 +                        return NULL;
1858 +                }
1859 +               printerr(2, "select mds service cred\n");
1860 +                return gssd_cred_mds;
1861 +        case LUSTRE_GSS_SVC_OSS:
1862 +                if (!gssd_cred_oss_valid) {
1863 +                        printerr(0, "ERROR: service cred for oss not ready\n");
1864 +                        return NULL;
1865 +                }
1866 +               printerr(2, "select oss service cred\n");
1867 +                return gssd_cred_oss;
1868 +        default:
1869 +                printerr(0, "ERROR: invalid lustre svc id %d\n", lustre_svc);
1870 +        }
1871 +
1872 +        return NULL;
1873  }
1874  
1875  int gssd_check_mechs(void)
1876 @@ -249,3 +361,42 @@ out:
1877         return retval;
1878  }
1879  
1880 +/*********************************
1881 + * FIXME should be in krb5_util.c
1882 + *********************************/
1883 +
1884 +#include "krb5_util.h"
1885 +
1886 +/* realm of this node */
1887 +char *this_realm = NULL;
1888 +
1889 +int gssd_get_local_realm(void)
1890 +{
1891 +       krb5_context context = NULL;
1892 +       krb5_error_code code;
1893 +       int retval = -1;
1894 +
1895 +       if (this_realm != NULL)
1896 +               return 0;
1897 +
1898 +       code = krb5_init_context(&context);
1899 +       if (code) {
1900 +               printerr(0, "ERROR: get default realm: init ctx: %s\n",
1901 +                        error_message(code));
1902 +               goto out;
1903 +       }
1904 +
1905 +       code = krb5_get_default_realm(context, &this_realm);
1906 +       if (code) {
1907 +               printerr(0, "ERROR: get default realm: %s\n",
1908 +                        error_message(code));
1909 +               goto out;
1910 +       }
1911 +       retval = 0;
1912 +
1913 +       printerr(1, "Local realm: %s\n", this_realm);
1914 +out:
1915 +       krb5_free_context(context);
1916 +       return retval;
1917 +}
1918 +
1919 diff -Nrup nfs-utils-1.0.11/utils/gssd/gss_util.h nfs-utils-1.0.11.lustre/utils/gssd/gss_util.h
1920 --- nfs-utils-1.0.11/utils/gssd/gss_util.h      2007-02-21 21:50:03.000000000 -0700
1921 +++ nfs-utils-1.0.11.lustre/utils/gssd/gss_util.h       2007-06-29 12:32:41.000000000 -0600
1922 @@ -32,14 +32,14 @@
1923  #define _GSS_UTIL_H_
1924  
1925  #include <stdlib.h>
1926 -#include <rpc/rpc.h>
1927  #include "write_bytes.h"
1928  
1929 +char *this_realm;
1930  extern gss_cred_id_t   gssd_creds;
1931  
1932 -int gssd_acquire_cred(char *server_name);
1933  void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat,
1934         const gss_OID mech);
1935  int gssd_check_mechs(void);
1936 +int gssd_get_local_realm(void);
1937  
1938  #endif /* _GSS_UTIL_H_ */
1939 diff -Nrup nfs-utils-1.0.11/utils/gssd/krb5_util.c nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.c
1940 --- nfs-utils-1.0.11/utils/gssd/krb5_util.c     2007-06-29 12:28:01.000000000 -0600
1941 +++ nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.c      2007-06-29 12:32:42.000000000 -0600
1942 @@ -99,12 +99,15 @@
1943  #include <rpc/rpc.h>
1944  #include <sys/types.h>
1945  #include <sys/stat.h>
1946 +#include <sys/utsname.h>
1947  #include <sys/socket.h>
1948  #include <arpa/inet.h>
1949  
1950 +#include <unistd.h>
1951  #include <stdio.h>
1952  #include <stdlib.h>
1953  #include <string.h>
1954 +#include <netdb.h>
1955  #include <dirent.h>
1956  #include <fcntl.h>
1957  #include <errno.h>
1958 @@ -114,7 +117,6 @@
1959  #include <gssapi/gssapi_krb5.h>
1960  #endif
1961  #include <krb5.h>
1962 -#include <rpc/auth_gss.h>
1963  
1964  #include "gssd.h"
1965  #include "err_util.h"
1966 @@ -129,6 +131,9 @@ struct gssd_k5_kt_princ *gssd_k5_kt_prin
1967  int num_krb5_enctypes = 0;
1968  krb5_enctype *krb5_enctypes = NULL;
1969  
1970 +/* credential expire time in advance */
1971 +unsigned long machine_cred_expire_advance = 300; /* 5 mins */
1972 +
1973  /*==========================*/
1974  /*===  Internal routines ===*/
1975  /*==========================*/
1976 @@ -137,11 +142,55 @@ static int select_krb5_ccache(const stru
1977  static int gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d);
1978  static int gssd_get_single_krb5_cred(krb5_context context,
1979                 krb5_keytab kt, struct gssd_k5_kt_princ *ple);
1980 -static int gssd_have_realm_ple(void *realm);
1981  static int gssd_process_krb5_keytab(krb5_context context, krb5_keytab kt,
1982                 char *kt_name);
1983  
1984  /*
1985 + * convenient macros, these perhaps need further cleanup
1986 + */
1987 +#ifdef HAVE_KRB5
1988 +
1989 +#define KEYTAB_ENTRY_MATCH(kte, name)                                         \
1990 +       (                                                                      \
1991 +        (kte).principal->data[0].length == (sizeof(name)-1) &&                \
1992 +        strncmp((kte).principal->data[0].data, (name), sizeof(name)-1) == 0   \
1993 +       )
1994 +#define KRB5_FREE_UNPARSED_NAME(ctx, name)                                    \
1995 +               krb5_free_unparsed_name((ctx), (name));
1996 +#define KRB5_STRDUP(str)                                                      \
1997 +               strndup((str).data, (str).length)
1998 +#define KRB5_STRCMP(str, name)                                                \
1999 +       (                                                                      \
2000 +        (str)->length != strlen(name) ||                                      \
2001 +        strncmp((str)->data, (name), (str)->length) != 0                      \
2002 +       )
2003 +#define KRB5_STRCASECMP(str, name)                                            \
2004 +       (                                                                      \
2005 +        (str)->length != strlen(name) ||                                      \
2006 +        strncasecmp((str)->data, (name), (str)->length) != 0                  \
2007 +       )
2008 +
2009 +#else /* !HAVE_KRB5 */
2010 +
2011 +#define KEYTAB_ENTRY_MATCH(kte, name)                                         \
2012 +       (                                                                      \
2013 +        strlen((kte).principal->name.name_string.val[0]) ==                   \
2014 +        (sizeof(name)-1) &&                                                   \
2015 +        strncmp(kte.principal->name.name_string.val[0], (name),               \
2016 +                sizeof(name)-1) == 0                                          \
2017 +       )
2018 +#define KRB5_FREE_UNPARSED_NAME(ctx, name)                                    \
2019 +               free(pname);
2020 +#define KRB5_STRDUP(str)                                                      \
2021 +               strdup(str)
2022 +#define KRB5_STRCMP(str, name)                                                \
2023 +               strcmp((str), (name))
2024 +#define KRB5_STRCASECMP(str, name)                                            \
2025 +               strcmp((str), (name))
2026 +
2027 +#endif /* HAVE_KRB5 */
2028 +
2029 +/*
2030   * Called from the scandir function to weed out potential krb5
2031   * credentials cache files
2032   *
2033 @@ -288,7 +337,7 @@ gssd_get_single_krb5_cred(krb5_context c
2034  
2035         memset(&my_creds, 0, sizeof(my_creds));
2036  
2037 -       if (ple->ccname && ple->endtime > now) {
2038 +       if (ple->ccname && ple->endtime > now + machine_cred_expire_advance) {
2039                 printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
2040                          ple->ccname, ple->endtime);
2041                 code = 0;
2042 @@ -308,6 +357,12 @@ gssd_get_single_krb5_cred(krb5_context c
2043         /* set a short lifetime (for debugging only!) */
2044         printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
2045         krb5_get_init_creds_opt_set_tkt_life(&options, 5*60);
2046 +#else
2047 +       /* FIXME try to get the ticket with lifetime as long as possible,
2048 +        * to work around ticket-expiry + recovery problem in cmd3-11
2049 +        * remove this!!!
2050 +        */
2051 +       krb5_get_init_creds_opt_set_tkt_life(&options, 30*24*60*60);
2052  #endif
2053          if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ,
2054                                           kt, 0, NULL, &options))) {
2055 @@ -319,11 +374,7 @@ gssd_get_single_krb5_cred(krb5_context c
2056                             "principal '%s' from keytab '%s'\n",
2057                          error_message(code),
2058                          pname ? pname : "<unparsable>", kt_name);
2059 -#ifdef HAVE_KRB5
2060 -               if (pname) krb5_free_unparsed_name(context, pname);
2061 -#else
2062 -               if (pname) free(pname);
2063 -#endif
2064 +               if (pname) KRB5_FREE_UNPARSED_NAME(context, pname);
2065                 goto out;
2066         }
2067  
2068 @@ -372,15 +423,7 @@ gssd_get_single_krb5_cred(krb5_context c
2069         return (code);
2070  }
2071  
2072 -/*
2073 - * Determine if we already have a ple for the given realm
2074 - *
2075 - * Returns:
2076 - *     0 => no ple found for given realm
2077 - *     1 => found ple for given realm
2078 - */
2079 -static int
2080 -gssd_have_realm_ple(void *r)
2081 +static struct gssd_k5_kt_princ * gssd_get_realm_ple(void *r)
2082  {
2083         struct gssd_k5_kt_princ *ple;
2084  #ifdef HAVE_KRB5
2085 @@ -390,18 +433,76 @@ gssd_have_realm_ple(void *r)
2086  #endif
2087  
2088         for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
2089 -#ifdef HAVE_KRB5
2090 -               if ((realm->length == strlen(ple->realm)) &&
2091 -                   (strncmp(realm->data, ple->realm, realm->length) == 0)) {
2092 -#else
2093 -               if (strcmp(realm, ple->realm) == 0) {
2094 -#endif
2095 -                   return 1;
2096 -               }
2097 +               if (KRB5_STRCMP(realm, ple->realm) == 0)
2098 +                   return ple;
2099 +       }
2100 +       return NULL;
2101 +}
2102 +
2103 +static void gssd_free_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
2104 +{
2105 +       if (ple->princ)
2106 +               krb5_free_principal(kctx, ple->princ);
2107 +       if (ple->realm)
2108 +               free(ple->realm);
2109 +       if (ple->ccname)
2110 +               free(ple->ccname);
2111 +       free(ple);
2112 +}
2113 +
2114 +static int gssd_remove_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple)
2115 +{
2116 +       struct gssd_k5_kt_princ **prev = &gssd_k5_kt_princ_list;
2117 +       struct gssd_k5_kt_princ  *ent = gssd_k5_kt_princ_list;
2118 +
2119 +       for (; ent; prev = &ent->next, ent = ent->next) {
2120 +               if (ent != ple)
2121 +                       continue;
2122 +
2123 +               *prev = ent->next;
2124 +               gssd_free_ple(kctx, ent);
2125 +               return 1;
2126         }
2127         return 0;
2128  }
2129  
2130 +static
2131 +struct gssd_k5_kt_princ *gssd_create_ple(krb5_context kctx,
2132 +                                        krb5_principal principal)
2133 +{
2134 +       struct gssd_k5_kt_princ *ple;
2135 +       krb5_error_code          code;
2136 +
2137 +       ple = malloc(sizeof(*ple));
2138 +       if (ple == NULL) {
2139 +               printerr(0, "ERROR: could not allocate storage "
2140 +                           "for principal list entry\n");
2141 +               return NULL;
2142 +       }
2143 +
2144 +       memset(ple, 0, sizeof(*ple));
2145 +
2146 +       ple->realm = KRB5_STRDUP(principal->realm);
2147 +       if (ple->realm == NULL) {
2148 +               printerr(0, "ERROR: not enough memory while copying realm to "
2149 +                           "principal list entry\n");
2150 +               goto err_free;
2151 +       }
2152 +
2153 +       code = krb5_copy_principal(kctx, principal, &ple->princ);
2154 +       if (code) {
2155 +               printerr(0, "ERROR: %s while copying principal "
2156 +                           "to principal list entry\n",
2157 +                        error_message(code));
2158 +               goto err_free;
2159 +       }
2160 +
2161 +       return ple;
2162 +err_free:
2163 +       gssd_free_ple(kctx, ple);
2164 +       return NULL;
2165 +}
2166 +
2167  /*
2168   * Process the given keytab file and create a list of principals we
2169   * might use to perform mount operations.
2170 @@ -445,82 +546,106 @@ gssd_process_krb5_keytab(krb5_context co
2171                 }
2172                 printerr(2, "Processing keytab entry for principal '%s'\n",
2173                          pname);
2174 -#ifdef HAVE_KRB5
2175 -               if ( (kte.principal->data[0].length == GSSD_SERVICE_NAME_LEN) &&
2176 -                    (strncmp(kte.principal->data[0].data, GSSD_SERVICE_NAME,
2177 -                             GSSD_SERVICE_NAME_LEN) == 0) &&
2178 -#else
2179 -               if ( (strlen(kte.principal->name.name_string.val[0]) == GSSD_SERVICE_NAME_LEN) &&
2180 -                    (strncmp(kte.principal->name.name_string.val[0], GSSD_SERVICE_NAME,
2181 -                             GSSD_SERVICE_NAME_LEN) == 0) &&
2182 -                             
2183 -#endif
2184 -                    (!gssd_have_realm_ple((void *)&kte.principal->realm)) ) {
2185 -                       printerr(2, "We will use this entry (%s)\n", pname);
2186 -                       ple = malloc(sizeof(struct gssd_k5_kt_princ));
2187 -                       if (ple == NULL) {
2188 -                               printerr(0, "ERROR: could not allocate storage "
2189 -                                           "for principal list entry\n");
2190 -#ifdef HAVE_KRB5
2191 -                               krb5_free_unparsed_name(context, pname);
2192 -#else
2193 -                               free(pname);
2194 -#endif
2195 -                               retval = ENOMEM;
2196 -                               goto out;
2197 -                       }
2198 -                       /* These will be filled in later */
2199 -                       ple->next = NULL;
2200 -                       ple->ccname = NULL;
2201 -                       ple->endtime = 0;
2202 -                       if ((ple->realm =
2203 -#ifdef HAVE_KRB5
2204 -                               strndup(kte.principal->realm.data,
2205 -                                       kte.principal->realm.length))
2206 -#else
2207 -                               strdup(kte.principal->realm))
2208 -#endif
2209 -                                       == NULL) {
2210 -                               printerr(0, "ERROR: %s while copying realm to "
2211 -                                           "principal list entry\n",
2212 -                                        "not enough memory");
2213 -#ifdef HAVE_KRB5
2214 -                               krb5_free_unparsed_name(context, pname);
2215 -#else
2216 -                               free(pname);
2217 -#endif
2218 -                               retval = ENOMEM;
2219 -                               goto out;
2220 -                       }
2221 -                       if ((code = krb5_copy_principal(context,
2222 -                                       kte.principal, &ple->princ))) {
2223 -                               printerr(0, "ERROR: %s while copying principal "
2224 -                                           "to principal list entry\n",
2225 -                                       error_message(code));
2226 -#ifdef HAVE_KRB5
2227 -                               krb5_free_unparsed_name(context, pname);
2228 -#else
2229 -                               free(pname);
2230 -#endif
2231 -                               retval = code;
2232 -                               goto out;
2233 -                       }
2234 -                       if (gssd_k5_kt_princ_list == NULL)
2235 -                               gssd_k5_kt_princ_list = ple;
2236 -                       else {
2237 -                               ple->next = gssd_k5_kt_princ_list;
2238 -                               gssd_k5_kt_princ_list = ple;
2239 +
2240 +               /* mds service entry:
2241 +                *   - hostname and realm should match this node
2242 +                *   - replace existing non-mds entry of this realm
2243 +                */
2244 +               if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS)) {
2245 +                       krb5_principal princ = kte.principal;
2246 +                       krb5_data *princ_host;
2247 +                       struct utsname utsbuf;
2248 +                       struct hostent *host;
2249 +
2250 +                       if (KRB5_STRCASECMP(krb5_princ_realm(context, princ),
2251 +                                           this_realm) != 0) {
2252 +                               printerr(2, "alien mds service entry, skip\n");
2253 +                               goto next;
2254 +                       }
2255 +
2256 +                       princ_host = krb5_princ_component(context, princ, 1);
2257 +                       if (princ_host == NULL) {
2258 +                               printerr(2, "mds service entry: no hostname in "
2259 +                                        "principal, skip\n");
2260 +                               goto next;
2261 +                       }
2262 +
2263 +                       if (uname(&utsbuf)) {
2264 +                               printerr(2, "mds service entry: unable to get "
2265 +                                        "UTS name, skip\n");
2266 +                               goto next;
2267 +                       }
2268 +                       host = gethostbyname(utsbuf.nodename);
2269 +                       if (host == NULL) {
2270 +                               printerr(2, "mds service entry: unable to get "
2271 +                                        "local hostname, skip\n");
2272 +                               goto next;
2273 +                       }
2274 +
2275 +                       if (KRB5_STRCASECMP(princ_host, host->h_name) != 0) {
2276 +                               printerr(2, "mds service entry: hostname "
2277 +                                        "doesn't match: %s - %.*s, skip\n",
2278 +                                        host->h_name,
2279 +                                        princ_host->length, princ_host->data);
2280 +                               goto next;
2281 +                       }
2282 +
2283 +                       ple = gssd_get_realm_ple((void *)&kte.principal->realm);
2284 +                       if (ple) {
2285 +                               if (ple->fl_mds) {
2286 +                                       printerr(2,"mds service entry: found a"
2287 +                                                "duplicated one, it's like a "
2288 +                                                "mis-configuration, skip\n");
2289 +                                       goto next;
2290 +                               }
2291 +
2292 +                               gssd_remove_ple(context, ple);
2293 +                               printerr(2, "mds service entry: replace an "
2294 +                                        "existed non-mds one\n");
2295 +                       }
2296 +               } else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME)) {
2297 +                       ple = gssd_get_realm_ple((void *)&kte.principal->realm);
2298 +                       if (ple) {
2299 +                               if (ple->fl_mds || ple->fl_root) {
2300 +                                       printerr(2, "root entry: found a "
2301 +                                                "existed %s entry, skip\n",
2302 +                                                ple->fl_mds ? "mds" : "root");
2303 +                                       goto next;
2304 +                               }
2305 +
2306 +                               gssd_remove_ple(context, ple);
2307 +                               printerr(2, "root entry: replace an existed "
2308 +                                        "non-mds non-root one\n");
2309                         }
2310 -               }
2311 -               else {
2312 +               } else {
2313                         printerr(2, "We will NOT use this entry (%s)\n",
2314                                 pname);
2315 +                       goto next;
2316                 }
2317 -#ifdef HAVE_KRB5
2318 -               krb5_free_unparsed_name(context, pname);
2319 -#else
2320 -               free(pname);
2321 -#endif
2322 +
2323 +               /* construct ple */
2324 +               printerr(2, "We will use this entry (%s)\n", pname);
2325 +               ple = gssd_create_ple(context, kte.principal);
2326 +               if (ple == NULL) {
2327 +                       KRB5_FREE_UNPARSED_NAME(context, pname);
2328 +                       goto out;
2329 +               }
2330 +
2331 +               /* add proper flags */
2332 +               if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS))
2333 +                       ple->fl_mds = 1;
2334 +               else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME))
2335 +                       ple->fl_root = 1;
2336 +
2337 +               /* enqueue */
2338 +               if (gssd_k5_kt_princ_list == NULL)
2339 +                       gssd_k5_kt_princ_list = ple;
2340 +               else {
2341 +                       ple->next = gssd_k5_kt_princ_list;
2342 +                       gssd_k5_kt_princ_list = ple;
2343 +               }
2344 + next:
2345 +               KRB5_FREE_UNPARSED_NAME(context, pname);
2346         }
2347  
2348         if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) {
2349 @@ -636,6 +761,7 @@ gssd_setup_krb5_user_gss_ccache(uid_t ui
2350         printerr(2, "getting credentials for client with uid %u for "
2351                     "server %s\n", uid, servername);
2352         memset(buf, 0, sizeof(buf));
2353 +
2354         if (gssd_find_existing_krb5_ccache(uid, &d)) {
2355                 snprintf(buf, sizeof(buf), "FILE:%s/%s",
2356                         ccachedir, d->d_name);
2357 @@ -696,7 +822,7 @@ gssd_refresh_krb5_machine_creds(void)
2358                 goto out;
2359         }
2360  
2361 -       printerr(1, "Using keytab file '%s'\n", keytabfile);
2362 +       printerr(2, "Using keytab file '%s'\n", keytabfile);
2363  
2364         if ((code = krb5_kt_resolve(context, keytabfile, &kt))) {
2365                 printerr(0, "ERROR: %s while resolving keytab '%s'\n",
2366 @@ -711,12 +837,12 @@ gssd_refresh_krb5_machine_creds(void)
2367                 if (gssd_k5_kt_princ_list == NULL) {
2368                         printerr(0, "ERROR: No usable keytab entries found in "
2369                                     "keytab '%s'\n", keytabfile);
2370 -                       printerr(0, "Do you have a valid keytab entry for "
2371 -                                   "%s/<your.host>@<YOUR.REALM> in "
2372 +                       printerr(0, "You must have a valid keytab entry for "
2373 +                                   "%s/<your.host>@<YOUR.REALM> on MDT nodes, "
2374 +                                   "and %s@<YOUR.REALM> on client nodes, in "
2375                                     "keytab file %s ?\n",
2376 -                                   GSSD_SERVICE_NAME, keytabfile);
2377 -                       printerr(0, "Continuing without (machine) credentials "
2378 -                                   "- nfs4 mounts with Kerberos will fail\n");
2379 +                                   GSSD_SERVICE_MDS, LUSTRE_ROOT_NAME,
2380 +                                   keytabfile);
2381                 }
2382         }
2383  
2384 @@ -866,6 +992,7 @@ gssd_destroy_krb5_machine_creds(void)
2385         krb5_free_context(context);
2386  }
2387  
2388 +#if 0
2389  #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
2390  /*
2391   * this routine obtains a credentials handle via gss_acquire_cred()
2392 @@ -921,7 +1048,9 @@ limit_krb5_enctypes(struct rpc_gss_sec *
2393         return 0;
2394  }
2395  #endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
2396 +#endif
2397  
2398 +#if 0
2399  /*
2400   * Obtain supported enctypes from kernel.
2401   * Set defaults if info is not available.
2402 @@ -988,3 +1117,4 @@ gssd_obtain_kernel_krb5_info(void)
2403                          code);
2404         }
2405  }
2406 +#endif
2407 diff -Nrup nfs-utils-1.0.11/utils/gssd/krb5_util.h nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.h
2408 --- nfs-utils-1.0.11/utils/gssd/krb5_util.h     2007-06-29 12:28:01.000000000 -0600
2409 +++ nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.h      2007-06-29 12:32:42.000000000 -0600
2410 @@ -10,6 +10,8 @@
2411  struct gssd_k5_kt_princ {
2412         struct gssd_k5_kt_princ *next;
2413         krb5_principal princ;
2414 +       unsigned int    fl_root:1,
2415 +                       fl_mds:1;
2416         char *ccname;
2417         char *realm;
2418         krb5_timestamp endtime;
2419 @@ -25,8 +27,4 @@ void gssd_destroy_krb5_machine_creds(voi
2420  void gssd_obtain_kernel_krb5_info(void);
2421  
2422  
2423 -#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
2424 -int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
2425 -#endif
2426 -
2427  #endif /* KRB5_UTIL_H */
2428 diff -Nrup nfs-utils-1.0.11/utils/gssd/lsupport.c nfs-utils-1.0.11.lustre/utils/gssd/lsupport.c
2429 --- nfs-utils-1.0.11/utils/gssd/lsupport.c      1969-12-31 17:00:00.000000000 -0700
2430 +++ nfs-utils-1.0.11.lustre/utils/gssd/lsupport.c       2007-06-29 12:32:43.000000000 -0600
2431 @@ -0,0 +1,787 @@
2432 +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2433 + * vim:expandtab:shiftwidth=8:tabstop=8:
2434 + *
2435 + *  Copyright (c) 2005 Cluster File Systems, Inc.
2436 + *
2437 + *   This file is part of Lustre, http://www.lustre.org.
2438 + *
2439 + *   Lustre is free software; you can redistribute it and/or
2440 + *   modify it under the terms of version 2 of the GNU General Public
2441 + *   License as published by the Free Software Foundation.
2442 + *
2443 + *   Lustre is distributed in the hope that it will be useful,
2444 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
2445 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2446 + *   GNU General Public License for more details.
2447 + *
2448 + *   You should have received a copy of the GNU General Public License
2449 + *   along with Lustre; if not, write to the Free Software
2450 + *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2451 + */
2452 +
2453 +#ifndef _GNU_SOURCE
2454 +#define _GNU_SOURCE
2455 +#endif
2456 +#include "config.h"
2457 +#include <sys/param.h>
2458 +#include <sys/utsname.h>
2459 +#include <sys/stat.h>
2460 +#include <sys/socket.h>
2461 +#include <arpa/inet.h>
2462 +#include <sys/types.h>
2463 +#include <sys/ipc.h>
2464 +#include <sys/sem.h>
2465 +
2466 +#include <stdio.h>
2467 +#include <stdlib.h>
2468 +#include <pwd.h>
2469 +#include <grp.h>
2470 +#include <string.h>
2471 +#include <dirent.h>
2472 +#include <poll.h>
2473 +#include <fcntl.h>
2474 +#include <signal.h>
2475 +#include <unistd.h>
2476 +#include <errno.h>
2477 +#include <assert.h>
2478 +#ifdef HAVE_GETHOSTBYNAME
2479 +# include <netdb.h>
2480 +#endif
2481 +
2482 +#ifdef _NEW_BUILD_
2483 +# include "lgss_utils.h"
2484 +#else
2485 +# include "err_util.h"
2486 +# include "gssd.h"
2487 +#endif
2488 +#include "lsupport.h"
2489 +
2490 +/****************************************
2491 + * exclusive startup                    *
2492 + ****************************************/
2493 +
2494 +static struct __sem_s {
2495 +        char           *name;
2496 +        key_t           sem_key;
2497 +        int             sem_id;
2498 +} sems[2] = {
2499 +        [GSSD_CLI] = { "client",  0x3a92d473, 0 },
2500 +        [GSSD_SVC] = { "server",  0x3b92d473, 0 },
2501 +};
2502 +
2503 +void gssd_init_unique(int type)
2504 +{
2505 +        struct __sem_s *sem = &sems[type];
2506 +        struct sembuf   sembuf;
2507 +
2508 +        assert(type == GSSD_CLI || type == GSSD_SVC);
2509 +
2510 +again:
2511 +        sem->sem_id = semget(sem->sem_key, 1, IPC_CREAT | IPC_EXCL | 0700);
2512 +        if (sem->sem_id == -1) {
2513 +                if (errno != EEXIST) {
2514 +                        printerr(0, "Create sem: %s\n", strerror(errno));
2515 +                        exit(-1);
2516 +                }
2517 +
2518 +                /* already exist. Note there's still a small window racing
2519 +                 * with other processes, due to the stupid semaphore semantics.
2520 +                 */
2521 +                sem->sem_id = semget(sem->sem_key, 0, 0700);
2522 +                if (sem->sem_id == -1) {
2523 +                        if (errno == ENOENT) {
2524 +                                printerr(0, "another instance just exit, "
2525 +                                         "try again\n");
2526 +                                goto again;
2527 +                        }
2528 +
2529 +                        printerr(0, "Obtain sem: %s\n", strerror(errno));
2530 +                        exit(-1);
2531 +                }
2532 +        } else {
2533 +                int val = 1;
2534 +
2535 +                if (semctl(sem->sem_id, 0, SETVAL, val) == -1) {
2536 +                        printerr(0, "Initialize sem: %s\n",
2537 +                                 strerror(errno));
2538 +                        exit(-1);
2539 +                }
2540 +        }
2541 +
2542 +        sembuf.sem_num = 0;
2543 +        sembuf.sem_op = -1;
2544 +        sembuf.sem_flg = IPC_NOWAIT | SEM_UNDO;
2545 +
2546 +        if (semop(sem->sem_id, &sembuf, 1) != 0) {
2547 +                if (errno == EAGAIN) {
2548 +                        printerr(0, "Another instance is running, exit\n");
2549 +                        exit(0);
2550 +                }
2551 +                printerr(0, "Grab sem: %s\n", strerror(errno));
2552 +                exit(0);
2553 +        }
2554 +
2555 +        printerr(2, "Successfully created %s global identity\n", sem->name);
2556 +}
2557 +
2558 +void gssd_exit_unique(int type)
2559 +{
2560 +        assert(type == GSSD_CLI || type == GSSD_SVC);
2561 +
2562 +        /*
2563 +         * do nothing. we can't remove the sem here, otherwise the race
2564 +         * window would be much bigger. So it's sad we have to leave the
2565 +         * sem in the system forever.
2566 +         */
2567 +}
2568 +
2569 +/****************************************
2570 + * client side resolvation:             *
2571 + *    lnd/netid/nid => hostname         *
2572 + ****************************************/
2573 +
2574 +char gethostname_ex[PATH_MAX] = GSSD_DEFAULT_GETHOSTNAME_EX;
2575 +
2576 +typedef int lnd_nid2hostname_t(char *lnd, uint32_t net, uint32_t addr,
2577 +                               char *buf, int buflen);
2578 +
2579 +/* FIXME what about IPv6? */
2580 +static
2581 +int ipv4_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
2582 +                      char *buf, int buflen)
2583 +{
2584 +        struct hostent  *ent;
2585 +
2586 +        addr = htonl(addr);
2587 +        ent = gethostbyaddr(&addr, sizeof(addr), AF_INET);
2588 +        if (!ent) {
2589 +                printerr(0, "%s: can't resolve 0x%x\n", lnd, addr);
2590 +                return -1;
2591 +        }
2592 +        if (strlen(ent->h_name) >= buflen) {
2593 +                printerr(0, "%s: name too long: %s\n", lnd, ent->h_name);
2594 +                return -1;
2595 +        }
2596 +        strcpy(buf, ent->h_name);
2597 +
2598 +        printerr(2, "%s: net 0x%x, addr 0x%x => %s\n",
2599 +                 lnd, net, addr, buf);
2600 +        return 0;
2601 +}
2602 +
2603 +static
2604 +int lolnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
2605 +                       char *buf, int buflen)
2606 +{
2607 +        struct utsname   uts;
2608 +        struct hostent  *ent;
2609 +
2610 +        if (addr) {
2611 +                printerr(0, "%s: addr is 0x%x, we expect 0\n", lnd, addr);
2612 +                return -1;
2613 +        }
2614 +
2615 +        if (uname(&uts)) {
2616 +                printerr(0, "%s: failed obtain local machine name\n", lnd);
2617 +                return -1;
2618 +        }
2619 +
2620 +        ent = gethostbyname(uts.nodename);
2621 +        if (!ent) {
2622 +                printerr(0, "%s: failed obtain canonical name of %s\n",
2623 +                         lnd, uts.nodename);
2624 +                return -1;
2625 +        }
2626 +
2627 +        if (strlen(ent->h_name) >= buflen) {
2628 +                printerr(0, "%s: name too long: %s\n", lnd, ent->h_name);
2629 +                return -1;
2630 +        }
2631 +        strcpy(buf, ent->h_name);
2632 +
2633 +        printerr(3, "%s: addr 0x%x => %s\n", lnd, addr, buf);
2634 +        return 0;
2635 +}
2636 +
2637 +static int is_space(char c)
2638 +{
2639 +        return (c == ' ' || c == '\t' || c == '\n');
2640 +}
2641 +
2642 +static
2643 +int external_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
2644 +                          char *namebuf, int namebuflen)
2645 +{
2646 +        const int bufsize = PATH_MAX + 256;
2647 +        char buf[bufsize], *head, *tail;
2648 +        FILE *fghn;
2649 +
2650 +        sprintf(buf, "%s %s 0x%x 0x%x", gethostname_ex, lnd, net, addr);
2651 +        printerr(2, "cmd: %s\n", buf);
2652 +
2653 +        fghn = popen(buf, "r");
2654 +        if (fghn == NULL) {
2655 +                printerr(0, "failed to call %s\n", gethostname_ex);
2656 +                return -1;
2657 +        }
2658 +
2659 +        head = fgets(buf, bufsize, fghn);
2660 +        if (head == NULL) {
2661 +                printerr(0, "can't read from %s\n", gethostname_ex);
2662 +                return -1;
2663 +        }
2664 +        if (pclose(fghn) == -1)
2665 +                printerr(1, "pclose failed, continue\n");
2666 +
2667 +        /* trim head/tail space */
2668 +        while (is_space(*head))
2669 +                head++;
2670 +
2671 +        tail = head + strlen(head);
2672 +        if (tail <= head) {
2673 +                printerr(0, "no output from %s\n", gethostname_ex);
2674 +                return -1;
2675 +        }
2676 +        while (is_space(*(tail - 1)))
2677 +                tail--;
2678 +        if (tail <= head) {
2679 +                printerr(0, "output are all space from %s\n", gethostname_ex);
2680 +                return -1;
2681 +        }
2682 +        *tail = '\0';
2683 +
2684 +        /* start with '@' means error msg */
2685 +        if (head[0] == '@') {
2686 +                printerr(0, "error from %s: %s\n", gethostname_ex, &head[1]);
2687 +                return -1;
2688 +        }
2689 +
2690 +        if (tail - head > namebuflen) {
2691 +                printerr(0, "external hostname too long: %s\n", head);
2692 +                return -1;
2693 +        }
2694 +
2695 +        printerr(2, "%s: net 0x%x, addr 0x%x => %s\n",
2696 +                 lnd, net, addr, head);
2697 +        strcpy(namebuf, head);
2698 +        return 0;
2699 +}
2700 +
2701 +static struct {
2702 +        char                    *name;
2703 +        lnd_nid2hostname_t      *nid2name;
2704 +} converter[LND_ENUM_END_MARKER] = {
2705 +        {"UNUSED0",     NULL},
2706 +        [QSWLND]        = { "QSWLND",   external_nid2hostname},
2707 +        [SOCKLND]       = { "SOCKLND",  ipv4_nid2hostname },
2708 +        [GMLND]         = { "GMLND",    external_nid2hostname},
2709 +        [PTLLND]        = { "PTLLND",   external_nid2hostname },
2710 +        [O2IBLND]       = { "O2IBLND",  ipv4_nid2hostname },
2711 +        [CIBLND]        = { "CIBLND",   external_nid2hostname },
2712 +        [OPENIBLND]     = { "OPENIBLND",external_nid2hostname },
2713 +        [IIBLND]        = { "IIBLND",   external_nid2hostname },
2714 +        [LOLND]         = { "LOLND",    lolnd_nid2hostname },
2715 +        [RALND]         = { "RALND",    external_nid2hostname },
2716 +        [VIBLND]        = { "VIBLND",   external_nid2hostname },
2717 +};
2718 +
2719 +int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen)
2720 +{
2721 +        uint32_t lnd, net, addr;
2722 +
2723 +        addr = LNET_NIDADDR(nid);
2724 +        net = LNET_NIDNET(nid);
2725 +        lnd = LNET_NETTYP(net);
2726 +
2727 +        if (lnd >= LND_ENUM_END_MARKER) {
2728 +                printerr(0, "ERROR: Unrecognized LND %u\n", lnd);
2729 +                return -1;
2730 +        }
2731 +
2732 +        if (converter[lnd].nid2name == NULL) {
2733 +                printerr(0, "ERROR: %s converter not ready\n",
2734 +                        converter[lnd].name);
2735 +                return -1;
2736 +        }
2737 +
2738 +        return converter[lnd].nid2name(converter[lnd].name, net, addr,
2739 +                                       buf, buflen);
2740 +}
2741 +
2742 +
2743 +/****************************************
2744 + * lnet support routine                 *
2745 + * (from lnet/libcfs/nidstrings.c       *
2746 + ****************************************/
2747 +
2748 +#define LNET_NIDSTR_SIZE   32      /* size of each one (see below for usage) */
2749 +
2750 +static int  libcfs_lo_str2addr(char *str, int nob, uint32_t *addr);
2751 +static void libcfs_ip_addr2str(uint32_t addr, char *str);
2752 +static int  libcfs_ip_str2addr(char *str, int nob, uint32_t *addr);
2753 +static void libcfs_decnum_addr2str(uint32_t addr, char *str);
2754 +static void libcfs_hexnum_addr2str(uint32_t addr, char *str);
2755 +static int  libcfs_num_str2addr(char *str, int nob, uint32_t *addr);
2756 +
2757 +struct netstrfns {
2758 +        int          nf_type;
2759 +        char        *nf_name;
2760 +        char        *nf_modname;
2761 +        void       (*nf_addr2str)(uint32_t addr, char *str);
2762 +        int        (*nf_str2addr)(char *str, int nob, uint32_t *addr);
2763 +};
2764 +
2765 +static struct netstrfns  libcfs_netstrfns[] = {
2766 +        {/* .nf_type      */  LOLND,
2767 +         /* .nf_name      */  "lo",
2768 +         /* .nf_modname   */  "klolnd",
2769 +         /* .nf_addr2str  */  libcfs_decnum_addr2str,
2770 +         /* .nf_str2addr  */  libcfs_lo_str2addr},
2771 +        {/* .nf_type      */  SOCKLND,
2772 +         /* .nf_name      */  "tcp",
2773 +         /* .nf_modname   */  "ksocklnd",
2774 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
2775 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
2776 +        {/* .nf_type      */  O2IBLND,
2777 +         /* .nf_name      */  "o2ib",
2778 +         /* .nf_modname   */  "ko2iblnd",
2779 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
2780 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
2781 +        {/* .nf_type      */  CIBLND,
2782 +         /* .nf_name      */  "cib",
2783 +         /* .nf_modname   */  "kciblnd",
2784 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
2785 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
2786 +        {/* .nf_type      */  OPENIBLND,
2787 +         /* .nf_name      */  "openib",
2788 +         /* .nf_modname   */  "kopeniblnd",
2789 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
2790 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
2791 +        {/* .nf_type      */  IIBLND,
2792 +         /* .nf_name      */  "iib",
2793 +         /* .nf_modname   */  "kiiblnd",
2794 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
2795 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
2796 +        {/* .nf_type      */  VIBLND,
2797 +         /* .nf_name      */  "vib",
2798 +         /* .nf_modname   */  "kviblnd",
2799 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
2800 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
2801 +        {/* .nf_type      */  RALND,
2802 +         /* .nf_name      */  "ra",
2803 +         /* .nf_modname   */  "kralnd",
2804 +         /* .nf_addr2str  */  libcfs_ip_addr2str,
2805 +         /* .nf_str2addr  */  libcfs_ip_str2addr},
2806 +        {/* .nf_type      */  QSWLND,
2807 +         /* .nf_name      */  "elan",
2808 +         /* .nf_modname   */  "kqswlnd",
2809 +         /* .nf_addr2str  */  libcfs_decnum_addr2str,
2810 +         /* .nf_str2addr  */  libcfs_num_str2addr},
2811 +        {/* .nf_type      */  GMLND,
2812 +         /* .nf_name      */  "gm",
2813 +         /* .nf_modname   */  "kgmlnd",
2814 +         /* .nf_addr2str  */  libcfs_hexnum_addr2str,
2815 +         /* .nf_str2addr  */  libcfs_num_str2addr},
2816 +        {/* .nf_type      */  PTLLND,
2817 +         /* .nf_name      */  "ptl",
2818 +         /* .nf_modname   */  "kptllnd",
2819 +         /* .nf_addr2str  */  libcfs_decnum_addr2str,
2820 +         /* .nf_str2addr  */  libcfs_num_str2addr},
2821 +        /* placeholder for net0 alias.  It MUST BE THE LAST ENTRY */
2822 +        {/* .nf_type      */  -1},
2823 +};
2824 +
2825 +const int libcfs_nnetstrfns = sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]);
2826 +
2827 +static int
2828 +libcfs_lo_str2addr(char *str, int nob, uint32_t *addr)
2829 +{
2830 +        *addr = 0;
2831 +        return 1;
2832 +}
2833 +
2834 +static void
2835 +libcfs_ip_addr2str(uint32_t addr, char *str)
2836 +{
2837 +        snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u",
2838 +                 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
2839 +                 (addr >> 8) & 0xff, addr & 0xff);
2840 +}
2841 +
2842 +/* CAVEAT EMPTOR XscanfX
2843 + * I use "%n" at the end of a sscanf format to detect trailing junk.  However
2844 + * sscanf may return immediately if it sees the terminating '0' in a string, so
2845 + * I initialise the %n variable to the expected length.  If sscanf sets it;
2846 + * fine, if it doesn't, then the scan ended at the end of the string, which is
2847 + * fine too :) */
2848 +
2849 +static int
2850 +libcfs_ip_str2addr(char *str, int nob, uint32_t *addr)
2851 +{
2852 +        int   a;
2853 +        int   b;
2854 +        int   c;
2855 +        int   d;
2856 +        int   n = nob;                          /* XscanfX */
2857 +
2858 +        /* numeric IP? */
2859 +        if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
2860 +            n == nob &&
2861 +            (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
2862 +            (c & ~0xff) == 0 && (d & ~0xff) == 0) {
2863 +                *addr = ((a<<24)|(b<<16)|(c<<8)|d);
2864 +                return 1;
2865 +        }
2866 +
2867 +#ifdef HAVE_GETHOSTBYNAME
2868 +        /* known hostname? */
2869 +        if (('a' <= str[0] && str[0] <= 'z') ||
2870 +            ('A' <= str[0] && str[0] <= 'Z')) {
2871 +                char *tmp;
2872 +
2873 +                tmp = malloc(nob + 1);
2874 +                if (tmp != NULL) {
2875 +                        struct hostent *he;
2876 +
2877 +                        memcpy(tmp, str, nob);
2878 +                        tmp[nob] = 0;
2879 +
2880 +                        he = gethostbyname(tmp);
2881 +
2882 +                        free(tmp);
2883 +                        tmp = NULL;
2884 +
2885 +                        if (he != NULL) {
2886 +                                uint32_t ip = *(uint32_t *)he->h_addr;
2887 +
2888 +                                *addr = ntohl(ip);
2889 +                                return 1;
2890 +                        }
2891 +                }
2892 +        }
2893 +#endif
2894 +        return 0;
2895 +}
2896 +
2897 +static void
2898 +libcfs_decnum_addr2str(uint32_t addr, char *str)
2899 +{
2900 +        snprintf(str, LNET_NIDSTR_SIZE, "%u", addr);
2901 +}
2902 +
2903 +static void
2904 +libcfs_hexnum_addr2str(uint32_t addr, char *str)
2905 +{
2906 +        snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr);
2907 +}
2908 +
2909 +static int
2910 +libcfs_num_str2addr(char *str, int nob, uint32_t *addr)
2911 +{
2912 +        int     n;
2913 +
2914 +        n = nob;
2915 +        if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
2916 +                return 1;
2917 +
2918 +        n = nob;
2919 +        if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
2920 +                return 1;
2921 +
2922 +        n = nob;
2923 +        if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
2924 +                return 1;
2925 +        
2926 +        return 0;
2927 +}
2928 +
2929 +static struct netstrfns *
2930 +libcfs_lnd2netstrfns(int lnd)
2931 +{
2932 +        int    i;
2933 +
2934 +        if (lnd >= 0)
2935 +                for (i = 0; i < libcfs_nnetstrfns; i++)
2936 +                        if (lnd == libcfs_netstrfns[i].nf_type)
2937 +                                return &libcfs_netstrfns[i];
2938 +
2939 +        return NULL;
2940 +}
2941 +
2942 +static struct netstrfns *
2943 +libcfs_str2net_internal(char *str, uint32_t *net)
2944 +{
2945 +        struct netstrfns *nf;
2946 +        int               nob;
2947 +        int               netnum;
2948 +        int               i;
2949 +
2950 +        for (i = 0; i < libcfs_nnetstrfns; i++) {
2951 +                nf = &libcfs_netstrfns[i];
2952 +                if (nf->nf_type >= 0 &&
2953 +                    !strncmp(str, nf->nf_name, strlen(nf->nf_name)))
2954 +                        break;
2955 +        }
2956 +
2957 +        if (i == libcfs_nnetstrfns)
2958 +                return NULL;
2959 +
2960 +        nob = strlen(nf->nf_name);
2961 +
2962 +        if (strlen(str) == (unsigned int)nob) {
2963 +                netnum = 0;
2964 +        } else {
2965 +                if (nf->nf_type == LOLND) /* net number not allowed */
2966 +                        return NULL;
2967 +
2968 +                str += nob;
2969 +                i = strlen(str);
2970 +                if (sscanf(str, "%u%n", &netnum, &i) < 1 ||
2971 +                    i != (int)strlen(str))
2972 +                        return NULL;
2973 +        }
2974 +
2975 +        *net = LNET_MKNET(nf->nf_type, netnum);
2976 +        return nf;
2977 +}
2978 +
2979 +lnet_nid_t
2980 +libcfs_str2nid(char *str)
2981 +{
2982 +        char             *sep = strchr(str, '@');
2983 +        struct netstrfns *nf;
2984 +        uint32_t             net;
2985 +        uint32_t             addr;
2986 +
2987 +        if (sep != NULL) {
2988 +                nf = libcfs_str2net_internal(sep + 1, &net);
2989 +                if (nf == NULL)
2990 +                        return LNET_NID_ANY;
2991 +        } else {
2992 +                sep = str + strlen(str);
2993 +                net = LNET_MKNET(SOCKLND, 0);
2994 +                nf = libcfs_lnd2netstrfns(SOCKLND);
2995 +                if (!nf)
2996 +                        return LNET_NID_ANY;
2997 +        }
2998 +
2999 +        if (!nf->nf_str2addr(str, sep - str, &addr))
3000 +                return LNET_NID_ANY;
3001 +
3002 +        return LNET_MKNID(net, addr);
3003 +}
3004 +
3005 +/****************************************
3006 + * user mapping database handling       *
3007 + * (very rudiment)                      *
3008 + ****************************************/
3009 +
3010 +#define MAPPING_GROW_SIZE       512
3011 +#define MAX_LINE_LEN            256
3012 +
3013 +struct user_map_item {
3014 +        char        *principal; /* NULL means match all, will cause multi->single mapped, FORBID */
3015 +        lnet_nid_t   nid;
3016 +        uid_t        uid;
3017 +};
3018 +
3019 +struct user_mapping {
3020 +        int                   nitems;
3021 +        struct user_map_item *items;
3022 +};
3023 +
3024 +static struct user_mapping mapping = {0, NULL};
3025 +/* FIXME to be finished: monitor change of mapping database */
3026 +static int mapping_mtime = 0;
3027 +
3028 +void cleanup_mapping(void)
3029 +{
3030 +        if (mapping.items) {
3031 +                for (; mapping.nitems > 0; mapping.nitems--)
3032 +                        free(mapping.items[mapping.nitems - 1].principal);
3033 +                free(mapping.items);
3034 +                mapping.items = NULL;
3035 +        }
3036 +}
3037 +
3038 +static int grow_mapping(int nitems)
3039 +{
3040 +        struct user_map_item *new;
3041 +        int oldsize, newsize;
3042 +
3043 +        oldsize = (mapping.nitems * sizeof(struct user_map_item) +
3044 +                   MAPPING_GROW_SIZE - 1) / MAPPING_GROW_SIZE;
3045 +        newsize = (nitems * sizeof(struct user_map_item) +
3046 +                   MAPPING_GROW_SIZE - 1) / MAPPING_GROW_SIZE;
3047 +        while (newsize <= oldsize)
3048 +                return 0;
3049 +
3050 +        newsize *= MAPPING_GROW_SIZE;
3051 +        new = malloc(newsize);
3052 +        if (!new) {
3053 +                printerr(0, "can't alloc mapping size %d\n", newsize);
3054 +                return -1;
3055 +        }
3056 +
3057 +        if (mapping.items) {
3058 +                memcpy(new, mapping.items, mapping.nitems * sizeof(struct user_map_item));
3059 +                free(mapping.items);
3060 +        }
3061 +        mapping.items = new;
3062 +        return 0;
3063 +}
3064 +
3065 +uid_t parse_uid(char *uidstr)
3066 +{
3067 +        struct passwd *pw;
3068 +        char *p = NULL;
3069 +        long uid;