summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/nfsclient/bootp_subr.c43
-rw-r--r--sys/nfsclient/nfs_diskless.c75
-rw-r--r--sys/nfsclient/nfs_vfsops.c9
-rw-r--r--sys/nfsclient/nfsdiskless.h1
4 files changed, 77 insertions, 51 deletions
diff --git a/sys/nfsclient/bootp_subr.c b/sys/nfsclient/bootp_subr.c
index 67a4b25..3a31353 100644
--- a/sys/nfsclient/bootp_subr.c
+++ b/sys/nfsclient/bootp_subr.c
@@ -220,7 +220,6 @@ static int setfs(struct sockaddr_in *addr, char *path, char *p,
const struct in_addr *siaddr);
static int getdec(char **ptr);
static int getip(char **ptr, struct in_addr *ip);
-static char *substr(char *a, char *b);
static void mountopts(struct nfs_args *args, char *p);
static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len);
static int xdr_int_decode(struct mbuf **ptr, int *iptr);
@@ -1234,53 +1233,16 @@ getdec(char **ptr)
return ret;
}
-static char *
-substr(char *a, char *b)
-{
- char *loc1;
- char *loc2;
-
- while (*a != '\0') {
- loc1 = a;
- loc2 = b;
- while (*loc1 == *loc2++) {
- if (*loc1 == '\0')
- return 0;
- loc1++;
- if (*loc2 == '\0')
- return loc1;
- }
- a++;
- }
- return 0;
-}
-
static void
mountopts(struct nfs_args *args, char *p)
{
- char *tmp;
-
args->version = NFS_ARGSVERSION;
args->rsize = 8192;
args->wsize = 8192;
args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT;
args->sotype = SOCK_DGRAM;
- if (p == NULL)
- return;
- if ((tmp = (char *)substr(p, "rsize=")))
- args->rsize = getdec(&tmp);
- if ((tmp = (char *)substr(p, "wsize=")))
- args->wsize = getdec(&tmp);
- if ((tmp = (char *)substr(p, "intr")))
- args->flags |= NFSMNT_INT;
- if ((tmp = (char *)substr(p, "soft")))
- args->flags |= NFSMNT_SOFT;
- if ((tmp = (char *)substr(p, "noconn")))
- args->flags |= NFSMNT_NOCONN;
- if ((tmp = (char *)substr(p, "nolockd")))
- args->flags |= NFSMNT_NOLOCKD;
- if ((tmp = (char *)substr(p, "tcp")))
- args->sotype = SOCK_STREAM;
+ if (p != NULL)
+ nfs_parse_options(p, args);
}
static int
@@ -1816,6 +1778,7 @@ md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep,
int authcount;
int authver;
+ /* XXX honor v2/v3 flags in args->flags? */
#ifdef BOOTP_NFSV3
/* First try NFS v3 */
/* Get port number for MOUNTD. */
diff --git a/sys/nfsclient/nfs_diskless.c b/sys/nfsclient/nfs_diskless.c
index bc62b50..4825d31 100644
--- a/sys/nfsclient/nfs_diskless.c
+++ b/sys/nfsclient/nfs_diskless.c
@@ -60,10 +60,34 @@ static int inaddr_to_sockaddr(char *ev, struct sockaddr_in *sa);
static int hwaddr_to_sockaddr(char *ev, struct sockaddr_dl *sa);
static int decode_nfshandle(char *ev, u_char *fh);
-static void
-nfs_parse_options(const char *envopts, struct nfs_diskless *nd)
+/*
+ * Validate/sanity check a rsize/wsize parameter.
+ */
+static int
+checkrwsize(unsigned long v, const char *name)
+{
+ /*
+ * 32K is used as an upper bound because most servers
+ * limit block size to satisfy IPv4's limit of
+ * 64K/reassembled packet. The lower bound is pretty
+ * much arbitrary.
+ */
+ if (!(4 <= v && v <= 32*1024)) {
+ printf("nfs_parse_options: invalid %s %lu ignored\n", name, v);
+ return 0;
+ } else
+ return 1;
+}
+
+/*
+ * Parse mount options and apply them to the supplied
+ * nfs_diskless state. Used also by bootp/dhcp support.
+ */
+void
+nfs_parse_options(const char *envopts, struct nfs_args *nd)
{
char *opts, *o, *otmp;
+ unsigned long v;
opts = strdup(envopts, M_TEMP);
otmp = opts;
@@ -71,15 +95,37 @@ nfs_parse_options(const char *envopts, struct nfs_diskless *nd)
if (*o == '\0')
; /* Skip empty options. */
else if (strcmp(o, "soft") == 0)
- nd->root_args.flags |= NFSMNT_SOFT;
+ nd->flags |= NFSMNT_SOFT;
else if (strcmp(o, "intr") == 0)
- nd->root_args.flags |= NFSMNT_INT;
+ nd->flags |= NFSMNT_INT;
else if (strcmp(o, "conn") == 0)
- nd->root_args.flags |= NFSMNT_NOCONN;
+ nd->flags |= NFSMNT_NOCONN;
else if (strcmp(o, "nolockd") == 0)
- nd->root_args.flags |= NFSMNT_NOLOCKD;
- else
- printf("nfs_diskless: unknown option: %s\n", o);
+ nd->flags |= NFSMNT_NOLOCKD;
+ else if (strcmp(o, "nfsv2") == 0)
+ nd->flags &= ~(NFSMNT_NFSV3 | NFSMNT_NFSV4);
+ else if (strcmp(o, "nfsv3") == 0) {
+ nd->flags &= ~NFSMNT_NFSV4;
+ nd->flags |= NFSMNT_NFSV3;
+ } else if (strcmp(o, "tcp") == 0)
+ nd->sotype = SOCK_STREAM;
+ else if (strcmp(o, "udp") == 0)
+ nd->sotype = SOCK_DGRAM;
+ else if (strncmp(o, "rsize=", 6) == 0) {
+ v = strtoul(o+6, NULL, 10);
+ if (checkrwsize(v, "rsize")) {
+ nd->rsize = (int) v;
+ nd->flags |= NFSMNT_RSIZE;
+ }
+ } else if (strncmp(o, "wsize=", 6) == 0) {
+ v = strtoul(o+6, NULL, 10);
+ if (checkrwsize(v, "wsize")) {
+ nd->wsize = (int) v;
+ nd->flags |= NFSMNT_WSIZE;
+ }
+ } else
+ printf("%s: skipping unknown option \"%s\"\n",
+ __func__, o);
}
free(opts, M_TEMP);
}
@@ -174,7 +220,18 @@ match_done:
freeenv(cp);
}
if ((cp = getenv("boot.nfsroot.options")) != NULL) {
- nfs_parse_options(cp, nd);
+ struct nfs_args args;
+
+ /* XXX yech, convert between old and current arg format */
+ args.flags = nd->root_args.flags;
+ args.sotype = nd->root_args.sotype;
+ args.rsize = nd->root_args.rsize;
+ args.wsize = nd->root_args.wsize;
+ nfs_parse_options(cp, &args);
+ nd->root_args.flags = args.flags;
+ nd->root_args.sotype = args.sotype;
+ nd->root_args.rsize = args.rsize;
+ nd->root_args.wsize = args.wsize;
freeenv(cp);
}
diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c
index ee4c977..653c946 100644
--- a/sys/nfsclient/nfs_vfsops.c
+++ b/sys/nfsclient/nfs_vfsops.c
@@ -223,8 +223,13 @@ nfs_convert_diskless(void)
bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
sizeof(struct sockaddr_in));
nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
- nfsv3_diskless.root_fhsize = NFSX_V2FH;
- bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
+ if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
+ nfsv3_diskless.root_fhsize = NFSX_V3FH;
+ bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V3FH);
+ } else {
+ nfsv3_diskless.root_fhsize = NFSX_V2FH;
+ bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
+ }
bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
sizeof(struct sockaddr_in));
bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
diff --git a/sys/nfsclient/nfsdiskless.h b/sys/nfsclient/nfsdiskless.h
index 69ee035..aa2bc04 100644
--- a/sys/nfsclient/nfsdiskless.h
+++ b/sys/nfsclient/nfsdiskless.h
@@ -108,6 +108,7 @@ extern struct nfs_diskless nfs_diskless;
extern int nfs_diskless_valid;
void bootpc_init(void);
void nfs_setup_diskless(void);
+void nfs_parse_options(const char *, struct nfs_args *);
#endif
#endif
OpenPOWER on IntegriCloud