diff -bpru oldu/mount/nfs_mount4.h newu/mount/nfs_mount4.h --- oldu/mount/nfs_mount4.h Sat Oct 14 09:20:51 2000 +++ newu/mount/nfs_mount4.h Fri Jul 26 11:27:21 2002 @@ -8,7 +8,7 @@ * so it is easiest to ignore the kernel altogether (at compile time). */ -#define NFS_MOUNT_VERSION 4 +#define NFS_MOUNT_VERSION 5 struct nfs2_fh { char data[32]; @@ -36,6 +36,8 @@ struct nfs_mount_data { int namlen; /* 2 */ unsigned int bsize; /* 3 */ struct nfs3_fh root; /* 4 */ + char mnt_path[256]; /* 5 */ + char ip_addr[16]; /* 5 */ }; /* bits in the flags field */ @@ -51,4 +53,5 @@ struct nfs_mount_data { #define NFS_MOUNT_KERBEROS 0x0100 /* 3 */ #define NFS_MOUNT_NONLM 0x0200 /* 3 */ #define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */ +#define NFS_MOUNT_VER4 0x0800 /* 5 */ diff -bpru oldu/mount/nfsmount.c newu/mount/nfsmount.c --- oldu/mount/nfsmount.c Fri Apr 5 05:35:53 2002 +++ newu/mount/nfsmount.c Fri Jul 26 11:53:07 2002 @@ -72,11 +72,14 @@ #define NFS_FHSIZE 32 #endif +#define GSSPROG 100666 + static char *nfs_strerror(int stat); #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) -#define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2) +#define MAX_NFSPROT ((nfs_mount_version >= 5) ? 4 : \ + ((nfs_mount_version >= 4) ? 3 : 2)) static int linux_version_code(void) { @@ -119,8 +122,10 @@ find_kernel_nfs_mount_version(void) { nfs_mount_version = 4; /* since 2.2.18pre9 */ else if (kernel_version < MAKE_VERSION(2,3,99)) nfs_mount_version = 3; - else + else if (kernel_version < MAKE_VERSION(2,5,25)) nfs_mount_version = 4; /* since 2.3.99pre4 */ + else + nfs_mount_version = 5; } if (nfs_mount_version > NFS_MOUNT_VERSION) nfs_mount_version = NFS_MOUNT_VERSION; @@ -188,6 +193,23 @@ get_mountport(struct sockaddr_in *server return &p; } +static int +check_for_gssd(void) +{ + struct pmaplist *pmap; + struct sockaddr_in local_addr; + + memset(&local_addr, 0, sizeof(local_addr)); + local_addr.sin_family = AF_INET; + local_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + local_addr.sin_port = htons(PMAPPORT); + + for (pmap = pmap_getmaps(&local_addr); pmap; pmap = pmap->pml_next) + if (pmap->pml_map.pm_prog == GSSPROG) + return 0; + return -1; +} + int nfsmount(const char *spec, const char *node, int *flags, char **extra_opts, char **mount_opts, int *nfs_mount_vers, int running_bg) @@ -223,6 +245,10 @@ int nfsmount(const char *spec, const cha time_t t; time_t prevt; time_t timeout; + char lname[128]; + struct hostent *lh; + struct in_addr lin; + char *laddr; /* The version to try is either specified or 0 In case it is 0 we tell the caller what we tried */ @@ -511,6 +537,9 @@ int nfsmount(const char *spec, const cha return retval; } + if (nfsvers == 4) + goto skip_mountd; + /* create mount deamon client */ /* See if the nfs host = mount host. */ if (mounthost) { @@ -670,6 +699,7 @@ int nfsmount(const char *spec, const cha } nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers; +skip_mountd: if (nfsvers == 2) { if (status.nfsv2.fhs_status != 0) { fprintf(stderr, @@ -687,7 +717,7 @@ int nfsmount(const char *spec, const cha (char *) status.nfsv2.fhstatus_u.fhs_fhandle, NFS_FHSIZE); #endif - } else { + } else if (nfsvers == 3) { #if NFS_MOUNT_VERSION >= 4 fhandle3 *fhandle; if (status.nfsv3.fhs_status != 0) { @@ -707,6 +737,37 @@ int nfsmount(const char *spec, const cha data.flags |= NFS_MOUNT_VER3; #endif + } else { + retval = EX_FAIL; + if (check_for_gssd()) { + fprintf(stderr, _("mount: local GSSD service not available\n")); + goto fail; + } + if (strlen(dirname) >= sizeof(data.mnt_path)) { + fprintf(stderr, _("mount: remote pathname too long\n")); + goto fail; + } + + /* + * Determine the local IP address, as a string in dotted-quad + * format. This is used by the client kernel to provide a + * callback path to the server, and to set the NFSv4 clientid. + */ + strncpy(data.mnt_path, dirname, sizeof(data.mnt_path)); + if (gethostname(lname, sizeof(lname)) < 0) { + perror(_("gethostname")); + goto fail; + } + lh = gethostbyname(lname); + if (!lh) { + fprintf(stderr, _("mount: couldn't determine local hostname\n")); + goto fail; + } + memcpy(&lin.s_addr, lh->h_addr, sizeof(lin.s_addr)); + laddr = inet_ntoa(lin); + strncpy(data.ip_addr, laddr, sizeof(data.ip_addr)); + + data.flags |= NFS_MOUNT_VER4; } /* create nfs socket for kernel */ @@ -774,8 +835,11 @@ int nfsmount(const char *spec, const cha /* clean up */ + if (mclient) { auth_destroy(mclient->cl_auth); clnt_destroy(mclient); + } + if (msock != -1) close(msock); return 0; diff -bpru oldu/mount/umount.c newu/mount/umount.c --- oldu/mount/umount.c Thu Mar 28 16:39:56 2002 +++ newu/mount/umount.c Fri Jul 26 12:09:10 2002 @@ -263,7 +263,7 @@ umount_one (const char *spec, const char #ifdef HAVE_NFS /* Ignore any RPC errors, so that you can umount the filesystem if the server is down. */ - if (strcasecmp(type, "nfs") == 0) + if (strcasecmp(type, "nfs") == 0 && strstr(opts, "vers=4") == NULL) nfs_umount_rpc_call(spec, opts); #endif