#include <rpc/pmap_clnt.h>
#include <sys/socket.h>
#include <sys/time.h>
-#include <sys/utsname.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define NFS_FHSIZE 32
#endif
-#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
-#define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2)
-#define MAX_MNTPROT ((nfs_mount_version >= 4) ? 3 : 2)
-#define HAVE_RELIABLE_TCP (nfs_mount_version >= 4)
-
#ifndef HAVE_INET_ATON
#define inet_aton(a,b) (0)
#endif
mnt3res_t nfsv3;
} mntres_t;
+extern int nfs_mount_data_version;
extern int verbose;
extern int sloppy;
-/* Define the order in which to probe for UDP/TCP services */
-enum plist {
- use_tcp = 0,
- udp_tcp,
- udp_only,
+extern int linux_version_code();
+
+static const unsigned int probe_udp_only[] = {
+ IPPROTO_UDP,
+ 0,
};
-static const u_int *
-proto_probelist(enum plist list)
-{
- static const u_int probe_udp_tcp[] = { IPPROTO_UDP, IPPROTO_TCP, 0 };
- static const u_int probe_both[] = { IPPROTO_TCP, IPPROTO_UDP, 0 };
- static const u_int probe_udponly[] = { IPPROTO_UDP, 0 };
-
- if (list == use_tcp)
- return probe_both;
- if (list == udp_tcp)
- return probe_udp_tcp;
- return probe_udponly;
-}
-/* Define the order in which NFS versions are probed on portmapper */
-static const u_long *
-nfs_probelist(const int vers)
-{
- static const u_long nfs2_probe[] = { 2, 0};
- static const u_long nfs3_probe[] = { 3, 2, 0};
- switch (vers) {
- case 3:
- return nfs3_probe;
- default:
- return nfs2_probe;
- }
-}
+static const unsigned int probe_udp_first[] = {
+ IPPROTO_UDP,
+ IPPROTO_TCP,
+ 0,
+};
-/* Define the order in which Mountd versions are probed on portmapper */
-static const u_long *
-mnt_probelist(const int vers)
-{
- static const u_long mnt1_probe[] = { 1, 2, 0 };
- static const u_long mnt3_probe[] = { 3, 1, 2, 0 };
- switch (vers) {
- case 3:
- return mnt3_probe;
- default:
- return mnt1_probe;
- }
-}
+static const unsigned int probe_tcp_first[] = {
+ IPPROTO_TCP,
+ IPPROTO_UDP,
+ 0,
+};
-static int
-linux_version_code(void) {
- struct utsname my_utsname;
- int p, q, r;
-
- if (uname(&my_utsname) == 0) {
- p = atoi(strtok(my_utsname.release, "."));
- q = atoi(strtok(NULL, "."));
- r = atoi(strtok(NULL, "."));
- return MAKE_VERSION(p,q,r);
- }
- return 0;
-}
+static const unsigned long probe_nfs2_only[] = {
+ 2,
+ 0,
+};
-/*
- * Unfortunately, the kernel prints annoying console messages
- * in case of an unexpected nfs mount version (instead of
- * just returning some error). Therefore we'll have to try
- * and figure out what version the kernel expects.
- *
- * Variables:
- * NFS_MOUNT_VERSION: these nfsmount sources at compile time
- * nfs_mount_version: version this source and running kernel can handle
- */
-int nfs_mount_version = NFS_MOUNT_VERSION;
+static const unsigned long probe_nfs3_first[] = {
+ 3,
+ 2,
+ 0,
+};
-int
-find_kernel_nfs_mount_version(void) {
- static int kernel_version = -1;
- int mnt_version = NFS_MOUNT_VERSION;
-
- if (kernel_version == -1)
- kernel_version = linux_version_code();
-
- if (kernel_version) {
- if (kernel_version < MAKE_VERSION(2,1,32))
- mnt_version = 1;
- else if (kernel_version < MAKE_VERSION(2,2,18))
- mnt_version = 3;
- else if (kernel_version < MAKE_VERSION(2,3,0))
- mnt_version = 4; /* since 2.2.18pre9 */
- else if (kernel_version < MAKE_VERSION(2,3,99))
- mnt_version = 3;
- else if (kernel_version < MAKE_VERSION(2,6,3))
- mnt_version = 4;
- else
- mnt_version = 6;
- }
- if (mnt_version > NFS_MOUNT_VERSION)
- mnt_version = NFS_MOUNT_VERSION;
- return mnt_version;
-}
+static const unsigned long probe_mnt1_first[] = {
+ 1,
+ 2,
+ 0,
+};
+
+static const unsigned long probe_mnt3_first[] = {
+ 3,
+ 1,
+ 2,
+ 0,
+};
int nfs_gethostbyname(const char *, struct sockaddr_in *);
int nfs_gethostbyname(const char *hostname, struct sockaddr_in *saddr)
return 1;
}
-static int
-probe_nfsport(clnt_addr_t *nfs_server)
+static int probe_nfsport(clnt_addr_t *nfs_server)
{
- const struct pmap *pmap = &nfs_server->pmap;
- const u_long *probe_vers;
- const u_int *probe_prot;
+ struct pmap *pmap = &nfs_server->pmap;
if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
return 1;
- probe_vers = nfs_probelist(MAX_NFSPROT);
- probe_prot = proto_probelist(HAVE_RELIABLE_TCP ? use_tcp : udp_only);
- return probe_port(nfs_server, probe_vers, probe_prot);
+
+ if (nfs_mount_data_version >= 4)
+ return probe_port(nfs_server, probe_nfs3_first, probe_tcp_first);
+ else
+ return probe_port(nfs_server, probe_nfs2_only, probe_udp_only);
}
int probe_mntport(clnt_addr_t *mnt_server)
{
- const struct pmap *pmap = &mnt_server->pmap;
- const u_long *probe_vers;
- const u_int *probe_prot;
+ struct pmap *pmap = &mnt_server->pmap;
if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
return 1;
- probe_vers = mnt_probelist(MAX_MNTPROT);
- probe_prot = proto_probelist(HAVE_RELIABLE_TCP ? udp_tcp : udp_only);
- return probe_port(mnt_server, probe_vers, probe_prot);
+
+ if (nfs_mount_data_version >= 4)
+ return probe_port(mnt_server, probe_mnt3_first, probe_udp_first);
+ else
+ return probe_port(mnt_server, probe_mnt1_first, probe_udp_only);
}
static int
struct pmap *mnt_pmap = &mnt_server->pmap;
struct pmap save_nfs, save_mnt;
int res;
- const u_long *probe_vers;
+ const unsigned long *probe_vers;
if (mnt_pmap->pm_vers && !nfs_pmap->pm_vers)
nfs_pmap->pm_vers = mntvers_to_nfs(mnt_pmap->pm_vers);
mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers);
if (nfs_pmap->pm_vers)
goto version_fixed;
+
memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
- for (probe_vers = mnt_probelist(MAX_MNTPROT); *probe_vers; probe_vers++) {
+ probe_vers = (nfs_mount_data_version >= 4) ?
+ probe_mnt3_first : probe_mnt1_first;
+
+ for (; *probe_vers; probe_vers++) {
nfs_pmap->pm_vers = mntvers_to_nfs(*probe_vers);
if ((res = probe_nfsport(nfs_server) != 0)) {
mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers);
}
memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
}
- out_bad:
+
+out_bad:
return 0;
- version_fixed:
+
+version_fixed:
if (!probe_nfsport(nfs_server))
goto out_bad;
return probe_mntport(mnt_server);
opt = "nfsvers";
#if NFS_MOUNT_VERSION >= 2
} else if (!strcmp(opt, "namlen")) {
- if (nfs_mount_version >= 2)
+ if (nfs_mount_data_version >= 2)
data->namlen = val;
else if (sloppy)
continue;
#if NFS_MOUNT_VERSION >= 2
data->flags &= ~NFS_MOUNT_TCP;
} else if (!strcmp(opteq+1, "tcp") &&
- nfs_mount_version > 2) {
+ nfs_mount_data_version > 2) {
nfs_pmap->pm_prot = IPPROTO_TCP;
mnt_pmap->pm_prot = IPPROTO_TCP;
data->flags |= NFS_MOUNT_TCP;
} else if (!strcmp(opt, "sec")) {
char *secflavor = opteq+1;
/* see RFC 2623 */
- if (nfs_mount_version < 5) {
+ if (nfs_mount_data_version < 5) {
printf(_("Warning: ignoring sec=%s option\n"), secflavor);
continue;
} else if (!strcmp(secflavor, "none"))
} else if (!strcmp(opt, "tcp")) {
data->flags &= ~NFS_MOUNT_TCP;
if (val) {
- if (nfs_mount_version < 2)
+ if (nfs_mount_data_version < 2)
goto bad_option;
nfs_pmap->pm_prot = IPPROTO_TCP;
mnt_pmap->pm_prot = IPPROTO_TCP;
} else if (!strcmp(opt, "udp")) {
data->flags &= ~NFS_MOUNT_TCP;
if (!val) {
- if (nfs_mount_version < 2)
+ if (nfs_mount_data_version < 2)
goto bad_option;
nfs_pmap->pm_prot = IPPROTO_TCP;
mnt_pmap->pm_prot = IPPROTO_TCP;
} else if (!strcmp(opt, "lock")) {
data->flags &= ~NFS_MOUNT_NONLM;
if (!val) {
- if (nfs_mount_version < 3)
+ if (nfs_mount_data_version < 3)
goto bad_option;
data->flags |= NFS_MOUNT_NONLM;
}
} else if (!strcmp(opt, "broken_suid")) {
data->flags &= ~NFS_MOUNT_BROKEN_SUID;
if (val) {
- if (nfs_mount_version < 4)
+ if (nfs_mount_data_version < 4)
goto bad_option;
data->flags |= NFS_MOUNT_BROKEN_SUID;
}
return 0;
}
-static inline int
-nfsmnt_check_compat(const struct pmap *nfs_pmap, const struct pmap *mnt_pmap)
+static int nfsmnt_check_compat(const struct pmap *nfs_pmap,
+ const struct pmap *mnt_pmap)
{
- if (nfs_pmap->pm_vers &&
- (nfs_pmap->pm_vers > MAX_NFSPROT || nfs_pmap->pm_vers < 2)) {
- if (nfs_pmap->pm_vers == 4)
- fprintf(stderr, _("'vers=4' is not supported. "
- "Use '-t nfs4' instead.\n"));
- else
- fprintf(stderr, _("NFS version %ld is not supported.\n"),
- nfs_pmap->pm_vers);
+ unsigned int max_nfs_vers = (nfs_mount_data_version >= 4) ? 3 : 2;
+ unsigned int max_mnt_vers = (nfs_mount_data_version >= 4) ? 3 : 2;
+
+ if (nfs_pmap->pm_vers == 4) {
+ fprintf(stderr, _("Please use '-t nfs4' "
+ "instead of '-o vers=4'.\n"));
goto out_bad;
}
- if (mnt_pmap->pm_vers > MAX_MNTPROT) {
+
+ if (nfs_pmap->pm_vers) {
+ if (nfs_pmap->pm_vers > max_nfs_vers || nfs_pmap->pm_vers < 2) {
+ fprintf(stderr, _("NFS version %ld is not supported.\n"),
+ nfs_pmap->pm_vers);
+ goto out_bad;
+ }
+ }
+
+ if (mnt_pmap->pm_vers > max_mnt_vers) {
fprintf(stderr, _("NFS mount version %ld s not supported.\n"),
mnt_pmap->pm_vers);
goto out_bad;
}
+
return 1;
- out_bad:
+
+out_bad:
return 0;
}
time_t prevt;
time_t timeout;
- nfs_mount_version = find_kernel_nfs_mount_version();
-
if (strlen(spec) >= sizeof(hostdir)) {
fprintf(stderr, _("mount: "
"excessively long host:dir argument\n"));
printf("\n");
#endif
- data.version = nfs_mount_version;
+ data.version = nfs_mount_data_version;
*mount_opts = (char *) &data;
if (*flags & MS_REMOUNT)
#endif
}
- if (nfs_mount_version == 1) {
+ if (nfs_mount_data_version == 1) {
/* create nfs socket for kernel */
if (nfs_pmap->pm_prot == IPPROTO_TCP)
fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);