Add support for the experimental nfs client to mount_nfs. The
experimental client is used when the fstype is "newnfs" or the "nfsv4" option is specified. It includes the addition of the option: gssname - to specify a client side initiator host based principal name which is specific to NFSv4. It also includes a change to mount.c, so that it knows about mount_newnfs, but not mount_nfs4. Reviewed by: dfr Approved by: kib (mentor)
This commit is contained in:
parent
b36d17c973
commit
08f63a0d18
@ -140,7 +140,7 @@ use_mountprog(const char *vfstype)
|
|||||||
*/
|
*/
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
const char *fs[] = {
|
const char *fs[] = {
|
||||||
"cd9660", "mfs", "msdosfs", "nfs", "nfs4", "ntfs",
|
"cd9660", "mfs", "msdosfs", "newnfs", "nfs", "ntfs",
|
||||||
"nwfs", "nullfs", "portalfs", "smbfs", "udf", "unionfs",
|
"nwfs", "nullfs", "portalfs", "smbfs", "udf", "unionfs",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -5,13 +5,15 @@
|
|||||||
PROG= mount_nfs
|
PROG= mount_nfs
|
||||||
SRCS= mount_nfs.c getmntopts.c mounttab.c
|
SRCS= mount_nfs.c getmntopts.c mounttab.c
|
||||||
MAN= mount_nfs.8
|
MAN= mount_nfs.8
|
||||||
MLINKS= mount_nfs.8
|
MLINKS= mount_nfs.8 mount_newnfs.8
|
||||||
|
|
||||||
MOUNT= ${.CURDIR}/../mount
|
MOUNT= ${.CURDIR}/../mount
|
||||||
UMNTALL= ${.CURDIR}/../../usr.sbin/rpc.umntall
|
UMNTALL= ${.CURDIR}/../../usr.sbin/rpc.umntall
|
||||||
CFLAGS+= -DNFS -I${MOUNT} -I${UMNTALL}
|
CFLAGS+= -DNFS -I${MOUNT} -I${UMNTALL}
|
||||||
WARNS?= 3
|
WARNS?= 3
|
||||||
|
|
||||||
|
LINKS= ${BINDIR}/mount_nfs ${BINDIR}/mount_newnfs
|
||||||
|
|
||||||
.PATH: ${MOUNT} ${UMNTALL}
|
.PATH: ${MOUNT} ${UMNTALL}
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
@ -132,6 +132,47 @@ short.
|
|||||||
.It Cm fg
|
.It Cm fg
|
||||||
Same as not specifying
|
Same as not specifying
|
||||||
.Cm bg .
|
.Cm bg .
|
||||||
|
.It Cm gssname Ns = Ns Aq Ar name
|
||||||
|
For the RPCSEC_GSS security flavors, such as krb5, krb5i and krb5p when being
|
||||||
|
used for an NFSv4 mount, this option specifies the host based principal
|
||||||
|
name to be used for the state related operations SetClientID,
|
||||||
|
SetClientIDConfirm, ReleaseLockOwner and Renew.
|
||||||
|
It is also used for other operations, such as Getattr for
|
||||||
|
.Xr statfs 2
|
||||||
|
information and during open/lock state recovery.
|
||||||
|
An entry for this principal must exist
|
||||||
|
in the client machine's default keytab file.
|
||||||
|
If possible, the keytab entry should be created using DES_CBC_CRC
|
||||||
|
encryption. If another encryption algorithm is used, the sysctl variable
|
||||||
|
.Va vfs.newnfs.keytab_enctype
|
||||||
|
must be set to the numeric value representing that encryption algorithm.
|
||||||
|
(The numeric values can be found in /usr/include/krb5_asn1.h. Look
|
||||||
|
for constants named ETYPE_xxx.)
|
||||||
|
If this option is given
|
||||||
|
as a name without an ``@<client-fqdn>'', such as ``root'' or ``nfs'',
|
||||||
|
``@<client-fqdn>'' will be appended to it.
|
||||||
|
.sp
|
||||||
|
If this option is not specified
|
||||||
|
for NFSv4 mounts using krb5[ip], the above operations will be done using the
|
||||||
|
user principal for the user that performed the mount. This
|
||||||
|
only works for mounts done by a user other than ``root'' and the user must
|
||||||
|
have a valid TGT in their credentials cache at the time the mount is done.
|
||||||
|
(Setting the
|
||||||
|
.Va vfs.usermount
|
||||||
|
to non-zero will allow users to do mounts.)
|
||||||
|
Because the user's TGT is used to acquire credentials for these operations,
|
||||||
|
it is important that that user's TGT does not expire before
|
||||||
|
.Xr umount 8
|
||||||
|
is done.
|
||||||
|
.It Cm allgssname
|
||||||
|
This option can be used along with
|
||||||
|
.Cm gssname
|
||||||
|
to indicate that all accesses to the mount point are to be done using
|
||||||
|
the host based principal specified by the
|
||||||
|
.Cm gssname
|
||||||
|
option.
|
||||||
|
This might be useful for nfsv4 mounts using sec=krb5[ip] that are being accessed
|
||||||
|
by batch utilities over long periods of time.
|
||||||
.It Cm hard
|
.It Cm hard
|
||||||
Same as not specifying
|
Same as not specifying
|
||||||
.Cm soft .
|
.Cm soft .
|
||||||
@ -157,6 +198,12 @@ then version 2).
|
|||||||
Note that NFS version 2 has a file size limit of 2 gigabytes.
|
Note that NFS version 2 has a file size limit of 2 gigabytes.
|
||||||
.It Cm nfsv3
|
.It Cm nfsv3
|
||||||
Use the NFS Version 3 protocol.
|
Use the NFS Version 3 protocol.
|
||||||
|
.It Cm nfsv4
|
||||||
|
Use the NFS Version 4 protocol.
|
||||||
|
This option will force the mount to use the experimental nfs subsystem and
|
||||||
|
TCP transport.
|
||||||
|
To use the experimental nfs subsystem for nfsv2 and nfsv3 mounts, you
|
||||||
|
must specify the ``newnfs'' file system type instead of ``nfs''.
|
||||||
.It Cm noconn
|
.It Cm noconn
|
||||||
For UDP mount points, do not do a
|
For UDP mount points, do not do a
|
||||||
.Xr connect 2 .
|
.Xr connect 2 .
|
||||||
@ -192,6 +239,11 @@ servers on the client.
|
|||||||
Note that this option will only be honored when performing the
|
Note that this option will only be honored when performing the
|
||||||
initial mount, it will be silently ignored if used while updating
|
initial mount, it will be silently ignored if used while updating
|
||||||
the mount options.
|
the mount options.
|
||||||
|
.It Cm principal
|
||||||
|
For the RPCSEC_GSS security flavors, such as krb5, krb5i and krb5p,
|
||||||
|
this option sets the name of the host based principal name expected
|
||||||
|
by the server. This option overrides the default, which will be
|
||||||
|
``nfs@<server-fqdn>'' and should normally be sufficient.
|
||||||
.It Cm noresvport
|
.It Cm noresvport
|
||||||
Do
|
Do
|
||||||
.Em not
|
.Em not
|
||||||
@ -200,8 +252,10 @@ use a reserved socket port number (see below).
|
|||||||
Use specified port number for NFS requests.
|
Use specified port number for NFS requests.
|
||||||
The default is to query the portmapper for the NFS port.
|
The default is to query the portmapper for the NFS port.
|
||||||
.It Cm rdirplus
|
.It Cm rdirplus
|
||||||
Used with NQNFS and NFSV3 to specify that the \fBReaddirPlus\fR RPC should
|
Used with NFSV3 to specify that the \fBReaddirPlus\fR RPC should
|
||||||
be used.
|
be used.
|
||||||
|
For NFSV4, setting this option has a similar effect, in that it will make
|
||||||
|
the Readdir Operation get more attributes.
|
||||||
This option reduces RPC traffic for cases such as
|
This option reduces RPC traffic for cases such as
|
||||||
.Dq "ls -l" ,
|
.Dq "ls -l" ,
|
||||||
but tends to flood the attribute and name caches with prefetched entries.
|
but tends to flood the attribute and name caches with prefetched entries.
|
||||||
@ -248,6 +302,18 @@ with the
|
|||||||
option to see what the
|
option to see what the
|
||||||
.Dq "fragments dropped due to timeout"
|
.Dq "fragments dropped due to timeout"
|
||||||
value is.)
|
value is.)
|
||||||
|
.It Cm sec Ns = Ns Aq Ar flavor
|
||||||
|
This option specifies what security flavor should be used for the mount.
|
||||||
|
Currently, they are:
|
||||||
|
.Bd -literal
|
||||||
|
krb5 - Use KerberosV authentication
|
||||||
|
krb5i - Use KerberosV authentication and
|
||||||
|
apply integrity checksums to RPCs
|
||||||
|
krb5p - Use KerberosV authentication and
|
||||||
|
encrypt the RPC data
|
||||||
|
sys - The default AUTH_SYS, which uses a
|
||||||
|
uid + gid list authenticator
|
||||||
|
.Ed
|
||||||
.It Cm soft
|
.It Cm soft
|
||||||
A soft mount, which implies that file system calls will fail
|
A soft mount, which implies that file system calls will fail
|
||||||
after
|
after
|
||||||
@ -368,8 +434,19 @@ Same as
|
|||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr nmount 2 ,
|
.Xr nmount 2 ,
|
||||||
.Xr unmount 2 ,
|
.Xr unmount 2 ,
|
||||||
|
.Xr nfsv4 4 ,
|
||||||
.Xr fstab 5 ,
|
.Xr fstab 5 ,
|
||||||
|
.Xr gssd 8 ,
|
||||||
.Xr mount 8 ,
|
.Xr mount 8 ,
|
||||||
.Xr nfsd 8 ,
|
.Xr nfsd 8 ,
|
||||||
.Xr nfsiod 8 ,
|
.Xr nfsiod 8 ,
|
||||||
.Xr showmount 8
|
.Xr showmount 8
|
||||||
|
.Sh BUGS
|
||||||
|
Since nfsv4 performs open/lock operations that have their ordering strictly
|
||||||
|
enforced by the server, the options
|
||||||
|
.Cm intr
|
||||||
|
and
|
||||||
|
.Cm soft
|
||||||
|
cannot be safely used.
|
||||||
|
.Cm hard
|
||||||
|
nfsv4 mounts are strongly recommended.
|
||||||
|
@ -45,6 +45,8 @@ static char sccsid[] = "@(#)mount_nfs.c 8.11 (Berkeley) 5/4/95";
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <sys/linker.h>
|
||||||
|
#include <sys/module.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -111,11 +113,13 @@ int addrlen = 0;
|
|||||||
u_char *fh = NULL;
|
u_char *fh = NULL;
|
||||||
int fhsize = 0;
|
int fhsize = 0;
|
||||||
int secflavor = -1;
|
int secflavor = -1;
|
||||||
|
int got_principal = 0;
|
||||||
|
|
||||||
enum mountmode {
|
enum mountmode {
|
||||||
ANY,
|
ANY,
|
||||||
V2,
|
V2,
|
||||||
V3,
|
V3,
|
||||||
|
V4
|
||||||
} mountmode = ANY;
|
} mountmode = ANY;
|
||||||
|
|
||||||
/* Return codes for nfs_tryproto. */
|
/* Return codes for nfs_tryproto. */
|
||||||
@ -150,11 +154,13 @@ main(int argc, char *argv[])
|
|||||||
int osversion;
|
int osversion;
|
||||||
char *name, *p, *spec, *fstype;
|
char *name, *p, *spec, *fstype;
|
||||||
char mntpath[MAXPATHLEN], errmsg[255];
|
char mntpath[MAXPATHLEN], errmsg[255];
|
||||||
|
char hostname[MAXHOSTNAMELEN + 1], *gssname, gssn[MAXHOSTNAMELEN + 50];
|
||||||
|
|
||||||
mntflags = 0;
|
mntflags = 0;
|
||||||
iov = NULL;
|
iov = NULL;
|
||||||
iovlen = 0;
|
iovlen = 0;
|
||||||
memset(errmsg, 0, sizeof(errmsg));
|
memset(errmsg, 0, sizeof(errmsg));
|
||||||
|
gssname = NULL;
|
||||||
|
|
||||||
fstype = strrchr(argv[0], '_');
|
fstype = strrchr(argv[0], '_');
|
||||||
if (fstype == NULL)
|
if (fstype == NULL)
|
||||||
@ -242,6 +248,9 @@ main(int argc, char *argv[])
|
|||||||
} else if (strcmp(opt, "fg") == 0) {
|
} else if (strcmp(opt, "fg") == 0) {
|
||||||
/* same as not specifying -o bg */
|
/* same as not specifying -o bg */
|
||||||
pass_flag_to_nmount=0;
|
pass_flag_to_nmount=0;
|
||||||
|
} else if (strcmp(opt, "gssname") == 0) {
|
||||||
|
pass_flag_to_nmount = 0;
|
||||||
|
gssname = val;
|
||||||
} else if (strcmp(opt, "mntudp") == 0) {
|
} else if (strcmp(opt, "mntudp") == 0) {
|
||||||
mnttcp_ok = 0;
|
mnttcp_ok = 0;
|
||||||
nfsproto = IPPROTO_UDP;
|
nfsproto = IPPROTO_UDP;
|
||||||
@ -262,12 +271,21 @@ main(int argc, char *argv[])
|
|||||||
mountmode = V2;
|
mountmode = V2;
|
||||||
} else if (strcmp(opt, "nfsv3") == 0) {
|
} else if (strcmp(opt, "nfsv3") == 0) {
|
||||||
mountmode = V3;
|
mountmode = V3;
|
||||||
|
} else if (strcmp(opt, "nfsv4") == 0) {
|
||||||
|
pass_flag_to_nmount=0;
|
||||||
|
mountmode = V4;
|
||||||
|
fstype = "newnfs";
|
||||||
|
nfsproto = IPPROTO_TCP;
|
||||||
|
if (portspec == NULL)
|
||||||
|
portspec = "2049";
|
||||||
} else if (strcmp(opt, "port") == 0) {
|
} else if (strcmp(opt, "port") == 0) {
|
||||||
pass_flag_to_nmount=0;
|
pass_flag_to_nmount=0;
|
||||||
asprintf(&portspec, "%d",
|
asprintf(&portspec, "%d",
|
||||||
atoi(val));
|
atoi(val));
|
||||||
if (portspec == NULL)
|
if (portspec == NULL)
|
||||||
err(1, "asprintf");
|
err(1, "asprintf");
|
||||||
|
} else if (strcmp(opt, "principal") == 0) {
|
||||||
|
got_principal = 1;
|
||||||
} else if (strcmp(opt, "sec") == 0) {
|
} else if (strcmp(opt, "sec") == 0) {
|
||||||
/*
|
/*
|
||||||
* Don't add this option to
|
* Don't add this option to
|
||||||
@ -363,6 +381,37 @@ main(int argc, char *argv[])
|
|||||||
/* The default is to keep retrying forever. */
|
/* The default is to keep retrying forever. */
|
||||||
retrycnt = 0;
|
retrycnt = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the experimental nfs subsystem is loaded into the kernel
|
||||||
|
* and the regular one is not, use it. Otherwise, use it if the
|
||||||
|
* fstype is set to "newnfs", either via "mount -t newnfs ..."
|
||||||
|
* or by specifying an nfsv4 mount.
|
||||||
|
*/
|
||||||
|
if (modfind("nfscl") >= 0 && modfind("nfs") < 0) {
|
||||||
|
fstype = "newnfs";
|
||||||
|
} else if (strcmp(fstype, "newnfs") == 0) {
|
||||||
|
if (modfind("nfscl") < 0) {
|
||||||
|
/* Not present in kernel, try loading it */
|
||||||
|
if (kldload("nfscl") < 0 ||
|
||||||
|
modfind("nfscl") < 0)
|
||||||
|
errx(1, "nfscl is not available");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the fqdn to the gssname, as required.
|
||||||
|
*/
|
||||||
|
if (gssname != NULL) {
|
||||||
|
if (strchr(gssname, '@') == NULL &&
|
||||||
|
gethostname(hostname, MAXHOSTNAMELEN) == 0) {
|
||||||
|
snprintf(gssn, sizeof (gssn), "%s@%s", gssname,
|
||||||
|
hostname);
|
||||||
|
gssname = gssn;
|
||||||
|
}
|
||||||
|
build_iovec(&iov, &iovlen, "gssname", gssname,
|
||||||
|
strlen(gssname) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (!getnfsargs(spec, &iov, &iovlen))
|
if (!getnfsargs(spec, &iov, &iovlen))
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
@ -652,7 +701,7 @@ getnfsargs(char *spec, struct iovec **iov, int *iovlen)
|
|||||||
int ecode, speclen, remoteerr;
|
int ecode, speclen, remoteerr;
|
||||||
char *hostp, *delimp, *errstr;
|
char *hostp, *delimp, *errstr;
|
||||||
size_t len;
|
size_t len;
|
||||||
static char nam[MNAMELEN + 1];
|
static char nam[MNAMELEN + 1], pname[MAXHOSTNAMELEN + 5];
|
||||||
|
|
||||||
if ((delimp = strrchr(spec, ':')) != NULL) {
|
if ((delimp = strrchr(spec, ':')) != NULL) {
|
||||||
hostp = spec;
|
hostp = spec;
|
||||||
@ -699,7 +748,7 @@ getnfsargs(char *spec, struct iovec **iov, int *iovlen)
|
|||||||
hints.ai_socktype = SOCK_DGRAM;
|
hints.ai_socktype = SOCK_DGRAM;
|
||||||
|
|
||||||
if (getaddrinfo(hostp, portspec, &hints, &ai_nfs) != 0) {
|
if (getaddrinfo(hostp, portspec, &hints, &ai_nfs) != 0) {
|
||||||
hints.ai_flags = 0;
|
hints.ai_flags = AI_CANONNAME;
|
||||||
if ((ecode = getaddrinfo(hostp, portspec, &hints, &ai_nfs))
|
if ((ecode = getaddrinfo(hostp, portspec, &hints, &ai_nfs))
|
||||||
!= 0) {
|
!= 0) {
|
||||||
if (portspec == NULL)
|
if (portspec == NULL)
|
||||||
@ -709,6 +758,18 @@ getnfsargs(char *spec, struct iovec **iov, int *iovlen)
|
|||||||
gai_strerror(ecode));
|
gai_strerror(ecode));
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For a Kerberized nfs mount where the "principal"
|
||||||
|
* argument has not been set, add it here.
|
||||||
|
*/
|
||||||
|
if (got_principal == 0 && secflavor >= 0 &&
|
||||||
|
secflavor != AUTH_SYS && ai_nfs->ai_canonname != NULL) {
|
||||||
|
snprintf(pname, sizeof (pname), "nfs@%s",
|
||||||
|
ai_nfs->ai_canonname);
|
||||||
|
build_iovec(iov, iovlen, "principal", pname,
|
||||||
|
strlen(pname) + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = TRYRET_LOCALERR;
|
ret = TRYRET_LOCALERR;
|
||||||
@ -834,7 +895,9 @@ nfs_tryproto(struct addrinfo *ai, char *hostp, char *spec, char **errstr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
tryagain:
|
tryagain:
|
||||||
if (trymntmode == V2) {
|
if (trymntmode == V4) {
|
||||||
|
nfsvers = 4;
|
||||||
|
} else if (trymntmode == V2) {
|
||||||
nfsvers = 2;
|
nfsvers = 2;
|
||||||
mntvers = 1;
|
mntvers = 1;
|
||||||
} else {
|
} else {
|
||||||
@ -894,8 +957,7 @@ nfs_tryproto(struct addrinfo *ai, char *hostp, char *spec, char **errstr,
|
|||||||
try.tv_sec = 10;
|
try.tv_sec = 10;
|
||||||
try.tv_usec = 0;
|
try.tv_usec = 0;
|
||||||
stat = clnt_call(clp, NFSPROC_NULL, (xdrproc_t)xdr_void, NULL,
|
stat = clnt_call(clp, NFSPROC_NULL, (xdrproc_t)xdr_void, NULL,
|
||||||
(xdrproc_t)xdr_void, NULL,
|
(xdrproc_t)xdr_void, NULL, try);
|
||||||
try);
|
|
||||||
if (stat != RPC_SUCCESS) {
|
if (stat != RPC_SUCCESS) {
|
||||||
if (stat == RPC_PROGVERSMISMATCH && trymntmode == ANY) {
|
if (stat == RPC_PROGVERSMISMATCH && trymntmode == ANY) {
|
||||||
clnt_destroy(clp);
|
clnt_destroy(clp);
|
||||||
@ -910,6 +972,30 @@ nfs_tryproto(struct addrinfo *ai, char *hostp, char *spec, char **errstr,
|
|||||||
}
|
}
|
||||||
clnt_destroy(clp);
|
clnt_destroy(clp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For NFSv4, there is no mount protocol.
|
||||||
|
*/
|
||||||
|
if (trymntmode == V4) {
|
||||||
|
/*
|
||||||
|
* Store the server address in nfsargsp, making
|
||||||
|
* sure to copy any locally allocated structures.
|
||||||
|
*/
|
||||||
|
addrlen = nfs_nb.len;
|
||||||
|
addr = malloc(addrlen);
|
||||||
|
if (addr == NULL)
|
||||||
|
err(1, "malloc");
|
||||||
|
bcopy(nfs_nb.buf, addr, addrlen);
|
||||||
|
|
||||||
|
build_iovec(iov, iovlen, "addr", addr, addrlen);
|
||||||
|
secname = sec_num_to_name(secflavor);
|
||||||
|
if (secname != NULL)
|
||||||
|
build_iovec(iov, iovlen, "sec", secname, (size_t)-1);
|
||||||
|
build_iovec(iov, iovlen, "nfsv4", NULL, 0);
|
||||||
|
build_iovec(iov, iovlen, "dirpath", spec, (size_t)-1);
|
||||||
|
|
||||||
|
return (TRYRET_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
/* Send the RPCMNT_MOUNT RPC to get the root filehandle. */
|
/* Send the RPCMNT_MOUNT RPC to get the root filehandle. */
|
||||||
try.tv_sec = 10;
|
try.tv_sec = 10;
|
||||||
try.tv_usec = 0;
|
try.tv_usec = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user