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
This commit is contained in:
sam 2006-12-06 02:15:25 +00:00
parent a1536822a0
commit 17d1a5f84e
4 changed files with 77 additions and 51 deletions

View File

@ -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. */

View File

@ -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 @@ nfs_setup_diskless(void)
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);
}

View File

@ -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);

View File

@ -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