diff options
author | sam <sam@FreeBSD.org> | 2006-12-06 02:15:25 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2006-12-06 02:15:25 +0000 |
commit | 17d1a5f84e80a69f2a8b2156001c5862f7c00afa (patch) | |
tree | 10aef5be481908cc63670873bf28cc9564a245d3 /sys/nfsclient | |
parent | a1536822a00c107949772c22d9e2d2d60257f121 (diff) | |
download | FreeBSD-src-17d1a5f84e80a69f2a8b2156001c5862f7c00afa.zip FreeBSD-src-17d1a5f84e80a69f2a8b2156001c5862f7c00afa.tar.gz |
consolidate parsing of nfs root mount options in one place
and handle all options (some may require fixes elsewhere)
Reviewed by: jhb, mohans
MFC after: 1 month
Diffstat (limited to 'sys/nfsclient')
-rw-r--r-- | sys/nfsclient/bootp_subr.c | 43 | ||||
-rw-r--r-- | sys/nfsclient/nfs_diskless.c | 75 | ||||
-rw-r--r-- | sys/nfsclient/nfs_vfsops.c | 9 | ||||
-rw-r--r-- | sys/nfsclient/nfsdiskless.h | 1 |
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 |