Date: Thu, 21 May 2009 11:55:33 -0400 (EDT) From: Rick Macklem <rmacklem@uoguelph.ca> To: freebsd-current@freebsd.org Subject: review of changes to mountd.c to add experimental server support Message-ID: <Pine.GSO.4.63.0905211151300.6977@muncher.cs.uoguelph.ca>
next in thread | raw e-mail | index | archive | help
In case anyone would like to review them, here are my proposed changes to src/usr.sbin/mountd.c so that it supports the experimental server as well as the regular one. It will run the experimental server if that is the only one loaded into the kernel or the "-4" option is specified on the command line. It parses one additional line in the exports file, which defines where the root of the nfsv4 file system is. This line is parsed but ignored for the regular server. Thanks in advance for any comments, rick --- diff -u mountd.c --- --- freebsd-svn/usr-src/usr.sbin/mountd/mountd.c 2009-05-17 15:59:31.000000000 -0400 +++ usr-src/usr.sbin/mountd/mountd.c 2009-05-19 09:47:58.000000000 -0400 @@ -61,7 +61,9 @@ #include <rpcsvc/mount.h> #include <nfs/rpcv2.h> #include <nfs/nfsproto.h> +#include <nfs/nfssvc.h> #include <nfsserver/nfs.h> +#include <fs/nfs/nfsport.h> #include <arpa/inet.h> @@ -200,6 +202,7 @@ struct sockaddr *samask); int scan_tree(struct dirlist *, struct sockaddr *); static void usage(void); +void parse_v4root(char *, char *, int, struct xucred *); int xdr_dir(XDR *, char *); int xdr_explist(XDR *, caddr_t); int xdr_explist_brief(XDR *, caddr_t); @@ -233,6 +236,10 @@ int opt_flags; static int have_v6 = 1; +int v4root_phase = 0; +int run_v4server = 0; +int has_publicfh = 0; + struct pidfh *pfh = NULL; /* Bits for opt_flags above */ #define OP_MAPROOT 0x01 @@ -288,17 +295,15 @@ have_v6 = 0; else close(s); - if (modfind("nfsserver") < 0) { - /* Not present in kernel, try loading it */ - if (kldload("nfsserver") < 0 || modfind("nfsserver") < 0) - errx(1, "NFS server is not available or loadable"); - } - while ((c = getopt(argc, argv, "2dh:lnp:r")) != -1) + while ((c = getopt(argc, argv, "24dh:lnp:r")) != -1) switch (c) { case '2': force_v2 = 1; break; + case '4': + run_v4server = 1; + break; case 'n': resvport_only = 0; break; @@ -343,6 +348,26 @@ default: usage(); }; + + /* + * If the "-4" option was specified OR only the nfsd module is + * found in the server, run "nfsd". + * Otherwise, try and run "nfsserver". + */ + if (run_v4server > 0) { + if (modfind("nfsd") < 0) { + /* Not present in kernel, try loading it */ + if (kldload("nfsd") < 0 || modfind("nfsd") < 0) + errx(1, "NFS server is not available"); + } + } else if (modfind("nfsserver") < 0 && modfind("nfsd") >= 0) { + run_v4server = 1; + } else if (modfind("nfsserver") < 0) { + /* Not present in kernel, try loading it */ + if (kldload("nfsserver") < 0 || modfind("nfsserver") < 0) + errx(1, "NFS server is not available"); + } + argc -= optind; argv += optind; grphead = (struct grouplist *)NULL; @@ -707,7 +732,7 @@ usage() { fprintf(stderr, - "usage: mountd [-2] [-d] [-l] [-n] [-p <port>] [-r] " + "usage: mountd [-2] [-4] [-d] [-l] [-n] [-p <port>] [-r] " "[-h <bindip>] [export_file ...]\n"); exit(1); } @@ -1166,6 +1191,26 @@ ep = (struct exportlist *)NULL; /* + * Handle the V4 root dir. + */ + if (*cp == 'V' && *(cp + 1) == '4' && *(cp + 2) == ':') { + /* + * V4: just indicates that it is the v4 root point, + * so skip over that and set v4root_phase. + */ + if (v4root_phase > 0) { + syslog(LOG_ERR, "V4:duplicate line, ignored"); + goto nextline; + } + v4root_phase = 1; + cp += 3; + nextfield(&cp, &endcp); + if (run_v4server > 0) + parse_v4root(cp, endcp, exflags, &anon); + goto nextline; + } + + /* * Create new exports list entry */ len = endcp-cp; @@ -1382,7 +1427,9 @@ int dirplen, num, i; int iovlen; int done; + struct nfsex_args eargs; + v4root_phase = 0; bzero(&export, sizeof(export)); export.ex_flags = MNT_DELEXPORT; dirp = NULL; @@ -1411,6 +1458,21 @@ grphead = (struct grouplist *)NULL; /* + * and the old V4 root dir. + */ + bzero(&eargs, sizeof (eargs)); + eargs.export.ex_flags = MNT_DELEXPORT; + if (run_v4server > 0 && + nfssvc(NFSSVC_V4ROOTEXPORT, (caddr_t)&eargs) < 0 && + errno != ENOENT) + syslog(LOG_ERR, "Can't delete exports for V4:"); + + /* + * and clear flag that notes if a public fh has been exported. + */ + has_publicfh = 0; + + /* * And delete exports that are in the kernel for all local * filesystems. * XXX: Should know how to handle all local exportable filesystems. @@ -1491,6 +1553,12 @@ syslog(LOG_ERR, "can't open any exports file"); exit(2); } + + /* + * If there was no public fh, clear any previous one set. + */ + if (run_v4server > 0 && has_publicfh == 0) + (void) nfssvc(NFSSVC_NOPUBLICFH, NULL); } /* @@ -1936,6 +2004,12 @@ syslog(LOG_ERR, "bad opt %s", cpopt); return (1); } + if (v4root_phase == 1 && + ((*exflagsp & ~MNT_EXPORTED) || + (opt_flags & ~OP_SEC))) { + syslog(LOG_ERR, "Bad opt %s on V4:", cpopt); + return (1); + } if (usedarg >= 0) { *endcp = savedc2; **endcpp = savedc; @@ -2233,6 +2307,29 @@ goto error_exit; } } + + /* + * For the experimental server: + * If this is the public directory, get the file handle + * and load it into the kernel via the nfssvc() syscall. + */ + if (run_v4server > 0 && (exflags & MNT_EXPUBLIC) != 0) { + fhandle_t fh; + char *public_name; + + if (eap.ex_indexfile != NULL) + public_name = eap.ex_indexfile; + else + public_name = dirp; + if (getfh(public_name, &fh) < 0) + syslog(LOG_ERR, + "Can't get public fh for %s", public_name); + else if (nfssvc(NFSSVC_PUBLICFH, (caddr_t)&fh) < 0) + syslog(LOG_ERR, + "Can't set public fh for %s", public_name); + else + has_publicfh = 1; + } skip: if (ai != NULL) ai = ai->ai_next; @@ -2688,7 +2785,7 @@ struct dirlist *dp; { - if (dp == (struct dirlist *)NULL) + if (v4root_phase != 1 && dp == NULL) return (1); if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL)) { syslog(LOG_ERR, "-mapall and -maproot mutually exclusive"); @@ -2710,6 +2807,12 @@ syslog(LOG_ERR, "-alldirs has multiple directories"); return (1); } + if (v4root_phase == 1) { + if ((opt_flags & ~OP_SEC) != 0) { + syslog(LOG_ERR, "only -sec option allowed on V4:"); + return (1); + } + } return (0); } @@ -2871,3 +2974,86 @@ rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); exit (0); } + +/* + * Parse the V4: line. + */ +void +parse_v4root(char *cp, char *endcp, int exflags, struct xucred *anonp) +{ + char *dirp, savedc; + struct grouplist gr; + struct exportlist ea; + struct nfsex_args nfsea; + int len, has_host, i; + + exflags = MNT_EXPORTED; + bzero(&nfsea, sizeof (nfsea)); + bzero(&ea, sizeof (ea)); + bzero(&gr, sizeof (gr)); + dirp = NULL; + len = endcp - cp; + while (len > 0) { + if (len > RPCMNT_NAMELEN) { + syslog(LOG_ERR, "V4: line too long, ignored"); + v4root_phase = 2; + return; + } + if (*cp == '-') { + if (debug) + warnx("doing opt %s", cp); + if (do_opt(&cp, &endcp, &ea, &gr, &has_host, + &exflags, anonp)) { + v4root_phase = 2; + return; + } + } else if (*cp == '/') { + savedc = *endcp; + *endcp = '\0'; + if (check_dirpath(cp)) { + if (dirp != NULL) { + syslog(LOG_ERR, "Multiple V4 dirs"); + v4root_phase = 2; + return; + } + dirp = cp; + } else { + syslog(LOG_ERR, "V4: dir %s invalid", cp); + v4root_phase = 2; + return; + } + *endcp = savedc; + } + cp = endcp; + nextfield(&cp, &endcp); + len = endcp - cp; + } + + /* Check the options */ + if (check_options(NULL)) { + v4root_phase = 2; + return; + } + + /* + * Now, do the nfssvc() syscall. + */ + nfsea.export.ex_flags = exflags; + nfsea.export.ex_anon = *anonp; + if (ea.ex_numsecflavors == 0) { + nfsea.export.ex_numsecflavors = 4; + nfsea.export.ex_secflavors[0] = AUTH_SYS; + nfsea.export.ex_secflavors[1] = RPCSEC_GSS_KRB5; + nfsea.export.ex_secflavors[2] = RPCSEC_GSS_KRB5I; + nfsea.export.ex_secflavors[3] = RPCSEC_GSS_KRB5P; + } else { + nfsea.export.ex_numsecflavors = ea.ex_numsecflavors; + for (i = 0; i < ea.ex_numsecflavors; i++) + nfsea.export.ex_secflavors[i] = ea.ex_secflavors[i]; + } + nfsea.fspec = dirp; + if (nfssvc(NFSSVC_V4ROOTEXPORT, (caddr_t)&nfsea) < 0) + syslog(LOG_ERR, "Exporting V4: failed"); + v4root_phase = 2; +} +
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.GSO.4.63.0905211151300.6977>