diff options
Diffstat (limited to 'sbin/mount_nfs/mount_nfs.c')
-rw-r--r-- | sbin/mount_nfs/mount_nfs.c | 697 |
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); }; |