Upstream-Status: Inappropriate [other] Upstream is not making further releases of this software. Signed-off-by: Scott Garman # Patch origin: nfs-server source RPM from openSUSE 10.3 diff -urN nfs-server-2.2beta47/.version nfs-server-2.2beta51/.version --- nfs-server-2.2beta47/.version Tue Sep 7 09:47:27 1999 +++ nfs-server-2.2beta51/.version Fri Nov 8 14:45:36 2002 @@ -1 +1 @@ -2.2beta46 +2.2beta51 diff -urN nfs-server-2.2beta47/ChangeLog nfs-server-2.2beta51/ChangeLog --- nfs-server-2.2beta47/ChangeLog Wed Nov 10 10:17:51 1999 +++ nfs-server-2.2beta51/ChangeLog Fri Nov 8 14:45:36 2002 @@ -1,8 +1,59 @@ +Thu Nov 9 17:03:05 2000 + + * No longer use OPEN_MAX + + * Reworked configure.in, BUILD script no longer needed + (nor functioning) + + * Be more anal about matching cached fh's and real files. + In addition to the psi, we also store dev/ino/type now + and match that in fh_find. + + * Write pidfiles + + * Support nosetuid + +Wed Feb 9 14:52:34 2000 + + * auth_init.c didn't properly parse options--rot_squash + which is obviously a typo was parsed as ro. + Thanks to Jan Steffan for complaining about this :-) + +Mon Jan 31 11:48:34 2000 + + * Fixed Y2K bug in logging.c. + Thanks to Jonathan Hankins . + +Thu Dec 9 11:14:21 1999 + + * Fix handling of NFS-mounted and /proc directories. + They weren't properly hidden. + Thanks to Dick Streefland + for the report and a first patch. + Wed Nov 10 10:17:16 1999 * Security fix for buffer overflow in fh_buildpath No thanks to Mariusz who reported it to bugtraq rather than me. + +Wed Nov 09 17:10:00 1999 + + * Workaround for broken Solaris clients that can't handle + atime/mtime/ctime of 0. + Thanks to Frank Wuebbelin for his problem report and + testing the fix. + + * Fixed typo in exports.man + +Tue Nov 2 10:31:14 1999 + + * Patch for mode 0100 and 0100 executables by + Michael Deutschmann + + * Common startup stuff for all daemons. + Inspired by code sent to me by someone (sorry, I forgot + your name, and the mail's gone!) Wed Sep 8 09:07:38 1999 diff -urN nfs-server-2.2beta47/Makefile.in nfs-server-2.2beta51/Makefile.in --- nfs-server-2.2beta47/Makefile.in Tue Jun 22 14:53:10 1999 +++ nfs-server-2.2beta51/Makefile.in Fri Nov 8 14:45:36 2002 @@ -17,23 +17,30 @@ #### Start of system configuration section. #### -srcdir = @srcdir@ -VPATH = @srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ -CC = @CC@ -AR = ar -RANLIB = @RANLIB@ - -INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -m 755 -INSTALL_DATA = @INSTALL_DATA@ -MAKEINFO = makeinfo -TEXI2DVI = texi2dvi -RPCGEN = @RPCGEN@ @RPCGEN_C@ +CC = @CC@ +AR = ar +RANLIB = @RANLIB@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ -m 755 +INSTALL_DATA = @INSTALL_DATA@ +MAKEINFO = makeinfo +TEXI2DVI = texi2dvi +RPCGEN = @RPCGEN@ @RPCGEN_C@ # General compile options and libs: -DEFS = @DEFS@ $(NFSD_DEFS) -LIBS = libnfs.a @LIBS@ +DEFS = @DEFS@ $(NFSD_DEFS) +LIBS = libnfs.a @LIBS@ + +# Ugidd support +UGIDD_PROG = @UGIDD_PROG@ +UGIDD_MAN = @UGIDD_MAN@ + +# New inode mapping scheme +DEVTAB_FILE = $(install_prefix)@PATH_DEVTAB@ # Compile options for nfsd: # CALL_PROFILING @@ -80,9 +87,6 @@ #### End of system configuration section. #### -# include site-specific defintions generated by BUILD. -include site.mk - SHELL = /bin/sh SRCS = version.c logging.c fh.c devtab.c \ @@ -96,19 +100,19 @@ utimes.c mkdir.c rename.c getopt.c getopt_long.c \ alloca.c mountlist.c xmalloc.c \ xstrdup.c strdup.c strstr.c nfsmounted.c faccess.c \ - haccess.c failsafe.c signals.c + haccess.c daemon.c signals.c XDRFILES = mount.x nfs_prot.x GENFILES = mount.h mount_xdr.c mount_svc.c nfs_prot.h nfs_prot_xdr.c \ ugid.h ugid_xdr.c ugid_clnt.c HDRS = system.h nfsd.h auth.h fh.h logging.h fakefsuid.h \ rpcmisc.h faccess.h rquotad.h rquota.h haccess.h -LIBHDRS = fsusage.h getopt.h mountlist.h failsafe.h signals.h +LIBHDRS = fsusage.h getopt.h mountlist.h daemon.h signals.h MANPAGES5 = exports MANPAGES8p = mountd nfsd $(UGIDD_MAN) MANPAGES8 = showmount MANPAGES = $(MANPAGES5) $(MANPAGES8p) $(MANPAGES8) LIBOBJS = version.o fsusage.o mountlist.o xmalloc.o xstrdup.o \ - nfsmounted.o faccess.o haccess.o failsafe.o \ + nfsmounted.o faccess.o haccess.o daemon.o \ signals.o @LIBOBJS@ @ALLOCA@ OBJS = logging.o fh.o devtab.o auth_init.o auth_clnt.o auth.o NFSD_OBJS = nfsd.o rpcmisc.o nfs_dispatch.o getattr.o setattr.o \ @@ -174,15 +178,13 @@ ${srcdir}/mkinstalldirs $(bindir) $(man5dir) $(man8dir) $(rpcprefix)mountd: $(MOUNTD_OBJS) libnfs.a - $(CC) $(LDFLAGS) -o $@ $(MOUNTD_OBJS) $(LIBS) \ - $(LIBWRAP_DIR) $(LIBWRAP_LIB) + $(CC) $(LDFLAGS) -o $@ $(MOUNTD_OBJS) $(LIBS) $(rpcprefix)nfsd: $(NFSD_OBJS) libnfs.a $(CC) $(LDFLAGS) -o $@ $(NFSD_OBJS) $(LIBS) $(rpcprefix)ugidd: $(UGIDD_OBJS) libnfs.a - $(CC) $(LDFLAGS) -o $@ $(UGIDD_OBJS) $(LIBS) \ - $(LIBWRAP_DIR) $(LIBWRAP_LIB) + $(CC) $(LDFLAGS) -o $@ $(UGIDD_OBJS) $(LIBS) showmount: $(SHOWMOUNT_OBJS) libnfs.a $(CC) $(LDFLAGS) -o $@ $(SHOWMOUNT_OBJS) $(LIBS) diff -urN nfs-server-2.2beta47/aclocal.m4 nfs-server-2.2beta51/aclocal.m4 --- nfs-server-2.2beta47/aclocal.m4 Fri Jun 11 12:04:22 1999 +++ nfs-server-2.2beta51/aclocal.m4 Fri Nov 8 14:45:36 2002 @@ -221,20 +221,14 @@ ])dnl dnl *********** libwrap bug ************** define(AC_LIBWRAP_BUG, - [if test -f site.mk; then - . ./site.mk - fi - if test ! -z "$LIBWRAP_DIR"; then + [if test "$ac_cv_lib_wrap_main" = yes; then AC_MSG_CHECKING(for link problem with libwrap.a) AC_CACHE_VAL(nfsd_cv_lib_wrap_bug, - [ac_save_LIBS=$LIBS - LIBS="$LIBS $LIBWRAP_DIR $LIBWRAP_LIB" - AC_TRY_LINK([ + [AC_TRY_LINK([ extern int deny_severity; ],[ deny_severity=1; ], nfsd_cv_lib_wrap_bug=no, nfsd_cv_lib_wrap_bug=yes) - LIBS=$ac_save_LIBS ]) dnl AC_MSG_RESULT($nfsd_cv_lib_wrap_bug) test $nfsd_cv_lib_wrap_bug = yes && AC_DEFINE(HAVE_LIBWRAP_BUG) diff -urN nfs-server-2.2beta47/auth.c nfs-server-2.2beta51/auth.c --- nfs-server-2.2beta47/auth.c Mon Sep 13 16:56:03 1999 +++ nfs-server-2.2beta51/auth.c Fri Nov 8 14:45:36 2002 @@ -84,8 +84,9 @@ 0, /* relative links */ 0, /* noaccess */ 1, /* cross_mounts */ - (uid_t)-2, /* default uid */ - (gid_t)-2, /* default gid */ + 1, /* allow setuid */ + 65534, /* default uid */ + 65534, /* default gid */ 0, /* no NIS domain */ }; @@ -99,8 +100,9 @@ 0, /* relative links */ 0, /* noaccess */ 1, /* cross_mounts */ - (uid_t)-2, /* default uid */ - (gid_t)-2, /* default gid */ + 0, /* allow setuid */ + 65534, /* default uid */ + 65534, /* default gid */ 0, /* no NIS domain */ }; @@ -673,6 +675,7 @@ cpp = &unknown_clients; } else { cpp = &known_clients; + cp->clnt_addr = *(struct in_addr *) hp->h_addr; auth_hash_host(cp, hp); } cp->next = *cpp; diff -urN nfs-server-2.2beta47/auth.h nfs-server-2.2beta51/auth.h --- nfs-server-2.2beta47/auth.h Thu Apr 8 14:47:56 1999 +++ nfs-server-2.2beta51/auth.h Fri Nov 8 14:45:36 2002 @@ -23,14 +23,6 @@ extern char * public_root_path; extern struct nfs_fh public_root; -#if defined(linux) && defined(i386) && !defined(HAVE_SETFSUID) -# define MAYBE_HAVE_SETFSUID -#endif - -#ifdef MAYBE_HAVE_SETFSUID -extern int have_setfsuid; -#endif - /* * These externs are set in the dispatcher (dispatch.c) and auth_fh * (nfsd.c) so that we can determine access rights, export options, @@ -59,6 +51,7 @@ int link_relative; int noaccess; int cross_mounts; + int allow_setuid; uid_t nobody_uid; gid_t nobody_gid; char * clnt_nisdomain; @@ -112,7 +105,7 @@ extern void auth_free_lists(void); extern nfs_client *auth_clnt(struct svc_req *rqstp); extern nfs_mount *auth_path(nfs_client *, struct svc_req *, char *); -extern void auth_user(nfs_mount *, struct svc_req *); +extern int auth_user(nfs_mount *, struct svc_req *); extern nfs_client *auth_get_client(char *); extern nfs_mount *auth_match_mount(nfs_client *, char *); diff -urN nfs-server-2.2beta47/auth_clnt.c nfs-server-2.2beta51/auth_clnt.c --- nfs-server-2.2beta47/auth_clnt.c Wed Nov 10 10:18:06 1999 +++ nfs-server-2.2beta51/auth_clnt.c Fri Nov 8 14:45:36 2002 @@ -12,20 +12,17 @@ */ +#include #include "system.h" #include "nfsd.h" -#include "fakefsuid.h" - -#ifndef svc_getcaller -#define svc_getcaller(x) ((struct sockaddr_in *) &(x)->xp_rtaddr.buf) -#endif +#include "rpcmisc.h" -#if defined(HAVE_SETFSUID) || defined(MAYBE_HAVE_SETFSUID) -static void setfsids(uid_t, gid_t, gid_t *, int); +#if defined(HAVE_SETFSUID) +static int setfsids(uid_t, gid_t, gid_t *, int); #endif #ifndef HAVE_SETFSUID -static void seteids(uid_t, gid_t, gid_t *, int); +static int seteids(uid_t, gid_t, gid_t *, int); #endif uid_t auth_uid = 0; /* Current effective user ids */ @@ -43,6 +40,17 @@ short *gid, short *nrgids, int *groups); #endif +/* + * The following crap is required for glibc 2.1 which has 32bit uids + * in user land mapped to 16bit uids in the Linux kernel + */ +#if defined(HAVE_BROKEN_SETFSUID) +# define native_uid(u) ((unsigned short)(u)) +# define native_gid(g) ((unsigned short)(g)) +#else +# define native_uid(u) (u) +# define native_gid(g) (g) +#endif /* * For an RPC request, look up the NFS client info along with the @@ -92,8 +100,9 @@ } if (logging_enabled(D_AUTH)) { - Dprintf(D_AUTH, "auth_path(%s): mount point %s, (%s%s%s%s%s)\n", - path, mp->path, + Dprintf(D_AUTH, "auth_path(%s, %s): " + "mount point %s, (%s%s%s%s%s)\n", + inet_ntoa(cp->clnt_addr), path, mp->path, mp->o.all_squash? "all_squash " : ( mp->o.root_squash? "root_squash " : ""), (mp->o.uidmap == map_daemon)? "uidmap " : "", @@ -105,7 +114,8 @@ return mp; } -void auth_user(nfs_mount *mp, struct svc_req *rqstp) +int +auth_user(nfs_mount *mp, struct svc_req *rqstp) { uid_t cuid; gid_t cgid; @@ -160,23 +170,18 @@ else if (cred_len > NGRPS) cred_len = NGRPS; - cuid = luid(cred_uid, mp, rqstp); - cgid = lgid(cred_gid, mp, rqstp); + cuid = luid(native_uid(cred_uid), mp, rqstp); + cgid = lgid(native_gid(cred_gid), mp, rqstp); clen = cred_len; for (i = 0; i < cred_len; i++) - cgids[i] = lgid(cred_gids[i], mp, rqstp); + cgids[i] = lgid(native_gid(cred_gids[i]), mp, rqstp); } else { /* On systems that have 32bit uid_t in user space but * 16bit in the kernel, we need to truncate the * nobody ID (default -2). */ -#if !defined(HAVE_BROKEN_SETFSUID) - cuid = mp->o.nobody_uid; - cgid = mp->o.nobody_gid; -#else - cuid = (unsigned short) mp->o.nobody_uid; - cgid = (unsigned short) mp->o.nobody_gid; -#endif + cuid = native_uid(mp->o.nobody_uid); + cgid = native_gid(mp->o.nobody_gid); /* Construct a list of one gid. */ cgids[0] = cgid; clen = 1; @@ -193,14 +198,9 @@ * upper 16 bits set (including our default nobody uid -2). */ #if defined(HAVE_SETFSUID) - setfsids(cuid, cgid, cgids, clen); + return setfsids(cuid, cgid, cgids, clen); #else -#if defined(MAYBE_HAVE_SETFSUID) - if (have_setfsuid) - setfsids(cuid, cgid, cgids, clen); - else -#endif - seteids(cuid, cgid, cgids, clen); + return seteids(cuid, cgid, cgids, clen); #endif } @@ -210,6 +210,8 @@ void auth_override_uid(uid_t uid) { + int res; + /* extension hooks: */ efs_setfsuid(uid); @@ -217,19 +219,18 @@ uid = (unsigned short) uid; #endif #if defined(HAVE_SETFSUID) - setfsuid(uid); + res = setfsuid(uid); #else -#if defined(MAYBE_HAVE_SETFSUID) - if (have_setfsuid) - setfsuid(uid); - else -#endif - seteuid(uid); + res = seteuid(uid); #endif + /* should never happen */ + if (res < 0) + Dprintf(L_FATAL, "auth_override_uid(%d) failed: %s", + uid, strerror(errno)); } -#if defined(HAVE_SETFSUID) || defined(MAYBE_HAVE_SETFSUID) -static void +#if defined(HAVE_SETFSUID) +static int setfsids(uid_t cred_uid, gid_t cred_gid, gid_t *cred_gids, int cred_len) { /* extension hooks: */ @@ -238,43 +239,47 @@ /* First, set the user ID. */ if (auth_uid != cred_uid) { - if (setfsuid(cred_uid) < 0) + if (setfsuid(cred_uid) < 0) { Dprintf(L_ERROR, "Unable to setfsuid %d: %s\n", cred_uid, strerror(errno)); - else - auth_uid = cred_uid; + return 0; + } + auth_uid = cred_uid; } /* Next, the group ID. */ if (auth_gid != cred_gid) { - if (setfsgid(cred_gid) < 0) + if (setfsgid(cred_gid) < 0) { Dprintf(L_ERROR, "Unable to setfsgid %d: %s\n", cred_gid, strerror(errno)); - else - auth_gid = cred_gid; + return 0; + } + auth_gid = cred_gid; } #ifdef HAVE_SETGROUPS /* Finally, set the supplementary group IDs if possible. */ - if (cred_len < 0 || cred_len > NGRPS) + if (cred_len < 0 || cred_len > NGRPS) { Dprintf(L_ERROR, "Negative or huge cred_len: %d\n", cred_len); - else if (cred_len != auth_gidlen - || memcmp(cred_gids, auth_gids, auth_gidlen*sizeof(gid_t))) { - if (setgroups(cred_len, cred_gids) < 0) + return 0; + } + if (cred_len != auth_gidlen + || memcmp(cred_gids, auth_gids, auth_gidlen*sizeof(gid_t))) { + if (setgroups(cred_len, cred_gids) < 0) { Dprintf(L_ERROR, "Unable to setgroups: %s\n", strerror(errno)); - else { - memcpy(auth_gids, cred_gids, cred_len*sizeof(gid_t)); - auth_gidlen = cred_len; + return 0; } + memcpy(auth_gids, cred_gids, cred_len*sizeof(gid_t)); + auth_gidlen = cred_len; } #endif /* HAVE_SETGROUPS */ - + return 1; } #endif #if !defined(HAVE_SETFSUID) -static void +static int seteids(uid_t cred_uid, gid_t cred_gid, gid_t *cred_gids, int cred_len) { /* extension hooks: */ @@ -286,52 +291,62 @@ /* First set the group ID. */ if (auth_gid != cred_gid) { if (auth_uid != ROOT_UID) { - if (seteuid(ROOT_UID) < 0) + if (seteuid(ROOT_UID) < 0) { Dprintf(L_ERROR, "Unable to seteuid(%d): %s\n", ROOT_UID, strerror(errno)); - else - auth_uid = ROOT_UID; + return 0; + } + auth_uid = ROOT_UID; } - if (setegid(cred_gid) < 0) + if (setegid(cred_gid) < 0) { Dprintf(L_ERROR, "Unable to setegid(%d): %s\n", cred_gid, strerror(errno)); - else - auth_gid = cred_gid; + return 0; + } + auth_gid = cred_gid; } #ifdef HAVE_SETGROUPS /* Next set the supplementary group IDs if possible. */ - if (cred_len < 0 || cred_len > NGRPS) + if (cred_len < 0 || cred_len > NGRPS) { Dprintf(L_ERROR, "Negative or huge cred_len: %d\n", cred_len); - else if (cred_len != auth_gidlen - || memcmp(cred_gids, auth_gids, auth_gidlen*sizeof(gid_t))) { + return 0; + } + if (cred_len != auth_gidlen + || memcmp(cred_gids, auth_gids, auth_gidlen*sizeof(gid_t))) { if (auth_uid != ROOT_UID) { - if (seteuid(ROOT_UID) < 0) + if (seteuid(ROOT_UID) < 0) { Dprintf(L_ERROR, "Unable to seteuid(%d): %s\n", ROOT_UID, strerror(errno)); - else - auth_uid = ROOT_UID; + return 0; + } + auth_uid = ROOT_UID; } - if (setgroups(cred_len, cred_gids) < 0) + if (setgroups(cred_len, cred_gids) < 0) { Dprintf(L_ERROR, "Unable to setgroups: %s\n", strerror(errno)); - else { - memcpy(auth_gids, cred_gids, cred_len*sizeof(gid_t)); - auth_gidlen = cred_len; + return 0; } + memcpy(auth_gids, cred_gids, cred_len*sizeof(gid_t)); + auth_gidlen = cred_len; } #endif /* HAVE_SETGROUPS */ /* Finally, set the user ID. */ if (auth_uid != cred_uid) { - if (auth_uid != ROOT_UID && seteuid(ROOT_UID) < 0) + if (auth_uid != ROOT_UID && seteuid(ROOT_UID) < 0) { Dprintf(L_ERROR, "Unable to seteuid(%d): %s\n", ROOT_UID, strerror(errno)); - if (seteuid(cred_uid) < 0) + return 0; + } + if (seteuid(cred_uid) < 0) { Dprintf(L_ERROR, "Unable to seteuid(%d): %s\n", cred_uid, strerror(errno)); - else - auth_uid = cred_uid; + return 0; + } + auth_uid = cred_uid; } + + return 1; } #endif diff -urN nfs-server-2.2beta47/auth_init.c nfs-server-2.2beta51/auth_init.c --- nfs-server-2.2beta47/auth_init.c Mon Apr 19 14:01:21 1999 +++ nfs-server-2.2beta51/auth_init.c Fri Nov 8 14:45:36 2002 @@ -13,7 +13,6 @@ */ #include "nfsd.h" -#include "fakefsuid.h" #include #define LINE_SIZE 1024 @@ -263,55 +262,63 @@ cp++; while (*cp != terminator) { kwd = cp; - while (isalpha(*cp) || *cp == '_' || *cp == '=') { - /* break out of loop after = sign */ - if (*cp++ == '=') - break; - } + /* Gobble up keyword and "=" if there is one */ + while (isalpha(*cp) || *cp == '_') + ++cp; + if (*cp == '=') + ++cp; + klen = cp - kwd; /* process keyword */ - if (strncmp(kwd, "secure", 6) == 0) +#define ifkwd(n, string) \ + if (klen == (n) && !strncmp(kwd, string, (n))) + + ifkwd(2, "ro") + mp->o.read_only = 1; + else ifkwd(2, "rw") + mp->o.read_only = 0; + else ifkwd(6, "secure") mp->o.secure_port = 1; - else if (strncmp(kwd, "insecure", 8) == 0) + else ifkwd(8, "insecure") mp->o.secure_port = 0; - else if (strncmp(kwd, "root_squash", 11) == 0) + else ifkwd(11, "root_squash") mp->o.root_squash = 1; - else if (strncmp(kwd, "no_root_squash", 14) == 0) + else ifkwd(14, "no_root_squash") mp->o.root_squash = 0; - else if (strncmp(kwd, "ro", 2) == 0) - mp->o.read_only = 1; - else if (strncmp(kwd, "rw", 2) == 0) - mp->o.read_only = 0; - else if (strncmp(kwd, "link_relative", 13) == 0) + else ifkwd(13, "link_relative") mp->o.link_relative = 1; - else if (strncmp(kwd, "link_absolute", 13) == 0) + else ifkwd(13, "link_absolute") mp->o.link_relative = 0; - else if (strncmp(kwd, "map_daemon", 10) == 0) + else ifkwd(10, "map_daemon") mp->o.uidmap = map_daemon; - else if (strncmp(kwd, "map_nis=", 8) == 0) + else ifkwd(8, "map_nis=") parse_nis_uidmap(mp, &cp); - else if (strncmp(kwd, "map_static=", 11) == 0) + else ifkwd(11, "map_static=") parse_static_uidmap(mp, &cp); - else if (strncmp(kwd, "map_identity", 12) == 0) + else ifkwd(12, "map_identity") mp->o.uidmap = identity; - else if (strncmp(kwd, "all_squash", 10) == 0) + else ifkwd(10, "all_squash") mp->o.all_squash = 1; - else if (strncmp(kwd, "no_all_squash", 13) == 0) + else ifkwd(13, "no_all_squash") mp->o.all_squash = 0; - else if (strncmp(kwd, "noaccess", 8) == 0) + else ifkwd(8, "noaccess") mp->o.noaccess = 1; - else if (strncmp(kwd, "squash_uids=", 12) == 0) + else ifkwd(12, "squash_uids=") parse_squash(mp, 1, &cp); - else if (strncmp(kwd, "squash_gids=", 12) == 0) + else ifkwd(12, "squash_gids=") parse_squash(mp, 0, &cp); - else if (strncmp(kwd, "anonuid=", 8) == 0) + else ifkwd(8, "anonuid=") mp->o.nobody_uid = parse_num(&cp); - else if (strncmp(kwd, "anongid=", 8) == 0) + else ifkwd(8, "anongid=") mp->o.nobody_gid = parse_num(&cp); - else if (strncmp(kwd, "async", 5) == 0) + else ifkwd(6, "setuid") + mp->o.allow_setuid = 1; + else ifkwd(8, "nosetuid") + mp->o.allow_setuid = 0; + else ifkwd(5, "async") /* knfsd compatibility, ignore */; - else if (strncmp(kwd, "sync", 4) == 0) + else ifkwd(4, "sync") /* knfsd compatibility, ignore */; else { Dprintf(L_ERROR, @@ -566,11 +573,6 @@ auth_check_all_wildcards(); auth_sort_all_mountlists(); auth_log_all(); - -#if defined(MAYBE_HAVE_SETFSUID) && !defined(HAVE_SETFSUID) - /* check if the a.out setfsuid syscall works on this machine */ - have_setfsuid = (setfsuid(0) >= 0); -#endif auth_initialized = 1; } diff -urN nfs-server-2.2beta47/config.h.in nfs-server-2.2beta51/config.h.in --- nfs-server-2.2beta47/config.h.in Fri Jun 11 12:01:22 1999 +++ nfs-server-2.2beta51/config.h.in Fri Nov 8 14:45:36 2002 @@ -3,7 +3,7 @@ /* Define if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ -#ifndef _ALL_SOURCE +#ifdef _ALL_SOURCE #undef _ALL_SOURCE #endif diff -urN nfs-server-2.2beta47/configure.in nfs-server-2.2beta51/configure.in --- nfs-server-2.2beta47/configure.in Fri Jun 11 11:58:10 1999 +++ nfs-server-2.2beta51/configure.in Fri Nov 8 14:45:36 2002 @@ -2,7 +2,36 @@ dnl Updated for autoconf 2. dnl AC_INIT(nfsd.c) -AC_CONFIG_HEADER(config.h) +AC_CONFIG_HEADER(config.h site.h) + +dnl ************************************************************** +dnl * handle --enable options +dnl ************************************************************** +AC_ARG_ENABLE(new-inodes, + [ --enable-new-inodes Enable new-style inode inodes]) +AC_ARG_WITH(devtab, + [ --with-devtab=file Specify location for devtab [/var/lib/nfs/devtab]], + PATH_DEVTAB=$withval, + PATH_DEVTAB=/var/lib/nfs/devtab) +AC_ARG_ENABLE(ugid-dynamic, + [ --enable-ugid-dynamic Enable uid mapping using rpc.ugidd (not recommended)]) +AC_ARG_ENABLE(ugid-nis, + [ --enable-ugid-nis Enable NIS-based uid mapping]) +AC_ARG_ENABLE(host-access, + [ --enable-host-access Enable host access checking]) +AC_ARG_ENABLE(mount-logging, + [ --disable-mount-logging Do not log mount operations to syslog],, + enable_mount_logging=yes) +AC_ARG_WITH(exports-uid, + [ --with-exports-uid=N Make sure that /etc/exports is owned by uid N],, + with_exports_uid=0) +AC_ARG_WITH(exports-gid, + [ --with-exports-gid=N Make sure that /etc/exports is owned by gid N],, + with_exports_gid=0) + +dnl ************************************************************** +dnl * Check for all kinds of stuff +dnl ************************************************************** AC_PROG_CC # If we're using gcc, we want warning flags test -n "$GCC" && @@ -19,7 +48,7 @@ AC_MINIX AC_ISC_POSIX AC_PROG_INSTALL -AC_CROSS_CHECK +dnl AC_CROSS_CHECK AC_STDC_HEADERS AC_GNULIBC AC_CONST @@ -52,14 +81,45 @@ AC_CHECK_LIB(rpc, main) AC_CHECK_LIB(crypt, main) AC_CHECK_LIB(nys, main) -AC_REPLACE_FUNCS(strerror realpath mkdir rename utimes strdup strstr getopt getopt_long) AC_HAVE_FUNCS(getcwd seteuid setreuid getdtablesize setgroups lchown setsid setfsuid setfsgid innetgr quotactl authdes_getucred) AC_AUTHDES_GETUCRED AC_BROKEN_SETFSUID AC_MOUNTLIST AC_FSUSAGE +AC_CHECK_LIB(wrap, main) AC_LIBWRAP_BUG AC_BSD_SIGNALS + +dnl ************************************************************** +dnl * Munge user specified options +dnl ************************************************************** +if test "$enable_new_inodes" = yes; then + AC_DEFINE(ENABLE_DEVTAB) +fi +if test "$enable_ugid_dynamic" = yes; then + AC_DEFINE(ENABLE_UGID_DAEMON) + UGIDD_PROG=\${rpcprefix}.ugidd + UGIDD_MAN=ugidd +fi +if test "$enable_ugid_nis" = yes; then + AC_DEFINE(ENABLE_UGID_NIS) +fi +if test "$enable_host_access" = yes; then + AC_DEFINE(HOSTS_ACCESS) +fi +if test "$enable_mount_logging" = yes; then + AC_DEFINE(WANT_LOG_MOUNTS) +fi +AC_DEFINE_UNQUOTED(EXPORTSOWNERUID, $with_exports_uid) +AC_DEFINE_UNQUOTED(EXPORTSOWNERGID, $with_exports_gid) +AC_SUBST(PATH_DEVTAB) +AC_SUBST(UGIDD_PROG) +AC_SUBST(UGIDD_MAN) + +dnl ************************************************************** +dnl * Output CFLAGS and LDFLAGS +dnl ************************************************************** AC_SUBST(LDFLAGS) AC_SUBST(CFLAGS) + AC_OUTPUT(Makefile) diff -urN nfs-server-2.2beta47/daemon.c nfs-server-2.2beta51/daemon.c --- nfs-server-2.2beta47/daemon.c Thu Jan 1 01:00:00 1970 +++ nfs-server-2.2beta51/daemon.c Fri Nov 8 14:45:52 2002 @@ -0,0 +1,270 @@ +/* + * daemon.c + * + * Copyright (C) 1998, + * + * Implements common daemon stuff and + * fail-safe mode for nfsd/mountd. + */ + +#include "system.h" +#include "logging.h" +#include "signals.h" +#include + +static const char * pidfilename = 0; +static const char * get_signame(int signo); + +/* + * Do the Crawley Thing + */ +void +daemonize(void) +{ + int c; + + /* Ignore SIGHUP so the parent can exit while we're still + * in limbo */ + ignore_signal(SIGHUP); + + /* Now fork */ + c = fork(); + if (c < 0) + Dprintf(L_FATAL, "unable to fork: %s", strerror(errno)); + + /* Parent process: exit */ + if (c > 0) + exit(0); + + /* Do the session stuff */ + close(0); + close(1); + close(2); +#ifdef HAVE_SETSID + setsid(); +#else + if ((c = open("/dev/tty", O_RDWR)) >= 0) { + ioctl(c, TIOCNOTTY, (char *) NULL); + close(c); + } +#endif + + /* Stop stderr logging */ + background_logging(); +} + +void +setpidpath(const char *filename) +{ + pidfilename = filename; +} + +void +writepid(pid_t pid, int clear) +{ + FILE *fp; + + fp = fopen(pidfilename, clear? "w" : "a"); + if (fp == NULL) + Dprintf(L_FATAL, "Unable to open %s: %m", pidfilename); + fprintf(fp, "%d\n", pid); + fclose(fp); + return; +} + +void +failsafe(int level, int ncopies) +{ + int *servers, running, child, i; + int pid, signo, status; + time_t last_restart = 0, now; + int restarts = 0, backoff = 60; + + servers = (int *) xmalloc(ncopies * sizeof(int)); + memset(servers, 0, ncopies * sizeof(int)); + + /* Loop forever, until we get SIGTERM */ + running = 0; + while (1) { + /* Rewrite the pidfile */ + writepid(getpid(), 1); + for (i = 0; i < ncopies; i++) { + if (servers[i] != 0) + writepid(servers[i], 0); + } + + while (running < ncopies) { + if ((now = time(NULL)) == last_restart) { + if (++restarts > 2 * ncopies) { + Dprintf(L_ERROR, + "Servers restarting too " + "quickly, backing off."); + if (backoff < 60 * 60) + backoff <<= 1; + sleep(backoff); + } + } else { + last_restart = now; + restarts = 0; + backoff = 60; + } + + /* Locate a free pid slot */ + for (i = 0, child = -1; i < ncopies; i++) { + if (servers[i] == 0) { + child = i; + break; + } + } + + if (child < 0) + Dprintf(L_FATAL, "failsafe: no pid slot?!"); + + Dprintf(D_GENERAL, + "starting server thread %d...\n", child + 1); + + pid = fork(); + if (pid < 0) + Dprintf(L_FATAL, + "Unable to fork for failsafe: %s", + strerror(errno)); + + if (pid == 0) { + /* Child process: continue with execution. */ + return; + } + + writepid(pid, 0); + servers[child] = pid; + running++; + } + + /* Ignore some signals */ + ignore_signal(SIGTERM); + ignore_signal(SIGHUP); + ignore_signal(SIGINT); + ignore_signal(SIGCHLD); + + if ((pid = wait(&status)) < 0) { + Dprintf((errno == ECHILD)? L_FATAL : L_WARNING, + "failsafe: wait(): %s", strerror(errno)); + continue; + } + + /* Locate the child */ + for (i = 0, child = -1; i < ncopies; i++) { + if (servers[i] == pid) { + child = i; + break; + } + } + + if (child < 0) { + Dprintf(L_WARNING, + "failsafe: unknown child (pid %d) terminated", + pid); + continue; + } + + /* Book-keeping */ + servers[child] = 0; + running--; + + if (WIFSIGNALED(status)) { + signo = WTERMSIG(status); + if (signo == SIGTERM) { + Dprintf(L_NOTICE, "failsafe: " + "child %d terminated by SIGTERM. %s.", + pid, running? "Continue" : "Exit"); + } else { + Dprintf(L_WARNING, "failsafe: " + "child %d terminated by %s. " + "Restarting.", + pid, get_signame(signo)); + child = -1; /* Restart */ + } + } else if (WIFEXITED(status)) { + Dprintf(L_NOTICE, "failsafe: " + "child %d exited, status %d.", + pid, WEXITSTATUS(status)); + } else { + Dprintf(L_ERROR, "failsafe: " + "abnormal child termination, " + "pid=%d status=%d. Restarting.", + pid, status); + child = -1; /* Restart */ + } + + /* If child >= 0, we should not restart */ + if (child >= 0) { + if (!running) { + Dprintf(D_GENERAL, + "No more children, exiting."); + exit(0); + } + for (i = child; i < ncopies-1; i++) + servers[i] = servers[i+1]; + ncopies--; /* Make sure we start no new servers */ + } + } +} + +/* + * Failsafe session, catch core file. + * + * Not yet implemented. + * General outline: we need to fork first, because nfsd changes + * uids frequently, and the kernel won't write out a core file after + * that. The forked proc starts out with a clean dumpable flag though. + * + * After the fork, we might want to make sure we end up in some common + * directory that the failsafe loop knows about. + */ +void +failsafe_loop(int level, void (*function)(void)) +{ + /* NOP */ +} + +static const char * +get_signame(int signo) +{ + static char namebuf[30]; + + switch (signo) { + case SIGHUP: return "SIGHUP"; + case SIGINT: return "SIGINT"; + case SIGQUIT: return "SIGQUIT"; + case SIGILL: return "SIGILL"; + case SIGTRAP: return "SIGTRAP"; + case SIGIOT: return "SIGIOT"; + case SIGBUS: return "SIGBUS"; + case SIGFPE: return "SIGFPE"; + case SIGKILL: return "SIGKILL"; + case SIGUSR1: return "SIGUSR1"; + case SIGSEGV: return "SIGSEGV"; + case SIGUSR2: return "SIGUSR2"; + case SIGPIPE: return "SIGPIPE"; + case SIGALRM: return "SIGALRM"; + case SIGTERM: return "SIGTERM"; + case SIGCHLD: return "SIGCHLD"; + case SIGCONT: return "SIGCONT"; + case SIGSTOP: return "SIGSTOP"; + case SIGTSTP: return "SIGTSTP"; + case SIGTTIN: return "SIGTTIN"; + case SIGTTOU: return "SIGTTOU"; + case SIGURG: return "SIGURG"; + case SIGXCPU: return "SIGXCPU"; + case SIGXFSZ: return "SIGXFSZ"; + case SIGVTALRM: return "SIGVTALRM"; + case SIGPROF: return "SIGPROF"; + case SIGWINCH: return "SIGWINCH"; + case SIGIO: return "SIGIO"; +#ifdef SIGPWR + case SIGPWR: return "SIGPWR"; +#endif + } + + sprintf(namebuf, "signal #%d", signo); + return namebuf; +} diff -urN nfs-server-2.2beta47/daemon.h nfs-server-2.2beta51/daemon.h --- nfs-server-2.2beta47/daemon.h Thu Jan 1 01:00:00 1970 +++ nfs-server-2.2beta51/daemon.h Fri Nov 8 14:45:52 2002 @@ -0,0 +1,18 @@ +/* + * daemon.h + * + * Daemon support + */ + +#ifndef CRAWLEY_H +#define CRAWLEY_H + +#define _PATH_NFSD_PIDFILE "/var/run/nfsd.pid" +#define _PATH_MOUNTD_PIDFILE "/var/run/mountd.pid" + +extern void daemonize(void); +extern void setpidpath(const char *); +extern void writepid(pid_t, int); +extern void failsafe(int level, int ncopies); + +#endif /* CRAWLEY_H */ diff -urN nfs-server-2.2beta47/exports.man nfs-server-2.2beta51/exports.man --- nfs-server-2.2beta47/exports.man Wed Nov 10 10:18:49 1999 +++ nfs-server-2.2beta51/exports.man Fri Nov 8 14:45:36 2002 @@ -45,6 +45,12 @@ simultaneously. This is done by specifying an IP address and netmask pair as .IR address/netmask . +.IP "world +You can export a directory to the world (i.e. to all computers that +are able to reach your NFS server network-wise) by using the empty +hostname. When exporting to the world, the +.BR root_squash ", " all_squash ", " ro " and " nosetuid +options are turned on by default. .TP .B =public This is a special ``hostname'' that identifies the given directory name @@ -81,6 +87,12 @@ by using the .IR ro " option. .TP +.I setuid +This allows clients to assert the setuid and setgid bits on regular +files. For non-anonymous exports, this option is on by default. +For anonymous exports, the default is +.IR nosetuid . +.TP .I noaccess This makes everything below the directory inaccessible for the named client. This is useful when you want to export a directory hierarchy to @@ -296,6 +308,22 @@ .I /usr/X11R6 entry apply. This is also true when the latter is a wildcard or netgroup entry. +.PP +You should also be careful about where you place spaces in the +exports file. For instance, the following may appear as if you've +exported +.BR /pub " readonly to host " foozle , +but what this does in fact is export the directory to +.B foozle +with the default options, +.I and +export it to the world with the readonly option: +.PP +.nf +.ta +3i +# bad: export to the world +/pub foozle (ro) +.fi .SH FILES /etc/exports .SH DIAGNOSTICS diff -urN nfs-server-2.2beta47/fh.c nfs-server-2.2beta51/fh.c --- nfs-server-2.2beta47/fh.c Wed Nov 10 10:41:14 1999 +++ nfs-server-2.2beta51/fh.c Fri Nov 8 14:45:36 2002 @@ -95,17 +95,14 @@ static int fh_list_size; static time_t curtime; -#ifndef FOPEN_MAX -#define FOPEN_MAX 256 -#endif - #ifndef FHTRACE #undef D_FHTRACE #define D_FHTRACE D_FHCACHE #endif -static fhcache * fd_cache[FOPEN_MAX] = { NULL }; +static fhcache ** fd_cache = NULL; static int fd_cache_size = 0; +static int fd_cache_max = 0; #ifndef NFSERR_INVAL /* that Sun forgot */ #define NFSERR_INVAL 22 @@ -141,10 +138,13 @@ /* Forward declared local functions */ static psi_t path_psi(char *, nfsstat *, struct stat *, int); +static psi_t path_psi_m(char *, nfsstat *, struct stat *, + struct stat *, int); static int fh_flush_fds(void); static char * fh_dump(svc_fh *); static void fh_insert_fdcache(fhcache *fhc); static void fh_unlink_fdcache(fhcache *fhc); +static void fh_complain(const char *msg, fhcache *fhc); static void fh_move_to_front(fhcache *fhc) @@ -192,6 +192,13 @@ static void fh_insert_fdcache(fhcache *fhc) { +#ifdef FHTRACE + Dprintf(D_FHTRACE, "insert fh %x into fdcache @%d\n", fhc->h.psi, fhc->fd); + if (fhc->fd < 0) { + fh_complain("fd cache bug: bad fd", fhc); + return; + } +#endif if (fhc == fd_lru_head) return; if (fhc->fd_next || fhc->fd_prev) @@ -203,9 +210,20 @@ fhc->fd_next = fd_lru_head; fd_lru_head = fhc; + if (fhc->fd >= fd_cache_max) { + int oldmax = fd_cache_max, newmax; + + newmax = (fhc->fd + 8) & ~7; + fd_cache = (fhcache **) xrealloc(fd_cache, newmax * sizeof(fhcache *)); + memset(fd_cache + oldmax, 0, (newmax - oldmax) * sizeof(fhcache *)); + fd_cache_max = newmax; + } + #ifdef FHTRACE if (fd_cache[fhc->fd] != NULL) { - Dprintf(L_ERROR, "fd cache inconsistency!\n"); + Dprintf(L_ERROR, "fd cache inconsistency (two fh's for same fd)"); + fh_complain("new fh", fhc); + fh_complain("old fh", fd_cache[fhc->fd]); return; } #endif @@ -225,7 +243,7 @@ } else if (fd_lru_tail == fhc) { fd_lru_tail = prev; } else { - Dprintf(L_ERROR, "fd cache inconsistency\n"); + fh_complain("fd cache inconsistency (no next and not at tail)", fhc); return; } if (prev) { @@ -233,13 +251,13 @@ } else if (fd_lru_head == fhc) { fd_lru_head = next; } else { - Dprintf(L_ERROR, "fd cache inconsistency\n"); + fh_complain("fd cache inconsistency (no prev and not at head)", fhc); return; } #ifdef FHTRACE if (fd_cache[fhc->fd] != fhc) { - Dprintf(L_ERROR, "fd cache inconsistency!\n"); + fh_complain("fd cache inconsistency (fd cache ptr mismatch)", fhc); return; } #endif @@ -285,7 +303,7 @@ hash_slot = &((*hash_slot)->hash_next); if (*hash_slot == NULL) Dprintf(L_ERROR, - "internal inconsistency -- fhc(%x) not in hash table\n", + "internal inconsistency -- fhc(%x) not in hash table!\n", fhc); else *hash_slot = fhc->hash_next; @@ -572,7 +590,7 @@ efs_seekdir(dir, cookie_stack[i]); while ((dp = efs_readdir(dir))) { char *name = dp->d_name; - int n = strlen(name); + int n = strlen(name); /* or: dp->d_reclen */ if (pathlen + n + 1 >= NFS_MAXPATHLEN || (name[0] == '.' @@ -738,7 +756,16 @@ static psi_t path_psi(char *path, nfsstat *status, struct stat *sbp, int svalid) { - struct stat sbuf; + struct stat smounted; + + return path_psi_m(path, status, sbp, &smounted, svalid); +} + +static psi_t +path_psi_m(char *path, nfsstat *status, + struct stat *sbp, struct stat *mbp, int svalid) +{ + struct stat sbuf, ddbuf; if (sbp == NULL) sbp = &sbuf; @@ -746,10 +773,10 @@ *status = nfs_errno(); return (0); } + *mbp = *sbp; if (S_ISDIR(sbp->st_mode) && strcmp(path, "/") != 0) { /* Special case for directories--test for mount point. */ - struct stat ddbuf; - char *fname; + char *fname; /* Find start of last component of path. */ #if 1 @@ -819,6 +846,19 @@ return (pseudo_inode(sbp->st_ino, sbp->st_dev)); } +/* + * Match attributes to make sure we're still referring to the original file + */ +static inline int +fh_attrmatch(struct fhcache *fhc, struct stat *attr) +{ + if (fhc->dev == attr->st_dev + && fhc->ino == attr->st_ino + && fhc->type == (attr->st_mode & S_IFMT)) + return 1; + return 0; +} + fhcache * fh_find(svc_fh *h, int mode) { @@ -838,6 +878,9 @@ ex_state = active; time(&curtime); while ((fhc = fh_lookup(h->psi)) != NULL) { + struct stat sbuf, *s = NULL; + nfsstat dummy; + Dprintf(D_FHCACHE, "fh_find: psi=%lx... found '%s', fd=%d\n", (unsigned long) h->psi, fhc->path ? fhc->path : "", @@ -857,33 +900,27 @@ * If it doesn't try to rebuild the path. */ if (check) { - struct stat *s = &fhc->attrs; - psi_t psi; - nfsstat dummy; - + s = &sbuf; if (efs_lstat(fhc->path, s) < 0) { Dprintf(D_FHTRACE, "fh_find: stale fh: lstat: %m\n"); } else { - fhc->flags |= FHC_ATTRVALID; - /* If pseudo-inos don't match, we fhc->path - * may be a mount point (hence lstat() returns + /* If device/ino don't match, fhc->path may + * be a mount point (hence lstat() returns * a different inode number than the readdir() * stuff used in path_psi) */ - psi = pseudo_inode(s->st_ino, s->st_dev); - if (h->psi == psi) + if (fh_attrmatch(fhc, s)) goto fh_return; - /* Try again by computing the path psi */ - psi = path_psi(fhc->path, &dummy, s, 1); - if (h->psi == psi) + /* Get the dev/ino of the underlying + * mount point. */ + path_psi(fhc->path, &dummy, s, 1); + if (fh_attrmatch(fhc, s)) goto fh_return; - Dprintf(D_FHTRACE, "fh_find: stale fh: " - "dev/ino %x/%lx psi %lx", - s->st_dev, s->st_ino, - (unsigned long) psi); + Dprintf(D_FHTRACE, "fh_find: stale fh: %lx", + (unsigned long) h->psi); } fh_discard: @@ -896,6 +933,12 @@ } fh_return: + /* Valid attributes; cache them */ + if (s != NULL) { + memcpy(&fhc->attrs, s, sizeof(*s)); + fhc->flags |= FHC_ATTRVALID; + } + /* The cached fh seems valid */ if (fhc != fh_head.next) fh_move_to_front(fhc); @@ -905,7 +948,8 @@ } Dprintf(D_FHCACHE, "fh_find: psi=%lx... not found\n", - (unsigned long) h->psi); + (unsigned long) h->psi); + if (mode == FHFIND_FCACHED) { ex_state = inactive; return NULL; @@ -918,6 +962,7 @@ fhc = flush->prev; fh_delete(flush); } + fhc = (fhcache *) xmalloc(sizeof *fhc); if (mode == FHFIND_FCREATE) { /* File will be created */ @@ -937,11 +982,31 @@ } fhc->path = path; } + fhc->flags = 0; if (fhc->path && efs_lstat(fhc->path, &fhc->attrs) >= 0) { - if (re_export && nfsmounted(fhc->path, &fhc->attrs)) + if (nfsmounted(fhc->path, &fhc->attrs)) { fhc->flags |= FHC_NFSMOUNTED; +#if 0 + /* We must allow the client to send us the + * file handle for the NFS mount point itself, + * but not for entries within an NFS mount. + * XXX: needs fixing. + */ + if (!re_export) { + Dprintf(D_FHTRACE, + "Attempt to use %s (non-exportable)\n", + fhc->path); + free(fhc); + ex_state = inactive; + return NULL; + } +#endif + } fhc->flags |= FHC_ATTRVALID; + fhc->dev = fhc->attrs.st_dev; + fhc->ino = fhc->attrs.st_ino; + fhc->type = fhc->attrs.st_mode & S_IFMT; } fhc->fd = -1; fhc->last_used = curtime; @@ -993,6 +1058,14 @@ return buf; } +static void +fh_complain(const char *msg, fhcache *fhc) +{ + Dprintf(L_ERROR, "%s: ptr=%p fd=%d path=%s\n", msg, + fhc, fhc->fd, + fhc->path? fhc->path : ""); +} + /* * This routine is only used by the mount daemon. * It creates the initial file handle. @@ -1000,23 +1073,25 @@ int fh_create(nfs_fh *fh, char *path) { - svc_fh key; - fhcache *h; - psi_t psi; - nfsstat status; - char *s; + struct stat stb; + svc_fh key; + fhcache *h; + psi_t psi; + nfsstat status; + char *s; memset(&key, 0, sizeof(key)); status = NFS_OK; - if ((psi = path_psi("/", &status, NULL, 0)) == 0) + if ((psi = path_psi("/", &status, &stb, 0)) == 0) return ((int) status); + s = path; while ((s = strchr(s + 1, '/')) != NULL) { if (++(key.hash_path[0]) >= HP_LEN) return ((int) NFSERR_NAMETOOLONG); key.hash_path[key.hash_path[0]] = hash_psi(psi); *s = '\0'; - if ((psi = path_psi(path, &status, NULL, 0)) == 0) + if ((psi = path_psi(path, &status, &stb, 0)) == 0) return ((int) status); *s = '/'; } @@ -1024,7 +1099,7 @@ if (++(key.hash_path[0]) >= HP_LEN) return ((int) NFSERR_NAMETOOLONG); key.hash_path[key.hash_path[0]] = hash_psi(psi); - if ((psi = path_psi(path, &status, NULL, 0)) == 0) + if ((psi = path_psi(path, &status, &stb, 0)) == 0) return ((int) status); } key.psi = psi; @@ -1037,9 +1112,12 @@ /* assert(h != NULL); */ if (h->path == NULL) { - h->fd = -1; - h->path = xstrdup(path); + h->fd = -1; + h->path = xstrdup(path); h->flags = 0; + h->dev = stb.st_dev; + h->ino = stb.st_ino; + h->type = stb.st_mode & S_IFMT; } memcpy(fh, &key, sizeof(key)); return ((int) status); @@ -1064,6 +1142,44 @@ return ((nfs_fh*)&(h->h)); } + +static inline int +access_override(int omode, int perm, struct stat *buf) +{ + /* Be suspicous of flags, particularly O_CREAT/O_TRUNC. A previous + * comment said: + * + * "[Not checking this] would truncate read-only files on creat() + * calls. Of course, ftruncate(fd, 0) should still be legal for + * the user when the file was chmoded *after* opening it, but we + * have no way to tell, and a semi-succeding `cp foo readonly-file' + * is much more unintuitive and destructive than a failing + * ftruncate()." + */ + if (omode & ~O_ACCMODE) + return 0; + + /* Users can do anything to their own files. Harmless (since they + * could chown anyway), and helps to mask NFSes statelessness. + * + * (in passing, this also handles mode 0100 execution) + */ + if (buf->st_uid == auth_uid) + return 1; + + /* Henceforth, we are considering granting read access to facilitate + * exec access. This is read only */ + if (omode != O_RDONLY) + return 0; + + /* Mode 0110 execution */ + if (buf->st_gid == auth_gid) + return (buf->st_mode & S_IXGRP) != 0; + + /* Mode 0111 execution */ + return (buf->st_mode & S_IXOTH) != 0; +} + int path_open(char *path, int omode, int perm) { @@ -1113,30 +1229,15 @@ * lishes two things: first, it gives the file owner r/w access to * the file whatever the permissions are, so that files are still * accessible after an fchown(fd, 0). The second part of the - * condition allows read access to mode 0111 executables. - * - * The old conditon read like this: - * if (fd < 0 && oerrno == EACCES) { - * if (oerrno == EACCES && (buf.st_uid == auth_uid - * || (omode == O_RDONLY && (buf.st_mode & S_IXOTH)))) { - * override uid; etc... - * } - * } - * This would truncate read-only files on creat() calls. Now - * ftruncate(fd, 0) should still be legal for the user when the - * file was chmoded *after* opening it, but we have no way to tell, - * and a semi-succeding `cp foo readonly-file' is much more - * unintuitive and destructive than a failing ftruncate(). + * condition allows read access to `execute-only' files. */ - if (fd < 0 && oerrno == EACCES && !(omode & (O_CREAT|O_TRUNC))) { - if ((buf.st_uid == auth_uid && (omode & O_ACCMODE) == omode) - || ((buf.st_mode & S_IXOTH) && omode == O_RDONLY)) { - auth_override_uid(ROOT_UID); - fd = efs_open(path, omode, perm); - oerrno = errno; - auth_override_uid(auth_uid); - } + if (fd < 0 && oerrno == EACCES && access_override(omode, perm, &buf)) { + auth_override_uid(ROOT_UID); + fd = efs_open(path, omode, perm); + oerrno = errno; + auth_override_uid(auth_uid); } + if (fd < 0) { Dprintf(D_FHCACHE, @@ -1241,7 +1342,7 @@ char *sindx; int is_dd; nfsstat ret; - struct stat sbuf; + struct stat sbuf, smount; char pathbuf[PATH_MAX + NAME_MAX + 1], *fname; /* should not happen */ @@ -1318,7 +1419,7 @@ *new_fh = dopa->dir; key = (svc_fh *) new_fh; - if ((key->psi = path_psi(pathbuf, &ret, sbp, 0)) == 0) + if ((key->psi = path_psi_m(pathbuf, &ret, sbp, &smount, 0)) == 0) return (ret); if (is_dd) { @@ -1344,6 +1445,10 @@ h->h.hash_path[0]); return NFSERR_STALE; } + if (sbp->st_dev != smount.st_dev) { + Dprintf(D_FHTRACE, "fh_compose: %s hit%s mount point\n", + pathbuf, nfsmounted(pathbuf, &smount)? " NFS" : ""); + } #endif /* New code added by Don Becker */ @@ -1356,7 +1461,8 @@ if (!h) return NFSERR_STALE; #endif if (h->path) - Dprintf(L_ERROR, "Internal inconsistency: double entry (path '%s', now '%s').\n", + Dprintf(L_ERROR, + "internal inconsistency: double entry (path '%s', now '%s').\n", h->path, pathbuf); } Dprintf(D_FHCACHE, "fh_compose: using handle %x ('%s', fd=%d)\n", @@ -1365,9 +1471,18 @@ /* assert(h != NULL); */ if (h->path == 0) { - h->path = xstrdup(pathbuf); + h->path = xstrdup(pathbuf); h->flags = 0; - if (!re_export && nfsmounted(pathbuf, sbp)) + h->dev = sbp->st_dev; + h->ino = sbp->st_ino; + h->type = sbp->st_mode & S_IFMT; + + /* Note: in the case of a mount point, + * sbp contains the stats of the mount point, while + * ddbuf has the dev/ino of the underlying directory + */ + if (sbp->st_dev != smount.st_dev + && nfsmounted(pathbuf, &smount)) h->flags |= FHC_NFSMOUNTED; #ifdef FHTRACE Dprintf(D_FHTRACE, "fh_compose: created handle %s\n", h->path); diff -urN nfs-server-2.2beta47/fh.h nfs-server-2.2beta51/fh.h --- nfs-server-2.2beta47/fh.h Mon Nov 23 12:15:43 1998 +++ nfs-server-2.2beta51/fh.h Fri Nov 8 14:45:36 2002 @@ -97,7 +97,13 @@ struct fhcache * hash_next; struct fhcache * fd_next; struct fhcache * fd_prev; + + /* These are fixed during the lifetime of this object */ svc_fh h; + dev_t dev; + ino_t ino; + mode_t type; /* st_mode & S_IFMT */ + int fd; int omode; char * path; diff -urN nfs-server-2.2beta47/getattr.c nfs-server-2.2beta51/getattr.c --- nfs-server-2.2beta47/getattr.c Fri Oct 30 18:10:11 1998 +++ nfs-server-2.2beta51/getattr.c Fri Nov 8 14:45:36 2002 @@ -115,6 +115,16 @@ attr->fsid = 1; attr->fileid = fh_psi((nfs_fh *)&(fhc->h)); #endif + + /* This may be needed by some Suns... testing */ +#define MINTIME (24 * 2600) + if (s->st_atime < MINTIME) + s->st_atime = MINTIME; + if (s->st_mtime < MINTIME) + s->st_mtime = MINTIME; + if (s->st_ctime < MINTIME) + s->st_ctime = MINTIME; + attr->atime.seconds = s->st_atime; attr->atime.useconds = 0; attr->mtime.seconds = s->st_mtime; diff -urN nfs-server-2.2beta47/logging.c nfs-server-2.2beta51/logging.c --- nfs-server-2.2beta47/logging.c Fri Oct 30 17:11:22 1998 +++ nfs-server-2.2beta51/logging.c Fri Nov 8 14:45:36 2002 @@ -147,8 +147,9 @@ (void) time(&now); tm = localtime(&now); fprintf(log_fp, "%s %02d/%02d/%02d %02d:%02d %s", - log_name, tm->tm_mon + 1, tm->tm_mday, tm->tm_year, - tm->tm_hour, tm->tm_min, buff); + log_name, tm->tm_mon + 1, tm->tm_mday, + tm->tm_year % 100, + tm->tm_hour, tm->tm_min, buff); if (strchr(buff, '\n') == NULL) fputc('\n', log_fp); } @@ -182,7 +183,8 @@ tm = localtime(&unix_cred->aup_time); snprintf(buffer + len, total - len, "%d/%d/%d %02d:%02d:%02d %s %d.%d", - tm->tm_year, tm->tm_mon + 1, tm->tm_mday, + tm->tm_year %100, + tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, unix_cred->aup_machname, unix_cred->aup_uid, diff -urN nfs-server-2.2beta47/mountd.c nfs-server-2.2beta51/mountd.c --- nfs-server-2.2beta47/mountd.c Wed Jun 2 14:10:33 1999 +++ nfs-server-2.2beta51/mountd.c Fri Nov 8 14:45:36 2002 @@ -32,7 +32,7 @@ #include "rpcmisc.h" #include "rmtab.h" #include "haccess.h" -#include "failsafe.h" +#include "daemon.h" #include "signals.h" #include @@ -44,6 +44,8 @@ /* * Option table for mountd */ +#define OPT_NOTCP 300 +#define OPT_LOOPBACK 301 static struct option longopts[] = { { "debug", required_argument, 0, 'd' }, @@ -56,6 +58,8 @@ { "no-spoof-trace", 0, 0, 't' }, { "version", 0, 0, 'v' }, { "fail-safe", optional_argument, 0, 'z' }, + { "no-tcp", 0, 0, OPT_NOTCP }, + { "loopback-only", 0, 0, OPT_LOOPBACK }, { NULL, 0, 0, 0 } }; @@ -358,6 +362,12 @@ break; case 0: break; + case OPT_NOTCP: + udp_only = 1; + break; + case OPT_LOOPBACK: + loopback_only = 1; + break; case '?': default: usage(stderr, 1); @@ -384,38 +394,27 @@ /* Create services and register with portmapper */ rpc_init("mountd", MOUNTPROG, mountd_versions, mount_dispatch, port, 0); - if (!foreground && !_rpcpmstart) { -#ifndef RPC_SVC_FG - /* We first fork off a child. */ - if ((c = fork()) > 0) - exit(0); - if (c < 0) { - Dprintf(L_FATAL, "mountd: cannot fork: %s\n", - strerror(errno)); - } - /* No more logging to stderr */ - background_logging(); + if (_rpcpmstart) { + /* Always foreground mode */ + foreground = 1; - /* Now we remove ourselves from the foreground. */ - (void) close(0); - (void) close(1); - (void) close(2); -#ifdef TIOCNOTTY - if ((c = open("/dev/tty", O_RDWR)) >= 0) { - (void) ioctl(c, TIOCNOTTY, (char *) NULL); - (void) close(c); - } -#else - setsid(); -#endif -#endif /* not RPC_SVC_FG */ + /* ... but no logging */ + background_logging(); } + /* Become a daemon */ + if (!foreground) + daemonize(); + /* Initialize the FH module. */ fh_init(); /* Initialize the AUTH module. */ auth_init(auth_file); + + /* Write pidfile */ + setpidpath(_PATH_MOUNTD_PIDFILE); + writepid(getpid(), 1); /* Failsafe mode */ if (failsafe_level) diff -urN nfs-server-2.2beta47/mountd.man nfs-server-2.2beta51/mountd.man --- nfs-server-2.2beta47/mountd.man Wed Jun 2 14:12:21 1999 +++ nfs-server-2.2beta51/mountd.man Fri Nov 8 14:45:36 2002 @@ -14,6 +14,8 @@ .B "[\ \-\-allow\-non\-root\ ]" .B "[\ \-\-re\-export\ ]" .B "[\ \-\-no\-spoof\-trace\ ]" +.B "[\ \-\-no\-tcp ]" +.B "[\ \-\-loopback\-only ]" .B "[\ \-\-version\ ]" .ad b .SH DESCRIPTION @@ -123,6 +125,18 @@ .TP .BR \-v " or " \-\-version Report the current version number of the program. +.TP +.BR \-\-no\-tcp +Force +.I mountd +to register only the UDP transport, but no TCP. +This is an experimental option. +.TP +.BR \-\-loopback\-only +Force +.I mountd +to bind to the loopback interface. +This is an experimental option. .SS Access Control For enhanced security, access to .I mountd diff -urN nfs-server-2.2beta47/nfsd.c nfs-server-2.2beta51/nfsd.c --- nfs-server-2.2beta47/nfsd.c Wed Nov 10 10:33:28 1999 +++ nfs-server-2.2beta51/nfsd.c Fri Nov 8 14:45:36 2002 @@ -21,7 +21,7 @@ #include "getopt.h" #include "fsusage.h" #include "rpcmisc.h" -#include "failsafe.h" +#include "daemon.h" #include "signals.h" #ifdef __linux__ /* XXX - MvS: for UNIX sockets. */ # include @@ -30,7 +30,6 @@ # include #endif -#define MULTIPLE_SERVERS /* Flags for auth_fh */ #define CHK_READ 0 @@ -51,6 +50,8 @@ /* * Option table */ +#define OPT_NOTCP 300 +#define OPT_LOOPBACK 301 static struct option longopts[] = { { "auth-deamon", required_argument, 0, 'a' }, { "debug", required_argument, 0, 'd' }, @@ -68,6 +69,9 @@ { "version", 0, 0, 'v' }, { "no-cross-mounts", 0, 0, 'x' }, { "fail-safe", optional_argument, 0, 'z' }, + { "no-tcp", 0, 0, OPT_NOTCP }, + { "udp-only", 0, 0, OPT_NOTCP }, + { "loopback-only", 0, 0, OPT_LOOPBACK }, { NULL, 0, 0, 0 } }; @@ -173,7 +177,10 @@ return NULL; } - auth_user(nfsmount, rqstp); + if (!auth_user(nfsmount, rqstp)) { + *statp = NFSERR_ACCES; + return NULL; + } *statp = NFS_OK; return fhc; @@ -211,7 +218,11 @@ if ((nfsmount = auth_path(nfsclient, rqstp, path)) == NULL) return NFSERR_ACCES; - auth_user(nfsmount, rqstp); + + /* XXX: really need to call it again here? + * Already invoked in auth_fh */ + if (!auth_user(nfsmount, rqstp)) + return NFSERR_ACCES; return (NFS_OK); } @@ -575,7 +586,8 @@ #endif /* MvS: Some clients use chardev 0xFFFF for a FIFO. */ - if (S_ISCHR(argp->attributes.mode) && dev == 0xFFFF) { + if (S_ISCHR(argp->attributes.mode) + && (dev == 0xFFFF || dev == (dev_t) -1)) { is_borc = 0; dev = 0; argp->attributes.mode &= ~S_IFMT; @@ -623,7 +635,7 @@ flags = (argp->attributes.size == 0 ? CREATE_OMODE | O_TRUNC : CREATE_OMODE); if (!exists) - flags |= O_CREAT; + flags |= O_CREAT|O_EXCL; tmpfd = path_open(pathbuf, flags, argp->attributes.mode & ~S_IFMT); if (tmpfd < 0) @@ -965,9 +977,7 @@ int nfsport = 0; int failsafe_level = 0; int c; -#ifdef MULTIPLE_SERVERS int i, ncopies = 1; -#endif program_name = argv[0]; chdir("/"); @@ -1031,12 +1041,17 @@ break; case 0: break; + case OPT_NOTCP: + udp_only = 1; + break; + case OPT_LOOPBACK: + loopback_only = 1; + break; case '?': default: usage(stderr, 1); } -#ifdef MULTIPLE_SERVERS if (optind == argc-1 && isdigit(argv[optind][0])) { ncopies = atoi(argv[optind++]); if (ncopies <= 0) { @@ -1051,7 +1066,6 @@ ncopies = 1; } } -#endif /* No more arguments allowed. */ if (optind != argc) @@ -1075,72 +1089,54 @@ rpc_init("nfsd", NFS_PROGRAM, nfsd_versions, nfs_dispatch, nfsport, NFS_MAXDATA); - /* No more than 1 copy when run from inetd */ - if (_rpcpmstart && ncopies > 1) { - Dprintf(L_WARNING, - "nfsd: warning: can run only " - "one server in inetd mode\n"); - ncopies = 1; + if (_rpcpmstart) { + /* Always do foreground mode */ + foreground = 1; + + /* ... but don't log to stderr */ + background_logging(); + + /* No more than 1 copy when run from inetd */ + if (ncopies > 1) { + Dprintf(L_WARNING, + "nfsd: warning: can run only " + "one server in inetd mode\n"); + ncopies = 1; + } } -#ifndef MULTIPLE_SERVERS_READWRITE if (ncopies > 1) read_only = 1; -#endif - /* We first fork off a child. */ - if (!foreground) { - if ((c = fork()) > 0) - exit(0); - if (c < 0) { - Dprintf(L_FATAL, "nfsd: cannot fork: %s\n", - strerror(errno)); - } - } + /* + * We first fork off a child and detach from tty + */ + if (!foreground) + daemonize(); /* Initialize the AUTH module. */ auth_init(auth_file); + setpidpath(_PATH_NFSD_PIDFILE); if (failsafe_level == 0) { /* Start multiple copies of the server */ + writepid(getpid(), 1); for (i = 1; i < ncopies; i++) { + pid_t pid; + Dprintf(D_GENERAL, "Forking server thread...\n"); - if ((c = fork()) < 0) { + if ((pid = fork()) < 0) { Dprintf(L_ERROR, "Unable to fork: %s", strerror(errno)); - } else if (c == 0) { - /* Child process */ - break; + } else if (pid != 0) { + writepid(pid, 0); + } else { + break; /* Child process */ } } } else { /* Init for failsafe mode */ failsafe(failsafe_level, ncopies); - } - - /* Now that we've done all the required forks, we make do all the - * session magic. - */ - if (!foreground) { - /* No more logging to stderr */ - background_logging(); - - /* Now we remove ourselves from the foreground. */ - close(0); - close(1); - close(2); -#ifdef HAVE_SETSID - setsid(); -#else - { - int fd; - - if ((fd = open("/dev/tty", O_RDWR)) >= 0) { - ioctl(fd, TIOCNOTTY, (char *) NULL); - close(fd); - } - } -#endif } /* diff -urN nfs-server-2.2beta47/nfsd.man nfs-server-2.2beta51/nfsd.man --- nfs-server-2.2beta47/nfsd.man Wed Jun 2 14:13:37 1999 +++ nfs-server-2.2beta51/nfsd.man Fri Nov 8 14:45:36 2002 @@ -8,7 +8,7 @@ .B "[\ \-d\ facility\ ]" .B "[\ \-P\ port\ ]" .B "[\ \-R\ dirname\ ]" -.B "[\ \-Fhlnprstv\ ]" +.B "[\ \-Fhlnprstuv\ ]" .B "[\ \-\-debug\ facility\ ]" .B "[\ \-\-exports\-file=file\ ]" .B "[\ \-\-foreground\ ]" @@ -18,6 +18,8 @@ .B "[\ \-\-public\-root\ dirname\ ]" .\".B "[\ \-\-synchronous\-writes\ ]" .B "[\ \-\-no\-spoof\-trace\ ]" +.B "[\ \-\-no\-tcp ]" +.B "[\ \-\-loopback-only ]" .B "[\ \-\-port\ port\ ]" .B "[\ \-\-log-transfers\ ]" .B "[\ \-\-version\ ]" @@ -56,7 +58,7 @@ .PP When run from .IR inetd , -.i nfsd +.I nfsd will terminate after a certain period of inactivity. .SH OPTIONS .TP @@ -167,6 +169,14 @@ .BR \-v " or " \-\-version Report the current version number of the program. .TP +.BR \-\-no\-tcp +Force nfsd to only register a UDP transport, but not TCP. +This is an experimental option. +.TP +.BR \-\-loopback\-only +Force nfsd to bind to the loopback interface. +This is an experimental option. +.TP .BR numcopies This is an experimental feature that lets you run several instances of .I nfsd @@ -174,15 +184,8 @@ .B numcopies greater than one, .I nfsd -will fork as many times as specified by this value. -However, the servers do not share a common file handle -cache, which makes certain file operations impossible. -.IP -For this reason, -.I nfsd -will disallow all write operations when invoked with this option. Although -this is very limiting, this feature may still prove useful for exporting -public FTP areas or Usenet News spools. +will fork as many times as specified by this value so it is able to +handle that many NFS requests in parallel. .SS WebNFS Support WebNFS is an extension to the normal NFS protocol developed by Sun that is particularly well-suited for file retrieval over the @@ -268,6 +271,19 @@ .I nfsd writes out a transfer record whenever it encounters a READ or WRITE request at offset zero. +.SS Generating a debug trace +When suspecting a bug in nfsd, it is helpful to look at a debug trace +of what's going on. You can create such a trace by first killing nfsd, +and then restarting it as +.PP +.nf +.ta +3i +/usr/sbin/rpc.nfsd -F -d all +.fi +.PP +Instead of +.BR all , +you can use less verbose debug facilities as described above. .SH "SEE ALSO" exports(5), mountd(8), ugidd(8C) .SH AUTHORS diff -urN nfs-server-2.2beta47/rmtab.c nfs-server-2.2beta51/rmtab.c --- nfs-server-2.2beta47/rmtab.c Fri Feb 6 09:43:25 1998 +++ nfs-server-2.2beta51/rmtab.c Fri Nov 8 14:45:36 2002 @@ -8,6 +8,7 @@ #include "nfsd.h" #include "rmtab.h" +#include "rpcmisc.h" static char * rmtab_gethost(struct svc_req *); static int rmtab_insert(char *, char *); diff -urN nfs-server-2.2beta47/rpcmisc.c nfs-server-2.2beta51/rpcmisc.c --- nfs-server-2.2beta47/rpcmisc.c Tue Sep 7 10:42:58 1999 +++ nfs-server-2.2beta51/rpcmisc.c Fri Nov 8 14:45:36 2002 @@ -39,6 +39,8 @@ int _rpcfdtype = 0; int _rpcsvcdirty = 0; const char * auth_daemon = 0; +int udp_only = 0; +int loopback_only = 0; #ifdef AUTH_DAEMON static bool_t (*tcp_rendevouser)(SVCXPRT *, struct rpc_msg *); @@ -96,7 +98,7 @@ } } - if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { + if ((_rpcfdtype == 0 && !udp_only) || (_rpcfdtype == SOCK_STREAM)) { if (_rpcfdtype == 0 && defport != 0) sock = makesock(defport, IPPROTO_TCP, bufsiz); transp = svctcp_create(sock, 0, 0); @@ -199,6 +201,9 @@ sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(port); + + if (loopback_only) + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); #ifdef DEBUG { diff -urN nfs-server-2.2beta47/rpcmisc.h nfs-server-2.2beta51/rpcmisc.h --- nfs-server-2.2beta47/rpcmisc.h Tue Sep 7 10:37:38 1999 +++ nfs-server-2.2beta51/rpcmisc.h Fri Nov 8 14:45:36 2002 @@ -9,6 +9,8 @@ extern int _rpcpmstart; extern int _rpcfdtype; extern int _rpcsvcdirty; +extern int udp_only; +extern int loopback_only; extern const char * auth_daemon; extern void rpc_init(const char *name, int prog, int *verstbl, @@ -16,5 +18,13 @@ int defport, int bufsize); extern void rpc_exit(int prog, int *verstbl); extern void rpc_closedown(void); + +/* + * Some older systems don't have svc_getcaller. + * Some, like glibc 2.2, have it but it returns some type that's + * not a sockaddr_in anymore. + */ +#undef svc_getcaller +#define svc_getcaller(xprt) ((struct sockaddr_in *) (&(xprt)->xp_raddr)) #endif /* RPCMISC_H */ diff -urN nfs-server-2.2beta47/setattr.c nfs-server-2.2beta51/setattr.c --- nfs-server-2.2beta47/setattr.c Fri Oct 30 18:29:42 1998 +++ nfs-server-2.2beta51/setattr.c Fri Nov 8 14:45:36 2002 @@ -103,6 +103,10 @@ if (flags & SATTR_CHMOD) { unsigned int mode = attr->mode; + /* If setuid is not allowed, silently squash them */ + if (!nfsmount->o.allow_setuid && S_ISREG(s->st_mode)) + mode &= ~(S_ISUID|S_ISGID) | s->st_mode; + if (mode != -1 && mode != 0xFFFF /* ultrix bug */ && (mode & 07777) != (s->st_mode & 07777)) { if (efs_chmod(path, mode) < 0) diff -urN nfs-server-2.2beta47/showmount.c nfs-server-2.2beta51/showmount.c --- nfs-server-2.2beta47/showmount.c Wed Jun 12 22:31:04 1996 +++ nfs-server-2.2beta51/showmount.c Fri Nov 8 14:45:36 2002 @@ -162,17 +162,13 @@ break; } - if (hostname[0] >= '0' && hostname[0] <= '9') { - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = inet_addr(hostname); - } - else { + server_addr.sin_family = AF_INET; + if (!inet_aton(hostname, &server_addr.sin_addr)) { if ((hp = gethostbyname(hostname)) == NULL) { fprintf(stderr, "%s: can't get address for %s\n", program_name, hostname); exit(1); } - server_addr.sin_family = AF_INET; memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length); } diff -urN nfs-server-2.2beta47/site.h.in nfs-server-2.2beta51/site.h.in --- nfs-server-2.2beta47/site.h.in Thu Jan 1 01:00:00 1970 +++ nfs-server-2.2beta51/site.h.in Fri Nov 8 14:45:57 2002 @@ -0,0 +1,50 @@ +/* + * Site-specific configuration options generated by BUILD. + * Please do not edit. + */ + +/* + * If ENABLE_DEVTAB is defined, nfsd will use the new inode + * number generation scheme for avoiding inode number clashes + * on big hard disks. + */ +#undef ENABLE_DEVTAB + +/* + * If MULTIPLE_SERVER_READWRITE is defined, you will be able + * to run several nfsd process in parallel servicing all NFS + * requests. + */ +#define MULTIPLE_SERVERS_READWRITE + +/* + * If ENABLE_UGID_DAEMON is defined, the real rpc.ugidd is built, + * nfsd is built to support ugidd queries. + * Otherwise, a dummy program is created + */ +#undef ENABLE_UGID_DAEMON + +/* + * If ENABLE_UGID_NIS is defined, nfsd will support user mapping + * vie the client's NIS server. + */ +#undef ENABLE_UGID_NIS + +/* + * if HOSTS_ACCESS is defined, ugidd uses host access control + * provided by libwrap.a from tcp_wrappers + */ +#define HOSTS_ACCESS + +/* + * Define correct ownership of export control file + */ +#define EXPORTSOWNERUID 0 +#define EXPORTSOWNERGID 0 + +/* + * If WANT_LOG_MOUNTS is defined, every mount request will be logged + * to syslogd with the name of source site and a path that was + * it requested + */ +#define WANT_LOG_MOUNTS diff -urN nfs-server-2.2beta47/ugidd.c nfs-server-2.2beta51/ugidd.c --- nfs-server-2.2beta47/ugidd.c Wed Dec 10 12:34:16 1997 +++ nfs-server-2.2beta51/ugidd.c Fri Nov 8 14:45:36 2002 @@ -43,9 +43,7 @@ }; int -main(argc, argv) -int argc; -char **argv; +main(int argc, char **argv) { SVCXPRT *transp; int c, longind; @@ -92,32 +90,11 @@ exit(1); } - if (!foreground) { - if ((c = fork()) > 0) - exit(0); - if (c < 0) { - fprintf(stderr, "ugidd: cannot fork: %s\n", - strerror(errno)); - exit(-1); - } - close(0); - close(1); - close(2); -#ifdef HAVE_SETSID - setsid(); -#else - { - int fd; - - if ((fd = open("/dev/tty", O_RDWR)) >= 0) { - ioctl(fd, TIOCNOTTY, (char *) NULL); - close(fd); - } - } -#endif - } - log_open("ugidd", foreground); + + /* Become a daemon */ + if (!foreground) + daemonize(); svc_run(); Dprintf(L_ERROR, "svc_run returned\n"); diff -urN nfs-server-2.2beta47/version.c nfs-server-2.2beta51/version.c --- nfs-server-2.2beta47/version.c Wed Nov 10 10:33:33 1999 +++ nfs-server-2.2beta51/version.c Fri Nov 8 14:45:36 2002 @@ -1 +1 @@ -char version[] = "Universal NFS Server 2.2beta47"; +char version[] = "Universal NFS Server 2.2beta51";