summaryrefslogtreecommitdiffstats
path: root/sbin/mount_nfs/mount_nfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/mount_nfs/mount_nfs.c')
-rw-r--r--sbin/mount_nfs/mount_nfs.c697
1 files changed, 406 insertions, 291 deletions
diff --git a/sbin/mount_nfs/mount_nfs.c b/sbin/mount_nfs/mount_nfs.c
index f12473c..2f8308f 100644
--- a/sbin/mount_nfs/mount_nfs.c
+++ b/sbin/mount_nfs/mount_nfs.c
@@ -82,7 +82,6 @@ __FBSDID("$FreeBSD$");
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
-#include <nfsclient/nfsargs.h>
#include <arpa/inet.h>
@@ -101,85 +100,9 @@ __FBSDID("$FreeBSD$");
#include "mntopts.h"
#include "mounttab.h"
-#define ALTF_BG 0x1
-#define ALTF_NOCONN 0x2
-#define ALTF_DUMBTIMR 0x4
-#define ALTF_INTR 0x8
-#define ALTF_NFSV3 0x20
-#define ALTF_RDIRPLUS 0x40
-#define ALTF_MNTUDP 0x80
-#define ALTF_RESVPORT 0x100
-#define ALTF_SEQPACKET 0x200
-#define ALTF_SOFT 0x800
-#define ALTF_TCP 0x1000
-#define ALTF_PORT 0x2000
-#define ALTF_NFSV2 0x4000
-#define ALTF_ACREGMIN 0x8000
-#define ALTF_ACREGMAX 0x10000
-#define ALTF_ACDIRMIN 0x20000
-#define ALTF_ACDIRMAX 0x40000
-#define ALTF_NOLOCKD 0x80000
-#define ALTF_NOINET4 0x100000
-#define ALTF_NOINET6 0x200000
-
-struct mntopt mopts[] = {
- MOPT_STDOPTS,
- MOPT_FORCE,
- MOPT_UPDATE,
- MOPT_ASYNC,
- { "bg", 0, ALTF_BG, 1 },
- { "fg", 1, ALTF_BG, 1 },
- { "conn", 1, ALTF_NOCONN, 1 },
- { "dumbtimer", 0, ALTF_DUMBTIMR, 1 },
- { "intr", 0, ALTF_INTR, 1 },
- { "nfsv3", 0, ALTF_NFSV3, 1 },
- { "rdirplus", 0, ALTF_RDIRPLUS, 1 },
- { "mntudp", 0, ALTF_MNTUDP, 1 },
- { "resvport", 0, ALTF_RESVPORT, 1 },
- { "soft", 0, ALTF_SOFT, 1 },
- { "hard", 1, ALTF_SOFT, 1 },
- { "tcp", 0, ALTF_TCP, 1 },
- { "port=", 0, ALTF_PORT, 1 },
- { "nfsv2", 0, ALTF_NFSV2, 1 },
- { "acregmin=", 0, ALTF_ACREGMIN, 1 },
- { "acregmax=", 0, ALTF_ACREGMAX, 1 },
- { "acdirmin=", 0, ALTF_ACDIRMIN, 1 },
- { "acdirmax=", 0, ALTF_ACDIRMAX, 1 },
- { "lockd", 1, ALTF_NOLOCKD, 1 },
- { "inet4", 1, ALTF_NOINET4, 1 },
- { "inet6", 1, ALTF_NOINET6, 1 },
- MOPT_END
-};
-
-struct nfs_args nfsdefargs = {
- NFS_ARGSVERSION,
- NULL,
- sizeof (struct sockaddr_in),
- SOCK_STREAM,
- 0,
- NULL,
- 0,
- NFSMNT_RESVPORT,
- NFS_WSIZE,
- NFS_RSIZE,
- NFS_READDIRSIZE,
- 10,
- NFS_RETRANS,
- NFS_MAXGRPS,
- NFS_DEFRAHEAD,
- 0, /* was: NQ_DEFLEASE */
- NFS_MAXDEADTHRESH, /* was: NQ_DEADTHRESH */
- NULL,
- /* args version 4 */
- NFS_MINATTRTIMO,
- NFS_MAXATTRTIMO,
- NFS_MINDIRATTRTIMO,
- NFS_MAXDIRATTRTIMO,
-};
-
/* Table for af,sotype -> netid conversions. */
struct nc_protos {
- char *netid;
+ const char *netid;
int af;
int sotype;
} nc_protos[] = {
@@ -205,7 +128,13 @@ int retrycnt = -1;
int opflags = 0;
int nfsproto = IPPROTO_UDP;
int mnttcp_ok = 1;
+int noconn = 0;
char *portspec = NULL; /* Server nfs port; NULL means look up via rpcbind. */
+struct sockaddr *addr;
+int addrlen = 0;
+u_char *fh = NULL;
+int fhsize = 0;
+
enum mountmode {
ANY,
V2,
@@ -221,65 +150,25 @@ enum tryret {
TRYRET_LOCALERR /* Local failure. */
};
-int getnfsargs(char *, struct nfs_args *);
-int getnfs4args(char *, struct nfs_args *);
+int fallback_mount(struct iovec *iov, int iovlen, int mntflags);
+int getnfsargs(char *, struct iovec **iov, int *iovlen);
+int getnfs4args(char *, struct iovec **iov, int *iovlen);
/* void set_rpc_maxgrouplist(int); */
struct netconfig *getnetconf_cached(const char *netid);
-char *netidbytype(int af, int sotype);
+const char *netidbytype(int af, int sotype);
void usage(void) __dead2;
int xdr_dir(XDR *, char *);
int xdr_fh(XDR *, struct nfhret *);
-enum tryret nfs_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai,
- char *hostp, char *spec, char **errstr);
-enum tryret nfs4_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai,
- char *hostp, char *spec, char **errstr);
+enum tryret nfs_tryproto(struct addrinfo *ai, char *hostp, char *spec,
+ char **errstr, struct iovec **iov, int *iovlen);
+enum tryret nfs4_tryproto(struct addrinfo *ai, char *hostp, char *spec,
+ char **errstr);
enum tryret returncode(enum clnt_stat stat, struct rpc_err *rpcerr);
-/*
- * Used to set mount flags with getmntopts. Call with dir=TRUE to
- * initialize altflags from the current mount flags. Call with
- * dir=FALSE to update mount flags with the new value of altflags after
- * the call to getmntopts.
- */
-static void
-set_flags(int* altflags, int* nfsflags, int dir)
-{
-#define F2(af, nf) \
- if (dir) { \
- if (*nfsflags & NFSMNT_##nf) \
- *altflags |= ALTF_##af; \
- else \
- *altflags &= ~ALTF_##af; \
- } else { \
- if (*altflags & ALTF_##af) \
- *nfsflags |= NFSMNT_##nf; \
- else \
- *nfsflags &= ~NFSMNT_##nf; \
- }
-#define F(f) F2(f,f)
-
- F(NOCONN);
- F(DUMBTIMR);
- F2(INTR, INT);
- F(RDIRPLUS);
- F(RESVPORT);
- F(SOFT);
- F(ACREGMIN);
- F(ACREGMAX);
- F(ACDIRMIN);
- F(ACDIRMAX);
- F(NOLOCKD);
-
-#undef F
-#undef F2
-}
-
int
main(int argc, char *argv[])
{
int c;
- struct nfs_args *nfsargsp;
- struct nfs_args nfsargs;
struct iovec *iov;
int mntflags, altflags, num;
int iovlen;
@@ -288,8 +177,6 @@ main(int argc, char *argv[])
mntflags = 0;
altflags = 0;
- nfsargs = nfsdefargs;
- nfsargsp = &nfsargs;
iov = NULL;
iovlen = 0;
memset(errmsg, 0, sizeof(errmsg));
@@ -303,7 +190,7 @@ main(int argc, char *argv[])
if (strcmp(fstype, "nfs4") == 0) {
nfsproto = IPPROTO_TCP;
portspec = "2049";
- nfsdefargs.sotype = SOCK_STREAM;
+ build_iovec(&iov, &iovlen, "tcp", NULL, 0);
mountmode = V4;
}
@@ -321,173 +208,166 @@ main(int argc, char *argv[])
fstype = "nfs4";
break;
case 'a':
- num = strtol(optarg, &p, 10);
- if (*p || num < 0)
- errx(1, "illegal -a value -- %s", optarg);
- nfsargsp->readahead = num;
- nfsargsp->flags |= NFSMNT_READAHEAD;
+ printf("-a deprecated, use -o readhead=<value>\n");
+ build_iovec(&iov, &iovlen, "readahead", optarg, (size_t)-1);
break;
case 'b':
opflags |= BGRND;
break;
case 'c':
- nfsargsp->flags |= NFSMNT_NOCONN;
+ printf("-c deprecated, use -o noconn\n");
+ build_iovec(&iov, &iovlen, "noconn", NULL, 0);
+ noconn = 1;
break;
case 'D':
- num = strtol(optarg, &p, 10);
- if (*p || num <= 0)
- errx(1, "illegal -D value -- %s", optarg);
- nfsargsp->deadthresh = num;
- nfsargsp->flags |= NFSMNT_DEADTHRESH;
+ printf("-D deprecated, use -o deadthresh=<value>\n");
+ build_iovec(&iov, &iovlen, "deadthresh", optarg, (size_t)-1);
break;
case 'd':
- nfsargsp->flags |= NFSMNT_DUMBTIMR;
+ printf("-d deprecated, use -o dumbtimer");
+ build_iovec(&iov, &iovlen, "dumbtimer", NULL, 0);
break;
-#if 0 /* XXXX */
case 'g':
+ printf("-g deprecated, use -o maxgroups");
num = strtol(optarg, &p, 10);
if (*p || num <= 0)
errx(1, "illegal -g value -- %s", optarg);
- set_rpc_maxgrouplist(num);
- nfsargsp->maxgrouplist = num;
- nfsargsp->flags |= NFSMNT_MAXGRPS;
+ //set_rpc_maxgrouplist(num);
+ build_iovec(&iov, &iovlen, "maxgroups", optarg, (size_t)-1);
break;
-#endif
case 'I':
- num = strtol(optarg, &p, 10);
- if (*p || num <= 0)
- errx(1, "illegal -I value -- %s", optarg);
- nfsargsp->readdirsize = num;
- nfsargsp->flags |= NFSMNT_READDIRSIZE;
+ printf("-I deprecated, use -o readdirsize=<value>\n");
+ build_iovec(&iov, &iovlen, "readdirsize", optarg, (size_t)-1);
break;
case 'i':
- nfsargsp->flags |= NFSMNT_INT;
+ printf("-i deprecated, use -o intr\n");
+ build_iovec(&iov, &iovlen, "intr", NULL, 0);
break;
case 'L':
- nfsargsp->flags |= NFSMNT_NOLOCKD;
+ printf("-i deprecated, use -o nolockd\n");
+ build_iovec(&iov, &iovlen, "nolockd", NULL, 0);
break;
case 'l':
- nfsargsp->flags |= NFSMNT_RDIRPLUS;
+ printf("-l deprecated, -o rdirplus\n");
+ build_iovec(&iov, &iovlen, "rdirplus", NULL, 0);
break;
case 'N':
- nfsargsp->flags &= ~NFSMNT_RESVPORT;
+ printf("-N deprecated, do not specify -o resvport\n");
break;
- case 'o':
- altflags = 0;
- set_flags(&altflags, &nfsargsp->flags, TRUE);
- if (mountmode == V2)
- altflags |= ALTF_NFSV2;
- else if (mountmode == V3)
- altflags |= ALTF_NFSV3;
- getmntopts(optarg, mopts, &mntflags, &altflags);
- set_flags(&altflags, &nfsargsp->flags, FALSE);
- /*
- * Handle altflags which don't map directly to
- * mount flags.
- */
- if (altflags & ALTF_BG)
- opflags |= BGRND;
- if (altflags & ALTF_NOINET4)
- opflags |= OF_NOINET4;
- if (altflags & ALTF_NOINET6)
- opflags |= OF_NOINET6;
- if (altflags & ALTF_MNTUDP) {
- mnttcp_ok = 0;
- nfsargsp->sotype = SOCK_DGRAM;
- nfsproto = IPPROTO_UDP;
- }
- if (altflags & ALTF_TCP) {
- nfsargsp->sotype = SOCK_STREAM;
- nfsproto = IPPROTO_TCP;
- }
- if (altflags & ALTF_PORT) {
- /*
- * XXX Converting from a string to an int
- * and back again is silly, and we should
- * allow /etc/services names.
- */
- p = strstr(optarg, "port=");
- if (p) {
+ case 'o': {
+ int pass_flag_to_nmount;
+ char *opt = optarg;
+ while (opt) {
+ char *pval = NULL;
+ char *pnextopt = NULL;
+ char *val = "";
+ pass_flag_to_nmount = 1;
+ pval = strchr(opt, '=');
+ pnextopt = strchr(opt, ',');
+ if (pval != NULL) {
+ *pval = '\0';
+ val = pval + 1;
+ }
+ if (pnextopt) {
+ *pnextopt = '\0';
+ pnextopt++;
+ }
+ if (strcmp(opt, "bg") == 0) {
+ opflags |= BGRND;
+ pass_flag_to_nmount=0;
+ } else if (strcmp(opt, "fg") == 0) {
+ /* same as not specifying -o bg */
+ pass_flag_to_nmount=0;
+ } else if (strcmp(opt, "mntudp") == 0) {
+ mnttcp_ok = 0;
+ nfsproto = IPPROTO_UDP;
+ } else if (strcmp(opt, "udp") == 0) {
+ nfsproto = IPPROTO_UDP;
+ } else if (strcmp(opt, "tcp") == 0) {
+ nfsproto = IPPROTO_TCP;
+ } else if (strcmp(opt, "noinet4") == 0) {
+ pass_flag_to_nmount=0;
+ opflags |= OF_NOINET4;
+ } else if (strcmp(opt, "noinet6") == 0) {
+ pass_flag_to_nmount=0;
+ opflags |= OF_NOINET6;
+ } else if (strcmp(opt, "noconn") == 0) {
+ noconn = 1;
+ } else if (strcmp(opt, "nfsv2") == 0) {
+ pass_flag_to_nmount=0;
+ mountmode = V2;
+ } else if (strcmp(opt, "nfsv3") == 0) {
+ mountmode = V3;
+ } else if (strcmp(opt, "nfsv4") == 0) {
+ pass_flag_to_nmount=0;
+ mountmode = V4;
+ fstype = "nfs4";
+ } else if (strcmp(opt, "port") == 0) {
+ pass_flag_to_nmount=0;
asprintf(&portspec, "%d",
- atoi(p + 5));
+ atoi(val));
if (portspec == NULL)
err(1, "asprintf");
+ } else if (strcmp(opt, "retrycnt") == 0) {
+ pass_flag_to_nmount=0;
+ num = strtol(val, &p, 10);
+ if (*p || num < 0)
+ errx(1, "illegal retrycnt value -- %s", val);
+ retrycnt = num;
+ } else if (strcmp(opt, "maxgroups") == 0) {
+ num = strtol(val, &p, 10);
+ if (*p || num <= 0)
+ errx(1, "illegal maxgroups value -- %s", val);
+ //set_rpc_maxgrouplist(num);
}
+ if (pass_flag_to_nmount)
+ build_iovec(&iov, &iovlen, opt, val,
+ strlen(val) + 1);
+ opt = pnextopt;
}
- mountmode = ANY;
- if (altflags & ALTF_NFSV2)
- mountmode = V2;
- if (altflags & ALTF_NFSV3)
- mountmode = V3;
- if (altflags & ALTF_ACREGMIN) {
- p = strstr(optarg, "acregmin=");
- if (p)
- nfsargsp->acregmin = atoi(p + 9);
- }
- if (altflags & ALTF_ACREGMAX) {
- p = strstr(optarg, "acregmax=");
- if (p)
- nfsargsp->acregmax = atoi(p + 9);
- }
- if (altflags & ALTF_ACDIRMIN) {
- p = strstr(optarg, "acdirmin=");
- if (p)
- nfsargsp->acdirmin = atoi(p + 9);
- }
- if (altflags & ALTF_ACDIRMAX) {
- p = strstr(optarg, "acdirmax=");
- if (p)
- nfsargsp->acdirmax = atoi(p + 9);
}
break;
case 'P':
- /* obsolete for NFSMNT_RESVPORT, now default */
+ /* obsolete for -o noresvport now default */
+ printf("-P deprecated, use -o noresvport\n");
+ build_iovec(&iov, &iovlen, "noresvport", NULL, 0);
break;
case 'R':
+ printf("-R deprecated, use -o retrycnt=<retrycnt>\n");
num = strtol(optarg, &p, 10);
if (*p || num < 0)
errx(1, "illegal -R value -- %s", optarg);
retrycnt = num;
break;
case 'r':
- num = strtol(optarg, &p, 10);
- if (*p || num <= 0)
- errx(1, "illegal -r value -- %s", optarg);
- nfsargsp->rsize = num;
- nfsargsp->flags |= NFSMNT_RSIZE;
+ printf("-r deprecated, use -o rsize=<rsize>\n");
+ build_iovec(&iov, &iovlen, "rsize", optarg, (size_t)-1);
break;
case 's':
- nfsargsp->flags |= NFSMNT_SOFT;
+ printf("-s deprecated, use -o soft\n");
+ build_iovec(&iov, &iovlen, "soft", NULL, 0);
break;
case 'T':
- nfsargsp->sotype = SOCK_STREAM;
nfsproto = IPPROTO_TCP;
+ printf("-T deprecated, use -o tcp\n");
break;
case 't':
- num = strtol(optarg, &p, 10);
- if (*p || num <= 0)
- errx(1, "illegal -t value -- %s", optarg);
- nfsargsp->timeo = num;
- nfsargsp->flags |= NFSMNT_TIMEO;
+ printf("-t deprecated, use -o timeout=<value>\n");
+ build_iovec(&iov, &iovlen, "timeout", optarg, (size_t)-1);
break;
case 'w':
- num = strtol(optarg, &p, 10);
- if (*p || num <= 0)
- errx(1, "illegal -w value -- %s", optarg);
- nfsargsp->wsize = num;
- nfsargsp->flags |= NFSMNT_WSIZE;
+ printf("-w deprecated, use -o wsize=<value>\n");
+ build_iovec(&iov, &iovlen, "wsize", optarg, (size_t)-1);
break;
case 'x':
- num = strtol(optarg, &p, 10);
- if (*p || num <= 0)
- errx(1, "illegal -x value -- %s", optarg);
- nfsargsp->retrans = num;
- nfsargsp->flags |= NFSMNT_RETRANS;
+ printf("-x deprecated, use -o retrans=<value>\n");
+ build_iovec(&iov, &iovlen, "retrans", optarg, (size_t)-1);
break;
case 'U':
+ printf("-U deprecated, use -o mntudp\n");
mnttcp_ok = 0;
- nfsargsp->sotype = SOCK_DGRAM;
nfsproto = IPPROTO_UDP;
+ build_iovec(&iov, &iovlen, "mntudp", NULL, 0);
break;
default:
usage();
@@ -509,29 +389,243 @@ main(int argc, char *argv[])
retrycnt = 0;
if (mountmode == V4) {
- if (!getnfs4args(spec, nfsargsp))
+ if (!getnfs4args(spec, &iov, &iovlen))
exit(1);
} else {
- if (!getnfsargs(spec, nfsargsp))
+ if (!getnfsargs(spec, &iov, &iovlen))
exit(1);
}
/* resolve the mountpoint with realpath(3) */
(void)checkpath(name, mntpath);
- build_iovec(&iov, &iovlen, "nfs_args", nfsargsp, sizeof(*nfsargsp));
build_iovec(&iov, &iovlen, "fstype", fstype, (size_t)-1);
build_iovec(&iov, &iovlen, "fspath", mntpath, (size_t)-1);
build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
- if (nmount(iov, iovlen, mntflags))
- err(1, "%s, %s", mntpath, errmsg);
+ if (nmount(iov, iovlen, mntflags)) {
+ if (errno != ENOENT
+ || fallback_mount(iov, iovlen, mntflags))
+ err(1, "%s, %s", mntpath, errmsg);
+ }
exit(0);
}
+static int
+findopt(struct iovec *iov, int iovlen, const char *name,
+ char **valuep, int *lenp)
+{
+ int i;
+
+ for (i = 0; i < iovlen/2; i++, iov += 2) {
+ if (strcmp(name, iov[0].iov_base) == 0) {
+ if (valuep)
+ *valuep = iov[1].iov_base;
+ if (lenp)
+ *lenp = iov[1].iov_len;
+ return (0);
+ }
+ }
+ return (ENOENT);
+}
+
+static void
+copyopt(struct iovec **newiov, int *newiovlen,
+ struct iovec *iov, int iovlen, const char *name)
+{
+ char *value;
+ int len;
+
+ if (findopt(iov, iovlen, name, &value, &len) == 0)
+ build_iovec(newiov, newiovlen, name, value, len);
+}
+
int
-getnfsargs(char *spec, struct nfs_args *nfsargsp)
+fallback_mount(struct iovec *iov, int iovlen, int mntflags)
+{
+ struct nfs_args args = {
+ .version = NFS_ARGSVERSION,
+ .addr = NULL,
+ .addrlen = sizeof (struct sockaddr_in),
+ .sotype = SOCK_STREAM,
+ .proto = 0,
+ .fh = NULL,
+ .fhsize = 0,
+ .flags = NFSMNT_RESVPORT,
+ .wsize = NFS_WSIZE,
+ .rsize = NFS_RSIZE,
+ .readdirsize = NFS_READDIRSIZE,
+ .timeo = 10,
+ .retrans = NFS_RETRANS,
+ .maxgrouplist = NFS_MAXGRPS,
+ .readahead = NFS_DEFRAHEAD,
+ .wcommitsize = 0, /* was: NQ_DEFLEASE */
+ .deadthresh = NFS_MAXDEADTHRESH, /* was: NQ_DEADTHRESH */
+ .hostname = NULL,
+ /* args version 4 */
+ .acregmin = NFS_MINATTRTIMO,
+ .acregmax = NFS_MAXATTRTIMO,
+ .acdirmin = NFS_MINDIRATTRTIMO,
+ .acdirmax = NFS_MAXDIRATTRTIMO,
+ };
+ int ret;
+ char *opt;
+ struct iovec *newiov;
+ int newiovlen;
+
+ if (findopt(iov, iovlen, "dumbtimer", NULL, NULL) == 0)
+ args.flags |= NFSMNT_DUMBTIMR;
+ if (findopt(iov, iovlen, "noconn", NULL, NULL) == 0)
+ args.flags |= NFSMNT_NOCONN;
+ if (findopt(iov, iovlen, "conn", NULL, NULL) == 0)
+ args.flags |= NFSMNT_NOCONN;
+ if (findopt(iov, iovlen, "nolockd", NULL, NULL) == 0)
+ args.flags |= NFSMNT_NOLOCKD;
+ if (findopt(iov, iovlen, "lockd", NULL, NULL) == 0)
+ args.flags &= ~NFSMNT_NOLOCKD;
+ if (findopt(iov, iovlen, "intr", NULL, NULL) == 0)
+ args.flags |= NFSMNT_INT;
+ if (findopt(iov, iovlen, "rdirplus", NULL, NULL) == 0)
+ args.flags |= NFSMNT_RDIRPLUS;
+ if (findopt(iov, iovlen, "resvport", NULL, NULL) == 0)
+ args.flags |= NFSMNT_RESVPORT;
+ if (findopt(iov, iovlen, "noresvport", NULL, NULL) == 0)
+ args.flags &= ~NFSMNT_RESVPORT;
+ if (findopt(iov, iovlen, "soft", NULL, NULL) == 0)
+ args.flags |= NFSMNT_SOFT;
+ if (findopt(iov, iovlen, "hard", NULL, NULL) == 0)
+ args.flags &= ~NFSMNT_SOFT;
+ if (findopt(iov, iovlen, "mntudp", NULL, NULL) == 0)
+ args.sotype = SOCK_DGRAM;
+ if (findopt(iov, iovlen, "udp", NULL, NULL) == 0)
+ args.sotype = SOCK_DGRAM;
+ if (findopt(iov, iovlen, "tcp", NULL, NULL) == 0)
+ args.sotype = SOCK_STREAM;
+ if (findopt(iov, iovlen, "nfsv3", NULL, NULL) == 0)
+ args.flags |= NFSMNT_NFSV3;
+ if (findopt(iov, iovlen, "readdirsize", &opt, NULL) == 0) {
+ if (opt == NULL) {
+ errx(1, "illegal readdirsize");
+ }
+ ret = sscanf(opt, "%d", &args.readdirsize);
+ if (ret != 1 || args.readdirsize <= 0) {
+ errx(1, "illegal readdirsize: %s", opt);
+ }
+ args.flags |= NFSMNT_READDIRSIZE;
+ }
+ if (findopt(iov, iovlen, "readahead", &opt, NULL) == 0) {
+ if (opt == NULL) {
+ errx(1, "illegal readahead");
+ }
+ ret = sscanf(opt, "%d", &args.readahead);
+ if (ret != 1 || args.readahead <= 0) {
+ errx(1, "illegal readahead: %s", opt);
+ }
+ args.flags |= NFSMNT_READAHEAD;
+ }
+ if (findopt(iov, iovlen, "wsize", &opt, NULL) == 0) {
+ if (opt == NULL) {
+ errx(1, "illegal wsize");
+ }
+ ret = sscanf(opt, "%d", &args.wsize);
+ if (ret != 1 || args.wsize <= 0) {
+ errx(1, "illegal wsize: %s", opt);
+ }
+ args.flags |= NFSMNT_WSIZE;
+ }
+ if (findopt(iov, iovlen, "rsize", &opt, NULL) == 0) {
+ if (opt == NULL) {
+ errx(1, "illegal rsize");
+ }
+ ret = sscanf(opt, "%d", &args.rsize);
+ if (ret != 1 || args.rsize <= 0) {
+ errx(1, "illegal wsize: %s", opt);
+ }
+ args.flags |= NFSMNT_RSIZE;
+ }
+ if (findopt(iov, iovlen, "retrans", &opt, NULL) == 0) {
+ if (opt == NULL) {
+ errx(1, "illegal retrans");
+ }
+ ret = sscanf(opt, "%d", &args.retrans);
+ if (ret != 1 || args.retrans <= 0) {
+ errx(1, "illegal retrans: %s", opt);
+ }
+ args.flags |= NFSMNT_RETRANS;
+ }
+ if (findopt(iov, iovlen, "acregmin", &opt, NULL) == 0) {
+ ret = sscanf(opt, "%d", &args.acregmin);
+ if (ret != 1 || args.acregmin <= 0) {
+ errx(1, "illegal acregmin: %s", opt);
+ }
+ }
+ if (findopt(iov, iovlen, "acregmax", &opt, NULL) == 0) {
+ ret = sscanf(opt, "%d", &args.acregmax);
+ if (ret != 1 || args.acregmax <= 0) {
+ errx(1, "illegal acregmax: %s", opt);
+ }
+ }
+ if (findopt(iov, iovlen, "acdirmin", &opt, NULL) == 0) {
+ ret = sscanf(opt, "%d", &args.acdirmin);
+ if (ret != 1 || args.acdirmin <= 0) {
+ errx(1, "illegal acdirmin: %s", opt);
+ }
+ }
+ if (findopt(iov, iovlen, "acdirmax", &opt, NULL) == 0) {
+ ret = sscanf(opt, "%d", &args.acdirmax);
+ if (ret != 1 || args.acdirmax <= 0) {
+ errx(1, "illegal acdirmax: %s", opt);
+ }
+ }
+ if (findopt(iov, iovlen, "deadthresh", &opt, NULL) == 0) {
+ ret = sscanf(opt, "%d", &args.deadthresh);
+ if (ret != 1 || args.deadthresh <= 0) {
+ errx(1, "illegal deadthresh: %s", opt);
+ }
+ args.flags |= NFSMNT_DEADTHRESH;
+ }
+ if (findopt(iov, iovlen, "timeout", &opt, NULL) == 0) {
+ ret = sscanf(opt, "%d", &args.timeo);
+ if (ret != 1 || args.timeo <= 0) {
+ errx(1, "illegal timeout: %s", opt);
+ }
+ args.flags |= NFSMNT_TIMEO;
+ }
+ if (findopt(iov, iovlen, "maxgroups", &opt, NULL) == 0) {
+ ret = sscanf(opt, "%d", &args.maxgrouplist);
+ if (ret != 1 || args.timeo <= 0) {
+ errx(1, "illegal maxgroups: %s", opt);
+ }
+ args.flags |= NFSMNT_MAXGRPS;
+ }
+ if (findopt(iov, iovlen, "addr", &opt,
+ &args.addrlen) == 0) {
+ args.addr = (struct sockaddr *) opt;
+ }
+ if (findopt(iov, iovlen, "fh", &opt, &args.fhsize) == 0) {
+ args.fh = opt;
+ }
+ if (findopt(iov, iovlen, "hostname", &args.hostname,
+ NULL) == 0) {
+ }
+ if (args.hostname == NULL) {
+ errx(1, "Invalid hostname");
+ }
+
+ newiov = NULL;
+ newiovlen = 0;
+
+ build_iovec(&newiov, &newiovlen, "nfs_args", &args, sizeof(args));
+ copyopt(&newiov, &newiovlen, iov, iovlen, "fstype");
+ copyopt(&newiov, &newiovlen, iov, iovlen, "fspath");
+ copyopt(&newiov, &newiovlen, iov, iovlen, "errmsg");
+
+ return nmount(newiov, newiovlen, mntflags);
+}
+
+int
+getnfsargs(char *spec, struct iovec **iov, int *iovlen)
{
struct addrinfo hints, *ai_nfs, *ai;
enum tryret ret;
@@ -579,7 +673,11 @@ getnfsargs(char *spec, struct nfs_args *nfsargsp)
*/
memset(&hints, 0, sizeof hints);
hints.ai_flags = AI_NUMERICHOST;
- hints.ai_socktype = nfsargsp->sotype;
+ if (nfsproto == IPPROTO_TCP)
+ hints.ai_socktype = SOCK_STREAM;
+ else if (nfsproto == IPPROTO_UDP)
+ hints.ai_socktype = SOCK_DGRAM;
+
if (getaddrinfo(hostp, portspec, &hints, &ai_nfs) != 0) {
hints.ai_flags = 0;
if ((ecode = getaddrinfo(hostp, portspec, &hints, &ai_nfs))
@@ -607,7 +705,8 @@ getnfsargs(char *spec, struct nfs_args *nfsargsp)
if ((ai->ai_family == AF_INET) &&
(opflags & OF_NOINET4))
continue;
- ret = nfs_tryproto(nfsargsp, ai, hostp, spec, &errstr);
+ ret = nfs_tryproto(ai, hostp, spec, &errstr, iov,
+ iovlen);
if (ret == TRYRET_SUCCESS)
break;
if (ret != TRYRET_LOCALERR)
@@ -639,7 +738,8 @@ getnfsargs(char *spec, struct nfs_args *nfsargsp)
sleep(60);
}
freeaddrinfo(ai_nfs);
- nfsargsp->hostname = nam;
+
+ build_iovec(iov, iovlen, "hostname", nam, (size_t)-1);
/* Add mounted file system to PATH_MOUNTTAB */
if (!add_mtab(hostp, spec))
warnx("can't update %s for %s:%s", PATH_MOUNTTAB, hostp, spec);
@@ -648,15 +748,21 @@ getnfsargs(char *spec, struct nfs_args *nfsargsp)
int
-getnfs4args(char *spec, struct nfs_args *nfsargsp)
+getnfs4args(char *spec, struct iovec **iov, int *iovlen)
{
struct addrinfo hints, *ai_nfs, *ai;
enum tryret ret;
- int ecode, speclen, remoteerr;
+ int ecode, speclen, remoteerr, sotype;
char *hostp, *delimp, *errstr;
size_t len;
static char nam[MNAMELEN + 1];
+ if (nfsproto == IPPROTO_TCP)
+ sotype = SOCK_STREAM;
+ else if (nfsproto == IPPROTO_UDP)
+ sotype = SOCK_DGRAM;
+
+
if ((delimp = strrchr(spec, ':')) != NULL) {
hostp = spec;
spec = delimp + 1;
@@ -696,7 +802,7 @@ getnfs4args(char *spec, struct nfs_args *nfsargsp)
*/
memset(&hints, 0, sizeof hints);
hints.ai_flags = AI_NUMERICHOST;
- hints.ai_socktype = nfsargsp->sotype;
+ hints.ai_socktype = sotype;
if (getaddrinfo(hostp, portspec, &hints, &ai_nfs) != 0) {
hints.ai_flags = 0;
if ((ecode = getaddrinfo(hostp, portspec, &hints, &ai_nfs))
@@ -724,7 +830,7 @@ getnfs4args(char *spec, struct nfs_args *nfsargsp)
if ((ai->ai_family == AF_INET) &&
(opflags & OF_NOINET4))
continue;
- ret = nfs4_tryproto(nfsargsp, ai, hostp, spec, &errstr);
+ ret = nfs4_tryproto(ai, hostp, spec, &errstr);
if (ret == TRYRET_SUCCESS)
break;
if (ret != TRYRET_LOCALERR)
@@ -756,7 +862,7 @@ getnfs4args(char *spec, struct nfs_args *nfsargsp)
sleep(60);
}
freeaddrinfo(ai_nfs);
- nfsargsp->hostname = nam;
+ build_iovec(iov, iovlen, "hostname", nam, (size_t)-1);
/* Add mounted file system to PATH_MOUNTTAB */
if (!add_mtab(hostp, spec))
warnx("can't update %s for %s:%s", PATH_MOUNTTAB, hostp, spec);
@@ -776,8 +882,8 @@ getnfs4args(char *spec, struct nfs_args *nfsargsp)
* describing the error.
*/
enum tryret
-nfs_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai, char *hostp,
- char *spec, char **errstr)
+nfs_tryproto(struct addrinfo *ai, char *hostp, char *spec, char **errstr,
+ struct iovec **iov, int *iovlen)
{
static char errbuf[256];
struct sockaddr_storage nfs_ss;
@@ -787,8 +893,8 @@ nfs_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai, char *hostp,
struct rpc_err rpcerr;
CLIENT *clp;
struct netconfig *nconf, *nconf_mnt;
- char *netid, *netid_mnt;
- int doconnect, nfsvers, mntvers;
+ const char *netid, *netid_mnt;
+ int doconnect, nfsvers, mntvers, sotype;
enum clnt_stat stat;
enum mountmode trymntmode;
@@ -796,10 +902,14 @@ nfs_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai, char *hostp,
errbuf[0] = '\0';
*errstr = errbuf;
- if ((netid = netidbytype(ai->ai_family, nfsargsp->sotype)) == NULL) {
+ if (nfsproto == IPPROTO_TCP)
+ sotype = SOCK_STREAM;
+ else if (nfsproto == IPPROTO_UDP)
+ sotype = SOCK_DGRAM;
+
+ if ((netid = netidbytype(ai->ai_family, sotype)) == NULL) {
snprintf(errbuf, sizeof errbuf,
- "af %d sotype %d not supported", ai->ai_family,
- nfsargsp->sotype);
+ "af %d sotype %d not supported", ai->ai_family, sotype);
return (TRYRET_LOCALERR);
}
if ((nconf = getnetconf_cached(netid)) == NULL) {
@@ -867,8 +977,7 @@ tryagain:
return (returncode(rpc_createerr.cf_stat,
&rpc_createerr.cf_error));
}
- if (nfsargsp->sotype == SOCK_DGRAM &&
- !(nfsargsp->flags & NFSMNT_NOCONN)) {
+ if (sotype == SOCK_DGRAM && noconn == 0) {
/*
* Use connect(), to match what the kernel does. This
* catches cases where the server responds from the
@@ -914,7 +1023,7 @@ tryagain:
&rpc_createerr.cf_error));
}
clp->cl_auth = authsys_create_default();
- nfhret.auth = RPCAUTH_UNIX;
+ nfhret.auth = -1;
nfhret.vers = mntvers;
stat = clnt_call(clp, RPCMNT_MOUNT, (xdrproc_t)xdr_dir, spec,
(xdrproc_t)xdr_fh, &nfhret,
@@ -944,19 +1053,19 @@ tryagain:
* Store the filehandle and server address in nfsargsp, making
* sure to copy any locally allocated structures.
*/
- nfsargsp->addrlen = nfs_nb.len;
- nfsargsp->addr = malloc(nfsargsp->addrlen);
- nfsargsp->fhsize = nfhret.fhsize;
- nfsargsp->fh = malloc(nfsargsp->fhsize);
- if (nfsargsp->addr == NULL || nfsargsp->fh == NULL)
+ addrlen = nfs_nb.len;
+ addr = malloc(addrlen);
+ fhsize = nfhret.fhsize;
+ fh = malloc(fhsize);
+ if (addr == NULL || fh == NULL)
err(1, "malloc");
- bcopy(nfs_nb.buf, nfsargsp->addr, nfsargsp->addrlen);
- bcopy(nfhret.nfh, nfsargsp->fh, nfsargsp->fhsize);
+ bcopy(nfs_nb.buf, addr, addrlen);
+ bcopy(nfhret.nfh, fh, fhsize);
+ build_iovec(iov, iovlen, "addr", addr, addrlen);
+ build_iovec(iov, iovlen, "fh", fh, fhsize);
if (nfsvers == 3)
- nfsargsp->flags |= NFSMNT_NFSV3;
- else
- nfsargsp->flags &= ~NFSMNT_NFSV3;
+ build_iovec(iov, iovlen, "nfsv3", NULL, 0);
return (TRYRET_SUCCESS);
}
@@ -975,23 +1084,26 @@ tryagain:
* describing the error.
*/
enum tryret
-nfs4_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai, char *hostp,
- char *spec, char **errstr)
+nfs4_tryproto(struct addrinfo *ai, char *hostp, char *spec, char **errstr)
{
static char errbuf[256];
struct sockaddr_storage nfs_ss;
struct netbuf nfs_nb;
struct netconfig *nconf;
- char *netid;
- int nfsvers;
+ const char *netid;
+ int nfsvers, sotype;
errbuf[0] = '\0';
*errstr = errbuf;
- if ((netid = netidbytype(ai->ai_family, nfsargsp->sotype)) == NULL) {
+ if (nfsproto == IPPROTO_TCP)
+ sotype = SOCK_STREAM;
+ else if (nfsproto == IPPROTO_UDP)
+ sotype = SOCK_DGRAM;
+
+ if ((netid = netidbytype(ai->ai_family, sotype)) == NULL) {
snprintf(errbuf, sizeof errbuf,
- "af %d sotype %d not supported", ai->ai_family,
- nfsargsp->sotype);
+ "af %d sotype %d not supported", ai->ai_family, sotype);
return (TRYRET_LOCALERR);
}
if ((nconf = getnetconf_cached(netid)) == NULL) {
@@ -1024,15 +1136,12 @@ nfs4_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai, char *hostp,
* Store the filehandle and server address in nfsargsp, making
* sure to copy any locally allocated structures.
*/
- nfsargsp->addrlen = nfs_nb.len;
- nfsargsp->addr = malloc(nfsargsp->addrlen);
+ addrlen = nfs_nb.len;
+ addr = malloc(addrlen);
- if (nfsargsp->addr == NULL)
+ if (addr == NULL)
err(1, "malloc");
- bcopy(nfs_nb.buf, nfsargsp->addr, nfsargsp->addrlen);
-
- /* XXX hack */
- nfsargsp->flags |= (NFSMNT_NFSV3 | NFSMNT_NFSV4);
+ bcopy(nfs_nb.buf, addr, addrlen);
return (TRYRET_SUCCESS);
}
@@ -1076,7 +1185,7 @@ returncode(enum clnt_stat stat, struct rpc_err *rpcerr)
*
* XXX there should be a library function for this.
*/
-char *
+const char *
netidbytype(int af, int sotype)
{
struct nc_protos *p;
@@ -1156,14 +1265,20 @@ xdr_fh(XDR *xdrsp, struct nfhret *np)
for (i = 0; i < authcnt; i++) {
if (!xdr_long(xdrsp, &auth))
return (0);
- if (auth == np->auth)
+ if (np->auth == -1) {
+ np->auth = auth;
+ authfnd++;
+ } else if (auth == np->auth) {
authfnd++;
+ }
}
/*
* Some servers, such as DEC's OSF/1 return a nil authenticator
* list to indicate RPCAUTH_UNIX.
*/
- if (!authfnd && (authcnt > 0 || np->auth != RPCAUTH_UNIX))
+ if (authcnt == 0 && np->auth == -1)
+ np->auth = AUTH_SYS;
+ if (!authfnd && (authcnt > 0 || np->auth != AUTH_SYS))
np->stat = EAUTH;
return (1);
};
OpenPOWER on IntegriCloud