mirror of
https://git.FreeBSD.org/src.git
synced 2024-10-19 02:29:40 +00:00
Changes to support version 3 of the NFS protocol.
The version 2 support has been tested (client+server) against FreeBSD-2.0, IRIX 5.3 and FreeBSD-current (using a loopback mount). The version 2 support is stable AFAIK. The version 3 support has been tested with a loopback mount and minimally against an IRIX 5.3 server. It needs more testing and may have problems. I have patched amd to support the new variable length filehandles although it will still only use version 2 of the protocol. Before booting a kernel with these changes, nfs clients will need to at least build and install /usr/sbin/mount_nfs. Servers will need to build and install /usr/sbin/mountd. NFS diskless support is untested. Obtained from: Rick Macklem <rick@snowhite.cis.uoguelph.ca>
This commit is contained in:
parent
82aaeb09ad
commit
a62dc40654
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=9336
@ -44,8 +44,6 @@
|
||||
%#include <sys/param.h>
|
||||
%#include <sys/syslimits.h>
|
||||
%#include <sys/ucred.h>
|
||||
%#include <nfs/nfsv2.h>
|
||||
%#include <nfs/nfs.h>
|
||||
#else
|
||||
%#ifndef lint
|
||||
%/*static char sccsid[] = "from: @(#)bootparam_prot.x 1.2 87/06/24 Copyr 1987 Sun Micro";*/
|
||||
|
@ -39,8 +39,9 @@
|
||||
.Nd mount nfs file systems
|
||||
.Sh SYNOPSIS
|
||||
.Nm mount_nfs
|
||||
.Op Fl KMPTbcdiklqs
|
||||
.Op Fl 3KPTUbcdilqs
|
||||
.Op Fl D Ar deadthresh
|
||||
.Op Fl I Ar readdirsize
|
||||
.Op Fl L Ar leaseterm
|
||||
.Op Fl R Ar retrycnt
|
||||
.Op Fl a Ar maxreadahead
|
||||
@ -63,10 +64,14 @@ on to the file system tree at the point
|
||||
.Ar node.
|
||||
This command is normally executed by
|
||||
.Xr mount 8 .
|
||||
It implements the mount protocol as described in RFC 1094, Appendix A.
|
||||
It implements the mount protocol as described in RFC 1094, Appendix A and
|
||||
.%T "NFS: Network File System Version 3 Protocol Specification" ,
|
||||
Appendix I.
|
||||
.Pp
|
||||
The options are:
|
||||
.Bl -tag -width indent
|
||||
.It Fl 3
|
||||
Use the NFS Version 3 protocol (Version 2 is the default).
|
||||
.It Fl D
|
||||
Used with NQNFS to set the
|
||||
.Dq "dead server threshold"
|
||||
@ -80,23 +85,27 @@ Values may be set in the range of 1 - 9, with 9 referring to an
|
||||
(i.e. never assume cached data still valid).
|
||||
This option is not generally recommended and is really an experimental
|
||||
feature.
|
||||
.It Fl I
|
||||
Set the readdir read size to the specified value. The value should normally
|
||||
be a multiple of DIRBLKSIZ that is <= the read size for the mount.
|
||||
.It Fl K
|
||||
Pass Kerberos authenticators to the server for client-to-server
|
||||
user-credential mapping.
|
||||
This may only be used over TCP mounts between 4.4BSD clients and servers.
|
||||
This requires that the kernel be built with the NFSKERB option.
|
||||
(Refer to the INTERNET-DRAFT titled
|
||||
.%T "Authentication Mechanisms for ONC RPC" ,
|
||||
for more information.)
|
||||
.It Fl L
|
||||
Used with NQNFS to set the lease term to the specified number of seconds.
|
||||
Only use this argument for mounts with a large round trip delay.
|
||||
Values are normally in the 10-30 second range.
|
||||
.It Fl M
|
||||
Assume that other clients are not writing a file concurrently with this client.
|
||||
This implements a slightly less strict consistency criteria than 4.3BSD-Reno
|
||||
did, that is more in line with most commercial client implementations.
|
||||
This is recommended for servers that do not support leasing.
|
||||
.It Fl P
|
||||
Use a reserved socket port number.
|
||||
This is useful for mounting servers that require clients to use a
|
||||
reserved port number.
|
||||
reserved port number on the mistaken belief that this makes NFS
|
||||
more secure. (For the rare case where the client has a trusted root account
|
||||
but untrusworthy users and the network cables are in secure areas this does
|
||||
help, but for normal desktop clients this does not apply.)
|
||||
.It Fl R
|
||||
Set the retry count for doing the mount to the specified value.
|
||||
.It Fl T
|
||||
@ -104,11 +113,15 @@ Use TCP transport instead of UDP.
|
||||
This is recommended for servers that are not on the same LAN cable as
|
||||
the client.
|
||||
(NB: This is NOT supported by most non-BSD servers.)
|
||||
.It Fl U
|
||||
Force the mount protocol to use UDP transport, even for TCP NFS mounts.
|
||||
(Necessary for some old BSD servers.)
|
||||
.It Fl a
|
||||
Set the read-ahead count to the specified value.
|
||||
This may be in the range of 0 - 4, and determines how many blocks
|
||||
will be read ahead when a large file is being read sequentially.
|
||||
This is recommended for mounts with a large bandwidth * delay product.
|
||||
Trying a value greater than 1 for this is suggested for
|
||||
mounts with a large bandwidth * delay product.
|
||||
.It Fl b
|
||||
If an initial attempt to contact the server fails, fork off a child to keep
|
||||
trying the mount in the background.
|
||||
@ -119,10 +132,12 @@ where the filesystem mount is not critical to multiuser operation.
|
||||
For UDP mount points, do not do a
|
||||
.Xr connect 2 .
|
||||
This must be used for servers that do not reply to requests from the
|
||||
standard port number.
|
||||
standard NFS port number 2049.
|
||||
.It Fl d
|
||||
Do not estimate retransmit timeout dynamically.
|
||||
This may be useful for UDP mounts that exhibit high retry rates.
|
||||
Turn off the dynamic retransmit timeout estimator.
|
||||
This may be useful for UDP mounts that exhibit high retry rates,
|
||||
since it is possible that the dynamically estimated timeout interval is too
|
||||
short.
|
||||
.It Fl g
|
||||
Set the maximum size of the group list for the credentials to the
|
||||
specified value.
|
||||
@ -134,20 +149,15 @@ point.
|
||||
Make the mount interruptible, which implies that file system calls that
|
||||
are delayed due to an unresponsive server will fail with EINTR when a
|
||||
termination signal is posted for the process.
|
||||
.It Fl k
|
||||
Used with NQNFS to specify
|
||||
.Dq get a lease
|
||||
for the file name being looked up.
|
||||
This is recommended unless the server is complaining about excessive
|
||||
lease load.
|
||||
.It Fl l
|
||||
Used with NQNFS to specify that the \fBReaddir_and_Lookup\fR RPC should
|
||||
Used with NQNFS and NFSV3 to specify that the \fBReaddirPlus\fR RPC should
|
||||
be used.
|
||||
This option reduces RPC traffic for cases such as
|
||||
.Dq "ls -l" ,
|
||||
but increases the lease load on the server.
|
||||
This is recommended unless the server is complaining about excessive
|
||||
lease load.
|
||||
but tends to flood the attribute and name caches with prefetched entries.
|
||||
Try this option and see whether performance improves or degrades. Probably
|
||||
most useful for client to server network interconnects with a large bandwidth
|
||||
times delay product.
|
||||
.It Fl m
|
||||
Set the Kerberos realm to the string argument.
|
||||
Used with the
|
||||
@ -167,12 +177,16 @@ Use specified port number for NFS requests.
|
||||
The default is to query the portmapper for the NFS port.
|
||||
.El
|
||||
.It Fl q
|
||||
Use the leasing extensions to the protocol to maintain cache consistency.
|
||||
This protocol, referred to as Not Quite Nfs (NQNFS),
|
||||
is only supported by 4.4BSD servers.
|
||||
Use the leasing extensions to the NFS Version 3 protocol to maintain cache consistency.
|
||||
This protocol Version 2, referred to as Not Quite Nfs (NQNFS),
|
||||
is only supported by this updated release of NFS code.
|
||||
(It is not backwards compatible with the release of NQNFS that went out on
|
||||
4.4BSD-Lite. To interoperate with a 4.4BSD-Lite NFS system you will have to
|
||||
avoid this option until you have had an oppurtunity to upgrade the NFS code
|
||||
on all your 4.4BSD-Lite based systems.)
|
||||
.It Fl r
|
||||
Set the read data size to the specified value.
|
||||
It should be a power of 2 greater than or equal to 1024.
|
||||
It should normally be a power of 2 greater than or equal to 1024.
|
||||
This should be used for UDP mounts when the
|
||||
.Dq "fragments dropped due to timeout"
|
||||
value is getting large while actively using a mount point.
|
||||
@ -197,6 +211,9 @@ Try increasing the interval if
|
||||
.Xr nfsstat 1
|
||||
shows high retransmit rates while the file system is active or reducing the
|
||||
value if there is a low retransmit rate but long response delay observed.
|
||||
(Normally, the -d option should be specified when using this option to manually
|
||||
tune the timeout
|
||||
interval.)
|
||||
.It Fl w
|
||||
Set the write data size to the specified value.
|
||||
Ditto the comments w.r.t. the
|
||||
|
@ -59,16 +59,16 @@ static char sccsid[] = "@(#)mount_nfs.c 8.3 (Berkeley) 3/27/94";
|
||||
#include <netiso/iso.h>
|
||||
#endif
|
||||
|
||||
#ifdef KERBEROS
|
||||
#ifdef NFSKERB
|
||||
#include <kerberosIV/des.h>
|
||||
#include <kerberosIV/krb.h>
|
||||
#endif
|
||||
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#define KERNEL
|
||||
#include <nfs/nfsproto.h>
|
||||
#define _KERNEL
|
||||
#include <nfs/nfs.h>
|
||||
#undef KERNEL
|
||||
#undef _KERNEL
|
||||
#include <nfs/nqnfs.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
@ -86,14 +86,15 @@ static char sccsid[] = "@(#)mount_nfs.c 8.3 (Berkeley) 3/27/94";
|
||||
|
||||
#include "mntopts.h"
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define ALTF_BG 0x1
|
||||
#define ALTF_NOCONN 0x2
|
||||
#define ALTF_DUMBTIMR 0x4
|
||||
#define ALTF_INTR 0x8
|
||||
#define ALTF_KERB 0x10
|
||||
#define ALTF_NQLOOKLSE 0x20
|
||||
#define ALTF_RDIRALOOK 0x40
|
||||
#define ALTF_MYWRITE 0x80
|
||||
#define ALTF_NFSV3 0x20
|
||||
#define ALTF_RDIRPLUS 0x40
|
||||
#define ALTF_MNTUDP 0x80
|
||||
#define ALTF_RESVPORT 0x100
|
||||
#define ALTF_SEQPACKET 0x200
|
||||
#define ALTF_NQNFS 0x400
|
||||
@ -109,12 +110,12 @@ struct mntopt mopts[] = {
|
||||
{ "conn", 1, ALTF_NOCONN, 1 },
|
||||
{ "dumbtimer", 0, ALTF_DUMBTIMR, 1 },
|
||||
{ "intr", 0, ALTF_INTR, 1 },
|
||||
#ifdef KERBEROS
|
||||
#ifdef NFSKERB
|
||||
{ "kerb", 0, ALTF_KERB, 1 },
|
||||
#endif
|
||||
{ "nqlooklease", 0, ALTF_NQLOOKLSE, 1 },
|
||||
{ "rdiralook", 0, ALTF_RDIRALOOK, 1 },
|
||||
{ "mywrite", 0, ALTF_MYWRITE, 1 },
|
||||
{ "nfsv3", 0, ALTF_NFSV3, 1 },
|
||||
{ "rdirplus", 0, ALTF_RDIRPLUS, 1 },
|
||||
{ "mntudp", 0, ALTF_MNTUDP, 1 },
|
||||
{ "resvport", 0, ALTF_RESVPORT, 1 },
|
||||
#ifdef ISO
|
||||
{ "seqpacket", 0, ALTF_SEQPACKET, 1 },
|
||||
@ -125,17 +126,27 @@ struct mntopt mopts[] = {
|
||||
{ "port=", 0, ALTF_PORT, 1 },
|
||||
{ NULL }
|
||||
};
|
||||
#else
|
||||
struct mntopt mopts[] = {
|
||||
MOPT_STDOPTS,
|
||||
MOPT_FORCE,
|
||||
MOPT_UPDATE,
|
||||
{ NULL }
|
||||
};
|
||||
#endif
|
||||
|
||||
struct nfs_args nfsdefargs = {
|
||||
(struct sockaddr *)0,
|
||||
sizeof (struct sockaddr_in),
|
||||
SOCK_DGRAM,
|
||||
0,
|
||||
(nfsv2fh_t *)0,
|
||||
(u_char *)0,
|
||||
0,
|
||||
0,
|
||||
NFS_WSIZE,
|
||||
NFS_RSIZE,
|
||||
NFS_TIMEO,
|
||||
NFS_READDIRSIZE,
|
||||
10,
|
||||
NFS_RETRANS,
|
||||
NFS_MAXGRPS,
|
||||
NFS_DEFRAHEAD,
|
||||
@ -145,20 +156,34 @@ struct nfs_args nfsdefargs = {
|
||||
};
|
||||
|
||||
struct nfhret {
|
||||
u_long stat;
|
||||
nfsv2fh_t nfh;
|
||||
u_long stat;
|
||||
long vers;
|
||||
long auth;
|
||||
long fhsize;
|
||||
u_char nfh[NFSX_V3FHMAX];
|
||||
};
|
||||
#define DEF_RETRY 10000
|
||||
#define BGRND 1
|
||||
#define ISBGRND 2
|
||||
int retrycnt = DEF_RETRY;
|
||||
int opflags = 0;
|
||||
int nfsproto = IPPROTO_UDP;
|
||||
int mnttcp_ok = 1;
|
||||
u_short port_no = 0;
|
||||
|
||||
#ifdef KERBEROS
|
||||
#ifdef NFSKERB
|
||||
char inst[INST_SZ];
|
||||
char realm[REALM_SZ];
|
||||
KTEXT_ST kt;
|
||||
struct {
|
||||
u_long kind;
|
||||
KTEXT_ST kt;
|
||||
} ktick;
|
||||
struct nfsrpc_nickverf kverf;
|
||||
struct nfsrpc_fullblock kin, kout;
|
||||
NFSKERBKEY_T kivec;
|
||||
CREDENTIALS kcr;
|
||||
struct timeval ktv;
|
||||
NFSKERBKEYSCHED_T kerb_keysched;
|
||||
#endif
|
||||
|
||||
int getnfsargs __P((char *, struct nfs_args *));
|
||||
@ -182,14 +207,17 @@ main(argc, argv)
|
||||
int mntflags, altflags, i, nfssvc_flag, num;
|
||||
char *name, *p, *spec;
|
||||
struct vfsconf *vfc;
|
||||
#ifdef KERBEROS
|
||||
#ifdef NFSKERB
|
||||
uid_t last_ruid;
|
||||
#endif
|
||||
|
||||
#ifdef KERBEROS
|
||||
last_ruid = -1;
|
||||
(void)strcpy(realm, KRB_REALM);
|
||||
#endif
|
||||
if (sizeof (struct nfsrpc_nickverf) != RPCX_NICKVERF ||
|
||||
sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK ||
|
||||
((char *)&ktick.kt) - ((char *)&ktick) != NFSX_UNSIGNED ||
|
||||
((char *)ktick.kt.dat) - ((char *)&ktick) != 2 * NFSX_UNSIGNED)
|
||||
fprintf(stderr, "Yikes! NFSKERB structs not packed!!\n");
|
||||
#endif /* NFSKERB */
|
||||
retrycnt = DEF_RETRY;
|
||||
|
||||
mntflags = 0;
|
||||
@ -197,8 +225,11 @@ main(argc, argv)
|
||||
nfsargs = nfsdefargs;
|
||||
nfsargsp = &nfsargs;
|
||||
while ((c = getopt(argc, argv,
|
||||
"a:bcdD:g:iKklL:Mm:o:PpqR:r:sTt:w:x:")) != EOF)
|
||||
"3a:bcdD:g:I:iKL:lm:o:PpqR:r:sTt:w:x:U")) != EOF)
|
||||
switch (c) {
|
||||
case '3':
|
||||
nfsargsp->flags |= NFSMNT_NFSV3;
|
||||
break;
|
||||
case 'a':
|
||||
num = strtol(optarg, &p, 10);
|
||||
if (*p || num < 0)
|
||||
@ -226,21 +257,27 @@ main(argc, argv)
|
||||
num = strtol(optarg, &p, 10);
|
||||
if (*p || num <= 0)
|
||||
errx(1, "illegal -g value -- %s", optarg);
|
||||
#ifdef __FreeBSD__
|
||||
set_rpc_maxgrouplist(num);
|
||||
#endif
|
||||
nfsargsp->maxgrouplist = num;
|
||||
nfsargsp->flags |= NFSMNT_MAXGRPS;
|
||||
break;
|
||||
case 'I':
|
||||
num = strtol(optarg, &p, 10);
|
||||
if (*p || num <= 0)
|
||||
errx(1, "illegal -I value -- %s", optarg);
|
||||
nfsargsp->readdirsize = num;
|
||||
nfsargsp->flags |= NFSMNT_READDIRSIZE;
|
||||
break;
|
||||
case 'i':
|
||||
nfsargsp->flags |= NFSMNT_INT;
|
||||
break;
|
||||
#ifdef KERBEROS
|
||||
#ifdef NFSKERB
|
||||
case 'K':
|
||||
nfsargsp->flags |= NFSMNT_KERB;
|
||||
break;
|
||||
#endif
|
||||
case 'k':
|
||||
nfsargsp->flags |= NFSMNT_NQLOOKLEASE;
|
||||
break;
|
||||
case 'L':
|
||||
num = strtol(optarg, &p, 10);
|
||||
if (*p || num < 2)
|
||||
@ -249,18 +286,16 @@ main(argc, argv)
|
||||
nfsargsp->flags |= NFSMNT_LEASETERM;
|
||||
break;
|
||||
case 'l':
|
||||
nfsargsp->flags |= NFSMNT_RDIRALOOK;
|
||||
nfsargsp->flags |= NFSMNT_RDIRPLUS;
|
||||
break;
|
||||
case 'M':
|
||||
nfsargsp->flags |= NFSMNT_MYWRITE;
|
||||
break;
|
||||
#ifdef KERBEROS
|
||||
#ifdef NFSKERB
|
||||
case 'm':
|
||||
(void)strncpy(realm, optarg, REALM_SZ - 1);
|
||||
realm[REALM_SZ - 1] = '\0';
|
||||
break;
|
||||
#endif
|
||||
case 'o':
|
||||
#ifdef __FreeBSD__
|
||||
getmntopts(optarg, mopts, &mntflags, &altflags);
|
||||
if(altflags & ALTF_BG)
|
||||
opflags |= BGRND;
|
||||
@ -270,16 +305,16 @@ main(argc, argv)
|
||||
nfsargsp->flags |= NFSMNT_DUMBTIMR;
|
||||
if(altflags & ALTF_INTR)
|
||||
nfsargsp->flags |= NFSMNT_INT;
|
||||
#ifdef KERBEROS
|
||||
#ifdef NFSKERB
|
||||
if(altflags & ALTF_KERB)
|
||||
nfsargsp->flags |= NFSMNT_KERB;
|
||||
#endif
|
||||
if(altflags & ALTF_NQLOOKLSE)
|
||||
nfsargsp->flags |= NFSMNT_NQLOOKLEASE;
|
||||
if(altflags & ALTF_RDIRALOOK)
|
||||
nfsargsp->flags |= NFSMNT_RDIRALOOK;
|
||||
if(altflags & ALTF_MYWRITE)
|
||||
nfsargsp->flags |= NFSMNT_MYWRITE;
|
||||
if(altflags & ALTF_NFSV3)
|
||||
nfsargsp->flags |= NFSMNT_NFSV3;
|
||||
if(altflags & ALTF_RDIRPLUS)
|
||||
nfsargsp->flags |= NFSMNT_RDIRPLUS;
|
||||
if(altflags & ALTF_MNTUDP)
|
||||
mnttcp_ok = 0;
|
||||
if(altflags & ALTF_RESVPORT)
|
||||
nfsargsp->flags |= NFSMNT_RESVPORT;
|
||||
#ifdef ISO
|
||||
@ -287,14 +322,19 @@ main(argc, argv)
|
||||
nfsargsp->sotype = SOCK_SEQPACKET;
|
||||
#endif
|
||||
if(altflags & ALTF_NQNFS)
|
||||
nfsargsp->flags |= NFSMNT_NQNFS;
|
||||
nfsargsp->flags |= (NFSMNT_NQNFS|NFSMNT_NFSV3);
|
||||
if(altflags & ALTF_SOFT)
|
||||
nfsargsp->flags |= NFSMNT_SOFT;
|
||||
if(altflags & ALTF_TCP)
|
||||
if(altflags & ALTF_TCP) {
|
||||
nfsargsp->sotype = SOCK_STREAM;
|
||||
nfsproto = IPPROTO_TCP;
|
||||
}
|
||||
if(altflags & ALTF_PORT)
|
||||
port_no = atoi(strstr(optarg, "port=") + 5);
|
||||
altflags = 0;
|
||||
#else
|
||||
getmntopts(optarg, mopts, &mntflags);
|
||||
#endif
|
||||
break;
|
||||
case 'P':
|
||||
nfsargsp->flags |= NFSMNT_RESVPORT;
|
||||
@ -305,7 +345,7 @@ main(argc, argv)
|
||||
break;
|
||||
#endif
|
||||
case 'q':
|
||||
nfsargsp->flags |= NFSMNT_NQNFS;
|
||||
nfsargsp->flags |= (NFSMNT_NQNFS | NFSMNT_NFSV3);
|
||||
break;
|
||||
case 'R':
|
||||
num = strtol(optarg, &p, 10);
|
||||
@ -325,6 +365,7 @@ main(argc, argv)
|
||||
break;
|
||||
case 'T':
|
||||
nfsargsp->sotype = SOCK_STREAM;
|
||||
nfsproto = IPPROTO_TCP;
|
||||
break;
|
||||
case 't':
|
||||
num = strtol(optarg, &p, 10);
|
||||
@ -347,6 +388,9 @@ main(argc, argv)
|
||||
nfsargsp->retrans = num;
|
||||
nfsargsp->flags |= NFSMNT_RETRANS;
|
||||
break;
|
||||
case 'U':
|
||||
mnttcp_ok = 0;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
@ -363,6 +407,7 @@ main(argc, argv)
|
||||
if (!getnfsargs(spec, nfsargsp))
|
||||
exit(1);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
vfc = getvfsbyname("nfs");
|
||||
if(!vfc && vfsisloadable("nfs")) {
|
||||
if(vfsload("nfs"))
|
||||
@ -372,6 +417,9 @@ main(argc, argv)
|
||||
}
|
||||
|
||||
if (mount(vfc ? vfc->vfc_index : MOUNT_NFS, name, mntflags, nfsargsp))
|
||||
#else
|
||||
if (mount(MOUNT_NFS, name, mntflags, nfsargsp))
|
||||
#endif
|
||||
err(1, "%s", name);
|
||||
if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) {
|
||||
if ((opflags & ISBGRND) == 0) {
|
||||
@ -396,13 +444,18 @@ main(argc, argv)
|
||||
}
|
||||
nfssvc_flag =
|
||||
NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL;
|
||||
#ifdef KERBEROS
|
||||
#ifdef NFSKERB
|
||||
/*
|
||||
* Set up as ncd_authuid for the kerberos call.
|
||||
* Must set ruid to ncd_authuid and reset the
|
||||
* ticket name iff ncd_authuid is not the same
|
||||
* as last time, so that the right ticket file
|
||||
* is found.
|
||||
* Get the Kerberos credential structure so that
|
||||
* we have the seesion key and get a ticket for
|
||||
* this uid.
|
||||
* For more info see the IETF Draft "Authentication
|
||||
* in ONC RPC".
|
||||
*/
|
||||
if (ncd.ncd_authuid != last_ruid) {
|
||||
char buf[512];
|
||||
@ -411,15 +464,62 @@ main(argc, argv)
|
||||
krb_set_tkt_string(buf);
|
||||
last_ruid = ncd.ncd_authuid;
|
||||
}
|
||||
if (krb_mk_req(&kt, "rcmd", inst, realm, 0) ==
|
||||
KSUCCESS &&
|
||||
kt.length <= (RPCAUTH_MAXSIZ - 2 * NFSX_UNSIGNED)) {
|
||||
ncd.ncd_authtype = RPCAUTH_NQNFS;
|
||||
ncd.ncd_authlen = kt.length;
|
||||
ncd.ncd_authstr = (char *)kt.dat;
|
||||
nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
|
||||
setreuid(ncd.ncd_authuid, 0);
|
||||
kret = krb_get_cred(NFS_KERBSRV, inst, realm, &kcr);
|
||||
if (kret == RET_NOTKT) {
|
||||
kret = get_ad_tkt(NFS_KERBSRV, inst, realm,
|
||||
DEFAULT_TKT_LIFE);
|
||||
if (kret == KSUCCESS)
|
||||
kret = krb_get_cred(NFS_KERBSRV, inst, realm,
|
||||
&kcr);
|
||||
}
|
||||
#endif /* KERBEROS */
|
||||
if (kret == KSUCCESS)
|
||||
kret = krb_mk_req(&ktick.kt, NFS_KERBSRV, inst,
|
||||
realm, 0);
|
||||
|
||||
/*
|
||||
* Fill in the AKN_FULLNAME authenticator and verfier.
|
||||
* Along with the Kerberos ticket, we need to build
|
||||
* the timestamp verifier and encrypt it in CBC mode.
|
||||
*/
|
||||
if (kret == KSUCCESS &&
|
||||
ktick.kt.length <= (RPCAUTH_MAXSIZ-3*NFSX_UNSIGNED)
|
||||
&& gettimeofday(&ktv, (struct timezone *)0) == 0) {
|
||||
ncd.ncd_authtype = RPCAUTH_KERB4;
|
||||
ncd.ncd_authstr = (u_char *)&ktick;
|
||||
ncd.ncd_authlen = nfsm_rndup(ktick.kt.length) +
|
||||
3 * NFSX_UNSIGNED;
|
||||
ncd.ncd_verfstr = (u_char *)&kverf;
|
||||
ncd.ncd_verflen = sizeof (kverf);
|
||||
bcopy((caddr_t)kcr.session, (caddr_t)ncd.ncd_key,
|
||||
sizeof (kcr.session));
|
||||
kin.t1 = htonl(ktv.tv_sec);
|
||||
kin.t2 = htonl(ktv.tv_usec);
|
||||
kin.w1 = htonl(NFS_KERBTTL);
|
||||
kin.w2 = htonl(NFS_KERBTTL - 1);
|
||||
bzero((caddr_t)kivec, sizeof (kivec));
|
||||
|
||||
/*
|
||||
* Encrypt kin in CBC mode using the session
|
||||
* key in kcr.
|
||||
*/
|
||||
XXX
|
||||
|
||||
/*
|
||||
* Finally, fill the timestamp verifier into the
|
||||
* authenticator and verifier.
|
||||
*/
|
||||
ktick.kind = htonl(RPCAKN_FULLNAME);
|
||||
kverf.kind = htonl(RPCAKN_FULLNAME);
|
||||
NFS_KERBW1(ktick.kt) = kout.w1;
|
||||
ktick.kt.length = htonl(ktick.kt.length);
|
||||
kverf.verf.t1 = kout.t1;
|
||||
kverf.verf.t2 = kout.t2;
|
||||
kverf.verf.w2 = kout.w2;
|
||||
nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
|
||||
}
|
||||
setreuid(0, 0);
|
||||
#endif /* NFSKERB */
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
@ -440,9 +540,9 @@ getnfsargs(spec, nfsargsp)
|
||||
#endif
|
||||
struct timeval pertry, try;
|
||||
enum clnt_stat clnt_stat;
|
||||
int so = RPC_ANYSOCK, i;
|
||||
int so = RPC_ANYSOCK, i, nfsvers, mntvers;
|
||||
char *hostp, *delimp;
|
||||
#ifdef KERBEROS
|
||||
#ifdef NFSKERB
|
||||
char *cp;
|
||||
#endif
|
||||
u_short tport;
|
||||
@ -507,7 +607,7 @@ getnfsargs(spec, nfsargsp)
|
||||
warnx("can't get net id for host");
|
||||
return (0);
|
||||
}
|
||||
#ifdef KERBEROS
|
||||
#ifdef NFSKERB
|
||||
if ((nfsargsp->flags & NFSMNT_KERB)) {
|
||||
if ((hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr,
|
||||
sizeof (u_long), AF_INET)) == (struct hostent *)0) {
|
||||
@ -520,33 +620,46 @@ getnfsargs(spec, nfsargsp)
|
||||
if (cp = strchr(inst, '.'))
|
||||
*cp = '\0';
|
||||
}
|
||||
#endif /* KERBEROS */
|
||||
#endif /* NFSKERB */
|
||||
|
||||
if (nfsargsp->flags & NFSMNT_NFSV3) {
|
||||
nfsvers = 3;
|
||||
mntvers = 3;
|
||||
} else {
|
||||
nfsvers = 2;
|
||||
mntvers = 1;
|
||||
}
|
||||
nfhret.stat = EACCES; /* Mark not yet successful */
|
||||
while (retrycnt > 0) {
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons(PMAPPORT);
|
||||
if ((tport = port_no ? port_no :
|
||||
pmap_getport(&saddr, RPCPROG_NFS,
|
||||
NFS_VER2, nfsargsp->sotype == SOCK_STREAM ? IPPROTO_TCP :
|
||||
IPPROTO_UDP)) == 0) {
|
||||
nfsvers, nfsproto)) == 0) {
|
||||
if ((opflags & ISBGRND) == 0)
|
||||
clnt_pcreateerror("NFS Portmap");
|
||||
} else {
|
||||
saddr.sin_port = 0;
|
||||
pertry.tv_sec = 10;
|
||||
pertry.tv_usec = 0;
|
||||
if ((clp = (nfsargsp->sotype == SOCK_STREAM ?
|
||||
clnttcp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
|
||||
&so, 0, 0) :
|
||||
clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
|
||||
pertry, &so))) == NULL) {
|
||||
if (mnttcp_ok && nfsargsp->sotype == SOCK_STREAM)
|
||||
clp = clnttcp_create(&saddr, RPCPROG_MNT, mntvers,
|
||||
&so, 0, 0);
|
||||
else
|
||||
clp = clntudp_create(&saddr, RPCPROG_MNT, mntvers,
|
||||
pertry, &so);
|
||||
if (clp == NULL) {
|
||||
if ((opflags & ISBGRND) == 0)
|
||||
clnt_pcreateerror("Cannot MNT RPC");
|
||||
} else {
|
||||
clp->cl_auth = authunix_create_default();
|
||||
try.tv_sec = 10;
|
||||
try.tv_usec = 0;
|
||||
if (nfsargsp->flags & NFSMNT_KERB)
|
||||
nfhret.auth = RPCAUTH_KERB4;
|
||||
else
|
||||
nfhret.auth = RPCAUTH_UNIX;
|
||||
nfhret.vers = mntvers;
|
||||
clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
|
||||
xdr_dir, spec, xdr_fh, &nfhret, try);
|
||||
if (clnt_stat != RPC_SUCCESS) {
|
||||
@ -596,7 +709,8 @@ getnfsargs(spec, nfsargsp)
|
||||
nfsargsp->addr = (struct sockaddr *) &saddr;
|
||||
nfsargsp->addrlen = sizeof (saddr);
|
||||
}
|
||||
nfsargsp->fh = &nfhret.nfh;
|
||||
nfsargsp->fh = nfhret.nfh;
|
||||
nfsargsp->fhsize = nfhret.fhsize;
|
||||
nfsargsp->hostname = nam;
|
||||
return (1);
|
||||
}
|
||||
@ -615,22 +729,53 @@ xdr_dir(xdrsp, dirp)
|
||||
int
|
||||
xdr_fh(xdrsp, np)
|
||||
XDR *xdrsp;
|
||||
struct nfhret *np;
|
||||
register struct nfhret *np;
|
||||
{
|
||||
if (!xdr_u_long(xdrsp, &(np->stat)))
|
||||
register int i;
|
||||
long auth, authcnt, authfnd = 0;
|
||||
|
||||
if (!xdr_u_long(xdrsp, &np->stat))
|
||||
return (0);
|
||||
if (np->stat)
|
||||
return (1);
|
||||
return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH));
|
||||
switch (np->vers) {
|
||||
case 1:
|
||||
np->fhsize = NFSX_V2FH;
|
||||
return (xdr_opaque(xdrsp, (caddr_t)np->nfh, NFSX_V2FH));
|
||||
case 3:
|
||||
if (!xdr_long(xdrsp, &np->fhsize))
|
||||
return (0);
|
||||
if (np->fhsize <= 0 || np->fhsize > NFSX_V3FHMAX)
|
||||
return (0);
|
||||
if (!xdr_opaque(xdrsp, (caddr_t)np->nfh, np->fhsize))
|
||||
return (0);
|
||||
if (!xdr_long(xdrsp, &authcnt))
|
||||
return (0);
|
||||
for (i = 0; i < authcnt; i++) {
|
||||
if (!xdr_long(xdrsp, &auth))
|
||||
return (0);
|
||||
if (auth == np->auth)
|
||||
authfnd++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some servers, such as DEC's OSF/1 return a nil authenticator
|
||||
* list to indicate RPCAUTH_UNIX.
|
||||
*/
|
||||
if (!authfnd && (authcnt > 0 || np->auth != RPCAUTH_UNIX))
|
||||
np->stat = EAUTH;
|
||||
return (1);
|
||||
};
|
||||
return (0);
|
||||
}
|
||||
|
||||
__dead void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: mount_nfs %s\n%s\n%s\n%s\n",
|
||||
"[-bcdiKklMPqsT] [-a maxreadahead] [-D deadthresh]",
|
||||
"\t[-g maxgroups] [-L leaseterm] [-m realm] [-o options] [-R retrycnt]",
|
||||
"\t[-r readsize] [-t timeout] [-w writesize] [-x retrans]",
|
||||
"\trhost:path node");
|
||||
(void)fprintf(stderr, "\
|
||||
usage: mount_nfs [-3KPTUbcdilqs] [-D deadthresh] [-I readdirsize]\n\
|
||||
[-L leaseterm] [-R retrycnt] [-a maxreadahead] [-g maxgroups]\n\
|
||||
[-m realm] [-o options] [-r readsize] [-t timeout] [-w writesize]\n\
|
||||
[-x retrans] rhost:path node\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -49,7 +49,9 @@ file specifies remote mount points for the
|
||||
mount protocol per the
|
||||
.Tn NFS
|
||||
server specification; see
|
||||
.%T "Network File System Protocol Specification \\*(tNRFC\\*(sP 1094, Appendix A" .
|
||||
.%T "Network File System Protocol Specification \\*(tNRFC\\*(sP 1094, Appendix A"
|
||||
and
|
||||
.%T "NFS: Network File System Version 3 Specification, Appendix I" .
|
||||
.Pp
|
||||
Each line in the file
|
||||
(other than comment lines that begin with a #)
|
||||
@ -71,7 +73,8 @@ The second is to specify the pathname of the root of the filesystem
|
||||
followed by the
|
||||
.Fl alldirs
|
||||
flag;
|
||||
this form allows the host(s) to mount any directory within the filesystem.
|
||||
this form allows the host(s) to mount at any point within the filesystem,
|
||||
including regular files if the ``-r'' option is used on mountd.
|
||||
The pathnames must not have any symbolic links in them and should not have
|
||||
any "." or ".." components.
|
||||
Mount points for a filesystem may appear on multiple lines each with
|
||||
@ -140,8 +143,7 @@ The
|
||||
.Fl kerb
|
||||
option specifies that the Kerberos authentication server should be
|
||||
used to authenticate and map client credentials.
|
||||
(Note that this is NOT Sun NFS compatible and
|
||||
is supported for TCP transport only.)
|
||||
This requires that the kernel be built with the NFSKERB option.
|
||||
.Pp
|
||||
The
|
||||
.Fl ro
|
||||
|
@ -30,7 +30,7 @@
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" From: @(#)mountd.8 8.1 (Berkeley) 6/9/93
|
||||
.\" $Id: mountd.8,v 1.2 1994/09/22 22:16:49 wollman Exp $
|
||||
.\" $Id: mountd.8,v 1.3 1995/02/22 21:42:48 ats Exp $
|
||||
.\"
|
||||
.Dd September 22, 1994
|
||||
.Dt MOUNTD 8
|
||||
@ -42,7 +42,7 @@
|
||||
mount requests
|
||||
.Sh SYNOPSIS
|
||||
.Nm /sbin/mountd
|
||||
.Op Fl n
|
||||
.Op Fl nr
|
||||
.Op Ar exportsfile
|
||||
.Sh DESCRIPTION
|
||||
.Xr Mountd
|
||||
@ -54,7 +54,9 @@ listens for service requests at the port indicated in the
|
||||
.Tn NFS
|
||||
server specification; see
|
||||
.%T "Network File System Protocol Specification" ,
|
||||
RFC1094.
|
||||
RFC1094, Appendix A and
|
||||
.%T "NFS: Network File System Version 3 Protocol Specification" ,
|
||||
Appendix I.
|
||||
.Pp
|
||||
Options and operands available for
|
||||
.Nm mountd :
|
||||
@ -65,6 +67,15 @@ The
|
||||
option allows non-root mount requests to be served.
|
||||
This should only be specified if there are clients such as PC's,
|
||||
that require it.
|
||||
.It Fl r
|
||||
The
|
||||
.Fl r
|
||||
option allows mount RPCs requests for regular files to be served.
|
||||
Although this seems to violate the mount protocol specification, some diskless
|
||||
workstations do mount requests for their swapfiles and expect them to be
|
||||
regular files. Since a regular file cannot be specified in /etc/exports, the
|
||||
entire file system that the swapfiles reside in will have to be exported with
|
||||
the ``-alldirs'' flag.
|
||||
.It Ar exportsfile
|
||||
The
|
||||
.Ar exportsfile
|
||||
|
@ -43,7 +43,7 @@ static char copyright[] =
|
||||
#ifndef lint
|
||||
/*static char sccsid[] = "From: @(#)mountd.c 8.8 (Berkeley) 2/20/94";*/
|
||||
static const char rcsid[] =
|
||||
"$Id: mountd.c,v 1.7.2.1 1995/06/08 04:34:11 davidg Exp $";
|
||||
"$Id: mountd.c,v 1.8 1995/06/11 19:30:46 rgrimes Exp $";
|
||||
#endif /*not lint*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -62,7 +62,7 @@ static const char rcsid[] =
|
||||
#include <netiso/iso.h>
|
||||
#endif
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
@ -100,6 +100,8 @@ struct dirlist {
|
||||
};
|
||||
/* dp_flag bits */
|
||||
#define DP_DEFSET 0x1
|
||||
#define DP_HOSTSET 0x2
|
||||
#define DP_KERB 0x4
|
||||
|
||||
struct exportlist {
|
||||
struct exportlist *ex_next;
|
||||
@ -139,22 +141,29 @@ struct grouplist {
|
||||
#define GT_IGNORE 0x5
|
||||
|
||||
struct hostlist {
|
||||
int ht_flag; /* Uses DP_xx bits */
|
||||
struct grouplist *ht_grp;
|
||||
struct hostlist *ht_next;
|
||||
};
|
||||
|
||||
struct fhreturn {
|
||||
int fhr_flag;
|
||||
int fhr_vers;
|
||||
nfsfh_t fhr_fh;
|
||||
};
|
||||
|
||||
/* Global defs */
|
||||
char *add_expdir __P((struct dirlist **, char *, int));
|
||||
void add_dlist __P((struct dirlist **, struct dirlist *,
|
||||
struct grouplist *));
|
||||
struct grouplist *, int));
|
||||
void add_mlist __P((char *, char *));
|
||||
int check_dirpath __P((char *));
|
||||
int check_options __P((struct dirlist *));
|
||||
int chk_host __P((struct dirlist *, u_long, int *));
|
||||
int chk_host __P((struct dirlist *, u_long, int *, int *));
|
||||
void del_mlist __P((char *, char *));
|
||||
struct dirlist *dirp_search __P((struct dirlist *, char *));
|
||||
int do_mount __P((struct exportlist *, struct grouplist *, int,
|
||||
struct ucred *, char *, int, struct statfs *));
|
||||
struct ucred *, char *, int, struct statfs *));
|
||||
int do_opt __P((char **, char **, struct exportlist *, struct grouplist *,
|
||||
int *, int *, struct ucred *));
|
||||
struct exportlist *ex_search __P((fsid_t *));
|
||||
@ -165,6 +174,7 @@ void free_grp __P((struct grouplist *));
|
||||
void free_host __P((struct hostlist *));
|
||||
void get_exportlist __P((void));
|
||||
int get_host __P((char *, struct grouplist *, struct grouplist *));
|
||||
int get_num __P((char *));
|
||||
struct hostlist *get_ht __P((void));
|
||||
int get_line __P((void));
|
||||
void get_mountlist __P((void));
|
||||
@ -183,7 +193,7 @@ void send_umntall __P((void));
|
||||
int umntall_each __P((caddr_t, struct sockaddr_in *));
|
||||
int xdr_dir __P((XDR *, char *));
|
||||
int xdr_explist __P((XDR *, caddr_t));
|
||||
int xdr_fhs __P((XDR *, nfsv2fh_t *));
|
||||
int xdr_fhs __P((XDR *, caddr_t));
|
||||
int xdr_mlist __P((XDR *, caddr_t));
|
||||
|
||||
/* C library */
|
||||
@ -205,7 +215,8 @@ struct ucred def_anon = {
|
||||
1,
|
||||
{ (gid_t) -2 }
|
||||
};
|
||||
int root_only = 1;
|
||||
int resvport_only = 1;
|
||||
int dir_only = 1;
|
||||
int opt_flags;
|
||||
/* Bits for above */
|
||||
#define OP_MAPROOT 0x01
|
||||
@ -238,6 +249,7 @@ main(argc, argv)
|
||||
{
|
||||
SVCXPRT *udptransp, *tcptransp;
|
||||
int c;
|
||||
#ifdef __FreeBSD__
|
||||
struct vfsconf *vfc;
|
||||
|
||||
vfc = getvfsbyname("nfs");
|
||||
@ -250,17 +262,21 @@ main(argc, argv)
|
||||
if(!vfc) {
|
||||
errx(1, "NFS support is not available in the running kernel");
|
||||
}
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
while ((c = getopt(argc, argv, "dn")) != EOF)
|
||||
while ((c = getopt(argc, argv, "dnr")) != EOF)
|
||||
switch (c) {
|
||||
case 'n':
|
||||
resvport_only = 0;
|
||||
break;
|
||||
case 'r':
|
||||
dir_only = 0;
|
||||
break;
|
||||
case 'd':
|
||||
debug = debug ? 0 : 1;
|
||||
break;
|
||||
case 'n':
|
||||
root_only = 0;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Usage: mountd [-n] [export_file]\n");
|
||||
fprintf(stderr, "Usage: mountd [-r] [-n] [export_file]\n");
|
||||
exit(1);
|
||||
};
|
||||
argc -= optind;
|
||||
@ -300,11 +316,12 @@ main(argc, argv)
|
||||
syslog(LOG_ERR, "Can't create socket");
|
||||
exit(1);
|
||||
}
|
||||
pmap_unset(RPCPROG_MNT, RPCMNT_VER1);
|
||||
if (!svc_register(udptransp, RPCPROG_MNT, RPCMNT_VER1, mntsrv,
|
||||
IPPROTO_UDP) ||
|
||||
!svc_register(tcptransp, RPCPROG_MNT, RPCMNT_VER1, mntsrv,
|
||||
IPPROTO_TCP)) {
|
||||
pmap_unset(RPCPROG_MNT, 1);
|
||||
pmap_unset(RPCPROG_MNT, 3);
|
||||
if (!svc_register(udptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_UDP) ||
|
||||
!svc_register(udptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_UDP) ||
|
||||
!svc_register(tcptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_TCP) ||
|
||||
!svc_register(tcptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_TCP)) {
|
||||
syslog(LOG_ERR, "Can't register mount");
|
||||
exit(1);
|
||||
}
|
||||
@ -323,28 +340,21 @@ mntsrv(rqstp, transp)
|
||||
{
|
||||
struct exportlist *ep;
|
||||
struct dirlist *dp;
|
||||
nfsv2fh_t nfh;
|
||||
struct fhreturn fhr;
|
||||
struct authunix_parms *ucr;
|
||||
struct stat stb;
|
||||
struct statfs fsb;
|
||||
struct hostent *hp;
|
||||
u_long saddr;
|
||||
u_short sport;
|
||||
char rpcpath[RPCMNT_PATHLEN+1], dirpath[MAXPATHLEN];
|
||||
int bad = ENOENT, omask, defset;
|
||||
uid_t uid = -2;
|
||||
|
||||
/* Get authorization */
|
||||
switch (rqstp->rq_cred.oa_flavor) {
|
||||
case AUTH_UNIX:
|
||||
ucr = (struct authunix_parms *)rqstp->rq_clntcred;
|
||||
uid = ucr->aup_uid;
|
||||
break;
|
||||
case AUTH_NULL:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
int bad = ENOENT, defset, hostset;
|
||||
sigset_t sighup_mask;
|
||||
|
||||
sigemptyset(&sighup_mask);
|
||||
sigaddset(&sighup_mask, SIGHUP);
|
||||
saddr = transp->xp_raddr.sin_addr.s_addr;
|
||||
sport = ntohs(transp->xp_raddr.sin_port);
|
||||
hp = (struct hostent *)NULL;
|
||||
switch (rqstp->rq_proc) {
|
||||
case NULLPROC:
|
||||
@ -352,7 +362,7 @@ mntsrv(rqstp, transp)
|
||||
syslog(LOG_ERR, "Can't send reply");
|
||||
return;
|
||||
case RPCMNT_MOUNT:
|
||||
if ((uid != 0 && root_only) || uid == -2) {
|
||||
if (sport >= IPPORT_RESERVED && resvport_only) {
|
||||
svcerr_weakauth(transp);
|
||||
return;
|
||||
}
|
||||
@ -363,11 +373,13 @@ mntsrv(rqstp, transp)
|
||||
|
||||
/*
|
||||
* Get the real pathname and make sure it is a directory
|
||||
* that exists.
|
||||
* or a regular file if the -r option was specified
|
||||
* and it exists.
|
||||
*/
|
||||
if (realpath(rpcpath, dirpath) == 0 ||
|
||||
stat(dirpath, &stb) < 0 ||
|
||||
(stb.st_mode & S_IFMT) != S_IFDIR ||
|
||||
(!S_ISDIR(stb.st_mode) &&
|
||||
(dir_only || !S_ISREG(stb.st_mode))) ||
|
||||
statfs(dirpath, &fsb) < 0) {
|
||||
chdir("/"); /* Just in case realpath doesn't */
|
||||
if (debug)
|
||||
@ -378,26 +390,31 @@ mntsrv(rqstp, transp)
|
||||
}
|
||||
|
||||
/* Check in the exports list */
|
||||
omask = sigblock(sigmask(SIGHUP));
|
||||
sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
|
||||
ep = ex_search(&fsb.f_fsid);
|
||||
defset = 0;
|
||||
if (ep && (chk_host(ep->ex_defdir, saddr, &defset) ||
|
||||
hostset = defset = 0;
|
||||
if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) ||
|
||||
((dp = dirp_search(ep->ex_dirl, dirpath)) &&
|
||||
chk_host(dp, saddr, &defset)) ||
|
||||
chk_host(dp, saddr, &defset, &hostset)) ||
|
||||
(defset && scan_tree(ep->ex_defdir, saddr) == 0 &&
|
||||
scan_tree(ep->ex_dirl, saddr) == 0))) {
|
||||
if (hostset & DP_HOSTSET)
|
||||
fhr.fhr_flag = hostset;
|
||||
else
|
||||
fhr.fhr_flag = defset;
|
||||
fhr.fhr_vers = rqstp->rq_vers;
|
||||
/* Get the file handle */
|
||||
bzero((caddr_t)&nfh, sizeof(nfh));
|
||||
if (getfh(dirpath, (fhandle_t *)&nfh) < 0) {
|
||||
bzero((caddr_t)&fhr.fhr_fh, sizeof(nfsfh_t));
|
||||
if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) {
|
||||
bad = errno;
|
||||
syslog(LOG_ERR, "Can't get fh for %s", dirpath);
|
||||
if (!svc_sendreply(transp, xdr_long,
|
||||
(caddr_t)&bad))
|
||||
syslog(LOG_ERR, "Can't send reply");
|
||||
sigsetmask(omask);
|
||||
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
|
||||
return;
|
||||
}
|
||||
if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh))
|
||||
if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr))
|
||||
syslog(LOG_ERR, "Can't send reply");
|
||||
if (hp == NULL)
|
||||
hp = gethostbyaddr((caddr_t)&saddr,
|
||||
@ -414,14 +431,14 @@ mntsrv(rqstp, transp)
|
||||
if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
|
||||
syslog(LOG_ERR, "Can't send reply");
|
||||
}
|
||||
sigsetmask(omask);
|
||||
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
|
||||
return;
|
||||
case RPCMNT_DUMP:
|
||||
if (!svc_sendreply(transp, xdr_mlist, (caddr_t)NULL))
|
||||
syslog(LOG_ERR, "Can't send reply");
|
||||
return;
|
||||
case RPCMNT_UMOUNT:
|
||||
if ((uid != 0 && root_only) || uid == -2) {
|
||||
if (sport >= IPPORT_RESERVED && resvport_only) {
|
||||
svcerr_weakauth(transp);
|
||||
return;
|
||||
}
|
||||
@ -437,7 +454,7 @@ mntsrv(rqstp, transp)
|
||||
del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), dirpath);
|
||||
return;
|
||||
case RPCMNT_UMNTALL:
|
||||
if ((uid != 0 && root_only) || uid == -2) {
|
||||
if (sport >= IPPORT_RESERVED && resvport_only) {
|
||||
svcerr_weakauth(transp);
|
||||
return;
|
||||
}
|
||||
@ -470,18 +487,37 @@ xdr_dir(xdrsp, dirp)
|
||||
}
|
||||
|
||||
/*
|
||||
* Xdr routine to generate fhstatus
|
||||
* Xdr routine to generate file handle reply
|
||||
*/
|
||||
int
|
||||
xdr_fhs(xdrsp, nfh)
|
||||
xdr_fhs(xdrsp, cp)
|
||||
XDR *xdrsp;
|
||||
nfsv2fh_t *nfh;
|
||||
caddr_t cp;
|
||||
{
|
||||
u_long ok = 0;
|
||||
register struct fhreturn *fhrp = (struct fhreturn *)cp;
|
||||
u_long ok = 0, len, auth;
|
||||
|
||||
if (!xdr_long(xdrsp, &ok))
|
||||
return (0);
|
||||
return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH));
|
||||
switch (fhrp->fhr_vers) {
|
||||
case 1:
|
||||
return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH));
|
||||
case 3:
|
||||
len = NFSX_V3FH;
|
||||
if (!xdr_long(xdrsp, &len))
|
||||
return (0);
|
||||
if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len))
|
||||
return (0);
|
||||
if (fhrp->fhr_flag & DP_KERB)
|
||||
auth = RPCAUTH_KERB4;
|
||||
else
|
||||
auth = RPCAUTH_UNIX;
|
||||
len = 1;
|
||||
if (!xdr_long(xdrsp, &len))
|
||||
return (0);
|
||||
return (xdr_long(xdrsp, &auth));
|
||||
};
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -521,9 +557,12 @@ xdr_explist(xdrsp, cp)
|
||||
{
|
||||
struct exportlist *ep;
|
||||
int false = 0;
|
||||
int omask, putdef;
|
||||
int putdef;
|
||||
sigset_t sighup_mask;
|
||||
|
||||
omask = sigblock(sigmask(SIGHUP));
|
||||
sigemptyset(&sighup_mask);
|
||||
sigaddset(&sighup_mask, SIGHUP);
|
||||
sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
|
||||
ep = exphead;
|
||||
while (ep) {
|
||||
putdef = 0;
|
||||
@ -535,12 +574,12 @@ xdr_explist(xdrsp, cp)
|
||||
goto errout;
|
||||
ep = ep->ex_next;
|
||||
}
|
||||
sigsetmask(omask);
|
||||
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
|
||||
if (!xdr_bool(xdrsp, &false))
|
||||
return (0);
|
||||
return (1);
|
||||
errout:
|
||||
sigsetmask(omask);
|
||||
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -660,6 +699,18 @@ get_exportlist()
|
||||
struct ufs_args ua;
|
||||
struct iso_args ia;
|
||||
struct mfs_args ma;
|
||||
#ifdef __NetBSD__
|
||||
struct msdosfs_args da;
|
||||
} targs;
|
||||
|
||||
if (!strcmp(fsp->f_fstypename, MOUNT_MFS) ||
|
||||
!strcmp(fsp->f_fstypename, MOUNT_UFS) ||
|
||||
!strcmp(fsp->f_fstypename, MOUNT_MSDOS) ||
|
||||
!strcmp(fsp->f_fstypename, MOUNT_CD9660)) {
|
||||
targs.ua.fspec = NULL;
|
||||
targs.ua.export.ex_flags = MNT_DELEXPORT;
|
||||
if (mount(fsp->f_fstypename, fsp->f_mntonname,
|
||||
#else
|
||||
} targs;
|
||||
|
||||
switch (fsp->f_type) {
|
||||
@ -670,6 +721,7 @@ get_exportlist()
|
||||
targs.ua.fspec = NULL;
|
||||
targs.ua.export.ex_flags = MNT_DELEXPORT;
|
||||
if (mount(fsp->f_type, fsp->f_mntonname,
|
||||
#endif
|
||||
fsp->f_flags | MNT_UPDATE,
|
||||
(caddr_t)&targs) < 0)
|
||||
syslog(LOG_ERR, "Can't delete exports for %s",
|
||||
@ -805,6 +857,7 @@ get_exportlist()
|
||||
if (get_host(hst, grp, tgrp)) {
|
||||
syslog(LOG_ERR, "Bad netgroup %s", cp);
|
||||
getexp_err(ep, tgrp);
|
||||
endnetgrent();
|
||||
goto nextline;
|
||||
}
|
||||
} else if (get_host(cp, grp, tgrp)) {
|
||||
@ -865,12 +918,12 @@ get_exportlist()
|
||||
* Success. Update the data structures.
|
||||
*/
|
||||
if (has_host) {
|
||||
hang_dirp(dirhead, tgrp, ep, (opt_flags & OP_ALLDIRS));
|
||||
hang_dirp(dirhead, tgrp, ep, opt_flags);
|
||||
grp->gr_next = grphead;
|
||||
grphead = tgrp;
|
||||
} else {
|
||||
hang_dirp(dirhead, (struct grouplist *)NULL, ep,
|
||||
(opt_flags & OP_ALLDIRS));
|
||||
opt_flags);
|
||||
free_grp(grp);
|
||||
}
|
||||
dirhead = (struct dirlist *)NULL;
|
||||
@ -994,24 +1047,28 @@ add_expdir(dpp, cp, len)
|
||||
* and update the entry for host.
|
||||
*/
|
||||
void
|
||||
hang_dirp(dp, grp, ep, alldirs)
|
||||
hang_dirp(dp, grp, ep, flags)
|
||||
struct dirlist *dp;
|
||||
struct grouplist *grp;
|
||||
struct exportlist *ep;
|
||||
int alldirs;
|
||||
int flags;
|
||||
{
|
||||
struct hostlist *hp;
|
||||
struct dirlist *dp2;
|
||||
|
||||
if (alldirs) {
|
||||
if (flags & OP_ALLDIRS) {
|
||||
if (ep->ex_defdir)
|
||||
free((caddr_t)dp);
|
||||
else
|
||||
ep->ex_defdir = dp;
|
||||
if (grp == (struct grouplist *)NULL)
|
||||
if (grp == (struct grouplist *)NULL) {
|
||||
ep->ex_defdir->dp_flag |= DP_DEFSET;
|
||||
else while (grp) {
|
||||
if (flags & OP_KERB)
|
||||
ep->ex_defdir->dp_flag |= DP_KERB;
|
||||
} else while (grp) {
|
||||
hp = get_ht();
|
||||
if (flags & OP_KERB)
|
||||
hp->ht_flag |= DP_KERB;
|
||||
hp->ht_grp = grp;
|
||||
hp->ht_next = ep->ex_defdir->dp_hosts;
|
||||
ep->ex_defdir->dp_hosts = hp;
|
||||
@ -1024,7 +1081,7 @@ hang_dirp(dp, grp, ep, alldirs)
|
||||
*/
|
||||
while (dp) {
|
||||
dp2 = dp->dp_left;
|
||||
add_dlist(&ep->ex_dirl, dp, grp);
|
||||
add_dlist(&ep->ex_dirl, dp, grp, flags);
|
||||
dp = dp2;
|
||||
}
|
||||
}
|
||||
@ -1035,10 +1092,11 @@ hang_dirp(dp, grp, ep, alldirs)
|
||||
* for the new directory or adding the new node.
|
||||
*/
|
||||
void
|
||||
add_dlist(dpp, newdp, grp)
|
||||
add_dlist(dpp, newdp, grp, flags)
|
||||
struct dirlist **dpp;
|
||||
struct dirlist *newdp;
|
||||
struct grouplist *grp;
|
||||
int flags;
|
||||
{
|
||||
struct dirlist *dp;
|
||||
struct hostlist *hp;
|
||||
@ -1048,10 +1106,10 @@ add_dlist(dpp, newdp, grp)
|
||||
if (dp) {
|
||||
cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
|
||||
if (cmp > 0) {
|
||||
add_dlist(&dp->dp_left, newdp, grp);
|
||||
add_dlist(&dp->dp_left, newdp, grp, flags);
|
||||
return;
|
||||
} else if (cmp < 0) {
|
||||
add_dlist(&dp->dp_right, newdp, grp);
|
||||
add_dlist(&dp->dp_right, newdp, grp, flags);
|
||||
return;
|
||||
} else
|
||||
free((caddr_t)newdp);
|
||||
@ -1067,13 +1125,18 @@ add_dlist(dpp, newdp, grp)
|
||||
*/
|
||||
do {
|
||||
hp = get_ht();
|
||||
if (flags & OP_KERB)
|
||||
hp->ht_flag |= DP_KERB;
|
||||
hp->ht_grp = grp;
|
||||
hp->ht_next = dp->dp_hosts;
|
||||
dp->dp_hosts = hp;
|
||||
grp = grp->gr_next;
|
||||
} while (grp);
|
||||
} else
|
||||
} else {
|
||||
dp->dp_flag |= DP_DEFSET;
|
||||
if (flags & OP_KERB)
|
||||
dp->dp_flag |= DP_KERB;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1102,10 +1165,11 @@ dirp_search(dp, dirpath)
|
||||
* Scan for a host match in a directory tree.
|
||||
*/
|
||||
int
|
||||
chk_host(dp, saddr, defsetp)
|
||||
chk_host(dp, saddr, defsetp, hostsetp)
|
||||
struct dirlist *dp;
|
||||
u_long saddr;
|
||||
int *defsetp;
|
||||
int *hostsetp;
|
||||
{
|
||||
struct hostlist *hp;
|
||||
struct grouplist *grp;
|
||||
@ -1113,7 +1177,7 @@ chk_host(dp, saddr, defsetp)
|
||||
|
||||
if (dp) {
|
||||
if (dp->dp_flag & DP_DEFSET)
|
||||
*defsetp = 1;
|
||||
*defsetp = dp->dp_flag;
|
||||
hp = dp->dp_hosts;
|
||||
while (hp) {
|
||||
grp = hp->ht_grp;
|
||||
@ -1122,15 +1186,19 @@ chk_host(dp, saddr, defsetp)
|
||||
addrp = (u_long **)
|
||||
grp->gr_ptr.gt_hostent->h_addr_list;
|
||||
while (*addrp) {
|
||||
if (**addrp == saddr)
|
||||
if (**addrp == saddr) {
|
||||
*hostsetp = (hp->ht_flag | DP_HOSTSET);
|
||||
return (1);
|
||||
}
|
||||
addrp++;
|
||||
}
|
||||
break;
|
||||
case GT_NET:
|
||||
if ((saddr & grp->gr_ptr.gt_net.nt_mask) ==
|
||||
grp->gr_ptr.gt_net.nt_net)
|
||||
grp->gr_ptr.gt_net.nt_net) {
|
||||
*hostsetp = (hp->ht_flag | DP_HOSTSET);
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
};
|
||||
hp = hp->ht_next;
|
||||
@ -1147,12 +1215,12 @@ scan_tree(dp, saddr)
|
||||
struct dirlist *dp;
|
||||
u_long saddr;
|
||||
{
|
||||
int defset;
|
||||
int defset, hostset;
|
||||
|
||||
if (dp) {
|
||||
if (scan_tree(dp->dp_left, saddr))
|
||||
return (1);
|
||||
if (chk_host(dp, saddr, &defset))
|
||||
if (chk_host(dp, saddr, &defset, &hostset))
|
||||
return (1);
|
||||
if (scan_tree(dp->dp_right, saddr))
|
||||
return (1);
|
||||
@ -1312,7 +1380,7 @@ get_host(cp, grp, tgrp)
|
||||
if (isdigit(*cp)) {
|
||||
saddr = inet_addr(cp);
|
||||
if (saddr == -1) {
|
||||
syslog(LOG_ERR, "Inet_addr failed");
|
||||
syslog(LOG_ERR, "Inet_addr failed for %s", cp);
|
||||
return (1);
|
||||
}
|
||||
if ((hp = gethostbyaddr((caddr_t)&saddr, sizeof (saddr),
|
||||
@ -1326,7 +1394,7 @@ get_host(cp, grp, tgrp)
|
||||
aptr[1] = (char *)NULL;
|
||||
}
|
||||
} else {
|
||||
syslog(LOG_ERR, "Gethostbyname failed");
|
||||
syslog(LOG_ERR, "Gethostbyname failed for %s", cp);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
@ -1424,6 +1492,7 @@ get_ht()
|
||||
if (hp == (struct hostlist *)NULL)
|
||||
out_of_mem();
|
||||
hp->ht_next = (struct hostlist *)NULL;
|
||||
hp->ht_flag = 0;
|
||||
return (hp);
|
||||
}
|
||||
|
||||
@ -1494,6 +1563,9 @@ do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
|
||||
struct ufs_args ua;
|
||||
struct iso_args ia;
|
||||
struct mfs_args ma;
|
||||
#ifdef __NetBSD__
|
||||
struct msdosfs_args da;
|
||||
#endif
|
||||
} args;
|
||||
u_long net;
|
||||
|
||||
@ -1569,7 +1641,11 @@ do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
|
||||
* Also, needs to know how to export all types of local
|
||||
* exportable file systems and not just MOUNT_UFS.
|
||||
*/
|
||||
#ifdef __NetBSD__
|
||||
while (mount(fsb->f_fstypename, dirp,
|
||||
#else
|
||||
while (mount(fsb->f_type, dirp,
|
||||
#endif
|
||||
fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) {
|
||||
if (cp)
|
||||
*cp-- = savedc;
|
||||
@ -2033,15 +2109,30 @@ check_dirpath(dirp)
|
||||
while (*cp && ret) {
|
||||
if (*cp == '/') {
|
||||
*cp = '\0';
|
||||
if (lstat(dirp, &sb) < 0 ||
|
||||
(sb.st_mode & S_IFMT) != S_IFDIR)
|
||||
if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode))
|
||||
ret = 0;
|
||||
*cp = '/';
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
if (lstat(dirp, &sb) < 0 ||
|
||||
(sb.st_mode & S_IFMT) != S_IFDIR)
|
||||
if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode))
|
||||
ret = 0;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Just translate an ascii string to an integer.
|
||||
*/
|
||||
int
|
||||
get_num(cp)
|
||||
register char *cp;
|
||||
{
|
||||
register int res = 0;
|
||||
|
||||
while (*cp) {
|
||||
if (*cp < '0' || *cp > '9')
|
||||
return (-1);
|
||||
res = res * 10 + (*cp++ - '0');
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
@ -98,7 +98,8 @@ listens for service requests at the port indicated in the
|
||||
.Tn NFS
|
||||
server specification; see
|
||||
.%T "Network File System Protocol Specification" ,
|
||||
RFC1094.
|
||||
RFC1094 and
|
||||
.%T "NFS: Network File System Version 3 Protocol Specification" .
|
||||
.Pp
|
||||
If
|
||||
.Nm nfsd
|
||||
|
110
sbin/nfsd/nfsd.c
110
sbin/nfsd/nfsd.c
@ -63,10 +63,10 @@ static char sccsid[] = "@(#)nfsd.c 8.7 (Berkeley) 2/22/94";
|
||||
#include <netiso/iso.h>
|
||||
#endif
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
|
||||
#ifdef KERBEROS
|
||||
#ifdef NFSKERB
|
||||
#include <kerberosIV/des.h>
|
||||
#include <kerberosIV/krb.h>
|
||||
#endif
|
||||
@ -94,16 +94,23 @@ struct nfsd_srvargs nsd;
|
||||
char **Argv = NULL; /* pointer to argument vector */
|
||||
char *LastArg = NULL; /* end of argv */
|
||||
|
||||
#ifdef KERBEROS
|
||||
#ifdef NFSKERB
|
||||
char lnam[ANAME_SZ];
|
||||
KTEXT_ST kt;
|
||||
AUTH_DAT auth;
|
||||
AUTH_DAT kauth;
|
||||
char inst[INST_SZ];
|
||||
struct nfsrpc_fullblock kin, kout;
|
||||
struct nfsrpc_fullverf kverf;
|
||||
NFSKERBKEY_T kivec;
|
||||
struct timeval ktv;
|
||||
NFSKERBKEYSCHED_T kerb_keysched;
|
||||
#endif
|
||||
|
||||
void nonfs __P((int));
|
||||
void reapchild __P((int));
|
||||
#ifdef __FreeBSD__
|
||||
void setproctitle __P((char *));
|
||||
#endif
|
||||
void usage __P((void));
|
||||
|
||||
/*
|
||||
@ -139,11 +146,13 @@ main(argc, argv, envp)
|
||||
#ifdef ISO
|
||||
struct sockaddr_iso isoaddr, isopeer;
|
||||
#endif
|
||||
struct timeval ktv;
|
||||
fd_set ready, sockbits;
|
||||
int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
|
||||
int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
|
||||
int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag;
|
||||
char *cp, **cpp;
|
||||
#ifdef __FreeBSD__
|
||||
struct vfsconf *vfc;
|
||||
|
||||
vfc = getvfsbyname("nfs");
|
||||
@ -156,6 +165,7 @@ main(argc, argv, envp)
|
||||
if(!vfc) {
|
||||
errx(1, "NFS is not available in the running kernel");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Save start and extent of argv for setproctitle. */
|
||||
Argv = argv;
|
||||
@ -241,10 +251,12 @@ main(argc, argv, envp)
|
||||
|
||||
if (reregister) {
|
||||
if (udpflag &&
|
||||
!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT))
|
||||
(!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
|
||||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)))
|
||||
err(1, "can't register with portmap for UDP.");
|
||||
if (tcpflag &&
|
||||
!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT))
|
||||
(!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
|
||||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)))
|
||||
err(1, "can't register with portmap for TCP.");
|
||||
exit(0);
|
||||
}
|
||||
@ -261,11 +273,17 @@ main(argc, argv, envp)
|
||||
continue;
|
||||
}
|
||||
|
||||
setproctitle("nfsd-srv");
|
||||
setproctitle("server");
|
||||
nfssvc_flag = NFSSVC_NFSD;
|
||||
nsd.nsd_nfsd = NULL;
|
||||
#ifdef KERBEROS
|
||||
nsd.nsd_authstr = (char *)kt.dat;
|
||||
#ifdef NFSKERB
|
||||
if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF ||
|
||||
sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK)
|
||||
syslog(LOG_ERR, "Yikes NFSKERB structs not packed!");
|
||||
nsd.nsd_authstr = (u_char *)&kt;
|
||||
nsd.nsd_authlen = sizeof (kt);
|
||||
nsd.nsd_verfstr = (u_char *)&kverf;
|
||||
nsd.nsd_verflen = sizeof (kverf);
|
||||
#endif
|
||||
while (nfssvc(nfssvc_flag, &nsd) < 0) {
|
||||
if (errno != ENEEDAUTH) {
|
||||
@ -273,14 +291,27 @@ main(argc, argv, envp)
|
||||
exit(1);
|
||||
}
|
||||
nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
|
||||
#ifdef KERBEROS
|
||||
kt.length = nsd.nsd_authlen;
|
||||
kt.mbz = 0;
|
||||
(void)strcpy(inst, "*");
|
||||
if (krb_rd_req(&kt, "rcmd",
|
||||
inst, nsd.nsd_haddr, &auth, "") == RD_AP_OK &&
|
||||
krb_kntoln(&auth, lnam) == KSUCCESS &&
|
||||
(pwd = getpwnam(lnam)) != NULL) {
|
||||
#ifdef NFSKERB
|
||||
/*
|
||||
* Get the Kerberos ticket out of the authenticator
|
||||
* verify it and convert the principal name to a user
|
||||
* name. The user name is then converted to a set of
|
||||
* user credentials via the password and group file.
|
||||
* Finally, decrypt the timestamp and validate it.
|
||||
* For more info see the IETF Draft "Authentication
|
||||
* in ONC RPC".
|
||||
*/
|
||||
kt.length = ntohl(kt.length);
|
||||
if (gettimeofday(&ktv, (struct timezone *)0) == 0 &&
|
||||
kt.length > 0 && kt.length <=
|
||||
(RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) {
|
||||
kin.w1 = NFS_KERBW1(kt);
|
||||
kt.mbz = 0;
|
||||
(void)strcpy(inst, "*");
|
||||
if (krb_rd_req(&kt, NFS_KERBSRV,
|
||||
inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK &&
|
||||
krb_kntoln(&kauth, lnam) == KSUCCESS &&
|
||||
(pwd = getpwnam(lnam)) != NULL) {
|
||||
cr = &nsd.nsd_cr;
|
||||
cr->cr_uid = pwd->pw_uid;
|
||||
cr->cr_groups[0] = pwd->pw_gid;
|
||||
@ -301,9 +332,34 @@ main(argc, argv, envp)
|
||||
break;
|
||||
}
|
||||
endgrent();
|
||||
nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
|
||||
|
||||
/*
|
||||
* Get the timestamp verifier out of the
|
||||
* authenticator and verifier strings.
|
||||
*/
|
||||
kin.t1 = kverf.t1;
|
||||
kin.t2 = kverf.t2;
|
||||
kin.w2 = kverf.w2;
|
||||
bzero((caddr_t)kivec, sizeof (kivec));
|
||||
bcopy((caddr_t)kauth.session,
|
||||
(caddr_t)nsd.nsd_key,sizeof(kauth.session));
|
||||
|
||||
/*
|
||||
* Decrypt the timestamp verifier in CBC mode.
|
||||
*/
|
||||
XXX
|
||||
|
||||
/*
|
||||
* Validate the timestamp verifier, to
|
||||
* check that the session key is ok.
|
||||
*/
|
||||
nsd.nsd_timestamp.tv_sec = ntohl(kout.t1);
|
||||
nsd.nsd_timestamp.tv_usec = ntohl(kout.t2);
|
||||
nsd.nsd_ttl = ntohl(kout.w1);
|
||||
if ((nsd.nsd_ttl - 1) == ntohl(kout.w2))
|
||||
nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
|
||||
}
|
||||
#endif /* KERBEROS */
|
||||
#endif /* NFSKERB */
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
@ -323,7 +379,8 @@ main(argc, argv, envp)
|
||||
syslog(LOG_ERR, "can't bind udp addr");
|
||||
exit(1);
|
||||
}
|
||||
if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
|
||||
if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
|
||||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
|
||||
syslog(LOG_ERR, "can't register with udp portmap");
|
||||
exit(1);
|
||||
}
|
||||
@ -403,7 +460,8 @@ main(argc, argv, envp)
|
||||
syslog(LOG_ERR, "listen failed");
|
||||
exit(1);
|
||||
}
|
||||
if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
|
||||
if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
|
||||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
|
||||
syslog(LOG_ERR, "can't register tcp with portmap");
|
||||
exit(1);
|
||||
}
|
||||
@ -492,7 +550,7 @@ main(argc, argv, envp)
|
||||
if (connect_type_cnt == 0)
|
||||
exit(0);
|
||||
|
||||
setproctitle("nfsd-master");
|
||||
setproctitle("master");
|
||||
|
||||
/*
|
||||
* Loop forever accepting connections and passing the sockets
|
||||
@ -566,7 +624,7 @@ main(argc, argv, envp)
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "nfsd %s\n", USAGE);
|
||||
(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -582,9 +640,10 @@ reapchild(signo)
|
||||
int signo;
|
||||
{
|
||||
|
||||
while (wait3(NULL, WNOHANG, NULL));
|
||||
while (wait3(NULL, WNOHANG, NULL) > 0);
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
void
|
||||
setproctitle(a)
|
||||
char *a;
|
||||
@ -593,9 +652,10 @@ setproctitle(a)
|
||||
char buf[80];
|
||||
|
||||
cp = Argv[0];
|
||||
(void)snprintf(buf, sizeof(buf), "%s", a);
|
||||
(void)snprintf(buf, sizeof(buf), "nfsd-%s", a);
|
||||
(void)strncpy(cp, buf, LastArg - cp);
|
||||
cp += strlen(cp);
|
||||
while (cp < LastArg)
|
||||
*cp++ = '\0';
|
||||
}
|
||||
#endif /* __FreeBSD__ */
|
||||
|
@ -50,8 +50,10 @@ static char sccsid[] = "@(#)nfsiod.c 8.3 (Berkeley) 2/22/94";
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
|
||||
#include <err.h>
|
||||
|
279
sys/nfs/nfs.h
279
sys/nfs/nfs.h
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfs.h,v 1.8 1994/11/02 00:11:00 wollman Exp $
|
||||
* $Id: nfs.h,v 1.9 1995/02/14 06:22:18 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFS_H_
|
||||
@ -45,11 +45,12 @@
|
||||
*/
|
||||
|
||||
#define NFS_MAXIOVEC 34
|
||||
#define NFS_HZ 25 /* Ticks per second for NFS timeouts */
|
||||
#define NFS_TIMEO (1*NFS_HZ) /* Default timeout = 1 second */
|
||||
#define NFS_MINTIMEO (1*NFS_HZ) /* Min timeout to use */
|
||||
#define NFS_MAXTIMEO (60*NFS_HZ) /* Max timeout to backoff to */
|
||||
#define NFS_MINIDEMTIMEO (5*NFS_HZ) /* Min timeout for non-idempotent ops*/
|
||||
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
|
||||
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
|
||||
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
|
||||
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
|
||||
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
|
||||
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
|
||||
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
|
||||
#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
|
||||
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
|
||||
@ -62,13 +63,81 @@
|
||||
#endif
|
||||
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
|
||||
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
|
||||
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
|
||||
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
|
||||
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
|
||||
#define NFS_MAXREADDIR NFS_MAXDATA /* Max. size of directory read */
|
||||
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
|
||||
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
|
||||
#define NFS_DIRBLKSIZ 1024 /* Size of an NFS directory block */
|
||||
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
|
||||
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
|
||||
#ifndef NFS_GATHERDELAY
|
||||
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
|
||||
#endif
|
||||
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
|
||||
|
||||
/*
|
||||
* Oddballs
|
||||
*/
|
||||
#define NMOD(a) ((a) % nfs_asyncdaemons)
|
||||
#define NFS_CMPFH(n, f, s) \
|
||||
((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
|
||||
#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
|
||||
#define NFS_SRVMAXDATA(n) \
|
||||
(((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
|
||||
NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* sys/buf.h should be editted to change B_APPENDWRITE --> B_NEEDCOMMIT, but
|
||||
* until then...
|
||||
* Same goes for sys/malloc.h, which needs M_NFSDIROFF,
|
||||
* M_NFSRVDESC and M_NFSBIGFH added.
|
||||
* The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
|
||||
* exclusive create.
|
||||
* The B_INVAFTERWRITE flag should be set to whatever is required by the
|
||||
* buffer cache code to say "Invalidate the block after it is written back".
|
||||
*/
|
||||
#ifndef B_NEEDCOMMIT
|
||||
#define B_NEEDCOMMIT B_APPENDWRITE
|
||||
#endif
|
||||
#ifndef M_NFSRVDESC
|
||||
#define M_NFSRVDESC M_TEMP
|
||||
#endif
|
||||
#ifndef M_NFSDIROFF
|
||||
#define M_NFSDIROFF M_TEMP
|
||||
#endif
|
||||
#ifndef M_NFSBIGFH
|
||||
#define M_NFSBIGFH M_TEMP
|
||||
#endif
|
||||
#ifndef VA_EXCLUSIVE
|
||||
#define VA_EXCLUSIVE 0
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#define B_INVAFTERWRITE B_NOCACHE
|
||||
#else
|
||||
#define B_INVAFTERWRITE B_INVAL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These ifdefs try to handle the differences between the various 4.4BSD-Lite
|
||||
* based vfs interfaces.
|
||||
* btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
|
||||
* differentiate between NetBSD-1.0 and NetBSD-current, so..
|
||||
* I also don't know about BSDi's 2.0 release.
|
||||
*/
|
||||
#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||
#define HAS_VOPLEASE 1
|
||||
#endif
|
||||
#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||
#define HAS_VOPREVOKE 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The IO_METASYNC flag should be implemented for local file systems.
|
||||
* (Until then, it is nothin at all.)
|
||||
*/
|
||||
#ifndef IO_METASYNC
|
||||
#define IO_METASYNC 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the attribute timeout based on how recently the file has been modified.
|
||||
@ -79,6 +148,20 @@
|
||||
((time.tv_sec - (np)->n_mtime) / 10 > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
|
||||
(time.tv_sec - (np)->n_mtime) / 10))
|
||||
|
||||
/*
|
||||
* Expected allocation sizes for major data structures. If the actual size
|
||||
* of the structure exceeds these sizes, then malloc() will be allocating
|
||||
* almost twice the memory required. This is used in nfs_init() to warn
|
||||
* the sysadmin that the size of a structure should be reduced.
|
||||
* (These sizes are always a power of 2. If the kernel malloc() changes
|
||||
* to one that does not allocate space in powers of 2 size, then this all
|
||||
* becomes bunk!)
|
||||
*/
|
||||
#define NFS_NODEALLOC 256
|
||||
#define NFS_MNTALLOC 512
|
||||
#define NFS_SVCALLOC 256
|
||||
#define NFS_UIDALLOC 128
|
||||
|
||||
/*
|
||||
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
|
||||
* should ever try and use it.
|
||||
@ -95,7 +178,12 @@ struct nfsd_srvargs {
|
||||
u_long nsd_haddr; /* Ip address of client */
|
||||
struct ucred nsd_cr; /* Cred. uid maps to */
|
||||
int nsd_authlen; /* Length of auth string (ret) */
|
||||
char *nsd_authstr; /* Auth string (ret) */
|
||||
u_char *nsd_authstr; /* Auth string (ret) */
|
||||
int nsd_verflen; /* and the verfier */
|
||||
u_char *nsd_verfstr;
|
||||
struct timeval nsd_timestamp; /* timestamp from verifier */
|
||||
u_long nsd_ttl; /* credential ttl (sec) */
|
||||
NFSKERBKEY_T nsd_key; /* Session key */
|
||||
};
|
||||
|
||||
struct nfsd_cargs {
|
||||
@ -103,7 +191,10 @@ struct nfsd_cargs {
|
||||
uid_t ncd_authuid; /* Effective uid */
|
||||
int ncd_authtype; /* Type of authenticator */
|
||||
int ncd_authlen; /* Length of authenticator string */
|
||||
char *ncd_authstr; /* Authenticator string */
|
||||
u_char *ncd_authstr; /* Authenticator string */
|
||||
int ncd_verflen; /* and the verifier */
|
||||
u_char *ncd_verfstr;
|
||||
NFSKERBKEY_T ncd_key; /* Session key */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -142,6 +233,7 @@ struct nfsstats {
|
||||
int srvnqnfs_leases;
|
||||
int srvnqnfs_maxleases;
|
||||
int srvnqnfs_getleases;
|
||||
int srvvop_writes;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -173,7 +265,7 @@ struct nfsstats {
|
||||
* such as SIGALRM will not expect file I/O system calls to be interrupted
|
||||
* by them and break.
|
||||
*/
|
||||
#ifdef KERNEL
|
||||
#if defined(KERNEL) || defined(_KERNEL)
|
||||
|
||||
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
|
||||
|
||||
@ -224,17 +316,29 @@ TAILQ_HEAD(, nfsreq) nfs_reqq;
|
||||
#define R_MUSTRESEND 0x40 /* Must resend request */
|
||||
#define R_GETONEREP 0x80 /* Probe for one reply only */
|
||||
|
||||
extern struct nfsstats nfsstats;
|
||||
|
||||
/*
|
||||
* A list of nfssvc_sock structures is maintained with all the sockets
|
||||
* that require service by the nfsd.
|
||||
* The nfsuid structs hang off of the nfssvc_sock structs in both lru
|
||||
* and uid hash lists.
|
||||
*/
|
||||
#define NUIDHASHSIZ 32
|
||||
#ifndef NFS_UIDHASHSIZ
|
||||
#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
|
||||
#endif
|
||||
#define NUIDHASH(sock, uid) \
|
||||
(&(sock)->ns_uidhashtbl[(uid) & (sock)->ns_uidhash])
|
||||
(&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
|
||||
#ifndef NFS_WDELAYHASHSIZ
|
||||
#define NFS_WDELAYHASHSIZ 16 /* and with this */
|
||||
#endif
|
||||
#define NWDELAYHASH(sock, f) \
|
||||
(&(sock)->ns_wdelayhashtbl[(*((u_long *)(f))) % NFS_WDELAYHASHSIZ])
|
||||
#ifndef NFS_MUIDHASHSIZ
|
||||
#define NFS_MUIDHASHSIZ 67 /* Tune the size of nfsmount with this */
|
||||
#endif
|
||||
#define NMUIDHASH(nmp, uid) \
|
||||
(&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
|
||||
#define NFSNOHASH(fhsum) \
|
||||
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
|
||||
|
||||
/*
|
||||
* Network address hash list element
|
||||
@ -248,35 +352,41 @@ struct nfsuid {
|
||||
TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
|
||||
LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
|
||||
int nu_flag; /* Flags */
|
||||
uid_t nu_uid; /* Uid mapped by this entry */
|
||||
union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
|
||||
struct ucred nu_cr; /* Cred uid mapped to */
|
||||
int nu_expire; /* Expiry time (sec) */
|
||||
struct timeval nu_timestamp; /* Kerb. timestamp */
|
||||
u_long nu_nickname; /* Nickname on server */
|
||||
NFSKERBKEY_T nu_key; /* and session key */
|
||||
};
|
||||
|
||||
#define nu_inetaddr nu_haddr.had_inetaddr
|
||||
#define nu_nam nu_haddr.had_nam
|
||||
/* Bits for nu_flag */
|
||||
#define NU_INETADDR 0x1
|
||||
#define NU_NAM 0x2
|
||||
#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
|
||||
|
||||
struct nfssvc_sock {
|
||||
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
|
||||
TAILQ_HEAD(, nfsuid) ns_uidlruhead;
|
||||
LIST_HEAD(, nfsuid) *ns_uidhashtbl;
|
||||
u_long ns_uidhash;
|
||||
|
||||
int ns_flag;
|
||||
u_long ns_sref;
|
||||
struct file *ns_fp;
|
||||
struct socket *ns_so;
|
||||
int ns_solock;
|
||||
struct mbuf *ns_nam;
|
||||
int ns_cc;
|
||||
struct mbuf *ns_raw;
|
||||
struct mbuf *ns_rawend;
|
||||
int ns_reclen;
|
||||
struct mbuf *ns_rec;
|
||||
struct mbuf *ns_recend;
|
||||
struct mbuf *ns_frag;
|
||||
int ns_flag;
|
||||
int ns_solock;
|
||||
int ns_cc;
|
||||
int ns_reclen;
|
||||
int ns_numuids;
|
||||
u_long ns_sref;
|
||||
LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
|
||||
LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
|
||||
LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
|
||||
};
|
||||
|
||||
/* Bits for "ns_flag" */
|
||||
@ -285,6 +395,7 @@ struct nfssvc_sock {
|
||||
#define SLP_NEEDQ 0x04
|
||||
#define SLP_DISCONN 0x08
|
||||
#define SLP_GETSTREAM 0x10
|
||||
#define SLP_LASTFRAG 0x20
|
||||
#define SLP_ALLFLAGS 0xff
|
||||
|
||||
TAILQ_HEAD(, nfssvc_sock) nfssvc_sockhead;
|
||||
@ -296,73 +407,124 @@ int nfssvc_sockhead_flag;
|
||||
* One of these structures is allocated for each nfsd.
|
||||
*/
|
||||
struct nfsd {
|
||||
TAILQ_ENTRY(nfsd) nd_chain; /* List of all nfsd's */
|
||||
int nd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nd_slp; /* Current socket */
|
||||
struct mbuf *nd_nam; /* Client addr for datagram req. */
|
||||
struct mbuf *nd_mrep; /* Req. mbuf list */
|
||||
struct mbuf *nd_md;
|
||||
caddr_t nd_dpos; /* Position in list */
|
||||
int nd_procnum; /* RPC procedure number */
|
||||
u_long nd_retxid; /* RPC xid */
|
||||
int nd_repstat; /* Reply status value */
|
||||
struct ucred nd_cr; /* Credentials for req. */
|
||||
int nd_nqlflag; /* Leasing flag */
|
||||
u_long nd_duration; /* Lease duration */
|
||||
int nd_authlen; /* Authenticator len */
|
||||
u_char nd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
|
||||
struct proc *nd_procp; /* Proc ptr */
|
||||
TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
|
||||
int nfsd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nfsd_slp; /* Current socket */
|
||||
int nfsd_authlen; /* Authenticator len */
|
||||
u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
|
||||
int nfsd_verflen; /* and the Verifier */
|
||||
u_char nfsd_verfstr[RPCVERF_MAXSIZ];
|
||||
struct proc *nfsd_procp; /* Proc ptr */
|
||||
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
|
||||
};
|
||||
|
||||
/* Bits for "nd_flag" */
|
||||
/* Bits for "nfsd_flag" */
|
||||
#define NFSD_WAITING 0x01
|
||||
#define NFSD_REQINPROG 0x02
|
||||
#define NFSD_NEEDAUTH 0x04
|
||||
#define NFSD_AUTHFAIL 0x08
|
||||
|
||||
/*
|
||||
* This structure is used by the server for describing each request.
|
||||
* Some fields are used only when write request gathering is performed.
|
||||
*/
|
||||
struct nfsrv_descript {
|
||||
u_quad_t nd_time; /* Write deadline (usec) */
|
||||
off_t nd_off; /* Start byte offset */
|
||||
off_t nd_eoff; /* and end byte offset */
|
||||
LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
|
||||
LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
|
||||
LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
|
||||
struct mbuf *nd_mrep; /* Request mbuf list */
|
||||
struct mbuf *nd_md; /* Current dissect mbuf */
|
||||
struct mbuf *nd_mreq; /* Reply mbuf list */
|
||||
struct mbuf *nd_nam; /* and socket addr */
|
||||
struct mbuf *nd_nam2; /* return socket addr */
|
||||
caddr_t nd_dpos; /* Current dissect pos */
|
||||
int nd_procnum; /* RPC # */
|
||||
int nd_stable; /* storage type */
|
||||
int nd_flag; /* nd_flag */
|
||||
int nd_len; /* Length of this write */
|
||||
int nd_repstat; /* Reply status */
|
||||
u_long nd_retxid; /* Reply xid */
|
||||
u_long nd_duration; /* Lease duration */
|
||||
struct timeval nd_starttime; /* Time RPC initiated */
|
||||
fhandle_t nd_fh; /* File handle */
|
||||
struct ucred nd_cr; /* Credentials */
|
||||
};
|
||||
|
||||
/* Bits for "nd_flag" */
|
||||
#define ND_READ LEASE_READ
|
||||
#define ND_WRITE LEASE_WRITE
|
||||
#define ND_CHECK 0x04
|
||||
#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
|
||||
#define ND_NFSV3 0x08
|
||||
#define ND_NQNFS 0x10
|
||||
#define ND_KERBNICK 0x20
|
||||
#define ND_KERBFULL 0x40
|
||||
#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
|
||||
|
||||
TAILQ_HEAD(, nfsd) nfsd_head;
|
||||
int nfsd_head_flag;
|
||||
#define NFSD_CHECKSLP 0x01
|
||||
|
||||
/*
|
||||
* These macros compare nfsrv_descript structures.
|
||||
*/
|
||||
#define NFSW_CONTIG(o, n) \
|
||||
((o)->nd_eoff >= (n)->nd_off && \
|
||||
!bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
|
||||
|
||||
#define NFSW_SAMECRED(o, n) \
|
||||
(((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
|
||||
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
|
||||
sizeof (struct ucred)))
|
||||
|
||||
int nfs_reply __P((struct nfsreq *));
|
||||
int nfs_getreq __P((struct nfsd *,int));
|
||||
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
|
||||
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
|
||||
int nfs_rephead __P((int,struct nfsd *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_rephead __P((int,struct nfsrv_descript *,struct nfssvc_sock *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_sndlock __P((int *,struct nfsreq *));
|
||||
int nfs_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
|
||||
int nfs_vinvalbuf __P((struct vnode *,int,struct ucred *,struct proc *,int));
|
||||
int nfs_readrpc __P((struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int));
|
||||
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int *,int *));
|
||||
int nfs_readdirrpc __P((register struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
|
||||
int nfs_asyncio __P((struct buf *,struct ucred *));
|
||||
int nfs_doio __P((struct buf *,struct ucred *,struct proc *));
|
||||
int nfs_readlinkrpc __P((struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_sigintr __P((struct nfsmount *,struct nfsreq *r,struct proc *));
|
||||
int nfs_readdirlookrpc __P((struct vnode *,register struct uio *,struct ucred *));
|
||||
int nfs_readdirplusrpc __P((struct vnode *,register struct uio *,struct ucred *));
|
||||
int nfsm_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
|
||||
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *));
|
||||
void nfsm_srvfattr __P((struct nfsrv_descript *,struct vattr *,struct nfs_fattr *));
|
||||
void nfsm_srvwcc __P((struct nfsrv_descript *,int,struct vattr *,int,struct vattr *,struct mbuf **,char **));
|
||||
void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct mbuf **,char **));
|
||||
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *,int));
|
||||
int nfsrv_access __P((struct vnode *,int,struct ucred *,int,struct proc *));
|
||||
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
|
||||
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
|
||||
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct proc *));
|
||||
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
|
||||
void nfsm_adj __P((struct mbuf *,int,int));
|
||||
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
|
||||
void nfsrv_initcache __P((void));
|
||||
int nfs_rcvlock __P((struct nfsreq *));
|
||||
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,int *,char **,int *));
|
||||
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,char **,int *,char *,int *,NFSKERBKEY_T));
|
||||
int nfs_getnickauth __P((struct nfsmount *,struct ucred *,char **,int *,char *,int));
|
||||
int nfs_savenickauth __P((struct nfsmount *,struct ucred *,int,NFSKERBKEY_T,struct mbuf **,char **,struct mbuf *));
|
||||
int nfs_msg __P((struct proc *,char *,char *));
|
||||
int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
|
||||
int nfsrv_getstream __P((struct nfssvc_sock *,int));
|
||||
void nfs_nhinit __P((void));
|
||||
void nfs_timer __P((void*));
|
||||
struct nfsnodehashhead * nfs_hash __P((nfsv2fh_t *));
|
||||
u_long nfs_hash __P((nfsfh_t *,int));
|
||||
int nfssvc_iod __P((struct proc *));
|
||||
int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,struct proc *));
|
||||
int nfssvc_addsock __P((struct file *,struct mbuf *));
|
||||
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *));
|
||||
int nfsrv_getcache __P((struct mbuf *,struct nfsd *,struct mbuf **));
|
||||
void nfsrv_updatecache __P((struct mbuf *,struct nfsd *,int,struct mbuf *));
|
||||
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
|
||||
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
|
||||
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
|
||||
int mountnfs __P((struct nfs_args *,struct mount *,struct mbuf *,char *,char *,struct vnode **));
|
||||
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
|
||||
int nfs_getattrcache __P((struct vnode *,struct vattr *));
|
||||
@ -370,9 +532,20 @@ int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
|
||||
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
|
||||
int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
|
||||
void nfsrv_init __P((int));
|
||||
void nfs_clearcommit __P((struct mount *));
|
||||
int nfsrv_errmap __P((struct nfsrv_descript *, int));
|
||||
void nfsrvw_coalesce __P((struct nfsrv_descript *,struct nfsrv_descript *));
|
||||
void nfsrvw_sort __P((gid_t [],int));
|
||||
void nfsrv_setcred __P((struct ucred *,struct ucred *));
|
||||
int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
|
||||
int nfs_writebp __P((struct buf *,int));
|
||||
int nfsrv_vput __P(( struct vnode * ));
|
||||
int nfsrv_vrele __P(( struct vnode * ));
|
||||
int nfsrv_vmio __P(( struct vnode * ));
|
||||
int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
|
||||
struct proc *, struct mbuf **));
|
||||
int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
|
||||
struct proc *p));
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_bio.c 8.5 (Berkeley) 1/4/94
|
||||
* $Id: nfs_bio.c,v 1.13 1995/05/21 21:39:21 davidg Exp $
|
||||
* $Id: nfs_bio.c,v 1.14 1995/05/30 08:12:35 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -49,16 +49,30 @@
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <nfs/nfsnode.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/nqnfs.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
|
||||
struct buf *nfs_getcacheblk();
|
||||
extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
|
||||
extern int nfs_numasync;
|
||||
extern struct nfsstats nfsstats;
|
||||
|
||||
/*
|
||||
* Ifdefs for FreeBSD-current's merged VM/buffer cache. It is unfortunate
|
||||
* that this isn't done inside getblk() and brelse() so these calls
|
||||
* wouldn't need to be here.
|
||||
*/
|
||||
#ifdef B_VMIO
|
||||
#define vnode_pager_uncache(vp)
|
||||
#else
|
||||
#define vfs_busy_pages(bp, f)
|
||||
#define vfs_unbusy_pages(bp)
|
||||
#define vfs_dirty_pages(bp)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Vnode op for read using bio
|
||||
@ -72,29 +86,28 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
struct ucred *cred;
|
||||
{
|
||||
register struct nfsnode *np = VTONFS(vp);
|
||||
register int biosize, diff;
|
||||
register int biosize, diff, i;
|
||||
struct buf *bp = 0, *rabp;
|
||||
struct vattr vattr;
|
||||
struct proc *p;
|
||||
struct nfsmount *nmp;
|
||||
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||
daddr_t lbn, rabn;
|
||||
int bufsize;
|
||||
int nra, error = 0, n = 0, on = 0, not_readin;
|
||||
nfsquad_t tquad;
|
||||
|
||||
#ifdef lint
|
||||
ioflag = ioflag;
|
||||
#endif /* lint */
|
||||
#ifdef DIAGNOSTIC
|
||||
if (uio->uio_rw != UIO_READ)
|
||||
panic("nfs_read mode");
|
||||
#endif
|
||||
if (uio->uio_resid == 0)
|
||||
return (0);
|
||||
if (uio->uio_offset < 0 && vp->v_type != VDIR)
|
||||
if (uio->uio_offset < 0)
|
||||
return (EINVAL);
|
||||
nmp = VFSTONFS(vp->v_mount);
|
||||
biosize = NFS_MAXDGRAMDATA;
|
||||
p = uio->uio_procp;
|
||||
if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
|
||||
(void)nfs_fsinfo(nmp, vp, cred, p);
|
||||
biosize = nmp->nm_rsize;
|
||||
/*
|
||||
* For nfs, cache consistency can only be maintained approximately.
|
||||
* Although RFC1094 does not specify the criteria, the following is
|
||||
@ -107,8 +120,6 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
* server, so flush all of the file's data out of the cache.
|
||||
* Then force a getattr rpc to ensure that you have up to date
|
||||
* attributes.
|
||||
* The mount flag NFSMNT_MYWRITE says "Assume that my writes are
|
||||
* the ones changing the modify time.
|
||||
* NB: This implies that cache data can be read when up to
|
||||
* NFS_ATTRTIMEO seconds out of date. If you find that you need current
|
||||
* attributes this could be forced by setting n_attrstamp to 0 before
|
||||
@ -116,14 +127,15 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
*/
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) == 0 && vp->v_type != VLNK) {
|
||||
if (np->n_flag & NMODIFIED) {
|
||||
if ((nmp->nm_flag & NFSMNT_MYWRITE) == 0 ||
|
||||
vp->v_type != VREG) {
|
||||
if (vp->v_type != VREG) {
|
||||
if (vp->v_type != VDIR)
|
||||
panic("nfs: bioread, not dir");
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
np->n_attrstamp = 0;
|
||||
np->n_direofoffset = 0;
|
||||
error = VOP_GETATTR(vp, &vattr, cred, p);
|
||||
if (error)
|
||||
return (error);
|
||||
@ -133,7 +145,8 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
if (error)
|
||||
return (error);
|
||||
if (np->n_mtime != vattr.va_mtime.ts_sec) {
|
||||
np->n_direofoffset = 0;
|
||||
if (vp->v_type == VDIR)
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
@ -147,27 +160,24 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
* Get a valid lease. If cached data is stale, flush it.
|
||||
*/
|
||||
if (nmp->nm_flag & NFSMNT_NQNFS) {
|
||||
if (NQNFS_CKINVALID(vp, np, NQL_READ)) {
|
||||
if (NQNFS_CKINVALID(vp, np, ND_READ)) {
|
||||
do {
|
||||
error = nqnfs_getlease(vp, NQL_READ, cred, p);
|
||||
error = nqnfs_getlease(vp, ND_READ, cred, p);
|
||||
} while (error == NQNFS_EXPIRED);
|
||||
if (error)
|
||||
return (error);
|
||||
if (np->n_lrev != np->n_brev ||
|
||||
(np->n_flag & NQNFSNONCACHE) ||
|
||||
((np->n_flag & NMODIFIED) && vp->v_type == VDIR)) {
|
||||
if (vp->v_type == VDIR) {
|
||||
np->n_direofoffset = 0;
|
||||
cache_purge(vp);
|
||||
}
|
||||
if (vp->v_type == VDIR)
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
np->n_brev = np->n_lrev;
|
||||
}
|
||||
} else if (vp->v_type == VDIR && (np->n_flag & NMODIFIED)) {
|
||||
np->n_direofoffset = 0;
|
||||
cache_purge(vp);
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
@ -176,33 +186,27 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
if (np->n_flag & NQNFSNONCACHE) {
|
||||
switch (vp->v_type) {
|
||||
case VREG:
|
||||
error = nfs_readrpc(vp, uio, cred);
|
||||
break;
|
||||
return (nfs_readrpc(vp, uio, cred));
|
||||
case VLNK:
|
||||
error = nfs_readlinkrpc(vp, uio, cred);
|
||||
break;
|
||||
return (nfs_readlinkrpc(vp, uio, cred));
|
||||
case VDIR:
|
||||
error = nfs_readdirrpc(vp, uio, cred);
|
||||
break;
|
||||
default:
|
||||
printf(" NQNFSNONCACHE: type %x unexpected\n",
|
||||
vp->v_type);
|
||||
break;
|
||||
};
|
||||
return (error);
|
||||
}
|
||||
switch (vp->v_type) {
|
||||
case VREG:
|
||||
nfsstats.biocache_reads++;
|
||||
lbn = uio->uio_offset / biosize;
|
||||
on = uio->uio_offset & (biosize-1);
|
||||
on = uio->uio_offset & (biosize - 1);
|
||||
not_readin = 1;
|
||||
|
||||
/*
|
||||
* Start the read ahead(s), as required.
|
||||
*/
|
||||
if (nfs_numasync > 0 && nmp->nm_readahead > 0 &&
|
||||
lbn == vp->v_lastr + 1) {
|
||||
if (nfs_numasync > 0 && nmp->nm_readahead > 0) {
|
||||
for (nra = 0; nra < nmp->nm_readahead &&
|
||||
(lbn + 1 + nra) * biosize < np->n_size; nra++) {
|
||||
rabn = lbn + 1 + nra;
|
||||
@ -296,32 +300,55 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
break;
|
||||
case VDIR:
|
||||
nfsstats.biocache_readdirs++;
|
||||
lbn = (daddr_t)uio->uio_offset;
|
||||
lbn = uio->uio_offset / NFS_DIRBLKSIZ;
|
||||
on = uio->uio_offset & (NFS_DIRBLKSIZ - 1);
|
||||
bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, p);
|
||||
if (!bp)
|
||||
return (EINTR);
|
||||
|
||||
return (EINTR);
|
||||
if ((bp->b_flags & B_CACHE) == 0) {
|
||||
bp->b_flags |= B_READ;
|
||||
vfs_busy_pages(bp, 0);
|
||||
error = nfs_doio(bp, cred, p);
|
||||
if (error) {
|
||||
bp->b_flags |= B_ERROR;
|
||||
brelse(bp);
|
||||
return (error);
|
||||
bp->b_flags |= B_READ;
|
||||
vfs_busy_pages(bp, 0);
|
||||
error = nfs_doio(bp, cred, p);
|
||||
if (error) {
|
||||
brelse(bp);
|
||||
while (error == NFSERR_BAD_COOKIE) {
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, 0, cred, p, 1);
|
||||
/*
|
||||
* Yuck! The directory has been modified on the
|
||||
* server. The only way to get the block is by
|
||||
* reading from the beginning to get all the
|
||||
* offset cookies.
|
||||
*/
|
||||
for (i = 0; i <= lbn && !error; i++) {
|
||||
bp = nfs_getcacheblk(vp, i, NFS_DIRBLKSIZ, p);
|
||||
if (!bp)
|
||||
return (EINTR);
|
||||
if ((bp->b_flags & B_DONE) == 0) {
|
||||
bp->b_flags |= B_READ;
|
||||
vfs_busy_pages(bp, 0);
|
||||
error = nfs_doio(bp, cred, p);
|
||||
if (error)
|
||||
brelse(bp);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If not eof and read aheads are enabled, start one.
|
||||
* (You need the current block first, so that you have the
|
||||
* directory offset cookie of the next block.
|
||||
* directory offset cookie of the next block.)
|
||||
*/
|
||||
rabn = bp->b_blkno;
|
||||
if (nfs_numasync > 0 && nmp->nm_readahead > 0 &&
|
||||
rabn != 0 && rabn != np->n_direofoffset &&
|
||||
!incore(vp, rabn)) {
|
||||
rabp = nfs_getcacheblk(vp, rabn, NFS_DIRBLKSIZ, p);
|
||||
(np->n_direofoffset == 0 ||
|
||||
(lbn + 1) * NFS_DIRBLKSIZ < np->n_direofoffset) &&
|
||||
!(np->n_flag & NQNFSNONCACHE) &&
|
||||
!incore(vp, lbn + 1)) {
|
||||
rabp = nfs_getcacheblk(vp, lbn + 1, NFS_DIRBLKSIZ, p);
|
||||
if (rabp) {
|
||||
if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) {
|
||||
rabp->b_flags |= (B_READ | B_ASYNC);
|
||||
@ -336,11 +363,10 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
}
|
||||
}
|
||||
}
|
||||
on = 0;
|
||||
n = min(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid);
|
||||
n = min(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid - on);
|
||||
break;
|
||||
default:
|
||||
printf(" nfsbioread: type %x unexpected\n",vp->v_type);
|
||||
printf(" nfs_bioread: type %x unexpected\n",vp->v_type);
|
||||
break;
|
||||
};
|
||||
|
||||
@ -354,11 +380,11 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
n = 0;
|
||||
break;
|
||||
case VDIR:
|
||||
uio->uio_offset = bp->b_blkno;
|
||||
if (np->n_flag & NQNFSNONCACHE)
|
||||
bp->b_flags |= B_INVAL;
|
||||
break;
|
||||
default:
|
||||
printf(" nfsbioread: type %x unexpected\n",vp->v_type);
|
||||
break;
|
||||
printf(" nfs_bioread: type %x unexpected\n",vp->v_type);
|
||||
}
|
||||
brelse(bp);
|
||||
} while (error == 0 && uio->uio_resid > 0 && n > 0);
|
||||
@ -386,10 +412,10 @@ nfs_write(ap)
|
||||
int ioflag = ap->a_ioflag;
|
||||
struct buf *bp;
|
||||
struct vattr vattr;
|
||||
struct nfsmount *nmp;
|
||||
daddr_t lbn;
|
||||
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||
daddr_t lbn, bn;
|
||||
int bufsize;
|
||||
int n, on, error = 0;
|
||||
int n, on, error = 0, iomode, must_commit;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (uio->uio_rw != UIO_WRITE)
|
||||
@ -403,6 +429,8 @@ nfs_write(ap)
|
||||
np->n_flag &= ~NWRITEERR;
|
||||
return (np->n_error);
|
||||
}
|
||||
if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
|
||||
(void)nfs_fsinfo(nmp, vp, cred, p);
|
||||
if (ioflag & (IO_APPEND | IO_SYNC)) {
|
||||
if (np->n_flag & NMODIFIED) {
|
||||
np->n_attrstamp = 0;
|
||||
@ -418,7 +446,6 @@ nfs_write(ap)
|
||||
uio->uio_offset = np->n_size;
|
||||
}
|
||||
}
|
||||
nmp = VFSTONFS(vp->v_mount);
|
||||
if (uio->uio_offset < 0)
|
||||
return (EINVAL);
|
||||
if (uio->uio_resid == 0)
|
||||
@ -437,7 +464,7 @@ nfs_write(ap)
|
||||
* will be the same size within a filesystem. nfs_writerpc will
|
||||
* still use nm_wsize when sizing the rpc's.
|
||||
*/
|
||||
biosize = NFS_MAXDGRAMDATA;
|
||||
biosize = nmp->nm_rsize;
|
||||
do {
|
||||
|
||||
/*
|
||||
@ -445,12 +472,11 @@ nfs_write(ap)
|
||||
*/
|
||||
/*
|
||||
* Check for a valid write lease.
|
||||
* If non-cachable, just do the rpc
|
||||
*/
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
NQNFS_CKINVALID(vp, np, NQL_WRITE)) {
|
||||
NQNFS_CKINVALID(vp, np, ND_WRITE)) {
|
||||
do {
|
||||
error = nqnfs_getlease(vp, NQL_WRITE, cred, p);
|
||||
error = nqnfs_getlease(vp, ND_WRITE, cred, p);
|
||||
} while (error == NQNFS_EXPIRED);
|
||||
if (error)
|
||||
return (error);
|
||||
@ -462,8 +488,13 @@ nfs_write(ap)
|
||||
np->n_brev = np->n_lrev;
|
||||
}
|
||||
}
|
||||
if (np->n_flag & NQNFSNONCACHE)
|
||||
return (nfs_writerpc(vp, uio, cred, ioflag));
|
||||
if ((np->n_flag & NQNFSNONCACHE) && uio->uio_iovcnt == 1) {
|
||||
iomode = NFSV3WRITE_FILESYNC;
|
||||
error = nfs_writerpc(vp, uio, cred, &iomode, &must_commit);
|
||||
if (must_commit)
|
||||
nfs_clearcommit(vp->v_mount);
|
||||
return (error);
|
||||
}
|
||||
nfsstats.biocache_writes++;
|
||||
lbn = uio->uio_offset / biosize;
|
||||
on = uio->uio_offset & (biosize-1);
|
||||
@ -509,9 +540,9 @@ nfs_write(ap)
|
||||
* In case getblk() and/or bwrite() delayed us.
|
||||
*/
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
NQNFS_CKINVALID(vp, np, NQL_WRITE)) {
|
||||
NQNFS_CKINVALID(vp, np, ND_WRITE)) {
|
||||
do {
|
||||
error = nqnfs_getlease(vp, NQL_WRITE, cred, p);
|
||||
error = nqnfs_getlease(vp, ND_WRITE, cred, p);
|
||||
} while (error == NQNFS_EXPIRED);
|
||||
if (error) {
|
||||
brelse(bp);
|
||||
@ -540,7 +571,6 @@ nfs_write(ap)
|
||||
bp->b_dirtyoff = on;
|
||||
bp->b_dirtyend = on + n;
|
||||
}
|
||||
#ifndef notdef
|
||||
if (bp->b_validend == 0 || bp->b_validend < bp->b_dirtyoff ||
|
||||
bp->b_validoff > bp->b_dirtyend) {
|
||||
bp->b_validoff = bp->b_dirtyoff;
|
||||
@ -549,13 +579,6 @@ nfs_write(ap)
|
||||
bp->b_validoff = min(bp->b_validoff, bp->b_dirtyoff);
|
||||
bp->b_validend = max(bp->b_validend, bp->b_dirtyend);
|
||||
}
|
||||
#else
|
||||
bp->b_validoff = bp->b_dirtyoff;
|
||||
bp->b_validend = bp->b_dirtyend;
|
||||
#endif
|
||||
if (ioflag & IO_APPEND)
|
||||
bp->b_flags |= B_APPENDWRITE;
|
||||
|
||||
/*
|
||||
* If the lease is non-cachable or IO_SYNC do bwrite().
|
||||
*/
|
||||
@ -564,10 +587,16 @@ nfs_write(ap)
|
||||
error = VOP_BWRITE(bp);
|
||||
if (error)
|
||||
return (error);
|
||||
if (np->n_flag & NQNFSNONCACHE) {
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
} else if ((n + on) == biosize &&
|
||||
(nmp->nm_flag & NFSMNT_NQNFS) == 0) {
|
||||
bp->b_proc = (struct proc *)0;
|
||||
bawrite(bp);
|
||||
bp->b_flags |= B_ASYNC;
|
||||
(void)nfs_writebp(bp, 0);
|
||||
} else
|
||||
bdwrite(bp);
|
||||
} while (uio->uio_resid > 0 && n > 0);
|
||||
@ -590,6 +619,7 @@ nfs_getcacheblk(vp, bn, size, p)
|
||||
{
|
||||
register struct buf *bp;
|
||||
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||
int biosize = nmp->nm_rsize;
|
||||
|
||||
if (nmp->nm_flag & NFSMNT_INT) {
|
||||
bp = getblk(vp, bn, size, PCATCH, 0);
|
||||
@ -602,7 +632,7 @@ nfs_getcacheblk(vp, bn, size, p)
|
||||
bp = getblk(vp, bn, size, 0, 0);
|
||||
|
||||
if( vp->v_type == VREG)
|
||||
bp->b_blkno = (bn * NFS_MAXDGRAMDATA) / DEV_BSIZE;
|
||||
bp->b_blkno = (bn * biosize) / DEV_BSIZE;
|
||||
|
||||
return (bp);
|
||||
}
|
||||
@ -689,6 +719,7 @@ nfs_asyncio(bp, cred)
|
||||
bp->b_rcred = cred;
|
||||
}
|
||||
} else {
|
||||
bp->b_flags |= B_WRITEINPROG;
|
||||
if (bp->b_wcred == NOCRED && cred != NOCRED) {
|
||||
crhold(cred);
|
||||
bp->b_wcred = cred;
|
||||
@ -700,7 +731,25 @@ nfs_asyncio(bp, cred)
|
||||
wakeup((caddr_t)&nfs_iodwant[i]);
|
||||
return (0);
|
||||
}
|
||||
return (EIO);
|
||||
|
||||
/*
|
||||
* If it is a read or a write already marked B_WRITEINPROG or B_NOCACHE
|
||||
* return EIO so the process will call nfs_doio() and do it
|
||||
* synchronously.
|
||||
*/
|
||||
if (bp->b_flags & (B_READ | B_WRITEINPROG | B_NOCACHE))
|
||||
return (EIO);
|
||||
|
||||
/*
|
||||
* Just turn the async write into a delayed write, instead of
|
||||
* doing in synchronously. Hopefully, at least one of the nfsiods
|
||||
* is currently doing a write for this file and will pick up the
|
||||
* delayed writes before going back to sleep.
|
||||
*/
|
||||
bp->b_flags |= B_DELWRI;
|
||||
reassignbuf(bp, bp->b_vp);
|
||||
biodone(bp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -717,9 +766,10 @@ nfs_doio(bp, cr, p)
|
||||
register struct vnode *vp;
|
||||
struct nfsnode *np;
|
||||
struct nfsmount *nmp;
|
||||
int error = 0, diff, len;
|
||||
int error = 0, diff, len, iomode, must_commit = 0;
|
||||
struct uio uio;
|
||||
struct iovec io;
|
||||
nfsquad_t tquad;
|
||||
|
||||
vp = bp->b_vp;
|
||||
np = VTONFS(vp);
|
||||
@ -740,15 +790,18 @@ nfs_doio(bp, cr, p)
|
||||
io.iov_len = uiop->uio_resid = bp->b_bcount;
|
||||
/* mapping was done by vmapbuf() */
|
||||
io.iov_base = bp->b_data;
|
||||
uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
|
||||
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
|
||||
if (bp->b_flags & B_READ) {
|
||||
uiop->uio_rw = UIO_READ;
|
||||
nfsstats.read_physios++;
|
||||
error = nfs_readrpc(vp, uiop, cr);
|
||||
} else {
|
||||
int com;
|
||||
|
||||
iomode = NFSV3WRITE_DATASYNC;
|
||||
uiop->uio_rw = UIO_WRITE;
|
||||
nfsstats.write_physios++;
|
||||
error = nfs_writerpc(vp, uiop, cr,0);
|
||||
error = nfs_writerpc(vp, uiop, cr, &iomode, &com);
|
||||
}
|
||||
if (error) {
|
||||
bp->b_flags |= B_ERROR;
|
||||
@ -760,7 +813,7 @@ nfs_doio(bp, cr, p)
|
||||
uiop->uio_rw = UIO_READ;
|
||||
switch (vp->v_type) {
|
||||
case VREG:
|
||||
uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
|
||||
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
|
||||
nfsstats.read_bios++;
|
||||
error = nfs_readrpc(vp, uiop, cr);
|
||||
if (!error) {
|
||||
@ -773,7 +826,7 @@ nfs_doio(bp, cr, p)
|
||||
* Just zero fill the rest of the valid area.
|
||||
*/
|
||||
diff = bp->b_bcount - uiop->uio_resid;
|
||||
len = np->n_size - (bp->b_blkno * DEV_BSIZE
|
||||
len = np->n_size - (((u_quad_t)bp->b_blkno) * DEV_BSIZE
|
||||
+ diff);
|
||||
if (len > 0) {
|
||||
len = min(len, uiop->uio_resid);
|
||||
@ -786,31 +839,34 @@ nfs_doio(bp, cr, p)
|
||||
}
|
||||
if (p && (vp->v_flag & VTEXT) &&
|
||||
(((nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
NQNFS_CKINVALID(vp, np, NQL_READ) &&
|
||||
NQNFS_CKINVALID(vp, np, ND_READ) &&
|
||||
np->n_lrev != np->n_brev) ||
|
||||
(!(nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
np->n_mtime != np->n_vattr.va_mtime.ts_sec))) {
|
||||
uprintf("Process killed due to text file modification\n");
|
||||
psignal(p, SIGKILL);
|
||||
#ifdef __NetBSD__
|
||||
p->p_holdcnt++;
|
||||
#else
|
||||
p->p_flag |= P_NOSWAP;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case VLNK:
|
||||
uiop->uio_offset = 0;
|
||||
uiop->uio_offset = (off_t)0;
|
||||
nfsstats.readlink_bios++;
|
||||
error = nfs_readlinkrpc(vp, uiop, cr);
|
||||
break;
|
||||
case VDIR:
|
||||
uiop->uio_offset = bp->b_lblkno;
|
||||
nfsstats.readdir_bios++;
|
||||
if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS)
|
||||
error = nfs_readdirlookrpc(vp, uiop, cr);
|
||||
else
|
||||
error = nfs_readdirrpc(vp, uiop, cr);
|
||||
/*
|
||||
* Save offset cookie in b_blkno.
|
||||
*/
|
||||
bp->b_blkno = uiop->uio_offset;
|
||||
uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * NFS_DIRBLKSIZ;
|
||||
if (nmp->nm_flag & NFSMNT_RDIRPLUS) {
|
||||
error = nfs_readdirplusrpc(vp, uiop, cr);
|
||||
if (error == NFSERR_NOTSUPP)
|
||||
nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
|
||||
}
|
||||
if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0)
|
||||
error = nfs_readdirrpc(vp, uiop, cr);
|
||||
break;
|
||||
default:
|
||||
printf("nfs_doio: type %x unexpected\n",vp->v_type);
|
||||
@ -821,32 +877,44 @@ nfs_doio(bp, cr, p)
|
||||
bp->b_error = error;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (((bp->b_blkno * DEV_BSIZE) + bp->b_dirtyend) > np->n_size)
|
||||
bp->b_dirtyend = np->n_size - (bp->b_blkno * DEV_BSIZE);
|
||||
|
||||
if (bp->b_dirtyend > bp->b_dirtyoff) {
|
||||
io.iov_len = uiop->uio_resid = bp->b_dirtyend
|
||||
- bp->b_dirtyoff;
|
||||
uiop->uio_offset = (bp->b_blkno * DEV_BSIZE)
|
||||
+ bp->b_dirtyoff;
|
||||
- bp->b_dirtyoff;
|
||||
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE
|
||||
+ bp->b_dirtyoff;
|
||||
io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;
|
||||
uiop->uio_rw = UIO_WRITE;
|
||||
nfsstats.write_bios++;
|
||||
if (bp->b_flags & B_APPENDWRITE)
|
||||
error = nfs_writerpc(vp, uiop, cr, IO_APPEND);
|
||||
if ((bp->b_flags & (B_ASYNC | B_NEEDCOMMIT | B_NOCACHE)) == B_ASYNC)
|
||||
iomode = NFSV3WRITE_UNSTABLE;
|
||||
else
|
||||
error = nfs_writerpc(vp, uiop, cr, 0);
|
||||
bp->b_flags &= ~(B_WRITEINPROG | B_APPENDWRITE);
|
||||
iomode = NFSV3WRITE_FILESYNC;
|
||||
bp->b_flags |= B_WRITEINPROG;
|
||||
error = nfs_writerpc(vp, uiop, cr, &iomode, &must_commit);
|
||||
if (!error && iomode == NFSV3WRITE_UNSTABLE)
|
||||
bp->b_flags |= B_NEEDCOMMIT;
|
||||
else
|
||||
bp->b_flags &= ~B_NEEDCOMMIT;
|
||||
bp->b_flags &= ~B_WRITEINPROG;
|
||||
|
||||
/*
|
||||
* For an interrupted write, the buffer is still valid and the
|
||||
* write hasn't been pushed to the server yet, so we can't set
|
||||
* B_ERROR and report the interruption by setting B_EINTR. For
|
||||
* the B_ASYNC case, B_EINTR is not relevant, so the rpc attempt
|
||||
* is essentially a noop.
|
||||
*/
|
||||
if (error == EINTR) {
|
||||
/*
|
||||
* For an interrupted write, the buffer is still valid
|
||||
* and the write hasn't been pushed to the server yet,
|
||||
* so we can't set B_ERROR and report the interruption
|
||||
* by setting B_EINTR. For the B_ASYNC case, B_EINTR
|
||||
* is not relevant, so the rpc attempt is essentially
|
||||
* a noop. For the case of a V3 write rpc not being
|
||||
* committed to stable storage, the block is still
|
||||
* dirty and requires either a commit rpc or another
|
||||
* write rpc with iomode == NFSV3WRITE_FILESYNC before
|
||||
* the block is reused. This is indicated by setting
|
||||
* the B_DELWRI and B_NEEDCOMMIT flags.
|
||||
*/
|
||||
if (error == EINTR
|
||||
|| (!error && (bp->b_flags & B_NEEDCOMMIT))) {
|
||||
bp->b_flags &= ~(B_INVAL|B_NOCACHE);
|
||||
bp->b_flags |= B_DELWRI;
|
||||
|
||||
@ -874,6 +942,8 @@ nfs_doio(bp, cr, p)
|
||||
}
|
||||
}
|
||||
bp->b_resid = uiop->uio_resid;
|
||||
if (must_commit)
|
||||
nfs_clearcommit(vp->v_mount);
|
||||
biodone(bp);
|
||||
return (error);
|
||||
}
|
||||
|
1037
sys/nfs/nfs_common.c
1037
sys/nfs/nfs_common.c
File diff suppressed because it is too large
Load Diff
@ -34,12 +34,13 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsm_subs.h 8.1 (Berkeley) 6/16/93
|
||||
* $Id: nfsm_subs.h,v 1.5 1994/10/17 17:47:42 phk Exp $
|
||||
* $Id: nfsm_subs.h,v 1.6 1995/05/30 08:12:51 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSM_SUBS_H_
|
||||
#define _NFS_NFSM_SUBS_H_
|
||||
|
||||
|
||||
/*
|
||||
* These macros do strange and peculiar things to mbuf chains for
|
||||
* the assistance of the nfs code. To attempt to use them for any
|
||||
@ -90,49 +91,153 @@ extern struct mbuf *nfsm_reqh();
|
||||
mb->m_len += (s); \
|
||||
bpos += (s); }
|
||||
|
||||
#define nfsm_dissect(a,c,s) \
|
||||
#define nfsm_dissect(a, c, s) \
|
||||
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
|
||||
if (t1 >= (s)) { \
|
||||
(a) = (c)(dpos); \
|
||||
dpos += (s); \
|
||||
} else if (t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} else { \
|
||||
error = nfsm_disct(&md, &dpos, (s), t1, &cp2); \
|
||||
if (error) { \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} else { \
|
||||
(a) = (c)cp2; \
|
||||
} \
|
||||
(a) = (c)cp2; \
|
||||
} }
|
||||
|
||||
#define nfsm_fhtom(v) \
|
||||
nfsm_build(cp,caddr_t,NFSX_FH); \
|
||||
bcopy((caddr_t)&(VTONFS(v)->n_fh), cp, NFSX_FH)
|
||||
#define nfsm_fhtom(v, v3) \
|
||||
{ if (v3) { \
|
||||
t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \
|
||||
if (t2 <= M_TRAILINGSPACE(mb)) { \
|
||||
nfsm_build(tl, u_long *, t2); \
|
||||
*tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \
|
||||
*(tl + ((t2>>2) - 2)) = 0; \
|
||||
bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \
|
||||
VTONFS(v)->n_fhsize); \
|
||||
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, \
|
||||
(caddr_t)VTONFS(v)->n_fhp, VTONFS(v)->n_fhsize)) { \
|
||||
error = t2; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
} else { \
|
||||
nfsm_build(cp, caddr_t, NFSX_V2FH); \
|
||||
bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \
|
||||
} }
|
||||
|
||||
#define nfsm_srvfhtom(f) \
|
||||
nfsm_build(cp,caddr_t,NFSX_FH); \
|
||||
bcopy((caddr_t)(f), cp, NFSX_FH)
|
||||
#define nfsm_srvfhtom(f, v3) \
|
||||
{ if (v3) { \
|
||||
nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FH); \
|
||||
*tl++ = txdr_unsigned(NFSX_V3FH); \
|
||||
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
|
||||
} else { \
|
||||
nfsm_build(cp, caddr_t, NFSX_V2FH); \
|
||||
bcopy((caddr_t)(f), cp, NFSX_V2FH); \
|
||||
} }
|
||||
|
||||
#define nfsm_mtofh(d,v) \
|
||||
{ struct nfsnode *np; nfsv2fh_t *fhp; \
|
||||
nfsm_dissect(fhp,nfsv2fh_t *,NFSX_FH); \
|
||||
error = nfs_nget((d)->v_mount, fhp, &np); \
|
||||
if (error) { \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = NFSTOV(np); \
|
||||
nfsm_loadattr(v, (struct vattr *)0); \
|
||||
#define nfsm_srvpostop_fh(f) \
|
||||
{ nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \
|
||||
*tl++ = nfs_true; \
|
||||
*tl++ = txdr_unsigned(NFSX_V3FH); \
|
||||
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
|
||||
}
|
||||
|
||||
#define nfsm_loadattr(v,a) \
|
||||
{ struct vnode *tvp = (v); \
|
||||
error = nfs_loadattrcache(&tvp, &md, &dpos, (a)); \
|
||||
if (error) { \
|
||||
#define nfsm_mtofh(d, v, v3, f) \
|
||||
{ struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \
|
||||
if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(f) = fxdr_unsigned(int, *tl); \
|
||||
} else \
|
||||
(f) = 1; \
|
||||
if (f) { \
|
||||
nfsm_getfh(ttfhp, ttfhsize, (v3)); \
|
||||
if (t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \
|
||||
&ttnp)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = NFSTOV(ttnp); \
|
||||
} \
|
||||
if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (f) \
|
||||
(f) = fxdr_unsigned(int, *tl); \
|
||||
else if (fxdr_unsigned(int, *tl)) \
|
||||
nfsm_adv(NFSX_V3FATTR); \
|
||||
} \
|
||||
if (f) \
|
||||
nfsm_loadattr((v), (struct vattr *)0); \
|
||||
}
|
||||
|
||||
#define nfsm_getfh(f, s, v3) \
|
||||
{ if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \
|
||||
(s) > NFSX_V3FHMAX) { \
|
||||
m_freem(mrep); \
|
||||
error = EBADRPC; \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
} else \
|
||||
(s) = NFSX_V2FH; \
|
||||
nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); }
|
||||
|
||||
#define nfsm_loadattr(v, a) \
|
||||
{ struct vnode *ttvp = (v); \
|
||||
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a))) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = tvp; }
|
||||
(v) = ttvp; }
|
||||
|
||||
#define nfsm_postop_attr(v, f) \
|
||||
{ struct vnode *ttvp = (v); \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if ((f) = fxdr_unsigned(int, *tl)) { \
|
||||
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
|
||||
(struct vattr *)0)) { \
|
||||
error = t1; \
|
||||
(f) = 0; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = ttvp; \
|
||||
} }
|
||||
|
||||
/* Used as (f) for nfsm_wcc_data() */
|
||||
#define NFSV3_WCCRATTR 0
|
||||
#define NFSV3_WCCCHK 1
|
||||
|
||||
#define nfsm_wcc_data(v, f) \
|
||||
{ int ttattrf, ttretf = 0; \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, 6 * NFSX_UNSIGNED); \
|
||||
if (f) \
|
||||
ttretf = (VTONFS(v)->n_mtime == \
|
||||
fxdr_unsigned(u_long, *(tl + 2))); \
|
||||
} \
|
||||
nfsm_postop_attr((v), ttattrf); \
|
||||
if (f) { \
|
||||
(f) = ttretf; \
|
||||
} else { \
|
||||
(f) = ttattrf; \
|
||||
} }
|
||||
|
||||
#define nfsm_v3sattr(s, a, u, g) \
|
||||
{ (s)->sa_modetrue = nfs_true; \
|
||||
(s)->sa_mode = vtonfsv3_mode((a)->va_mode); \
|
||||
(s)->sa_uidtrue = nfs_true; \
|
||||
(s)->sa_uid = txdr_unsigned(u); \
|
||||
(s)->sa_gidtrue = nfs_true; \
|
||||
(s)->sa_gid = txdr_unsigned(g); \
|
||||
(s)->sa_sizefalse = nfs_false; \
|
||||
(s)->sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
|
||||
txdr_nfsv3time(&(a)->va_atime, &(s)->sa_atime); \
|
||||
(s)->sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
|
||||
txdr_nfsv3time(&(a)->va_mtime, &(s)->sa_mtime); \
|
||||
}
|
||||
|
||||
#define nfsm_strsiz(s,m) \
|
||||
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
|
||||
@ -149,16 +254,27 @@ extern struct mbuf *nfsm_reqh();
|
||||
nfsm_reply(0); \
|
||||
} }
|
||||
|
||||
#define nfsm_srvnamesiz(s) \
|
||||
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
|
||||
if (((s) = fxdr_unsigned(long,*tl)) > NFS_MAXNAMLEN) \
|
||||
error = NFSERR_NAMETOL; \
|
||||
if ((s) <= 0) \
|
||||
error = EBADRPC; \
|
||||
if (error) \
|
||||
nfsm_reply(0); \
|
||||
}
|
||||
|
||||
#define nfsm_mtouio(p,s) \
|
||||
if ((s) > 0 && \
|
||||
(error = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
|
||||
(t1 = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_uiotom(p,s) \
|
||||
error = nfsm_uiotombuf((p),&mb,(s),&bpos); \
|
||||
if (error) { \
|
||||
if (t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) { \
|
||||
error = t1; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
@ -172,10 +288,13 @@ extern struct mbuf *nfsm_reqh();
|
||||
#define nfsm_rndup(a) (((a)+3)&(~0x3))
|
||||
|
||||
#define nfsm_request(v, t, p, c) \
|
||||
error = nfs_request((v), mreq, (t), (p), \
|
||||
(c), &mrep, &md, &dpos); \
|
||||
if (error) \
|
||||
goto nfsmout
|
||||
if (error = nfs_request((v), mreq, (t), (p), \
|
||||
(c), &mrep, &md, &dpos)) { \
|
||||
if (error & NFSERR_RETERR) \
|
||||
error &= ~NFSERR_RETERR; \
|
||||
else \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_strtom(a,s,m) \
|
||||
if ((s) > (m)) { \
|
||||
@ -189,12 +308,10 @@ extern struct mbuf *nfsm_reqh();
|
||||
*tl++ = txdr_unsigned(s); \
|
||||
*(tl+((t2>>2)-2)) = 0; \
|
||||
bcopy((caddr_t)(a), (caddr_t)tl, (s)); \
|
||||
} else { \
|
||||
error = nfsm_strtmbuf(&mb, &bpos, (a), (s)); \
|
||||
if (error) { \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) { \
|
||||
error = t2; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_srvdone \
|
||||
@ -204,33 +321,53 @@ extern struct mbuf *nfsm_reqh();
|
||||
#define nfsm_reply(s) \
|
||||
{ \
|
||||
nfsd->nd_repstat = error; \
|
||||
if (error) \
|
||||
(void) nfs_rephead(0, nfsd, error, cache, &frev, \
|
||||
if (error && !(nfsd->nd_flag & ND_NFSV3)) \
|
||||
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
|
||||
mrq, &mb, &bpos); \
|
||||
else \
|
||||
(void) nfs_rephead((s), nfsd, error, cache, &frev, \
|
||||
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
|
||||
mrq, &mb, &bpos); \
|
||||
m_freem(mrep); \
|
||||
mreq = *mrq; \
|
||||
if (error) \
|
||||
if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
|
||||
error == EBADRPC)) \
|
||||
return(0); \
|
||||
}
|
||||
|
||||
#define nfsm_adv(s) \
|
||||
t1 = mtod(md, caddr_t)+md->m_len-dpos; \
|
||||
if (t1 >= (s)) { \
|
||||
dpos += (s); \
|
||||
} else { \
|
||||
error = nfs_adv(&md, &dpos, (s), t1); \
|
||||
if (error) { \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
#define nfsm_writereply(s, v3) \
|
||||
{ \
|
||||
nfsd->nd_repstat = error; \
|
||||
if (error && !(v3)) \
|
||||
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
|
||||
&mreq, &mb, &bpos); \
|
||||
else \
|
||||
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
|
||||
&mreq, &mb, &bpos); \
|
||||
}
|
||||
|
||||
#define nfsm_adv(s) \
|
||||
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
|
||||
if (t1 >= (s)) { \
|
||||
dpos += (s); \
|
||||
} else if (t1 = nfs_adv(&md, &dpos, (s), t1)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} }
|
||||
|
||||
#define nfsm_srvmtofh(f) \
|
||||
nfsm_dissect(tl, u_long *, NFSX_FH); \
|
||||
bcopy((caddr_t)tl, (caddr_t)f, NFSX_FH)
|
||||
{ if (nfsd->nd_flag & ND_NFSV3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \
|
||||
error = EBADRPC; \
|
||||
nfsm_reply(0); \
|
||||
} \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
|
||||
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
|
||||
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
|
||||
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
|
||||
}
|
||||
|
||||
#define nfsm_clget \
|
||||
if (bp >= be) { \
|
||||
@ -246,41 +383,57 @@ extern struct mbuf *nfsm_reqh();
|
||||
} \
|
||||
tl = (u_long *)bp
|
||||
|
||||
#define nfsm_srvfillattr \
|
||||
fp->fa_type = vtonfs_type(vap->va_type); \
|
||||
fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); \
|
||||
fp->fa_nlink = txdr_unsigned(vap->va_nlink); \
|
||||
fp->fa_uid = txdr_unsigned(vap->va_uid); \
|
||||
fp->fa_gid = txdr_unsigned(vap->va_gid); \
|
||||
if (nfsd->nd_nqlflag == NQL_NOVAL) { \
|
||||
fp->fa_nfsblocksize = txdr_unsigned(vap->va_blocksize); \
|
||||
if (vap->va_type == VFIFO) \
|
||||
fp->fa_nfsrdev = 0xffffffff; \
|
||||
else \
|
||||
fp->fa_nfsrdev = txdr_unsigned(vap->va_rdev); \
|
||||
fp->fa_nfsfsid = txdr_unsigned(vap->va_fsid); \
|
||||
fp->fa_nfsfileid = txdr_unsigned(vap->va_fileid); \
|
||||
fp->fa_nfssize = txdr_unsigned(vap->va_size); \
|
||||
fp->fa_nfsblocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); \
|
||||
txdr_nfstime(&vap->va_atime, &fp->fa_nfsatime); \
|
||||
txdr_nfstime(&vap->va_mtime, &fp->fa_nfsmtime); \
|
||||
txdr_nfstime(&vap->va_ctime, &fp->fa_nfsctime); \
|
||||
} else { \
|
||||
fp->fa_nqblocksize = txdr_unsigned(vap->va_blocksize); \
|
||||
if (vap->va_type == VFIFO) \
|
||||
fp->fa_nqrdev = 0xffffffff; \
|
||||
else \
|
||||
fp->fa_nqrdev = txdr_unsigned(vap->va_rdev); \
|
||||
fp->fa_nqfsid = txdr_unsigned(vap->va_fsid); \
|
||||
fp->fa_nqfileid = txdr_unsigned(vap->va_fileid); \
|
||||
txdr_hyper(&vap->va_size, &fp->fa_nqsize); \
|
||||
txdr_hyper(&vap->va_bytes, &fp->fa_nqbytes); \
|
||||
txdr_nqtime(&vap->va_atime, &fp->fa_nqatime); \
|
||||
txdr_nqtime(&vap->va_mtime, &fp->fa_nqmtime); \
|
||||
txdr_nqtime(&vap->va_ctime, &fp->fa_nqctime); \
|
||||
fp->fa_nqflags = txdr_unsigned(vap->va_flags); \
|
||||
fp->fa_nqgen = txdr_unsigned(vap->va_gen); \
|
||||
txdr_hyper(&vap->va_filerev, &fp->fa_nqfilerev); \
|
||||
}
|
||||
#define nfsm_srvfillattr(a, f) \
|
||||
nfsm_srvfattr(nfsd, (a), (f))
|
||||
|
||||
#define nfsm_srvwcc_data(br, b, ar, a) \
|
||||
nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos)
|
||||
|
||||
#define nfsm_srvpostop_attr(r, a) \
|
||||
nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos)
|
||||
|
||||
#define nfsm_srvsattr(a) \
|
||||
{ nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_mode = nfstov_mode(*tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_uid = fxdr_unsigned(uid_t, *tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_gid = fxdr_unsigned(gid_t, *tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_hyper(tl, &(a)->va_size); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
switch (fxdr_unsigned(int, *tl)) { \
|
||||
case NFSV3SATTRTIME_TOCLIENT: \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_nfsv3time(tl, &(a)->va_atime); \
|
||||
break; \
|
||||
case NFSV3SATTRTIME_TOSERVER: \
|
||||
(a)->va_atime.ts_sec = time.tv_sec; \
|
||||
(a)->va_atime.ts_nsec = time.tv_usec * 1000; \
|
||||
break; \
|
||||
}; \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
switch (fxdr_unsigned(int, *tl)) { \
|
||||
case NFSV3SATTRTIME_TOCLIENT: \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_nfsv3time(tl, &(a)->va_mtime); \
|
||||
break; \
|
||||
case NFSV3SATTRTIME_TOSERVER: \
|
||||
(a)->va_mtime.ts_sec = time.tv_sec; \
|
||||
(a)->va_mtime.ts_nsec = time.tv_usec * 1000; \
|
||||
break; \
|
||||
}; }
|
||||
|
||||
#endif
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_node.c 8.2 (Berkeley) 12/30/93
|
||||
* $Id: nfs_node.c,v 1.7 1994/10/17 17:47:33 phk Exp $
|
||||
* $Id: nfs_node.c,v 1.8 1995/03/16 18:15:36 bde Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -47,14 +47,12 @@
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/nqnfs.h>
|
||||
|
||||
#define NFSNOHASH(fhsum) \
|
||||
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
|
||||
LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl;
|
||||
u_long nfsnodehash;
|
||||
|
||||
@ -79,19 +77,20 @@ nfs_nhinit()
|
||||
/*
|
||||
* Compute an entry in the NFS hash table structure
|
||||
*/
|
||||
struct nfsnodehashhead *
|
||||
nfs_hash(fhp)
|
||||
register nfsv2fh_t *fhp;
|
||||
u_long
|
||||
nfs_hash(fhp, fhsize)
|
||||
register nfsfh_t *fhp;
|
||||
int fhsize;
|
||||
{
|
||||
register u_char *fhpp;
|
||||
register u_long fhsum;
|
||||
int i;
|
||||
register int i;
|
||||
|
||||
fhpp = &fhp->fh_bytes[0];
|
||||
fhsum = 0;
|
||||
for (i = 0; i < NFSX_FH; i++)
|
||||
for (i = 0; i < fhsize; i++)
|
||||
fhsum += *fhpp++;
|
||||
return (NFSNOHASH(fhsum));
|
||||
return (fhsum);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -101,9 +100,10 @@ nfs_hash(fhp)
|
||||
* nfsnode structure is returned.
|
||||
*/
|
||||
int
|
||||
nfs_nget(mntp, fhp, npp)
|
||||
nfs_nget(mntp, fhp, fhsize, npp)
|
||||
struct mount *mntp;
|
||||
register nfsv2fh_t *fhp;
|
||||
register nfsfh_t *fhp;
|
||||
int fhsize;
|
||||
struct nfsnode **npp;
|
||||
{
|
||||
register struct nfsnode *np;
|
||||
@ -112,11 +112,11 @@ nfs_nget(mntp, fhp, npp)
|
||||
struct vnode *nvp;
|
||||
int error;
|
||||
|
||||
nhpp = nfs_hash(fhp);
|
||||
nhpp = NFSNOHASH(nfs_hash(fhp, fhsize));
|
||||
loop:
|
||||
for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) {
|
||||
if (mntp != NFSTOV(np)->v_mount ||
|
||||
bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH))
|
||||
if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
|
||||
bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize))
|
||||
continue;
|
||||
vp = NFSTOV(np);
|
||||
if (vget(vp, 1))
|
||||
@ -131,27 +131,26 @@ nfs_nget(mntp, fhp, npp)
|
||||
}
|
||||
vp = nvp;
|
||||
MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK);
|
||||
bzero((caddr_t)np, sizeof *np);
|
||||
vp->v_data = np;
|
||||
np->n_vnode = vp;
|
||||
/*
|
||||
* Insert the nfsnode in the hash queue for its new file handle
|
||||
*/
|
||||
np->n_flag = 0;
|
||||
LIST_INSERT_HEAD(nhpp, np, n_hash);
|
||||
bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH);
|
||||
np->n_attrstamp = 0;
|
||||
np->n_direofoffset = 0;
|
||||
np->n_sillyrename = (struct sillyrename *)0;
|
||||
np->n_size = 0;
|
||||
np->n_mtime = 0;
|
||||
np->n_lockf = 0;
|
||||
if (VFSTONFS(mntp)->nm_flag & NFSMNT_NQNFS) {
|
||||
np->n_brev = 0;
|
||||
np->n_lrev = 0;
|
||||
np->n_expiry = (time_t)0;
|
||||
np->n_timer.cqe_next = (struct nfsnode *)0;
|
||||
}
|
||||
if (fhsize > NFS_SMALLFH) {
|
||||
MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK);
|
||||
} else
|
||||
np->n_fhp = &np->n_fh;
|
||||
bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize);
|
||||
np->n_fhsize = fhsize;
|
||||
*npp = np;
|
||||
|
||||
/*
|
||||
* Lock the new nfsnode.
|
||||
*/
|
||||
VOP_LOCK(vp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -168,7 +167,10 @@ nfs_inactive(ap)
|
||||
np = VTONFS(ap->a_vp);
|
||||
if (prtactive && ap->a_vp->v_usecount != 0)
|
||||
vprint("nfs_inactive: pushing active", ap->a_vp);
|
||||
sp = np->n_sillyrename;
|
||||
if (ap->a_vp->v_type != VDIR)
|
||||
sp = np->n_sillyrename;
|
||||
else
|
||||
sp = (struct sillyrename *)0;
|
||||
np->n_sillyrename = (struct sillyrename *)0;
|
||||
if (sp) {
|
||||
/*
|
||||
@ -178,9 +180,7 @@ nfs_inactive(ap)
|
||||
nfs_removeit(sp);
|
||||
crfree(sp->s_cred);
|
||||
vrele(sp->s_dvp);
|
||||
#ifdef SILLYSEPARATE
|
||||
free((caddr_t)sp, M_NFSREQ);
|
||||
#endif
|
||||
FREE((caddr_t)sp, M_NFSREQ);
|
||||
}
|
||||
np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
|
||||
NQNFSNONCACHE | NQNFSWRITE);
|
||||
@ -199,6 +199,7 @@ nfs_reclaim(ap)
|
||||
register struct vnode *vp = ap->a_vp;
|
||||
register struct nfsnode *np = VTONFS(vp);
|
||||
register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||
register struct nfsdmap *dp, *dp2;
|
||||
|
||||
if (prtactive && vp->v_usecount != 0)
|
||||
vprint("nfs_reclaim: pushing active", vp);
|
||||
@ -211,6 +212,24 @@ nfs_reclaim(ap)
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) {
|
||||
CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free up any directory cookie structures and
|
||||
* large file handle structures that might be associated with
|
||||
* this nfs node.
|
||||
*/
|
||||
if (vp->v_type == VDIR) {
|
||||
dp = np->n_cookies.lh_first;
|
||||
while (dp) {
|
||||
dp2 = dp;
|
||||
dp = dp->ndm_list.le_next;
|
||||
FREE((caddr_t)dp2, M_NFSDIROFF);
|
||||
}
|
||||
}
|
||||
if (np->n_fhsize > NFS_SMALLFH) {
|
||||
FREE((caddr_t)np->n_fhp, M_NFSBIGFH);
|
||||
}
|
||||
|
||||
cache_purge(vp);
|
||||
FREE(vp->v_data, M_NFSNODE);
|
||||
vp->v_data = (void *)0;
|
||||
@ -227,6 +246,7 @@ nfs_lock(ap)
|
||||
} */ *ap;
|
||||
{
|
||||
register struct vnode *vp = ap->a_vp;
|
||||
struct nfsnode *np = VTONFS(vp);
|
||||
|
||||
/*
|
||||
* Ugh, another place where interruptible mounts will get hung.
|
||||
@ -239,6 +259,33 @@ nfs_lock(ap)
|
||||
}
|
||||
if (vp->v_tag == VT_NON)
|
||||
return (ENOENT);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Only lock regular files. If a server crashed while we were
|
||||
* holding a directory lock, we could easily end up sleeping
|
||||
* until the server rebooted while holding a lock on the root.
|
||||
* Locks are only needed for protecting critical sections in
|
||||
* VMIO at the moment.
|
||||
* New vnodes will have type VNON but they should be locked
|
||||
* since they may become VREG. This is checked in loadattrcache
|
||||
* and unwanted locks are released there.
|
||||
*/
|
||||
if (vp->v_type == VREG || vp->v_type == VNON) {
|
||||
while (np->n_flag & NLOCKED) {
|
||||
np->n_flag |= NWANTED;
|
||||
(void) tsleep((caddr_t) np, PINOD, "nfslck2", 0);
|
||||
/*
|
||||
* If the vnode has transmuted into a VDIR while we
|
||||
* were asleep, then skip the lock.
|
||||
*/
|
||||
if (vp->v_type != VREG && vp->v_type != VNON)
|
||||
return (0);
|
||||
}
|
||||
np->n_flag |= NLOCKED;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -251,6 +298,20 @@ nfs_unlock(ap)
|
||||
struct vnode *a_vp;
|
||||
} */ *ap;
|
||||
{
|
||||
#if 0
|
||||
struct vnode* vp = ap->a_vp;
|
||||
struct nfsnode* np = VTONFS(vp);
|
||||
|
||||
if (vp->v_type == VREG || vp->v_type == VNON) {
|
||||
if (!(np->n_flag & NLOCKED))
|
||||
panic("nfs_unlock: nfsnode not locked");
|
||||
np->n_flag &= ~NLOCKED;
|
||||
if (np->n_flag & NWANTED) {
|
||||
np->n_flag &= ~NWANTED;
|
||||
wakeup((caddr_t) np);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -264,8 +325,7 @@ nfs_islocked(ap)
|
||||
struct vnode *a_vp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
return (0);
|
||||
return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_nqlease.c 8.3 (Berkeley) 1/4/94
|
||||
* $Id: nfs_nqlease.c,v 1.10 1995/02/15 03:39:58 davidg Exp $
|
||||
* $Id: nfs_nqlease.c,v 1.11 1995/05/30 08:12:36 rgrimes Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -66,7 +66,7 @@
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsm_subs.h>
|
||||
#include <nfs/xdr_subs.h>
|
||||
@ -75,7 +75,6 @@
|
||||
#include <nfs/nfsmount.h>
|
||||
|
||||
time_t nqnfsstarttime = (time_t)0;
|
||||
u_long nqnfs_prog, nqnfs_vers;
|
||||
int nqsrv_clockskew = NQ_CLOCKSKEW;
|
||||
int nqsrv_writeslack = NQ_WRITESLACK;
|
||||
int nqsrv_maxlease = NQ_MAXLEASE;
|
||||
@ -91,14 +90,13 @@ struct mbuf *nfsm_rpchead();
|
||||
*/
|
||||
int nqnfs_piggy[NFS_NPROCS] = {
|
||||
0,
|
||||
NQL_READ,
|
||||
NQL_WRITE,
|
||||
0,
|
||||
NQL_READ,
|
||||
NQL_READ,
|
||||
NQL_READ,
|
||||
ND_WRITE,
|
||||
ND_READ,
|
||||
0,
|
||||
NQL_WRITE,
|
||||
ND_READ,
|
||||
ND_READ,
|
||||
ND_WRITE,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
@ -106,24 +104,30 @@ int nqnfs_piggy[NFS_NPROCS] = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NQL_READ,
|
||||
0,
|
||||
NQL_READ,
|
||||
ND_READ,
|
||||
ND_READ,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
extern nfstype nfs_type[9];
|
||||
extern nfstype nfsv2_type[9];
|
||||
extern nfstype nfsv3_type[9];
|
||||
extern struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock;
|
||||
extern int nfsd_waiting;
|
||||
extern struct nfsstats nfsstats;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
/*
|
||||
* Get or check for a lease for "vp", based on NQL_CHECK flag.
|
||||
* Get or check for a lease for "vp", based on ND_CHECK flag.
|
||||
* The rules are as follows:
|
||||
* - if a current non-caching lease, reply non-caching
|
||||
* - if a current lease for same host only, extend lease
|
||||
@ -146,11 +150,12 @@ extern int nfsd_waiting;
|
||||
* queue yet. (Ditto for the splsoftclock() and splx(s) calls)
|
||||
*/
|
||||
int
|
||||
nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
|
||||
nqsrv_getlease(vp, duration, flags, slp, procp, nam, cachablep, frev, cred)
|
||||
struct vnode *vp;
|
||||
u_long *duration;
|
||||
int flags;
|
||||
struct nfsd *nd;
|
||||
struct nfssvc_sock *slp;
|
||||
struct proc *procp;
|
||||
struct mbuf *nam;
|
||||
int *cachablep;
|
||||
u_quad_t *frev;
|
||||
@ -169,13 +174,13 @@ nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
|
||||
return (0);
|
||||
if (*duration > nqsrv_maxlease)
|
||||
*duration = nqsrv_maxlease;
|
||||
error = VOP_GETATTR(vp, &vattr, cred, nd->nd_procp);
|
||||
error = VOP_GETATTR(vp, &vattr, cred, procp);
|
||||
if (error)
|
||||
return (error);
|
||||
*frev = vattr.va_filerev;
|
||||
s = splsoftclock();
|
||||
tlp = vp->v_lease;
|
||||
if ((flags & NQL_CHECK) == 0)
|
||||
if ((flags & ND_CHECK) == 0)
|
||||
nfsstats.srvnqnfs_getleases++;
|
||||
if (tlp == (struct nqlease *)0) {
|
||||
|
||||
@ -205,12 +210,12 @@ nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
|
||||
if (lp) {
|
||||
if ((lp->lc_flag & LC_NONCACHABLE) ||
|
||||
(lp->lc_morehosts == (struct nqm *)0 &&
|
||||
nqsrv_cmpnam(nd->nd_slp, nam, &lp->lc_host)))
|
||||
nqsrv_cmpnam(slp, nam, &lp->lc_host)))
|
||||
goto doreply;
|
||||
if ((flags & NQL_READ) && (lp->lc_flag & LC_WRITE) == 0) {
|
||||
if (flags & NQL_CHECK)
|
||||
if ((flags & ND_READ) && (lp->lc_flag & LC_WRITE) == 0) {
|
||||
if (flags & ND_CHECK)
|
||||
goto doreply;
|
||||
if (nqsrv_cmpnam(nd->nd_slp, nam, &lp->lc_host))
|
||||
if (nqsrv_cmpnam(slp, nam, &lp->lc_host))
|
||||
goto doreply;
|
||||
i = 0;
|
||||
if (lp->lc_morehosts) {
|
||||
@ -222,7 +227,7 @@ nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
|
||||
ok = 0;
|
||||
}
|
||||
while (ok && (lph->lph_flag & LC_VALID)) {
|
||||
if (nqsrv_cmpnam(nd->nd_slp, nam, lph))
|
||||
if (nqsrv_cmpnam(slp, nam, lph))
|
||||
goto doreply;
|
||||
if (++i == LC_MOREHOSTSIZ) {
|
||||
i = 0;
|
||||
@ -242,12 +247,12 @@ nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
|
||||
bzero((caddr_t)*lphp, sizeof (struct nqm));
|
||||
lph = (*lphp)->lpm_hosts;
|
||||
}
|
||||
nqsrv_addhost(lph, nd->nd_slp, nam);
|
||||
nqsrv_addhost(lph, slp, nam);
|
||||
nqsrv_unlocklease(lp);
|
||||
} else {
|
||||
lp->lc_flag |= LC_NONCACHABLE;
|
||||
nqsrv_locklease(lp);
|
||||
nqsrv_send_eviction(vp, lp, nd->nd_slp, nam, cred);
|
||||
nqsrv_send_eviction(vp, lp, slp, nam, cred);
|
||||
nqsrv_waitfor_expiry(lp);
|
||||
nqsrv_unlocklease(lp);
|
||||
}
|
||||
@ -255,20 +260,20 @@ nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
|
||||
/*
|
||||
* Update the lease and return
|
||||
*/
|
||||
if ((flags & NQL_CHECK) == 0)
|
||||
if ((flags & ND_CHECK) == 0)
|
||||
nqsrv_instimeq(lp, *duration);
|
||||
if (lp->lc_flag & LC_NONCACHABLE)
|
||||
*cachablep = 0;
|
||||
else {
|
||||
*cachablep = 1;
|
||||
if (flags & NQL_WRITE)
|
||||
if (flags & ND_WRITE)
|
||||
lp->lc_flag |= LC_WRITTEN;
|
||||
}
|
||||
splx(s);
|
||||
return (0);
|
||||
}
|
||||
splx(s);
|
||||
if (flags & NQL_CHECK)
|
||||
if (flags & ND_CHECK)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
@ -285,9 +290,9 @@ nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
|
||||
}
|
||||
MALLOC(lp, struct nqlease *, sizeof (struct nqlease), M_NQLEASE, M_WAITOK);
|
||||
bzero((caddr_t)lp, sizeof (struct nqlease));
|
||||
if (flags & NQL_WRITE)
|
||||
if (flags & ND_WRITE)
|
||||
lp->lc_flag |= (LC_WRITE | LC_WRITTEN);
|
||||
nqsrv_addhost(&lp->lc_host, nd->nd_slp, nam);
|
||||
nqsrv_addhost(&lp->lc_host, slp, nam);
|
||||
lp->lc_vp = vp;
|
||||
lp->lc_fsid = fh.fh_fsid;
|
||||
bcopy(fh.fh_fid.fid_data, lp->lc_fiddata,
|
||||
@ -308,9 +313,12 @@ nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
|
||||
/*
|
||||
* Local lease check for server syscalls.
|
||||
* Just set up args and let nqsrv_getlease() do the rest.
|
||||
* nqnfs_vop_lease_check() is the VOP_LEASE() form of the same routine.
|
||||
* Ifdef'd code in nfsnode.h renames these routines to whatever a particular
|
||||
* OS needs.
|
||||
*/
|
||||
void
|
||||
nfs_lease_check(vp, p, cred, flag)
|
||||
nqnfs_lease_check(vp, p, cred, flag)
|
||||
struct vnode *vp;
|
||||
struct proc *p;
|
||||
struct ucred *cred;
|
||||
@ -318,15 +326,32 @@ nfs_lease_check(vp, p, cred, flag)
|
||||
{
|
||||
u_long duration = 0;
|
||||
int cache;
|
||||
struct nfsd nfsd;
|
||||
u_quad_t frev;
|
||||
|
||||
nfsd.nd_slp = NQLOCALSLP;
|
||||
nfsd.nd_procp = p;
|
||||
(void) nqsrv_getlease(vp, &duration, NQL_CHECK | flag, &nfsd,
|
||||
(struct mbuf *)0, &cache, &frev, cred);
|
||||
(void) nqsrv_getlease(vp, &duration, ND_CHECK | flag, NQLOCALSLP,
|
||||
p, (struct mbuf *)0, &cache, &frev, cred);
|
||||
}
|
||||
|
||||
#ifdef HAS_VOPLEASE
|
||||
int
|
||||
nqnfs_vop_lease_check(ap)
|
||||
struct vop_lease_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct proc *a_p;
|
||||
struct ucred *a_cred;
|
||||
int a_flag;
|
||||
} */ *ap;
|
||||
{
|
||||
u_long duration = 0;
|
||||
int cache;
|
||||
u_quad_t frev;
|
||||
|
||||
(void) nqsrv_getlease(ap->a_vp, &duration, ND_CHECK | ap->a_flag,
|
||||
NQLOCALSLP, ap->a_p, (struct mbuf *)0, &cache, &frev, ap->a_cred);
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Add a host to an nqhost structure for a lease.
|
||||
*/
|
||||
@ -486,9 +511,9 @@ nqsrv_send_eviction(vp, lp, slp, nam, cred)
|
||||
else
|
||||
solockp = (int *)0;
|
||||
nfsm_reqhead((struct vnode *)0, NQNFSPROC_EVICTED,
|
||||
NFSX_FH);
|
||||
nfsm_build(cp, caddr_t, NFSX_FH);
|
||||
bzero(cp, NFSX_FH);
|
||||
NFSX_V3FH);
|
||||
nfsm_build(cp, caddr_t, NFSX_V3FH);
|
||||
bzero(cp, NFSX_V3FH);
|
||||
fhp = (fhandle_t *)cp;
|
||||
fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
|
||||
VFS_VPTOFH(vp, &fhp->fh_fid);
|
||||
@ -502,8 +527,9 @@ nqsrv_send_eviction(vp, lp, slp, nam, cred)
|
||||
printf("mbuf siz=%d\n",siz);
|
||||
panic("Bad nfs svc reply");
|
||||
}
|
||||
m = nfsm_rpchead(cred, TRUE, NQNFSPROC_EVICTED,
|
||||
RPCAUTH_UNIX, 5*NFSX_UNSIGNED, (char *)0,
|
||||
m = nfsm_rpchead(cred, (NFSMNT_NFSV3 | NFSMNT_NQNFS),
|
||||
NQNFSPROC_EVICTED,
|
||||
RPCAUTH_UNIX, 5 * NFSX_UNSIGNED, (char *)0,
|
||||
mreq, siz, &mheadend, &xid);
|
||||
/*
|
||||
* For stream protocols, prepend a Sun RPC
|
||||
@ -677,18 +703,21 @@ nqnfs_serverd()
|
||||
* do the real work.
|
||||
*/
|
||||
int
|
||||
nqnfsrv_getlease(nfsd, mrep, md, dpos, cred, nam, mrq)
|
||||
struct nfsd *nfsd;
|
||||
struct mbuf *mrep, *md;
|
||||
caddr_t dpos;
|
||||
struct ucred *cred;
|
||||
struct mbuf *nam, **mrq;
|
||||
nqnfsrv_getlease(nfsd, slp, procp, mrq)
|
||||
struct nfsrv_descript *nfsd;
|
||||
struct nfssvc_sock *slp;
|
||||
struct proc *procp;
|
||||
struct mbuf **mrq;
|
||||
{
|
||||
register struct nfsv2_fattr *fp;
|
||||
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
|
||||
struct mbuf *nam = nfsd->nd_nam;
|
||||
caddr_t dpos = nfsd->nd_dpos;
|
||||
struct ucred *cred = &nfsd->nd_cr;
|
||||
register struct nfs_fattr *fp;
|
||||
struct vattr va;
|
||||
register struct vattr *vap = &va;
|
||||
struct vnode *vp;
|
||||
nfsv2fh_t nfh;
|
||||
nfsfh_t nfh;
|
||||
fhandle_t *fhp;
|
||||
register u_long *tl;
|
||||
register long t1;
|
||||
@ -701,29 +730,29 @@ nqnfsrv_getlease(nfsd, mrep, md, dpos, cred, nam, mrq)
|
||||
|
||||
fhp = &nfh.fh_generic;
|
||||
nfsm_srvmtofh(fhp);
|
||||
nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
|
||||
flags = fxdr_unsigned(int, *tl++);
|
||||
nfsd->nd_duration = fxdr_unsigned(int, *tl);
|
||||
error = nfsrv_fhtovp(fhp,
|
||||
TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly);
|
||||
error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
|
||||
(nfsd->nd_flag & ND_KERBAUTH));
|
||||
if (error)
|
||||
nfsm_reply(0);
|
||||
if (rdonly && flags == NQL_WRITE) {
|
||||
if (rdonly && flags == ND_WRITE) {
|
||||
error = EROFS;
|
||||
nfsrv_vput(vp);
|
||||
nfsm_reply(0);
|
||||
}
|
||||
(void) nqsrv_getlease(vp, &nfsd->nd_duration, flags, nfsd,
|
||||
(void) nqsrv_getlease(vp, &nfsd->nd_duration, flags, slp, procp,
|
||||
nam, &cache, &frev, cred);
|
||||
error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
|
||||
error = VOP_GETATTR(vp, vap, cred, procp);
|
||||
nfsrv_vput(vp);
|
||||
nfsm_reply(NFSX_NQFATTR + 4*NFSX_UNSIGNED);
|
||||
nfsm_build(tl, u_long *, 4*NFSX_UNSIGNED);
|
||||
nfsm_reply(NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
|
||||
nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(cache);
|
||||
*tl++ = txdr_unsigned(nfsd->nd_duration);
|
||||
txdr_hyper(&frev, tl);
|
||||
nfsm_build(fp, struct nfsv2_fattr *, NFSX_NQFATTR);
|
||||
nfsm_srvfillattr;
|
||||
nfsm_build(fp, struct nfs_fattr *, NFSX_V3FATTR);
|
||||
nfsm_srvfillattr(vap, fp);
|
||||
nfsm_srvdone;
|
||||
}
|
||||
|
||||
@ -732,23 +761,28 @@ nqnfsrv_getlease(nfsd, mrep, md, dpos, cred, nam, mrq)
|
||||
* client. Find the entry and expire it.
|
||||
*/
|
||||
int
|
||||
nqnfsrv_vacated(nfsd, mrep, md, dpos, cred, nam, mrq)
|
||||
struct nfsd *nfsd;
|
||||
struct mbuf *mrep, *md;
|
||||
caddr_t dpos;
|
||||
struct ucred *cred;
|
||||
struct mbuf *nam, **mrq;
|
||||
nqnfsrv_vacated(nfsd, slp, procp, mrq)
|
||||
struct nfsrv_descript *nfsd;
|
||||
struct nfssvc_sock *slp;
|
||||
struct proc *procp;
|
||||
struct mbuf **mrq;
|
||||
{
|
||||
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
|
||||
struct mbuf *nam = nfsd->nd_nam;
|
||||
caddr_t dpos = nfsd->nd_dpos;
|
||||
struct ucred *cred = &nfsd->nd_cr;
|
||||
register struct nqlease *lp;
|
||||
register struct nqhost *lph;
|
||||
struct nqlease *tlp = (struct nqlease *)0;
|
||||
nfsv2fh_t nfh;
|
||||
nfsfh_t nfh;
|
||||
fhandle_t *fhp;
|
||||
register u_long *tl;
|
||||
register long t1;
|
||||
struct nqm *lphnext;
|
||||
int error = 0, i, len, ok, gotit = 0;
|
||||
char *cp2;
|
||||
struct mbuf *mreq, *mb;
|
||||
int error = 0, i, len, ok, gotit = 0, cache = 0;
|
||||
char *cp2, *bpos;
|
||||
u_quad_t frev;
|
||||
|
||||
fhp = &nfh.fh_generic;
|
||||
nfsm_srvmtofh(fhp);
|
||||
@ -774,7 +808,7 @@ nqnfsrv_vacated(nfsd, mrep, md, dpos, cred, nam, mrq)
|
||||
lphnext = lp->lc_morehosts;
|
||||
ok = 1;
|
||||
while (ok && (lph->lph_flag & LC_VALID)) {
|
||||
if (nqsrv_cmpnam(nfsd->nd_slp, nam, lph)) {
|
||||
if (nqsrv_cmpnam(slp, nam, lph)) {
|
||||
lph->lph_flag |= LC_VACATED;
|
||||
gotit++;
|
||||
break;
|
||||
@ -812,7 +846,7 @@ nqnfs_getlease(vp, rwflag, cred, p)
|
||||
{
|
||||
register u_long *tl;
|
||||
register caddr_t cp;
|
||||
register long t1;
|
||||
register long t1, t2;
|
||||
register struct nfsnode *np;
|
||||
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||
caddr_t bpos, dpos, cp2;
|
||||
@ -823,16 +857,16 @@ nqnfs_getlease(vp, rwflag, cred, p)
|
||||
u_quad_t frev;
|
||||
|
||||
nfsstats.rpccnt[NQNFSPROC_GETLEASE]++;
|
||||
mb = mreq = nfsm_reqh(vp, NQNFSPROC_GETLEASE, NFSX_FH+2*NFSX_UNSIGNED,
|
||||
mb = mreq = nfsm_reqh(vp, NQNFSPROC_GETLEASE, NFSX_V3FH+2*NFSX_UNSIGNED,
|
||||
&bpos);
|
||||
nfsm_fhtom(vp);
|
||||
nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
|
||||
nfsm_fhtom(vp, 1);
|
||||
nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(rwflag);
|
||||
*tl = txdr_unsigned(nmp->nm_leaseterm);
|
||||
reqtime = time.tv_sec;
|
||||
nfsm_request(vp, NQNFSPROC_GETLEASE, p, cred);
|
||||
np = VTONFS(vp);
|
||||
nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED);
|
||||
nfsm_dissect(tl, u_long *, 4 * NFSX_UNSIGNED);
|
||||
cachable = fxdr_unsigned(int, *tl++);
|
||||
reqtime += fxdr_unsigned(int, *tl++);
|
||||
if (reqtime > time.tv_sec) {
|
||||
@ -856,6 +890,8 @@ nqnfs_vacated(vp, cred)
|
||||
register caddr_t cp;
|
||||
register struct mbuf *m;
|
||||
register int i;
|
||||
register u_long *tl;
|
||||
register long t1, t2;
|
||||
caddr_t bpos;
|
||||
u_long xid;
|
||||
int error = 0;
|
||||
@ -865,16 +901,16 @@ nqnfs_vacated(vp, cred)
|
||||
|
||||
nmp = VFSTONFS(vp->v_mount);
|
||||
nfsstats.rpccnt[NQNFSPROC_VACATED]++;
|
||||
nfsm_reqhead(vp, NQNFSPROC_VACATED, NFSX_FH);
|
||||
nfsm_fhtom(vp);
|
||||
nfsm_reqhead(vp, NQNFSPROC_VACATED, NFSX_V3FH);
|
||||
nfsm_fhtom(vp, 1);
|
||||
m = mreq;
|
||||
i = 0;
|
||||
while (m) {
|
||||
i += m->m_len;
|
||||
m = m->m_next;
|
||||
}
|
||||
m = nfsm_rpchead(cred, TRUE, NQNFSPROC_VACATED,
|
||||
RPCAUTH_UNIX, 5*NFSX_UNSIGNED, (char *)0,
|
||||
m = nfsm_rpchead(cred, nmp->nm_flag, NQNFSPROC_VACATED,
|
||||
RPCAUTH_UNIX, 5 * NFSX_UNSIGNED, (char *)0,
|
||||
mreq, i, &mheadend, &xid);
|
||||
if (nmp->nm_sotype == SOCK_STREAM) {
|
||||
M_PREPEND(m, NFSX_UNSIGNED, M_WAIT);
|
||||
@ -888,6 +924,7 @@ nqnfs_vacated(vp, cred)
|
||||
(void) nfs_send(nmp->nm_so, nmp->nm_nam, m, &myrep);
|
||||
if (nmp->nm_soflags & PR_CONNREQUIRED)
|
||||
nfs_sndunlock(&nmp->nm_flag);
|
||||
nfsmout:
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -903,29 +940,37 @@ nqnfs_callback(nmp, mrep, md, dpos)
|
||||
register struct vnode *vp;
|
||||
register u_long *tl;
|
||||
register long t1;
|
||||
nfsv2fh_t nfh;
|
||||
nfsfh_t nfh;
|
||||
fhandle_t *fhp;
|
||||
struct nfsnode *np;
|
||||
struct nfsd nd;
|
||||
int error;
|
||||
char *cp2;
|
||||
struct nfsd tnfsd;
|
||||
struct nfssvc_sock *slp;
|
||||
struct nfsrv_descript ndesc;
|
||||
register struct nfsrv_descript *nfsd = &ndesc;
|
||||
struct mbuf **mrq = (struct mbuf **)0, *mb, *mreq;
|
||||
int error = 0, cache = 0;
|
||||
char *cp2, *bpos;
|
||||
u_quad_t frev;
|
||||
|
||||
nd.nd_mrep = mrep;
|
||||
nd.nd_md = md;
|
||||
nd.nd_dpos = dpos;
|
||||
error = nfs_getreq(&nd, FALSE);
|
||||
#ifndef nolint
|
||||
slp = NULL;
|
||||
#endif
|
||||
nfsd->nd_mrep = mrep;
|
||||
nfsd->nd_md = md;
|
||||
nfsd->nd_dpos = dpos;
|
||||
error = nfs_getreq(nfsd, &tnfsd, FALSE);
|
||||
if (error)
|
||||
return (error);
|
||||
md = nd.nd_md;
|
||||
dpos = nd.nd_dpos;
|
||||
if (nd.nd_procnum != NQNFSPROC_EVICTED) {
|
||||
md = nfsd->nd_md;
|
||||
dpos = nfsd->nd_dpos;
|
||||
if (nfsd->nd_procnum != NQNFSPROC_EVICTED) {
|
||||
m_freem(mrep);
|
||||
return (EPERM);
|
||||
}
|
||||
fhp = &nfh.fh_generic;
|
||||
nfsm_srvmtofh(fhp);
|
||||
m_freem(mrep);
|
||||
error = nfs_nget(nmp->nm_mountp, &nfh, &np);
|
||||
error = nfs_nget(nmp->nm_mountp, (nfsfh_t *)fhp, NFSX_V3FH, &np);
|
||||
if (error)
|
||||
return (error);
|
||||
vp = NFSTOV(np);
|
||||
@ -937,7 +982,7 @@ nqnfs_callback(nmp, mrep, md, dpos)
|
||||
CIRCLEQ_INSERT_HEAD(&nmp->nm_timerhead, np, n_timer);
|
||||
}
|
||||
}
|
||||
vrele(vp);
|
||||
vput(vp);
|
||||
nfsm_srvdone;
|
||||
}
|
||||
|
||||
@ -960,35 +1005,39 @@ nqnfs_clientd(nmp, cred, ncd, flag, argp, p)
|
||||
register struct nfsnode *np;
|
||||
struct vnode *vp;
|
||||
struct nfsreq myrep;
|
||||
struct nfsuid *nuidp, *nnuidp;
|
||||
int error = 0, vpid;
|
||||
|
||||
/*
|
||||
* First initialize some variables
|
||||
*/
|
||||
nqnfs_prog = txdr_unsigned(NQNFS_PROG);
|
||||
nqnfs_vers = txdr_unsigned(NQNFS_VER1);
|
||||
|
||||
/*
|
||||
* If an authorization string is being passed in, get it.
|
||||
*/
|
||||
if ((flag & NFSSVC_GOTAUTH) &&
|
||||
(nmp->nm_flag & (NFSMNT_WAITAUTH | NFSMNT_DISMNT)) == 0) {
|
||||
if (nmp->nm_flag & NFSMNT_HASAUTH)
|
||||
panic("cld kerb");
|
||||
if ((flag & NFSSVC_AUTHINFAIL) == 0) {
|
||||
if (ncd->ncd_authlen <= RPCAUTH_MAXSIZ &&
|
||||
copyin(ncd->ncd_authstr, nmp->nm_authstr,
|
||||
ncd->ncd_authlen) == 0) {
|
||||
nmp->nm_authtype = ncd->ncd_authtype;
|
||||
nmp->nm_authlen = ncd->ncd_authlen;
|
||||
} else
|
||||
nmp->nm_flag |= NFSMNT_AUTHERR;
|
||||
(nmp->nm_flag & (NFSMNT_WAITAUTH | NFSMNT_DISMNT)) == 0) {
|
||||
if (nmp->nm_flag & NFSMNT_HASAUTH)
|
||||
panic("cld kerb");
|
||||
if ((flag & NFSSVC_AUTHINFAIL) == 0) {
|
||||
if (ncd->ncd_authlen <= nmp->nm_authlen &&
|
||||
ncd->ncd_verflen <= nmp->nm_verflen &&
|
||||
!copyin(ncd->ncd_authstr,nmp->nm_authstr,ncd->ncd_authlen)&&
|
||||
!copyin(ncd->ncd_verfstr,nmp->nm_verfstr,ncd->ncd_verflen)){
|
||||
nmp->nm_authtype = ncd->ncd_authtype;
|
||||
nmp->nm_authlen = ncd->ncd_authlen;
|
||||
nmp->nm_verflen = ncd->ncd_verflen;
|
||||
#ifdef NFSKERB
|
||||
nmp->nm_key = ncd->ncd_key;
|
||||
#endif
|
||||
} else
|
||||
nmp->nm_flag |= NFSMNT_AUTHERR;
|
||||
nmp->nm_flag |= NFSMNT_HASAUTH;
|
||||
wakeup((caddr_t)&nmp->nm_authlen);
|
||||
nmp->nm_flag |= NFSMNT_AUTHERR;
|
||||
} else
|
||||
nmp->nm_flag |= NFSMNT_AUTHERR;
|
||||
nmp->nm_flag |= NFSMNT_HASAUTH;
|
||||
wakeup((caddr_t)&nmp->nm_authlen);
|
||||
} else
|
||||
nmp->nm_flag |= NFSMNT_WAITAUTH;
|
||||
nmp->nm_flag |= NFSMNT_WAITAUTH;
|
||||
|
||||
/*
|
||||
* Loop every second updating queue until there is a termination sig.
|
||||
@ -1016,13 +1065,11 @@ nqnfs_clientd(nmp, cred, ncd, flag, argp, p)
|
||||
while (np != (void *)&nmp->nm_timerhead &&
|
||||
(nmp->nm_flag & NFSMNT_DISMINPROG) == 0) {
|
||||
vp = NFSTOV(np);
|
||||
if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash2");
|
||||
vpid = vp->v_id;
|
||||
if (np->n_expiry < time.tv_sec) {
|
||||
if (vget(vp, 1) == 0) {
|
||||
nmp->nm_inprog = vp;
|
||||
if (vpid == vp->v_id) {
|
||||
if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash3");
|
||||
CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
|
||||
np->n_timer.cqe_next = 0;
|
||||
if ((np->n_flag & (NMODIFIED | NQNFSEVICTED))
|
||||
@ -1047,9 +1094,8 @@ if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash3");
|
||||
== NQNFSWRITE && vp->v_dirtyblkhd.lh_first &&
|
||||
vget(vp, 1) == 0) {
|
||||
nmp->nm_inprog = vp;
|
||||
if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash4");
|
||||
if (vpid == vp->v_id &&
|
||||
nqnfs_getlease(vp, NQL_WRITE, cred, p)==0)
|
||||
nqnfs_getlease(vp, ND_WRITE, cred, p)==0)
|
||||
np->n_brev = np->n_lrev;
|
||||
vrele(vp);
|
||||
nmp->nm_inprog = NULLVP;
|
||||
@ -1084,6 +1130,16 @@ if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash4");
|
||||
(void) dounmount(nmp->nm_mountp, 0, p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, we can free up the mount structure.
|
||||
*/
|
||||
for (nuidp = nmp->nm_uidlruhead.tqh_first; nuidp != 0; nuidp = nnuidp) {
|
||||
nnuidp = nuidp->nu_lru.tqe_next;
|
||||
LIST_REMOVE(nuidp, nu_hash);
|
||||
TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru);
|
||||
free((caddr_t)nuidp, M_NFSUID);
|
||||
}
|
||||
free((caddr_t)nmp, M_NFSMNT);
|
||||
if (error == EWOULDBLOCK)
|
||||
error = 0;
|
||||
@ -1095,7 +1151,7 @@ if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash4");
|
||||
* Called from the settimeofday() syscall.
|
||||
*/
|
||||
void
|
||||
nfs_lease_updatetime(deltat)
|
||||
nqnfs_lease_updatetime(deltat)
|
||||
register int deltat;
|
||||
{
|
||||
register struct nqlease *lp;
|
||||
@ -1116,8 +1172,17 @@ nfs_lease_updatetime(deltat)
|
||||
* Search the mount list for all nqnfs mounts and do their timer
|
||||
* queues.
|
||||
*/
|
||||
#if NetBSD >= 1994101
|
||||
for (mp = mountlist.cqh_first; mp != (void *)&mountlist;
|
||||
mp = mp->mnt_list.cqe_next) {
|
||||
#else
|
||||
for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) {
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
if (!strcmp(&mp->mnt_stat.f_fstypename[0], MOUNT_NFS)) {
|
||||
#else
|
||||
if (mp->mnt_stat.f_fsid.val[1] == MOUNT_NFS) {
|
||||
#endif
|
||||
nmp = VFSTONFS(mp);
|
||||
if (nmp->nm_flag & NFSMNT_NQNFS) {
|
||||
for (np = nmp->nm_timerhead.cqh_first;
|
||||
@ -1174,9 +1239,9 @@ nqnfs_clientlease(nmp, np, rwflag, cachable, expiry, frev)
|
||||
|
||||
if (np->n_timer.cqe_next != 0) {
|
||||
CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
|
||||
if (rwflag == NQL_WRITE)
|
||||
if (rwflag == ND_WRITE)
|
||||
np->n_flag |= NQNFSWRITE;
|
||||
} else if (rwflag == NQL_READ)
|
||||
} else if (rwflag == ND_READ)
|
||||
np->n_flag &= ~NQNFSWRITE;
|
||||
else
|
||||
np->n_flag |= NQNFSWRITE;
|
||||
|
2912
sys/nfs/nfs_serv.c
2912
sys/nfs/nfs_serv.c
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_socket.c 8.3 (Berkeley) 1/12/94
|
||||
* $Id: nfs_socket.c,v 1.6 1995/03/16 18:15:37 bde Exp $
|
||||
* $Id: nfs_socket.c,v 1.7 1995/05/30 08:12:40 rgrimes Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -59,7 +59,7 @@
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/xdr_subs.h>
|
||||
#include <nfs/nfsm_subs.h>
|
||||
@ -94,36 +94,13 @@
|
||||
* External data, mostly RPC constants in XDR form
|
||||
*/
|
||||
extern u_long rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers, rpc_auth_unix,
|
||||
rpc_msgaccepted, rpc_call, rpc_autherr, rpc_rejectedcred,
|
||||
rpc_msgaccepted, rpc_call, rpc_autherr,
|
||||
rpc_auth_kerb;
|
||||
extern u_long nfs_prog, nfs_vers, nqnfs_prog, nqnfs_vers;
|
||||
extern u_long nfs_prog, nqnfs_prog;
|
||||
extern time_t nqnfsstarttime;
|
||||
extern int nonidempotent[NFS_NPROCS];
|
||||
|
||||
/*
|
||||
* Maps errno values to nfs error numbers.
|
||||
* Use NFSERR_IO as the catch all for ones not specifically defined in
|
||||
* RFC 1094.
|
||||
*/
|
||||
static int nfsrv_errmap[ELAST] = {
|
||||
NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR,
|
||||
NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO,
|
||||
};
|
||||
extern struct nfsstats nfsstats;
|
||||
extern int nfsv3_procid[NFS_NPROCS];
|
||||
extern int nfs_ticks;
|
||||
|
||||
/*
|
||||
* Defines which timer to use for the procnum.
|
||||
@ -134,7 +111,8 @@ static int nfsrv_errmap[ELAST] = {
|
||||
* 4 - write
|
||||
*/
|
||||
static int proct[NFS_NPROCS] = {
|
||||
0, 1, 0, 0, 2, 3, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0,
|
||||
0, 1, 0, 2, 1, 3, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0,
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -164,10 +142,12 @@ int nfsrv_null(),
|
||||
nfsrv_getattr(),
|
||||
nfsrv_setattr(),
|
||||
nfsrv_lookup(),
|
||||
nfsrv3_access(),
|
||||
nfsrv_readlink(),
|
||||
nfsrv_read(),
|
||||
nfsrv_write(),
|
||||
nfsrv_create(),
|
||||
nfsrv_mknod(),
|
||||
nfsrv_remove(),
|
||||
nfsrv_rename(),
|
||||
nfsrv_link(),
|
||||
@ -175,37 +155,42 @@ int nfsrv_null(),
|
||||
nfsrv_mkdir(),
|
||||
nfsrv_rmdir(),
|
||||
nfsrv_readdir(),
|
||||
nfsrv_readdirplus(),
|
||||
nfsrv_statfs(),
|
||||
nfsrv_fsinfo(),
|
||||
nfsrv_pathconf(),
|
||||
nfsrv_commit(),
|
||||
nfsrv_noop(),
|
||||
nqnfsrv_readdirlook(),
|
||||
nqnfsrv_getlease(),
|
||||
nqnfsrv_vacated(),
|
||||
nqnfsrv_access();
|
||||
nqnfsrv_vacated();
|
||||
|
||||
int (*nfsrv_procs[NFS_NPROCS])() = {
|
||||
int (*nfsrv3_procs[NFS_NPROCS])() = {
|
||||
nfsrv_null,
|
||||
nfsrv_getattr,
|
||||
nfsrv_setattr,
|
||||
nfsrv_noop,
|
||||
nfsrv_lookup,
|
||||
nfsrv3_access,
|
||||
nfsrv_readlink,
|
||||
nfsrv_read,
|
||||
nfsrv_noop,
|
||||
nfsrv_write,
|
||||
nfsrv_create,
|
||||
nfsrv_mkdir,
|
||||
nfsrv_symlink,
|
||||
nfsrv_mknod,
|
||||
nfsrv_remove,
|
||||
nfsrv_rmdir,
|
||||
nfsrv_rename,
|
||||
nfsrv_link,
|
||||
nfsrv_symlink,
|
||||
nfsrv_mkdir,
|
||||
nfsrv_rmdir,
|
||||
nfsrv_readdir,
|
||||
nfsrv_readdirplus,
|
||||
nfsrv_statfs,
|
||||
nqnfsrv_readdirlook,
|
||||
nfsrv_fsinfo,
|
||||
nfsrv_pathconf,
|
||||
nfsrv_commit,
|
||||
nqnfsrv_getlease,
|
||||
nqnfsrv_vacated,
|
||||
nfsrv_noop,
|
||||
nqnfsrv_access,
|
||||
nfsrv_noop
|
||||
};
|
||||
|
||||
/*
|
||||
@ -874,13 +859,16 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
struct nfsmount *nmp;
|
||||
struct mbuf *md, *mheadend;
|
||||
struct nfsnode *np;
|
||||
char nickv[RPCX_NICKVERF];
|
||||
time_t reqtime, waituntil;
|
||||
caddr_t dpos, cp2;
|
||||
int t1, nqlflag, cachable, s, error = 0, mrest_len, auth_len, auth_type;
|
||||
int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0, failed_auth = 0;
|
||||
int verf_len, verf_type;
|
||||
u_long xid;
|
||||
u_quad_t frev;
|
||||
char *auth_str;
|
||||
char *auth_str, *verf_str;
|
||||
NFSKERBKEY_T key; /* save session key */
|
||||
|
||||
nmp = VFSTONFS(vp->v_mount);
|
||||
MALLOC(rep, struct nfsreq *, sizeof(struct nfsreq), M_NFSREQ, M_WAITOK);
|
||||
@ -900,19 +888,21 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
* Get the RPC header with authorization.
|
||||
*/
|
||||
kerbauth:
|
||||
auth_str = (char *)0;
|
||||
verf_str = auth_str = (char *)0;
|
||||
if (nmp->nm_flag & NFSMNT_KERB) {
|
||||
if (failed_auth) {
|
||||
error = nfs_getauth(nmp, rep, cred, &auth_type,
|
||||
&auth_str, &auth_len);
|
||||
verf_str = nickv;
|
||||
verf_len = sizeof (nickv);
|
||||
auth_type = RPCAUTH_KERB4;
|
||||
bzero((caddr_t)key, sizeof (key));
|
||||
if (failed_auth || nfs_getnickauth(nmp, cred, &auth_str,
|
||||
&auth_len, verf_str, verf_len)) {
|
||||
error = nfs_getauth(nmp, rep, cred, &auth_str,
|
||||
&auth_len, verf_str, &verf_len, key);
|
||||
if (error) {
|
||||
free((caddr_t)rep, M_NFSREQ);
|
||||
m_freem(mrest);
|
||||
return (error);
|
||||
}
|
||||
} else {
|
||||
auth_type = RPCAUTH_UNIX;
|
||||
auth_len = 5 * NFSX_UNSIGNED;
|
||||
}
|
||||
} else {
|
||||
auth_type = RPCAUTH_UNIX;
|
||||
@ -922,8 +912,8 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) +
|
||||
5 * NFSX_UNSIGNED;
|
||||
}
|
||||
m = nfsm_rpchead(cred, (nmp->nm_flag & NFSMNT_NQNFS), procnum,
|
||||
auth_type, auth_len, auth_str, mrest, mrest_len, &mheadend, &xid);
|
||||
m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len,
|
||||
auth_str, verf_len, verf_str, mrest, mrest_len, &mheadend, &xid);
|
||||
if (auth_str)
|
||||
free(auth_str, M_TEMP);
|
||||
|
||||
@ -1029,12 +1019,12 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
/*
|
||||
* break down the rpc header and check if ok
|
||||
*/
|
||||
nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
|
||||
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
if (*tl++ == rpc_msgdenied) {
|
||||
if (*tl == rpc_mismatch)
|
||||
error = EOPNOTSUPP;
|
||||
else if ((nmp->nm_flag & NFSMNT_KERB) && *tl++ == rpc_autherr) {
|
||||
if (*tl == rpc_rejectedcred && failed_auth == 0) {
|
||||
if (!failed_auth) {
|
||||
failed_auth++;
|
||||
mheadend->m_next = (struct mbuf *)0;
|
||||
m_freem(mrep);
|
||||
@ -1051,22 +1041,25 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
}
|
||||
|
||||
/*
|
||||
* skip over the auth_verf, someday we may want to cache auth_short's
|
||||
* for nfs_reqhead(), but for now just dump it
|
||||
* Grab any Kerberos verifier, otherwise just throw it away.
|
||||
*/
|
||||
if (*++tl != 0) {
|
||||
i = nfsm_rndup(fxdr_unsigned(long, *tl));
|
||||
nfsm_adv(i);
|
||||
}
|
||||
verf_type = fxdr_unsigned(int, *tl++);
|
||||
i = fxdr_unsigned(int, *tl);
|
||||
if ((nmp->nm_flag & NFSMNT_KERB) && verf_type == RPCAUTH_KERB4) {
|
||||
error = nfs_savenickauth(nmp, cred, i, key, &md, &dpos, mrep);
|
||||
if (error)
|
||||
goto nfsmout;
|
||||
} else if (i > 0)
|
||||
nfsm_adv(nfsm_rndup(i));
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
|
||||
/* 0 == ok */
|
||||
if (*tl == 0) {
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
|
||||
if (*tl != 0) {
|
||||
error = fxdr_unsigned(int, *tl);
|
||||
m_freem(mrep);
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
error == NQNFS_TRYLATER) {
|
||||
if ((nmp->nm_flag & NFSMNT_NFSV3) &&
|
||||
error == NFSERR_TRYLATER) {
|
||||
m_freem(mrep);
|
||||
error = 0;
|
||||
waituntil = time.tv_sec + trylater_delay;
|
||||
while (time.tv_sec < waituntil)
|
||||
@ -1084,6 +1077,13 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
*/
|
||||
if (error == ESTALE)
|
||||
cache_purge(vp);
|
||||
if (nmp->nm_flag & NFSMNT_NFSV3) {
|
||||
*mrp = mrep;
|
||||
*mdp = md;
|
||||
*dposp = dpos;
|
||||
error |= NFSERR_RETERR;
|
||||
} else
|
||||
m_freem(mrep);
|
||||
m_freem(rep->r_mreq);
|
||||
free((caddr_t)rep, M_NFSREQ);
|
||||
return (error);
|
||||
@ -1115,10 +1115,10 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
return (0);
|
||||
}
|
||||
m_freem(mrep);
|
||||
m_freem(rep->r_mreq);
|
||||
free((caddr_t)rep, M_NFSREQ);
|
||||
error = EPROTONOSUPPORT;
|
||||
nfsmout:
|
||||
m_freem(rep->r_mreq);
|
||||
free((caddr_t)rep, M_NFSREQ);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1127,9 +1127,10 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
* siz arg. is used to decide if adding a cluster is worthwhile
|
||||
*/
|
||||
int
|
||||
nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
|
||||
nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
|
||||
int siz;
|
||||
struct nfsd *nd;
|
||||
struct nfsrv_descript *nd;
|
||||
struct nfssvc_sock *slp;
|
||||
int err;
|
||||
int cache;
|
||||
u_quad_t *frev;
|
||||
@ -1154,47 +1155,98 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
|
||||
} else
|
||||
mreq->m_data += max_hdr;
|
||||
tl = mtod(mreq, u_long *);
|
||||
mreq->m_len = 6*NFSX_UNSIGNED;
|
||||
bpos = ((caddr_t)tl)+mreq->m_len;
|
||||
mreq->m_len = 6 * NFSX_UNSIGNED;
|
||||
bpos = ((caddr_t)tl) + mreq->m_len;
|
||||
*tl++ = txdr_unsigned(nd->nd_retxid);
|
||||
*tl++ = rpc_reply;
|
||||
if (err == ERPCMISMATCH || err == NQNFS_AUTHERR) {
|
||||
if (err == ERPCMISMATCH || (err & NFSERR_AUTHERR)) {
|
||||
*tl++ = rpc_msgdenied;
|
||||
if (err == NQNFS_AUTHERR) {
|
||||
if (err & NFSERR_AUTHERR) {
|
||||
*tl++ = rpc_autherr;
|
||||
*tl = rpc_rejectedcred;
|
||||
*tl = txdr_unsigned(err & ~NFSERR_AUTHERR);
|
||||
mreq->m_len -= NFSX_UNSIGNED;
|
||||
bpos -= NFSX_UNSIGNED;
|
||||
} else {
|
||||
*tl++ = rpc_mismatch;
|
||||
*tl++ = txdr_unsigned(2);
|
||||
*tl = txdr_unsigned(2);
|
||||
*tl++ = txdr_unsigned(RPC_VER2);
|
||||
*tl = txdr_unsigned(RPC_VER2);
|
||||
}
|
||||
} else {
|
||||
*tl++ = rpc_msgaccepted;
|
||||
*tl++ = 0;
|
||||
*tl++ = 0;
|
||||
|
||||
/*
|
||||
* For Kerberos authentication, we must send the nickname
|
||||
* verifier back, otherwise just RPCAUTH_NULL.
|
||||
*/
|
||||
if (nd->nd_flag & ND_KERBFULL) {
|
||||
register struct nfsuid *nuidp;
|
||||
struct timeval ktvin, ktvout;
|
||||
NFSKERBKEYSCHED_T keys; /* stores key schedule */
|
||||
|
||||
for (nuidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
|
||||
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
|
||||
if (nuidp->nu_cr.cr_uid == nd->nd_cr.cr_uid &&
|
||||
(!nd->nd_nam2 || netaddr_match(NU_NETFAM(nuidp),
|
||||
&nuidp->nu_haddr, nd->nd_nam2)))
|
||||
break;
|
||||
}
|
||||
if (nuidp) {
|
||||
ktvin.tv_sec =
|
||||
txdr_unsigned(nuidp->nu_timestamp.tv_sec - 1);
|
||||
ktvin.tv_usec =
|
||||
txdr_unsigned(nuidp->nu_timestamp.tv_usec);
|
||||
|
||||
/*
|
||||
* Encrypt the timestamp in ecb mode using the
|
||||
* session key.
|
||||
*/
|
||||
#ifdef NFSKERB
|
||||
XXX
|
||||
#endif
|
||||
|
||||
*tl++ = rpc_auth_kerb;
|
||||
*tl++ = txdr_unsigned(3 * NFSX_UNSIGNED);
|
||||
*tl = ktvout.tv_sec;
|
||||
nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
*tl++ = ktvout.tv_usec;
|
||||
*tl++ = txdr_unsigned(nuidp->nu_cr.cr_uid);
|
||||
} else {
|
||||
*tl++ = 0;
|
||||
*tl++ = 0;
|
||||
}
|
||||
} else {
|
||||
*tl++ = 0;
|
||||
*tl++ = 0;
|
||||
}
|
||||
switch (err) {
|
||||
case EPROGUNAVAIL:
|
||||
*tl = txdr_unsigned(RPC_PROGUNAVAIL);
|
||||
break;
|
||||
case EPROGMISMATCH:
|
||||
*tl = txdr_unsigned(RPC_PROGMISMATCH);
|
||||
nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(2);
|
||||
*tl = txdr_unsigned(2); /* someday 3 */
|
||||
nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
|
||||
if (nd->nd_flag & ND_NQNFS) {
|
||||
*tl++ = txdr_unsigned(3);
|
||||
*tl = txdr_unsigned(3);
|
||||
} else {
|
||||
*tl++ = txdr_unsigned(2);
|
||||
*tl = txdr_unsigned(3);
|
||||
}
|
||||
break;
|
||||
case EPROCUNAVAIL:
|
||||
*tl = txdr_unsigned(RPC_PROCUNAVAIL);
|
||||
break;
|
||||
case EBADRPC:
|
||||
*tl = txdr_unsigned(RPC_GARBAGE);
|
||||
break;
|
||||
default:
|
||||
*tl = 0;
|
||||
if (err != VNOVAL) {
|
||||
if (err != NFSERR_RETVOID) {
|
||||
nfsm_build(tl, u_long *, NFSX_UNSIGNED);
|
||||
if (err)
|
||||
*tl = txdr_unsigned(nfsrv_errmap[err - 1]);
|
||||
*tl = txdr_unsigned(nfsrv_errmap(nd, err));
|
||||
else
|
||||
*tl = 0;
|
||||
*tl = 0;
|
||||
}
|
||||
break;
|
||||
};
|
||||
@ -1203,16 +1255,14 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
|
||||
/*
|
||||
* For nqnfs, piggyback lease as requested.
|
||||
*/
|
||||
if (nd->nd_nqlflag != NQL_NOVAL && err == 0) {
|
||||
if (nd->nd_nqlflag) {
|
||||
nfsm_build(tl, u_long *, 5*NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(nd->nd_nqlflag);
|
||||
if ((nd->nd_flag & ND_NQNFS) && err == 0) {
|
||||
if (nd->nd_flag & ND_LEASE) {
|
||||
nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(nd->nd_flag & ND_LEASE);
|
||||
*tl++ = txdr_unsigned(cache);
|
||||
*tl++ = txdr_unsigned(nd->nd_duration);
|
||||
txdr_hyper(frev, tl);
|
||||
} else {
|
||||
if (nd->nd_nqlflag != 0)
|
||||
panic("nqreph");
|
||||
nfsm_build(tl, u_long *, NFSX_UNSIGNED);
|
||||
*tl = 0;
|
||||
}
|
||||
@ -1220,7 +1270,7 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
|
||||
*mrq = mreq;
|
||||
*mbp = mb;
|
||||
*bposp = bpos;
|
||||
if (err != 0 && err != VNOVAL)
|
||||
if (err != 0 && err != NFSERR_RETVOID)
|
||||
nfsstats.srvrpc_errs++;
|
||||
return (0);
|
||||
}
|
||||
@ -1240,8 +1290,10 @@ nfs_timer(arg)
|
||||
register struct socket *so;
|
||||
register struct nfsmount *nmp;
|
||||
register int timeo;
|
||||
register struct nfssvc_sock *slp;
|
||||
static long lasttime = 0;
|
||||
int s, error;
|
||||
u_quad_t cur_usec;
|
||||
|
||||
s = splnet();
|
||||
for (rep = nfs_reqq.tqh_first; rep != 0; rep = rep->r_chain.tqe_next) {
|
||||
@ -1338,8 +1390,19 @@ nfs_timer(arg)
|
||||
lasttime = time.tv_sec;
|
||||
nqnfs_serverd();
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the write gathering queues for writes that need to be
|
||||
* completed now.
|
||||
*/
|
||||
cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
|
||||
for (slp = nfssvc_sockhead.tqh_first; slp != 0;
|
||||
slp = slp->ns_chain.tqe_next) {
|
||||
if (slp->ns_tq.lh_first && slp->ns_tq.lh_first->nd_time<=cur_usec)
|
||||
nfsrv_wakenfsd(slp);
|
||||
}
|
||||
splx(s);
|
||||
timeout(nfs_timer, (void *)0, hz / NFS_HZ);
|
||||
timeout(nfs_timer, (void *)0, nfs_ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1673,7 +1736,7 @@ nfsrv_getstream(slp, waitflag)
|
||||
register struct nfssvc_sock *slp;
|
||||
int waitflag;
|
||||
{
|
||||
register struct mbuf *m;
|
||||
register struct mbuf *m, **mpp;
|
||||
register char *cp1, *cp2;
|
||||
register int len;
|
||||
struct mbuf *om, *m2, *recm = 0;
|
||||
@ -1707,7 +1770,12 @@ nfsrv_getstream(slp, waitflag)
|
||||
}
|
||||
}
|
||||
slp->ns_cc -= NFSX_UNSIGNED;
|
||||
slp->ns_reclen = ntohl(recmark) & ~0x80000000;
|
||||
recmark = ntohl(recmark);
|
||||
slp->ns_reclen = recmark & ~0x80000000;
|
||||
if (recmark & 0x80000000)
|
||||
slp->ns_flag |= SLP_LASTFRAG;
|
||||
else
|
||||
slp->ns_flag &= ~SLP_LASTFRAG;
|
||||
if (slp->ns_reclen < NFS_MINPACKET || slp->ns_reclen > NFS_MAXPACKET) {
|
||||
slp->ns_flag &= ~SLP_GETSTREAM;
|
||||
return (EPERM);
|
||||
@ -1761,12 +1829,23 @@ nfsrv_getstream(slp, waitflag)
|
||||
slp->ns_flag &= ~SLP_GETSTREAM;
|
||||
return (0);
|
||||
}
|
||||
nfs_realign(recm, 10 * NFSX_UNSIGNED);
|
||||
if (slp->ns_recend)
|
||||
slp->ns_recend->m_nextpkt = recm;
|
||||
else
|
||||
slp->ns_rec = recm;
|
||||
slp->ns_recend = recm;
|
||||
|
||||
/*
|
||||
* Accumulate the fragments into a record.
|
||||
*/
|
||||
mpp = &slp->ns_frag;
|
||||
while (*mpp)
|
||||
mpp = &((*mpp)->m_next);
|
||||
*mpp = recm;
|
||||
if (slp->ns_flag & SLP_LASTFRAG) {
|
||||
nfs_realign(slp->ns_frag, 10 * NFSX_UNSIGNED);
|
||||
if (slp->ns_recend)
|
||||
slp->ns_recend->m_nextpkt = slp->ns_frag;
|
||||
else
|
||||
slp->ns_rec = slp->ns_frag;
|
||||
slp->ns_recend = slp->ns_frag;
|
||||
slp->ns_frag = (struct mbuf *)0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1774,13 +1853,16 @@ nfsrv_getstream(slp, waitflag)
|
||||
* Parse an RPC header.
|
||||
*/
|
||||
int
|
||||
nfsrv_dorec(slp, nd)
|
||||
nfsrv_dorec(slp, nfsd, ndp)
|
||||
register struct nfssvc_sock *slp;
|
||||
register struct nfsd *nd;
|
||||
struct nfsd *nfsd;
|
||||
struct nfsrv_descript **ndp;
|
||||
{
|
||||
register struct mbuf *m;
|
||||
register struct mbuf *m, *nam;
|
||||
register struct nfsrv_descript *nd;
|
||||
int error;
|
||||
|
||||
*ndp = NULL;
|
||||
if ((slp->ns_flag & SLP_VALID) == 0 ||
|
||||
(m = slp->ns_rec) == (struct mbuf *)0)
|
||||
return (ENOBUFS);
|
||||
@ -1790,19 +1872,24 @@ nfsrv_dorec(slp, nd)
|
||||
else
|
||||
slp->ns_recend = (struct mbuf *)0;
|
||||
if (m->m_type == MT_SONAME) {
|
||||
nd->nd_nam = m;
|
||||
nd->nd_md = nd->nd_mrep = m->m_next;
|
||||
m->m_next = (struct mbuf *)0;
|
||||
} else {
|
||||
nd->nd_nam = (struct mbuf *)0;
|
||||
nd->nd_md = nd->nd_mrep = m;
|
||||
}
|
||||
nd->nd_dpos = mtod(nd->nd_md, caddr_t);
|
||||
error = nfs_getreq(nd, TRUE);
|
||||
nam = m;
|
||||
m = m->m_next;
|
||||
nam->m_next = NULL;
|
||||
} else
|
||||
nam = NULL;
|
||||
MALLOC(nd, struct nfsrv_descript *, sizeof (struct nfsrv_descript),
|
||||
M_NFSRVDESC, M_WAITOK);
|
||||
nd->nd_md = nd->nd_mrep = m;
|
||||
nd->nd_nam2 = nam;
|
||||
nd->nd_dpos = mtod(m, caddr_t);
|
||||
error = nfs_getreq(nd, nfsd, TRUE);
|
||||
if (error) {
|
||||
m_freem(nd->nd_nam);
|
||||
m_freem(nam);
|
||||
free((caddr_t)nd, M_NFSRVDESC);
|
||||
return (error);
|
||||
}
|
||||
*ndp = nd;
|
||||
nfsd->nfsd_nd = nd;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1812,8 +1899,9 @@ nfsrv_dorec(slp, nd)
|
||||
* - fill in the cred struct.
|
||||
*/
|
||||
int
|
||||
nfs_getreq(nd, has_header)
|
||||
register struct nfsd *nd;
|
||||
nfs_getreq(nd, nfsd, has_header)
|
||||
register struct nfsrv_descript *nd;
|
||||
struct nfsd *nfsd;
|
||||
int has_header;
|
||||
{
|
||||
register int len, i;
|
||||
@ -1821,57 +1909,67 @@ nfs_getreq(nd, has_header)
|
||||
register long t1;
|
||||
struct uio uio;
|
||||
struct iovec iov;
|
||||
caddr_t dpos, cp2;
|
||||
caddr_t dpos, cp2, cp;
|
||||
u_long nfsvers, auth_type;
|
||||
int error = 0, nqnfs = 0;
|
||||
uid_t nickuid;
|
||||
int error = 0, nqnfs = 0, ticklen;
|
||||
struct mbuf *mrep, *md;
|
||||
register struct nfsuid *nuidp;
|
||||
struct timeval tvin, tvout;
|
||||
NFSKERBKEYSCHED_T keys; /* stores key schedule */
|
||||
|
||||
mrep = nd->nd_mrep;
|
||||
md = nd->nd_md;
|
||||
dpos = nd->nd_dpos;
|
||||
if (has_header) {
|
||||
nfsm_dissect(tl, u_long *, 10*NFSX_UNSIGNED);
|
||||
nfsm_dissect(tl, u_long *, 10 * NFSX_UNSIGNED);
|
||||
nd->nd_retxid = fxdr_unsigned(u_long, *tl++);
|
||||
if (*tl++ != rpc_call) {
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
} else {
|
||||
nfsm_dissect(tl, u_long *, 8*NFSX_UNSIGNED);
|
||||
}
|
||||
} else
|
||||
nfsm_dissect(tl, u_long *, 8 * NFSX_UNSIGNED);
|
||||
nd->nd_repstat = 0;
|
||||
nd->nd_flag = 0;
|
||||
if (*tl++ != rpc_vers) {
|
||||
nd->nd_repstat = ERPCMISMATCH;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nfsvers = nfs_vers;
|
||||
if (*tl != nfs_prog) {
|
||||
if (*tl == nqnfs_prog) {
|
||||
if (*tl == nqnfs_prog)
|
||||
nqnfs++;
|
||||
nfsvers = nqnfs_vers;
|
||||
} else {
|
||||
else {
|
||||
nd->nd_repstat = EPROGUNAVAIL;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
tl++;
|
||||
if (*tl++ != nfsvers) {
|
||||
nfsvers = fxdr_unsigned(u_long, *tl++);
|
||||
if (((nfsvers < NFS_VER2 || nfsvers > NFS_VER3) && !nqnfs) ||
|
||||
(nfsvers != NQNFS_VER3 && nqnfs)) {
|
||||
nd->nd_repstat = EPROGMISMATCH;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
if (nqnfs)
|
||||
nd->nd_flag = (ND_NFSV3 | ND_NQNFS);
|
||||
else if (nfsvers == NFS_VER3)
|
||||
nd->nd_flag = ND_NFSV3;
|
||||
nd->nd_procnum = fxdr_unsigned(u_long, *tl++);
|
||||
if (nd->nd_procnum == NFSPROC_NULL)
|
||||
return (0);
|
||||
if (nd->nd_procnum >= NFS_NPROCS ||
|
||||
(!nqnfs && nd->nd_procnum > NFSPROC_STATFS) ||
|
||||
(*tl != rpc_auth_unix && *tl != rpc_auth_kerb)) {
|
||||
(!nqnfs && nd->nd_procnum >= NQNFSPROC_GETLEASE) ||
|
||||
(!nd->nd_flag && nd->nd_procnum > NFSV2PROC_STATFS)) {
|
||||
nd->nd_repstat = EPROCUNAVAIL;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
if ((nd->nd_flag & ND_NFSV3) == 0)
|
||||
nd->nd_procnum = nfsv3_procid[nd->nd_procnum];
|
||||
auth_type = *tl++;
|
||||
len = fxdr_unsigned(int, *tl++);
|
||||
if (len < 0 || len > RPCAUTH_MAXSIZ) {
|
||||
@ -1879,6 +1977,7 @@ nfs_getreq(nd, has_header)
|
||||
return (EBADRPC);
|
||||
}
|
||||
|
||||
nd->nd_flag &= ~ND_KERBAUTH;
|
||||
/*
|
||||
* Handle auth_unix or auth_kerb.
|
||||
*/
|
||||
@ -1889,7 +1988,9 @@ nfs_getreq(nd, has_header)
|
||||
return (EBADRPC);
|
||||
}
|
||||
nfsm_adv(nfsm_rndup(len));
|
||||
nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
|
||||
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
bzero((caddr_t)&nd->nd_cr, sizeof (struct ucred));
|
||||
nd->nd_cr.cr_ref = 1;
|
||||
nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
|
||||
nd->nd_cr.cr_gid = fxdr_unsigned(gid_t, *tl++);
|
||||
len = fxdr_unsigned(int, *tl);
|
||||
@ -1897,45 +1998,124 @@ nfs_getreq(nd, has_header)
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
nfsm_dissect(tl, u_long *, (len + 2)*NFSX_UNSIGNED);
|
||||
nfsm_dissect(tl, u_long *, (len + 2) * NFSX_UNSIGNED);
|
||||
for (i = 1; i <= len; i++)
|
||||
if (i < NGROUPS)
|
||||
nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
|
||||
else
|
||||
tl++;
|
||||
if (i < NGROUPS)
|
||||
nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
|
||||
else
|
||||
tl++;
|
||||
nd->nd_cr.cr_ngroups = (len >= NGROUPS) ? NGROUPS : (len + 1);
|
||||
} else if (auth_type == rpc_auth_kerb) {
|
||||
nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
|
||||
nd->nd_authlen = fxdr_unsigned(int, *tl);
|
||||
uio.uio_resid = nfsm_rndup(nd->nd_authlen);
|
||||
if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
|
||||
if (nd->nd_cr.cr_ngroups > 1)
|
||||
nfsrvw_sort(nd->nd_cr.cr_groups, nd->nd_cr.cr_ngroups);
|
||||
len = fxdr_unsigned(int, *++tl);
|
||||
if (len < 0 || len > RPCAUTH_MAXSIZ) {
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
uio.uio_offset = 0;
|
||||
uio.uio_iov = &iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
uio.uio_segflg = UIO_SYSSPACE;
|
||||
iov.iov_base = (caddr_t)nd->nd_authstr;
|
||||
iov.iov_len = RPCAUTH_MAXSIZ;
|
||||
nfsm_mtouio(&uio, uio.uio_resid);
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
|
||||
nd->nd_flag |= NFSD_NEEDAUTH;
|
||||
}
|
||||
if (len > 0)
|
||||
nfsm_adv(nfsm_rndup(len));
|
||||
} else if (auth_type == rpc_auth_kerb) {
|
||||
switch (fxdr_unsigned(int, *tl++)) {
|
||||
case RPCAKN_FULLNAME:
|
||||
ticklen = fxdr_unsigned(int, *tl);
|
||||
*((u_long *)nfsd->nfsd_authstr) = *tl;
|
||||
uio.uio_resid = nfsm_rndup(ticklen) + NFSX_UNSIGNED;
|
||||
nfsd->nfsd_authlen = uio.uio_resid + NFSX_UNSIGNED;
|
||||
if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
uio.uio_offset = 0;
|
||||
uio.uio_iov = &iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
uio.uio_segflg = UIO_SYSSPACE;
|
||||
iov.iov_base = (caddr_t)&nfsd->nfsd_authstr[4];
|
||||
iov.iov_len = RPCAUTH_MAXSIZ - 4;
|
||||
nfsm_mtouio(&uio, uio.uio_resid);
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
|
||||
if (*tl++ != rpc_auth_kerb ||
|
||||
fxdr_unsigned(int, *tl) != 4 * NFSX_UNSIGNED) {
|
||||
printf("Bad kerb verifier\n");
|
||||
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nfsm_dissect(cp, caddr_t, 4 * NFSX_UNSIGNED);
|
||||
tl = (u_long *)cp;
|
||||
if (fxdr_unsigned(int, *tl) != RPCAKN_FULLNAME) {
|
||||
printf("Not fullname kerb verifier\n");
|
||||
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
cp += NFSX_UNSIGNED;
|
||||
bcopy(cp, nfsd->nfsd_verfstr, 3 * NFSX_UNSIGNED);
|
||||
nfsd->nfsd_verflen = 3 * NFSX_UNSIGNED;
|
||||
nd->nd_flag |= ND_KERBFULL;
|
||||
nfsd->nfsd_flag |= NFSD_NEEDAUTH;
|
||||
break;
|
||||
case RPCAKN_NICKNAME:
|
||||
if (len != 2 * NFSX_UNSIGNED) {
|
||||
printf("Kerb nickname short\n");
|
||||
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADCRED);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nickuid = fxdr_unsigned(uid_t, *tl);
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
|
||||
if (*tl++ != rpc_auth_kerb ||
|
||||
fxdr_unsigned(int, *tl) != 3 * NFSX_UNSIGNED) {
|
||||
printf("Kerb nick verifier bad\n");
|
||||
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
tvin.tv_sec = *tl++;
|
||||
tvin.tv_usec = *tl;
|
||||
|
||||
/*
|
||||
* Do we have any use for the verifier.
|
||||
* According to the "Remote Procedure Call Protocol Spec." it
|
||||
* should be AUTH_NULL, but some clients make it AUTH_UNIX?
|
||||
* For now, just skip over it
|
||||
*/
|
||||
len = fxdr_unsigned(int, *++tl);
|
||||
if (len < 0 || len > RPCAUTH_MAXSIZ) {
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
if (len > 0) {
|
||||
nfsm_adv(nfsm_rndup(len));
|
||||
for (nuidp = NUIDHASH(nfsd->nfsd_slp,nickuid)->lh_first;
|
||||
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
|
||||
if (nuidp->nu_cr.cr_uid == nickuid &&
|
||||
(!nd->nd_nam2 ||
|
||||
netaddr_match(NU_NETFAM(nuidp),
|
||||
&nuidp->nu_haddr, nd->nd_nam2)))
|
||||
break;
|
||||
}
|
||||
if (!nuidp) {
|
||||
nd->nd_repstat =
|
||||
(NFSERR_AUTHERR|AUTH_REJECTCRED);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, decrypt the timestamp using the session key
|
||||
* and validate it.
|
||||
*/
|
||||
#ifdef NFSKERB
|
||||
XXX
|
||||
#endif
|
||||
|
||||
tvout.tv_sec = fxdr_unsigned(long, tvout.tv_sec);
|
||||
tvout.tv_usec = fxdr_unsigned(long, tvout.tv_usec);
|
||||
if (nuidp->nu_expire < time.tv_sec ||
|
||||
nuidp->nu_timestamp.tv_sec > tvout.tv_sec ||
|
||||
(nuidp->nu_timestamp.tv_sec == tvout.tv_sec &&
|
||||
nuidp->nu_timestamp.tv_usec > tvout.tv_usec)) {
|
||||
nuidp->nu_expire = 0;
|
||||
nd->nd_repstat =
|
||||
(NFSERR_AUTHERR|AUTH_REJECTVERF);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nfsrv_setcred(&nuidp->nu_cr, &nd->nd_cr);
|
||||
nd->nd_flag |= ND_KERBNICK;
|
||||
};
|
||||
} else {
|
||||
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_REJECTCRED);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1943,16 +2123,14 @@ nfs_getreq(nd, has_header)
|
||||
*/
|
||||
if (nqnfs && nd->nd_procnum != NQNFSPROC_EVICTED) {
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
|
||||
nd->nd_nqlflag = fxdr_unsigned(int, *tl);
|
||||
if (nd->nd_nqlflag) {
|
||||
nd->nd_flag |= fxdr_unsigned(int, *tl);
|
||||
if (nd->nd_flag & ND_LEASE) {
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
|
||||
nd->nd_duration = fxdr_unsigned(int, *tl);
|
||||
} else
|
||||
nd->nd_duration = NQ_MINLEASE;
|
||||
} else {
|
||||
nd->nd_nqlflag = NQL_NOVAL;
|
||||
} else
|
||||
nd->nd_duration = NQ_MINLEASE;
|
||||
}
|
||||
nd->nd_md = md;
|
||||
nd->nd_dpos = dpos;
|
||||
return (0);
|
||||
@ -1973,13 +2151,13 @@ nfsrv_wakenfsd(slp)
|
||||
|
||||
if ((slp->ns_flag & SLP_VALID) == 0)
|
||||
return;
|
||||
for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nd_chain.tqe_next) {
|
||||
if (nd->nd_flag & NFSD_WAITING) {
|
||||
nd->nd_flag &= ~NFSD_WAITING;
|
||||
if (nd->nd_slp)
|
||||
for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nfsd_chain.tqe_next) {
|
||||
if (nd->nfsd_flag & NFSD_WAITING) {
|
||||
nd->nfsd_flag &= ~NFSD_WAITING;
|
||||
if (nd->nfsd_slp)
|
||||
panic("nfsd wakeup");
|
||||
slp->ns_sref++;
|
||||
nd->nd_slp = slp;
|
||||
nd->nfsd_slp = slp;
|
||||
wakeup((caddr_t)nd);
|
||||
return;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_srvcache.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfs_srvcache.c,v 1.4 1994/10/02 17:27:00 phk Exp $
|
||||
* $Id: nfs_srvcache.c,v 1.5 1994/10/17 17:47:36 phk Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -59,11 +59,13 @@
|
||||
#endif
|
||||
#include <nfs/nfsm_subs.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsrvcache.h>
|
||||
#include <nfs/nqnfs.h>
|
||||
|
||||
extern struct nfsstats nfsstats;
|
||||
extern int nfsv2_procid[NFS_NPROCS];
|
||||
long numnfsrvcache, desirednfsrvcache = NFSRVCACHESIZ;
|
||||
|
||||
#define NFSRCHASH(xid) \
|
||||
@ -89,15 +91,18 @@ int nonidempotent[NFS_NPROCS] = {
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
@ -108,7 +113,7 @@ int nonidempotent[NFS_NPROCS] = {
|
||||
};
|
||||
|
||||
/* True iff the rpc reply is an nfs status ONLY! */
|
||||
static int repliesstatus[NFS_NPROCS] = {
|
||||
static int nfsv2_repstat[NFS_NPROCS] = {
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
@ -127,11 +132,6 @@ static int repliesstatus[NFS_NPROCS] = {
|
||||
TRUE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
TRUE,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -160,9 +160,9 @@ nfsrv_initcache()
|
||||
* Update/add new request at end of lru list
|
||||
*/
|
||||
int
|
||||
nfsrv_getcache(nam, nd, repp)
|
||||
struct mbuf *nam;
|
||||
register struct nfsd *nd;
|
||||
nfsrv_getcache(nd, slp, repp)
|
||||
register struct nfsrv_descript *nd;
|
||||
struct nfssvc_sock *slp;
|
||||
struct mbuf **repp;
|
||||
{
|
||||
register struct nfsrvcache *rp;
|
||||
@ -171,13 +171,17 @@ nfsrv_getcache(nam, nd, repp)
|
||||
caddr_t bpos;
|
||||
int ret;
|
||||
|
||||
if (nd->nd_nqlflag != NQL_NOVAL)
|
||||
/*
|
||||
* Don't cache recent requests for reliable transport protocols.
|
||||
* (Maybe we should for the case of a reconnect, but..)
|
||||
*/
|
||||
if (!nd->nd_nam2)
|
||||
return (RC_DOIT);
|
||||
loop:
|
||||
for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
|
||||
rp = rp->rc_hash.le_next) {
|
||||
if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
|
||||
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nam)) {
|
||||
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
|
||||
if ((rp->rc_flag & RC_LOCKED) != 0) {
|
||||
rp->rc_flag |= RC_WANTED;
|
||||
(void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
|
||||
@ -196,7 +200,7 @@ nfsrv_getcache(nam, nd, repp)
|
||||
ret = RC_DROPIT;
|
||||
} else if (rp->rc_flag & RC_REPSTATUS) {
|
||||
nfsstats.srvcache_nonidemdonehits++;
|
||||
nfs_rephead(0, nd, rp->rc_status,
|
||||
nfs_rephead(0, nd, slp, rp->rc_status,
|
||||
0, (u_quad_t *)0, repp, &mb, &bpos);
|
||||
ret = RC_REPLY;
|
||||
} else if (rp->rc_flag & RC_REPMBUF) {
|
||||
@ -243,7 +247,7 @@ nfsrv_getcache(nam, nd, repp)
|
||||
TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru);
|
||||
rp->rc_state = RC_INPROG;
|
||||
rp->rc_xid = nd->nd_retxid;
|
||||
saddr = mtod(nam, struct sockaddr_in *);
|
||||
saddr = mtod(nd->nd_nam, struct sockaddr_in *);
|
||||
switch (saddr->sin_family) {
|
||||
case AF_INET:
|
||||
rp->rc_flag |= RC_INETADDR;
|
||||
@ -252,7 +256,7 @@ nfsrv_getcache(nam, nd, repp)
|
||||
case AF_ISO:
|
||||
default:
|
||||
rp->rc_flag |= RC_NAM;
|
||||
rp->rc_nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
|
||||
rp->rc_nam = m_copym(nd->nd_nam, 0, M_COPYALL, M_WAIT);
|
||||
break;
|
||||
};
|
||||
rp->rc_proc = nd->nd_procnum;
|
||||
@ -269,21 +273,20 @@ nfsrv_getcache(nam, nd, repp)
|
||||
* Update a request cache entry after the rpc has been done
|
||||
*/
|
||||
void
|
||||
nfsrv_updatecache(nam, nd, repvalid, repmbuf)
|
||||
struct mbuf *nam;
|
||||
register struct nfsd *nd;
|
||||
nfsrv_updatecache(nd, repvalid, repmbuf)
|
||||
register struct nfsrv_descript *nd;
|
||||
int repvalid;
|
||||
struct mbuf *repmbuf;
|
||||
{
|
||||
register struct nfsrvcache *rp;
|
||||
|
||||
if (nd->nd_nqlflag != NQL_NOVAL)
|
||||
if (!nd->nd_nam2)
|
||||
return;
|
||||
loop:
|
||||
for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
|
||||
rp = rp->rc_hash.le_next) {
|
||||
if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
|
||||
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nam)) {
|
||||
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
|
||||
if ((rp->rc_flag & RC_LOCKED) != 0) {
|
||||
rp->rc_flag |= RC_WANTED;
|
||||
(void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
|
||||
@ -296,7 +299,8 @@ nfsrv_updatecache(nam, nd, repvalid, repmbuf)
|
||||
* the reply for non-idempotent rpc's.
|
||||
*/
|
||||
if (repvalid && nonidempotent[nd->nd_procnum]) {
|
||||
if (repliesstatus[nd->nd_procnum]) {
|
||||
if ((nd->nd_flag & ND_NFSV3) == 0 &&
|
||||
nfsv2_repstat[nfsv2_procid[nd->nd_procnum]]) {
|
||||
rp->rc_status = nd->nd_repstat;
|
||||
rp->rc_flag |= RC_REPSTATUS;
|
||||
} else {
|
||||
|
1037
sys/nfs/nfs_subs.c
1037
sys/nfs/nfs_subs.c
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_syscalls.c 8.3 (Berkeley) 1/4/94
|
||||
* $Id: nfs_syscalls.c,v 1.5 1994/10/17 17:47:38 phk Exp $
|
||||
* $Id: nfs_syscalls.c,v 1.6 1995/05/30 08:12:45 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -61,9 +61,11 @@
|
||||
#ifdef ISO
|
||||
#include <netiso/iso.h>
|
||||
#endif
|
||||
#include <nfs/xdr_subs.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsm_subs.h>
|
||||
#include <nfs/nfsrvcache.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
@ -73,13 +75,14 @@
|
||||
void nfsrv_zapsock __P((struct nfssvc_sock *));
|
||||
|
||||
/* Global defs. */
|
||||
extern u_long nfs_prog, nfs_vers;
|
||||
extern int (*nfsrv_procs[NFS_NPROCS])();
|
||||
extern int (*nfsrv3_procs[NFS_NPROCS])();
|
||||
extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
|
||||
extern int nfs_numasync;
|
||||
extern time_t nqnfsstarttime;
|
||||
extern int nqsrv_writeslack;
|
||||
extern int nfsrtton;
|
||||
extern struct nfsstats nfsstats;
|
||||
extern int nfsrvw_procrastinate;
|
||||
struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock;
|
||||
int nuidhash_max = NFS_MAXUIDHASH;
|
||||
static int nfs_numnfsd = 0;
|
||||
@ -225,19 +228,25 @@ nfssvc(p, uap, retval)
|
||||
if (error)
|
||||
return (error);
|
||||
if ((uap->flag & NFSSVC_AUTHIN) && ((nfsd = nsd->nsd_nfsd)) &&
|
||||
(nfsd->nd_slp->ns_flag & SLP_VALID)) {
|
||||
slp = nfsd->nd_slp;
|
||||
(nfsd->nfsd_slp->ns_flag & SLP_VALID)) {
|
||||
slp = nfsd->nfsd_slp;
|
||||
|
||||
/*
|
||||
* First check to see if another nfsd has already
|
||||
* added this credential.
|
||||
*/
|
||||
for (nuidp = NUIDHASH(slp, nsd->nsd_uid)->lh_first;
|
||||
for (nuidp = NUIDHASH(slp,nsd->nsd_cr.cr_uid)->lh_first;
|
||||
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
|
||||
if (nuidp->nu_uid == nsd->nsd_uid)
|
||||
if (nuidp->nu_cr.cr_uid == nsd->nsd_cr.cr_uid &&
|
||||
(!nfsd->nfsd_nd->nd_nam2 ||
|
||||
netaddr_match(NU_NETFAM(nuidp),
|
||||
&nuidp->nu_haddr, nfsd->nfsd_nd->nd_nam2)))
|
||||
break;
|
||||
}
|
||||
if (!nuidp) {
|
||||
if (nuidp) {
|
||||
nfsrv_setcred(&nuidp->nu_cr,&nfsd->nfsd_nd->nd_cr);
|
||||
nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
|
||||
} else {
|
||||
/*
|
||||
* Nope, so we will.
|
||||
*/
|
||||
@ -257,22 +266,53 @@ nfssvc(p, uap, retval)
|
||||
LIST_REMOVE(nuidp, nu_hash);
|
||||
TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp,
|
||||
nu_lru);
|
||||
if (nuidp->nu_flag & NU_NAM)
|
||||
m_freem(nuidp->nu_nam);
|
||||
}
|
||||
nuidp->nu_flag = 0;
|
||||
nuidp->nu_cr = nsd->nsd_cr;
|
||||
if (nuidp->nu_cr.cr_ngroups > NGROUPS)
|
||||
nuidp->nu_cr.cr_ngroups = NGROUPS;
|
||||
nuidp->nu_cr.cr_ngroups = NGROUPS;
|
||||
nuidp->nu_cr.cr_ref = 1;
|
||||
nuidp->nu_uid = nsd->nsd_uid;
|
||||
nuidp->nu_timestamp = nsd->nsd_timestamp;
|
||||
nuidp->nu_expire = time.tv_sec + nsd->nsd_ttl;
|
||||
/*
|
||||
* and save the session key in nu_key.
|
||||
*/
|
||||
bcopy(nsd->nsd_key, nuidp->nu_key,
|
||||
sizeof (nsd->nsd_key));
|
||||
if (nfsd->nfsd_nd->nd_nam2) {
|
||||
struct sockaddr_in *saddr;
|
||||
|
||||
saddr = mtod(nfsd->nfsd_nd->nd_nam2,
|
||||
struct sockaddr_in *);
|
||||
switch (saddr->sin_family) {
|
||||
case AF_INET:
|
||||
nuidp->nu_flag |= NU_INETADDR;
|
||||
nuidp->nu_inetaddr =
|
||||
saddr->sin_addr.s_addr;
|
||||
break;
|
||||
case AF_ISO:
|
||||
default:
|
||||
nuidp->nu_flag |= NU_NAM;
|
||||
nuidp->nu_nam = m_copym(
|
||||
nfsd->nfsd_nd->nd_nam2, 0,
|
||||
M_COPYALL, M_WAIT);
|
||||
break;
|
||||
};
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&slp->ns_uidlruhead, nuidp,
|
||||
nu_lru);
|
||||
LIST_INSERT_HEAD(NUIDHASH(slp, nsd->nsd_uid),
|
||||
nuidp, nu_hash);
|
||||
|
||||
nfsrv_setcred(&nuidp->nu_cr,
|
||||
&nfsd->nfsd_nd->nd_cr);
|
||||
nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd))
|
||||
nfsd->nd_flag |= NFSD_AUTHFAIL;
|
||||
nfsd->nfsd_flag |= NFSD_AUTHFAIL;
|
||||
error = nfssvc_nfsd(nsd, uap->argp, p);
|
||||
}
|
||||
if (error == EINTR || error == ERESTART)
|
||||
@ -353,8 +393,6 @@ nfssvc_addsock(fp, mynam)
|
||||
slp = (struct nfssvc_sock *)
|
||||
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
|
||||
bzero((caddr_t)slp, sizeof (struct nfssvc_sock));
|
||||
slp->ns_uidhashtbl =
|
||||
hashinit(NUIDHASHSIZ, M_NFSSVC, &slp->ns_uidhash);
|
||||
TAILQ_INIT(&slp->ns_uidlruhead);
|
||||
TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain);
|
||||
}
|
||||
@ -381,44 +419,47 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
caddr_t argp;
|
||||
struct proc *p;
|
||||
{
|
||||
register struct mbuf *m, *nam2;
|
||||
register struct mbuf *m;
|
||||
register int siz;
|
||||
register struct nfssvc_sock *slp;
|
||||
register struct socket *so;
|
||||
register int *solockp;
|
||||
struct nfsd *nd = nsd->nsd_nfsd;
|
||||
struct mbuf *mreq, *nam;
|
||||
struct timeval starttime;
|
||||
struct nfsd *nfsd = nsd->nsd_nfsd;
|
||||
struct nfsrv_descript *nd = NULL;
|
||||
struct mbuf *mreq;
|
||||
struct nfsuid *uidp;
|
||||
int error = 0, cacherep, s;
|
||||
int sotype;
|
||||
int error = 0, cacherep, s, sotype, writes_todo;
|
||||
u_quad_t cur_usec;
|
||||
|
||||
#ifndef nolint
|
||||
cacherep = RC_DOIT;
|
||||
writes_todo = 0;
|
||||
#endif
|
||||
s = splnet();
|
||||
if (nd == (struct nfsd *)0) {
|
||||
nsd->nsd_nfsd = nd = (struct nfsd *)
|
||||
if (nfsd == (struct nfsd *)0) {
|
||||
nsd->nsd_nfsd = nfsd = (struct nfsd *)
|
||||
malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK);
|
||||
bzero((caddr_t)nd, sizeof (struct nfsd));
|
||||
nd->nd_procp = p;
|
||||
nd->nd_cr.cr_ref = 1;
|
||||
TAILQ_INSERT_TAIL(&nfsd_head, nd, nd_chain);
|
||||
nd->nd_nqlflag = NQL_NOVAL;
|
||||
bzero((caddr_t)nfsd, sizeof (struct nfsd));
|
||||
nfsd->nfsd_procp = p;
|
||||
TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain);
|
||||
nfs_numnfsd++;
|
||||
}
|
||||
/*
|
||||
* Loop getting rpc requests until SIGKILL.
|
||||
*/
|
||||
for (;;) {
|
||||
if ((nd->nd_flag & NFSD_REQINPROG) == 0) {
|
||||
while (nd->nd_slp == (struct nfssvc_sock *)0 &&
|
||||
if ((nfsd->nfsd_flag & NFSD_REQINPROG) == 0) {
|
||||
while (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
|
||||
(nfsd_head_flag & NFSD_CHECKSLP) == 0) {
|
||||
nd->nd_flag |= NFSD_WAITING;
|
||||
nfsd->nfsd_flag |= NFSD_WAITING;
|
||||
nfsd_waiting++;
|
||||
error = tsleep((caddr_t)nd, PSOCK | PCATCH, "nfsd", 0);
|
||||
error = tsleep((caddr_t)nfsd, PSOCK | PCATCH,
|
||||
"nfsd", 0);
|
||||
nfsd_waiting--;
|
||||
if (error)
|
||||
goto done;
|
||||
}
|
||||
if (nd->nd_slp == (struct nfssvc_sock *)0 &&
|
||||
if (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
|
||||
(nfsd_head_flag & NFSD_CHECKSLP) != 0) {
|
||||
for (slp = nfssvc_sockhead.tqh_first; slp != 0;
|
||||
slp = slp->ns_chain.tqe_next) {
|
||||
@ -426,14 +467,14 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
== (SLP_VALID | SLP_DOREC)) {
|
||||
slp->ns_flag &= ~SLP_DOREC;
|
||||
slp->ns_sref++;
|
||||
nd->nd_slp = slp;
|
||||
nfsd->nfsd_slp = slp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (slp == 0)
|
||||
nfsd_head_flag &= ~NFSD_CHECKSLP;
|
||||
}
|
||||
if ((slp = nd->nd_slp) == (struct nfssvc_sock *)0)
|
||||
if ((slp = nfsd->nfsd_slp) == (struct nfssvc_sock *)0)
|
||||
continue;
|
||||
if (slp->ns_flag & SLP_VALID) {
|
||||
if (slp->ns_flag & SLP_DISCONN)
|
||||
@ -446,86 +487,78 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
M_WAIT);
|
||||
nfs_sndunlock(&slp->ns_solock);
|
||||
}
|
||||
error = nfsrv_dorec(slp, nd);
|
||||
nd->nd_flag |= NFSD_REQINPROG;
|
||||
error = nfsrv_dorec(slp, nfsd, &nd);
|
||||
cur_usec = (u_quad_t)time.tv_sec * 1000000 +
|
||||
(u_quad_t)time.tv_usec;
|
||||
if (error && slp->ns_tq.lh_first &&
|
||||
slp->ns_tq.lh_first->nd_time <= cur_usec) {
|
||||
error = 0;
|
||||
cacherep = RC_DOIT;
|
||||
writes_todo = 1;
|
||||
} else
|
||||
writes_todo = 0;
|
||||
nfsd->nfsd_flag |= NFSD_REQINPROG;
|
||||
}
|
||||
} else {
|
||||
error = 0;
|
||||
slp = nd->nd_slp;
|
||||
slp = nfsd->nfsd_slp;
|
||||
}
|
||||
if (error || (slp->ns_flag & SLP_VALID) == 0) {
|
||||
nd->nd_slp = (struct nfssvc_sock *)0;
|
||||
nd->nd_flag &= ~NFSD_REQINPROG;
|
||||
if (nd) {
|
||||
free((caddr_t)nd, M_NFSRVDESC);
|
||||
nd = NULL;
|
||||
}
|
||||
nfsd->nfsd_slp = (struct nfssvc_sock *)0;
|
||||
nfsd->nfsd_flag &= ~NFSD_REQINPROG;
|
||||
nfsrv_slpderef(slp);
|
||||
continue;
|
||||
}
|
||||
splx(s);
|
||||
so = slp->ns_so;
|
||||
sotype = so->so_type;
|
||||
starttime = time;
|
||||
if (so->so_proto->pr_flags & PR_CONNREQUIRED)
|
||||
solockp = &slp->ns_solock;
|
||||
else
|
||||
solockp = (int *)0;
|
||||
/*
|
||||
* nam == nam2 for connectionless protocols such as UDP
|
||||
* nam2 == NULL for connection based protocols to disable
|
||||
* recent request caching.
|
||||
*/
|
||||
nam2 = nd->nd_nam;
|
||||
if (nam2) {
|
||||
nam = nam2;
|
||||
cacherep = RC_CHECKIT;
|
||||
} else {
|
||||
nam = slp->ns_nam;
|
||||
cacherep = RC_DOIT;
|
||||
}
|
||||
if (nd) {
|
||||
nd->nd_starttime = time;
|
||||
if (nd->nd_nam2)
|
||||
nd->nd_nam = nd->nd_nam2;
|
||||
else
|
||||
nd->nd_nam = slp->ns_nam;
|
||||
|
||||
/*
|
||||
* Check to see if authorization is needed.
|
||||
*/
|
||||
if (nd->nd_flag & NFSD_NEEDAUTH) {
|
||||
static int logauth = 0;
|
||||
/*
|
||||
* Check to see if authorization is needed.
|
||||
*/
|
||||
if (nfsd->nfsd_flag & NFSD_NEEDAUTH) {
|
||||
nfsd->nfsd_flag &= ~NFSD_NEEDAUTH;
|
||||
nsd->nsd_haddr = mtod(nd->nd_nam,
|
||||
struct sockaddr_in *)->sin_addr.s_addr;
|
||||
nsd->nsd_authlen = nfsd->nfsd_authlen;
|
||||
nsd->nsd_verflen = nfsd->nfsd_verflen;
|
||||
if (!copyout(nfsd->nfsd_authstr,nsd->nsd_authstr,
|
||||
nfsd->nfsd_authlen) &&
|
||||
!copyout(nfsd->nfsd_verfstr, nsd->nsd_verfstr,
|
||||
nfsd->nfsd_verflen) &&
|
||||
!copyout((caddr_t)nsd, argp, sizeof (*nsd)))
|
||||
return (ENEEDAUTH);
|
||||
cacherep = RC_DROPIT;
|
||||
} else
|
||||
cacherep = nfsrv_getcache(nd, slp, &mreq);
|
||||
|
||||
nd->nd_flag &= ~NFSD_NEEDAUTH;
|
||||
/*
|
||||
* Check for a mapping already installed.
|
||||
*/
|
||||
for (uidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
|
||||
uidp != 0; uidp = uidp->nu_hash.le_next) {
|
||||
if (uidp->nu_uid == nd->nd_cr.cr_uid)
|
||||
break;
|
||||
}
|
||||
if (!uidp) {
|
||||
nsd->nsd_uid = nd->nd_cr.cr_uid;
|
||||
if (nam2 && logauth++ == 0)
|
||||
log(LOG_WARNING, "Kerberized NFS using UDP\n");
|
||||
nsd->nsd_haddr =
|
||||
mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
|
||||
nsd->nsd_authlen = nd->nd_authlen;
|
||||
if (copyout(nd->nd_authstr, nsd->nsd_authstr,
|
||||
nd->nd_authlen) == 0 &&
|
||||
copyout((caddr_t)nsd, argp, sizeof (*nsd)) == 0)
|
||||
return (ENEEDAUTH);
|
||||
cacherep = RC_DROPIT;
|
||||
}
|
||||
}
|
||||
if (cacherep == RC_CHECKIT)
|
||||
cacherep = nfsrv_getcache(nam2, nd, &mreq);
|
||||
|
||||
/*
|
||||
* Check for just starting up for NQNFS and send
|
||||
* fake "try again later" replies to the NQNFS clients.
|
||||
*/
|
||||
if (notstarted && nqnfsstarttime <= time.tv_sec) {
|
||||
/*
|
||||
* Check for just starting up for NQNFS and send
|
||||
* fake "try again later" replies to the NQNFS clients.
|
||||
*/
|
||||
if (notstarted && nqnfsstarttime <= time.tv_sec) {
|
||||
if (modify_flag) {
|
||||
nqnfsstarttime = time.tv_sec + nqsrv_writeslack;
|
||||
modify_flag = 0;
|
||||
} else
|
||||
notstarted = 0;
|
||||
}
|
||||
if (notstarted) {
|
||||
if (nd->nd_nqlflag == NQL_NOVAL)
|
||||
}
|
||||
if (notstarted) {
|
||||
if ((nd->nd_flag & ND_NQNFS) == 0)
|
||||
cacherep = RC_DROPIT;
|
||||
else if (nd->nd_procnum != NFSPROC_WRITE) {
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
@ -533,36 +566,42 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
cacherep = RC_DOIT;
|
||||
} else
|
||||
modify_flag = 1;
|
||||
} else if (nd->nd_flag & NFSD_AUTHFAIL) {
|
||||
nd->nd_flag &= ~NFSD_AUTHFAIL;
|
||||
} else if (nfsd->nfsd_flag & NFSD_AUTHFAIL) {
|
||||
nfsd->nfsd_flag &= ~NFSD_AUTHFAIL;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
nd->nd_repstat = NQNFS_AUTHERR;
|
||||
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
|
||||
cacherep = RC_DOIT;
|
||||
}
|
||||
}
|
||||
|
||||
switch (cacherep) {
|
||||
case RC_DOIT:
|
||||
error = (*(nfsrv_procs[nd->nd_procnum]))(nd,
|
||||
nd->nd_mrep, nd->nd_md, nd->nd_dpos, &nd->nd_cr,
|
||||
nam, &mreq);
|
||||
if (nd->nd_cr.cr_ref != 1) {
|
||||
printf("nfssvc cref=%d\n", nd->nd_cr.cr_ref);
|
||||
panic("nfssvc cref");
|
||||
}
|
||||
/*
|
||||
* Loop to get all the write rpc relies that have been
|
||||
* gathered together.
|
||||
*/
|
||||
do {
|
||||
switch (cacherep) {
|
||||
case RC_DOIT:
|
||||
if (writes_todo || (nd->nd_procnum == NFSPROC_WRITE &&
|
||||
nfsrvw_procrastinate > 0 && !notstarted))
|
||||
error = nfsrv_writegather(&nd, slp,
|
||||
nfsd->nfsd_procp, &mreq);
|
||||
else
|
||||
error = (*(nfsrv3_procs[nd->nd_procnum]))(nd,
|
||||
slp, nfsd->nfsd_procp, &mreq);
|
||||
if (mreq == NULL)
|
||||
break;
|
||||
if (error) {
|
||||
if (nd->nd_procnum != NQNFSPROC_VACATED)
|
||||
nfsstats.srv_errs++;
|
||||
if (nam2) {
|
||||
nfsrv_updatecache(nam2, nd, FALSE, mreq);
|
||||
m_freem(nam2);
|
||||
}
|
||||
nfsrv_updatecache(nd, FALSE, mreq);
|
||||
if (nd->nd_nam2)
|
||||
m_freem(nd->nd_nam2);
|
||||
break;
|
||||
}
|
||||
nfsstats.srvrpccnt[nd->nd_procnum]++;
|
||||
if (nam2)
|
||||
nfsrv_updatecache(nam2, nd, TRUE, mreq);
|
||||
nfsrv_updatecache(nd, TRUE, mreq);
|
||||
nd->nd_mrep = (struct mbuf *)0;
|
||||
case RC_REPLY:
|
||||
case RC_REPLY:
|
||||
m = mreq;
|
||||
siz = 0;
|
||||
while (m) {
|
||||
@ -587,15 +626,15 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
if (solockp)
|
||||
(void) nfs_sndlock(solockp, (struct nfsreq *)0);
|
||||
if (slp->ns_flag & SLP_VALID)
|
||||
error = nfs_send(so, nam2, m, (struct nfsreq *)0);
|
||||
error = nfs_send(so, nd->nd_nam2, m, NULL);
|
||||
else {
|
||||
error = EPIPE;
|
||||
m_freem(m);
|
||||
}
|
||||
if (nfsrtton)
|
||||
nfsd_rt(&starttime, sotype, nd, nam, cacherep);
|
||||
if (nam2)
|
||||
MFREE(nam2, m);
|
||||
nfsd_rt(sotype, nd, cacherep);
|
||||
if (nd->nd_nam2)
|
||||
MFREE(nd->nd_nam2, m);
|
||||
if (nd->nd_mrep)
|
||||
m_freem(nd->nd_mrep);
|
||||
if (error == EPIPE)
|
||||
@ -603,29 +642,50 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
if (solockp)
|
||||
nfs_sndunlock(solockp);
|
||||
if (error == EINTR || error == ERESTART) {
|
||||
free((caddr_t)nd, M_NFSRVDESC);
|
||||
nfsrv_slpderef(slp);
|
||||
s = splnet();
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case RC_DROPIT:
|
||||
case RC_DROPIT:
|
||||
if (nfsrtton)
|
||||
nfsd_rt(&starttime, sotype, nd, nam, cacherep);
|
||||
nfsd_rt(sotype, nd, cacherep);
|
||||
m_freem(nd->nd_mrep);
|
||||
m_freem(nam2);
|
||||
m_freem(nd->nd_nam2);
|
||||
break;
|
||||
};
|
||||
};
|
||||
if (nd) {
|
||||
FREE((caddr_t)nd, M_NFSRVDESC);
|
||||
nd = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if there are outstanding writes that
|
||||
* need to be serviced.
|
||||
*/
|
||||
cur_usec = (u_quad_t)time.tv_sec * 1000000 +
|
||||
(u_quad_t)time.tv_usec;
|
||||
s = splsoftclock();
|
||||
if (slp->ns_tq.lh_first &&
|
||||
slp->ns_tq.lh_first->nd_time <= cur_usec) {
|
||||
cacherep = RC_DOIT;
|
||||
writes_todo = 1;
|
||||
} else
|
||||
writes_todo = 0;
|
||||
splx(s);
|
||||
} while (writes_todo);
|
||||
s = splnet();
|
||||
if (nfsrv_dorec(slp, nd)) {
|
||||
nd->nd_flag &= ~NFSD_REQINPROG;
|
||||
nd->nd_slp = (struct nfssvc_sock *)0;
|
||||
if (nfsrv_dorec(slp, nfsd, &nd)) {
|
||||
nfsd->nfsd_flag &= ~NFSD_REQINPROG;
|
||||
nfsd->nfsd_slp = NULL;
|
||||
nfsrv_slpderef(slp);
|
||||
}
|
||||
}
|
||||
done:
|
||||
TAILQ_REMOVE(&nfsd_head, nd, nd_chain);
|
||||
TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain);
|
||||
splx(s);
|
||||
free((caddr_t)nd, M_NFSD);
|
||||
free((caddr_t)nfsd, M_NFSD);
|
||||
nsd->nsd_nfsd = (struct nfsd *)0;
|
||||
if (--nfs_numnfsd == 0)
|
||||
nfsrv_init(TRUE); /* Reinitialize everything */
|
||||
@ -641,9 +701,10 @@ int
|
||||
nfssvc_iod(p)
|
||||
struct proc *p;
|
||||
{
|
||||
register struct buf *bp;
|
||||
register struct buf *bp, *nbp;
|
||||
register int i, myiod;
|
||||
int error = 0;
|
||||
struct vnode *vp;
|
||||
int error = 0, s;
|
||||
|
||||
/*
|
||||
* Assign my position or return error if too many already running
|
||||
@ -662,24 +723,53 @@ nfssvc_iod(p)
|
||||
* Just loop around doin our stuff until SIGKILL
|
||||
*/
|
||||
for (;;) {
|
||||
while (nfs_bufq.tqh_first == NULL && error == 0) {
|
||||
nfs_iodwant[myiod] = p;
|
||||
error = tsleep((caddr_t)&nfs_iodwant[myiod],
|
||||
PWAIT | PCATCH, "nfsidl", 0);
|
||||
}
|
||||
while ((bp = nfs_bufq.tqh_first) != NULL) {
|
||||
/* Take one off the front of the list */
|
||||
TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);
|
||||
if (bp->b_flags & B_READ)
|
||||
(void) nfs_doio(bp, bp->b_rcred, (struct proc *)0);
|
||||
else
|
||||
(void) nfs_doio(bp, bp->b_wcred, (struct proc *)0);
|
||||
}
|
||||
if (error) {
|
||||
nfs_asyncdaemon[myiod] = 0;
|
||||
nfs_numasync--;
|
||||
return (error);
|
||||
}
|
||||
while (nfs_bufq.tqh_first == NULL && error == 0) {
|
||||
nfs_iodwant[myiod] = p;
|
||||
error = tsleep((caddr_t)&nfs_iodwant[myiod],
|
||||
PWAIT | PCATCH, "nfsidl", 0);
|
||||
}
|
||||
while ((bp = nfs_bufq.tqh_first) != NULL) {
|
||||
/* Take one off the front of the list */
|
||||
TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);
|
||||
if (bp->b_flags & B_READ)
|
||||
(void) nfs_doio(bp, bp->b_rcred, (struct proc *)0);
|
||||
else do {
|
||||
/*
|
||||
* Look for a delayed write for the same vnode, so I can do
|
||||
* it now. We must grab it before calling nfs_doio() to
|
||||
* avoid any risk of the vnode getting vclean()'d while
|
||||
* we are doing the write rpc.
|
||||
*/
|
||||
vp = bp->b_vp;
|
||||
s = splbio();
|
||||
for (nbp = vp->v_dirtyblkhd.lh_first; nbp;
|
||||
nbp = nbp->b_vnbufs.le_next) {
|
||||
if ((nbp->b_flags &
|
||||
(B_BUSY|B_DELWRI|B_NEEDCOMMIT|B_NOCACHE))!=B_DELWRI)
|
||||
continue;
|
||||
bremfree(nbp);
|
||||
vfs_busy_pages(nbp, 1);
|
||||
nbp->b_flags |= (B_BUSY|B_ASYNC);
|
||||
break;
|
||||
}
|
||||
splx(s);
|
||||
/*
|
||||
* For the delayed write, do the first part of nfs_bwrite()
|
||||
* up to, but not including nfs_strategy().
|
||||
*/
|
||||
if (nbp) {
|
||||
nbp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
|
||||
reassignbuf(nbp, nbp->b_vp);
|
||||
nbp->b_vp->v_numoutput++;
|
||||
}
|
||||
(void) nfs_doio(bp, bp->b_wcred, (struct proc *)0);
|
||||
} while (bp = nbp);
|
||||
}
|
||||
if (error) {
|
||||
nfs_asyncdaemon[myiod] = 0;
|
||||
nfs_numasync--;
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -695,9 +785,11 @@ nfsrv_zapsock(slp)
|
||||
register struct nfssvc_sock *slp;
|
||||
{
|
||||
register struct nfsuid *nuidp, *nnuidp;
|
||||
register struct nfsrv_descript *nwp, *nnwp;
|
||||
struct socket *so;
|
||||
struct file *fp;
|
||||
struct mbuf *m;
|
||||
int s;
|
||||
|
||||
slp->ns_flag &= ~SLP_ALLFLAGS;
|
||||
fp = slp->ns_fp;
|
||||
@ -716,8 +808,18 @@ nfsrv_zapsock(slp)
|
||||
nnuidp = nuidp->nu_lru.tqe_next;
|
||||
LIST_REMOVE(nuidp, nu_hash);
|
||||
TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, nu_lru);
|
||||
if (nuidp->nu_flag & NU_NAM)
|
||||
m_freem(nuidp->nu_nam);
|
||||
free((caddr_t)nuidp, M_NFSUID);
|
||||
}
|
||||
s = splsoftclock();
|
||||
for (nwp = slp->ns_tq.lh_first; nwp; nwp = nnwp) {
|
||||
nnwp = nwp->nd_tq.le_next;
|
||||
LIST_REMOVE(nwp, nd_tq);
|
||||
free((caddr_t)nwp, M_NFSRVDESC);
|
||||
}
|
||||
LIST_INIT(&slp->ns_tq);
|
||||
splx(s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -726,13 +828,15 @@ nfsrv_zapsock(slp)
|
||||
* on this mount point porpous out of the kernel and do it.
|
||||
*/
|
||||
int
|
||||
nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
|
||||
nfs_getauth(nmp, rep, cred, auth_str, auth_len, verf_str, verf_len, key)
|
||||
register struct nfsmount *nmp;
|
||||
struct nfsreq *rep;
|
||||
struct ucred *cred;
|
||||
int *auth_type;
|
||||
char **auth_str;
|
||||
int *auth_len;
|
||||
char *verf_str;
|
||||
int *verf_len;
|
||||
NFSKERBKEY_T key; /* return session key */
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
@ -748,6 +852,9 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
|
||||
}
|
||||
nmp->nm_flag &= ~(NFSMNT_WAITAUTH | NFSMNT_WANTAUTH);
|
||||
nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK);
|
||||
nmp->nm_authlen = RPCAUTH_MAXSIZ;
|
||||
nmp->nm_verfstr = verf_str;
|
||||
nmp->nm_verflen = *verf_len;
|
||||
nmp->nm_authuid = cred->cr_uid;
|
||||
wakeup((caddr_t)&nmp->nm_authstr);
|
||||
|
||||
@ -766,8 +873,9 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
|
||||
if (error)
|
||||
free((caddr_t)*auth_str, M_TEMP);
|
||||
else {
|
||||
*auth_type = nmp->nm_authtype;
|
||||
*auth_len = nmp->nm_authlen;
|
||||
*verf_len = nmp->nm_verflen;
|
||||
bcopy((caddr_t)nmp->nm_key, (caddr_t)key, sizeof (key));
|
||||
}
|
||||
nmp->nm_flag &= ~NFSMNT_HASAUTH;
|
||||
nmp->nm_flag |= NFSMNT_WAITAUTH;
|
||||
@ -778,6 +886,149 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a nickname authenticator and verifier.
|
||||
*/
|
||||
int
|
||||
nfs_getnickauth(nmp, cred, auth_str, auth_len, verf_str, verf_len)
|
||||
struct nfsmount *nmp;
|
||||
struct ucred *cred;
|
||||
char **auth_str;
|
||||
int *auth_len;
|
||||
char *verf_str;
|
||||
int verf_len;
|
||||
{
|
||||
register struct nfsuid *nuidp;
|
||||
register u_long *nickp, *verfp;
|
||||
struct timeval ktvin, ktvout;
|
||||
NFSKERBKEYSCHED_T keys; /* stores key schedule */
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (verf_len < (4 * NFSX_UNSIGNED))
|
||||
panic("nfs_getnickauth verf too small");
|
||||
#endif
|
||||
for (nuidp = NMUIDHASH(nmp, cred->cr_uid)->lh_first;
|
||||
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
|
||||
if (nuidp->nu_cr.cr_uid == cred->cr_uid)
|
||||
break;
|
||||
}
|
||||
if (!nuidp || nuidp->nu_expire < time.tv_sec)
|
||||
return (EACCES);
|
||||
|
||||
/*
|
||||
* Move to the end of the lru list (end of lru == most recently used).
|
||||
*/
|
||||
TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru);
|
||||
TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp, nu_lru);
|
||||
|
||||
nickp = (u_long *)malloc(2 * NFSX_UNSIGNED, M_TEMP, M_WAITOK);
|
||||
*nickp++ = txdr_unsigned(RPCAKN_NICKNAME);
|
||||
*nickp = txdr_unsigned(nuidp->nu_nickname);
|
||||
*auth_str = (char *)nickp;
|
||||
*auth_len = 2 * NFSX_UNSIGNED;
|
||||
|
||||
/*
|
||||
* Now we must encrypt the verifier and package it up.
|
||||
*/
|
||||
verfp = (u_long *)verf_str;
|
||||
*verfp++ = txdr_unsigned(RPCAKN_NICKNAME);
|
||||
if (time.tv_sec > nuidp->nu_timestamp.tv_sec ||
|
||||
(time.tv_sec == nuidp->nu_timestamp.tv_sec &&
|
||||
time.tv_usec > nuidp->nu_timestamp.tv_usec))
|
||||
nuidp->nu_timestamp = time;
|
||||
else
|
||||
nuidp->nu_timestamp.tv_usec++;
|
||||
ktvin.tv_sec = txdr_unsigned(nuidp->nu_timestamp.tv_sec);
|
||||
ktvin.tv_usec = txdr_unsigned(nuidp->nu_timestamp.tv_usec);
|
||||
|
||||
/*
|
||||
* Now encrypt the timestamp verifier in ecb mode using the session
|
||||
* key.
|
||||
*/
|
||||
#ifdef NFSKERB
|
||||
XXX
|
||||
#endif
|
||||
|
||||
*verfp++ = ktvout.tv_sec;
|
||||
*verfp++ = ktvout.tv_usec;
|
||||
*verfp = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the current nickname in a hash list entry on the mount point.
|
||||
*/
|
||||
int
|
||||
nfs_savenickauth(nmp, cred, len, key, mdp, dposp, mrep)
|
||||
register struct nfsmount *nmp;
|
||||
struct ucred *cred;
|
||||
int len;
|
||||
NFSKERBKEY_T key;
|
||||
struct mbuf **mdp;
|
||||
char **dposp;
|
||||
struct mbuf *mrep;
|
||||
{
|
||||
register struct nfsuid *nuidp;
|
||||
register u_long *tl;
|
||||
register long t1;
|
||||
struct mbuf *md = *mdp;
|
||||
struct timeval ktvin, ktvout;
|
||||
u_long nick;
|
||||
NFSKERBKEYSCHED_T keys;
|
||||
char *dpos = *dposp, *cp2;
|
||||
int deltasec, error = 0;
|
||||
|
||||
if (len == (3 * NFSX_UNSIGNED)) {
|
||||
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
ktvin.tv_sec = *tl++;
|
||||
ktvin.tv_usec = *tl++;
|
||||
nick = fxdr_unsigned(u_long, *tl);
|
||||
|
||||
/*
|
||||
* Decrypt the timestamp in ecb mode.
|
||||
*/
|
||||
#ifdef NFSKERB
|
||||
XXX
|
||||
#endif
|
||||
ktvout.tv_sec = fxdr_unsigned(long, ktvout.tv_sec);
|
||||
ktvout.tv_usec = fxdr_unsigned(long, ktvout.tv_usec);
|
||||
deltasec = time.tv_sec - ktvout.tv_sec;
|
||||
if (deltasec < 0)
|
||||
deltasec = -deltasec;
|
||||
/*
|
||||
* If ok, add it to the hash list for the mount point.
|
||||
*/
|
||||
if (deltasec <= NFS_KERBCLOCKSKEW) {
|
||||
if (nmp->nm_numuids < nuidhash_max) {
|
||||
nmp->nm_numuids++;
|
||||
nuidp = (struct nfsuid *)
|
||||
malloc(sizeof (struct nfsuid), M_NFSUID,
|
||||
M_WAITOK);
|
||||
} else {
|
||||
nuidp = nmp->nm_uidlruhead.tqh_first;
|
||||
LIST_REMOVE(nuidp, nu_hash);
|
||||
TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp,
|
||||
nu_lru);
|
||||
}
|
||||
nuidp->nu_flag = 0;
|
||||
nuidp->nu_cr.cr_uid = cred->cr_uid;
|
||||
nuidp->nu_expire = time.tv_sec + NFS_KERBTTL;
|
||||
nuidp->nu_timestamp = ktvout;
|
||||
nuidp->nu_nickname = nick;
|
||||
bcopy(key, nuidp->nu_key, sizeof (key));
|
||||
TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp,
|
||||
nu_lru);
|
||||
LIST_INSERT_HEAD(NMUIDHASH(nmp, cred->cr_uid),
|
||||
nuidp, nu_hash);
|
||||
}
|
||||
} else
|
||||
nfsm_adv(nfsm_rndup(len));
|
||||
nfsmout:
|
||||
*mdp = md;
|
||||
*dposp = dpos;
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Derefence a server socket structure. If it has no more references and
|
||||
* is no longer valid, you can throw it away.
|
||||
@ -830,16 +1081,12 @@ nfsrv_init(terminating)
|
||||
nfs_udpsock = (struct nfssvc_sock *)
|
||||
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
|
||||
bzero((caddr_t)nfs_udpsock, sizeof (struct nfssvc_sock));
|
||||
nfs_udpsock->ns_uidhashtbl =
|
||||
hashinit(NUIDHASHSIZ, M_NFSSVC, &nfs_udpsock->ns_uidhash);
|
||||
TAILQ_INIT(&nfs_udpsock->ns_uidlruhead);
|
||||
TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain);
|
||||
|
||||
nfs_cltpsock = (struct nfssvc_sock *)
|
||||
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
|
||||
bzero((caddr_t)nfs_cltpsock, sizeof (struct nfssvc_sock));
|
||||
nfs_cltpsock->ns_uidhashtbl =
|
||||
hashinit(NUIDHASHSIZ, M_NFSSVC, &nfs_cltpsock->ns_uidhash);
|
||||
TAILQ_INIT(&nfs_cltpsock->ns_uidlruhead);
|
||||
TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain);
|
||||
}
|
||||
@ -848,11 +1095,9 @@ nfsrv_init(terminating)
|
||||
* Add entries to the server monitor log.
|
||||
*/
|
||||
static void
|
||||
nfsd_rt(startp, sotype, nd, nam, cacherep)
|
||||
struct timeval *startp;
|
||||
nfsd_rt(sotype, nd, cacherep)
|
||||
int sotype;
|
||||
register struct nfsd *nd;
|
||||
struct mbuf *nam;
|
||||
register struct nfsrv_descript *nd;
|
||||
int cacherep;
|
||||
{
|
||||
register struct drt *rt;
|
||||
@ -866,15 +1111,17 @@ nfsd_rt(startp, sotype, nd, nam, cacherep)
|
||||
rt->flag = DRT_CACHEDROP;
|
||||
if (sotype == SOCK_STREAM)
|
||||
rt->flag |= DRT_TCP;
|
||||
if (nd->nd_nqlflag != NQL_NOVAL)
|
||||
if (nd->nd_flag & ND_NQNFS)
|
||||
rt->flag |= DRT_NQNFS;
|
||||
else if (nd->nd_flag & ND_NFSV3)
|
||||
rt->flag |= DRT_NFSV3;
|
||||
rt->proc = nd->nd_procnum;
|
||||
if (mtod(nam, struct sockaddr *)->sa_family == AF_INET)
|
||||
rt->ipadr = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
|
||||
if (mtod(nd->nd_nam, struct sockaddr *)->sa_family == AF_INET)
|
||||
rt->ipadr = mtod(nd->nd_nam, struct sockaddr_in *)->sin_addr.s_addr;
|
||||
else
|
||||
rt->ipadr = INADDR_ANY;
|
||||
rt->resptime = ((time.tv_sec - startp->tv_sec) * 1000000) +
|
||||
(time.tv_usec - startp->tv_usec);
|
||||
rt->ipadr = INADDR_ANY;
|
||||
rt->resptime = ((time.tv_sec - nd->nd_starttime.tv_sec) * 1000000) +
|
||||
(time.tv_usec - nd->nd_starttime.tv_usec);
|
||||
rt->tstamp = time;
|
||||
nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_vfsops.c 8.3 (Berkeley) 1/4/94
|
||||
* $Id: nfs_vfsops.c,v 1.14.2.1 1995/06/02 11:13:15 davidg Exp $
|
||||
* $Id: nfs_vfsops.c,v 1.15 1995/06/11 19:31:46 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -59,10 +59,10 @@
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/xdr_subs.h>
|
||||
#include <nfs/nfsm_subs.h>
|
||||
#include <nfs/nfsdiskless.h>
|
||||
@ -71,11 +71,15 @@
|
||||
struct nfsstats nfsstats;
|
||||
static int nfs_sysctl(int *, u_int, void *, size_t *, void *, size_t,
|
||||
struct proc *);
|
||||
extern int nfs_ticks;
|
||||
|
||||
/*
|
||||
* nfs vfs operations.
|
||||
*/
|
||||
struct vfsops nfs_vfsops = {
|
||||
#ifdef __NetBSD__
|
||||
MOUNT_NFS,
|
||||
#endif
|
||||
nfs_mount,
|
||||
nfs_start,
|
||||
nfs_unmount,
|
||||
@ -87,9 +91,13 @@ struct vfsops nfs_vfsops = {
|
||||
nfs_fhtovp,
|
||||
nfs_vptofh,
|
||||
nfs_init,
|
||||
#ifdef __FreeBSD__
|
||||
nfs_sysctl
|
||||
#endif
|
||||
};
|
||||
#ifdef __FreeBSD__
|
||||
VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This structure must be filled in by a primary bootstrap or bootstrap
|
||||
@ -99,16 +107,11 @@ VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK);
|
||||
struct nfs_diskless nfs_diskless = { 0 };
|
||||
int nfs_diskless_valid = 0;
|
||||
|
||||
extern u_long nfs_procids[NFS_NPROCS];
|
||||
extern u_long nfs_prog, nfs_vers;
|
||||
void nfs_disconnect __P((struct nfsmount *));
|
||||
void nfsargs_ntoh __P((struct nfs_args *));
|
||||
static struct mount *nfs_mountdiskless __P((char *, char *, int,
|
||||
struct sockaddr_in *, struct nfs_args *, register struct vnode **));
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
/*
|
||||
* nfs statfs call
|
||||
*/
|
||||
@ -119,40 +122,65 @@ nfs_statfs(mp, sbp, p)
|
||||
struct proc *p;
|
||||
{
|
||||
register struct vnode *vp;
|
||||
register struct nfsv2_statfs *sfp;
|
||||
register struct nfs_statfs *sfp;
|
||||
register caddr_t cp;
|
||||
register long t1;
|
||||
register u_long *tl;
|
||||
register long t1, t2;
|
||||
caddr_t bpos, dpos, cp2;
|
||||
int error = 0, isnq;
|
||||
struct nfsmount *nmp = VFSTONFS(mp);
|
||||
int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
|
||||
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
|
||||
struct nfsmount *nmp;
|
||||
struct ucred *cred;
|
||||
struct nfsnode *np;
|
||||
u_quad_t tquad;
|
||||
|
||||
nmp = VFSTONFS(mp);
|
||||
isnq = (nmp->nm_flag & NFSMNT_NQNFS);
|
||||
error = nfs_nget(mp, &nmp->nm_fh, &np);
|
||||
#ifndef nolint
|
||||
sfp = (struct nfs_statfs *)0;
|
||||
#endif
|
||||
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
|
||||
if (error)
|
||||
return (error);
|
||||
vp = NFSTOV(np);
|
||||
nfsstats.rpccnt[NFSPROC_STATFS]++;
|
||||
cred = crget();
|
||||
cred->cr_ngroups = 1;
|
||||
nfsm_reqhead(vp, NFSPROC_STATFS, NFSX_FH);
|
||||
nfsm_fhtom(vp);
|
||||
nfsm_request(vp, NFSPROC_STATFS, p, cred);
|
||||
nfsm_dissect(sfp, struct nfsv2_statfs *, NFSX_STATFS(isnq));
|
||||
if (v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0)
|
||||
(void)nfs_fsinfo(nmp, vp, cred, p);
|
||||
nfsstats.rpccnt[NFSPROC_FSSTAT]++;
|
||||
nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
|
||||
nfsm_fhtom(vp, v3);
|
||||
nfsm_request(vp, NFSPROC_FSSTAT, p, cred);
|
||||
if (v3)
|
||||
nfsm_postop_attr(vp, retattr);
|
||||
if (!error)
|
||||
nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
|
||||
#ifdef __NetBSD__
|
||||
#ifdef COMPAT_09
|
||||
sbp->f_type = 2;
|
||||
#else
|
||||
sbp->f_type = 0;
|
||||
#endif
|
||||
#else
|
||||
sbp->f_type = MOUNT_NFS;
|
||||
#endif
|
||||
sbp->f_flags = nmp->nm_flag;
|
||||
sbp->f_iosize = NFS_MAXDGRAMDATA;
|
||||
sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize);
|
||||
sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
|
||||
sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
|
||||
sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
|
||||
if (isnq) {
|
||||
sbp->f_files = fxdr_unsigned(long, sfp->sf_files);
|
||||
sbp->f_ffree = fxdr_unsigned(long, sfp->sf_ffree);
|
||||
sbp->f_iosize = min(nmp->nm_rsize, nmp->nm_wsize);
|
||||
if (v3) {
|
||||
sbp->f_bsize = NFS_FABLKSIZE;
|
||||
fxdr_hyper(&sfp->sf_tbytes, &tquad);
|
||||
sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
|
||||
fxdr_hyper(&sfp->sf_fbytes, &tquad);
|
||||
sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
|
||||
fxdr_hyper(&sfp->sf_abytes, &tquad);
|
||||
sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
|
||||
sbp->f_files = (fxdr_unsigned(long, sfp->sf_tfiles.nfsuquad[1])
|
||||
& 0x7fffffff);
|
||||
sbp->f_ffree = (fxdr_unsigned(long, sfp->sf_ffiles.nfsuquad[1])
|
||||
& 0x7fffffff);
|
||||
} else {
|
||||
sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize);
|
||||
sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
|
||||
sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
|
||||
sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
|
||||
sbp->f_files = 0;
|
||||
sbp->f_ffree = 0;
|
||||
}
|
||||
@ -161,11 +189,71 @@ nfs_statfs(mp, sbp, p)
|
||||
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
|
||||
}
|
||||
nfsm_reqdone;
|
||||
vrele(vp);
|
||||
vput(vp);
|
||||
crfree(cred);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* nfs version 3 fsinfo rpc call
|
||||
*/
|
||||
int
|
||||
nfs_fsinfo(nmp, vp, cred, p)
|
||||
register struct nfsmount *nmp;
|
||||
register struct vnode *vp;
|
||||
struct ucred *cred;
|
||||
struct proc *p;
|
||||
{
|
||||
register struct nfsv3_fsinfo *fsp;
|
||||
register caddr_t cp;
|
||||
register long t1, t2;
|
||||
register u_long *tl, pref, max;
|
||||
caddr_t bpos, dpos, cp2;
|
||||
int error = 0, retattr;
|
||||
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
|
||||
|
||||
nfsstats.rpccnt[NFSPROC_FSINFO]++;
|
||||
nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
|
||||
nfsm_fhtom(vp, 1);
|
||||
nfsm_request(vp, NFSPROC_FSINFO, p, cred);
|
||||
nfsm_postop_attr(vp, retattr);
|
||||
if (!error) {
|
||||
nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
|
||||
pref = fxdr_unsigned(u_long, fsp->fs_wtpref);
|
||||
if (pref < nmp->nm_wsize)
|
||||
nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
|
||||
~(NFS_FABLKSIZE - 1);
|
||||
max = fxdr_unsigned(u_long, fsp->fs_wtmax);
|
||||
if (max < nmp->nm_wsize) {
|
||||
nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
|
||||
if (nmp->nm_wsize == 0)
|
||||
nmp->nm_wsize = max;
|
||||
}
|
||||
pref = fxdr_unsigned(u_long, fsp->fs_rtpref);
|
||||
if (pref < nmp->nm_rsize)
|
||||
nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
|
||||
~(NFS_FABLKSIZE - 1);
|
||||
max = fxdr_unsigned(u_long, fsp->fs_rtmax);
|
||||
if (max < nmp->nm_rsize) {
|
||||
nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
|
||||
if (nmp->nm_rsize == 0)
|
||||
nmp->nm_rsize = max;
|
||||
}
|
||||
pref = fxdr_unsigned(u_long, fsp->fs_dtpref);
|
||||
if (pref < nmp->nm_readdirsize)
|
||||
nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
|
||||
~(NFS_DIRBLKSIZ - 1);
|
||||
if (max < nmp->nm_readdirsize) {
|
||||
nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
|
||||
if (nmp->nm_readdirsize == 0)
|
||||
nmp->nm_readdirsize = max;
|
||||
}
|
||||
nmp->nm_flag |= NFSMNT_GOTFSINFO;
|
||||
}
|
||||
nfsm_reqdone;
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mount a remote root fs via. nfs. This depends on the info in the
|
||||
* nfs_diskless structure that has been filled in properly by some primary
|
||||
@ -268,7 +356,12 @@ nfs_mountroot()
|
||||
* Create a fake mount point just for the swap vnode so that the
|
||||
* swap file can be on a different server from the rootfs.
|
||||
*/
|
||||
nd->swap_args.fh = (nfsv2fh_t *)nd->swap_fh;
|
||||
nd->swap_args.fh = nd->swap_fh;
|
||||
/*
|
||||
* If using nfsv3_diskless, replace NFSX_V2FH with
|
||||
* nd->swap_fhsize.
|
||||
*/
|
||||
nd->swap_args.fhsize = NFSX_V2FH;
|
||||
l = ntohl(nd->swap_saddr.sin_addr.s_addr);
|
||||
sprintf(buf,"%ld.%ld.%ld.%ld:%s",
|
||||
(l >> 24) & 0xff, (l >> 16) & 0xff,
|
||||
@ -293,8 +386,12 @@ nfs_mountroot()
|
||||
/*
|
||||
* Create the rootfs mount point.
|
||||
*/
|
||||
nd->root_args.fh = (nfsv2fh_t *)nd->root_fh;
|
||||
l = ntohl(nd->root_saddr.sin_addr.s_addr);
|
||||
nd->root_args.fh = nd->root_fh;
|
||||
/*
|
||||
* If using nfsv3_diskless, replace NFSX_V2FH with nd->root_fhsize.
|
||||
*/
|
||||
nd->root_args.fhsize = NFSX_V2FH;
|
||||
l = ntohl(nd->swap_saddr.sin_addr.s_addr);
|
||||
sprintf(buf,"%ld.%ld.%ld.%ld:%s",
|
||||
(l >> 24) & 0xff, (l >> 16) & 0xff,
|
||||
(l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam);
|
||||
@ -304,7 +401,11 @@ nfs_mountroot()
|
||||
|
||||
if (vfs_lock(mp))
|
||||
panic("nfs_mountroot: vfs_lock");
|
||||
#if NetBSD >= 1994101
|
||||
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
|
||||
#else
|
||||
TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
|
||||
#endif
|
||||
mp->mnt_flag |= MNT_ROOTFS;
|
||||
mp->mnt_vnodecovered = NULLVP;
|
||||
vfs_unlock(mp);
|
||||
@ -386,12 +487,12 @@ nfs_mount(mp, path, data, ndp, p)
|
||||
struct vnode *vp;
|
||||
char pth[MNAMELEN], hst[MNAMELEN];
|
||||
u_int len;
|
||||
nfsv2fh_t nfh;
|
||||
u_char nfh[NFSX_V3FHMAX];
|
||||
|
||||
error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
|
||||
if (error)
|
||||
return (error);
|
||||
error = copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t));
|
||||
error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
|
||||
if (error)
|
||||
return (error);
|
||||
error = copyinstr(path, pth, MNAMELEN-1, &len);
|
||||
@ -406,7 +507,7 @@ nfs_mount(mp, path, data, ndp, p)
|
||||
error = sockargs(&nam, (caddr_t)args.addr, args.addrlen, MT_SONAME);
|
||||
if (error)
|
||||
return (error);
|
||||
args.fh = &nfh;
|
||||
args.fh = nfh;
|
||||
error = mountnfs(&args, mp, nam, pth, hst, &vp);
|
||||
return (error);
|
||||
}
|
||||
@ -424,7 +525,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
|
||||
{
|
||||
register struct nfsmount *nmp;
|
||||
struct nfsnode *np;
|
||||
int error;
|
||||
int error, maxio;
|
||||
|
||||
if (mp->mnt_flag & MNT_UPDATE) {
|
||||
nmp = VFSTONFS(mp);
|
||||
@ -435,16 +536,12 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
|
||||
MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount),
|
||||
M_NFSMNT, M_WAITOK);
|
||||
bzero((caddr_t)nmp, sizeof (struct nfsmount));
|
||||
TAILQ_INIT(&nmp->nm_uidlruhead);
|
||||
mp->mnt_data = (qaddr_t)nmp;
|
||||
}
|
||||
getnewfsid(mp, MOUNT_NFS);
|
||||
nmp->nm_mountp = mp;
|
||||
nmp->nm_flag = argp->flags;
|
||||
if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_MYWRITE)) ==
|
||||
(NFSMNT_NQNFS | NFSMNT_MYWRITE)) {
|
||||
error = EPERM;
|
||||
goto bad;
|
||||
}
|
||||
if (nmp->nm_flag & NFSMNT_NQNFS)
|
||||
/*
|
||||
* We have to set mnt_maxsymlink to a non-zero value so
|
||||
@ -457,14 +554,24 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
|
||||
nmp->nm_retry = NFS_RETRANS;
|
||||
nmp->nm_wsize = NFS_WSIZE;
|
||||
nmp->nm_rsize = NFS_RSIZE;
|
||||
nmp->nm_readdirsize = NFS_READDIRSIZE;
|
||||
nmp->nm_numgrps = NFS_MAXGRPS;
|
||||
nmp->nm_readahead = NFS_DEFRAHEAD;
|
||||
nmp->nm_leaseterm = NQ_DEFLEASE;
|
||||
nmp->nm_deadthresh = NQ_DEADTHRESH;
|
||||
CIRCLEQ_INIT(&nmp->nm_timerhead);
|
||||
nmp->nm_inprog = NULLVP;
|
||||
bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t));
|
||||
nmp->nm_fhsize = argp->fhsize;
|
||||
bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
|
||||
#ifdef __NetBSD__
|
||||
#ifdef COMPAT_09
|
||||
mp->mnt_stat.f_type = 2;
|
||||
#else
|
||||
mp->mnt_stat.f_type = 0;
|
||||
#endif
|
||||
#else
|
||||
mp->mnt_stat.f_type = MOUNT_NFS;
|
||||
#endif
|
||||
bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
|
||||
bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
|
||||
nmp->nm_nam = nam;
|
||||
@ -483,29 +590,48 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
|
||||
nmp->nm_retry = NFS_MAXREXMIT;
|
||||
}
|
||||
|
||||
if (argp->flags & NFSMNT_NFSV3) {
|
||||
if (argp->sotype == SOCK_DGRAM)
|
||||
maxio = NFS_MAXDGRAMDATA;
|
||||
else
|
||||
maxio = NFS_MAXDATA;
|
||||
} else
|
||||
maxio = NFS_V2MAXDATA;
|
||||
|
||||
if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
|
||||
nmp->nm_wsize = argp->wsize;
|
||||
/* Round down to multiple of blocksize */
|
||||
nmp->nm_wsize &= ~0x1ff;
|
||||
nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
|
||||
if (nmp->nm_wsize <= 0)
|
||||
nmp->nm_wsize = 512;
|
||||
else if (nmp->nm_wsize > NFS_MAXDATA)
|
||||
nmp->nm_wsize = NFS_MAXDATA;
|
||||
nmp->nm_wsize = NFS_FABLKSIZE;
|
||||
}
|
||||
if (nmp->nm_wsize > maxio)
|
||||
nmp->nm_wsize = maxio;
|
||||
if (nmp->nm_wsize > MAXBSIZE)
|
||||
nmp->nm_wsize = MAXBSIZE;
|
||||
|
||||
if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
|
||||
nmp->nm_rsize = argp->rsize;
|
||||
/* Round down to multiple of blocksize */
|
||||
nmp->nm_rsize &= ~0x1ff;
|
||||
nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
|
||||
if (nmp->nm_rsize <= 0)
|
||||
nmp->nm_rsize = 512;
|
||||
else if (nmp->nm_rsize > NFS_MAXDATA)
|
||||
nmp->nm_rsize = NFS_MAXDATA;
|
||||
nmp->nm_rsize = NFS_FABLKSIZE;
|
||||
}
|
||||
if (nmp->nm_rsize > maxio)
|
||||
nmp->nm_rsize = maxio;
|
||||
if (nmp->nm_rsize > MAXBSIZE)
|
||||
nmp->nm_rsize = MAXBSIZE;
|
||||
|
||||
if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
|
||||
nmp->nm_readdirsize = argp->readdirsize;
|
||||
/* Round down to multiple of blocksize */
|
||||
nmp->nm_readdirsize &= ~(NFS_DIRBLKSIZ - 1);
|
||||
if (nmp->nm_readdirsize < NFS_DIRBLKSIZ)
|
||||
nmp->nm_readdirsize = NFS_DIRBLKSIZ;
|
||||
}
|
||||
if (nmp->nm_readdirsize > maxio)
|
||||
nmp->nm_readdirsize = maxio;
|
||||
|
||||
if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 &&
|
||||
argp->maxgrouplist <= NFS_MAXGRPS)
|
||||
nmp->nm_numgrps = argp->maxgrouplist;
|
||||
@ -536,7 +662,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
|
||||
* stuck on a dead server and we are holding a lock on the mount
|
||||
* point.
|
||||
*/
|
||||
mp->mnt_stat.f_iosize = NFS_MAXDGRAMDATA;
|
||||
mp->mnt_stat.f_iosize = min(nmp->nm_rsize, nmp->nm_wsize);
|
||||
/*
|
||||
* A reference count is needed on the nfsnode representing the
|
||||
* remote root. If this object is not persistent, then backward
|
||||
@ -545,11 +671,16 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
|
||||
* this problem, because one can identify root inodes by their
|
||||
* number == ROOTINO (2).
|
||||
*/
|
||||
error = nfs_nget(mp, &nmp->nm_fh, &np);
|
||||
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
|
||||
if (error)
|
||||
goto bad;
|
||||
*vpp = NFSTOV(np);
|
||||
|
||||
/*
|
||||
* Lose the lock but keep the ref.
|
||||
*/
|
||||
VOP_UNLOCK(*vpp);
|
||||
|
||||
return (0);
|
||||
bad:
|
||||
nfs_disconnect(nmp);
|
||||
@ -592,7 +723,7 @@ nfs_unmount(mp, mntflags, p)
|
||||
* the remote root. See comment in mountnfs(). The VFS unmount()
|
||||
* has done vput on this vnode, otherwise we would get deadlock!
|
||||
*/
|
||||
error = nfs_nget(mp, &nmp->nm_fh, &np);
|
||||
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
|
||||
if (error)
|
||||
return(error);
|
||||
vp = NFSTOV(np);
|
||||
@ -622,9 +753,9 @@ nfs_unmount(mp, mntflags, p)
|
||||
nmp->nm_flag |= NFSMNT_DISMNT;
|
||||
|
||||
/*
|
||||
* There are two reference counts to get rid of here.
|
||||
* There are two reference counts and one lock to get rid of here.
|
||||
*/
|
||||
vrele(vp);
|
||||
vput(vp);
|
||||
vrele(vp);
|
||||
vgone(vp);
|
||||
nfs_disconnect(nmp);
|
||||
@ -649,10 +780,11 @@ nfs_root(mp, vpp)
|
||||
int error;
|
||||
|
||||
nmp = VFSTONFS(mp);
|
||||
error = nfs_nget(mp, &nmp->nm_fh, &np);
|
||||
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
|
||||
if (error)
|
||||
return (error);
|
||||
vp = NFSTOV(np);
|
||||
VOP_UNLOCK(vp);
|
||||
vp->v_type = VDIR;
|
||||
vp->v_flag = VROOT;
|
||||
*vpp = vp;
|
||||
|
2362
sys/nfs/nfs_vnops.c
2362
sys/nfs/nfs_vnops.c
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsdiskless.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfsdiskless.h,v 1.3 1994/08/05 09:28:49 davidg Exp $
|
||||
* $Id: nfsdiskless.h,v 1.4 1994/08/21 06:50:09 paul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSDISKLESS_H_
|
||||
@ -52,17 +52,45 @@
|
||||
* NB: All fields are stored in net byte order to avoid hassles with
|
||||
* client/server byte ordering differences.
|
||||
*/
|
||||
struct nfs_diskless {
|
||||
|
||||
/*
|
||||
* I have defined a new structure that can handle an NFS Version 3 file handle
|
||||
* but the kernel still expects the old Version 2 one to be provided. The
|
||||
* changes required in nfs_vfsops.c for using the new are documented there in
|
||||
* comments. (I felt that breaking network booting code by changing this
|
||||
* structure would not be prudent at this time, since almost all servers are
|
||||
* still Version 2 anyhow.)
|
||||
*/
|
||||
struct nfsv3_diskless {
|
||||
struct ifaliasreq myif; /* Default interface */
|
||||
struct sockaddr_in mygateway; /* Default gateway */
|
||||
struct nfs_args swap_args; /* Mount args for swap file */
|
||||
u_char swap_fh[NFS_FHSIZE]; /* Swap file's file handle */
|
||||
int swap_fhsize; /* Size of file handle */
|
||||
u_char swap_fh[NFSX_V3FHMAX]; /* Swap file's file handle */
|
||||
struct sockaddr_in swap_saddr; /* Address of swap server */
|
||||
char swap_hostnam[MNAMELEN]; /* Host name for mount pt */
|
||||
int swap_nblks; /* Size of server swap file */
|
||||
struct ucred swap_ucred; /* Swap credentials */
|
||||
struct nfs_args root_args; /* Mount args for root fs */
|
||||
u_char root_fh[NFS_FHSIZE]; /* File handle of root dir */
|
||||
int root_fhsize; /* Size of root file handle */
|
||||
u_char root_fh[NFSX_V3FHMAX]; /* File handle of root dir */
|
||||
struct sockaddr_in root_saddr; /* Address of root server */
|
||||
char root_hostnam[MNAMELEN]; /* Host name for mount pt */
|
||||
long root_time; /* Timestamp of root fs */
|
||||
char my_hostnam[MAXHOSTNAMELEN]; /* Client host name */
|
||||
};
|
||||
|
||||
struct nfs_diskless {
|
||||
struct ifaliasreq myif; /* Default interface */
|
||||
struct sockaddr_in mygateway; /* Default gateway */
|
||||
struct nfs_args swap_args; /* Mount args for swap file */
|
||||
u_char swap_fh[NFSX_V2FH]; /* Swap file's file handle */
|
||||
struct sockaddr_in swap_saddr; /* Address of swap server */
|
||||
char swap_hostnam[MNAMELEN]; /* Host name for mount pt */
|
||||
int swap_nblks; /* Size of server swap file */
|
||||
struct ucred swap_ucred; /* Swap credentials */
|
||||
struct nfs_args root_args; /* Mount args for root fs */
|
||||
u_char root_fh[NFSX_V2FH]; /* File handle of root dir */
|
||||
struct sockaddr_in root_saddr; /* Address of root server */
|
||||
char root_hostnam[MNAMELEN]; /* Host name for mount pt */
|
||||
long root_time; /* Timestamp of root fs */
|
||||
|
@ -34,12 +34,13 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsm_subs.h 8.1 (Berkeley) 6/16/93
|
||||
* $Id: nfsm_subs.h,v 1.5 1994/10/17 17:47:42 phk Exp $
|
||||
* $Id: nfsm_subs.h,v 1.6 1995/05/30 08:12:51 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSM_SUBS_H_
|
||||
#define _NFS_NFSM_SUBS_H_
|
||||
|
||||
|
||||
/*
|
||||
* These macros do strange and peculiar things to mbuf chains for
|
||||
* the assistance of the nfs code. To attempt to use them for any
|
||||
@ -90,49 +91,153 @@ extern struct mbuf *nfsm_reqh();
|
||||
mb->m_len += (s); \
|
||||
bpos += (s); }
|
||||
|
||||
#define nfsm_dissect(a,c,s) \
|
||||
#define nfsm_dissect(a, c, s) \
|
||||
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
|
||||
if (t1 >= (s)) { \
|
||||
(a) = (c)(dpos); \
|
||||
dpos += (s); \
|
||||
} else if (t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} else { \
|
||||
error = nfsm_disct(&md, &dpos, (s), t1, &cp2); \
|
||||
if (error) { \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} else { \
|
||||
(a) = (c)cp2; \
|
||||
} \
|
||||
(a) = (c)cp2; \
|
||||
} }
|
||||
|
||||
#define nfsm_fhtom(v) \
|
||||
nfsm_build(cp,caddr_t,NFSX_FH); \
|
||||
bcopy((caddr_t)&(VTONFS(v)->n_fh), cp, NFSX_FH)
|
||||
#define nfsm_fhtom(v, v3) \
|
||||
{ if (v3) { \
|
||||
t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \
|
||||
if (t2 <= M_TRAILINGSPACE(mb)) { \
|
||||
nfsm_build(tl, u_long *, t2); \
|
||||
*tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \
|
||||
*(tl + ((t2>>2) - 2)) = 0; \
|
||||
bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \
|
||||
VTONFS(v)->n_fhsize); \
|
||||
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, \
|
||||
(caddr_t)VTONFS(v)->n_fhp, VTONFS(v)->n_fhsize)) { \
|
||||
error = t2; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
} else { \
|
||||
nfsm_build(cp, caddr_t, NFSX_V2FH); \
|
||||
bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \
|
||||
} }
|
||||
|
||||
#define nfsm_srvfhtom(f) \
|
||||
nfsm_build(cp,caddr_t,NFSX_FH); \
|
||||
bcopy((caddr_t)(f), cp, NFSX_FH)
|
||||
#define nfsm_srvfhtom(f, v3) \
|
||||
{ if (v3) { \
|
||||
nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FH); \
|
||||
*tl++ = txdr_unsigned(NFSX_V3FH); \
|
||||
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
|
||||
} else { \
|
||||
nfsm_build(cp, caddr_t, NFSX_V2FH); \
|
||||
bcopy((caddr_t)(f), cp, NFSX_V2FH); \
|
||||
} }
|
||||
|
||||
#define nfsm_mtofh(d,v) \
|
||||
{ struct nfsnode *np; nfsv2fh_t *fhp; \
|
||||
nfsm_dissect(fhp,nfsv2fh_t *,NFSX_FH); \
|
||||
error = nfs_nget((d)->v_mount, fhp, &np); \
|
||||
if (error) { \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = NFSTOV(np); \
|
||||
nfsm_loadattr(v, (struct vattr *)0); \
|
||||
#define nfsm_srvpostop_fh(f) \
|
||||
{ nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \
|
||||
*tl++ = nfs_true; \
|
||||
*tl++ = txdr_unsigned(NFSX_V3FH); \
|
||||
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
|
||||
}
|
||||
|
||||
#define nfsm_loadattr(v,a) \
|
||||
{ struct vnode *tvp = (v); \
|
||||
error = nfs_loadattrcache(&tvp, &md, &dpos, (a)); \
|
||||
if (error) { \
|
||||
#define nfsm_mtofh(d, v, v3, f) \
|
||||
{ struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \
|
||||
if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(f) = fxdr_unsigned(int, *tl); \
|
||||
} else \
|
||||
(f) = 1; \
|
||||
if (f) { \
|
||||
nfsm_getfh(ttfhp, ttfhsize, (v3)); \
|
||||
if (t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \
|
||||
&ttnp)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = NFSTOV(ttnp); \
|
||||
} \
|
||||
if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (f) \
|
||||
(f) = fxdr_unsigned(int, *tl); \
|
||||
else if (fxdr_unsigned(int, *tl)) \
|
||||
nfsm_adv(NFSX_V3FATTR); \
|
||||
} \
|
||||
if (f) \
|
||||
nfsm_loadattr((v), (struct vattr *)0); \
|
||||
}
|
||||
|
||||
#define nfsm_getfh(f, s, v3) \
|
||||
{ if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \
|
||||
(s) > NFSX_V3FHMAX) { \
|
||||
m_freem(mrep); \
|
||||
error = EBADRPC; \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
} else \
|
||||
(s) = NFSX_V2FH; \
|
||||
nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); }
|
||||
|
||||
#define nfsm_loadattr(v, a) \
|
||||
{ struct vnode *ttvp = (v); \
|
||||
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a))) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = tvp; }
|
||||
(v) = ttvp; }
|
||||
|
||||
#define nfsm_postop_attr(v, f) \
|
||||
{ struct vnode *ttvp = (v); \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if ((f) = fxdr_unsigned(int, *tl)) { \
|
||||
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
|
||||
(struct vattr *)0)) { \
|
||||
error = t1; \
|
||||
(f) = 0; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = ttvp; \
|
||||
} }
|
||||
|
||||
/* Used as (f) for nfsm_wcc_data() */
|
||||
#define NFSV3_WCCRATTR 0
|
||||
#define NFSV3_WCCCHK 1
|
||||
|
||||
#define nfsm_wcc_data(v, f) \
|
||||
{ int ttattrf, ttretf = 0; \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, 6 * NFSX_UNSIGNED); \
|
||||
if (f) \
|
||||
ttretf = (VTONFS(v)->n_mtime == \
|
||||
fxdr_unsigned(u_long, *(tl + 2))); \
|
||||
} \
|
||||
nfsm_postop_attr((v), ttattrf); \
|
||||
if (f) { \
|
||||
(f) = ttretf; \
|
||||
} else { \
|
||||
(f) = ttattrf; \
|
||||
} }
|
||||
|
||||
#define nfsm_v3sattr(s, a, u, g) \
|
||||
{ (s)->sa_modetrue = nfs_true; \
|
||||
(s)->sa_mode = vtonfsv3_mode((a)->va_mode); \
|
||||
(s)->sa_uidtrue = nfs_true; \
|
||||
(s)->sa_uid = txdr_unsigned(u); \
|
||||
(s)->sa_gidtrue = nfs_true; \
|
||||
(s)->sa_gid = txdr_unsigned(g); \
|
||||
(s)->sa_sizefalse = nfs_false; \
|
||||
(s)->sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
|
||||
txdr_nfsv3time(&(a)->va_atime, &(s)->sa_atime); \
|
||||
(s)->sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
|
||||
txdr_nfsv3time(&(a)->va_mtime, &(s)->sa_mtime); \
|
||||
}
|
||||
|
||||
#define nfsm_strsiz(s,m) \
|
||||
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
|
||||
@ -149,16 +254,27 @@ extern struct mbuf *nfsm_reqh();
|
||||
nfsm_reply(0); \
|
||||
} }
|
||||
|
||||
#define nfsm_srvnamesiz(s) \
|
||||
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
|
||||
if (((s) = fxdr_unsigned(long,*tl)) > NFS_MAXNAMLEN) \
|
||||
error = NFSERR_NAMETOL; \
|
||||
if ((s) <= 0) \
|
||||
error = EBADRPC; \
|
||||
if (error) \
|
||||
nfsm_reply(0); \
|
||||
}
|
||||
|
||||
#define nfsm_mtouio(p,s) \
|
||||
if ((s) > 0 && \
|
||||
(error = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
|
||||
(t1 = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_uiotom(p,s) \
|
||||
error = nfsm_uiotombuf((p),&mb,(s),&bpos); \
|
||||
if (error) { \
|
||||
if (t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) { \
|
||||
error = t1; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
@ -172,10 +288,13 @@ extern struct mbuf *nfsm_reqh();
|
||||
#define nfsm_rndup(a) (((a)+3)&(~0x3))
|
||||
|
||||
#define nfsm_request(v, t, p, c) \
|
||||
error = nfs_request((v), mreq, (t), (p), \
|
||||
(c), &mrep, &md, &dpos); \
|
||||
if (error) \
|
||||
goto nfsmout
|
||||
if (error = nfs_request((v), mreq, (t), (p), \
|
||||
(c), &mrep, &md, &dpos)) { \
|
||||
if (error & NFSERR_RETERR) \
|
||||
error &= ~NFSERR_RETERR; \
|
||||
else \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_strtom(a,s,m) \
|
||||
if ((s) > (m)) { \
|
||||
@ -189,12 +308,10 @@ extern struct mbuf *nfsm_reqh();
|
||||
*tl++ = txdr_unsigned(s); \
|
||||
*(tl+((t2>>2)-2)) = 0; \
|
||||
bcopy((caddr_t)(a), (caddr_t)tl, (s)); \
|
||||
} else { \
|
||||
error = nfsm_strtmbuf(&mb, &bpos, (a), (s)); \
|
||||
if (error) { \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) { \
|
||||
error = t2; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_srvdone \
|
||||
@ -204,33 +321,53 @@ extern struct mbuf *nfsm_reqh();
|
||||
#define nfsm_reply(s) \
|
||||
{ \
|
||||
nfsd->nd_repstat = error; \
|
||||
if (error) \
|
||||
(void) nfs_rephead(0, nfsd, error, cache, &frev, \
|
||||
if (error && !(nfsd->nd_flag & ND_NFSV3)) \
|
||||
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
|
||||
mrq, &mb, &bpos); \
|
||||
else \
|
||||
(void) nfs_rephead((s), nfsd, error, cache, &frev, \
|
||||
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
|
||||
mrq, &mb, &bpos); \
|
||||
m_freem(mrep); \
|
||||
mreq = *mrq; \
|
||||
if (error) \
|
||||
if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
|
||||
error == EBADRPC)) \
|
||||
return(0); \
|
||||
}
|
||||
|
||||
#define nfsm_adv(s) \
|
||||
t1 = mtod(md, caddr_t)+md->m_len-dpos; \
|
||||
if (t1 >= (s)) { \
|
||||
dpos += (s); \
|
||||
} else { \
|
||||
error = nfs_adv(&md, &dpos, (s), t1); \
|
||||
if (error) { \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
#define nfsm_writereply(s, v3) \
|
||||
{ \
|
||||
nfsd->nd_repstat = error; \
|
||||
if (error && !(v3)) \
|
||||
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
|
||||
&mreq, &mb, &bpos); \
|
||||
else \
|
||||
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
|
||||
&mreq, &mb, &bpos); \
|
||||
}
|
||||
|
||||
#define nfsm_adv(s) \
|
||||
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
|
||||
if (t1 >= (s)) { \
|
||||
dpos += (s); \
|
||||
} else if (t1 = nfs_adv(&md, &dpos, (s), t1)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} }
|
||||
|
||||
#define nfsm_srvmtofh(f) \
|
||||
nfsm_dissect(tl, u_long *, NFSX_FH); \
|
||||
bcopy((caddr_t)tl, (caddr_t)f, NFSX_FH)
|
||||
{ if (nfsd->nd_flag & ND_NFSV3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \
|
||||
error = EBADRPC; \
|
||||
nfsm_reply(0); \
|
||||
} \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
|
||||
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
|
||||
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
|
||||
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
|
||||
}
|
||||
|
||||
#define nfsm_clget \
|
||||
if (bp >= be) { \
|
||||
@ -246,41 +383,57 @@ extern struct mbuf *nfsm_reqh();
|
||||
} \
|
||||
tl = (u_long *)bp
|
||||
|
||||
#define nfsm_srvfillattr \
|
||||
fp->fa_type = vtonfs_type(vap->va_type); \
|
||||
fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); \
|
||||
fp->fa_nlink = txdr_unsigned(vap->va_nlink); \
|
||||
fp->fa_uid = txdr_unsigned(vap->va_uid); \
|
||||
fp->fa_gid = txdr_unsigned(vap->va_gid); \
|
||||
if (nfsd->nd_nqlflag == NQL_NOVAL) { \
|
||||
fp->fa_nfsblocksize = txdr_unsigned(vap->va_blocksize); \
|
||||
if (vap->va_type == VFIFO) \
|
||||
fp->fa_nfsrdev = 0xffffffff; \
|
||||
else \
|
||||
fp->fa_nfsrdev = txdr_unsigned(vap->va_rdev); \
|
||||
fp->fa_nfsfsid = txdr_unsigned(vap->va_fsid); \
|
||||
fp->fa_nfsfileid = txdr_unsigned(vap->va_fileid); \
|
||||
fp->fa_nfssize = txdr_unsigned(vap->va_size); \
|
||||
fp->fa_nfsblocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); \
|
||||
txdr_nfstime(&vap->va_atime, &fp->fa_nfsatime); \
|
||||
txdr_nfstime(&vap->va_mtime, &fp->fa_nfsmtime); \
|
||||
txdr_nfstime(&vap->va_ctime, &fp->fa_nfsctime); \
|
||||
} else { \
|
||||
fp->fa_nqblocksize = txdr_unsigned(vap->va_blocksize); \
|
||||
if (vap->va_type == VFIFO) \
|
||||
fp->fa_nqrdev = 0xffffffff; \
|
||||
else \
|
||||
fp->fa_nqrdev = txdr_unsigned(vap->va_rdev); \
|
||||
fp->fa_nqfsid = txdr_unsigned(vap->va_fsid); \
|
||||
fp->fa_nqfileid = txdr_unsigned(vap->va_fileid); \
|
||||
txdr_hyper(&vap->va_size, &fp->fa_nqsize); \
|
||||
txdr_hyper(&vap->va_bytes, &fp->fa_nqbytes); \
|
||||
txdr_nqtime(&vap->va_atime, &fp->fa_nqatime); \
|
||||
txdr_nqtime(&vap->va_mtime, &fp->fa_nqmtime); \
|
||||
txdr_nqtime(&vap->va_ctime, &fp->fa_nqctime); \
|
||||
fp->fa_nqflags = txdr_unsigned(vap->va_flags); \
|
||||
fp->fa_nqgen = txdr_unsigned(vap->va_gen); \
|
||||
txdr_hyper(&vap->va_filerev, &fp->fa_nqfilerev); \
|
||||
}
|
||||
#define nfsm_srvfillattr(a, f) \
|
||||
nfsm_srvfattr(nfsd, (a), (f))
|
||||
|
||||
#define nfsm_srvwcc_data(br, b, ar, a) \
|
||||
nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos)
|
||||
|
||||
#define nfsm_srvpostop_attr(r, a) \
|
||||
nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos)
|
||||
|
||||
#define nfsm_srvsattr(a) \
|
||||
{ nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_mode = nfstov_mode(*tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_uid = fxdr_unsigned(uid_t, *tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_gid = fxdr_unsigned(gid_t, *tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_hyper(tl, &(a)->va_size); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
switch (fxdr_unsigned(int, *tl)) { \
|
||||
case NFSV3SATTRTIME_TOCLIENT: \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_nfsv3time(tl, &(a)->va_atime); \
|
||||
break; \
|
||||
case NFSV3SATTRTIME_TOSERVER: \
|
||||
(a)->va_atime.ts_sec = time.tv_sec; \
|
||||
(a)->va_atime.ts_nsec = time.tv_usec * 1000; \
|
||||
break; \
|
||||
}; \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
switch (fxdr_unsigned(int, *tl)) { \
|
||||
case NFSV3SATTRTIME_TOCLIENT: \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_nfsv3time(tl, &(a)->va_mtime); \
|
||||
break; \
|
||||
case NFSV3SATTRTIME_TOSERVER: \
|
||||
(a)->va_mtime.ts_sec = time.tv_sec; \
|
||||
(a)->va_mtime.ts_nsec = time.tv_usec * 1000; \
|
||||
break; \
|
||||
}; }
|
||||
|
||||
#endif
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsmount.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfsmount.h,v 1.3 1994/08/21 06:50:10 paul Exp $
|
||||
* $Id: nfsmount.h,v 1.4 1994/10/17 17:47:43 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSMOUNT_H_
|
||||
@ -49,7 +49,8 @@ struct nfsmount {
|
||||
int nm_flag; /* Flags for soft/hard... */
|
||||
struct mount *nm_mountp; /* Vfs structure for this filesystem */
|
||||
int nm_numgrps; /* Max. size of groupslist */
|
||||
nfsv2fh_t nm_fh; /* File handle of root dir */
|
||||
u_char nm_fh[NFSX_V3FHMAX]; /* File handle of root dir */
|
||||
int nm_fhsize; /* Size of root file handle */
|
||||
struct socket *nm_so; /* Rpc socket */
|
||||
int nm_sotype; /* Type of socket */
|
||||
int nm_soproto; /* and protocol */
|
||||
@ -65,6 +66,7 @@ struct nfsmount {
|
||||
int nm_deadthresh; /* Threshold of timeouts-->dead server*/
|
||||
int nm_rsize; /* Max size of read rpc */
|
||||
int nm_wsize; /* Max size of write rpc */
|
||||
int nm_readdirsize; /* Size of a readdir rpc */
|
||||
int nm_readahead; /* Num. of blocks to readahead */
|
||||
int nm_leaseterm; /* Term (sec) for NQNFS lease */
|
||||
CIRCLEQ_HEAD(, nfsnode) nm_timerhead; /* Head of lease timer queue */
|
||||
@ -73,9 +75,16 @@ struct nfsmount {
|
||||
int nm_authtype; /* Authenticator type */
|
||||
int nm_authlen; /* and length */
|
||||
char *nm_authstr; /* Authenticator string */
|
||||
char *nm_verfstr; /* and the verifier */
|
||||
int nm_verflen;
|
||||
u_char nm_verf[NFSX_V3WRITEVERF]; /* V3 write verifier */
|
||||
NFSKERBKEY_T nm_key; /* and the session key */
|
||||
int nm_numuids; /* Number of nfsuid mappings */
|
||||
TAILQ_HEAD(, nfsuid) nm_uidlruhead; /* Lists of nfsuid mappings */
|
||||
LIST_HEAD(, nfsuid) nm_uidhashtbl[NFS_MUIDHASHSIZ];
|
||||
};
|
||||
|
||||
#ifdef KERNEL
|
||||
#if defined(KERNEL) || defined(_KERNEL)
|
||||
/*
|
||||
* Convert mount ptr to nfsmount ptr.
|
||||
*/
|
||||
|
@ -34,12 +34,16 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsnode.h 8.4 (Berkeley) 2/13/94
|
||||
* $Id: nfsnode.h,v 1.8 1994/10/17 17:47:44 phk Exp $
|
||||
* $Id: nfsnode.h,v 1.9 1995/03/16 18:15:42 bde Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSNODE_H_
|
||||
#define _NFS_NFSNODE_H_
|
||||
|
||||
#ifndef _NFS_NFS_H_
|
||||
#include <nfs/nfs.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Silly rename structure that hangs off the nfsnode until the name
|
||||
* can be removed by nfs_inactive()
|
||||
@ -51,37 +55,74 @@ struct sillyrename {
|
||||
char s_name[20];
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure is used to save the logical directory offset to
|
||||
* NFS cookie mappings.
|
||||
* The mappings are stored in a list headed
|
||||
* by n_cookies, as required.
|
||||
* There is one mapping for each NFS_DIRBLKSIZ bytes of directory information
|
||||
* stored in increasing logical offset byte order.
|
||||
*/
|
||||
#define NFSNUMCOOKIES 31
|
||||
|
||||
struct nfsdmap {
|
||||
LIST_ENTRY(nfsdmap) ndm_list;
|
||||
int ndm_eocookie;
|
||||
nfsuint64 ndm_cookies[NFSNUMCOOKIES];
|
||||
};
|
||||
|
||||
/*
|
||||
* The nfsnode is the nfs equivalent to ufs's inode. Any similarity
|
||||
* is purely coincidental.
|
||||
* There is a unique nfsnode allocated for each active file,
|
||||
* each current directory, each mounted-on file, text file, and the root.
|
||||
* An nfsnode is 'named' by its file handle. (nget/nfs_node.c)
|
||||
* If this structure exceeds 256 bytes (it is currently 256 using 4.4BSD-Lite
|
||||
* type definitions), file handles of > 32 bytes should probably be split out
|
||||
* into a separate MALLOC()'d data structure. (Reduce the size of nfsfh_t by
|
||||
* changing the definition in sys/mount.h of NFS_SMALLFH.)
|
||||
* NB: Hopefully the current order of the fields is such that everything will
|
||||
* be well aligned and, therefore, tightly packed.
|
||||
*/
|
||||
|
||||
struct nfsnode {
|
||||
LIST_ENTRY(nfsnode) n_hash; /* Hash chain */
|
||||
CIRCLEQ_ENTRY(nfsnode) n_timer; /* Nqnfs timer chain */
|
||||
nfsv2fh_t n_fh; /* NFS File Handle */
|
||||
long n_flag; /* Flag for locking.. */
|
||||
struct vnode *n_vnode; /* vnode associated with this node */
|
||||
struct vattr n_vattr; /* Vnode attribute cache */
|
||||
time_t n_attrstamp; /* Time stamp for cached attributes */
|
||||
struct sillyrename *n_sillyrename; /* Ptr to silly rename struct */
|
||||
u_quad_t n_size; /* Current size of file */
|
||||
struct lockf *n_lockf; /* Locking record of file */
|
||||
int n_error; /* Save write error value */
|
||||
u_long n_direofoffset; /* Dir. EOF offset cache */
|
||||
time_t n_mtime; /* Prev modify time. */
|
||||
time_t n_ctime; /* Prev create time. */
|
||||
u_quad_t n_brev; /* Modify rev when cached */
|
||||
u_quad_t n_lrev; /* Modify rev for lease */
|
||||
time_t n_expiry; /* Lease expiry time */
|
||||
struct sillyrename n_silly; /* Silly rename struct */
|
||||
struct timeval n_atim; /* Special file times */
|
||||
struct timeval n_mtim;
|
||||
LIST_ENTRY(nfsnode) n_hash; /* Hash chain */
|
||||
CIRCLEQ_ENTRY(nfsnode) n_timer; /* Nqnfs timer chain */
|
||||
u_quad_t n_size; /* Current size of file */
|
||||
u_quad_t n_brev; /* Modify rev when cached */
|
||||
u_quad_t n_lrev; /* Modify rev for lease */
|
||||
struct vattr n_vattr; /* Vnode attribute cache */
|
||||
time_t n_attrstamp; /* Attr. cache timestamp */
|
||||
time_t n_mtime; /* Prev modify time. */
|
||||
time_t n_ctime; /* Prev create time. */
|
||||
time_t n_expiry; /* Lease expiry time */
|
||||
nfsfh_t *n_fhp; /* NFS File Handle */
|
||||
struct vnode *n_vnode; /* associated vnode */
|
||||
struct lockf *n_lockf; /* Locking record of file */
|
||||
int n_error; /* Save write error value */
|
||||
union {
|
||||
struct timespec nf_atim; /* Special file times */
|
||||
nfsuint64 nd_cookieverf; /* Cookie verifier (dir only) */
|
||||
} n_un1;
|
||||
union {
|
||||
struct timespec nf_mtim;
|
||||
off_t nd_direof; /* Dir. EOF offset cache */
|
||||
} n_un2;
|
||||
union {
|
||||
struct sillyrename *nf_silly; /* Ptr to silly rename struct */
|
||||
LIST_HEAD(, nfsdmap) nd_cook; /* cookies */
|
||||
} n_un3;
|
||||
short n_fhsize; /* size in bytes, of fh */
|
||||
short n_flag; /* Flag for locking.. */
|
||||
nfsfh_t n_fh; /* Small File Handle */
|
||||
};
|
||||
|
||||
#define n_atim n_un1.nf_atim
|
||||
#define n_mtim n_un2.nf_mtim
|
||||
#define n_sillyrename n_un3.nf_silly
|
||||
#define n_cookieverf n_un1.nd_cookieverf
|
||||
#define n_direofoffset n_un2.nd_direof
|
||||
#define n_cookies n_un3.nd_cook
|
||||
|
||||
/*
|
||||
* Flags for n_flag
|
||||
*/
|
||||
@ -95,6 +136,8 @@ struct nfsnode {
|
||||
#define NACC 0x0100 /* Special file accessed */
|
||||
#define NUPD 0x0200 /* Special file updated */
|
||||
#define NCHG 0x0400 /* Special file times changed */
|
||||
#define NLOCKED 0x0800 /* node is locked */
|
||||
#define NWANTED 0x0100 /* someone wants to lock */
|
||||
|
||||
/*
|
||||
* Convert between nfsnode pointers and vnode pointers
|
||||
@ -107,7 +150,7 @@ struct nfsnode {
|
||||
*/
|
||||
TAILQ_HEAD(, buf) nfs_bufq;
|
||||
|
||||
#ifdef KERNEL
|
||||
#if defined(KERNEL) || defined(_KERNEL)
|
||||
extern int (**fifo_nfsv2nodeop_p)();
|
||||
extern int (**nfsv2_vnodeop_p)();
|
||||
extern int (**spec_nfsv2nodeop_p)();
|
||||
@ -128,12 +171,25 @@ int nfs_getattr __P((struct vop_getattr_args *));
|
||||
int nfs_setattr __P((struct vop_setattr_args *));
|
||||
int nfs_read __P((struct vop_read_args *));
|
||||
int nfs_write __P((struct vop_write_args *));
|
||||
#ifdef HAS_VOPLEASE
|
||||
#define nfs_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
|
||||
#define nqnfs_vop_lease_check lease_check
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
#define nqnfs_lease_check nfs_lease_check
|
||||
#else
|
||||
#define nqnfs_lease_check lease_check
|
||||
#endif
|
||||
#endif
|
||||
int nfsspec_read __P((struct vop_read_args *));
|
||||
int nfsspec_write __P((struct vop_write_args *));
|
||||
int nfsfifo_read __P((struct vop_read_args *));
|
||||
int nfsfifo_write __P((struct vop_write_args *));
|
||||
#define nfs_ioctl ((int (*) __P((struct vop_ioctl_args *)))enoioctl)
|
||||
#define nfs_select ((int (*) __P((struct vop_select_args *)))seltrue)
|
||||
#ifdef HAS_VOPREVOKE
|
||||
#define nfs_revoke vop_revoke
|
||||
#endif
|
||||
int nfs_mmap __P((struct vop_mmap_args *));
|
||||
int nfs_fsync __P((struct vop_fsync_args *));
|
||||
#define nfs_seek ((int (*) __P((struct vop_seek_args *)))nullop)
|
||||
@ -157,6 +213,7 @@ int nfs_islocked __P((struct vop_islocked_args *));
|
||||
int nfs_pathconf __P((struct vop_pathconf_args *));
|
||||
int nfs_advlock __P((struct vop_advlock_args *));
|
||||
int nfs_blkatoff __P((struct vop_blkatoff_args *));
|
||||
int nfs_bwrite __P((struct vop_bwrite_args *));
|
||||
int nfs_vget __P((struct mount *, ino_t, struct vnode **));
|
||||
int nfs_valloc __P((struct vop_valloc_args *));
|
||||
#define nfs_reallocblks \
|
||||
@ -164,13 +221,20 @@ int nfs_valloc __P((struct vop_valloc_args *));
|
||||
int nfs_vfree __P((struct vop_vfree_args *));
|
||||
int nfs_truncate __P((struct vop_truncate_args *));
|
||||
int nfs_update __P((struct vop_update_args *));
|
||||
int nfs_bwrite __P((struct vop_bwrite_args *));
|
||||
|
||||
/* other stuff */
|
||||
int nfs_removeit __P((struct sillyrename *));
|
||||
int nfs_nget __P((struct mount *,nfsv2fh_t *,struct nfsnode **));
|
||||
int nfs_lookitup __P((struct sillyrename *,nfsv2fh_t *,struct proc *));
|
||||
int nfs_nget __P((struct mount *,nfsfh_t *,int,struct nfsnode **));
|
||||
int nfs_lookitup __P((struct vnode *,char *,int,struct ucred *,struct proc *,struct nfsnode **));
|
||||
int nfs_sillyrename __P((struct vnode *,struct vnode *,struct componentname *));
|
||||
nfsuint64 *nfs_getcookie __P((struct nfsnode *, off_t, int));
|
||||
void nfs_invaldir __P((struct vnode *));
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define nqnfs_lease_updatetime nfs_lease_updatetime
|
||||
#else
|
||||
#define nqnfs_lease_updatetime lease_updatetime
|
||||
#endif
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
|
441
sys/nfs/nfsproto.h
Normal file
441
sys/nfs/nfsproto.h
Normal file
@ -0,0 +1,441 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsproto.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfsproto.h,v 1.4 1994/08/21 06:50:13 paul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSPROTO_H_
|
||||
#define _NFS_NFSPROTO_H_
|
||||
|
||||
/*
|
||||
* nfs definitions as per the Version 2 and 3 specs
|
||||
*/
|
||||
|
||||
/*
|
||||
* Constants as defined in the Sun NFS Version 2 and 3 specs.
|
||||
* "NFS: Network File System Protocol Specification" RFC1094
|
||||
* and in the "NFS: Network File System Version 3 Protocol
|
||||
* Specification"
|
||||
*/
|
||||
|
||||
#define NFS_PORT 2049
|
||||
#define NFS_PROG 100003
|
||||
#define NFS_VER2 2
|
||||
#define NFS_VER3 3
|
||||
#define NFS_V2MAXDATA 8192
|
||||
#define NFS_MAXDGRAMDATA 16384
|
||||
#define NFS_MAXDATA 32768
|
||||
#define NFS_MAXPATHLEN 1024
|
||||
#define NFS_MAXNAMLEN 255
|
||||
#define NFS_MAXPKTHDR 404
|
||||
#define NFS_MAXPACKET (NFS_MAXPKTHDR + NFS_MAXDATA)
|
||||
#define NFS_MINPACKET 20
|
||||
#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */
|
||||
|
||||
/* Stat numbers for rpc returns (version 2 and 3) */
|
||||
#define NFS_OK 0
|
||||
#define NFSERR_PERM 1
|
||||
#define NFSERR_NOENT 2
|
||||
#define NFSERR_IO 5
|
||||
#define NFSERR_NXIO 6
|
||||
#define NFSERR_ACCES 13
|
||||
#define NFSERR_EXIST 17
|
||||
#define NFSERR_XDEV 18 /* Version 3 only */
|
||||
#define NFSERR_NODEV 19
|
||||
#define NFSERR_NOTDIR 20
|
||||
#define NFSERR_ISDIR 21
|
||||
#define NFSERR_INVAL 22 /* Version 3 only */
|
||||
#define NFSERR_FBIG 27
|
||||
#define NFSERR_NOSPC 28
|
||||
#define NFSERR_ROFS 30
|
||||
#define NFSERR_MLINK 31 /* Version 3 only */
|
||||
#define NFSERR_NAMETOL 63
|
||||
#define NFSERR_NOTEMPTY 66
|
||||
#define NFSERR_DQUOT 69
|
||||
#define NFSERR_STALE 70
|
||||
#define NFSERR_REMOTE 71 /* Version 3 only */
|
||||
#define NFSERR_WFLUSH 99 /* Version 2 only */
|
||||
#define NFSERR_BADHANDLE 10001 /* The rest Version 3 only */
|
||||
#define NFSERR_NOT_SYNC 10002
|
||||
#define NFSERR_BAD_COOKIE 10003
|
||||
#define NFSERR_NOTSUPP 10004
|
||||
#define NFSERR_TOOSMALL 10005
|
||||
#define NFSERR_SERVERFAULT 10006
|
||||
#define NFSERR_BADTYPE 10007
|
||||
#define NFSERR_JUKEBOX 10008
|
||||
#define NFSERR_TRYLATER NFSERR_JUKEBOX
|
||||
#define NFSERR_STALEWRITEVERF 30001 /* Fake return for nfs_commit() */
|
||||
|
||||
#define NFSERR_RETVOID 0x20000000 /* Return void, not error */
|
||||
#define NFSERR_AUTHERR 0x40000000 /* Mark an authentication error */
|
||||
#define NFSERR_RETERR 0x80000000 /* Mark an error return for V3 */
|
||||
|
||||
/* Sizes in bytes of various nfs rpc components */
|
||||
#define NFSX_UNSIGNED 4
|
||||
|
||||
/* specific to NFS Version 2 */
|
||||
#define NFSX_V2FH 32
|
||||
#define NFSX_V2FATTR 68
|
||||
#define NFSX_V2SATTR 32
|
||||
#define NFSX_V2COOKIE 4
|
||||
#define NFSX_V2STATFS 20
|
||||
|
||||
/* specific to NFS Version 3 */
|
||||
#define NFSX_V3FH (sizeof (fhandle_t)) /* size this server uses */
|
||||
#define NFSX_V3FHMAX 64 /* max. allowed by protocol */
|
||||
#define NFSX_V3FATTR 84
|
||||
#define NFSX_V3SATTR 60 /* max. all fields filled in */
|
||||
#define NFSX_V3SRVSATTR (sizeof (struct nfsv3_sattr))
|
||||
#define NFSX_V3POSTOPATTR (NFSX_V3FATTR + NFSX_UNSIGNED)
|
||||
#define NFSX_V3WCCDATA (NFSX_V3POSTOPATTR + 8 * NFSX_UNSIGNED)
|
||||
#define NFSX_V3COOKIEVERF 8
|
||||
#define NFSX_V3WRITEVERF 8
|
||||
#define NFSX_V3CREATEVERF 8
|
||||
#define NFSX_V3STATFS 52
|
||||
#define NFSX_V3FSINFO 48
|
||||
#define NFSX_V3PATHCONF 24
|
||||
|
||||
/* variants for both versions */
|
||||
#define NFSX_FH(v3) ((v3) ? (NFSX_V3FHMAX + NFSX_UNSIGNED) : \
|
||||
NFSX_V2FH)
|
||||
#define NFSX_SRVFH(v3) ((v3) ? NFSX_V3FH : NFSX_V2FH)
|
||||
#define NFSX_FATTR(v3) ((v3) ? NFSX_V3FATTR : NFSX_V2FATTR)
|
||||
#define NFSX_PREOPATTR(v3) ((v3) ? (7 * NFSX_UNSIGNED) : 0)
|
||||
#define NFSX_POSTOPATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : 0)
|
||||
#define NFSX_POSTOPORFATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : \
|
||||
NFSX_V2FATTR)
|
||||
#define NFSX_WCCDATA(v3) ((v3) ? NFSX_V3WCCDATA : 0)
|
||||
#define NFSX_WCCORFATTR(v3) ((v3) ? NFSX_V3WCCDATA : NFSX_V2FATTR)
|
||||
#define NFSX_SATTR(v3) ((v3) ? NFSX_V3SATTR : NFSX_V2SATTR)
|
||||
#define NFSX_COOKIEVERF(v3) ((v3) ? NFSX_V3COOKIEVERF : 0)
|
||||
#define NFSX_WRITEVERF(v3) ((v3) ? NFSX_V3WRITEVERF : 0)
|
||||
#define NFSX_READDIR(v3) ((v3) ? (5 * NFSX_UNSIGNED) : \
|
||||
(2 * NFSX_UNSIGNED))
|
||||
#define NFSX_STATFS(v3) ((v3) ? NFSX_V3STATFS : NFSX_V2STATFS)
|
||||
|
||||
/* nfs rpc procedure numbers (before version mapping) */
|
||||
#define NFSPROC_NULL 0
|
||||
#define NFSPROC_GETATTR 1
|
||||
#define NFSPROC_SETATTR 2
|
||||
#define NFSPROC_LOOKUP 3
|
||||
#define NFSPROC_ACCESS 4
|
||||
#define NFSPROC_READLINK 5
|
||||
#define NFSPROC_READ 6
|
||||
#define NFSPROC_WRITE 7
|
||||
#define NFSPROC_CREATE 8
|
||||
#define NFSPROC_MKDIR 9
|
||||
#define NFSPROC_SYMLINK 10
|
||||
#define NFSPROC_MKNOD 11
|
||||
#define NFSPROC_REMOVE 12
|
||||
#define NFSPROC_RMDIR 13
|
||||
#define NFSPROC_RENAME 14
|
||||
#define NFSPROC_LINK 15
|
||||
#define NFSPROC_READDIR 16
|
||||
#define NFSPROC_READDIRPLUS 17
|
||||
#define NFSPROC_FSSTAT 18
|
||||
#define NFSPROC_FSINFO 19
|
||||
#define NFSPROC_PATHCONF 20
|
||||
#define NFSPROC_COMMIT 21
|
||||
|
||||
/* And leasing (nqnfs) procedure numbers (must be last) */
|
||||
#define NQNFSPROC_GETLEASE 22
|
||||
#define NQNFSPROC_VACATED 23
|
||||
#define NQNFSPROC_EVICTED 24
|
||||
|
||||
#define NFSPROC_NOOP 25
|
||||
#define NFS_NPROCS 26
|
||||
|
||||
/* Actual Version 2 procedure numbers */
|
||||
#define NFSV2PROC_NULL 0
|
||||
#define NFSV2PROC_GETATTR 1
|
||||
#define NFSV2PROC_SETATTR 2
|
||||
#define NFSV2PROC_NOOP 3
|
||||
#define NFSV2PROC_ROOT NFSV2PROC_NOOP /* Obsolete */
|
||||
#define NFSV2PROC_LOOKUP 4
|
||||
#define NFSV2PROC_READLINK 5
|
||||
#define NFSV2PROC_READ 6
|
||||
#define NFSV2PROC_WRITECACHE NFSV2PROC_NOOP /* Obsolete */
|
||||
#define NFSV2PROC_WRITE 8
|
||||
#define NFSV2PROC_CREATE 9
|
||||
#define NFSV2PROC_REMOVE 10
|
||||
#define NFSV2PROC_RENAME 11
|
||||
#define NFSV2PROC_LINK 12
|
||||
#define NFSV2PROC_SYMLINK 13
|
||||
#define NFSV2PROC_MKDIR 14
|
||||
#define NFSV2PROC_RMDIR 15
|
||||
#define NFSV2PROC_READDIR 16
|
||||
#define NFSV2PROC_STATFS 17
|
||||
|
||||
/*
|
||||
* Constants used by the Version 3 protocol for various RPCs
|
||||
*/
|
||||
#define NFSV3SATTRTIME_DONTCHANGE 0
|
||||
#define NFSV3SATTRTIME_TOSERVER 1
|
||||
#define NFSV3SATTRTIME_TOCLIENT 2
|
||||
|
||||
#define NFSV3ACCESS_READ 0x01
|
||||
#define NFSV3ACCESS_LOOKUP 0x02
|
||||
#define NFSV3ACCESS_MODIFY 0x04
|
||||
#define NFSV3ACCESS_EXTEND 0x08
|
||||
#define NFSV3ACCESS_DELETE 0x10
|
||||
#define NFSV3ACCESS_EXECUTE 0x20
|
||||
|
||||
#define NFSV3WRITE_UNSTABLE 0
|
||||
#define NFSV3WRITE_DATASYNC 1
|
||||
#define NFSV3WRITE_FILESYNC 2
|
||||
|
||||
#define NFSV3CREATE_UNCHECKED 0
|
||||
#define NFSV3CREATE_GUARDED 1
|
||||
#define NFSV3CREATE_EXCLUSIVE 2
|
||||
|
||||
#define NFSV3FSINFO_LINK 0x01
|
||||
#define NFSV3FSINFO_SYMLINK 0x02
|
||||
#define NFSV3FSINFO_HOMOGENEOUS 0x08
|
||||
#define NFSV3FSINFO_CANSETTIME 0x10
|
||||
|
||||
/* Conversion macros */
|
||||
#define vtonfsv2_mode(t,m) \
|
||||
txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \
|
||||
MAKEIMODE((t), (m)))
|
||||
#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777)
|
||||
#define nfstov_mode(a) (fxdr_unsigned(u_short, (a))&07777)
|
||||
#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((long)(a))])
|
||||
#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((long)(a))])
|
||||
#define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(u_long,(a))&0x7]
|
||||
#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(u_long,(a))&0x7]
|
||||
|
||||
/* File types */
|
||||
typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5,
|
||||
NFSOCK=6, NFFIFO=7 } nfstype;
|
||||
|
||||
/* Structs for common parts of the rpc's */
|
||||
/*
|
||||
* File Handle (32 bytes for version 2), variable up to 64 for version 3.
|
||||
* File Handles of up to NFS_SMALLFH in size are stored directly in the
|
||||
* nfs node, whereas larger ones are malloc'd. (This never happens when
|
||||
* NFS_SMALLFH is set to 64.)
|
||||
* NFS_SMALLFH should be in the range of 32 to 64 and be divisible by 4.
|
||||
*/
|
||||
#ifndef NFS_SMALLFH
|
||||
#define NFS_SMALLFH 64
|
||||
#endif
|
||||
union nfsfh {
|
||||
fhandle_t fh_generic;
|
||||
u_char fh_bytes[NFS_SMALLFH];
|
||||
};
|
||||
typedef union nfsfh nfsfh_t;
|
||||
|
||||
struct nfsv2_time {
|
||||
u_long nfsv2_sec;
|
||||
u_long nfsv2_usec;
|
||||
};
|
||||
typedef struct nfsv2_time nfstime2;
|
||||
|
||||
struct nfsv3_time {
|
||||
u_long nfsv3_sec;
|
||||
u_long nfsv3_nsec;
|
||||
};
|
||||
typedef struct nfsv3_time nfstime3;
|
||||
|
||||
/*
|
||||
* Quads are defined as arrays of 2 longs to ensure dense packing for the
|
||||
* protocol and to facilitate xdr conversion.
|
||||
*/
|
||||
struct nfs_uquad {
|
||||
u_long nfsuquad[2];
|
||||
};
|
||||
typedef struct nfs_uquad nfsuint64;
|
||||
|
||||
/*
|
||||
* Used to convert between two u_longs and a u_quad_t.
|
||||
*/
|
||||
union nfs_quadconvert {
|
||||
u_long lval[2];
|
||||
u_quad_t qval;
|
||||
};
|
||||
typedef union nfs_quadconvert nfsquad_t;
|
||||
|
||||
/*
|
||||
* NFS Version 3 special file number.
|
||||
*/
|
||||
struct nfsv3_spec {
|
||||
u_long specdata1;
|
||||
u_long specdata2;
|
||||
};
|
||||
typedef struct nfsv3_spec nfsv3spec;
|
||||
|
||||
/*
|
||||
* File attributes and setable attributes. These structures cover both
|
||||
* NFS version 2 and the version 3 protocol. Note that the union is only
|
||||
* used so that one pointer can refer to both variants. These structures
|
||||
* go out on the wire and must be densely packed, so no quad data types
|
||||
* are used. (all fields are longs or u_longs or structures of same)
|
||||
* NB: You can't do sizeof(struct nfs_fattr), you must use the
|
||||
* NFSX_FATTR(v3) macro.
|
||||
*/
|
||||
struct nfs_fattr {
|
||||
u_long fa_type;
|
||||
u_long fa_mode;
|
||||
u_long fa_nlink;
|
||||
u_long fa_uid;
|
||||
u_long fa_gid;
|
||||
union {
|
||||
struct {
|
||||
u_long nfsv2fa_size;
|
||||
u_long nfsv2fa_blocksize;
|
||||
u_long nfsv2fa_rdev;
|
||||
u_long nfsv2fa_blocks;
|
||||
u_long nfsv2fa_fsid;
|
||||
u_long nfsv2fa_fileid;
|
||||
nfstime2 nfsv2fa_atime;
|
||||
nfstime2 nfsv2fa_mtime;
|
||||
nfstime2 nfsv2fa_ctime;
|
||||
} fa_nfsv2;
|
||||
struct {
|
||||
nfsuint64 nfsv3fa_size;
|
||||
nfsuint64 nfsv3fa_used;
|
||||
nfsv3spec nfsv3fa_rdev;
|
||||
nfsuint64 nfsv3fa_fsid;
|
||||
nfsuint64 nfsv3fa_fileid;
|
||||
nfstime3 nfsv3fa_atime;
|
||||
nfstime3 nfsv3fa_mtime;
|
||||
nfstime3 nfsv3fa_ctime;
|
||||
} fa_nfsv3;
|
||||
} fa_un;
|
||||
};
|
||||
|
||||
/* and some ugly defines for accessing union components */
|
||||
#define fa2_size fa_un.fa_nfsv2.nfsv2fa_size
|
||||
#define fa2_blocksize fa_un.fa_nfsv2.nfsv2fa_blocksize
|
||||
#define fa2_rdev fa_un.fa_nfsv2.nfsv2fa_rdev
|
||||
#define fa2_blocks fa_un.fa_nfsv2.nfsv2fa_blocks
|
||||
#define fa2_fsid fa_un.fa_nfsv2.nfsv2fa_fsid
|
||||
#define fa2_fileid fa_un.fa_nfsv2.nfsv2fa_fileid
|
||||
#define fa2_atime fa_un.fa_nfsv2.nfsv2fa_atime
|
||||
#define fa2_mtime fa_un.fa_nfsv2.nfsv2fa_mtime
|
||||
#define fa2_ctime fa_un.fa_nfsv2.nfsv2fa_ctime
|
||||
#define fa3_size fa_un.fa_nfsv3.nfsv3fa_size
|
||||
#define fa3_used fa_un.fa_nfsv3.nfsv3fa_used
|
||||
#define fa3_rdev fa_un.fa_nfsv3.nfsv3fa_rdev
|
||||
#define fa3_fsid fa_un.fa_nfsv3.nfsv3fa_fsid
|
||||
#define fa3_fileid fa_un.fa_nfsv3.nfsv3fa_fileid
|
||||
#define fa3_atime fa_un.fa_nfsv3.nfsv3fa_atime
|
||||
#define fa3_mtime fa_un.fa_nfsv3.nfsv3fa_mtime
|
||||
#define fa3_ctime fa_un.fa_nfsv3.nfsv3fa_ctime
|
||||
|
||||
struct nfsv2_sattr {
|
||||
u_long sa_mode;
|
||||
u_long sa_uid;
|
||||
u_long sa_gid;
|
||||
u_long sa_size;
|
||||
nfstime2 sa_atime;
|
||||
nfstime2 sa_mtime;
|
||||
};
|
||||
|
||||
/*
|
||||
* NFS Version 3 sattr structure for the new node creation case.
|
||||
*/
|
||||
struct nfsv3_sattr {
|
||||
u_long sa_modetrue;
|
||||
u_long sa_mode;
|
||||
u_long sa_uidtrue;
|
||||
u_long sa_uid;
|
||||
u_long sa_gidtrue;
|
||||
u_long sa_gid;
|
||||
u_long sa_sizefalse;
|
||||
u_long sa_atimetype;
|
||||
nfstime3 sa_atime;
|
||||
u_long sa_mtimetype;
|
||||
nfstime3 sa_mtime;
|
||||
};
|
||||
|
||||
struct nfs_statfs {
|
||||
union {
|
||||
struct {
|
||||
u_long nfsv2sf_tsize;
|
||||
u_long nfsv2sf_bsize;
|
||||
u_long nfsv2sf_blocks;
|
||||
u_long nfsv2sf_bfree;
|
||||
u_long nfsv2sf_bavail;
|
||||
} sf_nfsv2;
|
||||
struct {
|
||||
nfsuint64 nfsv3sf_tbytes;
|
||||
nfsuint64 nfsv3sf_fbytes;
|
||||
nfsuint64 nfsv3sf_abytes;
|
||||
nfsuint64 nfsv3sf_tfiles;
|
||||
nfsuint64 nfsv3sf_ffiles;
|
||||
nfsuint64 nfsv3sf_afiles;
|
||||
u_long nfsv3sf_invarsec;
|
||||
} sf_nfsv3;
|
||||
} sf_un;
|
||||
};
|
||||
|
||||
#define sf_tsize sf_un.sf_nfsv2.nfsv2sf_tsize
|
||||
#define sf_bsize sf_un.sf_nfsv2.nfsv2sf_bsize
|
||||
#define sf_blocks sf_un.sf_nfsv2.nfsv2sf_blocks
|
||||
#define sf_bfree sf_un.sf_nfsv2.nfsv2sf_bfree
|
||||
#define sf_bavail sf_un.sf_nfsv2.nfsv2sf_bavail
|
||||
#define sf_tbytes sf_un.sf_nfsv3.nfsv3sf_tbytes
|
||||
#define sf_fbytes sf_un.sf_nfsv3.nfsv3sf_fbytes
|
||||
#define sf_abytes sf_un.sf_nfsv3.nfsv3sf_abytes
|
||||
#define sf_tfiles sf_un.sf_nfsv3.nfsv3sf_tfiles
|
||||
#define sf_ffiles sf_un.sf_nfsv3.nfsv3sf_ffiles
|
||||
#define sf_afiles sf_un.sf_nfsv3.nfsv3sf_afiles
|
||||
#define sf_invarsec sf_un.sf_nfsv3.nfsv3sf_invarsec
|
||||
|
||||
struct nfsv3_fsinfo {
|
||||
u_long fs_rtmax;
|
||||
u_long fs_rtpref;
|
||||
u_long fs_rtmult;
|
||||
u_long fs_wtmax;
|
||||
u_long fs_wtpref;
|
||||
u_long fs_wtmult;
|
||||
u_long fs_dtpref;
|
||||
nfsuint64 fs_maxfilesize;
|
||||
nfstime3 fs_timedelta;
|
||||
u_long fs_properties;
|
||||
};
|
||||
|
||||
struct nfsv3_pathconf {
|
||||
u_long pc_linkmax;
|
||||
u_long pc_namemax;
|
||||
u_long pc_notrunc;
|
||||
u_long pc_chownrestricted;
|
||||
u_long pc_caseinsensitive;
|
||||
u_long pc_casepreserving;
|
||||
};
|
||||
|
||||
#endif
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsrtt.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfsrtt.h,v 1.2 1994/08/02 07:52:24 davidg Exp $
|
||||
* $Id: nfsrtt.h,v 1.3 1994/08/21 06:50:12 paul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSRTT_H_
|
||||
@ -82,6 +82,7 @@ struct nfsrtt {
|
||||
#define DRT_TCP 0x02 /* Client used TCP transport */
|
||||
#define DRT_CACHEREPLY 0x04 /* Reply was from recent request cache */
|
||||
#define DRT_CACHEDROP 0x08 /* Rpc request dropped, due to recent reply */
|
||||
#define DRT_NFSV3 0x10 /* Rpc used NFS Version 3 */
|
||||
|
||||
/*
|
||||
* Server log structure
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsrvcache.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfsrvcache.h,v 1.3 1994/08/21 06:50:13 paul Exp $
|
||||
* $Id: nfsrvcache.h,v 1.4 1994/10/17 17:47:44 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSRVCACHE_H_
|
||||
@ -44,7 +44,7 @@
|
||||
* Definitions for the server recent request cache
|
||||
*/
|
||||
|
||||
#define NFSRVCACHESIZ 256
|
||||
#define NFSRVCACHESIZ 64
|
||||
|
||||
struct nfsrvcache {
|
||||
TAILQ_ENTRY(nfsrvcache) rc_lru; /* LRU chain */
|
||||
|
361
sys/nfs/nfsv2.h
361
sys/nfs/nfsv2.h
@ -34,129 +34,201 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsv2.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfsv2.h,v 1.3 1994/08/18 22:35:37 wollman Exp $
|
||||
* $Id: nfsv2.h,v 1.4 1994/08/21 06:50:13 paul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSV2_H_
|
||||
#define _NFS_NFSV2_H_
|
||||
#include <nfs/nfsproto.h>
|
||||
|
||||
#if 0
|
||||
|
||||
|
||||
/*
|
||||
* nfs definitions as per the version 2 specs
|
||||
* nfs definitions as per the Version 2 and 3 specs
|
||||
*/
|
||||
|
||||
/*
|
||||
* Constants as defined in the Sun NFS Version 2 spec.
|
||||
* Constants as defined in the Sun NFS Version 2 and 3 specs.
|
||||
* "NFS: Network File System Protocol Specification" RFC1094
|
||||
* and in the "NFS: Network File System Version 3 Protocol
|
||||
* Specification"
|
||||
*/
|
||||
|
||||
#define NFS_PORT 2049
|
||||
#define NFS_PROG 100003
|
||||
#define NFS_VER2 2
|
||||
#define NFS_VER3 3
|
||||
#define NFS_MAXDGRAMDATA 8192
|
||||
#define NFS_MAXDATA 32768
|
||||
#define NFS_MAXPATHLEN 1024
|
||||
#define NFS_MAXNAMLEN 255
|
||||
#define NFS_FHSIZE 32
|
||||
#define NFS_MAXPKTHDR 404
|
||||
#define NFS_MAXPACKET (NFS_MAXPKTHDR+NFS_MAXDATA)
|
||||
#define NFS_MAXPACKET (NFS_MAXPKTHDR + NFS_MAXDATA)
|
||||
#define NFS_MINPACKET 20
|
||||
#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */
|
||||
|
||||
/* Stat numbers for rpc returns */
|
||||
#define NFS_OK 0
|
||||
#define NFSERR_PERM 1
|
||||
#define NFSERR_NOENT 2
|
||||
#define NFSERR_IO 5
|
||||
#define NFSERR_NXIO 6
|
||||
#define NFSERR_ACCES 13
|
||||
#define NFSERR_EXIST 17
|
||||
#define NFSERR_NODEV 19
|
||||
#define NFSERR_NOTDIR 20
|
||||
#define NFSERR_ISDIR 21
|
||||
#define NFSERR_FBIG 27
|
||||
#define NFSERR_NOSPC 28
|
||||
#define NFSERR_ROFS 30
|
||||
#define NFSERR_NAMETOL 63
|
||||
#define NFSERR_NOTEMPTY 66
|
||||
#define NFSERR_DQUOT 69
|
||||
#define NFSERR_STALE 70
|
||||
#define NFSERR_WFLUSH 99
|
||||
/* Stat numbers for rpc returns (version 2 and 3) */
|
||||
#define NFS_OK 0
|
||||
#define NFSERR_PERM 1
|
||||
#define NFSERR_NOENT 2
|
||||
#define NFSERR_IO 5
|
||||
#define NFSERR_NXIO 6
|
||||
#define NFSERR_ACCES 13
|
||||
#define NFSERR_EXIST 17
|
||||
#define NFSERR_XDEV 18 /* Version 3 only */
|
||||
#define NFSERR_NODEV 19
|
||||
#define NFSERR_NOTDIR 20
|
||||
#define NFSERR_ISDIR 21
|
||||
#define NFSERR_INVAL 22 /* Version 3 only */
|
||||
#define NFSERR_FBIG 27
|
||||
#define NFSERR_NOSPC 28
|
||||
#define NFSERR_ROFS 30
|
||||
#define NFSERR_MLINK 31 /* Version 3 only */
|
||||
#define NFSERR_NAMETOL 63
|
||||
#define NFSERR_NOTEMPTY 66
|
||||
#define NFSERR_DQUOT 69
|
||||
#define NFSERR_STALE 70
|
||||
#define NFSERR_REMOTE 71 /* Version 3 only */
|
||||
#define NFSERR_WFLUSH 99 /* Version 2 only */
|
||||
#define NFSERR_BADHANDLE 10001 /* The rest Version 3 only */
|
||||
#define NFSERR_NOT_SYNC 10002
|
||||
#define NFSERR_BAD_COOKIE 10003
|
||||
#define NFSERR_NOTSUPP 10004
|
||||
#define NFSERR_TOOSMALL 10005
|
||||
#define NFSERR_SERVERFAULT 10006
|
||||
#define NFSERR_BADTYPE 10007
|
||||
#define NFSERR_JUKEBOX 10008
|
||||
|
||||
/* Sizes in bytes of various nfs rpc components */
|
||||
#define NFSX_FH 32
|
||||
#define NFSX_UNSIGNED 4
|
||||
#define NFSX_NFSFATTR 68
|
||||
#define NFSX_NQFATTR 92
|
||||
#define NFSX_NFSSATTR 32
|
||||
#define NFSX_NQSATTR 44
|
||||
#define NFSX_COOKIE 4
|
||||
#define NFSX_NFSSTATFS 20
|
||||
#define NFSX_NQSTATFS 28
|
||||
#define NFSX_FATTR(isnq) ((isnq) ? NFSX_NQFATTR : NFSX_NFSFATTR)
|
||||
#define NFSX_SATTR(isnq) ((isnq) ? NFSX_NQSATTR : NFSX_NFSSATTR)
|
||||
#define NFSX_STATFS(isnq) ((isnq) ? NFSX_NQSTATFS : NFSX_NFSSTATFS)
|
||||
|
||||
/* nfs rpc procedure numbers */
|
||||
/* specific to NFS Version 2 */
|
||||
#define NFSX_V2FH 32
|
||||
#define NFSX_V2FATTR 68
|
||||
#define NFSX_V2SATTR 32
|
||||
#define NFSX_V2COOKIE 4
|
||||
#define NFSX_V2STATFS 20
|
||||
|
||||
/* specific to NFS Version 3 */
|
||||
#define NFSX_V3FH 16 /* size this server uses */
|
||||
#define NFSX_V3FHMAX 64 /* max. allowed by protocol */
|
||||
#define NFSX_V3FATTR 84
|
||||
#define NFSX_V3SATTR 60 /* max. all fields filled in */
|
||||
#define NFSX_V3COOKIEVERF 8
|
||||
|
||||
/* variants for both versions */
|
||||
#define NFSX_FH(v3) ((v3) ? (NFSX_V3FHMAX + NFSX_UNSIGNED) : \
|
||||
NFSX_V2FH)
|
||||
#define NFSX_SRVFH(v3) ((v3) ? NFSX_V3FH : NFSX_V2FH)
|
||||
#define NFSX_FATTR(v3) ((v3) ? NFSX_V3FATTR : NFSX_V2FATTR)
|
||||
#define NFSX_POSTOPATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : 0)
|
||||
#define NFSX_POSTOPORFATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : \
|
||||
NFSX_V2FATTR)
|
||||
#define NFSX_WCCDATA(v3) ((v3) ? (NFSX_V3FATTR + 32) : 0)
|
||||
#define NFSX_WCCORFATTR(v3) ((v3) ? (NFSX_V3FATTR + 32) : NFSX_V2FATTR)
|
||||
#define NFSX_SATTR(v3) ((v3) ? NFSX_V3SATTR : NFSX_V2SATTR)
|
||||
#define NFSX_COOKIEVERF(v3) ((v3) ? NFSX_V3COOKIEVERF : 0)
|
||||
#define NFSX_STATFS(isv3) ((isv3) ? NFSX_NFSV3STATFS : NFSX_NFSSTATFS)
|
||||
|
||||
/* nfs rpc procedure numbers (before version mapping) */
|
||||
#define NFSPROC_NULL 0
|
||||
#define NFSPROC_GETATTR 1
|
||||
#define NFSPROC_SETATTR 2
|
||||
#define NFSPROC_NOOP 3
|
||||
#define NFSPROC_ROOT NFSPROC_NOOP /* Obsolete */
|
||||
#define NFSPROC_LOOKUP 4
|
||||
#define NFSPROC_LOOKUP 3
|
||||
#define NFSPROC_ACCESS 4
|
||||
#define NFSPROC_READLINK 5
|
||||
#define NFSPROC_READ 6
|
||||
#define NFSPROC_WRITECACHE NFSPROC_NOOP /* Obsolete */
|
||||
#define NFSPROC_WRITE 8
|
||||
#define NFSPROC_CREATE 9
|
||||
#define NFSPROC_REMOVE 10
|
||||
#define NFSPROC_RENAME 11
|
||||
#define NFSPROC_LINK 12
|
||||
#define NFSPROC_SYMLINK 13
|
||||
#define NFSPROC_MKDIR 14
|
||||
#define NFSPROC_RMDIR 15
|
||||
#define NFSPROC_WRITE 7
|
||||
#define NFSPROC_CREATE 8
|
||||
#define NFSPROC_MKDIR 9
|
||||
#define NFSPROC_SYMLINK 10
|
||||
#define NFSPROC_MKNOD 11
|
||||
#define NFSPROC_REMOVE 12
|
||||
#define NFSPROC_RMDIR 13
|
||||
#define NFSPROC_RENAME 14
|
||||
#define NFSPROC_LINK 15
|
||||
#define NFSPROC_READDIR 16
|
||||
#define NFSPROC_STATFS 17
|
||||
#define NFSPROC_READDIRPLUS 17
|
||||
#define NFSPROC_FSSTAT 18
|
||||
#define NFSPROC_FSINFO 19
|
||||
#define NFSPROC_PATHCONF 20
|
||||
#define NFSPROC_COMMIT 21
|
||||
|
||||
/* NQ nfs numbers */
|
||||
#define NQNFSPROC_READDIRLOOK 18
|
||||
#define NQNFSPROC_GETLEASE 19
|
||||
#define NQNFSPROC_VACATED 20
|
||||
#define NQNFSPROC_EVICTED 21
|
||||
#define NQNFSPROC_ACCESS 22
|
||||
/* And leasing (nqnfs) procedure numbers */
|
||||
#define NQNFSPROC_GETLEASE 22
|
||||
#define NQNFSPROC_VACATED 23
|
||||
#define NQNFSPROC_EVICTED 24
|
||||
|
||||
#define NFS_NPROCS 25
|
||||
|
||||
/* Actual Version 2 procedure numbers */
|
||||
#define NFSV2PROC_NULL 0
|
||||
#define NFSV2PROC_GETATTR 1
|
||||
#define NFSV2PROC_SETATTR 2
|
||||
#define NFSV2PROC_NOOP 3
|
||||
#define NFSV2PROC_ROOT NFSV2PROC_NOOP /* Obsolete */
|
||||
#define NFSV2PROC_LOOKUP 4
|
||||
#define NFSV2PROC_READLINK 5
|
||||
#define NFSV2PROC_READ 6
|
||||
#define NFSV2PROC_WRITECACHE NFSV2PROC_NOOP /* Obsolete */
|
||||
#define NFSV2PROC_WRITE 8
|
||||
#define NFSV2PROC_CREATE 9
|
||||
#define NFSV2PROC_REMOVE 10
|
||||
#define NFSV2PROC_RENAME 11
|
||||
#define NFSV2PROC_LINK 12
|
||||
#define NFSV2PROC_SYMLINK 13
|
||||
#define NFSV2PROC_MKDIR 14
|
||||
#define NFSV2PROC_RMDIR 15
|
||||
#define NFSV2PROC_READDIR 16
|
||||
#define NFSV2PROC_STATFS 17
|
||||
|
||||
#define NFS_NPROCS 23
|
||||
/* Conversion macros */
|
||||
#define vtonfs_mode(t,m) \
|
||||
extern int vttoif_tab[];
|
||||
#define vtonfsv2_mode(t,m) \
|
||||
txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \
|
||||
MAKEIMODE((t), (m)))
|
||||
#define nfstov_mode(a) (fxdr_unsigned(u_short, (a))&07777)
|
||||
#define vtonfs_type(a) txdr_unsigned(nfs_type[((long)(a))])
|
||||
#define nfstov_type(a) ntov_type[fxdr_unsigned(u_long,(a))&0x7]
|
||||
#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777)
|
||||
#define nfstov_mode(a) (fxdr_unsigned(u_short, (a))&07777)
|
||||
#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((long)(a))])
|
||||
#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((long)(a))])
|
||||
#define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(u_long,(a))&0x7]
|
||||
#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(u_long,(a))&0x7]
|
||||
|
||||
/* File types */
|
||||
typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 } nfstype;
|
||||
typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5,
|
||||
NFSOCK=6, NFFIFO=7 } nfstype;
|
||||
|
||||
/* Structs for common parts of the rpc's */
|
||||
struct nfsv2_time {
|
||||
u_long nfs_sec;
|
||||
u_long nfs_usec;
|
||||
u_long nfsv2_sec;
|
||||
u_long nfsv2_usec;
|
||||
};
|
||||
typedef struct nfsv2_time nfstime2;
|
||||
|
||||
struct nqnfs_time {
|
||||
u_long nq_sec;
|
||||
u_long nq_nsec;
|
||||
struct nfsv3_time {
|
||||
u_long nfsv3_sec;
|
||||
u_long nfsv3_nsec;
|
||||
};
|
||||
typedef struct nfsv3_time nfstime3;
|
||||
|
||||
/*
|
||||
* Quads are defined as arrays of 2 longs to ensure dense packing for the
|
||||
* protocol and to facilitate xdr conversion.
|
||||
*/
|
||||
struct nfs_uquad {
|
||||
u_long nfsuquad[2];
|
||||
};
|
||||
typedef struct nfs_uquad nfsuint64;
|
||||
|
||||
/*
|
||||
* File attributes and setable attributes. These structures cover both
|
||||
* NFS version 2 and the NQNFS protocol. Note that the union is only
|
||||
* used to that one pointer can refer to both variants. These structures
|
||||
* NFS version 2 and the version 3 protocol. Note that the union is only
|
||||
* used so that one pointer can refer to both variants. These structures
|
||||
* go out on the wire and must be densely packed, so no quad data types
|
||||
* are used. (all fields are longs or u_longs or structures of same)
|
||||
* NB: You can't do sizeof(struct nfsv2_fattr), you must use the
|
||||
* NFSX_FATTR(isnq) macro.
|
||||
* NB: You can't do sizeof(struct nfs_fattr), you must use the
|
||||
* NFSX_FATTR(v3) macro.
|
||||
*/
|
||||
struct nfsv2_fattr {
|
||||
struct nfs_fattr {
|
||||
u_long fa_type;
|
||||
u_long fa_mode;
|
||||
u_long fa_nlink;
|
||||
@ -164,102 +236,85 @@ struct nfsv2_fattr {
|
||||
u_long fa_gid;
|
||||
union {
|
||||
struct {
|
||||
u_long nfsfa_size;
|
||||
u_long nfsfa_blocksize;
|
||||
u_long nfsfa_rdev;
|
||||
u_long nfsfa_blocks;
|
||||
u_long nfsfa_fsid;
|
||||
u_long nfsfa_fileid;
|
||||
struct nfsv2_time nfsfa_atime;
|
||||
struct nfsv2_time nfsfa_mtime;
|
||||
struct nfsv2_time nfsfa_ctime;
|
||||
u_long nfsv2fa_size;
|
||||
u_long nfsv2fa_blocksize;
|
||||
u_long nfsv2fa_rdev;
|
||||
u_long nfsv2fa_blocks;
|
||||
u_long nfsv2fa_fsid;
|
||||
u_long nfsv2fa_fileid;
|
||||
nfstime2 nfsv2fa_atime;
|
||||
nfstime2 nfsv2fa_mtime;
|
||||
nfstime2 nfsv2fa_ctime;
|
||||
} fa_nfsv2;
|
||||
struct {
|
||||
struct {
|
||||
u_long nqfa_qsize[2];
|
||||
} nqfa_size;
|
||||
u_long nqfa_blocksize;
|
||||
u_long nqfa_rdev;
|
||||
struct {
|
||||
u_long nqfa_qbytes[2];
|
||||
} nqfa_bytes;
|
||||
u_long nqfa_fsid;
|
||||
u_long nqfa_fileid;
|
||||
struct nqnfs_time nqfa_atime;
|
||||
struct nqnfs_time nqfa_mtime;
|
||||
struct nqnfs_time nqfa_ctime;
|
||||
u_long nqfa_flags;
|
||||
u_long nqfa_gen;
|
||||
struct {
|
||||
u_long nqfa_qfilerev[2];
|
||||
} nqfa_filerev;
|
||||
} fa_nqnfs;
|
||||
nfsuint64 nfsv3fa_size;
|
||||
nfsuint64 nfsv3fa_used;
|
||||
nfsuint64 nfsv3fa_rdev;
|
||||
nfsuint64 nfsv3fa_fsid;
|
||||
nfsuint64 nfsv3fa_fileid;
|
||||
nfstime3 nfsv3fa_atime;
|
||||
nfstime3 nfsv3fa_mtime;
|
||||
nfstime3 nfsv3fa_ctime;
|
||||
} fa_nfsv3;
|
||||
} fa_un;
|
||||
};
|
||||
|
||||
/* and some ugly defines for accessing union components */
|
||||
#define fa_nfssize fa_un.fa_nfsv2.nfsfa_size
|
||||
#define fa_nfsblocksize fa_un.fa_nfsv2.nfsfa_blocksize
|
||||
#define fa_nfsrdev fa_un.fa_nfsv2.nfsfa_rdev
|
||||
#define fa_nfsblocks fa_un.fa_nfsv2.nfsfa_blocks
|
||||
#define fa_nfsfsid fa_un.fa_nfsv2.nfsfa_fsid
|
||||
#define fa_nfsfileid fa_un.fa_nfsv2.nfsfa_fileid
|
||||
#define fa_nfsatime fa_un.fa_nfsv2.nfsfa_atime
|
||||
#define fa_nfsmtime fa_un.fa_nfsv2.nfsfa_mtime
|
||||
#define fa_nfsctime fa_un.fa_nfsv2.nfsfa_ctime
|
||||
#define fa_nqsize fa_un.fa_nqnfs.nqfa_size
|
||||
#define fa_nqblocksize fa_un.fa_nqnfs.nqfa_blocksize
|
||||
#define fa_nqrdev fa_un.fa_nqnfs.nqfa_rdev
|
||||
#define fa_nqbytes fa_un.fa_nqnfs.nqfa_bytes
|
||||
#define fa_nqfsid fa_un.fa_nqnfs.nqfa_fsid
|
||||
#define fa_nqfileid fa_un.fa_nqnfs.nqfa_fileid
|
||||
#define fa_nqatime fa_un.fa_nqnfs.nqfa_atime
|
||||
#define fa_nqmtime fa_un.fa_nqnfs.nqfa_mtime
|
||||
#define fa_nqctime fa_un.fa_nqnfs.nqfa_ctime
|
||||
#define fa_nqflags fa_un.fa_nqnfs.nqfa_flags
|
||||
#define fa_nqgen fa_un.fa_nqnfs.nqfa_gen
|
||||
#define fa_nqfilerev fa_un.fa_nqnfs.nqfa_filerev
|
||||
#define fa2_size fa_un.fa_nfsv2.nfsv2fa_size
|
||||
#define fa2_blocksize fa_un.fa_nfsv2.nfsv2fa_blocksize
|
||||
#define fa2_rdev fa_un.fa_nfsv2.nfsv2fa_rdev
|
||||
#define fa2_blocks fa_un.fa_nfsv2.nfsv2fa_blocks
|
||||
#define fa2_fsid fa_un.fa_nfsv2.nfsv2fa_fsid
|
||||
#define fa2_fileid fa_un.fa_nfsv2.nfsv2fa_fileid
|
||||
#define fa2_atime fa_un.fa_nfsv2.nfsv2fa_atime
|
||||
#define fa2_mtime fa_un.fa_nfsv2.nfsv2fa_mtime
|
||||
#define fa2_ctime fa_un.fa_nfsv2.nfsv2fa_ctime
|
||||
#define fa3_size fa_un.fa_nfsv3.nfsv3fa_size
|
||||
#define fa3_used fa_un.fa_nfsv3.nfsv3fa_used
|
||||
#define fa3_rdev fa_un.fa_nfsv3.nfsv3fa_rdev
|
||||
#define fa3_fsid fa_un.fa_nfsv3.nfsv3fa_fsid
|
||||
#define fa3_fileid fa_un.fa_nfsv3.nfsv3fa_fileid
|
||||
#define fa3_atime fa_un.fa_nfsv3.nfsv3fa_atime
|
||||
#define fa3_mtime fa_un.fa_nfsv3.nfsv3fa_mtime
|
||||
#define fa3_ctime fa_un.fa_nfsv3.nfsv3fa_ctime
|
||||
|
||||
struct nfsv2_sattr {
|
||||
u_long sa_mode;
|
||||
u_long sa_uid;
|
||||
u_long sa_gid;
|
||||
union {
|
||||
struct {
|
||||
u_long nfssa_size;
|
||||
struct nfsv2_time nfssa_atime;
|
||||
struct nfsv2_time nfssa_mtime;
|
||||
} sa_nfsv2;
|
||||
struct {
|
||||
struct {
|
||||
u_long nqsa_qsize[2];
|
||||
} nqsa_size;
|
||||
struct nqnfs_time nqsa_atime;
|
||||
struct nqnfs_time nqsa_mtime;
|
||||
u_long nqsa_flags;
|
||||
u_long nqsa_rdev;
|
||||
} sa_nqnfs;
|
||||
} sa_un;
|
||||
u_long sa_mode;
|
||||
u_long sa_uid;
|
||||
u_long sa_gid;
|
||||
u_long sa_size;
|
||||
nfstime2 sa_atime;
|
||||
nfstime2 sa_mtime;
|
||||
};
|
||||
|
||||
/* and some ugly defines for accessing the unions */
|
||||
#define sa_nfssize sa_un.sa_nfsv2.nfssa_size
|
||||
#define sa_nfsatime sa_un.sa_nfsv2.nfssa_atime
|
||||
#define sa_nfsmtime sa_un.sa_nfsv2.nfssa_mtime
|
||||
#define sa_nqsize sa_un.sa_nqnfs.nqsa_size
|
||||
#define sa_nqatime sa_un.sa_nqnfs.nqsa_atime
|
||||
#define sa_nqmtime sa_un.sa_nqnfs.nqsa_mtime
|
||||
#define sa_nqflags sa_un.sa_nqnfs.nqsa_flags
|
||||
#define sa_nqrdev sa_un.sa_nqnfs.nqsa_rdev
|
||||
|
||||
struct nfsv2_statfs {
|
||||
u_long sf_tsize;
|
||||
u_long sf_bsize;
|
||||
u_long sf_blocks;
|
||||
u_long sf_bfree;
|
||||
u_long sf_bavail;
|
||||
u_long sf_files; /* Nqnfs only */
|
||||
u_long sf_ffree; /* ditto */
|
||||
};
|
||||
|
||||
struct nfsv3_fsstat {
|
||||
nfsuint64 sf_tbytes;
|
||||
nfsuint64 sf_fbytes;
|
||||
nfsuint64 sf_abytes;
|
||||
nfsuint64 sf_tfiles;
|
||||
nfsuint64 sf_ffiles;
|
||||
nfsuint64 sf_afiles;
|
||||
u_long sf_invarsec;
|
||||
};
|
||||
|
||||
struct nfsv3_fsinfo {
|
||||
u_long fs_rtmax;
|
||||
u_long fs_rtpref;
|
||||
u_long fs_rtmult;
|
||||
u_long fs_wtmax;
|
||||
u_long fs_wtpref;
|
||||
u_long fs_wtmult;
|
||||
u_long fs_dtpref;
|
||||
nfsuint64 fs_maxfilesize;
|
||||
nfstime3 fs_time_delta;
|
||||
u_long fs_properties;
|
||||
};
|
||||
#endif
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nqnfs.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nqnfs.h,v 1.5 1994/10/02 17:27:07 phk Exp $
|
||||
* $Id: nqnfs.h,v 1.6 1994/10/17 17:47:45 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NQNFS_H_
|
||||
@ -58,7 +58,7 @@
|
||||
#define NQLCHSZ 256 /* Server hash table size */
|
||||
|
||||
#define NQNFS_PROG 300105 /* As assigned by Sun */
|
||||
#define NQNFS_VER1 1
|
||||
#define NQNFS_VER3 3
|
||||
#define NQNFS_EVICTSIZ 156 /* Size of eviction request in bytes */
|
||||
|
||||
/*
|
||||
@ -142,14 +142,6 @@ struct nqm {
|
||||
struct nqhost lpm_hosts[LC_MOREHOSTSIZ];
|
||||
};
|
||||
|
||||
/*
|
||||
* Flag bits for flags argument to nqsrv_getlease.
|
||||
*/
|
||||
#define NQL_READ LEASE_READ /* Read Request */
|
||||
#define NQL_WRITE LEASE_WRITE /* Write Request */
|
||||
#define NQL_CHECK 0x4 /* Check for lease */
|
||||
#define NQL_NOVAL 0xffffffff /* Invalid */
|
||||
|
||||
/*
|
||||
* Special value for slp for local server calls.
|
||||
*/
|
||||
@ -160,9 +152,9 @@ struct nqm {
|
||||
*/
|
||||
#define nqsrv_getl(v, l) \
|
||||
(void) nqsrv_getlease((v), &nfsd->nd_duration, \
|
||||
((nfsd->nd_nqlflag != 0 && nfsd->nd_nqlflag != NQL_NOVAL) ? nfsd->nd_nqlflag : \
|
||||
((l) | NQL_CHECK)), \
|
||||
nfsd, nam, &cache, &frev, cred)
|
||||
((nfsd->nd_flag & ND_LEASE) ? (nfsd->nd_flag & ND_LEASE) : \
|
||||
((l) | ND_CHECK)), \
|
||||
slp, procp, nfsd->nd_nam, &cache, &frev, cred)
|
||||
|
||||
/*
|
||||
* Client side macros that check for a valid lease.
|
||||
@ -170,13 +162,13 @@ struct nqm {
|
||||
#define NQNFS_CKINVALID(v, n, f) \
|
||||
((time.tv_sec > (n)->n_expiry && \
|
||||
VFSTONFS((v)->v_mount)->nm_timeouts < VFSTONFS((v)->v_mount)->nm_deadthresh) \
|
||||
|| ((f) == NQL_WRITE && ((n)->n_flag & NQNFSWRITE) == 0))
|
||||
|| ((f) == ND_WRITE && ((n)->n_flag & NQNFSWRITE) == 0))
|
||||
|
||||
#define NQNFS_CKCACHABLE(v, f) \
|
||||
((time.tv_sec <= VTONFS(v)->n_expiry || \
|
||||
VFSTONFS((v)->v_mount)->nm_timeouts >= VFSTONFS((v)->v_mount)->nm_deadthresh) \
|
||||
&& (VTONFS(v)->n_flag & NQNFSNONCACHE) == 0 && \
|
||||
((f) == NQL_READ || (VTONFS(v)->n_flag & NQNFSWRITE)))
|
||||
((f) == ND_READ || (VTONFS(v)->n_flag & NQNFSWRITE)))
|
||||
|
||||
#define NQNFS_NEEDLEASE(v, p) \
|
||||
(time.tv_sec > VTONFS(v)->n_expiry ? \
|
||||
@ -184,7 +176,7 @@ struct nqm {
|
||||
(((time.tv_sec + NQ_RENEWAL) > VTONFS(v)->n_expiry && \
|
||||
nqnfs_piggy[p]) ? \
|
||||
((VTONFS(v)->n_flag & NQNFSWRITE) ? \
|
||||
NQL_WRITE : nqnfs_piggy[p]) : 0))
|
||||
ND_WRITE : nqnfs_piggy[p]) : 0))
|
||||
|
||||
/*
|
||||
* List head for timer queue.
|
||||
@ -204,13 +196,12 @@ u_long nqfhhash;
|
||||
*/
|
||||
#define NQNFS_EXPIRED 500
|
||||
#define NQNFS_TRYLATER 501
|
||||
#define NQNFS_AUTHERR 502
|
||||
|
||||
#ifdef KERNEL
|
||||
void nfs_lease_check __P((struct vnode *, struct proc *, struct ucred *, int));
|
||||
void nfs_lease_updatetime __P((int));
|
||||
#if defined(KERNEL) || defined(_KERNEL)
|
||||
void nqnfs_lease_check __P((struct vnode *, struct proc *, struct ucred *, int));
|
||||
void nqnfs_lease_updatetime __P((int));
|
||||
int nqsrv_cmpnam __P((struct nfssvc_sock *,struct mbuf *,struct nqhost *));
|
||||
int nqsrv_getlease __P((struct vnode *,u_long *,int,struct nfsd *,struct mbuf *,int *,u_quad_t *,struct ucred *));
|
||||
int nqsrv_getlease __P((struct vnode *,u_long *,int,struct nfssvc_sock *,struct proc *,struct mbuf *,int *,u_quad_t *,struct ucred *));
|
||||
int nqnfs_getlease __P((struct vnode *,int,struct ucred *,struct proc *));
|
||||
int nqnfs_callback __P((struct nfsmount *,struct mbuf *,struct mbuf *,caddr_t));
|
||||
int nqnfs_clientd __P((struct nfsmount *,struct ucred *,struct nfsd_cargs *,int,caddr_t,struct proc *));
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)rpcv2.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: rpcv2.h,v 1.2 1994/08/02 07:52:29 davidg Exp $
|
||||
* $Id: rpcv2.h,v 1.3 1994/08/21 06:50:15 paul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_RPCV2_H_
|
||||
@ -52,10 +52,18 @@
|
||||
#define RPCAUTH_NULL 0
|
||||
#define RPCAUTH_UNIX 1
|
||||
#define RPCAUTH_SHORT 2
|
||||
#define RPCAUTH_KERB4 4
|
||||
#define RPCAUTH_NQNFS 300000
|
||||
#define RPCAUTH_MAXSIZ 400
|
||||
#define RPCVERF_MAXSIZ 12 /* For Kerb, can actually be 400 */
|
||||
#define RPCAUTH_UNIXGIDS 16
|
||||
|
||||
/*
|
||||
* Constants associated with authentication flavours.
|
||||
*/
|
||||
#define RPCAKN_FULLNAME 0
|
||||
#define RPCAKN_NICKNAME 1
|
||||
|
||||
/* Rpc Constants */
|
||||
#define RPC_CALL 0
|
||||
#define RPC_REPLY 1
|
||||
@ -91,4 +99,43 @@
|
||||
#define RPCMNT_PATHLEN 1024
|
||||
#define RPCPROG_NFS 100003
|
||||
|
||||
/*
|
||||
* Structures used for RPCAUTH_KERB4.
|
||||
*/
|
||||
struct nfsrpc_fullverf {
|
||||
u_long t1;
|
||||
u_long t2;
|
||||
u_long w2;
|
||||
};
|
||||
|
||||
struct nfsrpc_fullblock {
|
||||
u_long t1;
|
||||
u_long t2;
|
||||
u_long w1;
|
||||
u_long w2;
|
||||
};
|
||||
|
||||
struct nfsrpc_nickverf {
|
||||
u_long kind;
|
||||
struct nfsrpc_fullverf verf;
|
||||
};
|
||||
|
||||
/*
|
||||
* and their sizes in bytes.. If sizeof (struct nfsrpc_xx) != these
|
||||
* constants, well then things will break in mount_nfs and nfsd.
|
||||
*/
|
||||
#define RPCX_FULLVERF 12
|
||||
#define RPCX_FULLBLOCK 16
|
||||
#define RPCX_NICKVERF 16
|
||||
|
||||
#ifdef NFSKERB
|
||||
XXX
|
||||
#else
|
||||
typedef u_char NFSKERBKEY_T[2];
|
||||
typedef u_char NFSKERBKEYSCHED_T[2];
|
||||
#endif
|
||||
#define NFS_KERBSRV "rcmd" /* Kerberos Service for NFS */
|
||||
#define NFS_KERBTTL (30 * 60) /* Credential ttl (sec) */
|
||||
#define NFS_KERBCLOCKSKEW (5 * 60) /* Clock skew (sec) */
|
||||
#define NFS_KERBW1(t) (*((u_long *)(&((t).dat[((t).length + 3) & ~0x3]))))
|
||||
#endif
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)xdr_subs.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: xdr_subs.h,v 1.3 1994/08/21 06:50:16 paul Exp $
|
||||
* $Id: xdr_subs.h,v 1.4 1995/01/10 13:11:42 davidg Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_XDR_SUBS_H_
|
||||
@ -54,28 +54,28 @@
|
||||
#define fxdr_unsigned(t, v) ((t)ntohl((long)(v)))
|
||||
#define txdr_unsigned(v) (htonl((long)(v)))
|
||||
|
||||
#define fxdr_nfstime(f, t) { \
|
||||
(t)->ts_sec = ntohl(((struct nfsv2_time *)(f))->nfs_sec); \
|
||||
if (((struct nfsv2_time *)(f))->nfs_usec != 0xffffffff) \
|
||||
(t)->ts_nsec = 1000 * ntohl(((struct nfsv2_time *)(f))->nfs_usec); \
|
||||
#define fxdr_nfsv2time(f, t) { \
|
||||
(t)->ts_sec = ntohl(((struct nfsv2_time *)(f))->nfsv2_sec); \
|
||||
if (((struct nfsv2_time *)(f))->nfsv2_usec != 0xffffffff) \
|
||||
(t)->ts_nsec = 1000 * ntohl(((struct nfsv2_time *)(f))->nfsv2_usec); \
|
||||
else \
|
||||
(t)->ts_nsec = -1; \
|
||||
(t)->ts_nsec = 0; \
|
||||
}
|
||||
#define txdr_nfstime(f, t) { \
|
||||
((struct nfsv2_time *)(t))->nfs_sec = htonl((f)->ts_sec); \
|
||||
#define txdr_nfsv2time(f, t) { \
|
||||
((struct nfsv2_time *)(t))->nfsv2_sec = htonl((f)->ts_sec); \
|
||||
if ((f)->ts_nsec != -1) \
|
||||
((struct nfsv2_time *)(t))->nfs_usec = htonl((f)->ts_nsec / 1000); \
|
||||
((struct nfsv2_time *)(t))->nfsv2_usec = htonl((f)->ts_nsec / 1000); \
|
||||
else \
|
||||
((struct nfsv2_time *)(t))->nfs_usec = 0xffffffff; \
|
||||
((struct nfsv2_time *)(t))->nfsv2_usec = 0xffffffff; \
|
||||
}
|
||||
|
||||
#define fxdr_nqtime(f, t) { \
|
||||
(t)->ts_sec = ntohl(((struct nqnfs_time *)(f))->nq_sec); \
|
||||
(t)->ts_nsec = ntohl(((struct nqnfs_time *)(f))->nq_nsec); \
|
||||
#define fxdr_nfsv3time(f, t) { \
|
||||
(t)->ts_sec = ntohl(((struct nfsv3_time *)(f))->nfsv3_sec); \
|
||||
(t)->ts_nsec = ntohl(((struct nfsv3_time *)(f))->nfsv3_nsec); \
|
||||
}
|
||||
#define txdr_nqtime(f, t) { \
|
||||
((struct nqnfs_time *)(t))->nq_sec = htonl((f)->ts_sec); \
|
||||
((struct nqnfs_time *)(t))->nq_nsec = htonl((f)->ts_nsec); \
|
||||
#define txdr_nfsv3time(f, t) { \
|
||||
((struct nfsv3_time *)(t))->nfsv3_sec = htonl((f)->ts_sec); \
|
||||
((struct nfsv3_time *)(t))->nfsv3_nsec = htonl((f)->ts_nsec); \
|
||||
}
|
||||
|
||||
#define fxdr_hyper(f, t) { \
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfs.h,v 1.8 1994/11/02 00:11:00 wollman Exp $
|
||||
* $Id: nfs.h,v 1.9 1995/02/14 06:22:18 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFS_H_
|
||||
@ -45,11 +45,12 @@
|
||||
*/
|
||||
|
||||
#define NFS_MAXIOVEC 34
|
||||
#define NFS_HZ 25 /* Ticks per second for NFS timeouts */
|
||||
#define NFS_TIMEO (1*NFS_HZ) /* Default timeout = 1 second */
|
||||
#define NFS_MINTIMEO (1*NFS_HZ) /* Min timeout to use */
|
||||
#define NFS_MAXTIMEO (60*NFS_HZ) /* Max timeout to backoff to */
|
||||
#define NFS_MINIDEMTIMEO (5*NFS_HZ) /* Min timeout for non-idempotent ops*/
|
||||
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
|
||||
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
|
||||
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
|
||||
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
|
||||
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
|
||||
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
|
||||
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
|
||||
#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
|
||||
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
|
||||
@ -62,13 +63,81 @@
|
||||
#endif
|
||||
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
|
||||
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
|
||||
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
|
||||
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
|
||||
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
|
||||
#define NFS_MAXREADDIR NFS_MAXDATA /* Max. size of directory read */
|
||||
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
|
||||
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
|
||||
#define NFS_DIRBLKSIZ 1024 /* Size of an NFS directory block */
|
||||
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
|
||||
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
|
||||
#ifndef NFS_GATHERDELAY
|
||||
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
|
||||
#endif
|
||||
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
|
||||
|
||||
/*
|
||||
* Oddballs
|
||||
*/
|
||||
#define NMOD(a) ((a) % nfs_asyncdaemons)
|
||||
#define NFS_CMPFH(n, f, s) \
|
||||
((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
|
||||
#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
|
||||
#define NFS_SRVMAXDATA(n) \
|
||||
(((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
|
||||
NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* sys/buf.h should be editted to change B_APPENDWRITE --> B_NEEDCOMMIT, but
|
||||
* until then...
|
||||
* Same goes for sys/malloc.h, which needs M_NFSDIROFF,
|
||||
* M_NFSRVDESC and M_NFSBIGFH added.
|
||||
* The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
|
||||
* exclusive create.
|
||||
* The B_INVAFTERWRITE flag should be set to whatever is required by the
|
||||
* buffer cache code to say "Invalidate the block after it is written back".
|
||||
*/
|
||||
#ifndef B_NEEDCOMMIT
|
||||
#define B_NEEDCOMMIT B_APPENDWRITE
|
||||
#endif
|
||||
#ifndef M_NFSRVDESC
|
||||
#define M_NFSRVDESC M_TEMP
|
||||
#endif
|
||||
#ifndef M_NFSDIROFF
|
||||
#define M_NFSDIROFF M_TEMP
|
||||
#endif
|
||||
#ifndef M_NFSBIGFH
|
||||
#define M_NFSBIGFH M_TEMP
|
||||
#endif
|
||||
#ifndef VA_EXCLUSIVE
|
||||
#define VA_EXCLUSIVE 0
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#define B_INVAFTERWRITE B_NOCACHE
|
||||
#else
|
||||
#define B_INVAFTERWRITE B_INVAL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These ifdefs try to handle the differences between the various 4.4BSD-Lite
|
||||
* based vfs interfaces.
|
||||
* btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
|
||||
* differentiate between NetBSD-1.0 and NetBSD-current, so..
|
||||
* I also don't know about BSDi's 2.0 release.
|
||||
*/
|
||||
#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||
#define HAS_VOPLEASE 1
|
||||
#endif
|
||||
#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||
#define HAS_VOPREVOKE 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The IO_METASYNC flag should be implemented for local file systems.
|
||||
* (Until then, it is nothin at all.)
|
||||
*/
|
||||
#ifndef IO_METASYNC
|
||||
#define IO_METASYNC 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the attribute timeout based on how recently the file has been modified.
|
||||
@ -79,6 +148,20 @@
|
||||
((time.tv_sec - (np)->n_mtime) / 10 > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
|
||||
(time.tv_sec - (np)->n_mtime) / 10))
|
||||
|
||||
/*
|
||||
* Expected allocation sizes for major data structures. If the actual size
|
||||
* of the structure exceeds these sizes, then malloc() will be allocating
|
||||
* almost twice the memory required. This is used in nfs_init() to warn
|
||||
* the sysadmin that the size of a structure should be reduced.
|
||||
* (These sizes are always a power of 2. If the kernel malloc() changes
|
||||
* to one that does not allocate space in powers of 2 size, then this all
|
||||
* becomes bunk!)
|
||||
*/
|
||||
#define NFS_NODEALLOC 256
|
||||
#define NFS_MNTALLOC 512
|
||||
#define NFS_SVCALLOC 256
|
||||
#define NFS_UIDALLOC 128
|
||||
|
||||
/*
|
||||
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
|
||||
* should ever try and use it.
|
||||
@ -95,7 +178,12 @@ struct nfsd_srvargs {
|
||||
u_long nsd_haddr; /* Ip address of client */
|
||||
struct ucred nsd_cr; /* Cred. uid maps to */
|
||||
int nsd_authlen; /* Length of auth string (ret) */
|
||||
char *nsd_authstr; /* Auth string (ret) */
|
||||
u_char *nsd_authstr; /* Auth string (ret) */
|
||||
int nsd_verflen; /* and the verfier */
|
||||
u_char *nsd_verfstr;
|
||||
struct timeval nsd_timestamp; /* timestamp from verifier */
|
||||
u_long nsd_ttl; /* credential ttl (sec) */
|
||||
NFSKERBKEY_T nsd_key; /* Session key */
|
||||
};
|
||||
|
||||
struct nfsd_cargs {
|
||||
@ -103,7 +191,10 @@ struct nfsd_cargs {
|
||||
uid_t ncd_authuid; /* Effective uid */
|
||||
int ncd_authtype; /* Type of authenticator */
|
||||
int ncd_authlen; /* Length of authenticator string */
|
||||
char *ncd_authstr; /* Authenticator string */
|
||||
u_char *ncd_authstr; /* Authenticator string */
|
||||
int ncd_verflen; /* and the verifier */
|
||||
u_char *ncd_verfstr;
|
||||
NFSKERBKEY_T ncd_key; /* Session key */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -142,6 +233,7 @@ struct nfsstats {
|
||||
int srvnqnfs_leases;
|
||||
int srvnqnfs_maxleases;
|
||||
int srvnqnfs_getleases;
|
||||
int srvvop_writes;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -173,7 +265,7 @@ struct nfsstats {
|
||||
* such as SIGALRM will not expect file I/O system calls to be interrupted
|
||||
* by them and break.
|
||||
*/
|
||||
#ifdef KERNEL
|
||||
#if defined(KERNEL) || defined(_KERNEL)
|
||||
|
||||
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
|
||||
|
||||
@ -224,17 +316,29 @@ TAILQ_HEAD(, nfsreq) nfs_reqq;
|
||||
#define R_MUSTRESEND 0x40 /* Must resend request */
|
||||
#define R_GETONEREP 0x80 /* Probe for one reply only */
|
||||
|
||||
extern struct nfsstats nfsstats;
|
||||
|
||||
/*
|
||||
* A list of nfssvc_sock structures is maintained with all the sockets
|
||||
* that require service by the nfsd.
|
||||
* The nfsuid structs hang off of the nfssvc_sock structs in both lru
|
||||
* and uid hash lists.
|
||||
*/
|
||||
#define NUIDHASHSIZ 32
|
||||
#ifndef NFS_UIDHASHSIZ
|
||||
#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
|
||||
#endif
|
||||
#define NUIDHASH(sock, uid) \
|
||||
(&(sock)->ns_uidhashtbl[(uid) & (sock)->ns_uidhash])
|
||||
(&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
|
||||
#ifndef NFS_WDELAYHASHSIZ
|
||||
#define NFS_WDELAYHASHSIZ 16 /* and with this */
|
||||
#endif
|
||||
#define NWDELAYHASH(sock, f) \
|
||||
(&(sock)->ns_wdelayhashtbl[(*((u_long *)(f))) % NFS_WDELAYHASHSIZ])
|
||||
#ifndef NFS_MUIDHASHSIZ
|
||||
#define NFS_MUIDHASHSIZ 67 /* Tune the size of nfsmount with this */
|
||||
#endif
|
||||
#define NMUIDHASH(nmp, uid) \
|
||||
(&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
|
||||
#define NFSNOHASH(fhsum) \
|
||||
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
|
||||
|
||||
/*
|
||||
* Network address hash list element
|
||||
@ -248,35 +352,41 @@ struct nfsuid {
|
||||
TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
|
||||
LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
|
||||
int nu_flag; /* Flags */
|
||||
uid_t nu_uid; /* Uid mapped by this entry */
|
||||
union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
|
||||
struct ucred nu_cr; /* Cred uid mapped to */
|
||||
int nu_expire; /* Expiry time (sec) */
|
||||
struct timeval nu_timestamp; /* Kerb. timestamp */
|
||||
u_long nu_nickname; /* Nickname on server */
|
||||
NFSKERBKEY_T nu_key; /* and session key */
|
||||
};
|
||||
|
||||
#define nu_inetaddr nu_haddr.had_inetaddr
|
||||
#define nu_nam nu_haddr.had_nam
|
||||
/* Bits for nu_flag */
|
||||
#define NU_INETADDR 0x1
|
||||
#define NU_NAM 0x2
|
||||
#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
|
||||
|
||||
struct nfssvc_sock {
|
||||
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
|
||||
TAILQ_HEAD(, nfsuid) ns_uidlruhead;
|
||||
LIST_HEAD(, nfsuid) *ns_uidhashtbl;
|
||||
u_long ns_uidhash;
|
||||
|
||||
int ns_flag;
|
||||
u_long ns_sref;
|
||||
struct file *ns_fp;
|
||||
struct socket *ns_so;
|
||||
int ns_solock;
|
||||
struct mbuf *ns_nam;
|
||||
int ns_cc;
|
||||
struct mbuf *ns_raw;
|
||||
struct mbuf *ns_rawend;
|
||||
int ns_reclen;
|
||||
struct mbuf *ns_rec;
|
||||
struct mbuf *ns_recend;
|
||||
struct mbuf *ns_frag;
|
||||
int ns_flag;
|
||||
int ns_solock;
|
||||
int ns_cc;
|
||||
int ns_reclen;
|
||||
int ns_numuids;
|
||||
u_long ns_sref;
|
||||
LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
|
||||
LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
|
||||
LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
|
||||
};
|
||||
|
||||
/* Bits for "ns_flag" */
|
||||
@ -285,6 +395,7 @@ struct nfssvc_sock {
|
||||
#define SLP_NEEDQ 0x04
|
||||
#define SLP_DISCONN 0x08
|
||||
#define SLP_GETSTREAM 0x10
|
||||
#define SLP_LASTFRAG 0x20
|
||||
#define SLP_ALLFLAGS 0xff
|
||||
|
||||
TAILQ_HEAD(, nfssvc_sock) nfssvc_sockhead;
|
||||
@ -296,73 +407,124 @@ int nfssvc_sockhead_flag;
|
||||
* One of these structures is allocated for each nfsd.
|
||||
*/
|
||||
struct nfsd {
|
||||
TAILQ_ENTRY(nfsd) nd_chain; /* List of all nfsd's */
|
||||
int nd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nd_slp; /* Current socket */
|
||||
struct mbuf *nd_nam; /* Client addr for datagram req. */
|
||||
struct mbuf *nd_mrep; /* Req. mbuf list */
|
||||
struct mbuf *nd_md;
|
||||
caddr_t nd_dpos; /* Position in list */
|
||||
int nd_procnum; /* RPC procedure number */
|
||||
u_long nd_retxid; /* RPC xid */
|
||||
int nd_repstat; /* Reply status value */
|
||||
struct ucred nd_cr; /* Credentials for req. */
|
||||
int nd_nqlflag; /* Leasing flag */
|
||||
u_long nd_duration; /* Lease duration */
|
||||
int nd_authlen; /* Authenticator len */
|
||||
u_char nd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
|
||||
struct proc *nd_procp; /* Proc ptr */
|
||||
TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
|
||||
int nfsd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nfsd_slp; /* Current socket */
|
||||
int nfsd_authlen; /* Authenticator len */
|
||||
u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
|
||||
int nfsd_verflen; /* and the Verifier */
|
||||
u_char nfsd_verfstr[RPCVERF_MAXSIZ];
|
||||
struct proc *nfsd_procp; /* Proc ptr */
|
||||
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
|
||||
};
|
||||
|
||||
/* Bits for "nd_flag" */
|
||||
/* Bits for "nfsd_flag" */
|
||||
#define NFSD_WAITING 0x01
|
||||
#define NFSD_REQINPROG 0x02
|
||||
#define NFSD_NEEDAUTH 0x04
|
||||
#define NFSD_AUTHFAIL 0x08
|
||||
|
||||
/*
|
||||
* This structure is used by the server for describing each request.
|
||||
* Some fields are used only when write request gathering is performed.
|
||||
*/
|
||||
struct nfsrv_descript {
|
||||
u_quad_t nd_time; /* Write deadline (usec) */
|
||||
off_t nd_off; /* Start byte offset */
|
||||
off_t nd_eoff; /* and end byte offset */
|
||||
LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
|
||||
LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
|
||||
LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
|
||||
struct mbuf *nd_mrep; /* Request mbuf list */
|
||||
struct mbuf *nd_md; /* Current dissect mbuf */
|
||||
struct mbuf *nd_mreq; /* Reply mbuf list */
|
||||
struct mbuf *nd_nam; /* and socket addr */
|
||||
struct mbuf *nd_nam2; /* return socket addr */
|
||||
caddr_t nd_dpos; /* Current dissect pos */
|
||||
int nd_procnum; /* RPC # */
|
||||
int nd_stable; /* storage type */
|
||||
int nd_flag; /* nd_flag */
|
||||
int nd_len; /* Length of this write */
|
||||
int nd_repstat; /* Reply status */
|
||||
u_long nd_retxid; /* Reply xid */
|
||||
u_long nd_duration; /* Lease duration */
|
||||
struct timeval nd_starttime; /* Time RPC initiated */
|
||||
fhandle_t nd_fh; /* File handle */
|
||||
struct ucred nd_cr; /* Credentials */
|
||||
};
|
||||
|
||||
/* Bits for "nd_flag" */
|
||||
#define ND_READ LEASE_READ
|
||||
#define ND_WRITE LEASE_WRITE
|
||||
#define ND_CHECK 0x04
|
||||
#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
|
||||
#define ND_NFSV3 0x08
|
||||
#define ND_NQNFS 0x10
|
||||
#define ND_KERBNICK 0x20
|
||||
#define ND_KERBFULL 0x40
|
||||
#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
|
||||
|
||||
TAILQ_HEAD(, nfsd) nfsd_head;
|
||||
int nfsd_head_flag;
|
||||
#define NFSD_CHECKSLP 0x01
|
||||
|
||||
/*
|
||||
* These macros compare nfsrv_descript structures.
|
||||
*/
|
||||
#define NFSW_CONTIG(o, n) \
|
||||
((o)->nd_eoff >= (n)->nd_off && \
|
||||
!bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
|
||||
|
||||
#define NFSW_SAMECRED(o, n) \
|
||||
(((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
|
||||
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
|
||||
sizeof (struct ucred)))
|
||||
|
||||
int nfs_reply __P((struct nfsreq *));
|
||||
int nfs_getreq __P((struct nfsd *,int));
|
||||
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
|
||||
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
|
||||
int nfs_rephead __P((int,struct nfsd *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_rephead __P((int,struct nfsrv_descript *,struct nfssvc_sock *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_sndlock __P((int *,struct nfsreq *));
|
||||
int nfs_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
|
||||
int nfs_vinvalbuf __P((struct vnode *,int,struct ucred *,struct proc *,int));
|
||||
int nfs_readrpc __P((struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int));
|
||||
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int *,int *));
|
||||
int nfs_readdirrpc __P((register struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
|
||||
int nfs_asyncio __P((struct buf *,struct ucred *));
|
||||
int nfs_doio __P((struct buf *,struct ucred *,struct proc *));
|
||||
int nfs_readlinkrpc __P((struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_sigintr __P((struct nfsmount *,struct nfsreq *r,struct proc *));
|
||||
int nfs_readdirlookrpc __P((struct vnode *,register struct uio *,struct ucred *));
|
||||
int nfs_readdirplusrpc __P((struct vnode *,register struct uio *,struct ucred *));
|
||||
int nfsm_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
|
||||
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *));
|
||||
void nfsm_srvfattr __P((struct nfsrv_descript *,struct vattr *,struct nfs_fattr *));
|
||||
void nfsm_srvwcc __P((struct nfsrv_descript *,int,struct vattr *,int,struct vattr *,struct mbuf **,char **));
|
||||
void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct mbuf **,char **));
|
||||
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *,int));
|
||||
int nfsrv_access __P((struct vnode *,int,struct ucred *,int,struct proc *));
|
||||
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
|
||||
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
|
||||
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct proc *));
|
||||
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
|
||||
void nfsm_adj __P((struct mbuf *,int,int));
|
||||
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
|
||||
void nfsrv_initcache __P((void));
|
||||
int nfs_rcvlock __P((struct nfsreq *));
|
||||
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,int *,char **,int *));
|
||||
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,char **,int *,char *,int *,NFSKERBKEY_T));
|
||||
int nfs_getnickauth __P((struct nfsmount *,struct ucred *,char **,int *,char *,int));
|
||||
int nfs_savenickauth __P((struct nfsmount *,struct ucred *,int,NFSKERBKEY_T,struct mbuf **,char **,struct mbuf *));
|
||||
int nfs_msg __P((struct proc *,char *,char *));
|
||||
int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
|
||||
int nfsrv_getstream __P((struct nfssvc_sock *,int));
|
||||
void nfs_nhinit __P((void));
|
||||
void nfs_timer __P((void*));
|
||||
struct nfsnodehashhead * nfs_hash __P((nfsv2fh_t *));
|
||||
u_long nfs_hash __P((nfsfh_t *,int));
|
||||
int nfssvc_iod __P((struct proc *));
|
||||
int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,struct proc *));
|
||||
int nfssvc_addsock __P((struct file *,struct mbuf *));
|
||||
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *));
|
||||
int nfsrv_getcache __P((struct mbuf *,struct nfsd *,struct mbuf **));
|
||||
void nfsrv_updatecache __P((struct mbuf *,struct nfsd *,int,struct mbuf *));
|
||||
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
|
||||
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
|
||||
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
|
||||
int mountnfs __P((struct nfs_args *,struct mount *,struct mbuf *,char *,char *,struct vnode **));
|
||||
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
|
||||
int nfs_getattrcache __P((struct vnode *,struct vattr *));
|
||||
@ -370,9 +532,20 @@ int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
|
||||
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
|
||||
int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
|
||||
void nfsrv_init __P((int));
|
||||
void nfs_clearcommit __P((struct mount *));
|
||||
int nfsrv_errmap __P((struct nfsrv_descript *, int));
|
||||
void nfsrvw_coalesce __P((struct nfsrv_descript *,struct nfsrv_descript *));
|
||||
void nfsrvw_sort __P((gid_t [],int));
|
||||
void nfsrv_setcred __P((struct ucred *,struct ucred *));
|
||||
int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
|
||||
int nfs_writebp __P((struct buf *,int));
|
||||
int nfsrv_vput __P(( struct vnode * ));
|
||||
int nfsrv_vrele __P(( struct vnode * ));
|
||||
int nfsrv_vmio __P(( struct vnode * ));
|
||||
int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
|
||||
struct proc *, struct mbuf **));
|
||||
int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
|
||||
struct proc *p));
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_bio.c 8.5 (Berkeley) 1/4/94
|
||||
* $Id: nfs_bio.c,v 1.13 1995/05/21 21:39:21 davidg Exp $
|
||||
* $Id: nfs_bio.c,v 1.14 1995/05/30 08:12:35 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -49,16 +49,30 @@
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <nfs/nfsnode.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/nqnfs.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
|
||||
struct buf *nfs_getcacheblk();
|
||||
extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
|
||||
extern int nfs_numasync;
|
||||
extern struct nfsstats nfsstats;
|
||||
|
||||
/*
|
||||
* Ifdefs for FreeBSD-current's merged VM/buffer cache. It is unfortunate
|
||||
* that this isn't done inside getblk() and brelse() so these calls
|
||||
* wouldn't need to be here.
|
||||
*/
|
||||
#ifdef B_VMIO
|
||||
#define vnode_pager_uncache(vp)
|
||||
#else
|
||||
#define vfs_busy_pages(bp, f)
|
||||
#define vfs_unbusy_pages(bp)
|
||||
#define vfs_dirty_pages(bp)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Vnode op for read using bio
|
||||
@ -72,29 +86,28 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
struct ucred *cred;
|
||||
{
|
||||
register struct nfsnode *np = VTONFS(vp);
|
||||
register int biosize, diff;
|
||||
register int biosize, diff, i;
|
||||
struct buf *bp = 0, *rabp;
|
||||
struct vattr vattr;
|
||||
struct proc *p;
|
||||
struct nfsmount *nmp;
|
||||
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||
daddr_t lbn, rabn;
|
||||
int bufsize;
|
||||
int nra, error = 0, n = 0, on = 0, not_readin;
|
||||
nfsquad_t tquad;
|
||||
|
||||
#ifdef lint
|
||||
ioflag = ioflag;
|
||||
#endif /* lint */
|
||||
#ifdef DIAGNOSTIC
|
||||
if (uio->uio_rw != UIO_READ)
|
||||
panic("nfs_read mode");
|
||||
#endif
|
||||
if (uio->uio_resid == 0)
|
||||
return (0);
|
||||
if (uio->uio_offset < 0 && vp->v_type != VDIR)
|
||||
if (uio->uio_offset < 0)
|
||||
return (EINVAL);
|
||||
nmp = VFSTONFS(vp->v_mount);
|
||||
biosize = NFS_MAXDGRAMDATA;
|
||||
p = uio->uio_procp;
|
||||
if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
|
||||
(void)nfs_fsinfo(nmp, vp, cred, p);
|
||||
biosize = nmp->nm_rsize;
|
||||
/*
|
||||
* For nfs, cache consistency can only be maintained approximately.
|
||||
* Although RFC1094 does not specify the criteria, the following is
|
||||
@ -107,8 +120,6 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
* server, so flush all of the file's data out of the cache.
|
||||
* Then force a getattr rpc to ensure that you have up to date
|
||||
* attributes.
|
||||
* The mount flag NFSMNT_MYWRITE says "Assume that my writes are
|
||||
* the ones changing the modify time.
|
||||
* NB: This implies that cache data can be read when up to
|
||||
* NFS_ATTRTIMEO seconds out of date. If you find that you need current
|
||||
* attributes this could be forced by setting n_attrstamp to 0 before
|
||||
@ -116,14 +127,15 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
*/
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) == 0 && vp->v_type != VLNK) {
|
||||
if (np->n_flag & NMODIFIED) {
|
||||
if ((nmp->nm_flag & NFSMNT_MYWRITE) == 0 ||
|
||||
vp->v_type != VREG) {
|
||||
if (vp->v_type != VREG) {
|
||||
if (vp->v_type != VDIR)
|
||||
panic("nfs: bioread, not dir");
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
np->n_attrstamp = 0;
|
||||
np->n_direofoffset = 0;
|
||||
error = VOP_GETATTR(vp, &vattr, cred, p);
|
||||
if (error)
|
||||
return (error);
|
||||
@ -133,7 +145,8 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
if (error)
|
||||
return (error);
|
||||
if (np->n_mtime != vattr.va_mtime.ts_sec) {
|
||||
np->n_direofoffset = 0;
|
||||
if (vp->v_type == VDIR)
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
@ -147,27 +160,24 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
* Get a valid lease. If cached data is stale, flush it.
|
||||
*/
|
||||
if (nmp->nm_flag & NFSMNT_NQNFS) {
|
||||
if (NQNFS_CKINVALID(vp, np, NQL_READ)) {
|
||||
if (NQNFS_CKINVALID(vp, np, ND_READ)) {
|
||||
do {
|
||||
error = nqnfs_getlease(vp, NQL_READ, cred, p);
|
||||
error = nqnfs_getlease(vp, ND_READ, cred, p);
|
||||
} while (error == NQNFS_EXPIRED);
|
||||
if (error)
|
||||
return (error);
|
||||
if (np->n_lrev != np->n_brev ||
|
||||
(np->n_flag & NQNFSNONCACHE) ||
|
||||
((np->n_flag & NMODIFIED) && vp->v_type == VDIR)) {
|
||||
if (vp->v_type == VDIR) {
|
||||
np->n_direofoffset = 0;
|
||||
cache_purge(vp);
|
||||
}
|
||||
if (vp->v_type == VDIR)
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
np->n_brev = np->n_lrev;
|
||||
}
|
||||
} else if (vp->v_type == VDIR && (np->n_flag & NMODIFIED)) {
|
||||
np->n_direofoffset = 0;
|
||||
cache_purge(vp);
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
@ -176,33 +186,27 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
if (np->n_flag & NQNFSNONCACHE) {
|
||||
switch (vp->v_type) {
|
||||
case VREG:
|
||||
error = nfs_readrpc(vp, uio, cred);
|
||||
break;
|
||||
return (nfs_readrpc(vp, uio, cred));
|
||||
case VLNK:
|
||||
error = nfs_readlinkrpc(vp, uio, cred);
|
||||
break;
|
||||
return (nfs_readlinkrpc(vp, uio, cred));
|
||||
case VDIR:
|
||||
error = nfs_readdirrpc(vp, uio, cred);
|
||||
break;
|
||||
default:
|
||||
printf(" NQNFSNONCACHE: type %x unexpected\n",
|
||||
vp->v_type);
|
||||
break;
|
||||
};
|
||||
return (error);
|
||||
}
|
||||
switch (vp->v_type) {
|
||||
case VREG:
|
||||
nfsstats.biocache_reads++;
|
||||
lbn = uio->uio_offset / biosize;
|
||||
on = uio->uio_offset & (biosize-1);
|
||||
on = uio->uio_offset & (biosize - 1);
|
||||
not_readin = 1;
|
||||
|
||||
/*
|
||||
* Start the read ahead(s), as required.
|
||||
*/
|
||||
if (nfs_numasync > 0 && nmp->nm_readahead > 0 &&
|
||||
lbn == vp->v_lastr + 1) {
|
||||
if (nfs_numasync > 0 && nmp->nm_readahead > 0) {
|
||||
for (nra = 0; nra < nmp->nm_readahead &&
|
||||
(lbn + 1 + nra) * biosize < np->n_size; nra++) {
|
||||
rabn = lbn + 1 + nra;
|
||||
@ -296,32 +300,55 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
break;
|
||||
case VDIR:
|
||||
nfsstats.biocache_readdirs++;
|
||||
lbn = (daddr_t)uio->uio_offset;
|
||||
lbn = uio->uio_offset / NFS_DIRBLKSIZ;
|
||||
on = uio->uio_offset & (NFS_DIRBLKSIZ - 1);
|
||||
bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, p);
|
||||
if (!bp)
|
||||
return (EINTR);
|
||||
|
||||
return (EINTR);
|
||||
if ((bp->b_flags & B_CACHE) == 0) {
|
||||
bp->b_flags |= B_READ;
|
||||
vfs_busy_pages(bp, 0);
|
||||
error = nfs_doio(bp, cred, p);
|
||||
if (error) {
|
||||
bp->b_flags |= B_ERROR;
|
||||
brelse(bp);
|
||||
return (error);
|
||||
bp->b_flags |= B_READ;
|
||||
vfs_busy_pages(bp, 0);
|
||||
error = nfs_doio(bp, cred, p);
|
||||
if (error) {
|
||||
brelse(bp);
|
||||
while (error == NFSERR_BAD_COOKIE) {
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, 0, cred, p, 1);
|
||||
/*
|
||||
* Yuck! The directory has been modified on the
|
||||
* server. The only way to get the block is by
|
||||
* reading from the beginning to get all the
|
||||
* offset cookies.
|
||||
*/
|
||||
for (i = 0; i <= lbn && !error; i++) {
|
||||
bp = nfs_getcacheblk(vp, i, NFS_DIRBLKSIZ, p);
|
||||
if (!bp)
|
||||
return (EINTR);
|
||||
if ((bp->b_flags & B_DONE) == 0) {
|
||||
bp->b_flags |= B_READ;
|
||||
vfs_busy_pages(bp, 0);
|
||||
error = nfs_doio(bp, cred, p);
|
||||
if (error)
|
||||
brelse(bp);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If not eof and read aheads are enabled, start one.
|
||||
* (You need the current block first, so that you have the
|
||||
* directory offset cookie of the next block.
|
||||
* directory offset cookie of the next block.)
|
||||
*/
|
||||
rabn = bp->b_blkno;
|
||||
if (nfs_numasync > 0 && nmp->nm_readahead > 0 &&
|
||||
rabn != 0 && rabn != np->n_direofoffset &&
|
||||
!incore(vp, rabn)) {
|
||||
rabp = nfs_getcacheblk(vp, rabn, NFS_DIRBLKSIZ, p);
|
||||
(np->n_direofoffset == 0 ||
|
||||
(lbn + 1) * NFS_DIRBLKSIZ < np->n_direofoffset) &&
|
||||
!(np->n_flag & NQNFSNONCACHE) &&
|
||||
!incore(vp, lbn + 1)) {
|
||||
rabp = nfs_getcacheblk(vp, lbn + 1, NFS_DIRBLKSIZ, p);
|
||||
if (rabp) {
|
||||
if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) {
|
||||
rabp->b_flags |= (B_READ | B_ASYNC);
|
||||
@ -336,11 +363,10 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
}
|
||||
}
|
||||
}
|
||||
on = 0;
|
||||
n = min(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid);
|
||||
n = min(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid - on);
|
||||
break;
|
||||
default:
|
||||
printf(" nfsbioread: type %x unexpected\n",vp->v_type);
|
||||
printf(" nfs_bioread: type %x unexpected\n",vp->v_type);
|
||||
break;
|
||||
};
|
||||
|
||||
@ -354,11 +380,11 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
n = 0;
|
||||
break;
|
||||
case VDIR:
|
||||
uio->uio_offset = bp->b_blkno;
|
||||
if (np->n_flag & NQNFSNONCACHE)
|
||||
bp->b_flags |= B_INVAL;
|
||||
break;
|
||||
default:
|
||||
printf(" nfsbioread: type %x unexpected\n",vp->v_type);
|
||||
break;
|
||||
printf(" nfs_bioread: type %x unexpected\n",vp->v_type);
|
||||
}
|
||||
brelse(bp);
|
||||
} while (error == 0 && uio->uio_resid > 0 && n > 0);
|
||||
@ -386,10 +412,10 @@ nfs_write(ap)
|
||||
int ioflag = ap->a_ioflag;
|
||||
struct buf *bp;
|
||||
struct vattr vattr;
|
||||
struct nfsmount *nmp;
|
||||
daddr_t lbn;
|
||||
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||
daddr_t lbn, bn;
|
||||
int bufsize;
|
||||
int n, on, error = 0;
|
||||
int n, on, error = 0, iomode, must_commit;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (uio->uio_rw != UIO_WRITE)
|
||||
@ -403,6 +429,8 @@ nfs_write(ap)
|
||||
np->n_flag &= ~NWRITEERR;
|
||||
return (np->n_error);
|
||||
}
|
||||
if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
|
||||
(void)nfs_fsinfo(nmp, vp, cred, p);
|
||||
if (ioflag & (IO_APPEND | IO_SYNC)) {
|
||||
if (np->n_flag & NMODIFIED) {
|
||||
np->n_attrstamp = 0;
|
||||
@ -418,7 +446,6 @@ nfs_write(ap)
|
||||
uio->uio_offset = np->n_size;
|
||||
}
|
||||
}
|
||||
nmp = VFSTONFS(vp->v_mount);
|
||||
if (uio->uio_offset < 0)
|
||||
return (EINVAL);
|
||||
if (uio->uio_resid == 0)
|
||||
@ -437,7 +464,7 @@ nfs_write(ap)
|
||||
* will be the same size within a filesystem. nfs_writerpc will
|
||||
* still use nm_wsize when sizing the rpc's.
|
||||
*/
|
||||
biosize = NFS_MAXDGRAMDATA;
|
||||
biosize = nmp->nm_rsize;
|
||||
do {
|
||||
|
||||
/*
|
||||
@ -445,12 +472,11 @@ nfs_write(ap)
|
||||
*/
|
||||
/*
|
||||
* Check for a valid write lease.
|
||||
* If non-cachable, just do the rpc
|
||||
*/
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
NQNFS_CKINVALID(vp, np, NQL_WRITE)) {
|
||||
NQNFS_CKINVALID(vp, np, ND_WRITE)) {
|
||||
do {
|
||||
error = nqnfs_getlease(vp, NQL_WRITE, cred, p);
|
||||
error = nqnfs_getlease(vp, ND_WRITE, cred, p);
|
||||
} while (error == NQNFS_EXPIRED);
|
||||
if (error)
|
||||
return (error);
|
||||
@ -462,8 +488,13 @@ nfs_write(ap)
|
||||
np->n_brev = np->n_lrev;
|
||||
}
|
||||
}
|
||||
if (np->n_flag & NQNFSNONCACHE)
|
||||
return (nfs_writerpc(vp, uio, cred, ioflag));
|
||||
if ((np->n_flag & NQNFSNONCACHE) && uio->uio_iovcnt == 1) {
|
||||
iomode = NFSV3WRITE_FILESYNC;
|
||||
error = nfs_writerpc(vp, uio, cred, &iomode, &must_commit);
|
||||
if (must_commit)
|
||||
nfs_clearcommit(vp->v_mount);
|
||||
return (error);
|
||||
}
|
||||
nfsstats.biocache_writes++;
|
||||
lbn = uio->uio_offset / biosize;
|
||||
on = uio->uio_offset & (biosize-1);
|
||||
@ -509,9 +540,9 @@ nfs_write(ap)
|
||||
* In case getblk() and/or bwrite() delayed us.
|
||||
*/
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
NQNFS_CKINVALID(vp, np, NQL_WRITE)) {
|
||||
NQNFS_CKINVALID(vp, np, ND_WRITE)) {
|
||||
do {
|
||||
error = nqnfs_getlease(vp, NQL_WRITE, cred, p);
|
||||
error = nqnfs_getlease(vp, ND_WRITE, cred, p);
|
||||
} while (error == NQNFS_EXPIRED);
|
||||
if (error) {
|
||||
brelse(bp);
|
||||
@ -540,7 +571,6 @@ nfs_write(ap)
|
||||
bp->b_dirtyoff = on;
|
||||
bp->b_dirtyend = on + n;
|
||||
}
|
||||
#ifndef notdef
|
||||
if (bp->b_validend == 0 || bp->b_validend < bp->b_dirtyoff ||
|
||||
bp->b_validoff > bp->b_dirtyend) {
|
||||
bp->b_validoff = bp->b_dirtyoff;
|
||||
@ -549,13 +579,6 @@ nfs_write(ap)
|
||||
bp->b_validoff = min(bp->b_validoff, bp->b_dirtyoff);
|
||||
bp->b_validend = max(bp->b_validend, bp->b_dirtyend);
|
||||
}
|
||||
#else
|
||||
bp->b_validoff = bp->b_dirtyoff;
|
||||
bp->b_validend = bp->b_dirtyend;
|
||||
#endif
|
||||
if (ioflag & IO_APPEND)
|
||||
bp->b_flags |= B_APPENDWRITE;
|
||||
|
||||
/*
|
||||
* If the lease is non-cachable or IO_SYNC do bwrite().
|
||||
*/
|
||||
@ -564,10 +587,16 @@ nfs_write(ap)
|
||||
error = VOP_BWRITE(bp);
|
||||
if (error)
|
||||
return (error);
|
||||
if (np->n_flag & NQNFSNONCACHE) {
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
} else if ((n + on) == biosize &&
|
||||
(nmp->nm_flag & NFSMNT_NQNFS) == 0) {
|
||||
bp->b_proc = (struct proc *)0;
|
||||
bawrite(bp);
|
||||
bp->b_flags |= B_ASYNC;
|
||||
(void)nfs_writebp(bp, 0);
|
||||
} else
|
||||
bdwrite(bp);
|
||||
} while (uio->uio_resid > 0 && n > 0);
|
||||
@ -590,6 +619,7 @@ nfs_getcacheblk(vp, bn, size, p)
|
||||
{
|
||||
register struct buf *bp;
|
||||
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||
int biosize = nmp->nm_rsize;
|
||||
|
||||
if (nmp->nm_flag & NFSMNT_INT) {
|
||||
bp = getblk(vp, bn, size, PCATCH, 0);
|
||||
@ -602,7 +632,7 @@ nfs_getcacheblk(vp, bn, size, p)
|
||||
bp = getblk(vp, bn, size, 0, 0);
|
||||
|
||||
if( vp->v_type == VREG)
|
||||
bp->b_blkno = (bn * NFS_MAXDGRAMDATA) / DEV_BSIZE;
|
||||
bp->b_blkno = (bn * biosize) / DEV_BSIZE;
|
||||
|
||||
return (bp);
|
||||
}
|
||||
@ -689,6 +719,7 @@ nfs_asyncio(bp, cred)
|
||||
bp->b_rcred = cred;
|
||||
}
|
||||
} else {
|
||||
bp->b_flags |= B_WRITEINPROG;
|
||||
if (bp->b_wcred == NOCRED && cred != NOCRED) {
|
||||
crhold(cred);
|
||||
bp->b_wcred = cred;
|
||||
@ -700,7 +731,25 @@ nfs_asyncio(bp, cred)
|
||||
wakeup((caddr_t)&nfs_iodwant[i]);
|
||||
return (0);
|
||||
}
|
||||
return (EIO);
|
||||
|
||||
/*
|
||||
* If it is a read or a write already marked B_WRITEINPROG or B_NOCACHE
|
||||
* return EIO so the process will call nfs_doio() and do it
|
||||
* synchronously.
|
||||
*/
|
||||
if (bp->b_flags & (B_READ | B_WRITEINPROG | B_NOCACHE))
|
||||
return (EIO);
|
||||
|
||||
/*
|
||||
* Just turn the async write into a delayed write, instead of
|
||||
* doing in synchronously. Hopefully, at least one of the nfsiods
|
||||
* is currently doing a write for this file and will pick up the
|
||||
* delayed writes before going back to sleep.
|
||||
*/
|
||||
bp->b_flags |= B_DELWRI;
|
||||
reassignbuf(bp, bp->b_vp);
|
||||
biodone(bp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -717,9 +766,10 @@ nfs_doio(bp, cr, p)
|
||||
register struct vnode *vp;
|
||||
struct nfsnode *np;
|
||||
struct nfsmount *nmp;
|
||||
int error = 0, diff, len;
|
||||
int error = 0, diff, len, iomode, must_commit = 0;
|
||||
struct uio uio;
|
||||
struct iovec io;
|
||||
nfsquad_t tquad;
|
||||
|
||||
vp = bp->b_vp;
|
||||
np = VTONFS(vp);
|
||||
@ -740,15 +790,18 @@ nfs_doio(bp, cr, p)
|
||||
io.iov_len = uiop->uio_resid = bp->b_bcount;
|
||||
/* mapping was done by vmapbuf() */
|
||||
io.iov_base = bp->b_data;
|
||||
uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
|
||||
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
|
||||
if (bp->b_flags & B_READ) {
|
||||
uiop->uio_rw = UIO_READ;
|
||||
nfsstats.read_physios++;
|
||||
error = nfs_readrpc(vp, uiop, cr);
|
||||
} else {
|
||||
int com;
|
||||
|
||||
iomode = NFSV3WRITE_DATASYNC;
|
||||
uiop->uio_rw = UIO_WRITE;
|
||||
nfsstats.write_physios++;
|
||||
error = nfs_writerpc(vp, uiop, cr,0);
|
||||
error = nfs_writerpc(vp, uiop, cr, &iomode, &com);
|
||||
}
|
||||
if (error) {
|
||||
bp->b_flags |= B_ERROR;
|
||||
@ -760,7 +813,7 @@ nfs_doio(bp, cr, p)
|
||||
uiop->uio_rw = UIO_READ;
|
||||
switch (vp->v_type) {
|
||||
case VREG:
|
||||
uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
|
||||
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
|
||||
nfsstats.read_bios++;
|
||||
error = nfs_readrpc(vp, uiop, cr);
|
||||
if (!error) {
|
||||
@ -773,7 +826,7 @@ nfs_doio(bp, cr, p)
|
||||
* Just zero fill the rest of the valid area.
|
||||
*/
|
||||
diff = bp->b_bcount - uiop->uio_resid;
|
||||
len = np->n_size - (bp->b_blkno * DEV_BSIZE
|
||||
len = np->n_size - (((u_quad_t)bp->b_blkno) * DEV_BSIZE
|
||||
+ diff);
|
||||
if (len > 0) {
|
||||
len = min(len, uiop->uio_resid);
|
||||
@ -786,31 +839,34 @@ nfs_doio(bp, cr, p)
|
||||
}
|
||||
if (p && (vp->v_flag & VTEXT) &&
|
||||
(((nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
NQNFS_CKINVALID(vp, np, NQL_READ) &&
|
||||
NQNFS_CKINVALID(vp, np, ND_READ) &&
|
||||
np->n_lrev != np->n_brev) ||
|
||||
(!(nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
np->n_mtime != np->n_vattr.va_mtime.ts_sec))) {
|
||||
uprintf("Process killed due to text file modification\n");
|
||||
psignal(p, SIGKILL);
|
||||
#ifdef __NetBSD__
|
||||
p->p_holdcnt++;
|
||||
#else
|
||||
p->p_flag |= P_NOSWAP;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case VLNK:
|
||||
uiop->uio_offset = 0;
|
||||
uiop->uio_offset = (off_t)0;
|
||||
nfsstats.readlink_bios++;
|
||||
error = nfs_readlinkrpc(vp, uiop, cr);
|
||||
break;
|
||||
case VDIR:
|
||||
uiop->uio_offset = bp->b_lblkno;
|
||||
nfsstats.readdir_bios++;
|
||||
if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS)
|
||||
error = nfs_readdirlookrpc(vp, uiop, cr);
|
||||
else
|
||||
error = nfs_readdirrpc(vp, uiop, cr);
|
||||
/*
|
||||
* Save offset cookie in b_blkno.
|
||||
*/
|
||||
bp->b_blkno = uiop->uio_offset;
|
||||
uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * NFS_DIRBLKSIZ;
|
||||
if (nmp->nm_flag & NFSMNT_RDIRPLUS) {
|
||||
error = nfs_readdirplusrpc(vp, uiop, cr);
|
||||
if (error == NFSERR_NOTSUPP)
|
||||
nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
|
||||
}
|
||||
if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0)
|
||||
error = nfs_readdirrpc(vp, uiop, cr);
|
||||
break;
|
||||
default:
|
||||
printf("nfs_doio: type %x unexpected\n",vp->v_type);
|
||||
@ -821,32 +877,44 @@ nfs_doio(bp, cr, p)
|
||||
bp->b_error = error;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (((bp->b_blkno * DEV_BSIZE) + bp->b_dirtyend) > np->n_size)
|
||||
bp->b_dirtyend = np->n_size - (bp->b_blkno * DEV_BSIZE);
|
||||
|
||||
if (bp->b_dirtyend > bp->b_dirtyoff) {
|
||||
io.iov_len = uiop->uio_resid = bp->b_dirtyend
|
||||
- bp->b_dirtyoff;
|
||||
uiop->uio_offset = (bp->b_blkno * DEV_BSIZE)
|
||||
+ bp->b_dirtyoff;
|
||||
- bp->b_dirtyoff;
|
||||
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE
|
||||
+ bp->b_dirtyoff;
|
||||
io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;
|
||||
uiop->uio_rw = UIO_WRITE;
|
||||
nfsstats.write_bios++;
|
||||
if (bp->b_flags & B_APPENDWRITE)
|
||||
error = nfs_writerpc(vp, uiop, cr, IO_APPEND);
|
||||
if ((bp->b_flags & (B_ASYNC | B_NEEDCOMMIT | B_NOCACHE)) == B_ASYNC)
|
||||
iomode = NFSV3WRITE_UNSTABLE;
|
||||
else
|
||||
error = nfs_writerpc(vp, uiop, cr, 0);
|
||||
bp->b_flags &= ~(B_WRITEINPROG | B_APPENDWRITE);
|
||||
iomode = NFSV3WRITE_FILESYNC;
|
||||
bp->b_flags |= B_WRITEINPROG;
|
||||
error = nfs_writerpc(vp, uiop, cr, &iomode, &must_commit);
|
||||
if (!error && iomode == NFSV3WRITE_UNSTABLE)
|
||||
bp->b_flags |= B_NEEDCOMMIT;
|
||||
else
|
||||
bp->b_flags &= ~B_NEEDCOMMIT;
|
||||
bp->b_flags &= ~B_WRITEINPROG;
|
||||
|
||||
/*
|
||||
* For an interrupted write, the buffer is still valid and the
|
||||
* write hasn't been pushed to the server yet, so we can't set
|
||||
* B_ERROR and report the interruption by setting B_EINTR. For
|
||||
* the B_ASYNC case, B_EINTR is not relevant, so the rpc attempt
|
||||
* is essentially a noop.
|
||||
*/
|
||||
if (error == EINTR) {
|
||||
/*
|
||||
* For an interrupted write, the buffer is still valid
|
||||
* and the write hasn't been pushed to the server yet,
|
||||
* so we can't set B_ERROR and report the interruption
|
||||
* by setting B_EINTR. For the B_ASYNC case, B_EINTR
|
||||
* is not relevant, so the rpc attempt is essentially
|
||||
* a noop. For the case of a V3 write rpc not being
|
||||
* committed to stable storage, the block is still
|
||||
* dirty and requires either a commit rpc or another
|
||||
* write rpc with iomode == NFSV3WRITE_FILESYNC before
|
||||
* the block is reused. This is indicated by setting
|
||||
* the B_DELWRI and B_NEEDCOMMIT flags.
|
||||
*/
|
||||
if (error == EINTR
|
||||
|| (!error && (bp->b_flags & B_NEEDCOMMIT))) {
|
||||
bp->b_flags &= ~(B_INVAL|B_NOCACHE);
|
||||
bp->b_flags |= B_DELWRI;
|
||||
|
||||
@ -874,6 +942,8 @@ nfs_doio(bp, cr, p)
|
||||
}
|
||||
}
|
||||
bp->b_resid = uiop->uio_resid;
|
||||
if (must_commit)
|
||||
nfs_clearcommit(vp->v_mount);
|
||||
biodone(bp);
|
||||
return (error);
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_syscalls.c 8.3 (Berkeley) 1/4/94
|
||||
* $Id: nfs_syscalls.c,v 1.5 1994/10/17 17:47:38 phk Exp $
|
||||
* $Id: nfs_syscalls.c,v 1.6 1995/05/30 08:12:45 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -61,9 +61,11 @@
|
||||
#ifdef ISO
|
||||
#include <netiso/iso.h>
|
||||
#endif
|
||||
#include <nfs/xdr_subs.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsm_subs.h>
|
||||
#include <nfs/nfsrvcache.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
@ -73,13 +75,14 @@
|
||||
void nfsrv_zapsock __P((struct nfssvc_sock *));
|
||||
|
||||
/* Global defs. */
|
||||
extern u_long nfs_prog, nfs_vers;
|
||||
extern int (*nfsrv_procs[NFS_NPROCS])();
|
||||
extern int (*nfsrv3_procs[NFS_NPROCS])();
|
||||
extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
|
||||
extern int nfs_numasync;
|
||||
extern time_t nqnfsstarttime;
|
||||
extern int nqsrv_writeslack;
|
||||
extern int nfsrtton;
|
||||
extern struct nfsstats nfsstats;
|
||||
extern int nfsrvw_procrastinate;
|
||||
struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock;
|
||||
int nuidhash_max = NFS_MAXUIDHASH;
|
||||
static int nfs_numnfsd = 0;
|
||||
@ -225,19 +228,25 @@ nfssvc(p, uap, retval)
|
||||
if (error)
|
||||
return (error);
|
||||
if ((uap->flag & NFSSVC_AUTHIN) && ((nfsd = nsd->nsd_nfsd)) &&
|
||||
(nfsd->nd_slp->ns_flag & SLP_VALID)) {
|
||||
slp = nfsd->nd_slp;
|
||||
(nfsd->nfsd_slp->ns_flag & SLP_VALID)) {
|
||||
slp = nfsd->nfsd_slp;
|
||||
|
||||
/*
|
||||
* First check to see if another nfsd has already
|
||||
* added this credential.
|
||||
*/
|
||||
for (nuidp = NUIDHASH(slp, nsd->nsd_uid)->lh_first;
|
||||
for (nuidp = NUIDHASH(slp,nsd->nsd_cr.cr_uid)->lh_first;
|
||||
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
|
||||
if (nuidp->nu_uid == nsd->nsd_uid)
|
||||
if (nuidp->nu_cr.cr_uid == nsd->nsd_cr.cr_uid &&
|
||||
(!nfsd->nfsd_nd->nd_nam2 ||
|
||||
netaddr_match(NU_NETFAM(nuidp),
|
||||
&nuidp->nu_haddr, nfsd->nfsd_nd->nd_nam2)))
|
||||
break;
|
||||
}
|
||||
if (!nuidp) {
|
||||
if (nuidp) {
|
||||
nfsrv_setcred(&nuidp->nu_cr,&nfsd->nfsd_nd->nd_cr);
|
||||
nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
|
||||
} else {
|
||||
/*
|
||||
* Nope, so we will.
|
||||
*/
|
||||
@ -257,22 +266,53 @@ nfssvc(p, uap, retval)
|
||||
LIST_REMOVE(nuidp, nu_hash);
|
||||
TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp,
|
||||
nu_lru);
|
||||
if (nuidp->nu_flag & NU_NAM)
|
||||
m_freem(nuidp->nu_nam);
|
||||
}
|
||||
nuidp->nu_flag = 0;
|
||||
nuidp->nu_cr = nsd->nsd_cr;
|
||||
if (nuidp->nu_cr.cr_ngroups > NGROUPS)
|
||||
nuidp->nu_cr.cr_ngroups = NGROUPS;
|
||||
nuidp->nu_cr.cr_ngroups = NGROUPS;
|
||||
nuidp->nu_cr.cr_ref = 1;
|
||||
nuidp->nu_uid = nsd->nsd_uid;
|
||||
nuidp->nu_timestamp = nsd->nsd_timestamp;
|
||||
nuidp->nu_expire = time.tv_sec + nsd->nsd_ttl;
|
||||
/*
|
||||
* and save the session key in nu_key.
|
||||
*/
|
||||
bcopy(nsd->nsd_key, nuidp->nu_key,
|
||||
sizeof (nsd->nsd_key));
|
||||
if (nfsd->nfsd_nd->nd_nam2) {
|
||||
struct sockaddr_in *saddr;
|
||||
|
||||
saddr = mtod(nfsd->nfsd_nd->nd_nam2,
|
||||
struct sockaddr_in *);
|
||||
switch (saddr->sin_family) {
|
||||
case AF_INET:
|
||||
nuidp->nu_flag |= NU_INETADDR;
|
||||
nuidp->nu_inetaddr =
|
||||
saddr->sin_addr.s_addr;
|
||||
break;
|
||||
case AF_ISO:
|
||||
default:
|
||||
nuidp->nu_flag |= NU_NAM;
|
||||
nuidp->nu_nam = m_copym(
|
||||
nfsd->nfsd_nd->nd_nam2, 0,
|
||||
M_COPYALL, M_WAIT);
|
||||
break;
|
||||
};
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&slp->ns_uidlruhead, nuidp,
|
||||
nu_lru);
|
||||
LIST_INSERT_HEAD(NUIDHASH(slp, nsd->nsd_uid),
|
||||
nuidp, nu_hash);
|
||||
|
||||
nfsrv_setcred(&nuidp->nu_cr,
|
||||
&nfsd->nfsd_nd->nd_cr);
|
||||
nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd))
|
||||
nfsd->nd_flag |= NFSD_AUTHFAIL;
|
||||
nfsd->nfsd_flag |= NFSD_AUTHFAIL;
|
||||
error = nfssvc_nfsd(nsd, uap->argp, p);
|
||||
}
|
||||
if (error == EINTR || error == ERESTART)
|
||||
@ -353,8 +393,6 @@ nfssvc_addsock(fp, mynam)
|
||||
slp = (struct nfssvc_sock *)
|
||||
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
|
||||
bzero((caddr_t)slp, sizeof (struct nfssvc_sock));
|
||||
slp->ns_uidhashtbl =
|
||||
hashinit(NUIDHASHSIZ, M_NFSSVC, &slp->ns_uidhash);
|
||||
TAILQ_INIT(&slp->ns_uidlruhead);
|
||||
TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain);
|
||||
}
|
||||
@ -381,44 +419,47 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
caddr_t argp;
|
||||
struct proc *p;
|
||||
{
|
||||
register struct mbuf *m, *nam2;
|
||||
register struct mbuf *m;
|
||||
register int siz;
|
||||
register struct nfssvc_sock *slp;
|
||||
register struct socket *so;
|
||||
register int *solockp;
|
||||
struct nfsd *nd = nsd->nsd_nfsd;
|
||||
struct mbuf *mreq, *nam;
|
||||
struct timeval starttime;
|
||||
struct nfsd *nfsd = nsd->nsd_nfsd;
|
||||
struct nfsrv_descript *nd = NULL;
|
||||
struct mbuf *mreq;
|
||||
struct nfsuid *uidp;
|
||||
int error = 0, cacherep, s;
|
||||
int sotype;
|
||||
int error = 0, cacherep, s, sotype, writes_todo;
|
||||
u_quad_t cur_usec;
|
||||
|
||||
#ifndef nolint
|
||||
cacherep = RC_DOIT;
|
||||
writes_todo = 0;
|
||||
#endif
|
||||
s = splnet();
|
||||
if (nd == (struct nfsd *)0) {
|
||||
nsd->nsd_nfsd = nd = (struct nfsd *)
|
||||
if (nfsd == (struct nfsd *)0) {
|
||||
nsd->nsd_nfsd = nfsd = (struct nfsd *)
|
||||
malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK);
|
||||
bzero((caddr_t)nd, sizeof (struct nfsd));
|
||||
nd->nd_procp = p;
|
||||
nd->nd_cr.cr_ref = 1;
|
||||
TAILQ_INSERT_TAIL(&nfsd_head, nd, nd_chain);
|
||||
nd->nd_nqlflag = NQL_NOVAL;
|
||||
bzero((caddr_t)nfsd, sizeof (struct nfsd));
|
||||
nfsd->nfsd_procp = p;
|
||||
TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain);
|
||||
nfs_numnfsd++;
|
||||
}
|
||||
/*
|
||||
* Loop getting rpc requests until SIGKILL.
|
||||
*/
|
||||
for (;;) {
|
||||
if ((nd->nd_flag & NFSD_REQINPROG) == 0) {
|
||||
while (nd->nd_slp == (struct nfssvc_sock *)0 &&
|
||||
if ((nfsd->nfsd_flag & NFSD_REQINPROG) == 0) {
|
||||
while (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
|
||||
(nfsd_head_flag & NFSD_CHECKSLP) == 0) {
|
||||
nd->nd_flag |= NFSD_WAITING;
|
||||
nfsd->nfsd_flag |= NFSD_WAITING;
|
||||
nfsd_waiting++;
|
||||
error = tsleep((caddr_t)nd, PSOCK | PCATCH, "nfsd", 0);
|
||||
error = tsleep((caddr_t)nfsd, PSOCK | PCATCH,
|
||||
"nfsd", 0);
|
||||
nfsd_waiting--;
|
||||
if (error)
|
||||
goto done;
|
||||
}
|
||||
if (nd->nd_slp == (struct nfssvc_sock *)0 &&
|
||||
if (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
|
||||
(nfsd_head_flag & NFSD_CHECKSLP) != 0) {
|
||||
for (slp = nfssvc_sockhead.tqh_first; slp != 0;
|
||||
slp = slp->ns_chain.tqe_next) {
|
||||
@ -426,14 +467,14 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
== (SLP_VALID | SLP_DOREC)) {
|
||||
slp->ns_flag &= ~SLP_DOREC;
|
||||
slp->ns_sref++;
|
||||
nd->nd_slp = slp;
|
||||
nfsd->nfsd_slp = slp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (slp == 0)
|
||||
nfsd_head_flag &= ~NFSD_CHECKSLP;
|
||||
}
|
||||
if ((slp = nd->nd_slp) == (struct nfssvc_sock *)0)
|
||||
if ((slp = nfsd->nfsd_slp) == (struct nfssvc_sock *)0)
|
||||
continue;
|
||||
if (slp->ns_flag & SLP_VALID) {
|
||||
if (slp->ns_flag & SLP_DISCONN)
|
||||
@ -446,86 +487,78 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
M_WAIT);
|
||||
nfs_sndunlock(&slp->ns_solock);
|
||||
}
|
||||
error = nfsrv_dorec(slp, nd);
|
||||
nd->nd_flag |= NFSD_REQINPROG;
|
||||
error = nfsrv_dorec(slp, nfsd, &nd);
|
||||
cur_usec = (u_quad_t)time.tv_sec * 1000000 +
|
||||
(u_quad_t)time.tv_usec;
|
||||
if (error && slp->ns_tq.lh_first &&
|
||||
slp->ns_tq.lh_first->nd_time <= cur_usec) {
|
||||
error = 0;
|
||||
cacherep = RC_DOIT;
|
||||
writes_todo = 1;
|
||||
} else
|
||||
writes_todo = 0;
|
||||
nfsd->nfsd_flag |= NFSD_REQINPROG;
|
||||
}
|
||||
} else {
|
||||
error = 0;
|
||||
slp = nd->nd_slp;
|
||||
slp = nfsd->nfsd_slp;
|
||||
}
|
||||
if (error || (slp->ns_flag & SLP_VALID) == 0) {
|
||||
nd->nd_slp = (struct nfssvc_sock *)0;
|
||||
nd->nd_flag &= ~NFSD_REQINPROG;
|
||||
if (nd) {
|
||||
free((caddr_t)nd, M_NFSRVDESC);
|
||||
nd = NULL;
|
||||
}
|
||||
nfsd->nfsd_slp = (struct nfssvc_sock *)0;
|
||||
nfsd->nfsd_flag &= ~NFSD_REQINPROG;
|
||||
nfsrv_slpderef(slp);
|
||||
continue;
|
||||
}
|
||||
splx(s);
|
||||
so = slp->ns_so;
|
||||
sotype = so->so_type;
|
||||
starttime = time;
|
||||
if (so->so_proto->pr_flags & PR_CONNREQUIRED)
|
||||
solockp = &slp->ns_solock;
|
||||
else
|
||||
solockp = (int *)0;
|
||||
/*
|
||||
* nam == nam2 for connectionless protocols such as UDP
|
||||
* nam2 == NULL for connection based protocols to disable
|
||||
* recent request caching.
|
||||
*/
|
||||
nam2 = nd->nd_nam;
|
||||
if (nam2) {
|
||||
nam = nam2;
|
||||
cacherep = RC_CHECKIT;
|
||||
} else {
|
||||
nam = slp->ns_nam;
|
||||
cacherep = RC_DOIT;
|
||||
}
|
||||
if (nd) {
|
||||
nd->nd_starttime = time;
|
||||
if (nd->nd_nam2)
|
||||
nd->nd_nam = nd->nd_nam2;
|
||||
else
|
||||
nd->nd_nam = slp->ns_nam;
|
||||
|
||||
/*
|
||||
* Check to see if authorization is needed.
|
||||
*/
|
||||
if (nd->nd_flag & NFSD_NEEDAUTH) {
|
||||
static int logauth = 0;
|
||||
/*
|
||||
* Check to see if authorization is needed.
|
||||
*/
|
||||
if (nfsd->nfsd_flag & NFSD_NEEDAUTH) {
|
||||
nfsd->nfsd_flag &= ~NFSD_NEEDAUTH;
|
||||
nsd->nsd_haddr = mtod(nd->nd_nam,
|
||||
struct sockaddr_in *)->sin_addr.s_addr;
|
||||
nsd->nsd_authlen = nfsd->nfsd_authlen;
|
||||
nsd->nsd_verflen = nfsd->nfsd_verflen;
|
||||
if (!copyout(nfsd->nfsd_authstr,nsd->nsd_authstr,
|
||||
nfsd->nfsd_authlen) &&
|
||||
!copyout(nfsd->nfsd_verfstr, nsd->nsd_verfstr,
|
||||
nfsd->nfsd_verflen) &&
|
||||
!copyout((caddr_t)nsd, argp, sizeof (*nsd)))
|
||||
return (ENEEDAUTH);
|
||||
cacherep = RC_DROPIT;
|
||||
} else
|
||||
cacherep = nfsrv_getcache(nd, slp, &mreq);
|
||||
|
||||
nd->nd_flag &= ~NFSD_NEEDAUTH;
|
||||
/*
|
||||
* Check for a mapping already installed.
|
||||
*/
|
||||
for (uidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
|
||||
uidp != 0; uidp = uidp->nu_hash.le_next) {
|
||||
if (uidp->nu_uid == nd->nd_cr.cr_uid)
|
||||
break;
|
||||
}
|
||||
if (!uidp) {
|
||||
nsd->nsd_uid = nd->nd_cr.cr_uid;
|
||||
if (nam2 && logauth++ == 0)
|
||||
log(LOG_WARNING, "Kerberized NFS using UDP\n");
|
||||
nsd->nsd_haddr =
|
||||
mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
|
||||
nsd->nsd_authlen = nd->nd_authlen;
|
||||
if (copyout(nd->nd_authstr, nsd->nsd_authstr,
|
||||
nd->nd_authlen) == 0 &&
|
||||
copyout((caddr_t)nsd, argp, sizeof (*nsd)) == 0)
|
||||
return (ENEEDAUTH);
|
||||
cacherep = RC_DROPIT;
|
||||
}
|
||||
}
|
||||
if (cacherep == RC_CHECKIT)
|
||||
cacherep = nfsrv_getcache(nam2, nd, &mreq);
|
||||
|
||||
/*
|
||||
* Check for just starting up for NQNFS and send
|
||||
* fake "try again later" replies to the NQNFS clients.
|
||||
*/
|
||||
if (notstarted && nqnfsstarttime <= time.tv_sec) {
|
||||
/*
|
||||
* Check for just starting up for NQNFS and send
|
||||
* fake "try again later" replies to the NQNFS clients.
|
||||
*/
|
||||
if (notstarted && nqnfsstarttime <= time.tv_sec) {
|
||||
if (modify_flag) {
|
||||
nqnfsstarttime = time.tv_sec + nqsrv_writeslack;
|
||||
modify_flag = 0;
|
||||
} else
|
||||
notstarted = 0;
|
||||
}
|
||||
if (notstarted) {
|
||||
if (nd->nd_nqlflag == NQL_NOVAL)
|
||||
}
|
||||
if (notstarted) {
|
||||
if ((nd->nd_flag & ND_NQNFS) == 0)
|
||||
cacherep = RC_DROPIT;
|
||||
else if (nd->nd_procnum != NFSPROC_WRITE) {
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
@ -533,36 +566,42 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
cacherep = RC_DOIT;
|
||||
} else
|
||||
modify_flag = 1;
|
||||
} else if (nd->nd_flag & NFSD_AUTHFAIL) {
|
||||
nd->nd_flag &= ~NFSD_AUTHFAIL;
|
||||
} else if (nfsd->nfsd_flag & NFSD_AUTHFAIL) {
|
||||
nfsd->nfsd_flag &= ~NFSD_AUTHFAIL;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
nd->nd_repstat = NQNFS_AUTHERR;
|
||||
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
|
||||
cacherep = RC_DOIT;
|
||||
}
|
||||
}
|
||||
|
||||
switch (cacherep) {
|
||||
case RC_DOIT:
|
||||
error = (*(nfsrv_procs[nd->nd_procnum]))(nd,
|
||||
nd->nd_mrep, nd->nd_md, nd->nd_dpos, &nd->nd_cr,
|
||||
nam, &mreq);
|
||||
if (nd->nd_cr.cr_ref != 1) {
|
||||
printf("nfssvc cref=%d\n", nd->nd_cr.cr_ref);
|
||||
panic("nfssvc cref");
|
||||
}
|
||||
/*
|
||||
* Loop to get all the write rpc relies that have been
|
||||
* gathered together.
|
||||
*/
|
||||
do {
|
||||
switch (cacherep) {
|
||||
case RC_DOIT:
|
||||
if (writes_todo || (nd->nd_procnum == NFSPROC_WRITE &&
|
||||
nfsrvw_procrastinate > 0 && !notstarted))
|
||||
error = nfsrv_writegather(&nd, slp,
|
||||
nfsd->nfsd_procp, &mreq);
|
||||
else
|
||||
error = (*(nfsrv3_procs[nd->nd_procnum]))(nd,
|
||||
slp, nfsd->nfsd_procp, &mreq);
|
||||
if (mreq == NULL)
|
||||
break;
|
||||
if (error) {
|
||||
if (nd->nd_procnum != NQNFSPROC_VACATED)
|
||||
nfsstats.srv_errs++;
|
||||
if (nam2) {
|
||||
nfsrv_updatecache(nam2, nd, FALSE, mreq);
|
||||
m_freem(nam2);
|
||||
}
|
||||
nfsrv_updatecache(nd, FALSE, mreq);
|
||||
if (nd->nd_nam2)
|
||||
m_freem(nd->nd_nam2);
|
||||
break;
|
||||
}
|
||||
nfsstats.srvrpccnt[nd->nd_procnum]++;
|
||||
if (nam2)
|
||||
nfsrv_updatecache(nam2, nd, TRUE, mreq);
|
||||
nfsrv_updatecache(nd, TRUE, mreq);
|
||||
nd->nd_mrep = (struct mbuf *)0;
|
||||
case RC_REPLY:
|
||||
case RC_REPLY:
|
||||
m = mreq;
|
||||
siz = 0;
|
||||
while (m) {
|
||||
@ -587,15 +626,15 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
if (solockp)
|
||||
(void) nfs_sndlock(solockp, (struct nfsreq *)0);
|
||||
if (slp->ns_flag & SLP_VALID)
|
||||
error = nfs_send(so, nam2, m, (struct nfsreq *)0);
|
||||
error = nfs_send(so, nd->nd_nam2, m, NULL);
|
||||
else {
|
||||
error = EPIPE;
|
||||
m_freem(m);
|
||||
}
|
||||
if (nfsrtton)
|
||||
nfsd_rt(&starttime, sotype, nd, nam, cacherep);
|
||||
if (nam2)
|
||||
MFREE(nam2, m);
|
||||
nfsd_rt(sotype, nd, cacherep);
|
||||
if (nd->nd_nam2)
|
||||
MFREE(nd->nd_nam2, m);
|
||||
if (nd->nd_mrep)
|
||||
m_freem(nd->nd_mrep);
|
||||
if (error == EPIPE)
|
||||
@ -603,29 +642,50 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
if (solockp)
|
||||
nfs_sndunlock(solockp);
|
||||
if (error == EINTR || error == ERESTART) {
|
||||
free((caddr_t)nd, M_NFSRVDESC);
|
||||
nfsrv_slpderef(slp);
|
||||
s = splnet();
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case RC_DROPIT:
|
||||
case RC_DROPIT:
|
||||
if (nfsrtton)
|
||||
nfsd_rt(&starttime, sotype, nd, nam, cacherep);
|
||||
nfsd_rt(sotype, nd, cacherep);
|
||||
m_freem(nd->nd_mrep);
|
||||
m_freem(nam2);
|
||||
m_freem(nd->nd_nam2);
|
||||
break;
|
||||
};
|
||||
};
|
||||
if (nd) {
|
||||
FREE((caddr_t)nd, M_NFSRVDESC);
|
||||
nd = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if there are outstanding writes that
|
||||
* need to be serviced.
|
||||
*/
|
||||
cur_usec = (u_quad_t)time.tv_sec * 1000000 +
|
||||
(u_quad_t)time.tv_usec;
|
||||
s = splsoftclock();
|
||||
if (slp->ns_tq.lh_first &&
|
||||
slp->ns_tq.lh_first->nd_time <= cur_usec) {
|
||||
cacherep = RC_DOIT;
|
||||
writes_todo = 1;
|
||||
} else
|
||||
writes_todo = 0;
|
||||
splx(s);
|
||||
} while (writes_todo);
|
||||
s = splnet();
|
||||
if (nfsrv_dorec(slp, nd)) {
|
||||
nd->nd_flag &= ~NFSD_REQINPROG;
|
||||
nd->nd_slp = (struct nfssvc_sock *)0;
|
||||
if (nfsrv_dorec(slp, nfsd, &nd)) {
|
||||
nfsd->nfsd_flag &= ~NFSD_REQINPROG;
|
||||
nfsd->nfsd_slp = NULL;
|
||||
nfsrv_slpderef(slp);
|
||||
}
|
||||
}
|
||||
done:
|
||||
TAILQ_REMOVE(&nfsd_head, nd, nd_chain);
|
||||
TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain);
|
||||
splx(s);
|
||||
free((caddr_t)nd, M_NFSD);
|
||||
free((caddr_t)nfsd, M_NFSD);
|
||||
nsd->nsd_nfsd = (struct nfsd *)0;
|
||||
if (--nfs_numnfsd == 0)
|
||||
nfsrv_init(TRUE); /* Reinitialize everything */
|
||||
@ -641,9 +701,10 @@ int
|
||||
nfssvc_iod(p)
|
||||
struct proc *p;
|
||||
{
|
||||
register struct buf *bp;
|
||||
register struct buf *bp, *nbp;
|
||||
register int i, myiod;
|
||||
int error = 0;
|
||||
struct vnode *vp;
|
||||
int error = 0, s;
|
||||
|
||||
/*
|
||||
* Assign my position or return error if too many already running
|
||||
@ -662,24 +723,53 @@ nfssvc_iod(p)
|
||||
* Just loop around doin our stuff until SIGKILL
|
||||
*/
|
||||
for (;;) {
|
||||
while (nfs_bufq.tqh_first == NULL && error == 0) {
|
||||
nfs_iodwant[myiod] = p;
|
||||
error = tsleep((caddr_t)&nfs_iodwant[myiod],
|
||||
PWAIT | PCATCH, "nfsidl", 0);
|
||||
}
|
||||
while ((bp = nfs_bufq.tqh_first) != NULL) {
|
||||
/* Take one off the front of the list */
|
||||
TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);
|
||||
if (bp->b_flags & B_READ)
|
||||
(void) nfs_doio(bp, bp->b_rcred, (struct proc *)0);
|
||||
else
|
||||
(void) nfs_doio(bp, bp->b_wcred, (struct proc *)0);
|
||||
}
|
||||
if (error) {
|
||||
nfs_asyncdaemon[myiod] = 0;
|
||||
nfs_numasync--;
|
||||
return (error);
|
||||
}
|
||||
while (nfs_bufq.tqh_first == NULL && error == 0) {
|
||||
nfs_iodwant[myiod] = p;
|
||||
error = tsleep((caddr_t)&nfs_iodwant[myiod],
|
||||
PWAIT | PCATCH, "nfsidl", 0);
|
||||
}
|
||||
while ((bp = nfs_bufq.tqh_first) != NULL) {
|
||||
/* Take one off the front of the list */
|
||||
TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);
|
||||
if (bp->b_flags & B_READ)
|
||||
(void) nfs_doio(bp, bp->b_rcred, (struct proc *)0);
|
||||
else do {
|
||||
/*
|
||||
* Look for a delayed write for the same vnode, so I can do
|
||||
* it now. We must grab it before calling nfs_doio() to
|
||||
* avoid any risk of the vnode getting vclean()'d while
|
||||
* we are doing the write rpc.
|
||||
*/
|
||||
vp = bp->b_vp;
|
||||
s = splbio();
|
||||
for (nbp = vp->v_dirtyblkhd.lh_first; nbp;
|
||||
nbp = nbp->b_vnbufs.le_next) {
|
||||
if ((nbp->b_flags &
|
||||
(B_BUSY|B_DELWRI|B_NEEDCOMMIT|B_NOCACHE))!=B_DELWRI)
|
||||
continue;
|
||||
bremfree(nbp);
|
||||
vfs_busy_pages(nbp, 1);
|
||||
nbp->b_flags |= (B_BUSY|B_ASYNC);
|
||||
break;
|
||||
}
|
||||
splx(s);
|
||||
/*
|
||||
* For the delayed write, do the first part of nfs_bwrite()
|
||||
* up to, but not including nfs_strategy().
|
||||
*/
|
||||
if (nbp) {
|
||||
nbp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
|
||||
reassignbuf(nbp, nbp->b_vp);
|
||||
nbp->b_vp->v_numoutput++;
|
||||
}
|
||||
(void) nfs_doio(bp, bp->b_wcred, (struct proc *)0);
|
||||
} while (bp = nbp);
|
||||
}
|
||||
if (error) {
|
||||
nfs_asyncdaemon[myiod] = 0;
|
||||
nfs_numasync--;
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -695,9 +785,11 @@ nfsrv_zapsock(slp)
|
||||
register struct nfssvc_sock *slp;
|
||||
{
|
||||
register struct nfsuid *nuidp, *nnuidp;
|
||||
register struct nfsrv_descript *nwp, *nnwp;
|
||||
struct socket *so;
|
||||
struct file *fp;
|
||||
struct mbuf *m;
|
||||
int s;
|
||||
|
||||
slp->ns_flag &= ~SLP_ALLFLAGS;
|
||||
fp = slp->ns_fp;
|
||||
@ -716,8 +808,18 @@ nfsrv_zapsock(slp)
|
||||
nnuidp = nuidp->nu_lru.tqe_next;
|
||||
LIST_REMOVE(nuidp, nu_hash);
|
||||
TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, nu_lru);
|
||||
if (nuidp->nu_flag & NU_NAM)
|
||||
m_freem(nuidp->nu_nam);
|
||||
free((caddr_t)nuidp, M_NFSUID);
|
||||
}
|
||||
s = splsoftclock();
|
||||
for (nwp = slp->ns_tq.lh_first; nwp; nwp = nnwp) {
|
||||
nnwp = nwp->nd_tq.le_next;
|
||||
LIST_REMOVE(nwp, nd_tq);
|
||||
free((caddr_t)nwp, M_NFSRVDESC);
|
||||
}
|
||||
LIST_INIT(&slp->ns_tq);
|
||||
splx(s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -726,13 +828,15 @@ nfsrv_zapsock(slp)
|
||||
* on this mount point porpous out of the kernel and do it.
|
||||
*/
|
||||
int
|
||||
nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
|
||||
nfs_getauth(nmp, rep, cred, auth_str, auth_len, verf_str, verf_len, key)
|
||||
register struct nfsmount *nmp;
|
||||
struct nfsreq *rep;
|
||||
struct ucred *cred;
|
||||
int *auth_type;
|
||||
char **auth_str;
|
||||
int *auth_len;
|
||||
char *verf_str;
|
||||
int *verf_len;
|
||||
NFSKERBKEY_T key; /* return session key */
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
@ -748,6 +852,9 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
|
||||
}
|
||||
nmp->nm_flag &= ~(NFSMNT_WAITAUTH | NFSMNT_WANTAUTH);
|
||||
nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK);
|
||||
nmp->nm_authlen = RPCAUTH_MAXSIZ;
|
||||
nmp->nm_verfstr = verf_str;
|
||||
nmp->nm_verflen = *verf_len;
|
||||
nmp->nm_authuid = cred->cr_uid;
|
||||
wakeup((caddr_t)&nmp->nm_authstr);
|
||||
|
||||
@ -766,8 +873,9 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
|
||||
if (error)
|
||||
free((caddr_t)*auth_str, M_TEMP);
|
||||
else {
|
||||
*auth_type = nmp->nm_authtype;
|
||||
*auth_len = nmp->nm_authlen;
|
||||
*verf_len = nmp->nm_verflen;
|
||||
bcopy((caddr_t)nmp->nm_key, (caddr_t)key, sizeof (key));
|
||||
}
|
||||
nmp->nm_flag &= ~NFSMNT_HASAUTH;
|
||||
nmp->nm_flag |= NFSMNT_WAITAUTH;
|
||||
@ -778,6 +886,149 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a nickname authenticator and verifier.
|
||||
*/
|
||||
int
|
||||
nfs_getnickauth(nmp, cred, auth_str, auth_len, verf_str, verf_len)
|
||||
struct nfsmount *nmp;
|
||||
struct ucred *cred;
|
||||
char **auth_str;
|
||||
int *auth_len;
|
||||
char *verf_str;
|
||||
int verf_len;
|
||||
{
|
||||
register struct nfsuid *nuidp;
|
||||
register u_long *nickp, *verfp;
|
||||
struct timeval ktvin, ktvout;
|
||||
NFSKERBKEYSCHED_T keys; /* stores key schedule */
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (verf_len < (4 * NFSX_UNSIGNED))
|
||||
panic("nfs_getnickauth verf too small");
|
||||
#endif
|
||||
for (nuidp = NMUIDHASH(nmp, cred->cr_uid)->lh_first;
|
||||
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
|
||||
if (nuidp->nu_cr.cr_uid == cred->cr_uid)
|
||||
break;
|
||||
}
|
||||
if (!nuidp || nuidp->nu_expire < time.tv_sec)
|
||||
return (EACCES);
|
||||
|
||||
/*
|
||||
* Move to the end of the lru list (end of lru == most recently used).
|
||||
*/
|
||||
TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru);
|
||||
TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp, nu_lru);
|
||||
|
||||
nickp = (u_long *)malloc(2 * NFSX_UNSIGNED, M_TEMP, M_WAITOK);
|
||||
*nickp++ = txdr_unsigned(RPCAKN_NICKNAME);
|
||||
*nickp = txdr_unsigned(nuidp->nu_nickname);
|
||||
*auth_str = (char *)nickp;
|
||||
*auth_len = 2 * NFSX_UNSIGNED;
|
||||
|
||||
/*
|
||||
* Now we must encrypt the verifier and package it up.
|
||||
*/
|
||||
verfp = (u_long *)verf_str;
|
||||
*verfp++ = txdr_unsigned(RPCAKN_NICKNAME);
|
||||
if (time.tv_sec > nuidp->nu_timestamp.tv_sec ||
|
||||
(time.tv_sec == nuidp->nu_timestamp.tv_sec &&
|
||||
time.tv_usec > nuidp->nu_timestamp.tv_usec))
|
||||
nuidp->nu_timestamp = time;
|
||||
else
|
||||
nuidp->nu_timestamp.tv_usec++;
|
||||
ktvin.tv_sec = txdr_unsigned(nuidp->nu_timestamp.tv_sec);
|
||||
ktvin.tv_usec = txdr_unsigned(nuidp->nu_timestamp.tv_usec);
|
||||
|
||||
/*
|
||||
* Now encrypt the timestamp verifier in ecb mode using the session
|
||||
* key.
|
||||
*/
|
||||
#ifdef NFSKERB
|
||||
XXX
|
||||
#endif
|
||||
|
||||
*verfp++ = ktvout.tv_sec;
|
||||
*verfp++ = ktvout.tv_usec;
|
||||
*verfp = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the current nickname in a hash list entry on the mount point.
|
||||
*/
|
||||
int
|
||||
nfs_savenickauth(nmp, cred, len, key, mdp, dposp, mrep)
|
||||
register struct nfsmount *nmp;
|
||||
struct ucred *cred;
|
||||
int len;
|
||||
NFSKERBKEY_T key;
|
||||
struct mbuf **mdp;
|
||||
char **dposp;
|
||||
struct mbuf *mrep;
|
||||
{
|
||||
register struct nfsuid *nuidp;
|
||||
register u_long *tl;
|
||||
register long t1;
|
||||
struct mbuf *md = *mdp;
|
||||
struct timeval ktvin, ktvout;
|
||||
u_long nick;
|
||||
NFSKERBKEYSCHED_T keys;
|
||||
char *dpos = *dposp, *cp2;
|
||||
int deltasec, error = 0;
|
||||
|
||||
if (len == (3 * NFSX_UNSIGNED)) {
|
||||
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
ktvin.tv_sec = *tl++;
|
||||
ktvin.tv_usec = *tl++;
|
||||
nick = fxdr_unsigned(u_long, *tl);
|
||||
|
||||
/*
|
||||
* Decrypt the timestamp in ecb mode.
|
||||
*/
|
||||
#ifdef NFSKERB
|
||||
XXX
|
||||
#endif
|
||||
ktvout.tv_sec = fxdr_unsigned(long, ktvout.tv_sec);
|
||||
ktvout.tv_usec = fxdr_unsigned(long, ktvout.tv_usec);
|
||||
deltasec = time.tv_sec - ktvout.tv_sec;
|
||||
if (deltasec < 0)
|
||||
deltasec = -deltasec;
|
||||
/*
|
||||
* If ok, add it to the hash list for the mount point.
|
||||
*/
|
||||
if (deltasec <= NFS_KERBCLOCKSKEW) {
|
||||
if (nmp->nm_numuids < nuidhash_max) {
|
||||
nmp->nm_numuids++;
|
||||
nuidp = (struct nfsuid *)
|
||||
malloc(sizeof (struct nfsuid), M_NFSUID,
|
||||
M_WAITOK);
|
||||
} else {
|
||||
nuidp = nmp->nm_uidlruhead.tqh_first;
|
||||
LIST_REMOVE(nuidp, nu_hash);
|
||||
TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp,
|
||||
nu_lru);
|
||||
}
|
||||
nuidp->nu_flag = 0;
|
||||
nuidp->nu_cr.cr_uid = cred->cr_uid;
|
||||
nuidp->nu_expire = time.tv_sec + NFS_KERBTTL;
|
||||
nuidp->nu_timestamp = ktvout;
|
||||
nuidp->nu_nickname = nick;
|
||||
bcopy(key, nuidp->nu_key, sizeof (key));
|
||||
TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp,
|
||||
nu_lru);
|
||||
LIST_INSERT_HEAD(NMUIDHASH(nmp, cred->cr_uid),
|
||||
nuidp, nu_hash);
|
||||
}
|
||||
} else
|
||||
nfsm_adv(nfsm_rndup(len));
|
||||
nfsmout:
|
||||
*mdp = md;
|
||||
*dposp = dpos;
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Derefence a server socket structure. If it has no more references and
|
||||
* is no longer valid, you can throw it away.
|
||||
@ -830,16 +1081,12 @@ nfsrv_init(terminating)
|
||||
nfs_udpsock = (struct nfssvc_sock *)
|
||||
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
|
||||
bzero((caddr_t)nfs_udpsock, sizeof (struct nfssvc_sock));
|
||||
nfs_udpsock->ns_uidhashtbl =
|
||||
hashinit(NUIDHASHSIZ, M_NFSSVC, &nfs_udpsock->ns_uidhash);
|
||||
TAILQ_INIT(&nfs_udpsock->ns_uidlruhead);
|
||||
TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain);
|
||||
|
||||
nfs_cltpsock = (struct nfssvc_sock *)
|
||||
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
|
||||
bzero((caddr_t)nfs_cltpsock, sizeof (struct nfssvc_sock));
|
||||
nfs_cltpsock->ns_uidhashtbl =
|
||||
hashinit(NUIDHASHSIZ, M_NFSSVC, &nfs_cltpsock->ns_uidhash);
|
||||
TAILQ_INIT(&nfs_cltpsock->ns_uidlruhead);
|
||||
TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain);
|
||||
}
|
||||
@ -848,11 +1095,9 @@ nfsrv_init(terminating)
|
||||
* Add entries to the server monitor log.
|
||||
*/
|
||||
static void
|
||||
nfsd_rt(startp, sotype, nd, nam, cacherep)
|
||||
struct timeval *startp;
|
||||
nfsd_rt(sotype, nd, cacherep)
|
||||
int sotype;
|
||||
register struct nfsd *nd;
|
||||
struct mbuf *nam;
|
||||
register struct nfsrv_descript *nd;
|
||||
int cacherep;
|
||||
{
|
||||
register struct drt *rt;
|
||||
@ -866,15 +1111,17 @@ nfsd_rt(startp, sotype, nd, nam, cacherep)
|
||||
rt->flag = DRT_CACHEDROP;
|
||||
if (sotype == SOCK_STREAM)
|
||||
rt->flag |= DRT_TCP;
|
||||
if (nd->nd_nqlflag != NQL_NOVAL)
|
||||
if (nd->nd_flag & ND_NQNFS)
|
||||
rt->flag |= DRT_NQNFS;
|
||||
else if (nd->nd_flag & ND_NFSV3)
|
||||
rt->flag |= DRT_NFSV3;
|
||||
rt->proc = nd->nd_procnum;
|
||||
if (mtod(nam, struct sockaddr *)->sa_family == AF_INET)
|
||||
rt->ipadr = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
|
||||
if (mtod(nd->nd_nam, struct sockaddr *)->sa_family == AF_INET)
|
||||
rt->ipadr = mtod(nd->nd_nam, struct sockaddr_in *)->sin_addr.s_addr;
|
||||
else
|
||||
rt->ipadr = INADDR_ANY;
|
||||
rt->resptime = ((time.tv_sec - startp->tv_sec) * 1000000) +
|
||||
(time.tv_usec - startp->tv_usec);
|
||||
rt->ipadr = INADDR_ANY;
|
||||
rt->resptime = ((time.tv_sec - nd->nd_starttime.tv_sec) * 1000000) +
|
||||
(time.tv_usec - nd->nd_starttime.tv_usec);
|
||||
rt->tstamp = time;
|
||||
nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_node.c 8.2 (Berkeley) 12/30/93
|
||||
* $Id: nfs_node.c,v 1.7 1994/10/17 17:47:33 phk Exp $
|
||||
* $Id: nfs_node.c,v 1.8 1995/03/16 18:15:36 bde Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -47,14 +47,12 @@
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/nqnfs.h>
|
||||
|
||||
#define NFSNOHASH(fhsum) \
|
||||
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
|
||||
LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl;
|
||||
u_long nfsnodehash;
|
||||
|
||||
@ -79,19 +77,20 @@ nfs_nhinit()
|
||||
/*
|
||||
* Compute an entry in the NFS hash table structure
|
||||
*/
|
||||
struct nfsnodehashhead *
|
||||
nfs_hash(fhp)
|
||||
register nfsv2fh_t *fhp;
|
||||
u_long
|
||||
nfs_hash(fhp, fhsize)
|
||||
register nfsfh_t *fhp;
|
||||
int fhsize;
|
||||
{
|
||||
register u_char *fhpp;
|
||||
register u_long fhsum;
|
||||
int i;
|
||||
register int i;
|
||||
|
||||
fhpp = &fhp->fh_bytes[0];
|
||||
fhsum = 0;
|
||||
for (i = 0; i < NFSX_FH; i++)
|
||||
for (i = 0; i < fhsize; i++)
|
||||
fhsum += *fhpp++;
|
||||
return (NFSNOHASH(fhsum));
|
||||
return (fhsum);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -101,9 +100,10 @@ nfs_hash(fhp)
|
||||
* nfsnode structure is returned.
|
||||
*/
|
||||
int
|
||||
nfs_nget(mntp, fhp, npp)
|
||||
nfs_nget(mntp, fhp, fhsize, npp)
|
||||
struct mount *mntp;
|
||||
register nfsv2fh_t *fhp;
|
||||
register nfsfh_t *fhp;
|
||||
int fhsize;
|
||||
struct nfsnode **npp;
|
||||
{
|
||||
register struct nfsnode *np;
|
||||
@ -112,11 +112,11 @@ nfs_nget(mntp, fhp, npp)
|
||||
struct vnode *nvp;
|
||||
int error;
|
||||
|
||||
nhpp = nfs_hash(fhp);
|
||||
nhpp = NFSNOHASH(nfs_hash(fhp, fhsize));
|
||||
loop:
|
||||
for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) {
|
||||
if (mntp != NFSTOV(np)->v_mount ||
|
||||
bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH))
|
||||
if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
|
||||
bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize))
|
||||
continue;
|
||||
vp = NFSTOV(np);
|
||||
if (vget(vp, 1))
|
||||
@ -131,27 +131,26 @@ nfs_nget(mntp, fhp, npp)
|
||||
}
|
||||
vp = nvp;
|
||||
MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK);
|
||||
bzero((caddr_t)np, sizeof *np);
|
||||
vp->v_data = np;
|
||||
np->n_vnode = vp;
|
||||
/*
|
||||
* Insert the nfsnode in the hash queue for its new file handle
|
||||
*/
|
||||
np->n_flag = 0;
|
||||
LIST_INSERT_HEAD(nhpp, np, n_hash);
|
||||
bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH);
|
||||
np->n_attrstamp = 0;
|
||||
np->n_direofoffset = 0;
|
||||
np->n_sillyrename = (struct sillyrename *)0;
|
||||
np->n_size = 0;
|
||||
np->n_mtime = 0;
|
||||
np->n_lockf = 0;
|
||||
if (VFSTONFS(mntp)->nm_flag & NFSMNT_NQNFS) {
|
||||
np->n_brev = 0;
|
||||
np->n_lrev = 0;
|
||||
np->n_expiry = (time_t)0;
|
||||
np->n_timer.cqe_next = (struct nfsnode *)0;
|
||||
}
|
||||
if (fhsize > NFS_SMALLFH) {
|
||||
MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK);
|
||||
} else
|
||||
np->n_fhp = &np->n_fh;
|
||||
bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize);
|
||||
np->n_fhsize = fhsize;
|
||||
*npp = np;
|
||||
|
||||
/*
|
||||
* Lock the new nfsnode.
|
||||
*/
|
||||
VOP_LOCK(vp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -168,7 +167,10 @@ nfs_inactive(ap)
|
||||
np = VTONFS(ap->a_vp);
|
||||
if (prtactive && ap->a_vp->v_usecount != 0)
|
||||
vprint("nfs_inactive: pushing active", ap->a_vp);
|
||||
sp = np->n_sillyrename;
|
||||
if (ap->a_vp->v_type != VDIR)
|
||||
sp = np->n_sillyrename;
|
||||
else
|
||||
sp = (struct sillyrename *)0;
|
||||
np->n_sillyrename = (struct sillyrename *)0;
|
||||
if (sp) {
|
||||
/*
|
||||
@ -178,9 +180,7 @@ nfs_inactive(ap)
|
||||
nfs_removeit(sp);
|
||||
crfree(sp->s_cred);
|
||||
vrele(sp->s_dvp);
|
||||
#ifdef SILLYSEPARATE
|
||||
free((caddr_t)sp, M_NFSREQ);
|
||||
#endif
|
||||
FREE((caddr_t)sp, M_NFSREQ);
|
||||
}
|
||||
np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
|
||||
NQNFSNONCACHE | NQNFSWRITE);
|
||||
@ -199,6 +199,7 @@ nfs_reclaim(ap)
|
||||
register struct vnode *vp = ap->a_vp;
|
||||
register struct nfsnode *np = VTONFS(vp);
|
||||
register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||
register struct nfsdmap *dp, *dp2;
|
||||
|
||||
if (prtactive && vp->v_usecount != 0)
|
||||
vprint("nfs_reclaim: pushing active", vp);
|
||||
@ -211,6 +212,24 @@ nfs_reclaim(ap)
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) {
|
||||
CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free up any directory cookie structures and
|
||||
* large file handle structures that might be associated with
|
||||
* this nfs node.
|
||||
*/
|
||||
if (vp->v_type == VDIR) {
|
||||
dp = np->n_cookies.lh_first;
|
||||
while (dp) {
|
||||
dp2 = dp;
|
||||
dp = dp->ndm_list.le_next;
|
||||
FREE((caddr_t)dp2, M_NFSDIROFF);
|
||||
}
|
||||
}
|
||||
if (np->n_fhsize > NFS_SMALLFH) {
|
||||
FREE((caddr_t)np->n_fhp, M_NFSBIGFH);
|
||||
}
|
||||
|
||||
cache_purge(vp);
|
||||
FREE(vp->v_data, M_NFSNODE);
|
||||
vp->v_data = (void *)0;
|
||||
@ -227,6 +246,7 @@ nfs_lock(ap)
|
||||
} */ *ap;
|
||||
{
|
||||
register struct vnode *vp = ap->a_vp;
|
||||
struct nfsnode *np = VTONFS(vp);
|
||||
|
||||
/*
|
||||
* Ugh, another place where interruptible mounts will get hung.
|
||||
@ -239,6 +259,33 @@ nfs_lock(ap)
|
||||
}
|
||||
if (vp->v_tag == VT_NON)
|
||||
return (ENOENT);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Only lock regular files. If a server crashed while we were
|
||||
* holding a directory lock, we could easily end up sleeping
|
||||
* until the server rebooted while holding a lock on the root.
|
||||
* Locks are only needed for protecting critical sections in
|
||||
* VMIO at the moment.
|
||||
* New vnodes will have type VNON but they should be locked
|
||||
* since they may become VREG. This is checked in loadattrcache
|
||||
* and unwanted locks are released there.
|
||||
*/
|
||||
if (vp->v_type == VREG || vp->v_type == VNON) {
|
||||
while (np->n_flag & NLOCKED) {
|
||||
np->n_flag |= NWANTED;
|
||||
(void) tsleep((caddr_t) np, PINOD, "nfslck2", 0);
|
||||
/*
|
||||
* If the vnode has transmuted into a VDIR while we
|
||||
* were asleep, then skip the lock.
|
||||
*/
|
||||
if (vp->v_type != VREG && vp->v_type != VNON)
|
||||
return (0);
|
||||
}
|
||||
np->n_flag |= NLOCKED;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -251,6 +298,20 @@ nfs_unlock(ap)
|
||||
struct vnode *a_vp;
|
||||
} */ *ap;
|
||||
{
|
||||
#if 0
|
||||
struct vnode* vp = ap->a_vp;
|
||||
struct nfsnode* np = VTONFS(vp);
|
||||
|
||||
if (vp->v_type == VREG || vp->v_type == VNON) {
|
||||
if (!(np->n_flag & NLOCKED))
|
||||
panic("nfs_unlock: nfsnode not locked");
|
||||
np->n_flag &= ~NLOCKED;
|
||||
if (np->n_flag & NWANTED) {
|
||||
np->n_flag &= ~NWANTED;
|
||||
wakeup((caddr_t) np);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -264,8 +325,7 @@ nfs_islocked(ap)
|
||||
struct vnode *a_vp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
return (0);
|
||||
return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_socket.c 8.3 (Berkeley) 1/12/94
|
||||
* $Id: nfs_socket.c,v 1.6 1995/03/16 18:15:37 bde Exp $
|
||||
* $Id: nfs_socket.c,v 1.7 1995/05/30 08:12:40 rgrimes Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -59,7 +59,7 @@
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/xdr_subs.h>
|
||||
#include <nfs/nfsm_subs.h>
|
||||
@ -94,36 +94,13 @@
|
||||
* External data, mostly RPC constants in XDR form
|
||||
*/
|
||||
extern u_long rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers, rpc_auth_unix,
|
||||
rpc_msgaccepted, rpc_call, rpc_autherr, rpc_rejectedcred,
|
||||
rpc_msgaccepted, rpc_call, rpc_autherr,
|
||||
rpc_auth_kerb;
|
||||
extern u_long nfs_prog, nfs_vers, nqnfs_prog, nqnfs_vers;
|
||||
extern u_long nfs_prog, nqnfs_prog;
|
||||
extern time_t nqnfsstarttime;
|
||||
extern int nonidempotent[NFS_NPROCS];
|
||||
|
||||
/*
|
||||
* Maps errno values to nfs error numbers.
|
||||
* Use NFSERR_IO as the catch all for ones not specifically defined in
|
||||
* RFC 1094.
|
||||
*/
|
||||
static int nfsrv_errmap[ELAST] = {
|
||||
NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR,
|
||||
NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO,
|
||||
};
|
||||
extern struct nfsstats nfsstats;
|
||||
extern int nfsv3_procid[NFS_NPROCS];
|
||||
extern int nfs_ticks;
|
||||
|
||||
/*
|
||||
* Defines which timer to use for the procnum.
|
||||
@ -134,7 +111,8 @@ static int nfsrv_errmap[ELAST] = {
|
||||
* 4 - write
|
||||
*/
|
||||
static int proct[NFS_NPROCS] = {
|
||||
0, 1, 0, 0, 2, 3, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0,
|
||||
0, 1, 0, 2, 1, 3, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0,
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -164,10 +142,12 @@ int nfsrv_null(),
|
||||
nfsrv_getattr(),
|
||||
nfsrv_setattr(),
|
||||
nfsrv_lookup(),
|
||||
nfsrv3_access(),
|
||||
nfsrv_readlink(),
|
||||
nfsrv_read(),
|
||||
nfsrv_write(),
|
||||
nfsrv_create(),
|
||||
nfsrv_mknod(),
|
||||
nfsrv_remove(),
|
||||
nfsrv_rename(),
|
||||
nfsrv_link(),
|
||||
@ -175,37 +155,42 @@ int nfsrv_null(),
|
||||
nfsrv_mkdir(),
|
||||
nfsrv_rmdir(),
|
||||
nfsrv_readdir(),
|
||||
nfsrv_readdirplus(),
|
||||
nfsrv_statfs(),
|
||||
nfsrv_fsinfo(),
|
||||
nfsrv_pathconf(),
|
||||
nfsrv_commit(),
|
||||
nfsrv_noop(),
|
||||
nqnfsrv_readdirlook(),
|
||||
nqnfsrv_getlease(),
|
||||
nqnfsrv_vacated(),
|
||||
nqnfsrv_access();
|
||||
nqnfsrv_vacated();
|
||||
|
||||
int (*nfsrv_procs[NFS_NPROCS])() = {
|
||||
int (*nfsrv3_procs[NFS_NPROCS])() = {
|
||||
nfsrv_null,
|
||||
nfsrv_getattr,
|
||||
nfsrv_setattr,
|
||||
nfsrv_noop,
|
||||
nfsrv_lookup,
|
||||
nfsrv3_access,
|
||||
nfsrv_readlink,
|
||||
nfsrv_read,
|
||||
nfsrv_noop,
|
||||
nfsrv_write,
|
||||
nfsrv_create,
|
||||
nfsrv_mkdir,
|
||||
nfsrv_symlink,
|
||||
nfsrv_mknod,
|
||||
nfsrv_remove,
|
||||
nfsrv_rmdir,
|
||||
nfsrv_rename,
|
||||
nfsrv_link,
|
||||
nfsrv_symlink,
|
||||
nfsrv_mkdir,
|
||||
nfsrv_rmdir,
|
||||
nfsrv_readdir,
|
||||
nfsrv_readdirplus,
|
||||
nfsrv_statfs,
|
||||
nqnfsrv_readdirlook,
|
||||
nfsrv_fsinfo,
|
||||
nfsrv_pathconf,
|
||||
nfsrv_commit,
|
||||
nqnfsrv_getlease,
|
||||
nqnfsrv_vacated,
|
||||
nfsrv_noop,
|
||||
nqnfsrv_access,
|
||||
nfsrv_noop
|
||||
};
|
||||
|
||||
/*
|
||||
@ -874,13 +859,16 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
struct nfsmount *nmp;
|
||||
struct mbuf *md, *mheadend;
|
||||
struct nfsnode *np;
|
||||
char nickv[RPCX_NICKVERF];
|
||||
time_t reqtime, waituntil;
|
||||
caddr_t dpos, cp2;
|
||||
int t1, nqlflag, cachable, s, error = 0, mrest_len, auth_len, auth_type;
|
||||
int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0, failed_auth = 0;
|
||||
int verf_len, verf_type;
|
||||
u_long xid;
|
||||
u_quad_t frev;
|
||||
char *auth_str;
|
||||
char *auth_str, *verf_str;
|
||||
NFSKERBKEY_T key; /* save session key */
|
||||
|
||||
nmp = VFSTONFS(vp->v_mount);
|
||||
MALLOC(rep, struct nfsreq *, sizeof(struct nfsreq), M_NFSREQ, M_WAITOK);
|
||||
@ -900,19 +888,21 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
* Get the RPC header with authorization.
|
||||
*/
|
||||
kerbauth:
|
||||
auth_str = (char *)0;
|
||||
verf_str = auth_str = (char *)0;
|
||||
if (nmp->nm_flag & NFSMNT_KERB) {
|
||||
if (failed_auth) {
|
||||
error = nfs_getauth(nmp, rep, cred, &auth_type,
|
||||
&auth_str, &auth_len);
|
||||
verf_str = nickv;
|
||||
verf_len = sizeof (nickv);
|
||||
auth_type = RPCAUTH_KERB4;
|
||||
bzero((caddr_t)key, sizeof (key));
|
||||
if (failed_auth || nfs_getnickauth(nmp, cred, &auth_str,
|
||||
&auth_len, verf_str, verf_len)) {
|
||||
error = nfs_getauth(nmp, rep, cred, &auth_str,
|
||||
&auth_len, verf_str, &verf_len, key);
|
||||
if (error) {
|
||||
free((caddr_t)rep, M_NFSREQ);
|
||||
m_freem(mrest);
|
||||
return (error);
|
||||
}
|
||||
} else {
|
||||
auth_type = RPCAUTH_UNIX;
|
||||
auth_len = 5 * NFSX_UNSIGNED;
|
||||
}
|
||||
} else {
|
||||
auth_type = RPCAUTH_UNIX;
|
||||
@ -922,8 +912,8 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) +
|
||||
5 * NFSX_UNSIGNED;
|
||||
}
|
||||
m = nfsm_rpchead(cred, (nmp->nm_flag & NFSMNT_NQNFS), procnum,
|
||||
auth_type, auth_len, auth_str, mrest, mrest_len, &mheadend, &xid);
|
||||
m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len,
|
||||
auth_str, verf_len, verf_str, mrest, mrest_len, &mheadend, &xid);
|
||||
if (auth_str)
|
||||
free(auth_str, M_TEMP);
|
||||
|
||||
@ -1029,12 +1019,12 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
/*
|
||||
* break down the rpc header and check if ok
|
||||
*/
|
||||
nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
|
||||
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
if (*tl++ == rpc_msgdenied) {
|
||||
if (*tl == rpc_mismatch)
|
||||
error = EOPNOTSUPP;
|
||||
else if ((nmp->nm_flag & NFSMNT_KERB) && *tl++ == rpc_autherr) {
|
||||
if (*tl == rpc_rejectedcred && failed_auth == 0) {
|
||||
if (!failed_auth) {
|
||||
failed_auth++;
|
||||
mheadend->m_next = (struct mbuf *)0;
|
||||
m_freem(mrep);
|
||||
@ -1051,22 +1041,25 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
}
|
||||
|
||||
/*
|
||||
* skip over the auth_verf, someday we may want to cache auth_short's
|
||||
* for nfs_reqhead(), but for now just dump it
|
||||
* Grab any Kerberos verifier, otherwise just throw it away.
|
||||
*/
|
||||
if (*++tl != 0) {
|
||||
i = nfsm_rndup(fxdr_unsigned(long, *tl));
|
||||
nfsm_adv(i);
|
||||
}
|
||||
verf_type = fxdr_unsigned(int, *tl++);
|
||||
i = fxdr_unsigned(int, *tl);
|
||||
if ((nmp->nm_flag & NFSMNT_KERB) && verf_type == RPCAUTH_KERB4) {
|
||||
error = nfs_savenickauth(nmp, cred, i, key, &md, &dpos, mrep);
|
||||
if (error)
|
||||
goto nfsmout;
|
||||
} else if (i > 0)
|
||||
nfsm_adv(nfsm_rndup(i));
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
|
||||
/* 0 == ok */
|
||||
if (*tl == 0) {
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
|
||||
if (*tl != 0) {
|
||||
error = fxdr_unsigned(int, *tl);
|
||||
m_freem(mrep);
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
error == NQNFS_TRYLATER) {
|
||||
if ((nmp->nm_flag & NFSMNT_NFSV3) &&
|
||||
error == NFSERR_TRYLATER) {
|
||||
m_freem(mrep);
|
||||
error = 0;
|
||||
waituntil = time.tv_sec + trylater_delay;
|
||||
while (time.tv_sec < waituntil)
|
||||
@ -1084,6 +1077,13 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
*/
|
||||
if (error == ESTALE)
|
||||
cache_purge(vp);
|
||||
if (nmp->nm_flag & NFSMNT_NFSV3) {
|
||||
*mrp = mrep;
|
||||
*mdp = md;
|
||||
*dposp = dpos;
|
||||
error |= NFSERR_RETERR;
|
||||
} else
|
||||
m_freem(mrep);
|
||||
m_freem(rep->r_mreq);
|
||||
free((caddr_t)rep, M_NFSREQ);
|
||||
return (error);
|
||||
@ -1115,10 +1115,10 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
return (0);
|
||||
}
|
||||
m_freem(mrep);
|
||||
m_freem(rep->r_mreq);
|
||||
free((caddr_t)rep, M_NFSREQ);
|
||||
error = EPROTONOSUPPORT;
|
||||
nfsmout:
|
||||
m_freem(rep->r_mreq);
|
||||
free((caddr_t)rep, M_NFSREQ);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1127,9 +1127,10 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
* siz arg. is used to decide if adding a cluster is worthwhile
|
||||
*/
|
||||
int
|
||||
nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
|
||||
nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
|
||||
int siz;
|
||||
struct nfsd *nd;
|
||||
struct nfsrv_descript *nd;
|
||||
struct nfssvc_sock *slp;
|
||||
int err;
|
||||
int cache;
|
||||
u_quad_t *frev;
|
||||
@ -1154,47 +1155,98 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
|
||||
} else
|
||||
mreq->m_data += max_hdr;
|
||||
tl = mtod(mreq, u_long *);
|
||||
mreq->m_len = 6*NFSX_UNSIGNED;
|
||||
bpos = ((caddr_t)tl)+mreq->m_len;
|
||||
mreq->m_len = 6 * NFSX_UNSIGNED;
|
||||
bpos = ((caddr_t)tl) + mreq->m_len;
|
||||
*tl++ = txdr_unsigned(nd->nd_retxid);
|
||||
*tl++ = rpc_reply;
|
||||
if (err == ERPCMISMATCH || err == NQNFS_AUTHERR) {
|
||||
if (err == ERPCMISMATCH || (err & NFSERR_AUTHERR)) {
|
||||
*tl++ = rpc_msgdenied;
|
||||
if (err == NQNFS_AUTHERR) {
|
||||
if (err & NFSERR_AUTHERR) {
|
||||
*tl++ = rpc_autherr;
|
||||
*tl = rpc_rejectedcred;
|
||||
*tl = txdr_unsigned(err & ~NFSERR_AUTHERR);
|
||||
mreq->m_len -= NFSX_UNSIGNED;
|
||||
bpos -= NFSX_UNSIGNED;
|
||||
} else {
|
||||
*tl++ = rpc_mismatch;
|
||||
*tl++ = txdr_unsigned(2);
|
||||
*tl = txdr_unsigned(2);
|
||||
*tl++ = txdr_unsigned(RPC_VER2);
|
||||
*tl = txdr_unsigned(RPC_VER2);
|
||||
}
|
||||
} else {
|
||||
*tl++ = rpc_msgaccepted;
|
||||
*tl++ = 0;
|
||||
*tl++ = 0;
|
||||
|
||||
/*
|
||||
* For Kerberos authentication, we must send the nickname
|
||||
* verifier back, otherwise just RPCAUTH_NULL.
|
||||
*/
|
||||
if (nd->nd_flag & ND_KERBFULL) {
|
||||
register struct nfsuid *nuidp;
|
||||
struct timeval ktvin, ktvout;
|
||||
NFSKERBKEYSCHED_T keys; /* stores key schedule */
|
||||
|
||||
for (nuidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
|
||||
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
|
||||
if (nuidp->nu_cr.cr_uid == nd->nd_cr.cr_uid &&
|
||||
(!nd->nd_nam2 || netaddr_match(NU_NETFAM(nuidp),
|
||||
&nuidp->nu_haddr, nd->nd_nam2)))
|
||||
break;
|
||||
}
|
||||
if (nuidp) {
|
||||
ktvin.tv_sec =
|
||||
txdr_unsigned(nuidp->nu_timestamp.tv_sec - 1);
|
||||
ktvin.tv_usec =
|
||||
txdr_unsigned(nuidp->nu_timestamp.tv_usec);
|
||||
|
||||
/*
|
||||
* Encrypt the timestamp in ecb mode using the
|
||||
* session key.
|
||||
*/
|
||||
#ifdef NFSKERB
|
||||
XXX
|
||||
#endif
|
||||
|
||||
*tl++ = rpc_auth_kerb;
|
||||
*tl++ = txdr_unsigned(3 * NFSX_UNSIGNED);
|
||||
*tl = ktvout.tv_sec;
|
||||
nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
*tl++ = ktvout.tv_usec;
|
||||
*tl++ = txdr_unsigned(nuidp->nu_cr.cr_uid);
|
||||
} else {
|
||||
*tl++ = 0;
|
||||
*tl++ = 0;
|
||||
}
|
||||
} else {
|
||||
*tl++ = 0;
|
||||
*tl++ = 0;
|
||||
}
|
||||
switch (err) {
|
||||
case EPROGUNAVAIL:
|
||||
*tl = txdr_unsigned(RPC_PROGUNAVAIL);
|
||||
break;
|
||||
case EPROGMISMATCH:
|
||||
*tl = txdr_unsigned(RPC_PROGMISMATCH);
|
||||
nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(2);
|
||||
*tl = txdr_unsigned(2); /* someday 3 */
|
||||
nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
|
||||
if (nd->nd_flag & ND_NQNFS) {
|
||||
*tl++ = txdr_unsigned(3);
|
||||
*tl = txdr_unsigned(3);
|
||||
} else {
|
||||
*tl++ = txdr_unsigned(2);
|
||||
*tl = txdr_unsigned(3);
|
||||
}
|
||||
break;
|
||||
case EPROCUNAVAIL:
|
||||
*tl = txdr_unsigned(RPC_PROCUNAVAIL);
|
||||
break;
|
||||
case EBADRPC:
|
||||
*tl = txdr_unsigned(RPC_GARBAGE);
|
||||
break;
|
||||
default:
|
||||
*tl = 0;
|
||||
if (err != VNOVAL) {
|
||||
if (err != NFSERR_RETVOID) {
|
||||
nfsm_build(tl, u_long *, NFSX_UNSIGNED);
|
||||
if (err)
|
||||
*tl = txdr_unsigned(nfsrv_errmap[err - 1]);
|
||||
*tl = txdr_unsigned(nfsrv_errmap(nd, err));
|
||||
else
|
||||
*tl = 0;
|
||||
*tl = 0;
|
||||
}
|
||||
break;
|
||||
};
|
||||
@ -1203,16 +1255,14 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
|
||||
/*
|
||||
* For nqnfs, piggyback lease as requested.
|
||||
*/
|
||||
if (nd->nd_nqlflag != NQL_NOVAL && err == 0) {
|
||||
if (nd->nd_nqlflag) {
|
||||
nfsm_build(tl, u_long *, 5*NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(nd->nd_nqlflag);
|
||||
if ((nd->nd_flag & ND_NQNFS) && err == 0) {
|
||||
if (nd->nd_flag & ND_LEASE) {
|
||||
nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(nd->nd_flag & ND_LEASE);
|
||||
*tl++ = txdr_unsigned(cache);
|
||||
*tl++ = txdr_unsigned(nd->nd_duration);
|
||||
txdr_hyper(frev, tl);
|
||||
} else {
|
||||
if (nd->nd_nqlflag != 0)
|
||||
panic("nqreph");
|
||||
nfsm_build(tl, u_long *, NFSX_UNSIGNED);
|
||||
*tl = 0;
|
||||
}
|
||||
@ -1220,7 +1270,7 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
|
||||
*mrq = mreq;
|
||||
*mbp = mb;
|
||||
*bposp = bpos;
|
||||
if (err != 0 && err != VNOVAL)
|
||||
if (err != 0 && err != NFSERR_RETVOID)
|
||||
nfsstats.srvrpc_errs++;
|
||||
return (0);
|
||||
}
|
||||
@ -1240,8 +1290,10 @@ nfs_timer(arg)
|
||||
register struct socket *so;
|
||||
register struct nfsmount *nmp;
|
||||
register int timeo;
|
||||
register struct nfssvc_sock *slp;
|
||||
static long lasttime = 0;
|
||||
int s, error;
|
||||
u_quad_t cur_usec;
|
||||
|
||||
s = splnet();
|
||||
for (rep = nfs_reqq.tqh_first; rep != 0; rep = rep->r_chain.tqe_next) {
|
||||
@ -1338,8 +1390,19 @@ nfs_timer(arg)
|
||||
lasttime = time.tv_sec;
|
||||
nqnfs_serverd();
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the write gathering queues for writes that need to be
|
||||
* completed now.
|
||||
*/
|
||||
cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
|
||||
for (slp = nfssvc_sockhead.tqh_first; slp != 0;
|
||||
slp = slp->ns_chain.tqe_next) {
|
||||
if (slp->ns_tq.lh_first && slp->ns_tq.lh_first->nd_time<=cur_usec)
|
||||
nfsrv_wakenfsd(slp);
|
||||
}
|
||||
splx(s);
|
||||
timeout(nfs_timer, (void *)0, hz / NFS_HZ);
|
||||
timeout(nfs_timer, (void *)0, nfs_ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1673,7 +1736,7 @@ nfsrv_getstream(slp, waitflag)
|
||||
register struct nfssvc_sock *slp;
|
||||
int waitflag;
|
||||
{
|
||||
register struct mbuf *m;
|
||||
register struct mbuf *m, **mpp;
|
||||
register char *cp1, *cp2;
|
||||
register int len;
|
||||
struct mbuf *om, *m2, *recm = 0;
|
||||
@ -1707,7 +1770,12 @@ nfsrv_getstream(slp, waitflag)
|
||||
}
|
||||
}
|
||||
slp->ns_cc -= NFSX_UNSIGNED;
|
||||
slp->ns_reclen = ntohl(recmark) & ~0x80000000;
|
||||
recmark = ntohl(recmark);
|
||||
slp->ns_reclen = recmark & ~0x80000000;
|
||||
if (recmark & 0x80000000)
|
||||
slp->ns_flag |= SLP_LASTFRAG;
|
||||
else
|
||||
slp->ns_flag &= ~SLP_LASTFRAG;
|
||||
if (slp->ns_reclen < NFS_MINPACKET || slp->ns_reclen > NFS_MAXPACKET) {
|
||||
slp->ns_flag &= ~SLP_GETSTREAM;
|
||||
return (EPERM);
|
||||
@ -1761,12 +1829,23 @@ nfsrv_getstream(slp, waitflag)
|
||||
slp->ns_flag &= ~SLP_GETSTREAM;
|
||||
return (0);
|
||||
}
|
||||
nfs_realign(recm, 10 * NFSX_UNSIGNED);
|
||||
if (slp->ns_recend)
|
||||
slp->ns_recend->m_nextpkt = recm;
|
||||
else
|
||||
slp->ns_rec = recm;
|
||||
slp->ns_recend = recm;
|
||||
|
||||
/*
|
||||
* Accumulate the fragments into a record.
|
||||
*/
|
||||
mpp = &slp->ns_frag;
|
||||
while (*mpp)
|
||||
mpp = &((*mpp)->m_next);
|
||||
*mpp = recm;
|
||||
if (slp->ns_flag & SLP_LASTFRAG) {
|
||||
nfs_realign(slp->ns_frag, 10 * NFSX_UNSIGNED);
|
||||
if (slp->ns_recend)
|
||||
slp->ns_recend->m_nextpkt = slp->ns_frag;
|
||||
else
|
||||
slp->ns_rec = slp->ns_frag;
|
||||
slp->ns_recend = slp->ns_frag;
|
||||
slp->ns_frag = (struct mbuf *)0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1774,13 +1853,16 @@ nfsrv_getstream(slp, waitflag)
|
||||
* Parse an RPC header.
|
||||
*/
|
||||
int
|
||||
nfsrv_dorec(slp, nd)
|
||||
nfsrv_dorec(slp, nfsd, ndp)
|
||||
register struct nfssvc_sock *slp;
|
||||
register struct nfsd *nd;
|
||||
struct nfsd *nfsd;
|
||||
struct nfsrv_descript **ndp;
|
||||
{
|
||||
register struct mbuf *m;
|
||||
register struct mbuf *m, *nam;
|
||||
register struct nfsrv_descript *nd;
|
||||
int error;
|
||||
|
||||
*ndp = NULL;
|
||||
if ((slp->ns_flag & SLP_VALID) == 0 ||
|
||||
(m = slp->ns_rec) == (struct mbuf *)0)
|
||||
return (ENOBUFS);
|
||||
@ -1790,19 +1872,24 @@ nfsrv_dorec(slp, nd)
|
||||
else
|
||||
slp->ns_recend = (struct mbuf *)0;
|
||||
if (m->m_type == MT_SONAME) {
|
||||
nd->nd_nam = m;
|
||||
nd->nd_md = nd->nd_mrep = m->m_next;
|
||||
m->m_next = (struct mbuf *)0;
|
||||
} else {
|
||||
nd->nd_nam = (struct mbuf *)0;
|
||||
nd->nd_md = nd->nd_mrep = m;
|
||||
}
|
||||
nd->nd_dpos = mtod(nd->nd_md, caddr_t);
|
||||
error = nfs_getreq(nd, TRUE);
|
||||
nam = m;
|
||||
m = m->m_next;
|
||||
nam->m_next = NULL;
|
||||
} else
|
||||
nam = NULL;
|
||||
MALLOC(nd, struct nfsrv_descript *, sizeof (struct nfsrv_descript),
|
||||
M_NFSRVDESC, M_WAITOK);
|
||||
nd->nd_md = nd->nd_mrep = m;
|
||||
nd->nd_nam2 = nam;
|
||||
nd->nd_dpos = mtod(m, caddr_t);
|
||||
error = nfs_getreq(nd, nfsd, TRUE);
|
||||
if (error) {
|
||||
m_freem(nd->nd_nam);
|
||||
m_freem(nam);
|
||||
free((caddr_t)nd, M_NFSRVDESC);
|
||||
return (error);
|
||||
}
|
||||
*ndp = nd;
|
||||
nfsd->nfsd_nd = nd;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1812,8 +1899,9 @@ nfsrv_dorec(slp, nd)
|
||||
* - fill in the cred struct.
|
||||
*/
|
||||
int
|
||||
nfs_getreq(nd, has_header)
|
||||
register struct nfsd *nd;
|
||||
nfs_getreq(nd, nfsd, has_header)
|
||||
register struct nfsrv_descript *nd;
|
||||
struct nfsd *nfsd;
|
||||
int has_header;
|
||||
{
|
||||
register int len, i;
|
||||
@ -1821,57 +1909,67 @@ nfs_getreq(nd, has_header)
|
||||
register long t1;
|
||||
struct uio uio;
|
||||
struct iovec iov;
|
||||
caddr_t dpos, cp2;
|
||||
caddr_t dpos, cp2, cp;
|
||||
u_long nfsvers, auth_type;
|
||||
int error = 0, nqnfs = 0;
|
||||
uid_t nickuid;
|
||||
int error = 0, nqnfs = 0, ticklen;
|
||||
struct mbuf *mrep, *md;
|
||||
register struct nfsuid *nuidp;
|
||||
struct timeval tvin, tvout;
|
||||
NFSKERBKEYSCHED_T keys; /* stores key schedule */
|
||||
|
||||
mrep = nd->nd_mrep;
|
||||
md = nd->nd_md;
|
||||
dpos = nd->nd_dpos;
|
||||
if (has_header) {
|
||||
nfsm_dissect(tl, u_long *, 10*NFSX_UNSIGNED);
|
||||
nfsm_dissect(tl, u_long *, 10 * NFSX_UNSIGNED);
|
||||
nd->nd_retxid = fxdr_unsigned(u_long, *tl++);
|
||||
if (*tl++ != rpc_call) {
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
} else {
|
||||
nfsm_dissect(tl, u_long *, 8*NFSX_UNSIGNED);
|
||||
}
|
||||
} else
|
||||
nfsm_dissect(tl, u_long *, 8 * NFSX_UNSIGNED);
|
||||
nd->nd_repstat = 0;
|
||||
nd->nd_flag = 0;
|
||||
if (*tl++ != rpc_vers) {
|
||||
nd->nd_repstat = ERPCMISMATCH;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nfsvers = nfs_vers;
|
||||
if (*tl != nfs_prog) {
|
||||
if (*tl == nqnfs_prog) {
|
||||
if (*tl == nqnfs_prog)
|
||||
nqnfs++;
|
||||
nfsvers = nqnfs_vers;
|
||||
} else {
|
||||
else {
|
||||
nd->nd_repstat = EPROGUNAVAIL;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
tl++;
|
||||
if (*tl++ != nfsvers) {
|
||||
nfsvers = fxdr_unsigned(u_long, *tl++);
|
||||
if (((nfsvers < NFS_VER2 || nfsvers > NFS_VER3) && !nqnfs) ||
|
||||
(nfsvers != NQNFS_VER3 && nqnfs)) {
|
||||
nd->nd_repstat = EPROGMISMATCH;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
if (nqnfs)
|
||||
nd->nd_flag = (ND_NFSV3 | ND_NQNFS);
|
||||
else if (nfsvers == NFS_VER3)
|
||||
nd->nd_flag = ND_NFSV3;
|
||||
nd->nd_procnum = fxdr_unsigned(u_long, *tl++);
|
||||
if (nd->nd_procnum == NFSPROC_NULL)
|
||||
return (0);
|
||||
if (nd->nd_procnum >= NFS_NPROCS ||
|
||||
(!nqnfs && nd->nd_procnum > NFSPROC_STATFS) ||
|
||||
(*tl != rpc_auth_unix && *tl != rpc_auth_kerb)) {
|
||||
(!nqnfs && nd->nd_procnum >= NQNFSPROC_GETLEASE) ||
|
||||
(!nd->nd_flag && nd->nd_procnum > NFSV2PROC_STATFS)) {
|
||||
nd->nd_repstat = EPROCUNAVAIL;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
if ((nd->nd_flag & ND_NFSV3) == 0)
|
||||
nd->nd_procnum = nfsv3_procid[nd->nd_procnum];
|
||||
auth_type = *tl++;
|
||||
len = fxdr_unsigned(int, *tl++);
|
||||
if (len < 0 || len > RPCAUTH_MAXSIZ) {
|
||||
@ -1879,6 +1977,7 @@ nfs_getreq(nd, has_header)
|
||||
return (EBADRPC);
|
||||
}
|
||||
|
||||
nd->nd_flag &= ~ND_KERBAUTH;
|
||||
/*
|
||||
* Handle auth_unix or auth_kerb.
|
||||
*/
|
||||
@ -1889,7 +1988,9 @@ nfs_getreq(nd, has_header)
|
||||
return (EBADRPC);
|
||||
}
|
||||
nfsm_adv(nfsm_rndup(len));
|
||||
nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
|
||||
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
bzero((caddr_t)&nd->nd_cr, sizeof (struct ucred));
|
||||
nd->nd_cr.cr_ref = 1;
|
||||
nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
|
||||
nd->nd_cr.cr_gid = fxdr_unsigned(gid_t, *tl++);
|
||||
len = fxdr_unsigned(int, *tl);
|
||||
@ -1897,45 +1998,124 @@ nfs_getreq(nd, has_header)
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
nfsm_dissect(tl, u_long *, (len + 2)*NFSX_UNSIGNED);
|
||||
nfsm_dissect(tl, u_long *, (len + 2) * NFSX_UNSIGNED);
|
||||
for (i = 1; i <= len; i++)
|
||||
if (i < NGROUPS)
|
||||
nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
|
||||
else
|
||||
tl++;
|
||||
if (i < NGROUPS)
|
||||
nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
|
||||
else
|
||||
tl++;
|
||||
nd->nd_cr.cr_ngroups = (len >= NGROUPS) ? NGROUPS : (len + 1);
|
||||
} else if (auth_type == rpc_auth_kerb) {
|
||||
nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
|
||||
nd->nd_authlen = fxdr_unsigned(int, *tl);
|
||||
uio.uio_resid = nfsm_rndup(nd->nd_authlen);
|
||||
if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
|
||||
if (nd->nd_cr.cr_ngroups > 1)
|
||||
nfsrvw_sort(nd->nd_cr.cr_groups, nd->nd_cr.cr_ngroups);
|
||||
len = fxdr_unsigned(int, *++tl);
|
||||
if (len < 0 || len > RPCAUTH_MAXSIZ) {
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
uio.uio_offset = 0;
|
||||
uio.uio_iov = &iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
uio.uio_segflg = UIO_SYSSPACE;
|
||||
iov.iov_base = (caddr_t)nd->nd_authstr;
|
||||
iov.iov_len = RPCAUTH_MAXSIZ;
|
||||
nfsm_mtouio(&uio, uio.uio_resid);
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
|
||||
nd->nd_flag |= NFSD_NEEDAUTH;
|
||||
}
|
||||
if (len > 0)
|
||||
nfsm_adv(nfsm_rndup(len));
|
||||
} else if (auth_type == rpc_auth_kerb) {
|
||||
switch (fxdr_unsigned(int, *tl++)) {
|
||||
case RPCAKN_FULLNAME:
|
||||
ticklen = fxdr_unsigned(int, *tl);
|
||||
*((u_long *)nfsd->nfsd_authstr) = *tl;
|
||||
uio.uio_resid = nfsm_rndup(ticklen) + NFSX_UNSIGNED;
|
||||
nfsd->nfsd_authlen = uio.uio_resid + NFSX_UNSIGNED;
|
||||
if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
uio.uio_offset = 0;
|
||||
uio.uio_iov = &iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
uio.uio_segflg = UIO_SYSSPACE;
|
||||
iov.iov_base = (caddr_t)&nfsd->nfsd_authstr[4];
|
||||
iov.iov_len = RPCAUTH_MAXSIZ - 4;
|
||||
nfsm_mtouio(&uio, uio.uio_resid);
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
|
||||
if (*tl++ != rpc_auth_kerb ||
|
||||
fxdr_unsigned(int, *tl) != 4 * NFSX_UNSIGNED) {
|
||||
printf("Bad kerb verifier\n");
|
||||
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nfsm_dissect(cp, caddr_t, 4 * NFSX_UNSIGNED);
|
||||
tl = (u_long *)cp;
|
||||
if (fxdr_unsigned(int, *tl) != RPCAKN_FULLNAME) {
|
||||
printf("Not fullname kerb verifier\n");
|
||||
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
cp += NFSX_UNSIGNED;
|
||||
bcopy(cp, nfsd->nfsd_verfstr, 3 * NFSX_UNSIGNED);
|
||||
nfsd->nfsd_verflen = 3 * NFSX_UNSIGNED;
|
||||
nd->nd_flag |= ND_KERBFULL;
|
||||
nfsd->nfsd_flag |= NFSD_NEEDAUTH;
|
||||
break;
|
||||
case RPCAKN_NICKNAME:
|
||||
if (len != 2 * NFSX_UNSIGNED) {
|
||||
printf("Kerb nickname short\n");
|
||||
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADCRED);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nickuid = fxdr_unsigned(uid_t, *tl);
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
|
||||
if (*tl++ != rpc_auth_kerb ||
|
||||
fxdr_unsigned(int, *tl) != 3 * NFSX_UNSIGNED) {
|
||||
printf("Kerb nick verifier bad\n");
|
||||
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
tvin.tv_sec = *tl++;
|
||||
tvin.tv_usec = *tl;
|
||||
|
||||
/*
|
||||
* Do we have any use for the verifier.
|
||||
* According to the "Remote Procedure Call Protocol Spec." it
|
||||
* should be AUTH_NULL, but some clients make it AUTH_UNIX?
|
||||
* For now, just skip over it
|
||||
*/
|
||||
len = fxdr_unsigned(int, *++tl);
|
||||
if (len < 0 || len > RPCAUTH_MAXSIZ) {
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
if (len > 0) {
|
||||
nfsm_adv(nfsm_rndup(len));
|
||||
for (nuidp = NUIDHASH(nfsd->nfsd_slp,nickuid)->lh_first;
|
||||
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
|
||||
if (nuidp->nu_cr.cr_uid == nickuid &&
|
||||
(!nd->nd_nam2 ||
|
||||
netaddr_match(NU_NETFAM(nuidp),
|
||||
&nuidp->nu_haddr, nd->nd_nam2)))
|
||||
break;
|
||||
}
|
||||
if (!nuidp) {
|
||||
nd->nd_repstat =
|
||||
(NFSERR_AUTHERR|AUTH_REJECTCRED);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, decrypt the timestamp using the session key
|
||||
* and validate it.
|
||||
*/
|
||||
#ifdef NFSKERB
|
||||
XXX
|
||||
#endif
|
||||
|
||||
tvout.tv_sec = fxdr_unsigned(long, tvout.tv_sec);
|
||||
tvout.tv_usec = fxdr_unsigned(long, tvout.tv_usec);
|
||||
if (nuidp->nu_expire < time.tv_sec ||
|
||||
nuidp->nu_timestamp.tv_sec > tvout.tv_sec ||
|
||||
(nuidp->nu_timestamp.tv_sec == tvout.tv_sec &&
|
||||
nuidp->nu_timestamp.tv_usec > tvout.tv_usec)) {
|
||||
nuidp->nu_expire = 0;
|
||||
nd->nd_repstat =
|
||||
(NFSERR_AUTHERR|AUTH_REJECTVERF);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nfsrv_setcred(&nuidp->nu_cr, &nd->nd_cr);
|
||||
nd->nd_flag |= ND_KERBNICK;
|
||||
};
|
||||
} else {
|
||||
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_REJECTCRED);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1943,16 +2123,14 @@ nfs_getreq(nd, has_header)
|
||||
*/
|
||||
if (nqnfs && nd->nd_procnum != NQNFSPROC_EVICTED) {
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
|
||||
nd->nd_nqlflag = fxdr_unsigned(int, *tl);
|
||||
if (nd->nd_nqlflag) {
|
||||
nd->nd_flag |= fxdr_unsigned(int, *tl);
|
||||
if (nd->nd_flag & ND_LEASE) {
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
|
||||
nd->nd_duration = fxdr_unsigned(int, *tl);
|
||||
} else
|
||||
nd->nd_duration = NQ_MINLEASE;
|
||||
} else {
|
||||
nd->nd_nqlflag = NQL_NOVAL;
|
||||
} else
|
||||
nd->nd_duration = NQ_MINLEASE;
|
||||
}
|
||||
nd->nd_md = md;
|
||||
nd->nd_dpos = dpos;
|
||||
return (0);
|
||||
@ -1973,13 +2151,13 @@ nfsrv_wakenfsd(slp)
|
||||
|
||||
if ((slp->ns_flag & SLP_VALID) == 0)
|
||||
return;
|
||||
for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nd_chain.tqe_next) {
|
||||
if (nd->nd_flag & NFSD_WAITING) {
|
||||
nd->nd_flag &= ~NFSD_WAITING;
|
||||
if (nd->nd_slp)
|
||||
for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nfsd_chain.tqe_next) {
|
||||
if (nd->nfsd_flag & NFSD_WAITING) {
|
||||
nd->nfsd_flag &= ~NFSD_WAITING;
|
||||
if (nd->nfsd_slp)
|
||||
panic("nfsd wakeup");
|
||||
slp->ns_sref++;
|
||||
nd->nd_slp = slp;
|
||||
nd->nfsd_slp = slp;
|
||||
wakeup((caddr_t)nd);
|
||||
return;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_vfsops.c 8.3 (Berkeley) 1/4/94
|
||||
* $Id: nfs_vfsops.c,v 1.14.2.1 1995/06/02 11:13:15 davidg Exp $
|
||||
* $Id: nfs_vfsops.c,v 1.15 1995/06/11 19:31:46 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -59,10 +59,10 @@
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/xdr_subs.h>
|
||||
#include <nfs/nfsm_subs.h>
|
||||
#include <nfs/nfsdiskless.h>
|
||||
@ -71,11 +71,15 @@
|
||||
struct nfsstats nfsstats;
|
||||
static int nfs_sysctl(int *, u_int, void *, size_t *, void *, size_t,
|
||||
struct proc *);
|
||||
extern int nfs_ticks;
|
||||
|
||||
/*
|
||||
* nfs vfs operations.
|
||||
*/
|
||||
struct vfsops nfs_vfsops = {
|
||||
#ifdef __NetBSD__
|
||||
MOUNT_NFS,
|
||||
#endif
|
||||
nfs_mount,
|
||||
nfs_start,
|
||||
nfs_unmount,
|
||||
@ -87,9 +91,13 @@ struct vfsops nfs_vfsops = {
|
||||
nfs_fhtovp,
|
||||
nfs_vptofh,
|
||||
nfs_init,
|
||||
#ifdef __FreeBSD__
|
||||
nfs_sysctl
|
||||
#endif
|
||||
};
|
||||
#ifdef __FreeBSD__
|
||||
VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This structure must be filled in by a primary bootstrap or bootstrap
|
||||
@ -99,16 +107,11 @@ VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK);
|
||||
struct nfs_diskless nfs_diskless = { 0 };
|
||||
int nfs_diskless_valid = 0;
|
||||
|
||||
extern u_long nfs_procids[NFS_NPROCS];
|
||||
extern u_long nfs_prog, nfs_vers;
|
||||
void nfs_disconnect __P((struct nfsmount *));
|
||||
void nfsargs_ntoh __P((struct nfs_args *));
|
||||
static struct mount *nfs_mountdiskless __P((char *, char *, int,
|
||||
struct sockaddr_in *, struct nfs_args *, register struct vnode **));
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
/*
|
||||
* nfs statfs call
|
||||
*/
|
||||
@ -119,40 +122,65 @@ nfs_statfs(mp, sbp, p)
|
||||
struct proc *p;
|
||||
{
|
||||
register struct vnode *vp;
|
||||
register struct nfsv2_statfs *sfp;
|
||||
register struct nfs_statfs *sfp;
|
||||
register caddr_t cp;
|
||||
register long t1;
|
||||
register u_long *tl;
|
||||
register long t1, t2;
|
||||
caddr_t bpos, dpos, cp2;
|
||||
int error = 0, isnq;
|
||||
struct nfsmount *nmp = VFSTONFS(mp);
|
||||
int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
|
||||
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
|
||||
struct nfsmount *nmp;
|
||||
struct ucred *cred;
|
||||
struct nfsnode *np;
|
||||
u_quad_t tquad;
|
||||
|
||||
nmp = VFSTONFS(mp);
|
||||
isnq = (nmp->nm_flag & NFSMNT_NQNFS);
|
||||
error = nfs_nget(mp, &nmp->nm_fh, &np);
|
||||
#ifndef nolint
|
||||
sfp = (struct nfs_statfs *)0;
|
||||
#endif
|
||||
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
|
||||
if (error)
|
||||
return (error);
|
||||
vp = NFSTOV(np);
|
||||
nfsstats.rpccnt[NFSPROC_STATFS]++;
|
||||
cred = crget();
|
||||
cred->cr_ngroups = 1;
|
||||
nfsm_reqhead(vp, NFSPROC_STATFS, NFSX_FH);
|
||||
nfsm_fhtom(vp);
|
||||
nfsm_request(vp, NFSPROC_STATFS, p, cred);
|
||||
nfsm_dissect(sfp, struct nfsv2_statfs *, NFSX_STATFS(isnq));
|
||||
if (v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0)
|
||||
(void)nfs_fsinfo(nmp, vp, cred, p);
|
||||
nfsstats.rpccnt[NFSPROC_FSSTAT]++;
|
||||
nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
|
||||
nfsm_fhtom(vp, v3);
|
||||
nfsm_request(vp, NFSPROC_FSSTAT, p, cred);
|
||||
if (v3)
|
||||
nfsm_postop_attr(vp, retattr);
|
||||
if (!error)
|
||||
nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
|
||||
#ifdef __NetBSD__
|
||||
#ifdef COMPAT_09
|
||||
sbp->f_type = 2;
|
||||
#else
|
||||
sbp->f_type = 0;
|
||||
#endif
|
||||
#else
|
||||
sbp->f_type = MOUNT_NFS;
|
||||
#endif
|
||||
sbp->f_flags = nmp->nm_flag;
|
||||
sbp->f_iosize = NFS_MAXDGRAMDATA;
|
||||
sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize);
|
||||
sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
|
||||
sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
|
||||
sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
|
||||
if (isnq) {
|
||||
sbp->f_files = fxdr_unsigned(long, sfp->sf_files);
|
||||
sbp->f_ffree = fxdr_unsigned(long, sfp->sf_ffree);
|
||||
sbp->f_iosize = min(nmp->nm_rsize, nmp->nm_wsize);
|
||||
if (v3) {
|
||||
sbp->f_bsize = NFS_FABLKSIZE;
|
||||
fxdr_hyper(&sfp->sf_tbytes, &tquad);
|
||||
sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
|
||||
fxdr_hyper(&sfp->sf_fbytes, &tquad);
|
||||
sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
|
||||
fxdr_hyper(&sfp->sf_abytes, &tquad);
|
||||
sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
|
||||
sbp->f_files = (fxdr_unsigned(long, sfp->sf_tfiles.nfsuquad[1])
|
||||
& 0x7fffffff);
|
||||
sbp->f_ffree = (fxdr_unsigned(long, sfp->sf_ffiles.nfsuquad[1])
|
||||
& 0x7fffffff);
|
||||
} else {
|
||||
sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize);
|
||||
sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
|
||||
sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
|
||||
sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
|
||||
sbp->f_files = 0;
|
||||
sbp->f_ffree = 0;
|
||||
}
|
||||
@ -161,11 +189,71 @@ nfs_statfs(mp, sbp, p)
|
||||
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
|
||||
}
|
||||
nfsm_reqdone;
|
||||
vrele(vp);
|
||||
vput(vp);
|
||||
crfree(cred);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* nfs version 3 fsinfo rpc call
|
||||
*/
|
||||
int
|
||||
nfs_fsinfo(nmp, vp, cred, p)
|
||||
register struct nfsmount *nmp;
|
||||
register struct vnode *vp;
|
||||
struct ucred *cred;
|
||||
struct proc *p;
|
||||
{
|
||||
register struct nfsv3_fsinfo *fsp;
|
||||
register caddr_t cp;
|
||||
register long t1, t2;
|
||||
register u_long *tl, pref, max;
|
||||
caddr_t bpos, dpos, cp2;
|
||||
int error = 0, retattr;
|
||||
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
|
||||
|
||||
nfsstats.rpccnt[NFSPROC_FSINFO]++;
|
||||
nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
|
||||
nfsm_fhtom(vp, 1);
|
||||
nfsm_request(vp, NFSPROC_FSINFO, p, cred);
|
||||
nfsm_postop_attr(vp, retattr);
|
||||
if (!error) {
|
||||
nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
|
||||
pref = fxdr_unsigned(u_long, fsp->fs_wtpref);
|
||||
if (pref < nmp->nm_wsize)
|
||||
nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
|
||||
~(NFS_FABLKSIZE - 1);
|
||||
max = fxdr_unsigned(u_long, fsp->fs_wtmax);
|
||||
if (max < nmp->nm_wsize) {
|
||||
nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
|
||||
if (nmp->nm_wsize == 0)
|
||||
nmp->nm_wsize = max;
|
||||
}
|
||||
pref = fxdr_unsigned(u_long, fsp->fs_rtpref);
|
||||
if (pref < nmp->nm_rsize)
|
||||
nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
|
||||
~(NFS_FABLKSIZE - 1);
|
||||
max = fxdr_unsigned(u_long, fsp->fs_rtmax);
|
||||
if (max < nmp->nm_rsize) {
|
||||
nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
|
||||
if (nmp->nm_rsize == 0)
|
||||
nmp->nm_rsize = max;
|
||||
}
|
||||
pref = fxdr_unsigned(u_long, fsp->fs_dtpref);
|
||||
if (pref < nmp->nm_readdirsize)
|
||||
nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
|
||||
~(NFS_DIRBLKSIZ - 1);
|
||||
if (max < nmp->nm_readdirsize) {
|
||||
nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
|
||||
if (nmp->nm_readdirsize == 0)
|
||||
nmp->nm_readdirsize = max;
|
||||
}
|
||||
nmp->nm_flag |= NFSMNT_GOTFSINFO;
|
||||
}
|
||||
nfsm_reqdone;
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mount a remote root fs via. nfs. This depends on the info in the
|
||||
* nfs_diskless structure that has been filled in properly by some primary
|
||||
@ -268,7 +356,12 @@ nfs_mountroot()
|
||||
* Create a fake mount point just for the swap vnode so that the
|
||||
* swap file can be on a different server from the rootfs.
|
||||
*/
|
||||
nd->swap_args.fh = (nfsv2fh_t *)nd->swap_fh;
|
||||
nd->swap_args.fh = nd->swap_fh;
|
||||
/*
|
||||
* If using nfsv3_diskless, replace NFSX_V2FH with
|
||||
* nd->swap_fhsize.
|
||||
*/
|
||||
nd->swap_args.fhsize = NFSX_V2FH;
|
||||
l = ntohl(nd->swap_saddr.sin_addr.s_addr);
|
||||
sprintf(buf,"%ld.%ld.%ld.%ld:%s",
|
||||
(l >> 24) & 0xff, (l >> 16) & 0xff,
|
||||
@ -293,8 +386,12 @@ nfs_mountroot()
|
||||
/*
|
||||
* Create the rootfs mount point.
|
||||
*/
|
||||
nd->root_args.fh = (nfsv2fh_t *)nd->root_fh;
|
||||
l = ntohl(nd->root_saddr.sin_addr.s_addr);
|
||||
nd->root_args.fh = nd->root_fh;
|
||||
/*
|
||||
* If using nfsv3_diskless, replace NFSX_V2FH with nd->root_fhsize.
|
||||
*/
|
||||
nd->root_args.fhsize = NFSX_V2FH;
|
||||
l = ntohl(nd->swap_saddr.sin_addr.s_addr);
|
||||
sprintf(buf,"%ld.%ld.%ld.%ld:%s",
|
||||
(l >> 24) & 0xff, (l >> 16) & 0xff,
|
||||
(l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam);
|
||||
@ -304,7 +401,11 @@ nfs_mountroot()
|
||||
|
||||
if (vfs_lock(mp))
|
||||
panic("nfs_mountroot: vfs_lock");
|
||||
#if NetBSD >= 1994101
|
||||
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
|
||||
#else
|
||||
TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
|
||||
#endif
|
||||
mp->mnt_flag |= MNT_ROOTFS;
|
||||
mp->mnt_vnodecovered = NULLVP;
|
||||
vfs_unlock(mp);
|
||||
@ -386,12 +487,12 @@ nfs_mount(mp, path, data, ndp, p)
|
||||
struct vnode *vp;
|
||||
char pth[MNAMELEN], hst[MNAMELEN];
|
||||
u_int len;
|
||||
nfsv2fh_t nfh;
|
||||
u_char nfh[NFSX_V3FHMAX];
|
||||
|
||||
error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
|
||||
if (error)
|
||||
return (error);
|
||||
error = copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t));
|
||||
error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
|
||||
if (error)
|
||||
return (error);
|
||||
error = copyinstr(path, pth, MNAMELEN-1, &len);
|
||||
@ -406,7 +507,7 @@ nfs_mount(mp, path, data, ndp, p)
|
||||
error = sockargs(&nam, (caddr_t)args.addr, args.addrlen, MT_SONAME);
|
||||
if (error)
|
||||
return (error);
|
||||
args.fh = &nfh;
|
||||
args.fh = nfh;
|
||||
error = mountnfs(&args, mp, nam, pth, hst, &vp);
|
||||
return (error);
|
||||
}
|
||||
@ -424,7 +525,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
|
||||
{
|
||||
register struct nfsmount *nmp;
|
||||
struct nfsnode *np;
|
||||
int error;
|
||||
int error, maxio;
|
||||
|
||||
if (mp->mnt_flag & MNT_UPDATE) {
|
||||
nmp = VFSTONFS(mp);
|
||||
@ -435,16 +536,12 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
|
||||
MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount),
|
||||
M_NFSMNT, M_WAITOK);
|
||||
bzero((caddr_t)nmp, sizeof (struct nfsmount));
|
||||
TAILQ_INIT(&nmp->nm_uidlruhead);
|
||||
mp->mnt_data = (qaddr_t)nmp;
|
||||
}
|
||||
getnewfsid(mp, MOUNT_NFS);
|
||||
nmp->nm_mountp = mp;
|
||||
nmp->nm_flag = argp->flags;
|
||||
if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_MYWRITE)) ==
|
||||
(NFSMNT_NQNFS | NFSMNT_MYWRITE)) {
|
||||
error = EPERM;
|
||||
goto bad;
|
||||
}
|
||||
if (nmp->nm_flag & NFSMNT_NQNFS)
|
||||
/*
|
||||
* We have to set mnt_maxsymlink to a non-zero value so
|
||||
@ -457,14 +554,24 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
|
||||
nmp->nm_retry = NFS_RETRANS;
|
||||
nmp->nm_wsize = NFS_WSIZE;
|
||||
nmp->nm_rsize = NFS_RSIZE;
|
||||
nmp->nm_readdirsize = NFS_READDIRSIZE;
|
||||
nmp->nm_numgrps = NFS_MAXGRPS;
|
||||
nmp->nm_readahead = NFS_DEFRAHEAD;
|
||||
nmp->nm_leaseterm = NQ_DEFLEASE;
|
||||
nmp->nm_deadthresh = NQ_DEADTHRESH;
|
||||
CIRCLEQ_INIT(&nmp->nm_timerhead);
|
||||
nmp->nm_inprog = NULLVP;
|
||||
bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t));
|
||||
nmp->nm_fhsize = argp->fhsize;
|
||||
bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
|
||||
#ifdef __NetBSD__
|
||||
#ifdef COMPAT_09
|
||||
mp->mnt_stat.f_type = 2;
|
||||
#else
|
||||
mp->mnt_stat.f_type = 0;
|
||||
#endif
|
||||
#else
|
||||
mp->mnt_stat.f_type = MOUNT_NFS;
|
||||
#endif
|
||||
bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
|
||||
bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
|
||||
nmp->nm_nam = nam;
|
||||
@ -483,29 +590,48 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
|
||||
nmp->nm_retry = NFS_MAXREXMIT;
|
||||
}
|
||||
|
||||
if (argp->flags & NFSMNT_NFSV3) {
|
||||
if (argp->sotype == SOCK_DGRAM)
|
||||
maxio = NFS_MAXDGRAMDATA;
|
||||
else
|
||||
maxio = NFS_MAXDATA;
|
||||
} else
|
||||
maxio = NFS_V2MAXDATA;
|
||||
|
||||
if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
|
||||
nmp->nm_wsize = argp->wsize;
|
||||
/* Round down to multiple of blocksize */
|
||||
nmp->nm_wsize &= ~0x1ff;
|
||||
nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
|
||||
if (nmp->nm_wsize <= 0)
|
||||
nmp->nm_wsize = 512;
|
||||
else if (nmp->nm_wsize > NFS_MAXDATA)
|
||||
nmp->nm_wsize = NFS_MAXDATA;
|
||||
nmp->nm_wsize = NFS_FABLKSIZE;
|
||||
}
|
||||
if (nmp->nm_wsize > maxio)
|
||||
nmp->nm_wsize = maxio;
|
||||
if (nmp->nm_wsize > MAXBSIZE)
|
||||
nmp->nm_wsize = MAXBSIZE;
|
||||
|
||||
if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
|
||||
nmp->nm_rsize = argp->rsize;
|
||||
/* Round down to multiple of blocksize */
|
||||
nmp->nm_rsize &= ~0x1ff;
|
||||
nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
|
||||
if (nmp->nm_rsize <= 0)
|
||||
nmp->nm_rsize = 512;
|
||||
else if (nmp->nm_rsize > NFS_MAXDATA)
|
||||
nmp->nm_rsize = NFS_MAXDATA;
|
||||
nmp->nm_rsize = NFS_FABLKSIZE;
|
||||
}
|
||||
if (nmp->nm_rsize > maxio)
|
||||
nmp->nm_rsize = maxio;
|
||||
if (nmp->nm_rsize > MAXBSIZE)
|
||||
nmp->nm_rsize = MAXBSIZE;
|
||||
|
||||
if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
|
||||
nmp->nm_readdirsize = argp->readdirsize;
|
||||
/* Round down to multiple of blocksize */
|
||||
nmp->nm_readdirsize &= ~(NFS_DIRBLKSIZ - 1);
|
||||
if (nmp->nm_readdirsize < NFS_DIRBLKSIZ)
|
||||
nmp->nm_readdirsize = NFS_DIRBLKSIZ;
|
||||
}
|
||||
if (nmp->nm_readdirsize > maxio)
|
||||
nmp->nm_readdirsize = maxio;
|
||||
|
||||
if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 &&
|
||||
argp->maxgrouplist <= NFS_MAXGRPS)
|
||||
nmp->nm_numgrps = argp->maxgrouplist;
|
||||
@ -536,7 +662,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
|
||||
* stuck on a dead server and we are holding a lock on the mount
|
||||
* point.
|
||||
*/
|
||||
mp->mnt_stat.f_iosize = NFS_MAXDGRAMDATA;
|
||||
mp->mnt_stat.f_iosize = min(nmp->nm_rsize, nmp->nm_wsize);
|
||||
/*
|
||||
* A reference count is needed on the nfsnode representing the
|
||||
* remote root. If this object is not persistent, then backward
|
||||
@ -545,11 +671,16 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
|
||||
* this problem, because one can identify root inodes by their
|
||||
* number == ROOTINO (2).
|
||||
*/
|
||||
error = nfs_nget(mp, &nmp->nm_fh, &np);
|
||||
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
|
||||
if (error)
|
||||
goto bad;
|
||||
*vpp = NFSTOV(np);
|
||||
|
||||
/*
|
||||
* Lose the lock but keep the ref.
|
||||
*/
|
||||
VOP_UNLOCK(*vpp);
|
||||
|
||||
return (0);
|
||||
bad:
|
||||
nfs_disconnect(nmp);
|
||||
@ -592,7 +723,7 @@ nfs_unmount(mp, mntflags, p)
|
||||
* the remote root. See comment in mountnfs(). The VFS unmount()
|
||||
* has done vput on this vnode, otherwise we would get deadlock!
|
||||
*/
|
||||
error = nfs_nget(mp, &nmp->nm_fh, &np);
|
||||
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
|
||||
if (error)
|
||||
return(error);
|
||||
vp = NFSTOV(np);
|
||||
@ -622,9 +753,9 @@ nfs_unmount(mp, mntflags, p)
|
||||
nmp->nm_flag |= NFSMNT_DISMNT;
|
||||
|
||||
/*
|
||||
* There are two reference counts to get rid of here.
|
||||
* There are two reference counts and one lock to get rid of here.
|
||||
*/
|
||||
vrele(vp);
|
||||
vput(vp);
|
||||
vrele(vp);
|
||||
vgone(vp);
|
||||
nfs_disconnect(nmp);
|
||||
@ -649,10 +780,11 @@ nfs_root(mp, vpp)
|
||||
int error;
|
||||
|
||||
nmp = VFSTONFS(mp);
|
||||
error = nfs_nget(mp, &nmp->nm_fh, &np);
|
||||
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
|
||||
if (error)
|
||||
return (error);
|
||||
vp = NFSTOV(np);
|
||||
VOP_UNLOCK(vp);
|
||||
vp->v_type = VDIR;
|
||||
vp->v_flag = VROOT;
|
||||
*vpp = vp;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfs.h,v 1.8 1994/11/02 00:11:00 wollman Exp $
|
||||
* $Id: nfs.h,v 1.9 1995/02/14 06:22:18 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFS_H_
|
||||
@ -45,11 +45,12 @@
|
||||
*/
|
||||
|
||||
#define NFS_MAXIOVEC 34
|
||||
#define NFS_HZ 25 /* Ticks per second for NFS timeouts */
|
||||
#define NFS_TIMEO (1*NFS_HZ) /* Default timeout = 1 second */
|
||||
#define NFS_MINTIMEO (1*NFS_HZ) /* Min timeout to use */
|
||||
#define NFS_MAXTIMEO (60*NFS_HZ) /* Max timeout to backoff to */
|
||||
#define NFS_MINIDEMTIMEO (5*NFS_HZ) /* Min timeout for non-idempotent ops*/
|
||||
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
|
||||
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
|
||||
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
|
||||
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
|
||||
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
|
||||
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
|
||||
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
|
||||
#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
|
||||
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
|
||||
@ -62,13 +63,81 @@
|
||||
#endif
|
||||
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
|
||||
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
|
||||
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
|
||||
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
|
||||
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
|
||||
#define NFS_MAXREADDIR NFS_MAXDATA /* Max. size of directory read */
|
||||
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
|
||||
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
|
||||
#define NFS_DIRBLKSIZ 1024 /* Size of an NFS directory block */
|
||||
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
|
||||
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
|
||||
#ifndef NFS_GATHERDELAY
|
||||
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
|
||||
#endif
|
||||
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
|
||||
|
||||
/*
|
||||
* Oddballs
|
||||
*/
|
||||
#define NMOD(a) ((a) % nfs_asyncdaemons)
|
||||
#define NFS_CMPFH(n, f, s) \
|
||||
((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
|
||||
#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
|
||||
#define NFS_SRVMAXDATA(n) \
|
||||
(((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
|
||||
NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* sys/buf.h should be editted to change B_APPENDWRITE --> B_NEEDCOMMIT, but
|
||||
* until then...
|
||||
* Same goes for sys/malloc.h, which needs M_NFSDIROFF,
|
||||
* M_NFSRVDESC and M_NFSBIGFH added.
|
||||
* The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
|
||||
* exclusive create.
|
||||
* The B_INVAFTERWRITE flag should be set to whatever is required by the
|
||||
* buffer cache code to say "Invalidate the block after it is written back".
|
||||
*/
|
||||
#ifndef B_NEEDCOMMIT
|
||||
#define B_NEEDCOMMIT B_APPENDWRITE
|
||||
#endif
|
||||
#ifndef M_NFSRVDESC
|
||||
#define M_NFSRVDESC M_TEMP
|
||||
#endif
|
||||
#ifndef M_NFSDIROFF
|
||||
#define M_NFSDIROFF M_TEMP
|
||||
#endif
|
||||
#ifndef M_NFSBIGFH
|
||||
#define M_NFSBIGFH M_TEMP
|
||||
#endif
|
||||
#ifndef VA_EXCLUSIVE
|
||||
#define VA_EXCLUSIVE 0
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#define B_INVAFTERWRITE B_NOCACHE
|
||||
#else
|
||||
#define B_INVAFTERWRITE B_INVAL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These ifdefs try to handle the differences between the various 4.4BSD-Lite
|
||||
* based vfs interfaces.
|
||||
* btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
|
||||
* differentiate between NetBSD-1.0 and NetBSD-current, so..
|
||||
* I also don't know about BSDi's 2.0 release.
|
||||
*/
|
||||
#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||
#define HAS_VOPLEASE 1
|
||||
#endif
|
||||
#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||
#define HAS_VOPREVOKE 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The IO_METASYNC flag should be implemented for local file systems.
|
||||
* (Until then, it is nothin at all.)
|
||||
*/
|
||||
#ifndef IO_METASYNC
|
||||
#define IO_METASYNC 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the attribute timeout based on how recently the file has been modified.
|
||||
@ -79,6 +148,20 @@
|
||||
((time.tv_sec - (np)->n_mtime) / 10 > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
|
||||
(time.tv_sec - (np)->n_mtime) / 10))
|
||||
|
||||
/*
|
||||
* Expected allocation sizes for major data structures. If the actual size
|
||||
* of the structure exceeds these sizes, then malloc() will be allocating
|
||||
* almost twice the memory required. This is used in nfs_init() to warn
|
||||
* the sysadmin that the size of a structure should be reduced.
|
||||
* (These sizes are always a power of 2. If the kernel malloc() changes
|
||||
* to one that does not allocate space in powers of 2 size, then this all
|
||||
* becomes bunk!)
|
||||
*/
|
||||
#define NFS_NODEALLOC 256
|
||||
#define NFS_MNTALLOC 512
|
||||
#define NFS_SVCALLOC 256
|
||||
#define NFS_UIDALLOC 128
|
||||
|
||||
/*
|
||||
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
|
||||
* should ever try and use it.
|
||||
@ -95,7 +178,12 @@ struct nfsd_srvargs {
|
||||
u_long nsd_haddr; /* Ip address of client */
|
||||
struct ucred nsd_cr; /* Cred. uid maps to */
|
||||
int nsd_authlen; /* Length of auth string (ret) */
|
||||
char *nsd_authstr; /* Auth string (ret) */
|
||||
u_char *nsd_authstr; /* Auth string (ret) */
|
||||
int nsd_verflen; /* and the verfier */
|
||||
u_char *nsd_verfstr;
|
||||
struct timeval nsd_timestamp; /* timestamp from verifier */
|
||||
u_long nsd_ttl; /* credential ttl (sec) */
|
||||
NFSKERBKEY_T nsd_key; /* Session key */
|
||||
};
|
||||
|
||||
struct nfsd_cargs {
|
||||
@ -103,7 +191,10 @@ struct nfsd_cargs {
|
||||
uid_t ncd_authuid; /* Effective uid */
|
||||
int ncd_authtype; /* Type of authenticator */
|
||||
int ncd_authlen; /* Length of authenticator string */
|
||||
char *ncd_authstr; /* Authenticator string */
|
||||
u_char *ncd_authstr; /* Authenticator string */
|
||||
int ncd_verflen; /* and the verifier */
|
||||
u_char *ncd_verfstr;
|
||||
NFSKERBKEY_T ncd_key; /* Session key */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -142,6 +233,7 @@ struct nfsstats {
|
||||
int srvnqnfs_leases;
|
||||
int srvnqnfs_maxleases;
|
||||
int srvnqnfs_getleases;
|
||||
int srvvop_writes;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -173,7 +265,7 @@ struct nfsstats {
|
||||
* such as SIGALRM will not expect file I/O system calls to be interrupted
|
||||
* by them and break.
|
||||
*/
|
||||
#ifdef KERNEL
|
||||
#if defined(KERNEL) || defined(_KERNEL)
|
||||
|
||||
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
|
||||
|
||||
@ -224,17 +316,29 @@ TAILQ_HEAD(, nfsreq) nfs_reqq;
|
||||
#define R_MUSTRESEND 0x40 /* Must resend request */
|
||||
#define R_GETONEREP 0x80 /* Probe for one reply only */
|
||||
|
||||
extern struct nfsstats nfsstats;
|
||||
|
||||
/*
|
||||
* A list of nfssvc_sock structures is maintained with all the sockets
|
||||
* that require service by the nfsd.
|
||||
* The nfsuid structs hang off of the nfssvc_sock structs in both lru
|
||||
* and uid hash lists.
|
||||
*/
|
||||
#define NUIDHASHSIZ 32
|
||||
#ifndef NFS_UIDHASHSIZ
|
||||
#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
|
||||
#endif
|
||||
#define NUIDHASH(sock, uid) \
|
||||
(&(sock)->ns_uidhashtbl[(uid) & (sock)->ns_uidhash])
|
||||
(&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
|
||||
#ifndef NFS_WDELAYHASHSIZ
|
||||
#define NFS_WDELAYHASHSIZ 16 /* and with this */
|
||||
#endif
|
||||
#define NWDELAYHASH(sock, f) \
|
||||
(&(sock)->ns_wdelayhashtbl[(*((u_long *)(f))) % NFS_WDELAYHASHSIZ])
|
||||
#ifndef NFS_MUIDHASHSIZ
|
||||
#define NFS_MUIDHASHSIZ 67 /* Tune the size of nfsmount with this */
|
||||
#endif
|
||||
#define NMUIDHASH(nmp, uid) \
|
||||
(&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
|
||||
#define NFSNOHASH(fhsum) \
|
||||
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
|
||||
|
||||
/*
|
||||
* Network address hash list element
|
||||
@ -248,35 +352,41 @@ struct nfsuid {
|
||||
TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
|
||||
LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
|
||||
int nu_flag; /* Flags */
|
||||
uid_t nu_uid; /* Uid mapped by this entry */
|
||||
union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
|
||||
struct ucred nu_cr; /* Cred uid mapped to */
|
||||
int nu_expire; /* Expiry time (sec) */
|
||||
struct timeval nu_timestamp; /* Kerb. timestamp */
|
||||
u_long nu_nickname; /* Nickname on server */
|
||||
NFSKERBKEY_T nu_key; /* and session key */
|
||||
};
|
||||
|
||||
#define nu_inetaddr nu_haddr.had_inetaddr
|
||||
#define nu_nam nu_haddr.had_nam
|
||||
/* Bits for nu_flag */
|
||||
#define NU_INETADDR 0x1
|
||||
#define NU_NAM 0x2
|
||||
#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
|
||||
|
||||
struct nfssvc_sock {
|
||||
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
|
||||
TAILQ_HEAD(, nfsuid) ns_uidlruhead;
|
||||
LIST_HEAD(, nfsuid) *ns_uidhashtbl;
|
||||
u_long ns_uidhash;
|
||||
|
||||
int ns_flag;
|
||||
u_long ns_sref;
|
||||
struct file *ns_fp;
|
||||
struct socket *ns_so;
|
||||
int ns_solock;
|
||||
struct mbuf *ns_nam;
|
||||
int ns_cc;
|
||||
struct mbuf *ns_raw;
|
||||
struct mbuf *ns_rawend;
|
||||
int ns_reclen;
|
||||
struct mbuf *ns_rec;
|
||||
struct mbuf *ns_recend;
|
||||
struct mbuf *ns_frag;
|
||||
int ns_flag;
|
||||
int ns_solock;
|
||||
int ns_cc;
|
||||
int ns_reclen;
|
||||
int ns_numuids;
|
||||
u_long ns_sref;
|
||||
LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
|
||||
LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
|
||||
LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
|
||||
};
|
||||
|
||||
/* Bits for "ns_flag" */
|
||||
@ -285,6 +395,7 @@ struct nfssvc_sock {
|
||||
#define SLP_NEEDQ 0x04
|
||||
#define SLP_DISCONN 0x08
|
||||
#define SLP_GETSTREAM 0x10
|
||||
#define SLP_LASTFRAG 0x20
|
||||
#define SLP_ALLFLAGS 0xff
|
||||
|
||||
TAILQ_HEAD(, nfssvc_sock) nfssvc_sockhead;
|
||||
@ -296,73 +407,124 @@ int nfssvc_sockhead_flag;
|
||||
* One of these structures is allocated for each nfsd.
|
||||
*/
|
||||
struct nfsd {
|
||||
TAILQ_ENTRY(nfsd) nd_chain; /* List of all nfsd's */
|
||||
int nd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nd_slp; /* Current socket */
|
||||
struct mbuf *nd_nam; /* Client addr for datagram req. */
|
||||
struct mbuf *nd_mrep; /* Req. mbuf list */
|
||||
struct mbuf *nd_md;
|
||||
caddr_t nd_dpos; /* Position in list */
|
||||
int nd_procnum; /* RPC procedure number */
|
||||
u_long nd_retxid; /* RPC xid */
|
||||
int nd_repstat; /* Reply status value */
|
||||
struct ucred nd_cr; /* Credentials for req. */
|
||||
int nd_nqlflag; /* Leasing flag */
|
||||
u_long nd_duration; /* Lease duration */
|
||||
int nd_authlen; /* Authenticator len */
|
||||
u_char nd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
|
||||
struct proc *nd_procp; /* Proc ptr */
|
||||
TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
|
||||
int nfsd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nfsd_slp; /* Current socket */
|
||||
int nfsd_authlen; /* Authenticator len */
|
||||
u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
|
||||
int nfsd_verflen; /* and the Verifier */
|
||||
u_char nfsd_verfstr[RPCVERF_MAXSIZ];
|
||||
struct proc *nfsd_procp; /* Proc ptr */
|
||||
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
|
||||
};
|
||||
|
||||
/* Bits for "nd_flag" */
|
||||
/* Bits for "nfsd_flag" */
|
||||
#define NFSD_WAITING 0x01
|
||||
#define NFSD_REQINPROG 0x02
|
||||
#define NFSD_NEEDAUTH 0x04
|
||||
#define NFSD_AUTHFAIL 0x08
|
||||
|
||||
/*
|
||||
* This structure is used by the server for describing each request.
|
||||
* Some fields are used only when write request gathering is performed.
|
||||
*/
|
||||
struct nfsrv_descript {
|
||||
u_quad_t nd_time; /* Write deadline (usec) */
|
||||
off_t nd_off; /* Start byte offset */
|
||||
off_t nd_eoff; /* and end byte offset */
|
||||
LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
|
||||
LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
|
||||
LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
|
||||
struct mbuf *nd_mrep; /* Request mbuf list */
|
||||
struct mbuf *nd_md; /* Current dissect mbuf */
|
||||
struct mbuf *nd_mreq; /* Reply mbuf list */
|
||||
struct mbuf *nd_nam; /* and socket addr */
|
||||
struct mbuf *nd_nam2; /* return socket addr */
|
||||
caddr_t nd_dpos; /* Current dissect pos */
|
||||
int nd_procnum; /* RPC # */
|
||||
int nd_stable; /* storage type */
|
||||
int nd_flag; /* nd_flag */
|
||||
int nd_len; /* Length of this write */
|
||||
int nd_repstat; /* Reply status */
|
||||
u_long nd_retxid; /* Reply xid */
|
||||
u_long nd_duration; /* Lease duration */
|
||||
struct timeval nd_starttime; /* Time RPC initiated */
|
||||
fhandle_t nd_fh; /* File handle */
|
||||
struct ucred nd_cr; /* Credentials */
|
||||
};
|
||||
|
||||
/* Bits for "nd_flag" */
|
||||
#define ND_READ LEASE_READ
|
||||
#define ND_WRITE LEASE_WRITE
|
||||
#define ND_CHECK 0x04
|
||||
#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
|
||||
#define ND_NFSV3 0x08
|
||||
#define ND_NQNFS 0x10
|
||||
#define ND_KERBNICK 0x20
|
||||
#define ND_KERBFULL 0x40
|
||||
#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
|
||||
|
||||
TAILQ_HEAD(, nfsd) nfsd_head;
|
||||
int nfsd_head_flag;
|
||||
#define NFSD_CHECKSLP 0x01
|
||||
|
||||
/*
|
||||
* These macros compare nfsrv_descript structures.
|
||||
*/
|
||||
#define NFSW_CONTIG(o, n) \
|
||||
((o)->nd_eoff >= (n)->nd_off && \
|
||||
!bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
|
||||
|
||||
#define NFSW_SAMECRED(o, n) \
|
||||
(((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
|
||||
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
|
||||
sizeof (struct ucred)))
|
||||
|
||||
int nfs_reply __P((struct nfsreq *));
|
||||
int nfs_getreq __P((struct nfsd *,int));
|
||||
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
|
||||
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
|
||||
int nfs_rephead __P((int,struct nfsd *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_rephead __P((int,struct nfsrv_descript *,struct nfssvc_sock *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_sndlock __P((int *,struct nfsreq *));
|
||||
int nfs_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
|
||||
int nfs_vinvalbuf __P((struct vnode *,int,struct ucred *,struct proc *,int));
|
||||
int nfs_readrpc __P((struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int));
|
||||
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int *,int *));
|
||||
int nfs_readdirrpc __P((register struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
|
||||
int nfs_asyncio __P((struct buf *,struct ucred *));
|
||||
int nfs_doio __P((struct buf *,struct ucred *,struct proc *));
|
||||
int nfs_readlinkrpc __P((struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_sigintr __P((struct nfsmount *,struct nfsreq *r,struct proc *));
|
||||
int nfs_readdirlookrpc __P((struct vnode *,register struct uio *,struct ucred *));
|
||||
int nfs_readdirplusrpc __P((struct vnode *,register struct uio *,struct ucred *));
|
||||
int nfsm_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
|
||||
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *));
|
||||
void nfsm_srvfattr __P((struct nfsrv_descript *,struct vattr *,struct nfs_fattr *));
|
||||
void nfsm_srvwcc __P((struct nfsrv_descript *,int,struct vattr *,int,struct vattr *,struct mbuf **,char **));
|
||||
void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct mbuf **,char **));
|
||||
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *,int));
|
||||
int nfsrv_access __P((struct vnode *,int,struct ucred *,int,struct proc *));
|
||||
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
|
||||
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
|
||||
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct proc *));
|
||||
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
|
||||
void nfsm_adj __P((struct mbuf *,int,int));
|
||||
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
|
||||
void nfsrv_initcache __P((void));
|
||||
int nfs_rcvlock __P((struct nfsreq *));
|
||||
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,int *,char **,int *));
|
||||
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,char **,int *,char *,int *,NFSKERBKEY_T));
|
||||
int nfs_getnickauth __P((struct nfsmount *,struct ucred *,char **,int *,char *,int));
|
||||
int nfs_savenickauth __P((struct nfsmount *,struct ucred *,int,NFSKERBKEY_T,struct mbuf **,char **,struct mbuf *));
|
||||
int nfs_msg __P((struct proc *,char *,char *));
|
||||
int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
|
||||
int nfsrv_getstream __P((struct nfssvc_sock *,int));
|
||||
void nfs_nhinit __P((void));
|
||||
void nfs_timer __P((void*));
|
||||
struct nfsnodehashhead * nfs_hash __P((nfsv2fh_t *));
|
||||
u_long nfs_hash __P((nfsfh_t *,int));
|
||||
int nfssvc_iod __P((struct proc *));
|
||||
int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,struct proc *));
|
||||
int nfssvc_addsock __P((struct file *,struct mbuf *));
|
||||
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *));
|
||||
int nfsrv_getcache __P((struct mbuf *,struct nfsd *,struct mbuf **));
|
||||
void nfsrv_updatecache __P((struct mbuf *,struct nfsd *,int,struct mbuf *));
|
||||
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
|
||||
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
|
||||
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
|
||||
int mountnfs __P((struct nfs_args *,struct mount *,struct mbuf *,char *,char *,struct vnode **));
|
||||
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
|
||||
int nfs_getattrcache __P((struct vnode *,struct vattr *));
|
||||
@ -370,9 +532,20 @@ int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
|
||||
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
|
||||
int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
|
||||
void nfsrv_init __P((int));
|
||||
void nfs_clearcommit __P((struct mount *));
|
||||
int nfsrv_errmap __P((struct nfsrv_descript *, int));
|
||||
void nfsrvw_coalesce __P((struct nfsrv_descript *,struct nfsrv_descript *));
|
||||
void nfsrvw_sort __P((gid_t [],int));
|
||||
void nfsrv_setcred __P((struct ucred *,struct ucred *));
|
||||
int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
|
||||
int nfs_writebp __P((struct buf *,int));
|
||||
int nfsrv_vput __P(( struct vnode * ));
|
||||
int nfsrv_vrele __P(( struct vnode * ));
|
||||
int nfsrv_vmio __P(( struct vnode * ));
|
||||
int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
|
||||
struct proc *, struct mbuf **));
|
||||
int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
|
||||
struct proc *p));
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsdiskless.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfsdiskless.h,v 1.3 1994/08/05 09:28:49 davidg Exp $
|
||||
* $Id: nfsdiskless.h,v 1.4 1994/08/21 06:50:09 paul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSDISKLESS_H_
|
||||
@ -52,17 +52,45 @@
|
||||
* NB: All fields are stored in net byte order to avoid hassles with
|
||||
* client/server byte ordering differences.
|
||||
*/
|
||||
struct nfs_diskless {
|
||||
|
||||
/*
|
||||
* I have defined a new structure that can handle an NFS Version 3 file handle
|
||||
* but the kernel still expects the old Version 2 one to be provided. The
|
||||
* changes required in nfs_vfsops.c for using the new are documented there in
|
||||
* comments. (I felt that breaking network booting code by changing this
|
||||
* structure would not be prudent at this time, since almost all servers are
|
||||
* still Version 2 anyhow.)
|
||||
*/
|
||||
struct nfsv3_diskless {
|
||||
struct ifaliasreq myif; /* Default interface */
|
||||
struct sockaddr_in mygateway; /* Default gateway */
|
||||
struct nfs_args swap_args; /* Mount args for swap file */
|
||||
u_char swap_fh[NFS_FHSIZE]; /* Swap file's file handle */
|
||||
int swap_fhsize; /* Size of file handle */
|
||||
u_char swap_fh[NFSX_V3FHMAX]; /* Swap file's file handle */
|
||||
struct sockaddr_in swap_saddr; /* Address of swap server */
|
||||
char swap_hostnam[MNAMELEN]; /* Host name for mount pt */
|
||||
int swap_nblks; /* Size of server swap file */
|
||||
struct ucred swap_ucred; /* Swap credentials */
|
||||
struct nfs_args root_args; /* Mount args for root fs */
|
||||
u_char root_fh[NFS_FHSIZE]; /* File handle of root dir */
|
||||
int root_fhsize; /* Size of root file handle */
|
||||
u_char root_fh[NFSX_V3FHMAX]; /* File handle of root dir */
|
||||
struct sockaddr_in root_saddr; /* Address of root server */
|
||||
char root_hostnam[MNAMELEN]; /* Host name for mount pt */
|
||||
long root_time; /* Timestamp of root fs */
|
||||
char my_hostnam[MAXHOSTNAMELEN]; /* Client host name */
|
||||
};
|
||||
|
||||
struct nfs_diskless {
|
||||
struct ifaliasreq myif; /* Default interface */
|
||||
struct sockaddr_in mygateway; /* Default gateway */
|
||||
struct nfs_args swap_args; /* Mount args for swap file */
|
||||
u_char swap_fh[NFSX_V2FH]; /* Swap file's file handle */
|
||||
struct sockaddr_in swap_saddr; /* Address of swap server */
|
||||
char swap_hostnam[MNAMELEN]; /* Host name for mount pt */
|
||||
int swap_nblks; /* Size of server swap file */
|
||||
struct ucred swap_ucred; /* Swap credentials */
|
||||
struct nfs_args root_args; /* Mount args for root fs */
|
||||
u_char root_fh[NFSX_V2FH]; /* File handle of root dir */
|
||||
struct sockaddr_in root_saddr; /* Address of root server */
|
||||
char root_hostnam[MNAMELEN]; /* Host name for mount pt */
|
||||
long root_time; /* Timestamp of root fs */
|
||||
|
@ -34,12 +34,13 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsm_subs.h 8.1 (Berkeley) 6/16/93
|
||||
* $Id: nfsm_subs.h,v 1.5 1994/10/17 17:47:42 phk Exp $
|
||||
* $Id: nfsm_subs.h,v 1.6 1995/05/30 08:12:51 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSM_SUBS_H_
|
||||
#define _NFS_NFSM_SUBS_H_
|
||||
|
||||
|
||||
/*
|
||||
* These macros do strange and peculiar things to mbuf chains for
|
||||
* the assistance of the nfs code. To attempt to use them for any
|
||||
@ -90,49 +91,153 @@ extern struct mbuf *nfsm_reqh();
|
||||
mb->m_len += (s); \
|
||||
bpos += (s); }
|
||||
|
||||
#define nfsm_dissect(a,c,s) \
|
||||
#define nfsm_dissect(a, c, s) \
|
||||
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
|
||||
if (t1 >= (s)) { \
|
||||
(a) = (c)(dpos); \
|
||||
dpos += (s); \
|
||||
} else if (t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} else { \
|
||||
error = nfsm_disct(&md, &dpos, (s), t1, &cp2); \
|
||||
if (error) { \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} else { \
|
||||
(a) = (c)cp2; \
|
||||
} \
|
||||
(a) = (c)cp2; \
|
||||
} }
|
||||
|
||||
#define nfsm_fhtom(v) \
|
||||
nfsm_build(cp,caddr_t,NFSX_FH); \
|
||||
bcopy((caddr_t)&(VTONFS(v)->n_fh), cp, NFSX_FH)
|
||||
#define nfsm_fhtom(v, v3) \
|
||||
{ if (v3) { \
|
||||
t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \
|
||||
if (t2 <= M_TRAILINGSPACE(mb)) { \
|
||||
nfsm_build(tl, u_long *, t2); \
|
||||
*tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \
|
||||
*(tl + ((t2>>2) - 2)) = 0; \
|
||||
bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \
|
||||
VTONFS(v)->n_fhsize); \
|
||||
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, \
|
||||
(caddr_t)VTONFS(v)->n_fhp, VTONFS(v)->n_fhsize)) { \
|
||||
error = t2; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
} else { \
|
||||
nfsm_build(cp, caddr_t, NFSX_V2FH); \
|
||||
bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \
|
||||
} }
|
||||
|
||||
#define nfsm_srvfhtom(f) \
|
||||
nfsm_build(cp,caddr_t,NFSX_FH); \
|
||||
bcopy((caddr_t)(f), cp, NFSX_FH)
|
||||
#define nfsm_srvfhtom(f, v3) \
|
||||
{ if (v3) { \
|
||||
nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FH); \
|
||||
*tl++ = txdr_unsigned(NFSX_V3FH); \
|
||||
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
|
||||
} else { \
|
||||
nfsm_build(cp, caddr_t, NFSX_V2FH); \
|
||||
bcopy((caddr_t)(f), cp, NFSX_V2FH); \
|
||||
} }
|
||||
|
||||
#define nfsm_mtofh(d,v) \
|
||||
{ struct nfsnode *np; nfsv2fh_t *fhp; \
|
||||
nfsm_dissect(fhp,nfsv2fh_t *,NFSX_FH); \
|
||||
error = nfs_nget((d)->v_mount, fhp, &np); \
|
||||
if (error) { \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = NFSTOV(np); \
|
||||
nfsm_loadattr(v, (struct vattr *)0); \
|
||||
#define nfsm_srvpostop_fh(f) \
|
||||
{ nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \
|
||||
*tl++ = nfs_true; \
|
||||
*tl++ = txdr_unsigned(NFSX_V3FH); \
|
||||
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
|
||||
}
|
||||
|
||||
#define nfsm_loadattr(v,a) \
|
||||
{ struct vnode *tvp = (v); \
|
||||
error = nfs_loadattrcache(&tvp, &md, &dpos, (a)); \
|
||||
if (error) { \
|
||||
#define nfsm_mtofh(d, v, v3, f) \
|
||||
{ struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \
|
||||
if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(f) = fxdr_unsigned(int, *tl); \
|
||||
} else \
|
||||
(f) = 1; \
|
||||
if (f) { \
|
||||
nfsm_getfh(ttfhp, ttfhsize, (v3)); \
|
||||
if (t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \
|
||||
&ttnp)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = NFSTOV(ttnp); \
|
||||
} \
|
||||
if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (f) \
|
||||
(f) = fxdr_unsigned(int, *tl); \
|
||||
else if (fxdr_unsigned(int, *tl)) \
|
||||
nfsm_adv(NFSX_V3FATTR); \
|
||||
} \
|
||||
if (f) \
|
||||
nfsm_loadattr((v), (struct vattr *)0); \
|
||||
}
|
||||
|
||||
#define nfsm_getfh(f, s, v3) \
|
||||
{ if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \
|
||||
(s) > NFSX_V3FHMAX) { \
|
||||
m_freem(mrep); \
|
||||
error = EBADRPC; \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
} else \
|
||||
(s) = NFSX_V2FH; \
|
||||
nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); }
|
||||
|
||||
#define nfsm_loadattr(v, a) \
|
||||
{ struct vnode *ttvp = (v); \
|
||||
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a))) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = tvp; }
|
||||
(v) = ttvp; }
|
||||
|
||||
#define nfsm_postop_attr(v, f) \
|
||||
{ struct vnode *ttvp = (v); \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if ((f) = fxdr_unsigned(int, *tl)) { \
|
||||
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
|
||||
(struct vattr *)0)) { \
|
||||
error = t1; \
|
||||
(f) = 0; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = ttvp; \
|
||||
} }
|
||||
|
||||
/* Used as (f) for nfsm_wcc_data() */
|
||||
#define NFSV3_WCCRATTR 0
|
||||
#define NFSV3_WCCCHK 1
|
||||
|
||||
#define nfsm_wcc_data(v, f) \
|
||||
{ int ttattrf, ttretf = 0; \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, 6 * NFSX_UNSIGNED); \
|
||||
if (f) \
|
||||
ttretf = (VTONFS(v)->n_mtime == \
|
||||
fxdr_unsigned(u_long, *(tl + 2))); \
|
||||
} \
|
||||
nfsm_postop_attr((v), ttattrf); \
|
||||
if (f) { \
|
||||
(f) = ttretf; \
|
||||
} else { \
|
||||
(f) = ttattrf; \
|
||||
} }
|
||||
|
||||
#define nfsm_v3sattr(s, a, u, g) \
|
||||
{ (s)->sa_modetrue = nfs_true; \
|
||||
(s)->sa_mode = vtonfsv3_mode((a)->va_mode); \
|
||||
(s)->sa_uidtrue = nfs_true; \
|
||||
(s)->sa_uid = txdr_unsigned(u); \
|
||||
(s)->sa_gidtrue = nfs_true; \
|
||||
(s)->sa_gid = txdr_unsigned(g); \
|
||||
(s)->sa_sizefalse = nfs_false; \
|
||||
(s)->sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
|
||||
txdr_nfsv3time(&(a)->va_atime, &(s)->sa_atime); \
|
||||
(s)->sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
|
||||
txdr_nfsv3time(&(a)->va_mtime, &(s)->sa_mtime); \
|
||||
}
|
||||
|
||||
#define nfsm_strsiz(s,m) \
|
||||
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
|
||||
@ -149,16 +254,27 @@ extern struct mbuf *nfsm_reqh();
|
||||
nfsm_reply(0); \
|
||||
} }
|
||||
|
||||
#define nfsm_srvnamesiz(s) \
|
||||
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
|
||||
if (((s) = fxdr_unsigned(long,*tl)) > NFS_MAXNAMLEN) \
|
||||
error = NFSERR_NAMETOL; \
|
||||
if ((s) <= 0) \
|
||||
error = EBADRPC; \
|
||||
if (error) \
|
||||
nfsm_reply(0); \
|
||||
}
|
||||
|
||||
#define nfsm_mtouio(p,s) \
|
||||
if ((s) > 0 && \
|
||||
(error = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
|
||||
(t1 = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_uiotom(p,s) \
|
||||
error = nfsm_uiotombuf((p),&mb,(s),&bpos); \
|
||||
if (error) { \
|
||||
if (t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) { \
|
||||
error = t1; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
@ -172,10 +288,13 @@ extern struct mbuf *nfsm_reqh();
|
||||
#define nfsm_rndup(a) (((a)+3)&(~0x3))
|
||||
|
||||
#define nfsm_request(v, t, p, c) \
|
||||
error = nfs_request((v), mreq, (t), (p), \
|
||||
(c), &mrep, &md, &dpos); \
|
||||
if (error) \
|
||||
goto nfsmout
|
||||
if (error = nfs_request((v), mreq, (t), (p), \
|
||||
(c), &mrep, &md, &dpos)) { \
|
||||
if (error & NFSERR_RETERR) \
|
||||
error &= ~NFSERR_RETERR; \
|
||||
else \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_strtom(a,s,m) \
|
||||
if ((s) > (m)) { \
|
||||
@ -189,12 +308,10 @@ extern struct mbuf *nfsm_reqh();
|
||||
*tl++ = txdr_unsigned(s); \
|
||||
*(tl+((t2>>2)-2)) = 0; \
|
||||
bcopy((caddr_t)(a), (caddr_t)tl, (s)); \
|
||||
} else { \
|
||||
error = nfsm_strtmbuf(&mb, &bpos, (a), (s)); \
|
||||
if (error) { \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) { \
|
||||
error = t2; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_srvdone \
|
||||
@ -204,33 +321,53 @@ extern struct mbuf *nfsm_reqh();
|
||||
#define nfsm_reply(s) \
|
||||
{ \
|
||||
nfsd->nd_repstat = error; \
|
||||
if (error) \
|
||||
(void) nfs_rephead(0, nfsd, error, cache, &frev, \
|
||||
if (error && !(nfsd->nd_flag & ND_NFSV3)) \
|
||||
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
|
||||
mrq, &mb, &bpos); \
|
||||
else \
|
||||
(void) nfs_rephead((s), nfsd, error, cache, &frev, \
|
||||
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
|
||||
mrq, &mb, &bpos); \
|
||||
m_freem(mrep); \
|
||||
mreq = *mrq; \
|
||||
if (error) \
|
||||
if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
|
||||
error == EBADRPC)) \
|
||||
return(0); \
|
||||
}
|
||||
|
||||
#define nfsm_adv(s) \
|
||||
t1 = mtod(md, caddr_t)+md->m_len-dpos; \
|
||||
if (t1 >= (s)) { \
|
||||
dpos += (s); \
|
||||
} else { \
|
||||
error = nfs_adv(&md, &dpos, (s), t1); \
|
||||
if (error) { \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
#define nfsm_writereply(s, v3) \
|
||||
{ \
|
||||
nfsd->nd_repstat = error; \
|
||||
if (error && !(v3)) \
|
||||
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
|
||||
&mreq, &mb, &bpos); \
|
||||
else \
|
||||
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
|
||||
&mreq, &mb, &bpos); \
|
||||
}
|
||||
|
||||
#define nfsm_adv(s) \
|
||||
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
|
||||
if (t1 >= (s)) { \
|
||||
dpos += (s); \
|
||||
} else if (t1 = nfs_adv(&md, &dpos, (s), t1)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} }
|
||||
|
||||
#define nfsm_srvmtofh(f) \
|
||||
nfsm_dissect(tl, u_long *, NFSX_FH); \
|
||||
bcopy((caddr_t)tl, (caddr_t)f, NFSX_FH)
|
||||
{ if (nfsd->nd_flag & ND_NFSV3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \
|
||||
error = EBADRPC; \
|
||||
nfsm_reply(0); \
|
||||
} \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
|
||||
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
|
||||
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
|
||||
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
|
||||
}
|
||||
|
||||
#define nfsm_clget \
|
||||
if (bp >= be) { \
|
||||
@ -246,41 +383,57 @@ extern struct mbuf *nfsm_reqh();
|
||||
} \
|
||||
tl = (u_long *)bp
|
||||
|
||||
#define nfsm_srvfillattr \
|
||||
fp->fa_type = vtonfs_type(vap->va_type); \
|
||||
fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); \
|
||||
fp->fa_nlink = txdr_unsigned(vap->va_nlink); \
|
||||
fp->fa_uid = txdr_unsigned(vap->va_uid); \
|
||||
fp->fa_gid = txdr_unsigned(vap->va_gid); \
|
||||
if (nfsd->nd_nqlflag == NQL_NOVAL) { \
|
||||
fp->fa_nfsblocksize = txdr_unsigned(vap->va_blocksize); \
|
||||
if (vap->va_type == VFIFO) \
|
||||
fp->fa_nfsrdev = 0xffffffff; \
|
||||
else \
|
||||
fp->fa_nfsrdev = txdr_unsigned(vap->va_rdev); \
|
||||
fp->fa_nfsfsid = txdr_unsigned(vap->va_fsid); \
|
||||
fp->fa_nfsfileid = txdr_unsigned(vap->va_fileid); \
|
||||
fp->fa_nfssize = txdr_unsigned(vap->va_size); \
|
||||
fp->fa_nfsblocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); \
|
||||
txdr_nfstime(&vap->va_atime, &fp->fa_nfsatime); \
|
||||
txdr_nfstime(&vap->va_mtime, &fp->fa_nfsmtime); \
|
||||
txdr_nfstime(&vap->va_ctime, &fp->fa_nfsctime); \
|
||||
} else { \
|
||||
fp->fa_nqblocksize = txdr_unsigned(vap->va_blocksize); \
|
||||
if (vap->va_type == VFIFO) \
|
||||
fp->fa_nqrdev = 0xffffffff; \
|
||||
else \
|
||||
fp->fa_nqrdev = txdr_unsigned(vap->va_rdev); \
|
||||
fp->fa_nqfsid = txdr_unsigned(vap->va_fsid); \
|
||||
fp->fa_nqfileid = txdr_unsigned(vap->va_fileid); \
|
||||
txdr_hyper(&vap->va_size, &fp->fa_nqsize); \
|
||||
txdr_hyper(&vap->va_bytes, &fp->fa_nqbytes); \
|
||||
txdr_nqtime(&vap->va_atime, &fp->fa_nqatime); \
|
||||
txdr_nqtime(&vap->va_mtime, &fp->fa_nqmtime); \
|
||||
txdr_nqtime(&vap->va_ctime, &fp->fa_nqctime); \
|
||||
fp->fa_nqflags = txdr_unsigned(vap->va_flags); \
|
||||
fp->fa_nqgen = txdr_unsigned(vap->va_gen); \
|
||||
txdr_hyper(&vap->va_filerev, &fp->fa_nqfilerev); \
|
||||
}
|
||||
#define nfsm_srvfillattr(a, f) \
|
||||
nfsm_srvfattr(nfsd, (a), (f))
|
||||
|
||||
#define nfsm_srvwcc_data(br, b, ar, a) \
|
||||
nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos)
|
||||
|
||||
#define nfsm_srvpostop_attr(r, a) \
|
||||
nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos)
|
||||
|
||||
#define nfsm_srvsattr(a) \
|
||||
{ nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_mode = nfstov_mode(*tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_uid = fxdr_unsigned(uid_t, *tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_gid = fxdr_unsigned(gid_t, *tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_hyper(tl, &(a)->va_size); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
switch (fxdr_unsigned(int, *tl)) { \
|
||||
case NFSV3SATTRTIME_TOCLIENT: \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_nfsv3time(tl, &(a)->va_atime); \
|
||||
break; \
|
||||
case NFSV3SATTRTIME_TOSERVER: \
|
||||
(a)->va_atime.ts_sec = time.tv_sec; \
|
||||
(a)->va_atime.ts_nsec = time.tv_usec * 1000; \
|
||||
break; \
|
||||
}; \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
switch (fxdr_unsigned(int, *tl)) { \
|
||||
case NFSV3SATTRTIME_TOCLIENT: \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_nfsv3time(tl, &(a)->va_mtime); \
|
||||
break; \
|
||||
case NFSV3SATTRTIME_TOSERVER: \
|
||||
(a)->va_mtime.ts_sec = time.tv_sec; \
|
||||
(a)->va_mtime.ts_nsec = time.tv_usec * 1000; \
|
||||
break; \
|
||||
}; }
|
||||
|
||||
#endif
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsmount.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfsmount.h,v 1.3 1994/08/21 06:50:10 paul Exp $
|
||||
* $Id: nfsmount.h,v 1.4 1994/10/17 17:47:43 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSMOUNT_H_
|
||||
@ -49,7 +49,8 @@ struct nfsmount {
|
||||
int nm_flag; /* Flags for soft/hard... */
|
||||
struct mount *nm_mountp; /* Vfs structure for this filesystem */
|
||||
int nm_numgrps; /* Max. size of groupslist */
|
||||
nfsv2fh_t nm_fh; /* File handle of root dir */
|
||||
u_char nm_fh[NFSX_V3FHMAX]; /* File handle of root dir */
|
||||
int nm_fhsize; /* Size of root file handle */
|
||||
struct socket *nm_so; /* Rpc socket */
|
||||
int nm_sotype; /* Type of socket */
|
||||
int nm_soproto; /* and protocol */
|
||||
@ -65,6 +66,7 @@ struct nfsmount {
|
||||
int nm_deadthresh; /* Threshold of timeouts-->dead server*/
|
||||
int nm_rsize; /* Max size of read rpc */
|
||||
int nm_wsize; /* Max size of write rpc */
|
||||
int nm_readdirsize; /* Size of a readdir rpc */
|
||||
int nm_readahead; /* Num. of blocks to readahead */
|
||||
int nm_leaseterm; /* Term (sec) for NQNFS lease */
|
||||
CIRCLEQ_HEAD(, nfsnode) nm_timerhead; /* Head of lease timer queue */
|
||||
@ -73,9 +75,16 @@ struct nfsmount {
|
||||
int nm_authtype; /* Authenticator type */
|
||||
int nm_authlen; /* and length */
|
||||
char *nm_authstr; /* Authenticator string */
|
||||
char *nm_verfstr; /* and the verifier */
|
||||
int nm_verflen;
|
||||
u_char nm_verf[NFSX_V3WRITEVERF]; /* V3 write verifier */
|
||||
NFSKERBKEY_T nm_key; /* and the session key */
|
||||
int nm_numuids; /* Number of nfsuid mappings */
|
||||
TAILQ_HEAD(, nfsuid) nm_uidlruhead; /* Lists of nfsuid mappings */
|
||||
LIST_HEAD(, nfsuid) nm_uidhashtbl[NFS_MUIDHASHSIZ];
|
||||
};
|
||||
|
||||
#ifdef KERNEL
|
||||
#if defined(KERNEL) || defined(_KERNEL)
|
||||
/*
|
||||
* Convert mount ptr to nfsmount ptr.
|
||||
*/
|
||||
|
@ -34,12 +34,16 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsnode.h 8.4 (Berkeley) 2/13/94
|
||||
* $Id: nfsnode.h,v 1.8 1994/10/17 17:47:44 phk Exp $
|
||||
* $Id: nfsnode.h,v 1.9 1995/03/16 18:15:42 bde Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSNODE_H_
|
||||
#define _NFS_NFSNODE_H_
|
||||
|
||||
#ifndef _NFS_NFS_H_
|
||||
#include <nfs/nfs.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Silly rename structure that hangs off the nfsnode until the name
|
||||
* can be removed by nfs_inactive()
|
||||
@ -51,37 +55,74 @@ struct sillyrename {
|
||||
char s_name[20];
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure is used to save the logical directory offset to
|
||||
* NFS cookie mappings.
|
||||
* The mappings are stored in a list headed
|
||||
* by n_cookies, as required.
|
||||
* There is one mapping for each NFS_DIRBLKSIZ bytes of directory information
|
||||
* stored in increasing logical offset byte order.
|
||||
*/
|
||||
#define NFSNUMCOOKIES 31
|
||||
|
||||
struct nfsdmap {
|
||||
LIST_ENTRY(nfsdmap) ndm_list;
|
||||
int ndm_eocookie;
|
||||
nfsuint64 ndm_cookies[NFSNUMCOOKIES];
|
||||
};
|
||||
|
||||
/*
|
||||
* The nfsnode is the nfs equivalent to ufs's inode. Any similarity
|
||||
* is purely coincidental.
|
||||
* There is a unique nfsnode allocated for each active file,
|
||||
* each current directory, each mounted-on file, text file, and the root.
|
||||
* An nfsnode is 'named' by its file handle. (nget/nfs_node.c)
|
||||
* If this structure exceeds 256 bytes (it is currently 256 using 4.4BSD-Lite
|
||||
* type definitions), file handles of > 32 bytes should probably be split out
|
||||
* into a separate MALLOC()'d data structure. (Reduce the size of nfsfh_t by
|
||||
* changing the definition in sys/mount.h of NFS_SMALLFH.)
|
||||
* NB: Hopefully the current order of the fields is such that everything will
|
||||
* be well aligned and, therefore, tightly packed.
|
||||
*/
|
||||
|
||||
struct nfsnode {
|
||||
LIST_ENTRY(nfsnode) n_hash; /* Hash chain */
|
||||
CIRCLEQ_ENTRY(nfsnode) n_timer; /* Nqnfs timer chain */
|
||||
nfsv2fh_t n_fh; /* NFS File Handle */
|
||||
long n_flag; /* Flag for locking.. */
|
||||
struct vnode *n_vnode; /* vnode associated with this node */
|
||||
struct vattr n_vattr; /* Vnode attribute cache */
|
||||
time_t n_attrstamp; /* Time stamp for cached attributes */
|
||||
struct sillyrename *n_sillyrename; /* Ptr to silly rename struct */
|
||||
u_quad_t n_size; /* Current size of file */
|
||||
struct lockf *n_lockf; /* Locking record of file */
|
||||
int n_error; /* Save write error value */
|
||||
u_long n_direofoffset; /* Dir. EOF offset cache */
|
||||
time_t n_mtime; /* Prev modify time. */
|
||||
time_t n_ctime; /* Prev create time. */
|
||||
u_quad_t n_brev; /* Modify rev when cached */
|
||||
u_quad_t n_lrev; /* Modify rev for lease */
|
||||
time_t n_expiry; /* Lease expiry time */
|
||||
struct sillyrename n_silly; /* Silly rename struct */
|
||||
struct timeval n_atim; /* Special file times */
|
||||
struct timeval n_mtim;
|
||||
LIST_ENTRY(nfsnode) n_hash; /* Hash chain */
|
||||
CIRCLEQ_ENTRY(nfsnode) n_timer; /* Nqnfs timer chain */
|
||||
u_quad_t n_size; /* Current size of file */
|
||||
u_quad_t n_brev; /* Modify rev when cached */
|
||||
u_quad_t n_lrev; /* Modify rev for lease */
|
||||
struct vattr n_vattr; /* Vnode attribute cache */
|
||||
time_t n_attrstamp; /* Attr. cache timestamp */
|
||||
time_t n_mtime; /* Prev modify time. */
|
||||
time_t n_ctime; /* Prev create time. */
|
||||
time_t n_expiry; /* Lease expiry time */
|
||||
nfsfh_t *n_fhp; /* NFS File Handle */
|
||||
struct vnode *n_vnode; /* associated vnode */
|
||||
struct lockf *n_lockf; /* Locking record of file */
|
||||
int n_error; /* Save write error value */
|
||||
union {
|
||||
struct timespec nf_atim; /* Special file times */
|
||||
nfsuint64 nd_cookieverf; /* Cookie verifier (dir only) */
|
||||
} n_un1;
|
||||
union {
|
||||
struct timespec nf_mtim;
|
||||
off_t nd_direof; /* Dir. EOF offset cache */
|
||||
} n_un2;
|
||||
union {
|
||||
struct sillyrename *nf_silly; /* Ptr to silly rename struct */
|
||||
LIST_HEAD(, nfsdmap) nd_cook; /* cookies */
|
||||
} n_un3;
|
||||
short n_fhsize; /* size in bytes, of fh */
|
||||
short n_flag; /* Flag for locking.. */
|
||||
nfsfh_t n_fh; /* Small File Handle */
|
||||
};
|
||||
|
||||
#define n_atim n_un1.nf_atim
|
||||
#define n_mtim n_un2.nf_mtim
|
||||
#define n_sillyrename n_un3.nf_silly
|
||||
#define n_cookieverf n_un1.nd_cookieverf
|
||||
#define n_direofoffset n_un2.nd_direof
|
||||
#define n_cookies n_un3.nd_cook
|
||||
|
||||
/*
|
||||
* Flags for n_flag
|
||||
*/
|
||||
@ -95,6 +136,8 @@ struct nfsnode {
|
||||
#define NACC 0x0100 /* Special file accessed */
|
||||
#define NUPD 0x0200 /* Special file updated */
|
||||
#define NCHG 0x0400 /* Special file times changed */
|
||||
#define NLOCKED 0x0800 /* node is locked */
|
||||
#define NWANTED 0x0100 /* someone wants to lock */
|
||||
|
||||
/*
|
||||
* Convert between nfsnode pointers and vnode pointers
|
||||
@ -107,7 +150,7 @@ struct nfsnode {
|
||||
*/
|
||||
TAILQ_HEAD(, buf) nfs_bufq;
|
||||
|
||||
#ifdef KERNEL
|
||||
#if defined(KERNEL) || defined(_KERNEL)
|
||||
extern int (**fifo_nfsv2nodeop_p)();
|
||||
extern int (**nfsv2_vnodeop_p)();
|
||||
extern int (**spec_nfsv2nodeop_p)();
|
||||
@ -128,12 +171,25 @@ int nfs_getattr __P((struct vop_getattr_args *));
|
||||
int nfs_setattr __P((struct vop_setattr_args *));
|
||||
int nfs_read __P((struct vop_read_args *));
|
||||
int nfs_write __P((struct vop_write_args *));
|
||||
#ifdef HAS_VOPLEASE
|
||||
#define nfs_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
|
||||
#define nqnfs_vop_lease_check lease_check
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
#define nqnfs_lease_check nfs_lease_check
|
||||
#else
|
||||
#define nqnfs_lease_check lease_check
|
||||
#endif
|
||||
#endif
|
||||
int nfsspec_read __P((struct vop_read_args *));
|
||||
int nfsspec_write __P((struct vop_write_args *));
|
||||
int nfsfifo_read __P((struct vop_read_args *));
|
||||
int nfsfifo_write __P((struct vop_write_args *));
|
||||
#define nfs_ioctl ((int (*) __P((struct vop_ioctl_args *)))enoioctl)
|
||||
#define nfs_select ((int (*) __P((struct vop_select_args *)))seltrue)
|
||||
#ifdef HAS_VOPREVOKE
|
||||
#define nfs_revoke vop_revoke
|
||||
#endif
|
||||
int nfs_mmap __P((struct vop_mmap_args *));
|
||||
int nfs_fsync __P((struct vop_fsync_args *));
|
||||
#define nfs_seek ((int (*) __P((struct vop_seek_args *)))nullop)
|
||||
@ -157,6 +213,7 @@ int nfs_islocked __P((struct vop_islocked_args *));
|
||||
int nfs_pathconf __P((struct vop_pathconf_args *));
|
||||
int nfs_advlock __P((struct vop_advlock_args *));
|
||||
int nfs_blkatoff __P((struct vop_blkatoff_args *));
|
||||
int nfs_bwrite __P((struct vop_bwrite_args *));
|
||||
int nfs_vget __P((struct mount *, ino_t, struct vnode **));
|
||||
int nfs_valloc __P((struct vop_valloc_args *));
|
||||
#define nfs_reallocblks \
|
||||
@ -164,13 +221,20 @@ int nfs_valloc __P((struct vop_valloc_args *));
|
||||
int nfs_vfree __P((struct vop_vfree_args *));
|
||||
int nfs_truncate __P((struct vop_truncate_args *));
|
||||
int nfs_update __P((struct vop_update_args *));
|
||||
int nfs_bwrite __P((struct vop_bwrite_args *));
|
||||
|
||||
/* other stuff */
|
||||
int nfs_removeit __P((struct sillyrename *));
|
||||
int nfs_nget __P((struct mount *,nfsv2fh_t *,struct nfsnode **));
|
||||
int nfs_lookitup __P((struct sillyrename *,nfsv2fh_t *,struct proc *));
|
||||
int nfs_nget __P((struct mount *,nfsfh_t *,int,struct nfsnode **));
|
||||
int nfs_lookitup __P((struct vnode *,char *,int,struct ucred *,struct proc *,struct nfsnode **));
|
||||
int nfs_sillyrename __P((struct vnode *,struct vnode *,struct componentname *));
|
||||
nfsuint64 *nfs_getcookie __P((struct nfsnode *, off_t, int));
|
||||
void nfs_invaldir __P((struct vnode *));
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define nqnfs_lease_updatetime nfs_lease_updatetime
|
||||
#else
|
||||
#define nqnfs_lease_updatetime lease_updatetime
|
||||
#endif
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfs.h,v 1.8 1994/11/02 00:11:00 wollman Exp $
|
||||
* $Id: nfs.h,v 1.9 1995/02/14 06:22:18 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFS_H_
|
||||
@ -45,11 +45,12 @@
|
||||
*/
|
||||
|
||||
#define NFS_MAXIOVEC 34
|
||||
#define NFS_HZ 25 /* Ticks per second for NFS timeouts */
|
||||
#define NFS_TIMEO (1*NFS_HZ) /* Default timeout = 1 second */
|
||||
#define NFS_MINTIMEO (1*NFS_HZ) /* Min timeout to use */
|
||||
#define NFS_MAXTIMEO (60*NFS_HZ) /* Max timeout to backoff to */
|
||||
#define NFS_MINIDEMTIMEO (5*NFS_HZ) /* Min timeout for non-idempotent ops*/
|
||||
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
|
||||
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
|
||||
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
|
||||
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
|
||||
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
|
||||
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
|
||||
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
|
||||
#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
|
||||
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
|
||||
@ -62,13 +63,81 @@
|
||||
#endif
|
||||
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
|
||||
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
|
||||
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
|
||||
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
|
||||
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
|
||||
#define NFS_MAXREADDIR NFS_MAXDATA /* Max. size of directory read */
|
||||
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
|
||||
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
|
||||
#define NFS_DIRBLKSIZ 1024 /* Size of an NFS directory block */
|
||||
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
|
||||
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
|
||||
#ifndef NFS_GATHERDELAY
|
||||
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
|
||||
#endif
|
||||
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
|
||||
|
||||
/*
|
||||
* Oddballs
|
||||
*/
|
||||
#define NMOD(a) ((a) % nfs_asyncdaemons)
|
||||
#define NFS_CMPFH(n, f, s) \
|
||||
((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
|
||||
#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
|
||||
#define NFS_SRVMAXDATA(n) \
|
||||
(((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
|
||||
NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* sys/buf.h should be editted to change B_APPENDWRITE --> B_NEEDCOMMIT, but
|
||||
* until then...
|
||||
* Same goes for sys/malloc.h, which needs M_NFSDIROFF,
|
||||
* M_NFSRVDESC and M_NFSBIGFH added.
|
||||
* The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
|
||||
* exclusive create.
|
||||
* The B_INVAFTERWRITE flag should be set to whatever is required by the
|
||||
* buffer cache code to say "Invalidate the block after it is written back".
|
||||
*/
|
||||
#ifndef B_NEEDCOMMIT
|
||||
#define B_NEEDCOMMIT B_APPENDWRITE
|
||||
#endif
|
||||
#ifndef M_NFSRVDESC
|
||||
#define M_NFSRVDESC M_TEMP
|
||||
#endif
|
||||
#ifndef M_NFSDIROFF
|
||||
#define M_NFSDIROFF M_TEMP
|
||||
#endif
|
||||
#ifndef M_NFSBIGFH
|
||||
#define M_NFSBIGFH M_TEMP
|
||||
#endif
|
||||
#ifndef VA_EXCLUSIVE
|
||||
#define VA_EXCLUSIVE 0
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#define B_INVAFTERWRITE B_NOCACHE
|
||||
#else
|
||||
#define B_INVAFTERWRITE B_INVAL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These ifdefs try to handle the differences between the various 4.4BSD-Lite
|
||||
* based vfs interfaces.
|
||||
* btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
|
||||
* differentiate between NetBSD-1.0 and NetBSD-current, so..
|
||||
* I also don't know about BSDi's 2.0 release.
|
||||
*/
|
||||
#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||
#define HAS_VOPLEASE 1
|
||||
#endif
|
||||
#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||
#define HAS_VOPREVOKE 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The IO_METASYNC flag should be implemented for local file systems.
|
||||
* (Until then, it is nothin at all.)
|
||||
*/
|
||||
#ifndef IO_METASYNC
|
||||
#define IO_METASYNC 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the attribute timeout based on how recently the file has been modified.
|
||||
@ -79,6 +148,20 @@
|
||||
((time.tv_sec - (np)->n_mtime) / 10 > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
|
||||
(time.tv_sec - (np)->n_mtime) / 10))
|
||||
|
||||
/*
|
||||
* Expected allocation sizes for major data structures. If the actual size
|
||||
* of the structure exceeds these sizes, then malloc() will be allocating
|
||||
* almost twice the memory required. This is used in nfs_init() to warn
|
||||
* the sysadmin that the size of a structure should be reduced.
|
||||
* (These sizes are always a power of 2. If the kernel malloc() changes
|
||||
* to one that does not allocate space in powers of 2 size, then this all
|
||||
* becomes bunk!)
|
||||
*/
|
||||
#define NFS_NODEALLOC 256
|
||||
#define NFS_MNTALLOC 512
|
||||
#define NFS_SVCALLOC 256
|
||||
#define NFS_UIDALLOC 128
|
||||
|
||||
/*
|
||||
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
|
||||
* should ever try and use it.
|
||||
@ -95,7 +178,12 @@ struct nfsd_srvargs {
|
||||
u_long nsd_haddr; /* Ip address of client */
|
||||
struct ucred nsd_cr; /* Cred. uid maps to */
|
||||
int nsd_authlen; /* Length of auth string (ret) */
|
||||
char *nsd_authstr; /* Auth string (ret) */
|
||||
u_char *nsd_authstr; /* Auth string (ret) */
|
||||
int nsd_verflen; /* and the verfier */
|
||||
u_char *nsd_verfstr;
|
||||
struct timeval nsd_timestamp; /* timestamp from verifier */
|
||||
u_long nsd_ttl; /* credential ttl (sec) */
|
||||
NFSKERBKEY_T nsd_key; /* Session key */
|
||||
};
|
||||
|
||||
struct nfsd_cargs {
|
||||
@ -103,7 +191,10 @@ struct nfsd_cargs {
|
||||
uid_t ncd_authuid; /* Effective uid */
|
||||
int ncd_authtype; /* Type of authenticator */
|
||||
int ncd_authlen; /* Length of authenticator string */
|
||||
char *ncd_authstr; /* Authenticator string */
|
||||
u_char *ncd_authstr; /* Authenticator string */
|
||||
int ncd_verflen; /* and the verifier */
|
||||
u_char *ncd_verfstr;
|
||||
NFSKERBKEY_T ncd_key; /* Session key */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -142,6 +233,7 @@ struct nfsstats {
|
||||
int srvnqnfs_leases;
|
||||
int srvnqnfs_maxleases;
|
||||
int srvnqnfs_getleases;
|
||||
int srvvop_writes;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -173,7 +265,7 @@ struct nfsstats {
|
||||
* such as SIGALRM will not expect file I/O system calls to be interrupted
|
||||
* by them and break.
|
||||
*/
|
||||
#ifdef KERNEL
|
||||
#if defined(KERNEL) || defined(_KERNEL)
|
||||
|
||||
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
|
||||
|
||||
@ -224,17 +316,29 @@ TAILQ_HEAD(, nfsreq) nfs_reqq;
|
||||
#define R_MUSTRESEND 0x40 /* Must resend request */
|
||||
#define R_GETONEREP 0x80 /* Probe for one reply only */
|
||||
|
||||
extern struct nfsstats nfsstats;
|
||||
|
||||
/*
|
||||
* A list of nfssvc_sock structures is maintained with all the sockets
|
||||
* that require service by the nfsd.
|
||||
* The nfsuid structs hang off of the nfssvc_sock structs in both lru
|
||||
* and uid hash lists.
|
||||
*/
|
||||
#define NUIDHASHSIZ 32
|
||||
#ifndef NFS_UIDHASHSIZ
|
||||
#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
|
||||
#endif
|
||||
#define NUIDHASH(sock, uid) \
|
||||
(&(sock)->ns_uidhashtbl[(uid) & (sock)->ns_uidhash])
|
||||
(&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
|
||||
#ifndef NFS_WDELAYHASHSIZ
|
||||
#define NFS_WDELAYHASHSIZ 16 /* and with this */
|
||||
#endif
|
||||
#define NWDELAYHASH(sock, f) \
|
||||
(&(sock)->ns_wdelayhashtbl[(*((u_long *)(f))) % NFS_WDELAYHASHSIZ])
|
||||
#ifndef NFS_MUIDHASHSIZ
|
||||
#define NFS_MUIDHASHSIZ 67 /* Tune the size of nfsmount with this */
|
||||
#endif
|
||||
#define NMUIDHASH(nmp, uid) \
|
||||
(&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
|
||||
#define NFSNOHASH(fhsum) \
|
||||
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
|
||||
|
||||
/*
|
||||
* Network address hash list element
|
||||
@ -248,35 +352,41 @@ struct nfsuid {
|
||||
TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
|
||||
LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
|
||||
int nu_flag; /* Flags */
|
||||
uid_t nu_uid; /* Uid mapped by this entry */
|
||||
union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
|
||||
struct ucred nu_cr; /* Cred uid mapped to */
|
||||
int nu_expire; /* Expiry time (sec) */
|
||||
struct timeval nu_timestamp; /* Kerb. timestamp */
|
||||
u_long nu_nickname; /* Nickname on server */
|
||||
NFSKERBKEY_T nu_key; /* and session key */
|
||||
};
|
||||
|
||||
#define nu_inetaddr nu_haddr.had_inetaddr
|
||||
#define nu_nam nu_haddr.had_nam
|
||||
/* Bits for nu_flag */
|
||||
#define NU_INETADDR 0x1
|
||||
#define NU_NAM 0x2
|
||||
#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
|
||||
|
||||
struct nfssvc_sock {
|
||||
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
|
||||
TAILQ_HEAD(, nfsuid) ns_uidlruhead;
|
||||
LIST_HEAD(, nfsuid) *ns_uidhashtbl;
|
||||
u_long ns_uidhash;
|
||||
|
||||
int ns_flag;
|
||||
u_long ns_sref;
|
||||
struct file *ns_fp;
|
||||
struct socket *ns_so;
|
||||
int ns_solock;
|
||||
struct mbuf *ns_nam;
|
||||
int ns_cc;
|
||||
struct mbuf *ns_raw;
|
||||
struct mbuf *ns_rawend;
|
||||
int ns_reclen;
|
||||
struct mbuf *ns_rec;
|
||||
struct mbuf *ns_recend;
|
||||
struct mbuf *ns_frag;
|
||||
int ns_flag;
|
||||
int ns_solock;
|
||||
int ns_cc;
|
||||
int ns_reclen;
|
||||
int ns_numuids;
|
||||
u_long ns_sref;
|
||||
LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
|
||||
LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
|
||||
LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
|
||||
};
|
||||
|
||||
/* Bits for "ns_flag" */
|
||||
@ -285,6 +395,7 @@ struct nfssvc_sock {
|
||||
#define SLP_NEEDQ 0x04
|
||||
#define SLP_DISCONN 0x08
|
||||
#define SLP_GETSTREAM 0x10
|
||||
#define SLP_LASTFRAG 0x20
|
||||
#define SLP_ALLFLAGS 0xff
|
||||
|
||||
TAILQ_HEAD(, nfssvc_sock) nfssvc_sockhead;
|
||||
@ -296,73 +407,124 @@ int nfssvc_sockhead_flag;
|
||||
* One of these structures is allocated for each nfsd.
|
||||
*/
|
||||
struct nfsd {
|
||||
TAILQ_ENTRY(nfsd) nd_chain; /* List of all nfsd's */
|
||||
int nd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nd_slp; /* Current socket */
|
||||
struct mbuf *nd_nam; /* Client addr for datagram req. */
|
||||
struct mbuf *nd_mrep; /* Req. mbuf list */
|
||||
struct mbuf *nd_md;
|
||||
caddr_t nd_dpos; /* Position in list */
|
||||
int nd_procnum; /* RPC procedure number */
|
||||
u_long nd_retxid; /* RPC xid */
|
||||
int nd_repstat; /* Reply status value */
|
||||
struct ucred nd_cr; /* Credentials for req. */
|
||||
int nd_nqlflag; /* Leasing flag */
|
||||
u_long nd_duration; /* Lease duration */
|
||||
int nd_authlen; /* Authenticator len */
|
||||
u_char nd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
|
||||
struct proc *nd_procp; /* Proc ptr */
|
||||
TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
|
||||
int nfsd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nfsd_slp; /* Current socket */
|
||||
int nfsd_authlen; /* Authenticator len */
|
||||
u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
|
||||
int nfsd_verflen; /* and the Verifier */
|
||||
u_char nfsd_verfstr[RPCVERF_MAXSIZ];
|
||||
struct proc *nfsd_procp; /* Proc ptr */
|
||||
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
|
||||
};
|
||||
|
||||
/* Bits for "nd_flag" */
|
||||
/* Bits for "nfsd_flag" */
|
||||
#define NFSD_WAITING 0x01
|
||||
#define NFSD_REQINPROG 0x02
|
||||
#define NFSD_NEEDAUTH 0x04
|
||||
#define NFSD_AUTHFAIL 0x08
|
||||
|
||||
/*
|
||||
* This structure is used by the server for describing each request.
|
||||
* Some fields are used only when write request gathering is performed.
|
||||
*/
|
||||
struct nfsrv_descript {
|
||||
u_quad_t nd_time; /* Write deadline (usec) */
|
||||
off_t nd_off; /* Start byte offset */
|
||||
off_t nd_eoff; /* and end byte offset */
|
||||
LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
|
||||
LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
|
||||
LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
|
||||
struct mbuf *nd_mrep; /* Request mbuf list */
|
||||
struct mbuf *nd_md; /* Current dissect mbuf */
|
||||
struct mbuf *nd_mreq; /* Reply mbuf list */
|
||||
struct mbuf *nd_nam; /* and socket addr */
|
||||
struct mbuf *nd_nam2; /* return socket addr */
|
||||
caddr_t nd_dpos; /* Current dissect pos */
|
||||
int nd_procnum; /* RPC # */
|
||||
int nd_stable; /* storage type */
|
||||
int nd_flag; /* nd_flag */
|
||||
int nd_len; /* Length of this write */
|
||||
int nd_repstat; /* Reply status */
|
||||
u_long nd_retxid; /* Reply xid */
|
||||
u_long nd_duration; /* Lease duration */
|
||||
struct timeval nd_starttime; /* Time RPC initiated */
|
||||
fhandle_t nd_fh; /* File handle */
|
||||
struct ucred nd_cr; /* Credentials */
|
||||
};
|
||||
|
||||
/* Bits for "nd_flag" */
|
||||
#define ND_READ LEASE_READ
|
||||
#define ND_WRITE LEASE_WRITE
|
||||
#define ND_CHECK 0x04
|
||||
#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
|
||||
#define ND_NFSV3 0x08
|
||||
#define ND_NQNFS 0x10
|
||||
#define ND_KERBNICK 0x20
|
||||
#define ND_KERBFULL 0x40
|
||||
#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
|
||||
|
||||
TAILQ_HEAD(, nfsd) nfsd_head;
|
||||
int nfsd_head_flag;
|
||||
#define NFSD_CHECKSLP 0x01
|
||||
|
||||
/*
|
||||
* These macros compare nfsrv_descript structures.
|
||||
*/
|
||||
#define NFSW_CONTIG(o, n) \
|
||||
((o)->nd_eoff >= (n)->nd_off && \
|
||||
!bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
|
||||
|
||||
#define NFSW_SAMECRED(o, n) \
|
||||
(((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
|
||||
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
|
||||
sizeof (struct ucred)))
|
||||
|
||||
int nfs_reply __P((struct nfsreq *));
|
||||
int nfs_getreq __P((struct nfsd *,int));
|
||||
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
|
||||
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
|
||||
int nfs_rephead __P((int,struct nfsd *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_rephead __P((int,struct nfsrv_descript *,struct nfssvc_sock *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_sndlock __P((int *,struct nfsreq *));
|
||||
int nfs_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
|
||||
int nfs_vinvalbuf __P((struct vnode *,int,struct ucred *,struct proc *,int));
|
||||
int nfs_readrpc __P((struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int));
|
||||
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int *,int *));
|
||||
int nfs_readdirrpc __P((register struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
|
||||
int nfs_asyncio __P((struct buf *,struct ucred *));
|
||||
int nfs_doio __P((struct buf *,struct ucred *,struct proc *));
|
||||
int nfs_readlinkrpc __P((struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_sigintr __P((struct nfsmount *,struct nfsreq *r,struct proc *));
|
||||
int nfs_readdirlookrpc __P((struct vnode *,register struct uio *,struct ucred *));
|
||||
int nfs_readdirplusrpc __P((struct vnode *,register struct uio *,struct ucred *));
|
||||
int nfsm_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
|
||||
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *));
|
||||
void nfsm_srvfattr __P((struct nfsrv_descript *,struct vattr *,struct nfs_fattr *));
|
||||
void nfsm_srvwcc __P((struct nfsrv_descript *,int,struct vattr *,int,struct vattr *,struct mbuf **,char **));
|
||||
void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct mbuf **,char **));
|
||||
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *,int));
|
||||
int nfsrv_access __P((struct vnode *,int,struct ucred *,int,struct proc *));
|
||||
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
|
||||
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
|
||||
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct proc *));
|
||||
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
|
||||
void nfsm_adj __P((struct mbuf *,int,int));
|
||||
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
|
||||
void nfsrv_initcache __P((void));
|
||||
int nfs_rcvlock __P((struct nfsreq *));
|
||||
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,int *,char **,int *));
|
||||
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,char **,int *,char *,int *,NFSKERBKEY_T));
|
||||
int nfs_getnickauth __P((struct nfsmount *,struct ucred *,char **,int *,char *,int));
|
||||
int nfs_savenickauth __P((struct nfsmount *,struct ucred *,int,NFSKERBKEY_T,struct mbuf **,char **,struct mbuf *));
|
||||
int nfs_msg __P((struct proc *,char *,char *));
|
||||
int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
|
||||
int nfsrv_getstream __P((struct nfssvc_sock *,int));
|
||||
void nfs_nhinit __P((void));
|
||||
void nfs_timer __P((void*));
|
||||
struct nfsnodehashhead * nfs_hash __P((nfsv2fh_t *));
|
||||
u_long nfs_hash __P((nfsfh_t *,int));
|
||||
int nfssvc_iod __P((struct proc *));
|
||||
int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,struct proc *));
|
||||
int nfssvc_addsock __P((struct file *,struct mbuf *));
|
||||
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *));
|
||||
int nfsrv_getcache __P((struct mbuf *,struct nfsd *,struct mbuf **));
|
||||
void nfsrv_updatecache __P((struct mbuf *,struct nfsd *,int,struct mbuf *));
|
||||
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
|
||||
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
|
||||
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
|
||||
int mountnfs __P((struct nfs_args *,struct mount *,struct mbuf *,char *,char *,struct vnode **));
|
||||
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
|
||||
int nfs_getattrcache __P((struct vnode *,struct vattr *));
|
||||
@ -370,9 +532,20 @@ int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
|
||||
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
|
||||
int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
|
||||
void nfsrv_init __P((int));
|
||||
void nfs_clearcommit __P((struct mount *));
|
||||
int nfsrv_errmap __P((struct nfsrv_descript *, int));
|
||||
void nfsrvw_coalesce __P((struct nfsrv_descript *,struct nfsrv_descript *));
|
||||
void nfsrvw_sort __P((gid_t [],int));
|
||||
void nfsrv_setcred __P((struct ucred *,struct ucred *));
|
||||
int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
|
||||
int nfs_writebp __P((struct buf *,int));
|
||||
int nfsrv_vput __P(( struct vnode * ));
|
||||
int nfsrv_vrele __P(( struct vnode * ));
|
||||
int nfsrv_vmio __P(( struct vnode * ));
|
||||
int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
|
||||
struct proc *, struct mbuf **));
|
||||
int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
|
||||
struct proc *p));
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfs.h,v 1.8 1994/11/02 00:11:00 wollman Exp $
|
||||
* $Id: nfs.h,v 1.9 1995/02/14 06:22:18 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFS_H_
|
||||
@ -45,11 +45,12 @@
|
||||
*/
|
||||
|
||||
#define NFS_MAXIOVEC 34
|
||||
#define NFS_HZ 25 /* Ticks per second for NFS timeouts */
|
||||
#define NFS_TIMEO (1*NFS_HZ) /* Default timeout = 1 second */
|
||||
#define NFS_MINTIMEO (1*NFS_HZ) /* Min timeout to use */
|
||||
#define NFS_MAXTIMEO (60*NFS_HZ) /* Max timeout to backoff to */
|
||||
#define NFS_MINIDEMTIMEO (5*NFS_HZ) /* Min timeout for non-idempotent ops*/
|
||||
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
|
||||
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
|
||||
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
|
||||
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
|
||||
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
|
||||
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
|
||||
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
|
||||
#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
|
||||
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
|
||||
@ -62,13 +63,81 @@
|
||||
#endif
|
||||
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
|
||||
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
|
||||
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
|
||||
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
|
||||
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
|
||||
#define NFS_MAXREADDIR NFS_MAXDATA /* Max. size of directory read */
|
||||
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
|
||||
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
|
||||
#define NFS_DIRBLKSIZ 1024 /* Size of an NFS directory block */
|
||||
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
|
||||
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
|
||||
#ifndef NFS_GATHERDELAY
|
||||
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
|
||||
#endif
|
||||
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
|
||||
|
||||
/*
|
||||
* Oddballs
|
||||
*/
|
||||
#define NMOD(a) ((a) % nfs_asyncdaemons)
|
||||
#define NFS_CMPFH(n, f, s) \
|
||||
((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
|
||||
#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
|
||||
#define NFS_SRVMAXDATA(n) \
|
||||
(((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
|
||||
NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* sys/buf.h should be editted to change B_APPENDWRITE --> B_NEEDCOMMIT, but
|
||||
* until then...
|
||||
* Same goes for sys/malloc.h, which needs M_NFSDIROFF,
|
||||
* M_NFSRVDESC and M_NFSBIGFH added.
|
||||
* The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
|
||||
* exclusive create.
|
||||
* The B_INVAFTERWRITE flag should be set to whatever is required by the
|
||||
* buffer cache code to say "Invalidate the block after it is written back".
|
||||
*/
|
||||
#ifndef B_NEEDCOMMIT
|
||||
#define B_NEEDCOMMIT B_APPENDWRITE
|
||||
#endif
|
||||
#ifndef M_NFSRVDESC
|
||||
#define M_NFSRVDESC M_TEMP
|
||||
#endif
|
||||
#ifndef M_NFSDIROFF
|
||||
#define M_NFSDIROFF M_TEMP
|
||||
#endif
|
||||
#ifndef M_NFSBIGFH
|
||||
#define M_NFSBIGFH M_TEMP
|
||||
#endif
|
||||
#ifndef VA_EXCLUSIVE
|
||||
#define VA_EXCLUSIVE 0
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#define B_INVAFTERWRITE B_NOCACHE
|
||||
#else
|
||||
#define B_INVAFTERWRITE B_INVAL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These ifdefs try to handle the differences between the various 4.4BSD-Lite
|
||||
* based vfs interfaces.
|
||||
* btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
|
||||
* differentiate between NetBSD-1.0 and NetBSD-current, so..
|
||||
* I also don't know about BSDi's 2.0 release.
|
||||
*/
|
||||
#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||
#define HAS_VOPLEASE 1
|
||||
#endif
|
||||
#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||
#define HAS_VOPREVOKE 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The IO_METASYNC flag should be implemented for local file systems.
|
||||
* (Until then, it is nothin at all.)
|
||||
*/
|
||||
#ifndef IO_METASYNC
|
||||
#define IO_METASYNC 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the attribute timeout based on how recently the file has been modified.
|
||||
@ -79,6 +148,20 @@
|
||||
((time.tv_sec - (np)->n_mtime) / 10 > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
|
||||
(time.tv_sec - (np)->n_mtime) / 10))
|
||||
|
||||
/*
|
||||
* Expected allocation sizes for major data structures. If the actual size
|
||||
* of the structure exceeds these sizes, then malloc() will be allocating
|
||||
* almost twice the memory required. This is used in nfs_init() to warn
|
||||
* the sysadmin that the size of a structure should be reduced.
|
||||
* (These sizes are always a power of 2. If the kernel malloc() changes
|
||||
* to one that does not allocate space in powers of 2 size, then this all
|
||||
* becomes bunk!)
|
||||
*/
|
||||
#define NFS_NODEALLOC 256
|
||||
#define NFS_MNTALLOC 512
|
||||
#define NFS_SVCALLOC 256
|
||||
#define NFS_UIDALLOC 128
|
||||
|
||||
/*
|
||||
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
|
||||
* should ever try and use it.
|
||||
@ -95,7 +178,12 @@ struct nfsd_srvargs {
|
||||
u_long nsd_haddr; /* Ip address of client */
|
||||
struct ucred nsd_cr; /* Cred. uid maps to */
|
||||
int nsd_authlen; /* Length of auth string (ret) */
|
||||
char *nsd_authstr; /* Auth string (ret) */
|
||||
u_char *nsd_authstr; /* Auth string (ret) */
|
||||
int nsd_verflen; /* and the verfier */
|
||||
u_char *nsd_verfstr;
|
||||
struct timeval nsd_timestamp; /* timestamp from verifier */
|
||||
u_long nsd_ttl; /* credential ttl (sec) */
|
||||
NFSKERBKEY_T nsd_key; /* Session key */
|
||||
};
|
||||
|
||||
struct nfsd_cargs {
|
||||
@ -103,7 +191,10 @@ struct nfsd_cargs {
|
||||
uid_t ncd_authuid; /* Effective uid */
|
||||
int ncd_authtype; /* Type of authenticator */
|
||||
int ncd_authlen; /* Length of authenticator string */
|
||||
char *ncd_authstr; /* Authenticator string */
|
||||
u_char *ncd_authstr; /* Authenticator string */
|
||||
int ncd_verflen; /* and the verifier */
|
||||
u_char *ncd_verfstr;
|
||||
NFSKERBKEY_T ncd_key; /* Session key */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -142,6 +233,7 @@ struct nfsstats {
|
||||
int srvnqnfs_leases;
|
||||
int srvnqnfs_maxleases;
|
||||
int srvnqnfs_getleases;
|
||||
int srvvop_writes;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -173,7 +265,7 @@ struct nfsstats {
|
||||
* such as SIGALRM will not expect file I/O system calls to be interrupted
|
||||
* by them and break.
|
||||
*/
|
||||
#ifdef KERNEL
|
||||
#if defined(KERNEL) || defined(_KERNEL)
|
||||
|
||||
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
|
||||
|
||||
@ -224,17 +316,29 @@ TAILQ_HEAD(, nfsreq) nfs_reqq;
|
||||
#define R_MUSTRESEND 0x40 /* Must resend request */
|
||||
#define R_GETONEREP 0x80 /* Probe for one reply only */
|
||||
|
||||
extern struct nfsstats nfsstats;
|
||||
|
||||
/*
|
||||
* A list of nfssvc_sock structures is maintained with all the sockets
|
||||
* that require service by the nfsd.
|
||||
* The nfsuid structs hang off of the nfssvc_sock structs in both lru
|
||||
* and uid hash lists.
|
||||
*/
|
||||
#define NUIDHASHSIZ 32
|
||||
#ifndef NFS_UIDHASHSIZ
|
||||
#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
|
||||
#endif
|
||||
#define NUIDHASH(sock, uid) \
|
||||
(&(sock)->ns_uidhashtbl[(uid) & (sock)->ns_uidhash])
|
||||
(&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
|
||||
#ifndef NFS_WDELAYHASHSIZ
|
||||
#define NFS_WDELAYHASHSIZ 16 /* and with this */
|
||||
#endif
|
||||
#define NWDELAYHASH(sock, f) \
|
||||
(&(sock)->ns_wdelayhashtbl[(*((u_long *)(f))) % NFS_WDELAYHASHSIZ])
|
||||
#ifndef NFS_MUIDHASHSIZ
|
||||
#define NFS_MUIDHASHSIZ 67 /* Tune the size of nfsmount with this */
|
||||
#endif
|
||||
#define NMUIDHASH(nmp, uid) \
|
||||
(&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
|
||||
#define NFSNOHASH(fhsum) \
|
||||
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
|
||||
|
||||
/*
|
||||
* Network address hash list element
|
||||
@ -248,35 +352,41 @@ struct nfsuid {
|
||||
TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
|
||||
LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
|
||||
int nu_flag; /* Flags */
|
||||
uid_t nu_uid; /* Uid mapped by this entry */
|
||||
union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
|
||||
struct ucred nu_cr; /* Cred uid mapped to */
|
||||
int nu_expire; /* Expiry time (sec) */
|
||||
struct timeval nu_timestamp; /* Kerb. timestamp */
|
||||
u_long nu_nickname; /* Nickname on server */
|
||||
NFSKERBKEY_T nu_key; /* and session key */
|
||||
};
|
||||
|
||||
#define nu_inetaddr nu_haddr.had_inetaddr
|
||||
#define nu_nam nu_haddr.had_nam
|
||||
/* Bits for nu_flag */
|
||||
#define NU_INETADDR 0x1
|
||||
#define NU_NAM 0x2
|
||||
#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
|
||||
|
||||
struct nfssvc_sock {
|
||||
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
|
||||
TAILQ_HEAD(, nfsuid) ns_uidlruhead;
|
||||
LIST_HEAD(, nfsuid) *ns_uidhashtbl;
|
||||
u_long ns_uidhash;
|
||||
|
||||
int ns_flag;
|
||||
u_long ns_sref;
|
||||
struct file *ns_fp;
|
||||
struct socket *ns_so;
|
||||
int ns_solock;
|
||||
struct mbuf *ns_nam;
|
||||
int ns_cc;
|
||||
struct mbuf *ns_raw;
|
||||
struct mbuf *ns_rawend;
|
||||
int ns_reclen;
|
||||
struct mbuf *ns_rec;
|
||||
struct mbuf *ns_recend;
|
||||
struct mbuf *ns_frag;
|
||||
int ns_flag;
|
||||
int ns_solock;
|
||||
int ns_cc;
|
||||
int ns_reclen;
|
||||
int ns_numuids;
|
||||
u_long ns_sref;
|
||||
LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
|
||||
LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
|
||||
LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
|
||||
};
|
||||
|
||||
/* Bits for "ns_flag" */
|
||||
@ -285,6 +395,7 @@ struct nfssvc_sock {
|
||||
#define SLP_NEEDQ 0x04
|
||||
#define SLP_DISCONN 0x08
|
||||
#define SLP_GETSTREAM 0x10
|
||||
#define SLP_LASTFRAG 0x20
|
||||
#define SLP_ALLFLAGS 0xff
|
||||
|
||||
TAILQ_HEAD(, nfssvc_sock) nfssvc_sockhead;
|
||||
@ -296,73 +407,124 @@ int nfssvc_sockhead_flag;
|
||||
* One of these structures is allocated for each nfsd.
|
||||
*/
|
||||
struct nfsd {
|
||||
TAILQ_ENTRY(nfsd) nd_chain; /* List of all nfsd's */
|
||||
int nd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nd_slp; /* Current socket */
|
||||
struct mbuf *nd_nam; /* Client addr for datagram req. */
|
||||
struct mbuf *nd_mrep; /* Req. mbuf list */
|
||||
struct mbuf *nd_md;
|
||||
caddr_t nd_dpos; /* Position in list */
|
||||
int nd_procnum; /* RPC procedure number */
|
||||
u_long nd_retxid; /* RPC xid */
|
||||
int nd_repstat; /* Reply status value */
|
||||
struct ucred nd_cr; /* Credentials for req. */
|
||||
int nd_nqlflag; /* Leasing flag */
|
||||
u_long nd_duration; /* Lease duration */
|
||||
int nd_authlen; /* Authenticator len */
|
||||
u_char nd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
|
||||
struct proc *nd_procp; /* Proc ptr */
|
||||
TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
|
||||
int nfsd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nfsd_slp; /* Current socket */
|
||||
int nfsd_authlen; /* Authenticator len */
|
||||
u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
|
||||
int nfsd_verflen; /* and the Verifier */
|
||||
u_char nfsd_verfstr[RPCVERF_MAXSIZ];
|
||||
struct proc *nfsd_procp; /* Proc ptr */
|
||||
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
|
||||
};
|
||||
|
||||
/* Bits for "nd_flag" */
|
||||
/* Bits for "nfsd_flag" */
|
||||
#define NFSD_WAITING 0x01
|
||||
#define NFSD_REQINPROG 0x02
|
||||
#define NFSD_NEEDAUTH 0x04
|
||||
#define NFSD_AUTHFAIL 0x08
|
||||
|
||||
/*
|
||||
* This structure is used by the server for describing each request.
|
||||
* Some fields are used only when write request gathering is performed.
|
||||
*/
|
||||
struct nfsrv_descript {
|
||||
u_quad_t nd_time; /* Write deadline (usec) */
|
||||
off_t nd_off; /* Start byte offset */
|
||||
off_t nd_eoff; /* and end byte offset */
|
||||
LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
|
||||
LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
|
||||
LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
|
||||
struct mbuf *nd_mrep; /* Request mbuf list */
|
||||
struct mbuf *nd_md; /* Current dissect mbuf */
|
||||
struct mbuf *nd_mreq; /* Reply mbuf list */
|
||||
struct mbuf *nd_nam; /* and socket addr */
|
||||
struct mbuf *nd_nam2; /* return socket addr */
|
||||
caddr_t nd_dpos; /* Current dissect pos */
|
||||
int nd_procnum; /* RPC # */
|
||||
int nd_stable; /* storage type */
|
||||
int nd_flag; /* nd_flag */
|
||||
int nd_len; /* Length of this write */
|
||||
int nd_repstat; /* Reply status */
|
||||
u_long nd_retxid; /* Reply xid */
|
||||
u_long nd_duration; /* Lease duration */
|
||||
struct timeval nd_starttime; /* Time RPC initiated */
|
||||
fhandle_t nd_fh; /* File handle */
|
||||
struct ucred nd_cr; /* Credentials */
|
||||
};
|
||||
|
||||
/* Bits for "nd_flag" */
|
||||
#define ND_READ LEASE_READ
|
||||
#define ND_WRITE LEASE_WRITE
|
||||
#define ND_CHECK 0x04
|
||||
#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
|
||||
#define ND_NFSV3 0x08
|
||||
#define ND_NQNFS 0x10
|
||||
#define ND_KERBNICK 0x20
|
||||
#define ND_KERBFULL 0x40
|
||||
#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
|
||||
|
||||
TAILQ_HEAD(, nfsd) nfsd_head;
|
||||
int nfsd_head_flag;
|
||||
#define NFSD_CHECKSLP 0x01
|
||||
|
||||
/*
|
||||
* These macros compare nfsrv_descript structures.
|
||||
*/
|
||||
#define NFSW_CONTIG(o, n) \
|
||||
((o)->nd_eoff >= (n)->nd_off && \
|
||||
!bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
|
||||
|
||||
#define NFSW_SAMECRED(o, n) \
|
||||
(((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
|
||||
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
|
||||
sizeof (struct ucred)))
|
||||
|
||||
int nfs_reply __P((struct nfsreq *));
|
||||
int nfs_getreq __P((struct nfsd *,int));
|
||||
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
|
||||
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
|
||||
int nfs_rephead __P((int,struct nfsd *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_rephead __P((int,struct nfsrv_descript *,struct nfssvc_sock *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_sndlock __P((int *,struct nfsreq *));
|
||||
int nfs_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
|
||||
int nfs_vinvalbuf __P((struct vnode *,int,struct ucred *,struct proc *,int));
|
||||
int nfs_readrpc __P((struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int));
|
||||
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int *,int *));
|
||||
int nfs_readdirrpc __P((register struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
|
||||
int nfs_asyncio __P((struct buf *,struct ucred *));
|
||||
int nfs_doio __P((struct buf *,struct ucred *,struct proc *));
|
||||
int nfs_readlinkrpc __P((struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_sigintr __P((struct nfsmount *,struct nfsreq *r,struct proc *));
|
||||
int nfs_readdirlookrpc __P((struct vnode *,register struct uio *,struct ucred *));
|
||||
int nfs_readdirplusrpc __P((struct vnode *,register struct uio *,struct ucred *));
|
||||
int nfsm_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
|
||||
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *));
|
||||
void nfsm_srvfattr __P((struct nfsrv_descript *,struct vattr *,struct nfs_fattr *));
|
||||
void nfsm_srvwcc __P((struct nfsrv_descript *,int,struct vattr *,int,struct vattr *,struct mbuf **,char **));
|
||||
void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct mbuf **,char **));
|
||||
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *,int));
|
||||
int nfsrv_access __P((struct vnode *,int,struct ucred *,int,struct proc *));
|
||||
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
|
||||
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
|
||||
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct proc *));
|
||||
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
|
||||
void nfsm_adj __P((struct mbuf *,int,int));
|
||||
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
|
||||
void nfsrv_initcache __P((void));
|
||||
int nfs_rcvlock __P((struct nfsreq *));
|
||||
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,int *,char **,int *));
|
||||
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,char **,int *,char *,int *,NFSKERBKEY_T));
|
||||
int nfs_getnickauth __P((struct nfsmount *,struct ucred *,char **,int *,char *,int));
|
||||
int nfs_savenickauth __P((struct nfsmount *,struct ucred *,int,NFSKERBKEY_T,struct mbuf **,char **,struct mbuf *));
|
||||
int nfs_msg __P((struct proc *,char *,char *));
|
||||
int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
|
||||
int nfsrv_getstream __P((struct nfssvc_sock *,int));
|
||||
void nfs_nhinit __P((void));
|
||||
void nfs_timer __P((void*));
|
||||
struct nfsnodehashhead * nfs_hash __P((nfsv2fh_t *));
|
||||
u_long nfs_hash __P((nfsfh_t *,int));
|
||||
int nfssvc_iod __P((struct proc *));
|
||||
int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,struct proc *));
|
||||
int nfssvc_addsock __P((struct file *,struct mbuf *));
|
||||
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *));
|
||||
int nfsrv_getcache __P((struct mbuf *,struct nfsd *,struct mbuf **));
|
||||
void nfsrv_updatecache __P((struct mbuf *,struct nfsd *,int,struct mbuf *));
|
||||
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
|
||||
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
|
||||
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
|
||||
int mountnfs __P((struct nfs_args *,struct mount *,struct mbuf *,char *,char *,struct vnode **));
|
||||
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
|
||||
int nfs_getattrcache __P((struct vnode *,struct vattr *));
|
||||
@ -370,9 +532,20 @@ int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
|
||||
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
|
||||
int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
|
||||
void nfsrv_init __P((int));
|
||||
void nfs_clearcommit __P((struct mount *));
|
||||
int nfsrv_errmap __P((struct nfsrv_descript *, int));
|
||||
void nfsrvw_coalesce __P((struct nfsrv_descript *,struct nfsrv_descript *));
|
||||
void nfsrvw_sort __P((gid_t [],int));
|
||||
void nfsrv_setcred __P((struct ucred *,struct ucred *));
|
||||
int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
|
||||
int nfs_writebp __P((struct buf *,int));
|
||||
int nfsrv_vput __P(( struct vnode * ));
|
||||
int nfsrv_vrele __P(( struct vnode * ));
|
||||
int nfsrv_vmio __P(( struct vnode * ));
|
||||
int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
|
||||
struct proc *, struct mbuf **));
|
||||
int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
|
||||
struct proc *p));
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_srvcache.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfs_srvcache.c,v 1.4 1994/10/02 17:27:00 phk Exp $
|
||||
* $Id: nfs_srvcache.c,v 1.5 1994/10/17 17:47:36 phk Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -59,11 +59,13 @@
|
||||
#endif
|
||||
#include <nfs/nfsm_subs.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsrvcache.h>
|
||||
#include <nfs/nqnfs.h>
|
||||
|
||||
extern struct nfsstats nfsstats;
|
||||
extern int nfsv2_procid[NFS_NPROCS];
|
||||
long numnfsrvcache, desirednfsrvcache = NFSRVCACHESIZ;
|
||||
|
||||
#define NFSRCHASH(xid) \
|
||||
@ -89,15 +91,18 @@ int nonidempotent[NFS_NPROCS] = {
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
@ -108,7 +113,7 @@ int nonidempotent[NFS_NPROCS] = {
|
||||
};
|
||||
|
||||
/* True iff the rpc reply is an nfs status ONLY! */
|
||||
static int repliesstatus[NFS_NPROCS] = {
|
||||
static int nfsv2_repstat[NFS_NPROCS] = {
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
@ -127,11 +132,6 @@ static int repliesstatus[NFS_NPROCS] = {
|
||||
TRUE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
TRUE,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -160,9 +160,9 @@ nfsrv_initcache()
|
||||
* Update/add new request at end of lru list
|
||||
*/
|
||||
int
|
||||
nfsrv_getcache(nam, nd, repp)
|
||||
struct mbuf *nam;
|
||||
register struct nfsd *nd;
|
||||
nfsrv_getcache(nd, slp, repp)
|
||||
register struct nfsrv_descript *nd;
|
||||
struct nfssvc_sock *slp;
|
||||
struct mbuf **repp;
|
||||
{
|
||||
register struct nfsrvcache *rp;
|
||||
@ -171,13 +171,17 @@ nfsrv_getcache(nam, nd, repp)
|
||||
caddr_t bpos;
|
||||
int ret;
|
||||
|
||||
if (nd->nd_nqlflag != NQL_NOVAL)
|
||||
/*
|
||||
* Don't cache recent requests for reliable transport protocols.
|
||||
* (Maybe we should for the case of a reconnect, but..)
|
||||
*/
|
||||
if (!nd->nd_nam2)
|
||||
return (RC_DOIT);
|
||||
loop:
|
||||
for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
|
||||
rp = rp->rc_hash.le_next) {
|
||||
if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
|
||||
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nam)) {
|
||||
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
|
||||
if ((rp->rc_flag & RC_LOCKED) != 0) {
|
||||
rp->rc_flag |= RC_WANTED;
|
||||
(void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
|
||||
@ -196,7 +200,7 @@ nfsrv_getcache(nam, nd, repp)
|
||||
ret = RC_DROPIT;
|
||||
} else if (rp->rc_flag & RC_REPSTATUS) {
|
||||
nfsstats.srvcache_nonidemdonehits++;
|
||||
nfs_rephead(0, nd, rp->rc_status,
|
||||
nfs_rephead(0, nd, slp, rp->rc_status,
|
||||
0, (u_quad_t *)0, repp, &mb, &bpos);
|
||||
ret = RC_REPLY;
|
||||
} else if (rp->rc_flag & RC_REPMBUF) {
|
||||
@ -243,7 +247,7 @@ nfsrv_getcache(nam, nd, repp)
|
||||
TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru);
|
||||
rp->rc_state = RC_INPROG;
|
||||
rp->rc_xid = nd->nd_retxid;
|
||||
saddr = mtod(nam, struct sockaddr_in *);
|
||||
saddr = mtod(nd->nd_nam, struct sockaddr_in *);
|
||||
switch (saddr->sin_family) {
|
||||
case AF_INET:
|
||||
rp->rc_flag |= RC_INETADDR;
|
||||
@ -252,7 +256,7 @@ nfsrv_getcache(nam, nd, repp)
|
||||
case AF_ISO:
|
||||
default:
|
||||
rp->rc_flag |= RC_NAM;
|
||||
rp->rc_nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
|
||||
rp->rc_nam = m_copym(nd->nd_nam, 0, M_COPYALL, M_WAIT);
|
||||
break;
|
||||
};
|
||||
rp->rc_proc = nd->nd_procnum;
|
||||
@ -269,21 +273,20 @@ nfsrv_getcache(nam, nd, repp)
|
||||
* Update a request cache entry after the rpc has been done
|
||||
*/
|
||||
void
|
||||
nfsrv_updatecache(nam, nd, repvalid, repmbuf)
|
||||
struct mbuf *nam;
|
||||
register struct nfsd *nd;
|
||||
nfsrv_updatecache(nd, repvalid, repmbuf)
|
||||
register struct nfsrv_descript *nd;
|
||||
int repvalid;
|
||||
struct mbuf *repmbuf;
|
||||
{
|
||||
register struct nfsrvcache *rp;
|
||||
|
||||
if (nd->nd_nqlflag != NQL_NOVAL)
|
||||
if (!nd->nd_nam2)
|
||||
return;
|
||||
loop:
|
||||
for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
|
||||
rp = rp->rc_hash.le_next) {
|
||||
if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
|
||||
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nam)) {
|
||||
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
|
||||
if ((rp->rc_flag & RC_LOCKED) != 0) {
|
||||
rp->rc_flag |= RC_WANTED;
|
||||
(void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
|
||||
@ -296,7 +299,8 @@ nfsrv_updatecache(nam, nd, repvalid, repmbuf)
|
||||
* the reply for non-idempotent rpc's.
|
||||
*/
|
||||
if (repvalid && nonidempotent[nd->nd_procnum]) {
|
||||
if (repliesstatus[nd->nd_procnum]) {
|
||||
if ((nd->nd_flag & ND_NFSV3) == 0 &&
|
||||
nfsv2_repstat[nfsv2_procid[nd->nd_procnum]]) {
|
||||
rp->rc_status = nd->nd_repstat;
|
||||
rp->rc_flag |= RC_REPSTATUS;
|
||||
} else {
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_socket.c 8.3 (Berkeley) 1/12/94
|
||||
* $Id: nfs_socket.c,v 1.6 1995/03/16 18:15:37 bde Exp $
|
||||
* $Id: nfs_socket.c,v 1.7 1995/05/30 08:12:40 rgrimes Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -59,7 +59,7 @@
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/xdr_subs.h>
|
||||
#include <nfs/nfsm_subs.h>
|
||||
@ -94,36 +94,13 @@
|
||||
* External data, mostly RPC constants in XDR form
|
||||
*/
|
||||
extern u_long rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers, rpc_auth_unix,
|
||||
rpc_msgaccepted, rpc_call, rpc_autherr, rpc_rejectedcred,
|
||||
rpc_msgaccepted, rpc_call, rpc_autherr,
|
||||
rpc_auth_kerb;
|
||||
extern u_long nfs_prog, nfs_vers, nqnfs_prog, nqnfs_vers;
|
||||
extern u_long nfs_prog, nqnfs_prog;
|
||||
extern time_t nqnfsstarttime;
|
||||
extern int nonidempotent[NFS_NPROCS];
|
||||
|
||||
/*
|
||||
* Maps errno values to nfs error numbers.
|
||||
* Use NFSERR_IO as the catch all for ones not specifically defined in
|
||||
* RFC 1094.
|
||||
*/
|
||||
static int nfsrv_errmap[ELAST] = {
|
||||
NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR,
|
||||
NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
||||
NFSERR_IO,
|
||||
};
|
||||
extern struct nfsstats nfsstats;
|
||||
extern int nfsv3_procid[NFS_NPROCS];
|
||||
extern int nfs_ticks;
|
||||
|
||||
/*
|
||||
* Defines which timer to use for the procnum.
|
||||
@ -134,7 +111,8 @@ static int nfsrv_errmap[ELAST] = {
|
||||
* 4 - write
|
||||
*/
|
||||
static int proct[NFS_NPROCS] = {
|
||||
0, 1, 0, 0, 2, 3, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0,
|
||||
0, 1, 0, 2, 1, 3, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0,
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -164,10 +142,12 @@ int nfsrv_null(),
|
||||
nfsrv_getattr(),
|
||||
nfsrv_setattr(),
|
||||
nfsrv_lookup(),
|
||||
nfsrv3_access(),
|
||||
nfsrv_readlink(),
|
||||
nfsrv_read(),
|
||||
nfsrv_write(),
|
||||
nfsrv_create(),
|
||||
nfsrv_mknod(),
|
||||
nfsrv_remove(),
|
||||
nfsrv_rename(),
|
||||
nfsrv_link(),
|
||||
@ -175,37 +155,42 @@ int nfsrv_null(),
|
||||
nfsrv_mkdir(),
|
||||
nfsrv_rmdir(),
|
||||
nfsrv_readdir(),
|
||||
nfsrv_readdirplus(),
|
||||
nfsrv_statfs(),
|
||||
nfsrv_fsinfo(),
|
||||
nfsrv_pathconf(),
|
||||
nfsrv_commit(),
|
||||
nfsrv_noop(),
|
||||
nqnfsrv_readdirlook(),
|
||||
nqnfsrv_getlease(),
|
||||
nqnfsrv_vacated(),
|
||||
nqnfsrv_access();
|
||||
nqnfsrv_vacated();
|
||||
|
||||
int (*nfsrv_procs[NFS_NPROCS])() = {
|
||||
int (*nfsrv3_procs[NFS_NPROCS])() = {
|
||||
nfsrv_null,
|
||||
nfsrv_getattr,
|
||||
nfsrv_setattr,
|
||||
nfsrv_noop,
|
||||
nfsrv_lookup,
|
||||
nfsrv3_access,
|
||||
nfsrv_readlink,
|
||||
nfsrv_read,
|
||||
nfsrv_noop,
|
||||
nfsrv_write,
|
||||
nfsrv_create,
|
||||
nfsrv_mkdir,
|
||||
nfsrv_symlink,
|
||||
nfsrv_mknod,
|
||||
nfsrv_remove,
|
||||
nfsrv_rmdir,
|
||||
nfsrv_rename,
|
||||
nfsrv_link,
|
||||
nfsrv_symlink,
|
||||
nfsrv_mkdir,
|
||||
nfsrv_rmdir,
|
||||
nfsrv_readdir,
|
||||
nfsrv_readdirplus,
|
||||
nfsrv_statfs,
|
||||
nqnfsrv_readdirlook,
|
||||
nfsrv_fsinfo,
|
||||
nfsrv_pathconf,
|
||||
nfsrv_commit,
|
||||
nqnfsrv_getlease,
|
||||
nqnfsrv_vacated,
|
||||
nfsrv_noop,
|
||||
nqnfsrv_access,
|
||||
nfsrv_noop
|
||||
};
|
||||
|
||||
/*
|
||||
@ -874,13 +859,16 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
struct nfsmount *nmp;
|
||||
struct mbuf *md, *mheadend;
|
||||
struct nfsnode *np;
|
||||
char nickv[RPCX_NICKVERF];
|
||||
time_t reqtime, waituntil;
|
||||
caddr_t dpos, cp2;
|
||||
int t1, nqlflag, cachable, s, error = 0, mrest_len, auth_len, auth_type;
|
||||
int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0, failed_auth = 0;
|
||||
int verf_len, verf_type;
|
||||
u_long xid;
|
||||
u_quad_t frev;
|
||||
char *auth_str;
|
||||
char *auth_str, *verf_str;
|
||||
NFSKERBKEY_T key; /* save session key */
|
||||
|
||||
nmp = VFSTONFS(vp->v_mount);
|
||||
MALLOC(rep, struct nfsreq *, sizeof(struct nfsreq), M_NFSREQ, M_WAITOK);
|
||||
@ -900,19 +888,21 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
* Get the RPC header with authorization.
|
||||
*/
|
||||
kerbauth:
|
||||
auth_str = (char *)0;
|
||||
verf_str = auth_str = (char *)0;
|
||||
if (nmp->nm_flag & NFSMNT_KERB) {
|
||||
if (failed_auth) {
|
||||
error = nfs_getauth(nmp, rep, cred, &auth_type,
|
||||
&auth_str, &auth_len);
|
||||
verf_str = nickv;
|
||||
verf_len = sizeof (nickv);
|
||||
auth_type = RPCAUTH_KERB4;
|
||||
bzero((caddr_t)key, sizeof (key));
|
||||
if (failed_auth || nfs_getnickauth(nmp, cred, &auth_str,
|
||||
&auth_len, verf_str, verf_len)) {
|
||||
error = nfs_getauth(nmp, rep, cred, &auth_str,
|
||||
&auth_len, verf_str, &verf_len, key);
|
||||
if (error) {
|
||||
free((caddr_t)rep, M_NFSREQ);
|
||||
m_freem(mrest);
|
||||
return (error);
|
||||
}
|
||||
} else {
|
||||
auth_type = RPCAUTH_UNIX;
|
||||
auth_len = 5 * NFSX_UNSIGNED;
|
||||
}
|
||||
} else {
|
||||
auth_type = RPCAUTH_UNIX;
|
||||
@ -922,8 +912,8 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) +
|
||||
5 * NFSX_UNSIGNED;
|
||||
}
|
||||
m = nfsm_rpchead(cred, (nmp->nm_flag & NFSMNT_NQNFS), procnum,
|
||||
auth_type, auth_len, auth_str, mrest, mrest_len, &mheadend, &xid);
|
||||
m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len,
|
||||
auth_str, verf_len, verf_str, mrest, mrest_len, &mheadend, &xid);
|
||||
if (auth_str)
|
||||
free(auth_str, M_TEMP);
|
||||
|
||||
@ -1029,12 +1019,12 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
/*
|
||||
* break down the rpc header and check if ok
|
||||
*/
|
||||
nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
|
||||
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
if (*tl++ == rpc_msgdenied) {
|
||||
if (*tl == rpc_mismatch)
|
||||
error = EOPNOTSUPP;
|
||||
else if ((nmp->nm_flag & NFSMNT_KERB) && *tl++ == rpc_autherr) {
|
||||
if (*tl == rpc_rejectedcred && failed_auth == 0) {
|
||||
if (!failed_auth) {
|
||||
failed_auth++;
|
||||
mheadend->m_next = (struct mbuf *)0;
|
||||
m_freem(mrep);
|
||||
@ -1051,22 +1041,25 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
}
|
||||
|
||||
/*
|
||||
* skip over the auth_verf, someday we may want to cache auth_short's
|
||||
* for nfs_reqhead(), but for now just dump it
|
||||
* Grab any Kerberos verifier, otherwise just throw it away.
|
||||
*/
|
||||
if (*++tl != 0) {
|
||||
i = nfsm_rndup(fxdr_unsigned(long, *tl));
|
||||
nfsm_adv(i);
|
||||
}
|
||||
verf_type = fxdr_unsigned(int, *tl++);
|
||||
i = fxdr_unsigned(int, *tl);
|
||||
if ((nmp->nm_flag & NFSMNT_KERB) && verf_type == RPCAUTH_KERB4) {
|
||||
error = nfs_savenickauth(nmp, cred, i, key, &md, &dpos, mrep);
|
||||
if (error)
|
||||
goto nfsmout;
|
||||
} else if (i > 0)
|
||||
nfsm_adv(nfsm_rndup(i));
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
|
||||
/* 0 == ok */
|
||||
if (*tl == 0) {
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
|
||||
if (*tl != 0) {
|
||||
error = fxdr_unsigned(int, *tl);
|
||||
m_freem(mrep);
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
error == NQNFS_TRYLATER) {
|
||||
if ((nmp->nm_flag & NFSMNT_NFSV3) &&
|
||||
error == NFSERR_TRYLATER) {
|
||||
m_freem(mrep);
|
||||
error = 0;
|
||||
waituntil = time.tv_sec + trylater_delay;
|
||||
while (time.tv_sec < waituntil)
|
||||
@ -1084,6 +1077,13 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
*/
|
||||
if (error == ESTALE)
|
||||
cache_purge(vp);
|
||||
if (nmp->nm_flag & NFSMNT_NFSV3) {
|
||||
*mrp = mrep;
|
||||
*mdp = md;
|
||||
*dposp = dpos;
|
||||
error |= NFSERR_RETERR;
|
||||
} else
|
||||
m_freem(mrep);
|
||||
m_freem(rep->r_mreq);
|
||||
free((caddr_t)rep, M_NFSREQ);
|
||||
return (error);
|
||||
@ -1115,10 +1115,10 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
return (0);
|
||||
}
|
||||
m_freem(mrep);
|
||||
m_freem(rep->r_mreq);
|
||||
free((caddr_t)rep, M_NFSREQ);
|
||||
error = EPROTONOSUPPORT;
|
||||
nfsmout:
|
||||
m_freem(rep->r_mreq);
|
||||
free((caddr_t)rep, M_NFSREQ);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1127,9 +1127,10 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
|
||||
* siz arg. is used to decide if adding a cluster is worthwhile
|
||||
*/
|
||||
int
|
||||
nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
|
||||
nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
|
||||
int siz;
|
||||
struct nfsd *nd;
|
||||
struct nfsrv_descript *nd;
|
||||
struct nfssvc_sock *slp;
|
||||
int err;
|
||||
int cache;
|
||||
u_quad_t *frev;
|
||||
@ -1154,47 +1155,98 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
|
||||
} else
|
||||
mreq->m_data += max_hdr;
|
||||
tl = mtod(mreq, u_long *);
|
||||
mreq->m_len = 6*NFSX_UNSIGNED;
|
||||
bpos = ((caddr_t)tl)+mreq->m_len;
|
||||
mreq->m_len = 6 * NFSX_UNSIGNED;
|
||||
bpos = ((caddr_t)tl) + mreq->m_len;
|
||||
*tl++ = txdr_unsigned(nd->nd_retxid);
|
||||
*tl++ = rpc_reply;
|
||||
if (err == ERPCMISMATCH || err == NQNFS_AUTHERR) {
|
||||
if (err == ERPCMISMATCH || (err & NFSERR_AUTHERR)) {
|
||||
*tl++ = rpc_msgdenied;
|
||||
if (err == NQNFS_AUTHERR) {
|
||||
if (err & NFSERR_AUTHERR) {
|
||||
*tl++ = rpc_autherr;
|
||||
*tl = rpc_rejectedcred;
|
||||
*tl = txdr_unsigned(err & ~NFSERR_AUTHERR);
|
||||
mreq->m_len -= NFSX_UNSIGNED;
|
||||
bpos -= NFSX_UNSIGNED;
|
||||
} else {
|
||||
*tl++ = rpc_mismatch;
|
||||
*tl++ = txdr_unsigned(2);
|
||||
*tl = txdr_unsigned(2);
|
||||
*tl++ = txdr_unsigned(RPC_VER2);
|
||||
*tl = txdr_unsigned(RPC_VER2);
|
||||
}
|
||||
} else {
|
||||
*tl++ = rpc_msgaccepted;
|
||||
*tl++ = 0;
|
||||
*tl++ = 0;
|
||||
|
||||
/*
|
||||
* For Kerberos authentication, we must send the nickname
|
||||
* verifier back, otherwise just RPCAUTH_NULL.
|
||||
*/
|
||||
if (nd->nd_flag & ND_KERBFULL) {
|
||||
register struct nfsuid *nuidp;
|
||||
struct timeval ktvin, ktvout;
|
||||
NFSKERBKEYSCHED_T keys; /* stores key schedule */
|
||||
|
||||
for (nuidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
|
||||
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
|
||||
if (nuidp->nu_cr.cr_uid == nd->nd_cr.cr_uid &&
|
||||
(!nd->nd_nam2 || netaddr_match(NU_NETFAM(nuidp),
|
||||
&nuidp->nu_haddr, nd->nd_nam2)))
|
||||
break;
|
||||
}
|
||||
if (nuidp) {
|
||||
ktvin.tv_sec =
|
||||
txdr_unsigned(nuidp->nu_timestamp.tv_sec - 1);
|
||||
ktvin.tv_usec =
|
||||
txdr_unsigned(nuidp->nu_timestamp.tv_usec);
|
||||
|
||||
/*
|
||||
* Encrypt the timestamp in ecb mode using the
|
||||
* session key.
|
||||
*/
|
||||
#ifdef NFSKERB
|
||||
XXX
|
||||
#endif
|
||||
|
||||
*tl++ = rpc_auth_kerb;
|
||||
*tl++ = txdr_unsigned(3 * NFSX_UNSIGNED);
|
||||
*tl = ktvout.tv_sec;
|
||||
nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
*tl++ = ktvout.tv_usec;
|
||||
*tl++ = txdr_unsigned(nuidp->nu_cr.cr_uid);
|
||||
} else {
|
||||
*tl++ = 0;
|
||||
*tl++ = 0;
|
||||
}
|
||||
} else {
|
||||
*tl++ = 0;
|
||||
*tl++ = 0;
|
||||
}
|
||||
switch (err) {
|
||||
case EPROGUNAVAIL:
|
||||
*tl = txdr_unsigned(RPC_PROGUNAVAIL);
|
||||
break;
|
||||
case EPROGMISMATCH:
|
||||
*tl = txdr_unsigned(RPC_PROGMISMATCH);
|
||||
nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(2);
|
||||
*tl = txdr_unsigned(2); /* someday 3 */
|
||||
nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
|
||||
if (nd->nd_flag & ND_NQNFS) {
|
||||
*tl++ = txdr_unsigned(3);
|
||||
*tl = txdr_unsigned(3);
|
||||
} else {
|
||||
*tl++ = txdr_unsigned(2);
|
||||
*tl = txdr_unsigned(3);
|
||||
}
|
||||
break;
|
||||
case EPROCUNAVAIL:
|
||||
*tl = txdr_unsigned(RPC_PROCUNAVAIL);
|
||||
break;
|
||||
case EBADRPC:
|
||||
*tl = txdr_unsigned(RPC_GARBAGE);
|
||||
break;
|
||||
default:
|
||||
*tl = 0;
|
||||
if (err != VNOVAL) {
|
||||
if (err != NFSERR_RETVOID) {
|
||||
nfsm_build(tl, u_long *, NFSX_UNSIGNED);
|
||||
if (err)
|
||||
*tl = txdr_unsigned(nfsrv_errmap[err - 1]);
|
||||
*tl = txdr_unsigned(nfsrv_errmap(nd, err));
|
||||
else
|
||||
*tl = 0;
|
||||
*tl = 0;
|
||||
}
|
||||
break;
|
||||
};
|
||||
@ -1203,16 +1255,14 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
|
||||
/*
|
||||
* For nqnfs, piggyback lease as requested.
|
||||
*/
|
||||
if (nd->nd_nqlflag != NQL_NOVAL && err == 0) {
|
||||
if (nd->nd_nqlflag) {
|
||||
nfsm_build(tl, u_long *, 5*NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(nd->nd_nqlflag);
|
||||
if ((nd->nd_flag & ND_NQNFS) && err == 0) {
|
||||
if (nd->nd_flag & ND_LEASE) {
|
||||
nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(nd->nd_flag & ND_LEASE);
|
||||
*tl++ = txdr_unsigned(cache);
|
||||
*tl++ = txdr_unsigned(nd->nd_duration);
|
||||
txdr_hyper(frev, tl);
|
||||
} else {
|
||||
if (nd->nd_nqlflag != 0)
|
||||
panic("nqreph");
|
||||
nfsm_build(tl, u_long *, NFSX_UNSIGNED);
|
||||
*tl = 0;
|
||||
}
|
||||
@ -1220,7 +1270,7 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
|
||||
*mrq = mreq;
|
||||
*mbp = mb;
|
||||
*bposp = bpos;
|
||||
if (err != 0 && err != VNOVAL)
|
||||
if (err != 0 && err != NFSERR_RETVOID)
|
||||
nfsstats.srvrpc_errs++;
|
||||
return (0);
|
||||
}
|
||||
@ -1240,8 +1290,10 @@ nfs_timer(arg)
|
||||
register struct socket *so;
|
||||
register struct nfsmount *nmp;
|
||||
register int timeo;
|
||||
register struct nfssvc_sock *slp;
|
||||
static long lasttime = 0;
|
||||
int s, error;
|
||||
u_quad_t cur_usec;
|
||||
|
||||
s = splnet();
|
||||
for (rep = nfs_reqq.tqh_first; rep != 0; rep = rep->r_chain.tqe_next) {
|
||||
@ -1338,8 +1390,19 @@ nfs_timer(arg)
|
||||
lasttime = time.tv_sec;
|
||||
nqnfs_serverd();
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the write gathering queues for writes that need to be
|
||||
* completed now.
|
||||
*/
|
||||
cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
|
||||
for (slp = nfssvc_sockhead.tqh_first; slp != 0;
|
||||
slp = slp->ns_chain.tqe_next) {
|
||||
if (slp->ns_tq.lh_first && slp->ns_tq.lh_first->nd_time<=cur_usec)
|
||||
nfsrv_wakenfsd(slp);
|
||||
}
|
||||
splx(s);
|
||||
timeout(nfs_timer, (void *)0, hz / NFS_HZ);
|
||||
timeout(nfs_timer, (void *)0, nfs_ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1673,7 +1736,7 @@ nfsrv_getstream(slp, waitflag)
|
||||
register struct nfssvc_sock *slp;
|
||||
int waitflag;
|
||||
{
|
||||
register struct mbuf *m;
|
||||
register struct mbuf *m, **mpp;
|
||||
register char *cp1, *cp2;
|
||||
register int len;
|
||||
struct mbuf *om, *m2, *recm = 0;
|
||||
@ -1707,7 +1770,12 @@ nfsrv_getstream(slp, waitflag)
|
||||
}
|
||||
}
|
||||
slp->ns_cc -= NFSX_UNSIGNED;
|
||||
slp->ns_reclen = ntohl(recmark) & ~0x80000000;
|
||||
recmark = ntohl(recmark);
|
||||
slp->ns_reclen = recmark & ~0x80000000;
|
||||
if (recmark & 0x80000000)
|
||||
slp->ns_flag |= SLP_LASTFRAG;
|
||||
else
|
||||
slp->ns_flag &= ~SLP_LASTFRAG;
|
||||
if (slp->ns_reclen < NFS_MINPACKET || slp->ns_reclen > NFS_MAXPACKET) {
|
||||
slp->ns_flag &= ~SLP_GETSTREAM;
|
||||
return (EPERM);
|
||||
@ -1761,12 +1829,23 @@ nfsrv_getstream(slp, waitflag)
|
||||
slp->ns_flag &= ~SLP_GETSTREAM;
|
||||
return (0);
|
||||
}
|
||||
nfs_realign(recm, 10 * NFSX_UNSIGNED);
|
||||
if (slp->ns_recend)
|
||||
slp->ns_recend->m_nextpkt = recm;
|
||||
else
|
||||
slp->ns_rec = recm;
|
||||
slp->ns_recend = recm;
|
||||
|
||||
/*
|
||||
* Accumulate the fragments into a record.
|
||||
*/
|
||||
mpp = &slp->ns_frag;
|
||||
while (*mpp)
|
||||
mpp = &((*mpp)->m_next);
|
||||
*mpp = recm;
|
||||
if (slp->ns_flag & SLP_LASTFRAG) {
|
||||
nfs_realign(slp->ns_frag, 10 * NFSX_UNSIGNED);
|
||||
if (slp->ns_recend)
|
||||
slp->ns_recend->m_nextpkt = slp->ns_frag;
|
||||
else
|
||||
slp->ns_rec = slp->ns_frag;
|
||||
slp->ns_recend = slp->ns_frag;
|
||||
slp->ns_frag = (struct mbuf *)0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1774,13 +1853,16 @@ nfsrv_getstream(slp, waitflag)
|
||||
* Parse an RPC header.
|
||||
*/
|
||||
int
|
||||
nfsrv_dorec(slp, nd)
|
||||
nfsrv_dorec(slp, nfsd, ndp)
|
||||
register struct nfssvc_sock *slp;
|
||||
register struct nfsd *nd;
|
||||
struct nfsd *nfsd;
|
||||
struct nfsrv_descript **ndp;
|
||||
{
|
||||
register struct mbuf *m;
|
||||
register struct mbuf *m, *nam;
|
||||
register struct nfsrv_descript *nd;
|
||||
int error;
|
||||
|
||||
*ndp = NULL;
|
||||
if ((slp->ns_flag & SLP_VALID) == 0 ||
|
||||
(m = slp->ns_rec) == (struct mbuf *)0)
|
||||
return (ENOBUFS);
|
||||
@ -1790,19 +1872,24 @@ nfsrv_dorec(slp, nd)
|
||||
else
|
||||
slp->ns_recend = (struct mbuf *)0;
|
||||
if (m->m_type == MT_SONAME) {
|
||||
nd->nd_nam = m;
|
||||
nd->nd_md = nd->nd_mrep = m->m_next;
|
||||
m->m_next = (struct mbuf *)0;
|
||||
} else {
|
||||
nd->nd_nam = (struct mbuf *)0;
|
||||
nd->nd_md = nd->nd_mrep = m;
|
||||
}
|
||||
nd->nd_dpos = mtod(nd->nd_md, caddr_t);
|
||||
error = nfs_getreq(nd, TRUE);
|
||||
nam = m;
|
||||
m = m->m_next;
|
||||
nam->m_next = NULL;
|
||||
} else
|
||||
nam = NULL;
|
||||
MALLOC(nd, struct nfsrv_descript *, sizeof (struct nfsrv_descript),
|
||||
M_NFSRVDESC, M_WAITOK);
|
||||
nd->nd_md = nd->nd_mrep = m;
|
||||
nd->nd_nam2 = nam;
|
||||
nd->nd_dpos = mtod(m, caddr_t);
|
||||
error = nfs_getreq(nd, nfsd, TRUE);
|
||||
if (error) {
|
||||
m_freem(nd->nd_nam);
|
||||
m_freem(nam);
|
||||
free((caddr_t)nd, M_NFSRVDESC);
|
||||
return (error);
|
||||
}
|
||||
*ndp = nd;
|
||||
nfsd->nfsd_nd = nd;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1812,8 +1899,9 @@ nfsrv_dorec(slp, nd)
|
||||
* - fill in the cred struct.
|
||||
*/
|
||||
int
|
||||
nfs_getreq(nd, has_header)
|
||||
register struct nfsd *nd;
|
||||
nfs_getreq(nd, nfsd, has_header)
|
||||
register struct nfsrv_descript *nd;
|
||||
struct nfsd *nfsd;
|
||||
int has_header;
|
||||
{
|
||||
register int len, i;
|
||||
@ -1821,57 +1909,67 @@ nfs_getreq(nd, has_header)
|
||||
register long t1;
|
||||
struct uio uio;
|
||||
struct iovec iov;
|
||||
caddr_t dpos, cp2;
|
||||
caddr_t dpos, cp2, cp;
|
||||
u_long nfsvers, auth_type;
|
||||
int error = 0, nqnfs = 0;
|
||||
uid_t nickuid;
|
||||
int error = 0, nqnfs = 0, ticklen;
|
||||
struct mbuf *mrep, *md;
|
||||
register struct nfsuid *nuidp;
|
||||
struct timeval tvin, tvout;
|
||||
NFSKERBKEYSCHED_T keys; /* stores key schedule */
|
||||
|
||||
mrep = nd->nd_mrep;
|
||||
md = nd->nd_md;
|
||||
dpos = nd->nd_dpos;
|
||||
if (has_header) {
|
||||
nfsm_dissect(tl, u_long *, 10*NFSX_UNSIGNED);
|
||||
nfsm_dissect(tl, u_long *, 10 * NFSX_UNSIGNED);
|
||||
nd->nd_retxid = fxdr_unsigned(u_long, *tl++);
|
||||
if (*tl++ != rpc_call) {
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
} else {
|
||||
nfsm_dissect(tl, u_long *, 8*NFSX_UNSIGNED);
|
||||
}
|
||||
} else
|
||||
nfsm_dissect(tl, u_long *, 8 * NFSX_UNSIGNED);
|
||||
nd->nd_repstat = 0;
|
||||
nd->nd_flag = 0;
|
||||
if (*tl++ != rpc_vers) {
|
||||
nd->nd_repstat = ERPCMISMATCH;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nfsvers = nfs_vers;
|
||||
if (*tl != nfs_prog) {
|
||||
if (*tl == nqnfs_prog) {
|
||||
if (*tl == nqnfs_prog)
|
||||
nqnfs++;
|
||||
nfsvers = nqnfs_vers;
|
||||
} else {
|
||||
else {
|
||||
nd->nd_repstat = EPROGUNAVAIL;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
tl++;
|
||||
if (*tl++ != nfsvers) {
|
||||
nfsvers = fxdr_unsigned(u_long, *tl++);
|
||||
if (((nfsvers < NFS_VER2 || nfsvers > NFS_VER3) && !nqnfs) ||
|
||||
(nfsvers != NQNFS_VER3 && nqnfs)) {
|
||||
nd->nd_repstat = EPROGMISMATCH;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
if (nqnfs)
|
||||
nd->nd_flag = (ND_NFSV3 | ND_NQNFS);
|
||||
else if (nfsvers == NFS_VER3)
|
||||
nd->nd_flag = ND_NFSV3;
|
||||
nd->nd_procnum = fxdr_unsigned(u_long, *tl++);
|
||||
if (nd->nd_procnum == NFSPROC_NULL)
|
||||
return (0);
|
||||
if (nd->nd_procnum >= NFS_NPROCS ||
|
||||
(!nqnfs && nd->nd_procnum > NFSPROC_STATFS) ||
|
||||
(*tl != rpc_auth_unix && *tl != rpc_auth_kerb)) {
|
||||
(!nqnfs && nd->nd_procnum >= NQNFSPROC_GETLEASE) ||
|
||||
(!nd->nd_flag && nd->nd_procnum > NFSV2PROC_STATFS)) {
|
||||
nd->nd_repstat = EPROCUNAVAIL;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
if ((nd->nd_flag & ND_NFSV3) == 0)
|
||||
nd->nd_procnum = nfsv3_procid[nd->nd_procnum];
|
||||
auth_type = *tl++;
|
||||
len = fxdr_unsigned(int, *tl++);
|
||||
if (len < 0 || len > RPCAUTH_MAXSIZ) {
|
||||
@ -1879,6 +1977,7 @@ nfs_getreq(nd, has_header)
|
||||
return (EBADRPC);
|
||||
}
|
||||
|
||||
nd->nd_flag &= ~ND_KERBAUTH;
|
||||
/*
|
||||
* Handle auth_unix or auth_kerb.
|
||||
*/
|
||||
@ -1889,7 +1988,9 @@ nfs_getreq(nd, has_header)
|
||||
return (EBADRPC);
|
||||
}
|
||||
nfsm_adv(nfsm_rndup(len));
|
||||
nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
|
||||
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
bzero((caddr_t)&nd->nd_cr, sizeof (struct ucred));
|
||||
nd->nd_cr.cr_ref = 1;
|
||||
nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
|
||||
nd->nd_cr.cr_gid = fxdr_unsigned(gid_t, *tl++);
|
||||
len = fxdr_unsigned(int, *tl);
|
||||
@ -1897,45 +1998,124 @@ nfs_getreq(nd, has_header)
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
nfsm_dissect(tl, u_long *, (len + 2)*NFSX_UNSIGNED);
|
||||
nfsm_dissect(tl, u_long *, (len + 2) * NFSX_UNSIGNED);
|
||||
for (i = 1; i <= len; i++)
|
||||
if (i < NGROUPS)
|
||||
nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
|
||||
else
|
||||
tl++;
|
||||
if (i < NGROUPS)
|
||||
nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
|
||||
else
|
||||
tl++;
|
||||
nd->nd_cr.cr_ngroups = (len >= NGROUPS) ? NGROUPS : (len + 1);
|
||||
} else if (auth_type == rpc_auth_kerb) {
|
||||
nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
|
||||
nd->nd_authlen = fxdr_unsigned(int, *tl);
|
||||
uio.uio_resid = nfsm_rndup(nd->nd_authlen);
|
||||
if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
|
||||
if (nd->nd_cr.cr_ngroups > 1)
|
||||
nfsrvw_sort(nd->nd_cr.cr_groups, nd->nd_cr.cr_ngroups);
|
||||
len = fxdr_unsigned(int, *++tl);
|
||||
if (len < 0 || len > RPCAUTH_MAXSIZ) {
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
uio.uio_offset = 0;
|
||||
uio.uio_iov = &iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
uio.uio_segflg = UIO_SYSSPACE;
|
||||
iov.iov_base = (caddr_t)nd->nd_authstr;
|
||||
iov.iov_len = RPCAUTH_MAXSIZ;
|
||||
nfsm_mtouio(&uio, uio.uio_resid);
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
|
||||
nd->nd_flag |= NFSD_NEEDAUTH;
|
||||
}
|
||||
if (len > 0)
|
||||
nfsm_adv(nfsm_rndup(len));
|
||||
} else if (auth_type == rpc_auth_kerb) {
|
||||
switch (fxdr_unsigned(int, *tl++)) {
|
||||
case RPCAKN_FULLNAME:
|
||||
ticklen = fxdr_unsigned(int, *tl);
|
||||
*((u_long *)nfsd->nfsd_authstr) = *tl;
|
||||
uio.uio_resid = nfsm_rndup(ticklen) + NFSX_UNSIGNED;
|
||||
nfsd->nfsd_authlen = uio.uio_resid + NFSX_UNSIGNED;
|
||||
if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
uio.uio_offset = 0;
|
||||
uio.uio_iov = &iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
uio.uio_segflg = UIO_SYSSPACE;
|
||||
iov.iov_base = (caddr_t)&nfsd->nfsd_authstr[4];
|
||||
iov.iov_len = RPCAUTH_MAXSIZ - 4;
|
||||
nfsm_mtouio(&uio, uio.uio_resid);
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
|
||||
if (*tl++ != rpc_auth_kerb ||
|
||||
fxdr_unsigned(int, *tl) != 4 * NFSX_UNSIGNED) {
|
||||
printf("Bad kerb verifier\n");
|
||||
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nfsm_dissect(cp, caddr_t, 4 * NFSX_UNSIGNED);
|
||||
tl = (u_long *)cp;
|
||||
if (fxdr_unsigned(int, *tl) != RPCAKN_FULLNAME) {
|
||||
printf("Not fullname kerb verifier\n");
|
||||
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
cp += NFSX_UNSIGNED;
|
||||
bcopy(cp, nfsd->nfsd_verfstr, 3 * NFSX_UNSIGNED);
|
||||
nfsd->nfsd_verflen = 3 * NFSX_UNSIGNED;
|
||||
nd->nd_flag |= ND_KERBFULL;
|
||||
nfsd->nfsd_flag |= NFSD_NEEDAUTH;
|
||||
break;
|
||||
case RPCAKN_NICKNAME:
|
||||
if (len != 2 * NFSX_UNSIGNED) {
|
||||
printf("Kerb nickname short\n");
|
||||
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADCRED);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nickuid = fxdr_unsigned(uid_t, *tl);
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
|
||||
if (*tl++ != rpc_auth_kerb ||
|
||||
fxdr_unsigned(int, *tl) != 3 * NFSX_UNSIGNED) {
|
||||
printf("Kerb nick verifier bad\n");
|
||||
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
tvin.tv_sec = *tl++;
|
||||
tvin.tv_usec = *tl;
|
||||
|
||||
/*
|
||||
* Do we have any use for the verifier.
|
||||
* According to the "Remote Procedure Call Protocol Spec." it
|
||||
* should be AUTH_NULL, but some clients make it AUTH_UNIX?
|
||||
* For now, just skip over it
|
||||
*/
|
||||
len = fxdr_unsigned(int, *++tl);
|
||||
if (len < 0 || len > RPCAUTH_MAXSIZ) {
|
||||
m_freem(mrep);
|
||||
return (EBADRPC);
|
||||
}
|
||||
if (len > 0) {
|
||||
nfsm_adv(nfsm_rndup(len));
|
||||
for (nuidp = NUIDHASH(nfsd->nfsd_slp,nickuid)->lh_first;
|
||||
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
|
||||
if (nuidp->nu_cr.cr_uid == nickuid &&
|
||||
(!nd->nd_nam2 ||
|
||||
netaddr_match(NU_NETFAM(nuidp),
|
||||
&nuidp->nu_haddr, nd->nd_nam2)))
|
||||
break;
|
||||
}
|
||||
if (!nuidp) {
|
||||
nd->nd_repstat =
|
||||
(NFSERR_AUTHERR|AUTH_REJECTCRED);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, decrypt the timestamp using the session key
|
||||
* and validate it.
|
||||
*/
|
||||
#ifdef NFSKERB
|
||||
XXX
|
||||
#endif
|
||||
|
||||
tvout.tv_sec = fxdr_unsigned(long, tvout.tv_sec);
|
||||
tvout.tv_usec = fxdr_unsigned(long, tvout.tv_usec);
|
||||
if (nuidp->nu_expire < time.tv_sec ||
|
||||
nuidp->nu_timestamp.tv_sec > tvout.tv_sec ||
|
||||
(nuidp->nu_timestamp.tv_sec == tvout.tv_sec &&
|
||||
nuidp->nu_timestamp.tv_usec > tvout.tv_usec)) {
|
||||
nuidp->nu_expire = 0;
|
||||
nd->nd_repstat =
|
||||
(NFSERR_AUTHERR|AUTH_REJECTVERF);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
nfsrv_setcred(&nuidp->nu_cr, &nd->nd_cr);
|
||||
nd->nd_flag |= ND_KERBNICK;
|
||||
};
|
||||
} else {
|
||||
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_REJECTCRED);
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1943,16 +2123,14 @@ nfs_getreq(nd, has_header)
|
||||
*/
|
||||
if (nqnfs && nd->nd_procnum != NQNFSPROC_EVICTED) {
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
|
||||
nd->nd_nqlflag = fxdr_unsigned(int, *tl);
|
||||
if (nd->nd_nqlflag) {
|
||||
nd->nd_flag |= fxdr_unsigned(int, *tl);
|
||||
if (nd->nd_flag & ND_LEASE) {
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
|
||||
nd->nd_duration = fxdr_unsigned(int, *tl);
|
||||
} else
|
||||
nd->nd_duration = NQ_MINLEASE;
|
||||
} else {
|
||||
nd->nd_nqlflag = NQL_NOVAL;
|
||||
} else
|
||||
nd->nd_duration = NQ_MINLEASE;
|
||||
}
|
||||
nd->nd_md = md;
|
||||
nd->nd_dpos = dpos;
|
||||
return (0);
|
||||
@ -1973,13 +2151,13 @@ nfsrv_wakenfsd(slp)
|
||||
|
||||
if ((slp->ns_flag & SLP_VALID) == 0)
|
||||
return;
|
||||
for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nd_chain.tqe_next) {
|
||||
if (nd->nd_flag & NFSD_WAITING) {
|
||||
nd->nd_flag &= ~NFSD_WAITING;
|
||||
if (nd->nd_slp)
|
||||
for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nfsd_chain.tqe_next) {
|
||||
if (nd->nfsd_flag & NFSD_WAITING) {
|
||||
nd->nfsd_flag &= ~NFSD_WAITING;
|
||||
if (nd->nfsd_slp)
|
||||
panic("nfsd wakeup");
|
||||
slp->ns_sref++;
|
||||
nd->nd_slp = slp;
|
||||
nd->nfsd_slp = slp;
|
||||
wakeup((caddr_t)nd);
|
||||
return;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_syscalls.c 8.3 (Berkeley) 1/4/94
|
||||
* $Id: nfs_syscalls.c,v 1.5 1994/10/17 17:47:38 phk Exp $
|
||||
* $Id: nfs_syscalls.c,v 1.6 1995/05/30 08:12:45 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -61,9 +61,11 @@
|
||||
#ifdef ISO
|
||||
#include <netiso/iso.h>
|
||||
#endif
|
||||
#include <nfs/xdr_subs.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsm_subs.h>
|
||||
#include <nfs/nfsrvcache.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
@ -73,13 +75,14 @@
|
||||
void nfsrv_zapsock __P((struct nfssvc_sock *));
|
||||
|
||||
/* Global defs. */
|
||||
extern u_long nfs_prog, nfs_vers;
|
||||
extern int (*nfsrv_procs[NFS_NPROCS])();
|
||||
extern int (*nfsrv3_procs[NFS_NPROCS])();
|
||||
extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
|
||||
extern int nfs_numasync;
|
||||
extern time_t nqnfsstarttime;
|
||||
extern int nqsrv_writeslack;
|
||||
extern int nfsrtton;
|
||||
extern struct nfsstats nfsstats;
|
||||
extern int nfsrvw_procrastinate;
|
||||
struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock;
|
||||
int nuidhash_max = NFS_MAXUIDHASH;
|
||||
static int nfs_numnfsd = 0;
|
||||
@ -225,19 +228,25 @@ nfssvc(p, uap, retval)
|
||||
if (error)
|
||||
return (error);
|
||||
if ((uap->flag & NFSSVC_AUTHIN) && ((nfsd = nsd->nsd_nfsd)) &&
|
||||
(nfsd->nd_slp->ns_flag & SLP_VALID)) {
|
||||
slp = nfsd->nd_slp;
|
||||
(nfsd->nfsd_slp->ns_flag & SLP_VALID)) {
|
||||
slp = nfsd->nfsd_slp;
|
||||
|
||||
/*
|
||||
* First check to see if another nfsd has already
|
||||
* added this credential.
|
||||
*/
|
||||
for (nuidp = NUIDHASH(slp, nsd->nsd_uid)->lh_first;
|
||||
for (nuidp = NUIDHASH(slp,nsd->nsd_cr.cr_uid)->lh_first;
|
||||
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
|
||||
if (nuidp->nu_uid == nsd->nsd_uid)
|
||||
if (nuidp->nu_cr.cr_uid == nsd->nsd_cr.cr_uid &&
|
||||
(!nfsd->nfsd_nd->nd_nam2 ||
|
||||
netaddr_match(NU_NETFAM(nuidp),
|
||||
&nuidp->nu_haddr, nfsd->nfsd_nd->nd_nam2)))
|
||||
break;
|
||||
}
|
||||
if (!nuidp) {
|
||||
if (nuidp) {
|
||||
nfsrv_setcred(&nuidp->nu_cr,&nfsd->nfsd_nd->nd_cr);
|
||||
nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
|
||||
} else {
|
||||
/*
|
||||
* Nope, so we will.
|
||||
*/
|
||||
@ -257,22 +266,53 @@ nfssvc(p, uap, retval)
|
||||
LIST_REMOVE(nuidp, nu_hash);
|
||||
TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp,
|
||||
nu_lru);
|
||||
if (nuidp->nu_flag & NU_NAM)
|
||||
m_freem(nuidp->nu_nam);
|
||||
}
|
||||
nuidp->nu_flag = 0;
|
||||
nuidp->nu_cr = nsd->nsd_cr;
|
||||
if (nuidp->nu_cr.cr_ngroups > NGROUPS)
|
||||
nuidp->nu_cr.cr_ngroups = NGROUPS;
|
||||
nuidp->nu_cr.cr_ngroups = NGROUPS;
|
||||
nuidp->nu_cr.cr_ref = 1;
|
||||
nuidp->nu_uid = nsd->nsd_uid;
|
||||
nuidp->nu_timestamp = nsd->nsd_timestamp;
|
||||
nuidp->nu_expire = time.tv_sec + nsd->nsd_ttl;
|
||||
/*
|
||||
* and save the session key in nu_key.
|
||||
*/
|
||||
bcopy(nsd->nsd_key, nuidp->nu_key,
|
||||
sizeof (nsd->nsd_key));
|
||||
if (nfsd->nfsd_nd->nd_nam2) {
|
||||
struct sockaddr_in *saddr;
|
||||
|
||||
saddr = mtod(nfsd->nfsd_nd->nd_nam2,
|
||||
struct sockaddr_in *);
|
||||
switch (saddr->sin_family) {
|
||||
case AF_INET:
|
||||
nuidp->nu_flag |= NU_INETADDR;
|
||||
nuidp->nu_inetaddr =
|
||||
saddr->sin_addr.s_addr;
|
||||
break;
|
||||
case AF_ISO:
|
||||
default:
|
||||
nuidp->nu_flag |= NU_NAM;
|
||||
nuidp->nu_nam = m_copym(
|
||||
nfsd->nfsd_nd->nd_nam2, 0,
|
||||
M_COPYALL, M_WAIT);
|
||||
break;
|
||||
};
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&slp->ns_uidlruhead, nuidp,
|
||||
nu_lru);
|
||||
LIST_INSERT_HEAD(NUIDHASH(slp, nsd->nsd_uid),
|
||||
nuidp, nu_hash);
|
||||
|
||||
nfsrv_setcred(&nuidp->nu_cr,
|
||||
&nfsd->nfsd_nd->nd_cr);
|
||||
nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd))
|
||||
nfsd->nd_flag |= NFSD_AUTHFAIL;
|
||||
nfsd->nfsd_flag |= NFSD_AUTHFAIL;
|
||||
error = nfssvc_nfsd(nsd, uap->argp, p);
|
||||
}
|
||||
if (error == EINTR || error == ERESTART)
|
||||
@ -353,8 +393,6 @@ nfssvc_addsock(fp, mynam)
|
||||
slp = (struct nfssvc_sock *)
|
||||
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
|
||||
bzero((caddr_t)slp, sizeof (struct nfssvc_sock));
|
||||
slp->ns_uidhashtbl =
|
||||
hashinit(NUIDHASHSIZ, M_NFSSVC, &slp->ns_uidhash);
|
||||
TAILQ_INIT(&slp->ns_uidlruhead);
|
||||
TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain);
|
||||
}
|
||||
@ -381,44 +419,47 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
caddr_t argp;
|
||||
struct proc *p;
|
||||
{
|
||||
register struct mbuf *m, *nam2;
|
||||
register struct mbuf *m;
|
||||
register int siz;
|
||||
register struct nfssvc_sock *slp;
|
||||
register struct socket *so;
|
||||
register int *solockp;
|
||||
struct nfsd *nd = nsd->nsd_nfsd;
|
||||
struct mbuf *mreq, *nam;
|
||||
struct timeval starttime;
|
||||
struct nfsd *nfsd = nsd->nsd_nfsd;
|
||||
struct nfsrv_descript *nd = NULL;
|
||||
struct mbuf *mreq;
|
||||
struct nfsuid *uidp;
|
||||
int error = 0, cacherep, s;
|
||||
int sotype;
|
||||
int error = 0, cacherep, s, sotype, writes_todo;
|
||||
u_quad_t cur_usec;
|
||||
|
||||
#ifndef nolint
|
||||
cacherep = RC_DOIT;
|
||||
writes_todo = 0;
|
||||
#endif
|
||||
s = splnet();
|
||||
if (nd == (struct nfsd *)0) {
|
||||
nsd->nsd_nfsd = nd = (struct nfsd *)
|
||||
if (nfsd == (struct nfsd *)0) {
|
||||
nsd->nsd_nfsd = nfsd = (struct nfsd *)
|
||||
malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK);
|
||||
bzero((caddr_t)nd, sizeof (struct nfsd));
|
||||
nd->nd_procp = p;
|
||||
nd->nd_cr.cr_ref = 1;
|
||||
TAILQ_INSERT_TAIL(&nfsd_head, nd, nd_chain);
|
||||
nd->nd_nqlflag = NQL_NOVAL;
|
||||
bzero((caddr_t)nfsd, sizeof (struct nfsd));
|
||||
nfsd->nfsd_procp = p;
|
||||
TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain);
|
||||
nfs_numnfsd++;
|
||||
}
|
||||
/*
|
||||
* Loop getting rpc requests until SIGKILL.
|
||||
*/
|
||||
for (;;) {
|
||||
if ((nd->nd_flag & NFSD_REQINPROG) == 0) {
|
||||
while (nd->nd_slp == (struct nfssvc_sock *)0 &&
|
||||
if ((nfsd->nfsd_flag & NFSD_REQINPROG) == 0) {
|
||||
while (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
|
||||
(nfsd_head_flag & NFSD_CHECKSLP) == 0) {
|
||||
nd->nd_flag |= NFSD_WAITING;
|
||||
nfsd->nfsd_flag |= NFSD_WAITING;
|
||||
nfsd_waiting++;
|
||||
error = tsleep((caddr_t)nd, PSOCK | PCATCH, "nfsd", 0);
|
||||
error = tsleep((caddr_t)nfsd, PSOCK | PCATCH,
|
||||
"nfsd", 0);
|
||||
nfsd_waiting--;
|
||||
if (error)
|
||||
goto done;
|
||||
}
|
||||
if (nd->nd_slp == (struct nfssvc_sock *)0 &&
|
||||
if (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
|
||||
(nfsd_head_flag & NFSD_CHECKSLP) != 0) {
|
||||
for (slp = nfssvc_sockhead.tqh_first; slp != 0;
|
||||
slp = slp->ns_chain.tqe_next) {
|
||||
@ -426,14 +467,14 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
== (SLP_VALID | SLP_DOREC)) {
|
||||
slp->ns_flag &= ~SLP_DOREC;
|
||||
slp->ns_sref++;
|
||||
nd->nd_slp = slp;
|
||||
nfsd->nfsd_slp = slp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (slp == 0)
|
||||
nfsd_head_flag &= ~NFSD_CHECKSLP;
|
||||
}
|
||||
if ((slp = nd->nd_slp) == (struct nfssvc_sock *)0)
|
||||
if ((slp = nfsd->nfsd_slp) == (struct nfssvc_sock *)0)
|
||||
continue;
|
||||
if (slp->ns_flag & SLP_VALID) {
|
||||
if (slp->ns_flag & SLP_DISCONN)
|
||||
@ -446,86 +487,78 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
M_WAIT);
|
||||
nfs_sndunlock(&slp->ns_solock);
|
||||
}
|
||||
error = nfsrv_dorec(slp, nd);
|
||||
nd->nd_flag |= NFSD_REQINPROG;
|
||||
error = nfsrv_dorec(slp, nfsd, &nd);
|
||||
cur_usec = (u_quad_t)time.tv_sec * 1000000 +
|
||||
(u_quad_t)time.tv_usec;
|
||||
if (error && slp->ns_tq.lh_first &&
|
||||
slp->ns_tq.lh_first->nd_time <= cur_usec) {
|
||||
error = 0;
|
||||
cacherep = RC_DOIT;
|
||||
writes_todo = 1;
|
||||
} else
|
||||
writes_todo = 0;
|
||||
nfsd->nfsd_flag |= NFSD_REQINPROG;
|
||||
}
|
||||
} else {
|
||||
error = 0;
|
||||
slp = nd->nd_slp;
|
||||
slp = nfsd->nfsd_slp;
|
||||
}
|
||||
if (error || (slp->ns_flag & SLP_VALID) == 0) {
|
||||
nd->nd_slp = (struct nfssvc_sock *)0;
|
||||
nd->nd_flag &= ~NFSD_REQINPROG;
|
||||
if (nd) {
|
||||
free((caddr_t)nd, M_NFSRVDESC);
|
||||
nd = NULL;
|
||||
}
|
||||
nfsd->nfsd_slp = (struct nfssvc_sock *)0;
|
||||
nfsd->nfsd_flag &= ~NFSD_REQINPROG;
|
||||
nfsrv_slpderef(slp);
|
||||
continue;
|
||||
}
|
||||
splx(s);
|
||||
so = slp->ns_so;
|
||||
sotype = so->so_type;
|
||||
starttime = time;
|
||||
if (so->so_proto->pr_flags & PR_CONNREQUIRED)
|
||||
solockp = &slp->ns_solock;
|
||||
else
|
||||
solockp = (int *)0;
|
||||
/*
|
||||
* nam == nam2 for connectionless protocols such as UDP
|
||||
* nam2 == NULL for connection based protocols to disable
|
||||
* recent request caching.
|
||||
*/
|
||||
nam2 = nd->nd_nam;
|
||||
if (nam2) {
|
||||
nam = nam2;
|
||||
cacherep = RC_CHECKIT;
|
||||
} else {
|
||||
nam = slp->ns_nam;
|
||||
cacherep = RC_DOIT;
|
||||
}
|
||||
if (nd) {
|
||||
nd->nd_starttime = time;
|
||||
if (nd->nd_nam2)
|
||||
nd->nd_nam = nd->nd_nam2;
|
||||
else
|
||||
nd->nd_nam = slp->ns_nam;
|
||||
|
||||
/*
|
||||
* Check to see if authorization is needed.
|
||||
*/
|
||||
if (nd->nd_flag & NFSD_NEEDAUTH) {
|
||||
static int logauth = 0;
|
||||
/*
|
||||
* Check to see if authorization is needed.
|
||||
*/
|
||||
if (nfsd->nfsd_flag & NFSD_NEEDAUTH) {
|
||||
nfsd->nfsd_flag &= ~NFSD_NEEDAUTH;
|
||||
nsd->nsd_haddr = mtod(nd->nd_nam,
|
||||
struct sockaddr_in *)->sin_addr.s_addr;
|
||||
nsd->nsd_authlen = nfsd->nfsd_authlen;
|
||||
nsd->nsd_verflen = nfsd->nfsd_verflen;
|
||||
if (!copyout(nfsd->nfsd_authstr,nsd->nsd_authstr,
|
||||
nfsd->nfsd_authlen) &&
|
||||
!copyout(nfsd->nfsd_verfstr, nsd->nsd_verfstr,
|
||||
nfsd->nfsd_verflen) &&
|
||||
!copyout((caddr_t)nsd, argp, sizeof (*nsd)))
|
||||
return (ENEEDAUTH);
|
||||
cacherep = RC_DROPIT;
|
||||
} else
|
||||
cacherep = nfsrv_getcache(nd, slp, &mreq);
|
||||
|
||||
nd->nd_flag &= ~NFSD_NEEDAUTH;
|
||||
/*
|
||||
* Check for a mapping already installed.
|
||||
*/
|
||||
for (uidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
|
||||
uidp != 0; uidp = uidp->nu_hash.le_next) {
|
||||
if (uidp->nu_uid == nd->nd_cr.cr_uid)
|
||||
break;
|
||||
}
|
||||
if (!uidp) {
|
||||
nsd->nsd_uid = nd->nd_cr.cr_uid;
|
||||
if (nam2 && logauth++ == 0)
|
||||
log(LOG_WARNING, "Kerberized NFS using UDP\n");
|
||||
nsd->nsd_haddr =
|
||||
mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
|
||||
nsd->nsd_authlen = nd->nd_authlen;
|
||||
if (copyout(nd->nd_authstr, nsd->nsd_authstr,
|
||||
nd->nd_authlen) == 0 &&
|
||||
copyout((caddr_t)nsd, argp, sizeof (*nsd)) == 0)
|
||||
return (ENEEDAUTH);
|
||||
cacherep = RC_DROPIT;
|
||||
}
|
||||
}
|
||||
if (cacherep == RC_CHECKIT)
|
||||
cacherep = nfsrv_getcache(nam2, nd, &mreq);
|
||||
|
||||
/*
|
||||
* Check for just starting up for NQNFS and send
|
||||
* fake "try again later" replies to the NQNFS clients.
|
||||
*/
|
||||
if (notstarted && nqnfsstarttime <= time.tv_sec) {
|
||||
/*
|
||||
* Check for just starting up for NQNFS and send
|
||||
* fake "try again later" replies to the NQNFS clients.
|
||||
*/
|
||||
if (notstarted && nqnfsstarttime <= time.tv_sec) {
|
||||
if (modify_flag) {
|
||||
nqnfsstarttime = time.tv_sec + nqsrv_writeslack;
|
||||
modify_flag = 0;
|
||||
} else
|
||||
notstarted = 0;
|
||||
}
|
||||
if (notstarted) {
|
||||
if (nd->nd_nqlflag == NQL_NOVAL)
|
||||
}
|
||||
if (notstarted) {
|
||||
if ((nd->nd_flag & ND_NQNFS) == 0)
|
||||
cacherep = RC_DROPIT;
|
||||
else if (nd->nd_procnum != NFSPROC_WRITE) {
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
@ -533,36 +566,42 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
cacherep = RC_DOIT;
|
||||
} else
|
||||
modify_flag = 1;
|
||||
} else if (nd->nd_flag & NFSD_AUTHFAIL) {
|
||||
nd->nd_flag &= ~NFSD_AUTHFAIL;
|
||||
} else if (nfsd->nfsd_flag & NFSD_AUTHFAIL) {
|
||||
nfsd->nfsd_flag &= ~NFSD_AUTHFAIL;
|
||||
nd->nd_procnum = NFSPROC_NOOP;
|
||||
nd->nd_repstat = NQNFS_AUTHERR;
|
||||
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
|
||||
cacherep = RC_DOIT;
|
||||
}
|
||||
}
|
||||
|
||||
switch (cacherep) {
|
||||
case RC_DOIT:
|
||||
error = (*(nfsrv_procs[nd->nd_procnum]))(nd,
|
||||
nd->nd_mrep, nd->nd_md, nd->nd_dpos, &nd->nd_cr,
|
||||
nam, &mreq);
|
||||
if (nd->nd_cr.cr_ref != 1) {
|
||||
printf("nfssvc cref=%d\n", nd->nd_cr.cr_ref);
|
||||
panic("nfssvc cref");
|
||||
}
|
||||
/*
|
||||
* Loop to get all the write rpc relies that have been
|
||||
* gathered together.
|
||||
*/
|
||||
do {
|
||||
switch (cacherep) {
|
||||
case RC_DOIT:
|
||||
if (writes_todo || (nd->nd_procnum == NFSPROC_WRITE &&
|
||||
nfsrvw_procrastinate > 0 && !notstarted))
|
||||
error = nfsrv_writegather(&nd, slp,
|
||||
nfsd->nfsd_procp, &mreq);
|
||||
else
|
||||
error = (*(nfsrv3_procs[nd->nd_procnum]))(nd,
|
||||
slp, nfsd->nfsd_procp, &mreq);
|
||||
if (mreq == NULL)
|
||||
break;
|
||||
if (error) {
|
||||
if (nd->nd_procnum != NQNFSPROC_VACATED)
|
||||
nfsstats.srv_errs++;
|
||||
if (nam2) {
|
||||
nfsrv_updatecache(nam2, nd, FALSE, mreq);
|
||||
m_freem(nam2);
|
||||
}
|
||||
nfsrv_updatecache(nd, FALSE, mreq);
|
||||
if (nd->nd_nam2)
|
||||
m_freem(nd->nd_nam2);
|
||||
break;
|
||||
}
|
||||
nfsstats.srvrpccnt[nd->nd_procnum]++;
|
||||
if (nam2)
|
||||
nfsrv_updatecache(nam2, nd, TRUE, mreq);
|
||||
nfsrv_updatecache(nd, TRUE, mreq);
|
||||
nd->nd_mrep = (struct mbuf *)0;
|
||||
case RC_REPLY:
|
||||
case RC_REPLY:
|
||||
m = mreq;
|
||||
siz = 0;
|
||||
while (m) {
|
||||
@ -587,15 +626,15 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
if (solockp)
|
||||
(void) nfs_sndlock(solockp, (struct nfsreq *)0);
|
||||
if (slp->ns_flag & SLP_VALID)
|
||||
error = nfs_send(so, nam2, m, (struct nfsreq *)0);
|
||||
error = nfs_send(so, nd->nd_nam2, m, NULL);
|
||||
else {
|
||||
error = EPIPE;
|
||||
m_freem(m);
|
||||
}
|
||||
if (nfsrtton)
|
||||
nfsd_rt(&starttime, sotype, nd, nam, cacherep);
|
||||
if (nam2)
|
||||
MFREE(nam2, m);
|
||||
nfsd_rt(sotype, nd, cacherep);
|
||||
if (nd->nd_nam2)
|
||||
MFREE(nd->nd_nam2, m);
|
||||
if (nd->nd_mrep)
|
||||
m_freem(nd->nd_mrep);
|
||||
if (error == EPIPE)
|
||||
@ -603,29 +642,50 @@ nfssvc_nfsd(nsd, argp, p)
|
||||
if (solockp)
|
||||
nfs_sndunlock(solockp);
|
||||
if (error == EINTR || error == ERESTART) {
|
||||
free((caddr_t)nd, M_NFSRVDESC);
|
||||
nfsrv_slpderef(slp);
|
||||
s = splnet();
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case RC_DROPIT:
|
||||
case RC_DROPIT:
|
||||
if (nfsrtton)
|
||||
nfsd_rt(&starttime, sotype, nd, nam, cacherep);
|
||||
nfsd_rt(sotype, nd, cacherep);
|
||||
m_freem(nd->nd_mrep);
|
||||
m_freem(nam2);
|
||||
m_freem(nd->nd_nam2);
|
||||
break;
|
||||
};
|
||||
};
|
||||
if (nd) {
|
||||
FREE((caddr_t)nd, M_NFSRVDESC);
|
||||
nd = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if there are outstanding writes that
|
||||
* need to be serviced.
|
||||
*/
|
||||
cur_usec = (u_quad_t)time.tv_sec * 1000000 +
|
||||
(u_quad_t)time.tv_usec;
|
||||
s = splsoftclock();
|
||||
if (slp->ns_tq.lh_first &&
|
||||
slp->ns_tq.lh_first->nd_time <= cur_usec) {
|
||||
cacherep = RC_DOIT;
|
||||
writes_todo = 1;
|
||||
} else
|
||||
writes_todo = 0;
|
||||
splx(s);
|
||||
} while (writes_todo);
|
||||
s = splnet();
|
||||
if (nfsrv_dorec(slp, nd)) {
|
||||
nd->nd_flag &= ~NFSD_REQINPROG;
|
||||
nd->nd_slp = (struct nfssvc_sock *)0;
|
||||
if (nfsrv_dorec(slp, nfsd, &nd)) {
|
||||
nfsd->nfsd_flag &= ~NFSD_REQINPROG;
|
||||
nfsd->nfsd_slp = NULL;
|
||||
nfsrv_slpderef(slp);
|
||||
}
|
||||
}
|
||||
done:
|
||||
TAILQ_REMOVE(&nfsd_head, nd, nd_chain);
|
||||
TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain);
|
||||
splx(s);
|
||||
free((caddr_t)nd, M_NFSD);
|
||||
free((caddr_t)nfsd, M_NFSD);
|
||||
nsd->nsd_nfsd = (struct nfsd *)0;
|
||||
if (--nfs_numnfsd == 0)
|
||||
nfsrv_init(TRUE); /* Reinitialize everything */
|
||||
@ -641,9 +701,10 @@ int
|
||||
nfssvc_iod(p)
|
||||
struct proc *p;
|
||||
{
|
||||
register struct buf *bp;
|
||||
register struct buf *bp, *nbp;
|
||||
register int i, myiod;
|
||||
int error = 0;
|
||||
struct vnode *vp;
|
||||
int error = 0, s;
|
||||
|
||||
/*
|
||||
* Assign my position or return error if too many already running
|
||||
@ -662,24 +723,53 @@ nfssvc_iod(p)
|
||||
* Just loop around doin our stuff until SIGKILL
|
||||
*/
|
||||
for (;;) {
|
||||
while (nfs_bufq.tqh_first == NULL && error == 0) {
|
||||
nfs_iodwant[myiod] = p;
|
||||
error = tsleep((caddr_t)&nfs_iodwant[myiod],
|
||||
PWAIT | PCATCH, "nfsidl", 0);
|
||||
}
|
||||
while ((bp = nfs_bufq.tqh_first) != NULL) {
|
||||
/* Take one off the front of the list */
|
||||
TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);
|
||||
if (bp->b_flags & B_READ)
|
||||
(void) nfs_doio(bp, bp->b_rcred, (struct proc *)0);
|
||||
else
|
||||
(void) nfs_doio(bp, bp->b_wcred, (struct proc *)0);
|
||||
}
|
||||
if (error) {
|
||||
nfs_asyncdaemon[myiod] = 0;
|
||||
nfs_numasync--;
|
||||
return (error);
|
||||
}
|
||||
while (nfs_bufq.tqh_first == NULL && error == 0) {
|
||||
nfs_iodwant[myiod] = p;
|
||||
error = tsleep((caddr_t)&nfs_iodwant[myiod],
|
||||
PWAIT | PCATCH, "nfsidl", 0);
|
||||
}
|
||||
while ((bp = nfs_bufq.tqh_first) != NULL) {
|
||||
/* Take one off the front of the list */
|
||||
TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);
|
||||
if (bp->b_flags & B_READ)
|
||||
(void) nfs_doio(bp, bp->b_rcred, (struct proc *)0);
|
||||
else do {
|
||||
/*
|
||||
* Look for a delayed write for the same vnode, so I can do
|
||||
* it now. We must grab it before calling nfs_doio() to
|
||||
* avoid any risk of the vnode getting vclean()'d while
|
||||
* we are doing the write rpc.
|
||||
*/
|
||||
vp = bp->b_vp;
|
||||
s = splbio();
|
||||
for (nbp = vp->v_dirtyblkhd.lh_first; nbp;
|
||||
nbp = nbp->b_vnbufs.le_next) {
|
||||
if ((nbp->b_flags &
|
||||
(B_BUSY|B_DELWRI|B_NEEDCOMMIT|B_NOCACHE))!=B_DELWRI)
|
||||
continue;
|
||||
bremfree(nbp);
|
||||
vfs_busy_pages(nbp, 1);
|
||||
nbp->b_flags |= (B_BUSY|B_ASYNC);
|
||||
break;
|
||||
}
|
||||
splx(s);
|
||||
/*
|
||||
* For the delayed write, do the first part of nfs_bwrite()
|
||||
* up to, but not including nfs_strategy().
|
||||
*/
|
||||
if (nbp) {
|
||||
nbp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
|
||||
reassignbuf(nbp, nbp->b_vp);
|
||||
nbp->b_vp->v_numoutput++;
|
||||
}
|
||||
(void) nfs_doio(bp, bp->b_wcred, (struct proc *)0);
|
||||
} while (bp = nbp);
|
||||
}
|
||||
if (error) {
|
||||
nfs_asyncdaemon[myiod] = 0;
|
||||
nfs_numasync--;
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -695,9 +785,11 @@ nfsrv_zapsock(slp)
|
||||
register struct nfssvc_sock *slp;
|
||||
{
|
||||
register struct nfsuid *nuidp, *nnuidp;
|
||||
register struct nfsrv_descript *nwp, *nnwp;
|
||||
struct socket *so;
|
||||
struct file *fp;
|
||||
struct mbuf *m;
|
||||
int s;
|
||||
|
||||
slp->ns_flag &= ~SLP_ALLFLAGS;
|
||||
fp = slp->ns_fp;
|
||||
@ -716,8 +808,18 @@ nfsrv_zapsock(slp)
|
||||
nnuidp = nuidp->nu_lru.tqe_next;
|
||||
LIST_REMOVE(nuidp, nu_hash);
|
||||
TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, nu_lru);
|
||||
if (nuidp->nu_flag & NU_NAM)
|
||||
m_freem(nuidp->nu_nam);
|
||||
free((caddr_t)nuidp, M_NFSUID);
|
||||
}
|
||||
s = splsoftclock();
|
||||
for (nwp = slp->ns_tq.lh_first; nwp; nwp = nnwp) {
|
||||
nnwp = nwp->nd_tq.le_next;
|
||||
LIST_REMOVE(nwp, nd_tq);
|
||||
free((caddr_t)nwp, M_NFSRVDESC);
|
||||
}
|
||||
LIST_INIT(&slp->ns_tq);
|
||||
splx(s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -726,13 +828,15 @@ nfsrv_zapsock(slp)
|
||||
* on this mount point porpous out of the kernel and do it.
|
||||
*/
|
||||
int
|
||||
nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
|
||||
nfs_getauth(nmp, rep, cred, auth_str, auth_len, verf_str, verf_len, key)
|
||||
register struct nfsmount *nmp;
|
||||
struct nfsreq *rep;
|
||||
struct ucred *cred;
|
||||
int *auth_type;
|
||||
char **auth_str;
|
||||
int *auth_len;
|
||||
char *verf_str;
|
||||
int *verf_len;
|
||||
NFSKERBKEY_T key; /* return session key */
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
@ -748,6 +852,9 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
|
||||
}
|
||||
nmp->nm_flag &= ~(NFSMNT_WAITAUTH | NFSMNT_WANTAUTH);
|
||||
nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK);
|
||||
nmp->nm_authlen = RPCAUTH_MAXSIZ;
|
||||
nmp->nm_verfstr = verf_str;
|
||||
nmp->nm_verflen = *verf_len;
|
||||
nmp->nm_authuid = cred->cr_uid;
|
||||
wakeup((caddr_t)&nmp->nm_authstr);
|
||||
|
||||
@ -766,8 +873,9 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
|
||||
if (error)
|
||||
free((caddr_t)*auth_str, M_TEMP);
|
||||
else {
|
||||
*auth_type = nmp->nm_authtype;
|
||||
*auth_len = nmp->nm_authlen;
|
||||
*verf_len = nmp->nm_verflen;
|
||||
bcopy((caddr_t)nmp->nm_key, (caddr_t)key, sizeof (key));
|
||||
}
|
||||
nmp->nm_flag &= ~NFSMNT_HASAUTH;
|
||||
nmp->nm_flag |= NFSMNT_WAITAUTH;
|
||||
@ -778,6 +886,149 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a nickname authenticator and verifier.
|
||||
*/
|
||||
int
|
||||
nfs_getnickauth(nmp, cred, auth_str, auth_len, verf_str, verf_len)
|
||||
struct nfsmount *nmp;
|
||||
struct ucred *cred;
|
||||
char **auth_str;
|
||||
int *auth_len;
|
||||
char *verf_str;
|
||||
int verf_len;
|
||||
{
|
||||
register struct nfsuid *nuidp;
|
||||
register u_long *nickp, *verfp;
|
||||
struct timeval ktvin, ktvout;
|
||||
NFSKERBKEYSCHED_T keys; /* stores key schedule */
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (verf_len < (4 * NFSX_UNSIGNED))
|
||||
panic("nfs_getnickauth verf too small");
|
||||
#endif
|
||||
for (nuidp = NMUIDHASH(nmp, cred->cr_uid)->lh_first;
|
||||
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
|
||||
if (nuidp->nu_cr.cr_uid == cred->cr_uid)
|
||||
break;
|
||||
}
|
||||
if (!nuidp || nuidp->nu_expire < time.tv_sec)
|
||||
return (EACCES);
|
||||
|
||||
/*
|
||||
* Move to the end of the lru list (end of lru == most recently used).
|
||||
*/
|
||||
TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru);
|
||||
TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp, nu_lru);
|
||||
|
||||
nickp = (u_long *)malloc(2 * NFSX_UNSIGNED, M_TEMP, M_WAITOK);
|
||||
*nickp++ = txdr_unsigned(RPCAKN_NICKNAME);
|
||||
*nickp = txdr_unsigned(nuidp->nu_nickname);
|
||||
*auth_str = (char *)nickp;
|
||||
*auth_len = 2 * NFSX_UNSIGNED;
|
||||
|
||||
/*
|
||||
* Now we must encrypt the verifier and package it up.
|
||||
*/
|
||||
verfp = (u_long *)verf_str;
|
||||
*verfp++ = txdr_unsigned(RPCAKN_NICKNAME);
|
||||
if (time.tv_sec > nuidp->nu_timestamp.tv_sec ||
|
||||
(time.tv_sec == nuidp->nu_timestamp.tv_sec &&
|
||||
time.tv_usec > nuidp->nu_timestamp.tv_usec))
|
||||
nuidp->nu_timestamp = time;
|
||||
else
|
||||
nuidp->nu_timestamp.tv_usec++;
|
||||
ktvin.tv_sec = txdr_unsigned(nuidp->nu_timestamp.tv_sec);
|
||||
ktvin.tv_usec = txdr_unsigned(nuidp->nu_timestamp.tv_usec);
|
||||
|
||||
/*
|
||||
* Now encrypt the timestamp verifier in ecb mode using the session
|
||||
* key.
|
||||
*/
|
||||
#ifdef NFSKERB
|
||||
XXX
|
||||
#endif
|
||||
|
||||
*verfp++ = ktvout.tv_sec;
|
||||
*verfp++ = ktvout.tv_usec;
|
||||
*verfp = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the current nickname in a hash list entry on the mount point.
|
||||
*/
|
||||
int
|
||||
nfs_savenickauth(nmp, cred, len, key, mdp, dposp, mrep)
|
||||
register struct nfsmount *nmp;
|
||||
struct ucred *cred;
|
||||
int len;
|
||||
NFSKERBKEY_T key;
|
||||
struct mbuf **mdp;
|
||||
char **dposp;
|
||||
struct mbuf *mrep;
|
||||
{
|
||||
register struct nfsuid *nuidp;
|
||||
register u_long *tl;
|
||||
register long t1;
|
||||
struct mbuf *md = *mdp;
|
||||
struct timeval ktvin, ktvout;
|
||||
u_long nick;
|
||||
NFSKERBKEYSCHED_T keys;
|
||||
char *dpos = *dposp, *cp2;
|
||||
int deltasec, error = 0;
|
||||
|
||||
if (len == (3 * NFSX_UNSIGNED)) {
|
||||
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
|
||||
ktvin.tv_sec = *tl++;
|
||||
ktvin.tv_usec = *tl++;
|
||||
nick = fxdr_unsigned(u_long, *tl);
|
||||
|
||||
/*
|
||||
* Decrypt the timestamp in ecb mode.
|
||||
*/
|
||||
#ifdef NFSKERB
|
||||
XXX
|
||||
#endif
|
||||
ktvout.tv_sec = fxdr_unsigned(long, ktvout.tv_sec);
|
||||
ktvout.tv_usec = fxdr_unsigned(long, ktvout.tv_usec);
|
||||
deltasec = time.tv_sec - ktvout.tv_sec;
|
||||
if (deltasec < 0)
|
||||
deltasec = -deltasec;
|
||||
/*
|
||||
* If ok, add it to the hash list for the mount point.
|
||||
*/
|
||||
if (deltasec <= NFS_KERBCLOCKSKEW) {
|
||||
if (nmp->nm_numuids < nuidhash_max) {
|
||||
nmp->nm_numuids++;
|
||||
nuidp = (struct nfsuid *)
|
||||
malloc(sizeof (struct nfsuid), M_NFSUID,
|
||||
M_WAITOK);
|
||||
} else {
|
||||
nuidp = nmp->nm_uidlruhead.tqh_first;
|
||||
LIST_REMOVE(nuidp, nu_hash);
|
||||
TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp,
|
||||
nu_lru);
|
||||
}
|
||||
nuidp->nu_flag = 0;
|
||||
nuidp->nu_cr.cr_uid = cred->cr_uid;
|
||||
nuidp->nu_expire = time.tv_sec + NFS_KERBTTL;
|
||||
nuidp->nu_timestamp = ktvout;
|
||||
nuidp->nu_nickname = nick;
|
||||
bcopy(key, nuidp->nu_key, sizeof (key));
|
||||
TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp,
|
||||
nu_lru);
|
||||
LIST_INSERT_HEAD(NMUIDHASH(nmp, cred->cr_uid),
|
||||
nuidp, nu_hash);
|
||||
}
|
||||
} else
|
||||
nfsm_adv(nfsm_rndup(len));
|
||||
nfsmout:
|
||||
*mdp = md;
|
||||
*dposp = dpos;
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Derefence a server socket structure. If it has no more references and
|
||||
* is no longer valid, you can throw it away.
|
||||
@ -830,16 +1081,12 @@ nfsrv_init(terminating)
|
||||
nfs_udpsock = (struct nfssvc_sock *)
|
||||
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
|
||||
bzero((caddr_t)nfs_udpsock, sizeof (struct nfssvc_sock));
|
||||
nfs_udpsock->ns_uidhashtbl =
|
||||
hashinit(NUIDHASHSIZ, M_NFSSVC, &nfs_udpsock->ns_uidhash);
|
||||
TAILQ_INIT(&nfs_udpsock->ns_uidlruhead);
|
||||
TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain);
|
||||
|
||||
nfs_cltpsock = (struct nfssvc_sock *)
|
||||
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
|
||||
bzero((caddr_t)nfs_cltpsock, sizeof (struct nfssvc_sock));
|
||||
nfs_cltpsock->ns_uidhashtbl =
|
||||
hashinit(NUIDHASHSIZ, M_NFSSVC, &nfs_cltpsock->ns_uidhash);
|
||||
TAILQ_INIT(&nfs_cltpsock->ns_uidlruhead);
|
||||
TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain);
|
||||
}
|
||||
@ -848,11 +1095,9 @@ nfsrv_init(terminating)
|
||||
* Add entries to the server monitor log.
|
||||
*/
|
||||
static void
|
||||
nfsd_rt(startp, sotype, nd, nam, cacherep)
|
||||
struct timeval *startp;
|
||||
nfsd_rt(sotype, nd, cacherep)
|
||||
int sotype;
|
||||
register struct nfsd *nd;
|
||||
struct mbuf *nam;
|
||||
register struct nfsrv_descript *nd;
|
||||
int cacherep;
|
||||
{
|
||||
register struct drt *rt;
|
||||
@ -866,15 +1111,17 @@ nfsd_rt(startp, sotype, nd, nam, cacherep)
|
||||
rt->flag = DRT_CACHEDROP;
|
||||
if (sotype == SOCK_STREAM)
|
||||
rt->flag |= DRT_TCP;
|
||||
if (nd->nd_nqlflag != NQL_NOVAL)
|
||||
if (nd->nd_flag & ND_NQNFS)
|
||||
rt->flag |= DRT_NQNFS;
|
||||
else if (nd->nd_flag & ND_NFSV3)
|
||||
rt->flag |= DRT_NFSV3;
|
||||
rt->proc = nd->nd_procnum;
|
||||
if (mtod(nam, struct sockaddr *)->sa_family == AF_INET)
|
||||
rt->ipadr = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
|
||||
if (mtod(nd->nd_nam, struct sockaddr *)->sa_family == AF_INET)
|
||||
rt->ipadr = mtod(nd->nd_nam, struct sockaddr_in *)->sin_addr.s_addr;
|
||||
else
|
||||
rt->ipadr = INADDR_ANY;
|
||||
rt->resptime = ((time.tv_sec - startp->tv_sec) * 1000000) +
|
||||
(time.tv_usec - startp->tv_usec);
|
||||
rt->ipadr = INADDR_ANY;
|
||||
rt->resptime = ((time.tv_sec - nd->nd_starttime.tv_sec) * 1000000) +
|
||||
(time.tv_usec - nd->nd_starttime.tv_usec);
|
||||
rt->tstamp = time;
|
||||
nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ;
|
||||
}
|
||||
|
@ -34,12 +34,13 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsm_subs.h 8.1 (Berkeley) 6/16/93
|
||||
* $Id: nfsm_subs.h,v 1.5 1994/10/17 17:47:42 phk Exp $
|
||||
* $Id: nfsm_subs.h,v 1.6 1995/05/30 08:12:51 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSM_SUBS_H_
|
||||
#define _NFS_NFSM_SUBS_H_
|
||||
|
||||
|
||||
/*
|
||||
* These macros do strange and peculiar things to mbuf chains for
|
||||
* the assistance of the nfs code. To attempt to use them for any
|
||||
@ -90,49 +91,153 @@ extern struct mbuf *nfsm_reqh();
|
||||
mb->m_len += (s); \
|
||||
bpos += (s); }
|
||||
|
||||
#define nfsm_dissect(a,c,s) \
|
||||
#define nfsm_dissect(a, c, s) \
|
||||
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
|
||||
if (t1 >= (s)) { \
|
||||
(a) = (c)(dpos); \
|
||||
dpos += (s); \
|
||||
} else if (t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} else { \
|
||||
error = nfsm_disct(&md, &dpos, (s), t1, &cp2); \
|
||||
if (error) { \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} else { \
|
||||
(a) = (c)cp2; \
|
||||
} \
|
||||
(a) = (c)cp2; \
|
||||
} }
|
||||
|
||||
#define nfsm_fhtom(v) \
|
||||
nfsm_build(cp,caddr_t,NFSX_FH); \
|
||||
bcopy((caddr_t)&(VTONFS(v)->n_fh), cp, NFSX_FH)
|
||||
#define nfsm_fhtom(v, v3) \
|
||||
{ if (v3) { \
|
||||
t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \
|
||||
if (t2 <= M_TRAILINGSPACE(mb)) { \
|
||||
nfsm_build(tl, u_long *, t2); \
|
||||
*tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \
|
||||
*(tl + ((t2>>2) - 2)) = 0; \
|
||||
bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \
|
||||
VTONFS(v)->n_fhsize); \
|
||||
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, \
|
||||
(caddr_t)VTONFS(v)->n_fhp, VTONFS(v)->n_fhsize)) { \
|
||||
error = t2; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
} else { \
|
||||
nfsm_build(cp, caddr_t, NFSX_V2FH); \
|
||||
bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \
|
||||
} }
|
||||
|
||||
#define nfsm_srvfhtom(f) \
|
||||
nfsm_build(cp,caddr_t,NFSX_FH); \
|
||||
bcopy((caddr_t)(f), cp, NFSX_FH)
|
||||
#define nfsm_srvfhtom(f, v3) \
|
||||
{ if (v3) { \
|
||||
nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FH); \
|
||||
*tl++ = txdr_unsigned(NFSX_V3FH); \
|
||||
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
|
||||
} else { \
|
||||
nfsm_build(cp, caddr_t, NFSX_V2FH); \
|
||||
bcopy((caddr_t)(f), cp, NFSX_V2FH); \
|
||||
} }
|
||||
|
||||
#define nfsm_mtofh(d,v) \
|
||||
{ struct nfsnode *np; nfsv2fh_t *fhp; \
|
||||
nfsm_dissect(fhp,nfsv2fh_t *,NFSX_FH); \
|
||||
error = nfs_nget((d)->v_mount, fhp, &np); \
|
||||
if (error) { \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = NFSTOV(np); \
|
||||
nfsm_loadattr(v, (struct vattr *)0); \
|
||||
#define nfsm_srvpostop_fh(f) \
|
||||
{ nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \
|
||||
*tl++ = nfs_true; \
|
||||
*tl++ = txdr_unsigned(NFSX_V3FH); \
|
||||
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
|
||||
}
|
||||
|
||||
#define nfsm_loadattr(v,a) \
|
||||
{ struct vnode *tvp = (v); \
|
||||
error = nfs_loadattrcache(&tvp, &md, &dpos, (a)); \
|
||||
if (error) { \
|
||||
#define nfsm_mtofh(d, v, v3, f) \
|
||||
{ struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \
|
||||
if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(f) = fxdr_unsigned(int, *tl); \
|
||||
} else \
|
||||
(f) = 1; \
|
||||
if (f) { \
|
||||
nfsm_getfh(ttfhp, ttfhsize, (v3)); \
|
||||
if (t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \
|
||||
&ttnp)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = NFSTOV(ttnp); \
|
||||
} \
|
||||
if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (f) \
|
||||
(f) = fxdr_unsigned(int, *tl); \
|
||||
else if (fxdr_unsigned(int, *tl)) \
|
||||
nfsm_adv(NFSX_V3FATTR); \
|
||||
} \
|
||||
if (f) \
|
||||
nfsm_loadattr((v), (struct vattr *)0); \
|
||||
}
|
||||
|
||||
#define nfsm_getfh(f, s, v3) \
|
||||
{ if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \
|
||||
(s) > NFSX_V3FHMAX) { \
|
||||
m_freem(mrep); \
|
||||
error = EBADRPC; \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
} else \
|
||||
(s) = NFSX_V2FH; \
|
||||
nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); }
|
||||
|
||||
#define nfsm_loadattr(v, a) \
|
||||
{ struct vnode *ttvp = (v); \
|
||||
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a))) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = tvp; }
|
||||
(v) = ttvp; }
|
||||
|
||||
#define nfsm_postop_attr(v, f) \
|
||||
{ struct vnode *ttvp = (v); \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if ((f) = fxdr_unsigned(int, *tl)) { \
|
||||
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
|
||||
(struct vattr *)0)) { \
|
||||
error = t1; \
|
||||
(f) = 0; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = ttvp; \
|
||||
} }
|
||||
|
||||
/* Used as (f) for nfsm_wcc_data() */
|
||||
#define NFSV3_WCCRATTR 0
|
||||
#define NFSV3_WCCCHK 1
|
||||
|
||||
#define nfsm_wcc_data(v, f) \
|
||||
{ int ttattrf, ttretf = 0; \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, 6 * NFSX_UNSIGNED); \
|
||||
if (f) \
|
||||
ttretf = (VTONFS(v)->n_mtime == \
|
||||
fxdr_unsigned(u_long, *(tl + 2))); \
|
||||
} \
|
||||
nfsm_postop_attr((v), ttattrf); \
|
||||
if (f) { \
|
||||
(f) = ttretf; \
|
||||
} else { \
|
||||
(f) = ttattrf; \
|
||||
} }
|
||||
|
||||
#define nfsm_v3sattr(s, a, u, g) \
|
||||
{ (s)->sa_modetrue = nfs_true; \
|
||||
(s)->sa_mode = vtonfsv3_mode((a)->va_mode); \
|
||||
(s)->sa_uidtrue = nfs_true; \
|
||||
(s)->sa_uid = txdr_unsigned(u); \
|
||||
(s)->sa_gidtrue = nfs_true; \
|
||||
(s)->sa_gid = txdr_unsigned(g); \
|
||||
(s)->sa_sizefalse = nfs_false; \
|
||||
(s)->sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
|
||||
txdr_nfsv3time(&(a)->va_atime, &(s)->sa_atime); \
|
||||
(s)->sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
|
||||
txdr_nfsv3time(&(a)->va_mtime, &(s)->sa_mtime); \
|
||||
}
|
||||
|
||||
#define nfsm_strsiz(s,m) \
|
||||
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
|
||||
@ -149,16 +254,27 @@ extern struct mbuf *nfsm_reqh();
|
||||
nfsm_reply(0); \
|
||||
} }
|
||||
|
||||
#define nfsm_srvnamesiz(s) \
|
||||
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
|
||||
if (((s) = fxdr_unsigned(long,*tl)) > NFS_MAXNAMLEN) \
|
||||
error = NFSERR_NAMETOL; \
|
||||
if ((s) <= 0) \
|
||||
error = EBADRPC; \
|
||||
if (error) \
|
||||
nfsm_reply(0); \
|
||||
}
|
||||
|
||||
#define nfsm_mtouio(p,s) \
|
||||
if ((s) > 0 && \
|
||||
(error = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
|
||||
(t1 = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_uiotom(p,s) \
|
||||
error = nfsm_uiotombuf((p),&mb,(s),&bpos); \
|
||||
if (error) { \
|
||||
if (t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) { \
|
||||
error = t1; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
@ -172,10 +288,13 @@ extern struct mbuf *nfsm_reqh();
|
||||
#define nfsm_rndup(a) (((a)+3)&(~0x3))
|
||||
|
||||
#define nfsm_request(v, t, p, c) \
|
||||
error = nfs_request((v), mreq, (t), (p), \
|
||||
(c), &mrep, &md, &dpos); \
|
||||
if (error) \
|
||||
goto nfsmout
|
||||
if (error = nfs_request((v), mreq, (t), (p), \
|
||||
(c), &mrep, &md, &dpos)) { \
|
||||
if (error & NFSERR_RETERR) \
|
||||
error &= ~NFSERR_RETERR; \
|
||||
else \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_strtom(a,s,m) \
|
||||
if ((s) > (m)) { \
|
||||
@ -189,12 +308,10 @@ extern struct mbuf *nfsm_reqh();
|
||||
*tl++ = txdr_unsigned(s); \
|
||||
*(tl+((t2>>2)-2)) = 0; \
|
||||
bcopy((caddr_t)(a), (caddr_t)tl, (s)); \
|
||||
} else { \
|
||||
error = nfsm_strtmbuf(&mb, &bpos, (a), (s)); \
|
||||
if (error) { \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) { \
|
||||
error = t2; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_srvdone \
|
||||
@ -204,33 +321,53 @@ extern struct mbuf *nfsm_reqh();
|
||||
#define nfsm_reply(s) \
|
||||
{ \
|
||||
nfsd->nd_repstat = error; \
|
||||
if (error) \
|
||||
(void) nfs_rephead(0, nfsd, error, cache, &frev, \
|
||||
if (error && !(nfsd->nd_flag & ND_NFSV3)) \
|
||||
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
|
||||
mrq, &mb, &bpos); \
|
||||
else \
|
||||
(void) nfs_rephead((s), nfsd, error, cache, &frev, \
|
||||
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
|
||||
mrq, &mb, &bpos); \
|
||||
m_freem(mrep); \
|
||||
mreq = *mrq; \
|
||||
if (error) \
|
||||
if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
|
||||
error == EBADRPC)) \
|
||||
return(0); \
|
||||
}
|
||||
|
||||
#define nfsm_adv(s) \
|
||||
t1 = mtod(md, caddr_t)+md->m_len-dpos; \
|
||||
if (t1 >= (s)) { \
|
||||
dpos += (s); \
|
||||
} else { \
|
||||
error = nfs_adv(&md, &dpos, (s), t1); \
|
||||
if (error) { \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
#define nfsm_writereply(s, v3) \
|
||||
{ \
|
||||
nfsd->nd_repstat = error; \
|
||||
if (error && !(v3)) \
|
||||
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
|
||||
&mreq, &mb, &bpos); \
|
||||
else \
|
||||
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
|
||||
&mreq, &mb, &bpos); \
|
||||
}
|
||||
|
||||
#define nfsm_adv(s) \
|
||||
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
|
||||
if (t1 >= (s)) { \
|
||||
dpos += (s); \
|
||||
} else if (t1 = nfs_adv(&md, &dpos, (s), t1)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} }
|
||||
|
||||
#define nfsm_srvmtofh(f) \
|
||||
nfsm_dissect(tl, u_long *, NFSX_FH); \
|
||||
bcopy((caddr_t)tl, (caddr_t)f, NFSX_FH)
|
||||
{ if (nfsd->nd_flag & ND_NFSV3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \
|
||||
error = EBADRPC; \
|
||||
nfsm_reply(0); \
|
||||
} \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
|
||||
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
|
||||
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
|
||||
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
|
||||
}
|
||||
|
||||
#define nfsm_clget \
|
||||
if (bp >= be) { \
|
||||
@ -246,41 +383,57 @@ extern struct mbuf *nfsm_reqh();
|
||||
} \
|
||||
tl = (u_long *)bp
|
||||
|
||||
#define nfsm_srvfillattr \
|
||||
fp->fa_type = vtonfs_type(vap->va_type); \
|
||||
fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); \
|
||||
fp->fa_nlink = txdr_unsigned(vap->va_nlink); \
|
||||
fp->fa_uid = txdr_unsigned(vap->va_uid); \
|
||||
fp->fa_gid = txdr_unsigned(vap->va_gid); \
|
||||
if (nfsd->nd_nqlflag == NQL_NOVAL) { \
|
||||
fp->fa_nfsblocksize = txdr_unsigned(vap->va_blocksize); \
|
||||
if (vap->va_type == VFIFO) \
|
||||
fp->fa_nfsrdev = 0xffffffff; \
|
||||
else \
|
||||
fp->fa_nfsrdev = txdr_unsigned(vap->va_rdev); \
|
||||
fp->fa_nfsfsid = txdr_unsigned(vap->va_fsid); \
|
||||
fp->fa_nfsfileid = txdr_unsigned(vap->va_fileid); \
|
||||
fp->fa_nfssize = txdr_unsigned(vap->va_size); \
|
||||
fp->fa_nfsblocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); \
|
||||
txdr_nfstime(&vap->va_atime, &fp->fa_nfsatime); \
|
||||
txdr_nfstime(&vap->va_mtime, &fp->fa_nfsmtime); \
|
||||
txdr_nfstime(&vap->va_ctime, &fp->fa_nfsctime); \
|
||||
} else { \
|
||||
fp->fa_nqblocksize = txdr_unsigned(vap->va_blocksize); \
|
||||
if (vap->va_type == VFIFO) \
|
||||
fp->fa_nqrdev = 0xffffffff; \
|
||||
else \
|
||||
fp->fa_nqrdev = txdr_unsigned(vap->va_rdev); \
|
||||
fp->fa_nqfsid = txdr_unsigned(vap->va_fsid); \
|
||||
fp->fa_nqfileid = txdr_unsigned(vap->va_fileid); \
|
||||
txdr_hyper(&vap->va_size, &fp->fa_nqsize); \
|
||||
txdr_hyper(&vap->va_bytes, &fp->fa_nqbytes); \
|
||||
txdr_nqtime(&vap->va_atime, &fp->fa_nqatime); \
|
||||
txdr_nqtime(&vap->va_mtime, &fp->fa_nqmtime); \
|
||||
txdr_nqtime(&vap->va_ctime, &fp->fa_nqctime); \
|
||||
fp->fa_nqflags = txdr_unsigned(vap->va_flags); \
|
||||
fp->fa_nqgen = txdr_unsigned(vap->va_gen); \
|
||||
txdr_hyper(&vap->va_filerev, &fp->fa_nqfilerev); \
|
||||
}
|
||||
#define nfsm_srvfillattr(a, f) \
|
||||
nfsm_srvfattr(nfsd, (a), (f))
|
||||
|
||||
#define nfsm_srvwcc_data(br, b, ar, a) \
|
||||
nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos)
|
||||
|
||||
#define nfsm_srvpostop_attr(r, a) \
|
||||
nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos)
|
||||
|
||||
#define nfsm_srvsattr(a) \
|
||||
{ nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_mode = nfstov_mode(*tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_uid = fxdr_unsigned(uid_t, *tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_gid = fxdr_unsigned(gid_t, *tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_hyper(tl, &(a)->va_size); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
switch (fxdr_unsigned(int, *tl)) { \
|
||||
case NFSV3SATTRTIME_TOCLIENT: \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_nfsv3time(tl, &(a)->va_atime); \
|
||||
break; \
|
||||
case NFSV3SATTRTIME_TOSERVER: \
|
||||
(a)->va_atime.ts_sec = time.tv_sec; \
|
||||
(a)->va_atime.ts_nsec = time.tv_usec * 1000; \
|
||||
break; \
|
||||
}; \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
switch (fxdr_unsigned(int, *tl)) { \
|
||||
case NFSV3SATTRTIME_TOCLIENT: \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_nfsv3time(tl, &(a)->va_mtime); \
|
||||
break; \
|
||||
case NFSV3SATTRTIME_TOSERVER: \
|
||||
(a)->va_mtime.ts_sec = time.tv_sec; \
|
||||
(a)->va_mtime.ts_nsec = time.tv_usec * 1000; \
|
||||
break; \
|
||||
}; }
|
||||
|
||||
#endif
|
||||
|
441
sys/nfsserver/nfsproto.h
Normal file
441
sys/nfsserver/nfsproto.h
Normal file
@ -0,0 +1,441 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsproto.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfsproto.h,v 1.4 1994/08/21 06:50:13 paul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSPROTO_H_
|
||||
#define _NFS_NFSPROTO_H_
|
||||
|
||||
/*
|
||||
* nfs definitions as per the Version 2 and 3 specs
|
||||
*/
|
||||
|
||||
/*
|
||||
* Constants as defined in the Sun NFS Version 2 and 3 specs.
|
||||
* "NFS: Network File System Protocol Specification" RFC1094
|
||||
* and in the "NFS: Network File System Version 3 Protocol
|
||||
* Specification"
|
||||
*/
|
||||
|
||||
#define NFS_PORT 2049
|
||||
#define NFS_PROG 100003
|
||||
#define NFS_VER2 2
|
||||
#define NFS_VER3 3
|
||||
#define NFS_V2MAXDATA 8192
|
||||
#define NFS_MAXDGRAMDATA 16384
|
||||
#define NFS_MAXDATA 32768
|
||||
#define NFS_MAXPATHLEN 1024
|
||||
#define NFS_MAXNAMLEN 255
|
||||
#define NFS_MAXPKTHDR 404
|
||||
#define NFS_MAXPACKET (NFS_MAXPKTHDR + NFS_MAXDATA)
|
||||
#define NFS_MINPACKET 20
|
||||
#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */
|
||||
|
||||
/* Stat numbers for rpc returns (version 2 and 3) */
|
||||
#define NFS_OK 0
|
||||
#define NFSERR_PERM 1
|
||||
#define NFSERR_NOENT 2
|
||||
#define NFSERR_IO 5
|
||||
#define NFSERR_NXIO 6
|
||||
#define NFSERR_ACCES 13
|
||||
#define NFSERR_EXIST 17
|
||||
#define NFSERR_XDEV 18 /* Version 3 only */
|
||||
#define NFSERR_NODEV 19
|
||||
#define NFSERR_NOTDIR 20
|
||||
#define NFSERR_ISDIR 21
|
||||
#define NFSERR_INVAL 22 /* Version 3 only */
|
||||
#define NFSERR_FBIG 27
|
||||
#define NFSERR_NOSPC 28
|
||||
#define NFSERR_ROFS 30
|
||||
#define NFSERR_MLINK 31 /* Version 3 only */
|
||||
#define NFSERR_NAMETOL 63
|
||||
#define NFSERR_NOTEMPTY 66
|
||||
#define NFSERR_DQUOT 69
|
||||
#define NFSERR_STALE 70
|
||||
#define NFSERR_REMOTE 71 /* Version 3 only */
|
||||
#define NFSERR_WFLUSH 99 /* Version 2 only */
|
||||
#define NFSERR_BADHANDLE 10001 /* The rest Version 3 only */
|
||||
#define NFSERR_NOT_SYNC 10002
|
||||
#define NFSERR_BAD_COOKIE 10003
|
||||
#define NFSERR_NOTSUPP 10004
|
||||
#define NFSERR_TOOSMALL 10005
|
||||
#define NFSERR_SERVERFAULT 10006
|
||||
#define NFSERR_BADTYPE 10007
|
||||
#define NFSERR_JUKEBOX 10008
|
||||
#define NFSERR_TRYLATER NFSERR_JUKEBOX
|
||||
#define NFSERR_STALEWRITEVERF 30001 /* Fake return for nfs_commit() */
|
||||
|
||||
#define NFSERR_RETVOID 0x20000000 /* Return void, not error */
|
||||
#define NFSERR_AUTHERR 0x40000000 /* Mark an authentication error */
|
||||
#define NFSERR_RETERR 0x80000000 /* Mark an error return for V3 */
|
||||
|
||||
/* Sizes in bytes of various nfs rpc components */
|
||||
#define NFSX_UNSIGNED 4
|
||||
|
||||
/* specific to NFS Version 2 */
|
||||
#define NFSX_V2FH 32
|
||||
#define NFSX_V2FATTR 68
|
||||
#define NFSX_V2SATTR 32
|
||||
#define NFSX_V2COOKIE 4
|
||||
#define NFSX_V2STATFS 20
|
||||
|
||||
/* specific to NFS Version 3 */
|
||||
#define NFSX_V3FH (sizeof (fhandle_t)) /* size this server uses */
|
||||
#define NFSX_V3FHMAX 64 /* max. allowed by protocol */
|
||||
#define NFSX_V3FATTR 84
|
||||
#define NFSX_V3SATTR 60 /* max. all fields filled in */
|
||||
#define NFSX_V3SRVSATTR (sizeof (struct nfsv3_sattr))
|
||||
#define NFSX_V3POSTOPATTR (NFSX_V3FATTR + NFSX_UNSIGNED)
|
||||
#define NFSX_V3WCCDATA (NFSX_V3POSTOPATTR + 8 * NFSX_UNSIGNED)
|
||||
#define NFSX_V3COOKIEVERF 8
|
||||
#define NFSX_V3WRITEVERF 8
|
||||
#define NFSX_V3CREATEVERF 8
|
||||
#define NFSX_V3STATFS 52
|
||||
#define NFSX_V3FSINFO 48
|
||||
#define NFSX_V3PATHCONF 24
|
||||
|
||||
/* variants for both versions */
|
||||
#define NFSX_FH(v3) ((v3) ? (NFSX_V3FHMAX + NFSX_UNSIGNED) : \
|
||||
NFSX_V2FH)
|
||||
#define NFSX_SRVFH(v3) ((v3) ? NFSX_V3FH : NFSX_V2FH)
|
||||
#define NFSX_FATTR(v3) ((v3) ? NFSX_V3FATTR : NFSX_V2FATTR)
|
||||
#define NFSX_PREOPATTR(v3) ((v3) ? (7 * NFSX_UNSIGNED) : 0)
|
||||
#define NFSX_POSTOPATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : 0)
|
||||
#define NFSX_POSTOPORFATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : \
|
||||
NFSX_V2FATTR)
|
||||
#define NFSX_WCCDATA(v3) ((v3) ? NFSX_V3WCCDATA : 0)
|
||||
#define NFSX_WCCORFATTR(v3) ((v3) ? NFSX_V3WCCDATA : NFSX_V2FATTR)
|
||||
#define NFSX_SATTR(v3) ((v3) ? NFSX_V3SATTR : NFSX_V2SATTR)
|
||||
#define NFSX_COOKIEVERF(v3) ((v3) ? NFSX_V3COOKIEVERF : 0)
|
||||
#define NFSX_WRITEVERF(v3) ((v3) ? NFSX_V3WRITEVERF : 0)
|
||||
#define NFSX_READDIR(v3) ((v3) ? (5 * NFSX_UNSIGNED) : \
|
||||
(2 * NFSX_UNSIGNED))
|
||||
#define NFSX_STATFS(v3) ((v3) ? NFSX_V3STATFS : NFSX_V2STATFS)
|
||||
|
||||
/* nfs rpc procedure numbers (before version mapping) */
|
||||
#define NFSPROC_NULL 0
|
||||
#define NFSPROC_GETATTR 1
|
||||
#define NFSPROC_SETATTR 2
|
||||
#define NFSPROC_LOOKUP 3
|
||||
#define NFSPROC_ACCESS 4
|
||||
#define NFSPROC_READLINK 5
|
||||
#define NFSPROC_READ 6
|
||||
#define NFSPROC_WRITE 7
|
||||
#define NFSPROC_CREATE 8
|
||||
#define NFSPROC_MKDIR 9
|
||||
#define NFSPROC_SYMLINK 10
|
||||
#define NFSPROC_MKNOD 11
|
||||
#define NFSPROC_REMOVE 12
|
||||
#define NFSPROC_RMDIR 13
|
||||
#define NFSPROC_RENAME 14
|
||||
#define NFSPROC_LINK 15
|
||||
#define NFSPROC_READDIR 16
|
||||
#define NFSPROC_READDIRPLUS 17
|
||||
#define NFSPROC_FSSTAT 18
|
||||
#define NFSPROC_FSINFO 19
|
||||
#define NFSPROC_PATHCONF 20
|
||||
#define NFSPROC_COMMIT 21
|
||||
|
||||
/* And leasing (nqnfs) procedure numbers (must be last) */
|
||||
#define NQNFSPROC_GETLEASE 22
|
||||
#define NQNFSPROC_VACATED 23
|
||||
#define NQNFSPROC_EVICTED 24
|
||||
|
||||
#define NFSPROC_NOOP 25
|
||||
#define NFS_NPROCS 26
|
||||
|
||||
/* Actual Version 2 procedure numbers */
|
||||
#define NFSV2PROC_NULL 0
|
||||
#define NFSV2PROC_GETATTR 1
|
||||
#define NFSV2PROC_SETATTR 2
|
||||
#define NFSV2PROC_NOOP 3
|
||||
#define NFSV2PROC_ROOT NFSV2PROC_NOOP /* Obsolete */
|
||||
#define NFSV2PROC_LOOKUP 4
|
||||
#define NFSV2PROC_READLINK 5
|
||||
#define NFSV2PROC_READ 6
|
||||
#define NFSV2PROC_WRITECACHE NFSV2PROC_NOOP /* Obsolete */
|
||||
#define NFSV2PROC_WRITE 8
|
||||
#define NFSV2PROC_CREATE 9
|
||||
#define NFSV2PROC_REMOVE 10
|
||||
#define NFSV2PROC_RENAME 11
|
||||
#define NFSV2PROC_LINK 12
|
||||
#define NFSV2PROC_SYMLINK 13
|
||||
#define NFSV2PROC_MKDIR 14
|
||||
#define NFSV2PROC_RMDIR 15
|
||||
#define NFSV2PROC_READDIR 16
|
||||
#define NFSV2PROC_STATFS 17
|
||||
|
||||
/*
|
||||
* Constants used by the Version 3 protocol for various RPCs
|
||||
*/
|
||||
#define NFSV3SATTRTIME_DONTCHANGE 0
|
||||
#define NFSV3SATTRTIME_TOSERVER 1
|
||||
#define NFSV3SATTRTIME_TOCLIENT 2
|
||||
|
||||
#define NFSV3ACCESS_READ 0x01
|
||||
#define NFSV3ACCESS_LOOKUP 0x02
|
||||
#define NFSV3ACCESS_MODIFY 0x04
|
||||
#define NFSV3ACCESS_EXTEND 0x08
|
||||
#define NFSV3ACCESS_DELETE 0x10
|
||||
#define NFSV3ACCESS_EXECUTE 0x20
|
||||
|
||||
#define NFSV3WRITE_UNSTABLE 0
|
||||
#define NFSV3WRITE_DATASYNC 1
|
||||
#define NFSV3WRITE_FILESYNC 2
|
||||
|
||||
#define NFSV3CREATE_UNCHECKED 0
|
||||
#define NFSV3CREATE_GUARDED 1
|
||||
#define NFSV3CREATE_EXCLUSIVE 2
|
||||
|
||||
#define NFSV3FSINFO_LINK 0x01
|
||||
#define NFSV3FSINFO_SYMLINK 0x02
|
||||
#define NFSV3FSINFO_HOMOGENEOUS 0x08
|
||||
#define NFSV3FSINFO_CANSETTIME 0x10
|
||||
|
||||
/* Conversion macros */
|
||||
#define vtonfsv2_mode(t,m) \
|
||||
txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \
|
||||
MAKEIMODE((t), (m)))
|
||||
#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777)
|
||||
#define nfstov_mode(a) (fxdr_unsigned(u_short, (a))&07777)
|
||||
#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((long)(a))])
|
||||
#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((long)(a))])
|
||||
#define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(u_long,(a))&0x7]
|
||||
#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(u_long,(a))&0x7]
|
||||
|
||||
/* File types */
|
||||
typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5,
|
||||
NFSOCK=6, NFFIFO=7 } nfstype;
|
||||
|
||||
/* Structs for common parts of the rpc's */
|
||||
/*
|
||||
* File Handle (32 bytes for version 2), variable up to 64 for version 3.
|
||||
* File Handles of up to NFS_SMALLFH in size are stored directly in the
|
||||
* nfs node, whereas larger ones are malloc'd. (This never happens when
|
||||
* NFS_SMALLFH is set to 64.)
|
||||
* NFS_SMALLFH should be in the range of 32 to 64 and be divisible by 4.
|
||||
*/
|
||||
#ifndef NFS_SMALLFH
|
||||
#define NFS_SMALLFH 64
|
||||
#endif
|
||||
union nfsfh {
|
||||
fhandle_t fh_generic;
|
||||
u_char fh_bytes[NFS_SMALLFH];
|
||||
};
|
||||
typedef union nfsfh nfsfh_t;
|
||||
|
||||
struct nfsv2_time {
|
||||
u_long nfsv2_sec;
|
||||
u_long nfsv2_usec;
|
||||
};
|
||||
typedef struct nfsv2_time nfstime2;
|
||||
|
||||
struct nfsv3_time {
|
||||
u_long nfsv3_sec;
|
||||
u_long nfsv3_nsec;
|
||||
};
|
||||
typedef struct nfsv3_time nfstime3;
|
||||
|
||||
/*
|
||||
* Quads are defined as arrays of 2 longs to ensure dense packing for the
|
||||
* protocol and to facilitate xdr conversion.
|
||||
*/
|
||||
struct nfs_uquad {
|
||||
u_long nfsuquad[2];
|
||||
};
|
||||
typedef struct nfs_uquad nfsuint64;
|
||||
|
||||
/*
|
||||
* Used to convert between two u_longs and a u_quad_t.
|
||||
*/
|
||||
union nfs_quadconvert {
|
||||
u_long lval[2];
|
||||
u_quad_t qval;
|
||||
};
|
||||
typedef union nfs_quadconvert nfsquad_t;
|
||||
|
||||
/*
|
||||
* NFS Version 3 special file number.
|
||||
*/
|
||||
struct nfsv3_spec {
|
||||
u_long specdata1;
|
||||
u_long specdata2;
|
||||
};
|
||||
typedef struct nfsv3_spec nfsv3spec;
|
||||
|
||||
/*
|
||||
* File attributes and setable attributes. These structures cover both
|
||||
* NFS version 2 and the version 3 protocol. Note that the union is only
|
||||
* used so that one pointer can refer to both variants. These structures
|
||||
* go out on the wire and must be densely packed, so no quad data types
|
||||
* are used. (all fields are longs or u_longs or structures of same)
|
||||
* NB: You can't do sizeof(struct nfs_fattr), you must use the
|
||||
* NFSX_FATTR(v3) macro.
|
||||
*/
|
||||
struct nfs_fattr {
|
||||
u_long fa_type;
|
||||
u_long fa_mode;
|
||||
u_long fa_nlink;
|
||||
u_long fa_uid;
|
||||
u_long fa_gid;
|
||||
union {
|
||||
struct {
|
||||
u_long nfsv2fa_size;
|
||||
u_long nfsv2fa_blocksize;
|
||||
u_long nfsv2fa_rdev;
|
||||
u_long nfsv2fa_blocks;
|
||||
u_long nfsv2fa_fsid;
|
||||
u_long nfsv2fa_fileid;
|
||||
nfstime2 nfsv2fa_atime;
|
||||
nfstime2 nfsv2fa_mtime;
|
||||
nfstime2 nfsv2fa_ctime;
|
||||
} fa_nfsv2;
|
||||
struct {
|
||||
nfsuint64 nfsv3fa_size;
|
||||
nfsuint64 nfsv3fa_used;
|
||||
nfsv3spec nfsv3fa_rdev;
|
||||
nfsuint64 nfsv3fa_fsid;
|
||||
nfsuint64 nfsv3fa_fileid;
|
||||
nfstime3 nfsv3fa_atime;
|
||||
nfstime3 nfsv3fa_mtime;
|
||||
nfstime3 nfsv3fa_ctime;
|
||||
} fa_nfsv3;
|
||||
} fa_un;
|
||||
};
|
||||
|
||||
/* and some ugly defines for accessing union components */
|
||||
#define fa2_size fa_un.fa_nfsv2.nfsv2fa_size
|
||||
#define fa2_blocksize fa_un.fa_nfsv2.nfsv2fa_blocksize
|
||||
#define fa2_rdev fa_un.fa_nfsv2.nfsv2fa_rdev
|
||||
#define fa2_blocks fa_un.fa_nfsv2.nfsv2fa_blocks
|
||||
#define fa2_fsid fa_un.fa_nfsv2.nfsv2fa_fsid
|
||||
#define fa2_fileid fa_un.fa_nfsv2.nfsv2fa_fileid
|
||||
#define fa2_atime fa_un.fa_nfsv2.nfsv2fa_atime
|
||||
#define fa2_mtime fa_un.fa_nfsv2.nfsv2fa_mtime
|
||||
#define fa2_ctime fa_un.fa_nfsv2.nfsv2fa_ctime
|
||||
#define fa3_size fa_un.fa_nfsv3.nfsv3fa_size
|
||||
#define fa3_used fa_un.fa_nfsv3.nfsv3fa_used
|
||||
#define fa3_rdev fa_un.fa_nfsv3.nfsv3fa_rdev
|
||||
#define fa3_fsid fa_un.fa_nfsv3.nfsv3fa_fsid
|
||||
#define fa3_fileid fa_un.fa_nfsv3.nfsv3fa_fileid
|
||||
#define fa3_atime fa_un.fa_nfsv3.nfsv3fa_atime
|
||||
#define fa3_mtime fa_un.fa_nfsv3.nfsv3fa_mtime
|
||||
#define fa3_ctime fa_un.fa_nfsv3.nfsv3fa_ctime
|
||||
|
||||
struct nfsv2_sattr {
|
||||
u_long sa_mode;
|
||||
u_long sa_uid;
|
||||
u_long sa_gid;
|
||||
u_long sa_size;
|
||||
nfstime2 sa_atime;
|
||||
nfstime2 sa_mtime;
|
||||
};
|
||||
|
||||
/*
|
||||
* NFS Version 3 sattr structure for the new node creation case.
|
||||
*/
|
||||
struct nfsv3_sattr {
|
||||
u_long sa_modetrue;
|
||||
u_long sa_mode;
|
||||
u_long sa_uidtrue;
|
||||
u_long sa_uid;
|
||||
u_long sa_gidtrue;
|
||||
u_long sa_gid;
|
||||
u_long sa_sizefalse;
|
||||
u_long sa_atimetype;
|
||||
nfstime3 sa_atime;
|
||||
u_long sa_mtimetype;
|
||||
nfstime3 sa_mtime;
|
||||
};
|
||||
|
||||
struct nfs_statfs {
|
||||
union {
|
||||
struct {
|
||||
u_long nfsv2sf_tsize;
|
||||
u_long nfsv2sf_bsize;
|
||||
u_long nfsv2sf_blocks;
|
||||
u_long nfsv2sf_bfree;
|
||||
u_long nfsv2sf_bavail;
|
||||
} sf_nfsv2;
|
||||
struct {
|
||||
nfsuint64 nfsv3sf_tbytes;
|
||||
nfsuint64 nfsv3sf_fbytes;
|
||||
nfsuint64 nfsv3sf_abytes;
|
||||
nfsuint64 nfsv3sf_tfiles;
|
||||
nfsuint64 nfsv3sf_ffiles;
|
||||
nfsuint64 nfsv3sf_afiles;
|
||||
u_long nfsv3sf_invarsec;
|
||||
} sf_nfsv3;
|
||||
} sf_un;
|
||||
};
|
||||
|
||||
#define sf_tsize sf_un.sf_nfsv2.nfsv2sf_tsize
|
||||
#define sf_bsize sf_un.sf_nfsv2.nfsv2sf_bsize
|
||||
#define sf_blocks sf_un.sf_nfsv2.nfsv2sf_blocks
|
||||
#define sf_bfree sf_un.sf_nfsv2.nfsv2sf_bfree
|
||||
#define sf_bavail sf_un.sf_nfsv2.nfsv2sf_bavail
|
||||
#define sf_tbytes sf_un.sf_nfsv3.nfsv3sf_tbytes
|
||||
#define sf_fbytes sf_un.sf_nfsv3.nfsv3sf_fbytes
|
||||
#define sf_abytes sf_un.sf_nfsv3.nfsv3sf_abytes
|
||||
#define sf_tfiles sf_un.sf_nfsv3.nfsv3sf_tfiles
|
||||
#define sf_ffiles sf_un.sf_nfsv3.nfsv3sf_ffiles
|
||||
#define sf_afiles sf_un.sf_nfsv3.nfsv3sf_afiles
|
||||
#define sf_invarsec sf_un.sf_nfsv3.nfsv3sf_invarsec
|
||||
|
||||
struct nfsv3_fsinfo {
|
||||
u_long fs_rtmax;
|
||||
u_long fs_rtpref;
|
||||
u_long fs_rtmult;
|
||||
u_long fs_wtmax;
|
||||
u_long fs_wtpref;
|
||||
u_long fs_wtmult;
|
||||
u_long fs_dtpref;
|
||||
nfsuint64 fs_maxfilesize;
|
||||
nfstime3 fs_timedelta;
|
||||
u_long fs_properties;
|
||||
};
|
||||
|
||||
struct nfsv3_pathconf {
|
||||
u_long pc_linkmax;
|
||||
u_long pc_namemax;
|
||||
u_long pc_notrunc;
|
||||
u_long pc_chownrestricted;
|
||||
u_long pc_caseinsensitive;
|
||||
u_long pc_casepreserving;
|
||||
};
|
||||
|
||||
#endif
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsrvcache.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfsrvcache.h,v 1.3 1994/08/21 06:50:13 paul Exp $
|
||||
* $Id: nfsrvcache.h,v 1.4 1994/10/17 17:47:44 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSRVCACHE_H_
|
||||
@ -44,7 +44,7 @@
|
||||
* Definitions for the server recent request cache
|
||||
*/
|
||||
|
||||
#define NFSRVCACHESIZ 256
|
||||
#define NFSRVCACHESIZ 64
|
||||
|
||||
struct nfsrvcache {
|
||||
TAILQ_ENTRY(nfsrvcache) rc_lru; /* LRU chain */
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: nfs.h,v 1.8 1994/11/02 00:11:00 wollman Exp $
|
||||
* $Id: nfs.h,v 1.9 1995/02/14 06:22:18 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFS_H_
|
||||
@ -45,11 +45,12 @@
|
||||
*/
|
||||
|
||||
#define NFS_MAXIOVEC 34
|
||||
#define NFS_HZ 25 /* Ticks per second for NFS timeouts */
|
||||
#define NFS_TIMEO (1*NFS_HZ) /* Default timeout = 1 second */
|
||||
#define NFS_MINTIMEO (1*NFS_HZ) /* Min timeout to use */
|
||||
#define NFS_MAXTIMEO (60*NFS_HZ) /* Max timeout to backoff to */
|
||||
#define NFS_MINIDEMTIMEO (5*NFS_HZ) /* Min timeout for non-idempotent ops*/
|
||||
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
|
||||
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
|
||||
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
|
||||
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
|
||||
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
|
||||
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
|
||||
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
|
||||
#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
|
||||
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
|
||||
@ -62,13 +63,81 @@
|
||||
#endif
|
||||
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
|
||||
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
|
||||
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
|
||||
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
|
||||
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
|
||||
#define NFS_MAXREADDIR NFS_MAXDATA /* Max. size of directory read */
|
||||
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
|
||||
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
|
||||
#define NFS_DIRBLKSIZ 1024 /* Size of an NFS directory block */
|
||||
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
|
||||
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
|
||||
#ifndef NFS_GATHERDELAY
|
||||
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
|
||||
#endif
|
||||
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
|
||||
|
||||
/*
|
||||
* Oddballs
|
||||
*/
|
||||
#define NMOD(a) ((a) % nfs_asyncdaemons)
|
||||
#define NFS_CMPFH(n, f, s) \
|
||||
((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
|
||||
#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
|
||||
#define NFS_SRVMAXDATA(n) \
|
||||
(((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
|
||||
NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* sys/buf.h should be editted to change B_APPENDWRITE --> B_NEEDCOMMIT, but
|
||||
* until then...
|
||||
* Same goes for sys/malloc.h, which needs M_NFSDIROFF,
|
||||
* M_NFSRVDESC and M_NFSBIGFH added.
|
||||
* The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
|
||||
* exclusive create.
|
||||
* The B_INVAFTERWRITE flag should be set to whatever is required by the
|
||||
* buffer cache code to say "Invalidate the block after it is written back".
|
||||
*/
|
||||
#ifndef B_NEEDCOMMIT
|
||||
#define B_NEEDCOMMIT B_APPENDWRITE
|
||||
#endif
|
||||
#ifndef M_NFSRVDESC
|
||||
#define M_NFSRVDESC M_TEMP
|
||||
#endif
|
||||
#ifndef M_NFSDIROFF
|
||||
#define M_NFSDIROFF M_TEMP
|
||||
#endif
|
||||
#ifndef M_NFSBIGFH
|
||||
#define M_NFSBIGFH M_TEMP
|
||||
#endif
|
||||
#ifndef VA_EXCLUSIVE
|
||||
#define VA_EXCLUSIVE 0
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#define B_INVAFTERWRITE B_NOCACHE
|
||||
#else
|
||||
#define B_INVAFTERWRITE B_INVAL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These ifdefs try to handle the differences between the various 4.4BSD-Lite
|
||||
* based vfs interfaces.
|
||||
* btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
|
||||
* differentiate between NetBSD-1.0 and NetBSD-current, so..
|
||||
* I also don't know about BSDi's 2.0 release.
|
||||
*/
|
||||
#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||
#define HAS_VOPLEASE 1
|
||||
#endif
|
||||
#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||
#define HAS_VOPREVOKE 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The IO_METASYNC flag should be implemented for local file systems.
|
||||
* (Until then, it is nothin at all.)
|
||||
*/
|
||||
#ifndef IO_METASYNC
|
||||
#define IO_METASYNC 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the attribute timeout based on how recently the file has been modified.
|
||||
@ -79,6 +148,20 @@
|
||||
((time.tv_sec - (np)->n_mtime) / 10 > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
|
||||
(time.tv_sec - (np)->n_mtime) / 10))
|
||||
|
||||
/*
|
||||
* Expected allocation sizes for major data structures. If the actual size
|
||||
* of the structure exceeds these sizes, then malloc() will be allocating
|
||||
* almost twice the memory required. This is used in nfs_init() to warn
|
||||
* the sysadmin that the size of a structure should be reduced.
|
||||
* (These sizes are always a power of 2. If the kernel malloc() changes
|
||||
* to one that does not allocate space in powers of 2 size, then this all
|
||||
* becomes bunk!)
|
||||
*/
|
||||
#define NFS_NODEALLOC 256
|
||||
#define NFS_MNTALLOC 512
|
||||
#define NFS_SVCALLOC 256
|
||||
#define NFS_UIDALLOC 128
|
||||
|
||||
/*
|
||||
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
|
||||
* should ever try and use it.
|
||||
@ -95,7 +178,12 @@ struct nfsd_srvargs {
|
||||
u_long nsd_haddr; /* Ip address of client */
|
||||
struct ucred nsd_cr; /* Cred. uid maps to */
|
||||
int nsd_authlen; /* Length of auth string (ret) */
|
||||
char *nsd_authstr; /* Auth string (ret) */
|
||||
u_char *nsd_authstr; /* Auth string (ret) */
|
||||
int nsd_verflen; /* and the verfier */
|
||||
u_char *nsd_verfstr;
|
||||
struct timeval nsd_timestamp; /* timestamp from verifier */
|
||||
u_long nsd_ttl; /* credential ttl (sec) */
|
||||
NFSKERBKEY_T nsd_key; /* Session key */
|
||||
};
|
||||
|
||||
struct nfsd_cargs {
|
||||
@ -103,7 +191,10 @@ struct nfsd_cargs {
|
||||
uid_t ncd_authuid; /* Effective uid */
|
||||
int ncd_authtype; /* Type of authenticator */
|
||||
int ncd_authlen; /* Length of authenticator string */
|
||||
char *ncd_authstr; /* Authenticator string */
|
||||
u_char *ncd_authstr; /* Authenticator string */
|
||||
int ncd_verflen; /* and the verifier */
|
||||
u_char *ncd_verfstr;
|
||||
NFSKERBKEY_T ncd_key; /* Session key */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -142,6 +233,7 @@ struct nfsstats {
|
||||
int srvnqnfs_leases;
|
||||
int srvnqnfs_maxleases;
|
||||
int srvnqnfs_getleases;
|
||||
int srvvop_writes;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -173,7 +265,7 @@ struct nfsstats {
|
||||
* such as SIGALRM will not expect file I/O system calls to be interrupted
|
||||
* by them and break.
|
||||
*/
|
||||
#ifdef KERNEL
|
||||
#if defined(KERNEL) || defined(_KERNEL)
|
||||
|
||||
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
|
||||
|
||||
@ -224,17 +316,29 @@ TAILQ_HEAD(, nfsreq) nfs_reqq;
|
||||
#define R_MUSTRESEND 0x40 /* Must resend request */
|
||||
#define R_GETONEREP 0x80 /* Probe for one reply only */
|
||||
|
||||
extern struct nfsstats nfsstats;
|
||||
|
||||
/*
|
||||
* A list of nfssvc_sock structures is maintained with all the sockets
|
||||
* that require service by the nfsd.
|
||||
* The nfsuid structs hang off of the nfssvc_sock structs in both lru
|
||||
* and uid hash lists.
|
||||
*/
|
||||
#define NUIDHASHSIZ 32
|
||||
#ifndef NFS_UIDHASHSIZ
|
||||
#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
|
||||
#endif
|
||||
#define NUIDHASH(sock, uid) \
|
||||
(&(sock)->ns_uidhashtbl[(uid) & (sock)->ns_uidhash])
|
||||
(&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
|
||||
#ifndef NFS_WDELAYHASHSIZ
|
||||
#define NFS_WDELAYHASHSIZ 16 /* and with this */
|
||||
#endif
|
||||
#define NWDELAYHASH(sock, f) \
|
||||
(&(sock)->ns_wdelayhashtbl[(*((u_long *)(f))) % NFS_WDELAYHASHSIZ])
|
||||
#ifndef NFS_MUIDHASHSIZ
|
||||
#define NFS_MUIDHASHSIZ 67 /* Tune the size of nfsmount with this */
|
||||
#endif
|
||||
#define NMUIDHASH(nmp, uid) \
|
||||
(&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
|
||||
#define NFSNOHASH(fhsum) \
|
||||
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
|
||||
|
||||
/*
|
||||
* Network address hash list element
|
||||
@ -248,35 +352,41 @@ struct nfsuid {
|
||||
TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
|
||||
LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
|
||||
int nu_flag; /* Flags */
|
||||
uid_t nu_uid; /* Uid mapped by this entry */
|
||||
union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
|
||||
struct ucred nu_cr; /* Cred uid mapped to */
|
||||
int nu_expire; /* Expiry time (sec) */
|
||||
struct timeval nu_timestamp; /* Kerb. timestamp */
|
||||
u_long nu_nickname; /* Nickname on server */
|
||||
NFSKERBKEY_T nu_key; /* and session key */
|
||||
};
|
||||
|
||||
#define nu_inetaddr nu_haddr.had_inetaddr
|
||||
#define nu_nam nu_haddr.had_nam
|
||||
/* Bits for nu_flag */
|
||||
#define NU_INETADDR 0x1
|
||||
#define NU_NAM 0x2
|
||||
#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
|
||||
|
||||
struct nfssvc_sock {
|
||||
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
|
||||
TAILQ_HEAD(, nfsuid) ns_uidlruhead;
|
||||
LIST_HEAD(, nfsuid) *ns_uidhashtbl;
|
||||
u_long ns_uidhash;
|
||||
|
||||
int ns_flag;
|
||||
u_long ns_sref;
|
||||
struct file *ns_fp;
|
||||
struct socket *ns_so;
|
||||
int ns_solock;
|
||||
struct mbuf *ns_nam;
|
||||
int ns_cc;
|
||||
struct mbuf *ns_raw;
|
||||
struct mbuf *ns_rawend;
|
||||
int ns_reclen;
|
||||
struct mbuf *ns_rec;
|
||||
struct mbuf *ns_recend;
|
||||
struct mbuf *ns_frag;
|
||||
int ns_flag;
|
||||
int ns_solock;
|
||||
int ns_cc;
|
||||
int ns_reclen;
|
||||
int ns_numuids;
|
||||
u_long ns_sref;
|
||||
LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
|
||||
LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
|
||||
LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
|
||||
};
|
||||
|
||||
/* Bits for "ns_flag" */
|
||||
@ -285,6 +395,7 @@ struct nfssvc_sock {
|
||||
#define SLP_NEEDQ 0x04
|
||||
#define SLP_DISCONN 0x08
|
||||
#define SLP_GETSTREAM 0x10
|
||||
#define SLP_LASTFRAG 0x20
|
||||
#define SLP_ALLFLAGS 0xff
|
||||
|
||||
TAILQ_HEAD(, nfssvc_sock) nfssvc_sockhead;
|
||||
@ -296,73 +407,124 @@ int nfssvc_sockhead_flag;
|
||||
* One of these structures is allocated for each nfsd.
|
||||
*/
|
||||
struct nfsd {
|
||||
TAILQ_ENTRY(nfsd) nd_chain; /* List of all nfsd's */
|
||||
int nd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nd_slp; /* Current socket */
|
||||
struct mbuf *nd_nam; /* Client addr for datagram req. */
|
||||
struct mbuf *nd_mrep; /* Req. mbuf list */
|
||||
struct mbuf *nd_md;
|
||||
caddr_t nd_dpos; /* Position in list */
|
||||
int nd_procnum; /* RPC procedure number */
|
||||
u_long nd_retxid; /* RPC xid */
|
||||
int nd_repstat; /* Reply status value */
|
||||
struct ucred nd_cr; /* Credentials for req. */
|
||||
int nd_nqlflag; /* Leasing flag */
|
||||
u_long nd_duration; /* Lease duration */
|
||||
int nd_authlen; /* Authenticator len */
|
||||
u_char nd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
|
||||
struct proc *nd_procp; /* Proc ptr */
|
||||
TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
|
||||
int nfsd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nfsd_slp; /* Current socket */
|
||||
int nfsd_authlen; /* Authenticator len */
|
||||
u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
|
||||
int nfsd_verflen; /* and the Verifier */
|
||||
u_char nfsd_verfstr[RPCVERF_MAXSIZ];
|
||||
struct proc *nfsd_procp; /* Proc ptr */
|
||||
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
|
||||
};
|
||||
|
||||
/* Bits for "nd_flag" */
|
||||
/* Bits for "nfsd_flag" */
|
||||
#define NFSD_WAITING 0x01
|
||||
#define NFSD_REQINPROG 0x02
|
||||
#define NFSD_NEEDAUTH 0x04
|
||||
#define NFSD_AUTHFAIL 0x08
|
||||
|
||||
/*
|
||||
* This structure is used by the server for describing each request.
|
||||
* Some fields are used only when write request gathering is performed.
|
||||
*/
|
||||
struct nfsrv_descript {
|
||||
u_quad_t nd_time; /* Write deadline (usec) */
|
||||
off_t nd_off; /* Start byte offset */
|
||||
off_t nd_eoff; /* and end byte offset */
|
||||
LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
|
||||
LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
|
||||
LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
|
||||
struct mbuf *nd_mrep; /* Request mbuf list */
|
||||
struct mbuf *nd_md; /* Current dissect mbuf */
|
||||
struct mbuf *nd_mreq; /* Reply mbuf list */
|
||||
struct mbuf *nd_nam; /* and socket addr */
|
||||
struct mbuf *nd_nam2; /* return socket addr */
|
||||
caddr_t nd_dpos; /* Current dissect pos */
|
||||
int nd_procnum; /* RPC # */
|
||||
int nd_stable; /* storage type */
|
||||
int nd_flag; /* nd_flag */
|
||||
int nd_len; /* Length of this write */
|
||||
int nd_repstat; /* Reply status */
|
||||
u_long nd_retxid; /* Reply xid */
|
||||
u_long nd_duration; /* Lease duration */
|
||||
struct timeval nd_starttime; /* Time RPC initiated */
|
||||
fhandle_t nd_fh; /* File handle */
|
||||
struct ucred nd_cr; /* Credentials */
|
||||
};
|
||||
|
||||
/* Bits for "nd_flag" */
|
||||
#define ND_READ LEASE_READ
|
||||
#define ND_WRITE LEASE_WRITE
|
||||
#define ND_CHECK 0x04
|
||||
#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
|
||||
#define ND_NFSV3 0x08
|
||||
#define ND_NQNFS 0x10
|
||||
#define ND_KERBNICK 0x20
|
||||
#define ND_KERBFULL 0x40
|
||||
#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
|
||||
|
||||
TAILQ_HEAD(, nfsd) nfsd_head;
|
||||
int nfsd_head_flag;
|
||||
#define NFSD_CHECKSLP 0x01
|
||||
|
||||
/*
|
||||
* These macros compare nfsrv_descript structures.
|
||||
*/
|
||||
#define NFSW_CONTIG(o, n) \
|
||||
((o)->nd_eoff >= (n)->nd_off && \
|
||||
!bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
|
||||
|
||||
#define NFSW_SAMECRED(o, n) \
|
||||
(((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
|
||||
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
|
||||
sizeof (struct ucred)))
|
||||
|
||||
int nfs_reply __P((struct nfsreq *));
|
||||
int nfs_getreq __P((struct nfsd *,int));
|
||||
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
|
||||
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
|
||||
int nfs_rephead __P((int,struct nfsd *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_rephead __P((int,struct nfsrv_descript *,struct nfssvc_sock *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_sndlock __P((int *,struct nfsreq *));
|
||||
int nfs_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
|
||||
int nfs_vinvalbuf __P((struct vnode *,int,struct ucred *,struct proc *,int));
|
||||
int nfs_readrpc __P((struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int));
|
||||
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int *,int *));
|
||||
int nfs_readdirrpc __P((register struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
|
||||
int nfs_asyncio __P((struct buf *,struct ucred *));
|
||||
int nfs_doio __P((struct buf *,struct ucred *,struct proc *));
|
||||
int nfs_readlinkrpc __P((struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_sigintr __P((struct nfsmount *,struct nfsreq *r,struct proc *));
|
||||
int nfs_readdirlookrpc __P((struct vnode *,register struct uio *,struct ucred *));
|
||||
int nfs_readdirplusrpc __P((struct vnode *,register struct uio *,struct ucred *));
|
||||
int nfsm_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
|
||||
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *));
|
||||
void nfsm_srvfattr __P((struct nfsrv_descript *,struct vattr *,struct nfs_fattr *));
|
||||
void nfsm_srvwcc __P((struct nfsrv_descript *,int,struct vattr *,int,struct vattr *,struct mbuf **,char **));
|
||||
void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct mbuf **,char **));
|
||||
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *,int));
|
||||
int nfsrv_access __P((struct vnode *,int,struct ucred *,int,struct proc *));
|
||||
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
|
||||
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
|
||||
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct proc *));
|
||||
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
|
||||
void nfsm_adj __P((struct mbuf *,int,int));
|
||||
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
|
||||
void nfsrv_initcache __P((void));
|
||||
int nfs_rcvlock __P((struct nfsreq *));
|
||||
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,int *,char **,int *));
|
||||
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,char **,int *,char *,int *,NFSKERBKEY_T));
|
||||
int nfs_getnickauth __P((struct nfsmount *,struct ucred *,char **,int *,char *,int));
|
||||
int nfs_savenickauth __P((struct nfsmount *,struct ucred *,int,NFSKERBKEY_T,struct mbuf **,char **,struct mbuf *));
|
||||
int nfs_msg __P((struct proc *,char *,char *));
|
||||
int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
|
||||
int nfsrv_getstream __P((struct nfssvc_sock *,int));
|
||||
void nfs_nhinit __P((void));
|
||||
void nfs_timer __P((void*));
|
||||
struct nfsnodehashhead * nfs_hash __P((nfsv2fh_t *));
|
||||
u_long nfs_hash __P((nfsfh_t *,int));
|
||||
int nfssvc_iod __P((struct proc *));
|
||||
int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,struct proc *));
|
||||
int nfssvc_addsock __P((struct file *,struct mbuf *));
|
||||
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *));
|
||||
int nfsrv_getcache __P((struct mbuf *,struct nfsd *,struct mbuf **));
|
||||
void nfsrv_updatecache __P((struct mbuf *,struct nfsd *,int,struct mbuf *));
|
||||
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
|
||||
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
|
||||
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
|
||||
int mountnfs __P((struct nfs_args *,struct mount *,struct mbuf *,char *,char *,struct vnode **));
|
||||
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
|
||||
int nfs_getattrcache __P((struct vnode *,struct vattr *));
|
||||
@ -370,9 +532,20 @@ int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
|
||||
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
|
||||
int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
|
||||
void nfsrv_init __P((int));
|
||||
void nfs_clearcommit __P((struct mount *));
|
||||
int nfsrv_errmap __P((struct nfsrv_descript *, int));
|
||||
void nfsrvw_coalesce __P((struct nfsrv_descript *,struct nfsrv_descript *));
|
||||
void nfsrvw_sort __P((gid_t [],int));
|
||||
void nfsrv_setcred __P((struct ucred *,struct ucred *));
|
||||
int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
|
||||
int nfs_writebp __P((struct buf *,int));
|
||||
int nfsrv_vput __P(( struct vnode * ));
|
||||
int nfsrv_vrele __P(( struct vnode * ));
|
||||
int nfsrv_vmio __P(( struct vnode * ));
|
||||
int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
|
||||
struct proc *, struct mbuf **));
|
||||
int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
|
||||
struct proc *p));
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)mount.h 8.13 (Berkeley) 3/27/94
|
||||
* $Id: mount.h,v 1.18 1995/05/21 21:39:24 davidg Exp $
|
||||
* $Id: mount.h,v 1.19 1995/05/30 08:14:28 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_MOUNT_H_
|
||||
@ -402,15 +402,6 @@ struct iso_args {
|
||||
#endif /* CD9660 */
|
||||
|
||||
#ifdef NFS
|
||||
/*
|
||||
* File Handle (32 bytes for version 2), variable up to 1024 for version 3
|
||||
*/
|
||||
union nfsv2fh {
|
||||
fhandle_t fh_generic;
|
||||
u_char fh_bytes[32];
|
||||
};
|
||||
typedef union nfsv2fh nfsv2fh_t;
|
||||
|
||||
/*
|
||||
* Arguments to mount NFS
|
||||
*/
|
||||
@ -419,10 +410,12 @@ struct nfs_args {
|
||||
int addrlen; /* length of address */
|
||||
int sotype; /* Socket type */
|
||||
int proto; /* and Protocol */
|
||||
nfsv2fh_t *fh; /* File handle to be mounted */
|
||||
u_char *fh; /* File handle to be mounted */
|
||||
int fhsize; /* Size, in bytes, of fh */
|
||||
int flags; /* flags */
|
||||
int wsize; /* write size in bytes */
|
||||
int rsize; /* read size in bytes */
|
||||
int readdirsize; /* readdir size in bytes */
|
||||
int timeo; /* initial timeout in .1 secs */
|
||||
int retrans; /* times to retry send */
|
||||
int maxgrouplist; /* Max. size of group list */
|
||||
@ -432,7 +425,6 @@ struct nfs_args {
|
||||
char *hostname; /* server's name */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* NFS mount option flags
|
||||
*/
|
||||
@ -445,16 +437,19 @@ struct nfs_args {
|
||||
#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
|
||||
#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
|
||||
#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
|
||||
#define NFSMNT_MYWRITE 0x00000200 /* Assume writes were mine */
|
||||
#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
|
||||
#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
|
||||
#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
|
||||
#define NFSMNT_RDIRALOOK 0x00001000 /* Do lookup with readdir (nqnfs) */
|
||||
#define NFSMNT_LEASETERM 0x00002000 /* set lease term (nqnfs) */
|
||||
#define NFSMNT_READAHEAD 0x00004000 /* set read ahead */
|
||||
#define NFSMNT_DEADTHRESH 0x00008000 /* set dead server retry thresh */
|
||||
#define NFSMNT_NQLOOKLEASE 0x00010000 /* Get lease for lookup */
|
||||
#define NFSMNT_RESVPORT 0x00020000 /* Allocate a reserved port */
|
||||
#define NFSMNT_INTERNAL 0xffe00000 /* Bits set internally */
|
||||
#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
|
||||
#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
|
||||
#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
|
||||
#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
|
||||
#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
|
||||
#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
|
||||
#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
|
||||
#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
|
||||
#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
|
||||
#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
|
||||
#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
|
||||
#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
|
||||
#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
|
||||
|
@ -62,7 +62,7 @@ static char sccsid[] = "@(#)fstat.c 8.1 (Berkeley) 6/6/93";
|
||||
#undef KERNEL
|
||||
#define NFS
|
||||
#include <sys/mount.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
|
@ -43,13 +43,14 @@ static char copyright[] =
|
||||
#ifndef lint
|
||||
/*static char sccsid[] = "From: @(#)nfsstat.c 8.1 (Berkeley) 6/6/93";*/
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
"$Id: nfsstat.c,v 1.2 1994/10/23 23:25:43 wollman Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
@ -73,7 +74,10 @@ kvm_t *kd;
|
||||
|
||||
static int deadkernel = 0;
|
||||
|
||||
void intpr(void), printhdr(void), sidewaysintpr(u_int), usage(void);
|
||||
void intpr __P((void));
|
||||
void printhdr __P((void));
|
||||
void sidewaysintpr __P((u_int));
|
||||
void usage __P((void));
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
@ -146,7 +150,8 @@ main(argc, argv)
|
||||
* for dead ones.
|
||||
*/
|
||||
void
|
||||
readstats(struct nfsstats *stp)
|
||||
readstats(stp)
|
||||
struct nfsstats *stp;
|
||||
{
|
||||
if(deadkernel) {
|
||||
if(kvm_read(kd, (u_long)nl[N_NFSSTAT].n_value, stp,
|
||||
@ -171,7 +176,7 @@ readstats(struct nfsstats *stp)
|
||||
* Print a description of the nfs stats.
|
||||
*/
|
||||
void
|
||||
intpr(void)
|
||||
intpr()
|
||||
{
|
||||
struct nfsstats nfsstats;
|
||||
|
||||
@ -193,7 +198,7 @@ intpr(void)
|
||||
nfsstats.rpccnt[NFSPROC_REMOVE]);
|
||||
printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
|
||||
"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
|
||||
"Readdir", "Statfs", "RdirLook");
|
||||
"Readdir", "RdirPlus", "Access");
|
||||
printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
|
||||
nfsstats.rpccnt[NFSPROC_RENAME],
|
||||
nfsstats.rpccnt[NFSPROC_LINK],
|
||||
@ -201,11 +206,17 @@ intpr(void)
|
||||
nfsstats.rpccnt[NFSPROC_MKDIR],
|
||||
nfsstats.rpccnt[NFSPROC_RMDIR],
|
||||
nfsstats.rpccnt[NFSPROC_READDIR],
|
||||
nfsstats.rpccnt[NFSPROC_STATFS],
|
||||
nfsstats.rpccnt[NQNFSPROC_READDIRLOOK]);
|
||||
printf("%9.9s %9.9s %9.9s\n",
|
||||
nfsstats.rpccnt[NFSPROC_READDIRPLUS],
|
||||
nfsstats.rpccnt[NFSPROC_ACCESS]);
|
||||
printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
|
||||
"Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit",
|
||||
"GLease", "Vacate", "Evict");
|
||||
printf("%9d %9d %9d\n",
|
||||
printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
|
||||
nfsstats.rpccnt[NFSPROC_MKNOD],
|
||||
nfsstats.rpccnt[NFSPROC_FSSTAT],
|
||||
nfsstats.rpccnt[NFSPROC_FSINFO],
|
||||
nfsstats.rpccnt[NFSPROC_PATHCONF],
|
||||
nfsstats.rpccnt[NFSPROC_COMMIT],
|
||||
nfsstats.rpccnt[NQNFSPROC_GETLEASE],
|
||||
nfsstats.rpccnt[NQNFSPROC_VACATED],
|
||||
nfsstats.rpccnt[NQNFSPROC_EVICTED]);
|
||||
@ -256,7 +267,7 @@ intpr(void)
|
||||
nfsstats.srvrpccnt[NFSPROC_REMOVE]);
|
||||
printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
|
||||
"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
|
||||
"Readdir", "Statfs", "RdirLook");
|
||||
"Readdir", "RdirPlus", "Access");
|
||||
printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
|
||||
nfsstats.srvrpccnt[NFSPROC_RENAME],
|
||||
nfsstats.srvrpccnt[NFSPROC_LINK],
|
||||
@ -264,11 +275,17 @@ intpr(void)
|
||||
nfsstats.srvrpccnt[NFSPROC_MKDIR],
|
||||
nfsstats.srvrpccnt[NFSPROC_RMDIR],
|
||||
nfsstats.srvrpccnt[NFSPROC_READDIR],
|
||||
nfsstats.srvrpccnt[NFSPROC_STATFS],
|
||||
nfsstats.srvrpccnt[NQNFSPROC_READDIRLOOK]);
|
||||
printf("%9.9s %9.9s %9.9s\n",
|
||||
nfsstats.srvrpccnt[NFSPROC_READDIRPLUS],
|
||||
nfsstats.srvrpccnt[NFSPROC_ACCESS]);
|
||||
printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
|
||||
"Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit",
|
||||
"GLease", "Vacate", "Evict");
|
||||
printf("%9d %9d %9d\n",
|
||||
printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
|
||||
nfsstats.srvrpccnt[NFSPROC_MKNOD],
|
||||
nfsstats.srvrpccnt[NFSPROC_FSSTAT],
|
||||
nfsstats.srvrpccnt[NFSPROC_FSINFO],
|
||||
nfsstats.srvrpccnt[NFSPROC_PATHCONF],
|
||||
nfsstats.srvrpccnt[NFSPROC_COMMIT],
|
||||
nfsstats.srvrpccnt[NQNFSPROC_GETLEASE],
|
||||
nfsstats.srvrpccnt[NQNFSPROC_VACATED],
|
||||
nfsstats.srvrpccnt[NQNFSPROC_EVICTED]);
|
||||
@ -291,6 +308,13 @@ intpr(void)
|
||||
nfsstats.srvnqnfs_leases,
|
||||
nfsstats.srvnqnfs_maxleases,
|
||||
nfsstats.srvnqnfs_getleases);
|
||||
printf("Server Write Gathering:\n");
|
||||
printf("%9.9s %9.9s %9.9s\n",
|
||||
"WriteOps", "WriteRPC", "Opsaved");
|
||||
printf("%9d %9d %9d\n",
|
||||
nfsstats.srvvop_writes,
|
||||
nfsstats.srvrpccnt[NFSPROC_WRITE],
|
||||
nfsstats.srvrpccnt[NFSPROC_WRITE] - nfsstats.srvvop_writes);
|
||||
}
|
||||
|
||||
u_char signalled; /* set if alarm goes off "early" */
|
||||
@ -321,23 +345,25 @@ sidewaysintpr(interval)
|
||||
}
|
||||
readstats(&nfsstats);
|
||||
printf("Client: %8d %8d %8d %8d %8d %8d %8d %8d\n",
|
||||
nfsstats.rpccnt[1]-lastst.rpccnt[1],
|
||||
nfsstats.rpccnt[4]-lastst.rpccnt[4],
|
||||
nfsstats.rpccnt[5]-lastst.rpccnt[5],
|
||||
nfsstats.rpccnt[6]-lastst.rpccnt[6],
|
||||
nfsstats.rpccnt[8]-lastst.rpccnt[8],
|
||||
nfsstats.rpccnt[11]-lastst.rpccnt[11],
|
||||
nfsstats.rpccnt[12]-lastst.rpccnt[12],
|
||||
nfsstats.rpccnt[16]-lastst.rpccnt[16]);
|
||||
nfsstats.rpccnt[NFSPROC_GETATTR]-lastst.rpccnt[NFSPROC_GETATTR],
|
||||
nfsstats.rpccnt[NFSPROC_LOOKUP]-lastst.rpccnt[NFSPROC_LOOKUP],
|
||||
nfsstats.rpccnt[NFSPROC_READLINK]-lastst.rpccnt[NFSPROC_READLINK],
|
||||
nfsstats.rpccnt[NFSPROC_READ]-lastst.rpccnt[NFSPROC_READ],
|
||||
nfsstats.rpccnt[NFSPROC_WRITE]-lastst.rpccnt[NFSPROC_WRITE],
|
||||
nfsstats.rpccnt[NFSPROC_RENAME]-lastst.rpccnt[NFSPROC_RENAME],
|
||||
nfsstats.rpccnt[NFSPROC_ACCESS]-lastst.rpccnt[NFSPROC_ACCESS],
|
||||
(nfsstats.rpccnt[NFSPROC_READDIR]-lastst.rpccnt[NFSPROC_READDIR])
|
||||
+(nfsstats.rpccnt[NFSPROC_READDIRPLUS]-lastst.rpccnt[NFSPROC_READDIRPLUS]));
|
||||
printf("Server: %8d %8d %8d %8d %8d %8d %8d %8d\n",
|
||||
nfsstats.srvrpccnt[1]-lastst.srvrpccnt[1],
|
||||
nfsstats.srvrpccnt[4]-lastst.srvrpccnt[4],
|
||||
nfsstats.srvrpccnt[5]-lastst.srvrpccnt[5],
|
||||
nfsstats.srvrpccnt[6]-lastst.srvrpccnt[6],
|
||||
nfsstats.srvrpccnt[8]-lastst.srvrpccnt[8],
|
||||
nfsstats.srvrpccnt[11]-lastst.srvrpccnt[11],
|
||||
nfsstats.srvrpccnt[12]-lastst.srvrpccnt[12],
|
||||
nfsstats.srvrpccnt[16]-lastst.srvrpccnt[16]);
|
||||
nfsstats.srvrpccnt[NFSPROC_GETATTR]-lastst.srvrpccnt[NFSPROC_GETATTR],
|
||||
nfsstats.srvrpccnt[NFSPROC_LOOKUP]-lastst.srvrpccnt[NFSPROC_LOOKUP],
|
||||
nfsstats.srvrpccnt[NFSPROC_READLINK]-lastst.srvrpccnt[NFSPROC_READLINK],
|
||||
nfsstats.srvrpccnt[NFSPROC_READ]-lastst.srvrpccnt[NFSPROC_READ],
|
||||
nfsstats.srvrpccnt[NFSPROC_WRITE]-lastst.srvrpccnt[NFSPROC_WRITE],
|
||||
nfsstats.srvrpccnt[NFSPROC_RENAME]-lastst.srvrpccnt[NFSPROC_RENAME],
|
||||
nfsstats.srvrpccnt[NFSPROC_ACCESS]-lastst.srvrpccnt[NFSPROC_ACCESS],
|
||||
(nfsstats.srvrpccnt[NFSPROC_READDIR]-lastst.srvrpccnt[NFSPROC_READDIR])
|
||||
+(nfsstats.srvrpccnt[NFSPROC_READDIRPLUS]-lastst.srvrpccnt[NFSPROC_READDIRPLUS]));
|
||||
lastst = nfsstats;
|
||||
fflush(stdout);
|
||||
oldmask = sigblock(sigmask(SIGALRM));
|
||||
@ -355,7 +381,7 @@ printhdr()
|
||||
{
|
||||
printf(" %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s\n",
|
||||
"Getattr", "Lookup", "Readlink", "Read", "Write", "Rename",
|
||||
"Link", "Readdir");
|
||||
"Access", "Readdir");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
.Nd show remote nfs mounts on host
|
||||
.Sh SYNOPSIS
|
||||
.Nm showmount
|
||||
.Op Fl ade
|
||||
.Op Fl ade3
|
||||
.Op Ar host
|
||||
.Sh DESCRIPTION
|
||||
.Nm Showmount
|
||||
@ -56,7 +56,10 @@ file systems mounted
|
||||
on the host. See
|
||||
.%T "NFS: Network File System Protocol Specification" ,
|
||||
RFC 1094,
|
||||
Appendix A ,
|
||||
Appendix A,
|
||||
and
|
||||
.%T "NFS: Network File System Version 3 Protocol Specification" ,
|
||||
Appendix I,
|
||||
for a detailed description of the protocol.
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a
|
||||
@ -70,6 +73,8 @@ List directory paths of mount points instead of hosts
|
||||
Show the
|
||||
.Ar host Ns 's
|
||||
exports list
|
||||
.It Fl 3
|
||||
Use mount protocol Version 3, compatible with NFS Version 3.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr mount 1 ,
|
||||
|
@ -90,6 +90,7 @@ int xdr_mntdump(), xdr_exports();
|
||||
* This command queries the NFS mount daemon for it's mount list and/or
|
||||
* it's exports list and prints them out.
|
||||
* See "NFS: Network File System Protocol Specification, RFC1094, Appendix A"
|
||||
* and the "Network File System Protocol XXX.."
|
||||
* for detailed information on the protocol.
|
||||
*/
|
||||
main(argc, argv)
|
||||
@ -101,12 +102,12 @@ main(argc, argv)
|
||||
register struct grouplist *grp;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
register int rpcs = 0;
|
||||
register int rpcs = 0, mntvers = 1;
|
||||
char ch;
|
||||
char *host;
|
||||
int estat;
|
||||
|
||||
while ((ch = getopt(argc, argv, "ade")) != EOF)
|
||||
while ((ch = getopt(argc, argv, "ade3")) != EOF)
|
||||
switch((char)ch) {
|
||||
case 'a':
|
||||
if (type == 0) {
|
||||
@ -125,6 +126,9 @@ main(argc, argv)
|
||||
case 'e':
|
||||
rpcs |= DOEXPORTS;
|
||||
break;
|
||||
case '3':
|
||||
mntvers = 3;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
@ -141,7 +145,7 @@ main(argc, argv)
|
||||
rpcs = DODUMP;
|
||||
|
||||
if (rpcs & DODUMP)
|
||||
if ((estat = callrpc(host, RPCPROG_MNT, RPCMNT_VER1,
|
||||
if ((estat = callrpc(host, RPCPROG_MNT, mntvers,
|
||||
RPCMNT_DUMP, xdr_void, (char *)0,
|
||||
xdr_mntdump, (char *)&mntdump)) != 0) {
|
||||
clnt_perrno(estat);
|
||||
@ -149,7 +153,7 @@ main(argc, argv)
|
||||
exit(1);
|
||||
}
|
||||
if (rpcs & DOEXPORTS)
|
||||
if ((estat = callrpc(host, RPCPROG_MNT, RPCMNT_VER1,
|
||||
if ((estat = callrpc(host, RPCPROG_MNT, mntvers,
|
||||
RPCMNT_EXPORT, xdr_void, (char *)0,
|
||||
xdr_exports, (char *)&exports)) != 0) {
|
||||
clnt_perrno(estat);
|
||||
|
@ -37,7 +37,7 @@
|
||||
*
|
||||
* @(#)afs_ops.c 8.1 (Berkeley) 6/6/93
|
||||
*
|
||||
* $Id: afs_ops.c,v 1.1.1.1 1994/05/26 05:22:03 rgrimes Exp $
|
||||
* $Id: afs_ops.c,v 1.2 1995/05/30 03:45:43 rgrimes Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -144,6 +144,9 @@ char *opts;
|
||||
}
|
||||
|
||||
NFS_FH_DREF(nfs_args.fh, (NFS_FH_TYPE) fhp);
|
||||
#ifdef NFSv3
|
||||
nfs_args.fhsize = FHSIZE;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create sockaddr to point to the local machine. 127.0.0.1
|
||||
|
@ -35,7 +35,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: nfs_ops.c,v 1.2 1995/02/13 01:56:22 wpaul Exp $
|
||||
* $Id: nfs_ops.c,v 1.3 1995/05/30 03:45:52 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
@ -529,6 +529,9 @@ mntfs *mf;
|
||||
* set mount args
|
||||
*/
|
||||
NFS_FH_DREF(nfs_args.fh, (NFS_FH_TYPE) fhp->fhstatus_u.fhs_fhandle);
|
||||
#ifdef NFSv3
|
||||
nfs_args.fhsize = FHSIZE;
|
||||
#endif
|
||||
|
||||
#ifdef ULTRIX_HACK
|
||||
nfs_args.optstr = mnt.mnt_opts;
|
||||
|
@ -37,7 +37,7 @@
|
||||
*
|
||||
* @(#)os-bsd44.h 8.1 (Berkeley) 6/6/93
|
||||
*
|
||||
* $Id: os-bsd44.h,v 1.1.1.1 1994/05/26 05:22:07 rgrimes Exp $
|
||||
* $Id: os-bsd44.h,v 1.2 1995/01/20 20:58:54 wollman Exp $
|
||||
*
|
||||
* 4.4 BSD definitions for Amd (automounter)
|
||||
*/
|
||||
@ -61,6 +61,7 @@
|
||||
*/
|
||||
#define NFS_44
|
||||
#define HAS_TCP_NFS
|
||||
#define NFSv3
|
||||
|
||||
/*
|
||||
* Does this OS have NDBM support?
|
||||
@ -170,7 +171,11 @@ struct mntent {
|
||||
* Type of a file handle
|
||||
*/
|
||||
#undef NFS_FH_TYPE
|
||||
#ifdef NFSv3
|
||||
#define NFS_FH_TYPE fhandle_t *
|
||||
#else
|
||||
#define NFS_FH_TYPE nfsv2fh_t *
|
||||
#endif
|
||||
|
||||
/*
|
||||
* How to get a mount list
|
||||
|
@ -49,7 +49,9 @@ file specifies remote mount points for the
|
||||
mount protocol per the
|
||||
.Tn NFS
|
||||
server specification; see
|
||||
.%T "Network File System Protocol Specification \\*(tNRFC\\*(sP 1094, Appendix A" .
|
||||
.%T "Network File System Protocol Specification \\*(tNRFC\\*(sP 1094, Appendix A"
|
||||
and
|
||||
.%T "NFS: Network File System Version 3 Specification, Appendix I" .
|
||||
.Pp
|
||||
Each line in the file
|
||||
(other than comment lines that begin with a #)
|
||||
@ -71,7 +73,8 @@ The second is to specify the pathname of the root of the filesystem
|
||||
followed by the
|
||||
.Fl alldirs
|
||||
flag;
|
||||
this form allows the host(s) to mount any directory within the filesystem.
|
||||
this form allows the host(s) to mount at any point within the filesystem,
|
||||
including regular files if the ``-r'' option is used on mountd.
|
||||
The pathnames must not have any symbolic links in them and should not have
|
||||
any "." or ".." components.
|
||||
Mount points for a filesystem may appear on multiple lines each with
|
||||
@ -140,8 +143,7 @@ The
|
||||
.Fl kerb
|
||||
option specifies that the Kerberos authentication server should be
|
||||
used to authenticate and map client credentials.
|
||||
(Note that this is NOT Sun NFS compatible and
|
||||
is supported for TCP transport only.)
|
||||
This requires that the kernel be built with the NFSKERB option.
|
||||
.Pp
|
||||
The
|
||||
.Fl ro
|
||||
|
@ -30,7 +30,7 @@
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" From: @(#)mountd.8 8.1 (Berkeley) 6/9/93
|
||||
.\" $Id: mountd.8,v 1.2 1994/09/22 22:16:49 wollman Exp $
|
||||
.\" $Id: mountd.8,v 1.3 1995/02/22 21:42:48 ats Exp $
|
||||
.\"
|
||||
.Dd September 22, 1994
|
||||
.Dt MOUNTD 8
|
||||
@ -42,7 +42,7 @@
|
||||
mount requests
|
||||
.Sh SYNOPSIS
|
||||
.Nm /sbin/mountd
|
||||
.Op Fl n
|
||||
.Op Fl nr
|
||||
.Op Ar exportsfile
|
||||
.Sh DESCRIPTION
|
||||
.Xr Mountd
|
||||
@ -54,7 +54,9 @@ listens for service requests at the port indicated in the
|
||||
.Tn NFS
|
||||
server specification; see
|
||||
.%T "Network File System Protocol Specification" ,
|
||||
RFC1094.
|
||||
RFC1094, Appendix A and
|
||||
.%T "NFS: Network File System Version 3 Protocol Specification" ,
|
||||
Appendix I.
|
||||
.Pp
|
||||
Options and operands available for
|
||||
.Nm mountd :
|
||||
@ -65,6 +67,15 @@ The
|
||||
option allows non-root mount requests to be served.
|
||||
This should only be specified if there are clients such as PC's,
|
||||
that require it.
|
||||
.It Fl r
|
||||
The
|
||||
.Fl r
|
||||
option allows mount RPCs requests for regular files to be served.
|
||||
Although this seems to violate the mount protocol specification, some diskless
|
||||
workstations do mount requests for their swapfiles and expect them to be
|
||||
regular files. Since a regular file cannot be specified in /etc/exports, the
|
||||
entire file system that the swapfiles reside in will have to be exported with
|
||||
the ``-alldirs'' flag.
|
||||
.It Ar exportsfile
|
||||
The
|
||||
.Ar exportsfile
|
||||
|
@ -43,7 +43,7 @@ static char copyright[] =
|
||||
#ifndef lint
|
||||
/*static char sccsid[] = "From: @(#)mountd.c 8.8 (Berkeley) 2/20/94";*/
|
||||
static const char rcsid[] =
|
||||
"$Id: mountd.c,v 1.7.2.1 1995/06/08 04:34:11 davidg Exp $";
|
||||
"$Id: mountd.c,v 1.8 1995/06/11 19:30:46 rgrimes Exp $";
|
||||
#endif /*not lint*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -62,7 +62,7 @@ static const char rcsid[] =
|
||||
#include <netiso/iso.h>
|
||||
#endif
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
@ -100,6 +100,8 @@ struct dirlist {
|
||||
};
|
||||
/* dp_flag bits */
|
||||
#define DP_DEFSET 0x1
|
||||
#define DP_HOSTSET 0x2
|
||||
#define DP_KERB 0x4
|
||||
|
||||
struct exportlist {
|
||||
struct exportlist *ex_next;
|
||||
@ -139,22 +141,29 @@ struct grouplist {
|
||||
#define GT_IGNORE 0x5
|
||||
|
||||
struct hostlist {
|
||||
int ht_flag; /* Uses DP_xx bits */
|
||||
struct grouplist *ht_grp;
|
||||
struct hostlist *ht_next;
|
||||
};
|
||||
|
||||
struct fhreturn {
|
||||
int fhr_flag;
|
||||
int fhr_vers;
|
||||
nfsfh_t fhr_fh;
|
||||
};
|
||||
|
||||
/* Global defs */
|
||||
char *add_expdir __P((struct dirlist **, char *, int));
|
||||
void add_dlist __P((struct dirlist **, struct dirlist *,
|
||||
struct grouplist *));
|
||||
struct grouplist *, int));
|
||||
void add_mlist __P((char *, char *));
|
||||
int check_dirpath __P((char *));
|
||||
int check_options __P((struct dirlist *));
|
||||
int chk_host __P((struct dirlist *, u_long, int *));
|
||||
int chk_host __P((struct dirlist *, u_long, int *, int *));
|
||||
void del_mlist __P((char *, char *));
|
||||
struct dirlist *dirp_search __P((struct dirlist *, char *));
|
||||
int do_mount __P((struct exportlist *, struct grouplist *, int,
|
||||
struct ucred *, char *, int, struct statfs *));
|
||||
struct ucred *, char *, int, struct statfs *));
|
||||
int do_opt __P((char **, char **, struct exportlist *, struct grouplist *,
|
||||
int *, int *, struct ucred *));
|
||||
struct exportlist *ex_search __P((fsid_t *));
|
||||
@ -165,6 +174,7 @@ void free_grp __P((struct grouplist *));
|
||||
void free_host __P((struct hostlist *));
|
||||
void get_exportlist __P((void));
|
||||
int get_host __P((char *, struct grouplist *, struct grouplist *));
|
||||
int get_num __P((char *));
|
||||
struct hostlist *get_ht __P((void));
|
||||
int get_line __P((void));
|
||||
void get_mountlist __P((void));
|
||||
@ -183,7 +193,7 @@ void send_umntall __P((void));
|
||||
int umntall_each __P((caddr_t, struct sockaddr_in *));
|
||||
int xdr_dir __P((XDR *, char *));
|
||||
int xdr_explist __P((XDR *, caddr_t));
|
||||
int xdr_fhs __P((XDR *, nfsv2fh_t *));
|
||||
int xdr_fhs __P((XDR *, caddr_t));
|
||||
int xdr_mlist __P((XDR *, caddr_t));
|
||||
|
||||
/* C library */
|
||||
@ -205,7 +215,8 @@ struct ucred def_anon = {
|
||||
1,
|
||||
{ (gid_t) -2 }
|
||||
};
|
||||
int root_only = 1;
|
||||
int resvport_only = 1;
|
||||
int dir_only = 1;
|
||||
int opt_flags;
|
||||
/* Bits for above */
|
||||
#define OP_MAPROOT 0x01
|
||||
@ -238,6 +249,7 @@ main(argc, argv)
|
||||
{
|
||||
SVCXPRT *udptransp, *tcptransp;
|
||||
int c;
|
||||
#ifdef __FreeBSD__
|
||||
struct vfsconf *vfc;
|
||||
|
||||
vfc = getvfsbyname("nfs");
|
||||
@ -250,17 +262,21 @@ main(argc, argv)
|
||||
if(!vfc) {
|
||||
errx(1, "NFS support is not available in the running kernel");
|
||||
}
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
while ((c = getopt(argc, argv, "dn")) != EOF)
|
||||
while ((c = getopt(argc, argv, "dnr")) != EOF)
|
||||
switch (c) {
|
||||
case 'n':
|
||||
resvport_only = 0;
|
||||
break;
|
||||
case 'r':
|
||||
dir_only = 0;
|
||||
break;
|
||||
case 'd':
|
||||
debug = debug ? 0 : 1;
|
||||
break;
|
||||
case 'n':
|
||||
root_only = 0;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Usage: mountd [-n] [export_file]\n");
|
||||
fprintf(stderr, "Usage: mountd [-r] [-n] [export_file]\n");
|
||||
exit(1);
|
||||
};
|
||||
argc -= optind;
|
||||
@ -300,11 +316,12 @@ main(argc, argv)
|
||||
syslog(LOG_ERR, "Can't create socket");
|
||||
exit(1);
|
||||
}
|
||||
pmap_unset(RPCPROG_MNT, RPCMNT_VER1);
|
||||
if (!svc_register(udptransp, RPCPROG_MNT, RPCMNT_VER1, mntsrv,
|
||||
IPPROTO_UDP) ||
|
||||
!svc_register(tcptransp, RPCPROG_MNT, RPCMNT_VER1, mntsrv,
|
||||
IPPROTO_TCP)) {
|
||||
pmap_unset(RPCPROG_MNT, 1);
|
||||
pmap_unset(RPCPROG_MNT, 3);
|
||||
if (!svc_register(udptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_UDP) ||
|
||||
!svc_register(udptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_UDP) ||
|
||||
!svc_register(tcptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_TCP) ||
|
||||
!svc_register(tcptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_TCP)) {
|
||||
syslog(LOG_ERR, "Can't register mount");
|
||||
exit(1);
|
||||
}
|
||||
@ -323,28 +340,21 @@ mntsrv(rqstp, transp)
|
||||
{
|
||||
struct exportlist *ep;
|
||||
struct dirlist *dp;
|
||||
nfsv2fh_t nfh;
|
||||
struct fhreturn fhr;
|
||||
struct authunix_parms *ucr;
|
||||
struct stat stb;
|
||||
struct statfs fsb;
|
||||
struct hostent *hp;
|
||||
u_long saddr;
|
||||
u_short sport;
|
||||
char rpcpath[RPCMNT_PATHLEN+1], dirpath[MAXPATHLEN];
|
||||
int bad = ENOENT, omask, defset;
|
||||
uid_t uid = -2;
|
||||
|
||||
/* Get authorization */
|
||||
switch (rqstp->rq_cred.oa_flavor) {
|
||||
case AUTH_UNIX:
|
||||
ucr = (struct authunix_parms *)rqstp->rq_clntcred;
|
||||
uid = ucr->aup_uid;
|
||||
break;
|
||||
case AUTH_NULL:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
int bad = ENOENT, defset, hostset;
|
||||
sigset_t sighup_mask;
|
||||
|
||||
sigemptyset(&sighup_mask);
|
||||
sigaddset(&sighup_mask, SIGHUP);
|
||||
saddr = transp->xp_raddr.sin_addr.s_addr;
|
||||
sport = ntohs(transp->xp_raddr.sin_port);
|
||||
hp = (struct hostent *)NULL;
|
||||
switch (rqstp->rq_proc) {
|
||||
case NULLPROC:
|
||||
@ -352,7 +362,7 @@ mntsrv(rqstp, transp)
|
||||
syslog(LOG_ERR, "Can't send reply");
|
||||
return;
|
||||
case RPCMNT_MOUNT:
|
||||
if ((uid != 0 && root_only) || uid == -2) {
|
||||
if (sport >= IPPORT_RESERVED && resvport_only) {
|
||||
svcerr_weakauth(transp);
|
||||
return;
|
||||
}
|
||||
@ -363,11 +373,13 @@ mntsrv(rqstp, transp)
|
||||
|
||||
/*
|
||||
* Get the real pathname and make sure it is a directory
|
||||
* that exists.
|
||||
* or a regular file if the -r option was specified
|
||||
* and it exists.
|
||||
*/
|
||||
if (realpath(rpcpath, dirpath) == 0 ||
|
||||
stat(dirpath, &stb) < 0 ||
|
||||
(stb.st_mode & S_IFMT) != S_IFDIR ||
|
||||
(!S_ISDIR(stb.st_mode) &&
|
||||
(dir_only || !S_ISREG(stb.st_mode))) ||
|
||||
statfs(dirpath, &fsb) < 0) {
|
||||
chdir("/"); /* Just in case realpath doesn't */
|
||||
if (debug)
|
||||
@ -378,26 +390,31 @@ mntsrv(rqstp, transp)
|
||||
}
|
||||
|
||||
/* Check in the exports list */
|
||||
omask = sigblock(sigmask(SIGHUP));
|
||||
sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
|
||||
ep = ex_search(&fsb.f_fsid);
|
||||
defset = 0;
|
||||
if (ep && (chk_host(ep->ex_defdir, saddr, &defset) ||
|
||||
hostset = defset = 0;
|
||||
if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) ||
|
||||
((dp = dirp_search(ep->ex_dirl, dirpath)) &&
|
||||
chk_host(dp, saddr, &defset)) ||
|
||||
chk_host(dp, saddr, &defset, &hostset)) ||
|
||||
(defset && scan_tree(ep->ex_defdir, saddr) == 0 &&
|
||||
scan_tree(ep->ex_dirl, saddr) == 0))) {
|
||||
if (hostset & DP_HOSTSET)
|
||||
fhr.fhr_flag = hostset;
|
||||
else
|
||||
fhr.fhr_flag = defset;
|
||||
fhr.fhr_vers = rqstp->rq_vers;
|
||||
/* Get the file handle */
|
||||
bzero((caddr_t)&nfh, sizeof(nfh));
|
||||
if (getfh(dirpath, (fhandle_t *)&nfh) < 0) {
|
||||
bzero((caddr_t)&fhr.fhr_fh, sizeof(nfsfh_t));
|
||||
if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) {
|
||||
bad = errno;
|
||||
syslog(LOG_ERR, "Can't get fh for %s", dirpath);
|
||||
if (!svc_sendreply(transp, xdr_long,
|
||||
(caddr_t)&bad))
|
||||
syslog(LOG_ERR, "Can't send reply");
|
||||
sigsetmask(omask);
|
||||
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
|
||||
return;
|
||||
}
|
||||
if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh))
|
||||
if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr))
|
||||
syslog(LOG_ERR, "Can't send reply");
|
||||
if (hp == NULL)
|
||||
hp = gethostbyaddr((caddr_t)&saddr,
|
||||
@ -414,14 +431,14 @@ mntsrv(rqstp, transp)
|
||||
if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
|
||||
syslog(LOG_ERR, "Can't send reply");
|
||||
}
|
||||
sigsetmask(omask);
|
||||
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
|
||||
return;
|
||||
case RPCMNT_DUMP:
|
||||
if (!svc_sendreply(transp, xdr_mlist, (caddr_t)NULL))
|
||||
syslog(LOG_ERR, "Can't send reply");
|
||||
return;
|
||||
case RPCMNT_UMOUNT:
|
||||
if ((uid != 0 && root_only) || uid == -2) {
|
||||
if (sport >= IPPORT_RESERVED && resvport_only) {
|
||||
svcerr_weakauth(transp);
|
||||
return;
|
||||
}
|
||||
@ -437,7 +454,7 @@ mntsrv(rqstp, transp)
|
||||
del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), dirpath);
|
||||
return;
|
||||
case RPCMNT_UMNTALL:
|
||||
if ((uid != 0 && root_only) || uid == -2) {
|
||||
if (sport >= IPPORT_RESERVED && resvport_only) {
|
||||
svcerr_weakauth(transp);
|
||||
return;
|
||||
}
|
||||
@ -470,18 +487,37 @@ xdr_dir(xdrsp, dirp)
|
||||
}
|
||||
|
||||
/*
|
||||
* Xdr routine to generate fhstatus
|
||||
* Xdr routine to generate file handle reply
|
||||
*/
|
||||
int
|
||||
xdr_fhs(xdrsp, nfh)
|
||||
xdr_fhs(xdrsp, cp)
|
||||
XDR *xdrsp;
|
||||
nfsv2fh_t *nfh;
|
||||
caddr_t cp;
|
||||
{
|
||||
u_long ok = 0;
|
||||
register struct fhreturn *fhrp = (struct fhreturn *)cp;
|
||||
u_long ok = 0, len, auth;
|
||||
|
||||
if (!xdr_long(xdrsp, &ok))
|
||||
return (0);
|
||||
return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH));
|
||||
switch (fhrp->fhr_vers) {
|
||||
case 1:
|
||||
return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH));
|
||||
case 3:
|
||||
len = NFSX_V3FH;
|
||||
if (!xdr_long(xdrsp, &len))
|
||||
return (0);
|
||||
if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len))
|
||||
return (0);
|
||||
if (fhrp->fhr_flag & DP_KERB)
|
||||
auth = RPCAUTH_KERB4;
|
||||
else
|
||||
auth = RPCAUTH_UNIX;
|
||||
len = 1;
|
||||
if (!xdr_long(xdrsp, &len))
|
||||
return (0);
|
||||
return (xdr_long(xdrsp, &auth));
|
||||
};
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -521,9 +557,12 @@ xdr_explist(xdrsp, cp)
|
||||
{
|
||||
struct exportlist *ep;
|
||||
int false = 0;
|
||||
int omask, putdef;
|
||||
int putdef;
|
||||
sigset_t sighup_mask;
|
||||
|
||||
omask = sigblock(sigmask(SIGHUP));
|
||||
sigemptyset(&sighup_mask);
|
||||
sigaddset(&sighup_mask, SIGHUP);
|
||||
sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
|
||||
ep = exphead;
|
||||
while (ep) {
|
||||
putdef = 0;
|
||||
@ -535,12 +574,12 @@ xdr_explist(xdrsp, cp)
|
||||
goto errout;
|
||||
ep = ep->ex_next;
|
||||
}
|
||||
sigsetmask(omask);
|
||||
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
|
||||
if (!xdr_bool(xdrsp, &false))
|
||||
return (0);
|
||||
return (1);
|
||||
errout:
|
||||
sigsetmask(omask);
|
||||
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -660,6 +699,18 @@ get_exportlist()
|
||||
struct ufs_args ua;
|
||||
struct iso_args ia;
|
||||
struct mfs_args ma;
|
||||
#ifdef __NetBSD__
|
||||
struct msdosfs_args da;
|
||||
} targs;
|
||||
|
||||
if (!strcmp(fsp->f_fstypename, MOUNT_MFS) ||
|
||||
!strcmp(fsp->f_fstypename, MOUNT_UFS) ||
|
||||
!strcmp(fsp->f_fstypename, MOUNT_MSDOS) ||
|
||||
!strcmp(fsp->f_fstypename, MOUNT_CD9660)) {
|
||||
targs.ua.fspec = NULL;
|
||||
targs.ua.export.ex_flags = MNT_DELEXPORT;
|
||||
if (mount(fsp->f_fstypename, fsp->f_mntonname,
|
||||
#else
|
||||
} targs;
|
||||
|
||||
switch (fsp->f_type) {
|
||||
@ -670,6 +721,7 @@ get_exportlist()
|
||||
targs.ua.fspec = NULL;
|
||||
targs.ua.export.ex_flags = MNT_DELEXPORT;
|
||||
if (mount(fsp->f_type, fsp->f_mntonname,
|
||||
#endif
|
||||
fsp->f_flags | MNT_UPDATE,
|
||||
(caddr_t)&targs) < 0)
|
||||
syslog(LOG_ERR, "Can't delete exports for %s",
|
||||
@ -805,6 +857,7 @@ get_exportlist()
|
||||
if (get_host(hst, grp, tgrp)) {
|
||||
syslog(LOG_ERR, "Bad netgroup %s", cp);
|
||||
getexp_err(ep, tgrp);
|
||||
endnetgrent();
|
||||
goto nextline;
|
||||
}
|
||||
} else if (get_host(cp, grp, tgrp)) {
|
||||
@ -865,12 +918,12 @@ get_exportlist()
|
||||
* Success. Update the data structures.
|
||||
*/
|
||||
if (has_host) {
|
||||
hang_dirp(dirhead, tgrp, ep, (opt_flags & OP_ALLDIRS));
|
||||
hang_dirp(dirhead, tgrp, ep, opt_flags);
|
||||
grp->gr_next = grphead;
|
||||
grphead = tgrp;
|
||||
} else {
|
||||
hang_dirp(dirhead, (struct grouplist *)NULL, ep,
|
||||
(opt_flags & OP_ALLDIRS));
|
||||
opt_flags);
|
||||
free_grp(grp);
|
||||
}
|
||||
dirhead = (struct dirlist *)NULL;
|
||||
@ -994,24 +1047,28 @@ add_expdir(dpp, cp, len)
|
||||
* and update the entry for host.
|
||||
*/
|
||||
void
|
||||
hang_dirp(dp, grp, ep, alldirs)
|
||||
hang_dirp(dp, grp, ep, flags)
|
||||
struct dirlist *dp;
|
||||
struct grouplist *grp;
|
||||
struct exportlist *ep;
|
||||
int alldirs;
|
||||
int flags;
|
||||
{
|
||||
struct hostlist *hp;
|
||||
struct dirlist *dp2;
|
||||
|
||||
if (alldirs) {
|
||||
if (flags & OP_ALLDIRS) {
|
||||
if (ep->ex_defdir)
|
||||
free((caddr_t)dp);
|
||||
else
|
||||
ep->ex_defdir = dp;
|
||||
if (grp == (struct grouplist *)NULL)
|
||||
if (grp == (struct grouplist *)NULL) {
|
||||
ep->ex_defdir->dp_flag |= DP_DEFSET;
|
||||
else while (grp) {
|
||||
if (flags & OP_KERB)
|
||||
ep->ex_defdir->dp_flag |= DP_KERB;
|
||||
} else while (grp) {
|
||||
hp = get_ht();
|
||||
if (flags & OP_KERB)
|
||||
hp->ht_flag |= DP_KERB;
|
||||
hp->ht_grp = grp;
|
||||
hp->ht_next = ep->ex_defdir->dp_hosts;
|
||||
ep->ex_defdir->dp_hosts = hp;
|
||||
@ -1024,7 +1081,7 @@ hang_dirp(dp, grp, ep, alldirs)
|
||||
*/
|
||||
while (dp) {
|
||||
dp2 = dp->dp_left;
|
||||
add_dlist(&ep->ex_dirl, dp, grp);
|
||||
add_dlist(&ep->ex_dirl, dp, grp, flags);
|
||||
dp = dp2;
|
||||
}
|
||||
}
|
||||
@ -1035,10 +1092,11 @@ hang_dirp(dp, grp, ep, alldirs)
|
||||
* for the new directory or adding the new node.
|
||||
*/
|
||||
void
|
||||
add_dlist(dpp, newdp, grp)
|
||||
add_dlist(dpp, newdp, grp, flags)
|
||||
struct dirlist **dpp;
|
||||
struct dirlist *newdp;
|
||||
struct grouplist *grp;
|
||||
int flags;
|
||||
{
|
||||
struct dirlist *dp;
|
||||
struct hostlist *hp;
|
||||
@ -1048,10 +1106,10 @@ add_dlist(dpp, newdp, grp)
|
||||
if (dp) {
|
||||
cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
|
||||
if (cmp > 0) {
|
||||
add_dlist(&dp->dp_left, newdp, grp);
|
||||
add_dlist(&dp->dp_left, newdp, grp, flags);
|
||||
return;
|
||||
} else if (cmp < 0) {
|
||||
add_dlist(&dp->dp_right, newdp, grp);
|
||||
add_dlist(&dp->dp_right, newdp, grp, flags);
|
||||
return;
|
||||
} else
|
||||
free((caddr_t)newdp);
|
||||
@ -1067,13 +1125,18 @@ add_dlist(dpp, newdp, grp)
|
||||
*/
|
||||
do {
|
||||
hp = get_ht();
|
||||
if (flags & OP_KERB)
|
||||
hp->ht_flag |= DP_KERB;
|
||||
hp->ht_grp = grp;
|
||||
hp->ht_next = dp->dp_hosts;
|
||||
dp->dp_hosts = hp;
|
||||
grp = grp->gr_next;
|
||||
} while (grp);
|
||||
} else
|
||||
} else {
|
||||
dp->dp_flag |= DP_DEFSET;
|
||||
if (flags & OP_KERB)
|
||||
dp->dp_flag |= DP_KERB;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1102,10 +1165,11 @@ dirp_search(dp, dirpath)
|
||||
* Scan for a host match in a directory tree.
|
||||
*/
|
||||
int
|
||||
chk_host(dp, saddr, defsetp)
|
||||
chk_host(dp, saddr, defsetp, hostsetp)
|
||||
struct dirlist *dp;
|
||||
u_long saddr;
|
||||
int *defsetp;
|
||||
int *hostsetp;
|
||||
{
|
||||
struct hostlist *hp;
|
||||
struct grouplist *grp;
|
||||
@ -1113,7 +1177,7 @@ chk_host(dp, saddr, defsetp)
|
||||
|
||||
if (dp) {
|
||||
if (dp->dp_flag & DP_DEFSET)
|
||||
*defsetp = 1;
|
||||
*defsetp = dp->dp_flag;
|
||||
hp = dp->dp_hosts;
|
||||
while (hp) {
|
||||
grp = hp->ht_grp;
|
||||
@ -1122,15 +1186,19 @@ chk_host(dp, saddr, defsetp)
|
||||
addrp = (u_long **)
|
||||
grp->gr_ptr.gt_hostent->h_addr_list;
|
||||
while (*addrp) {
|
||||
if (**addrp == saddr)
|
||||
if (**addrp == saddr) {
|
||||
*hostsetp = (hp->ht_flag | DP_HOSTSET);
|
||||
return (1);
|
||||
}
|
||||
addrp++;
|
||||
}
|
||||
break;
|
||||
case GT_NET:
|
||||
if ((saddr & grp->gr_ptr.gt_net.nt_mask) ==
|
||||
grp->gr_ptr.gt_net.nt_net)
|
||||
grp->gr_ptr.gt_net.nt_net) {
|
||||
*hostsetp = (hp->ht_flag | DP_HOSTSET);
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
};
|
||||
hp = hp->ht_next;
|
||||
@ -1147,12 +1215,12 @@ scan_tree(dp, saddr)
|
||||
struct dirlist *dp;
|
||||
u_long saddr;
|
||||
{
|
||||
int defset;
|
||||
int defset, hostset;
|
||||
|
||||
if (dp) {
|
||||
if (scan_tree(dp->dp_left, saddr))
|
||||
return (1);
|
||||
if (chk_host(dp, saddr, &defset))
|
||||
if (chk_host(dp, saddr, &defset, &hostset))
|
||||
return (1);
|
||||
if (scan_tree(dp->dp_right, saddr))
|
||||
return (1);
|
||||
@ -1312,7 +1380,7 @@ get_host(cp, grp, tgrp)
|
||||
if (isdigit(*cp)) {
|
||||
saddr = inet_addr(cp);
|
||||
if (saddr == -1) {
|
||||
syslog(LOG_ERR, "Inet_addr failed");
|
||||
syslog(LOG_ERR, "Inet_addr failed for %s", cp);
|
||||
return (1);
|
||||
}
|
||||
if ((hp = gethostbyaddr((caddr_t)&saddr, sizeof (saddr),
|
||||
@ -1326,7 +1394,7 @@ get_host(cp, grp, tgrp)
|
||||
aptr[1] = (char *)NULL;
|
||||
}
|
||||
} else {
|
||||
syslog(LOG_ERR, "Gethostbyname failed");
|
||||
syslog(LOG_ERR, "Gethostbyname failed for %s", cp);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
@ -1424,6 +1492,7 @@ get_ht()
|
||||
if (hp == (struct hostlist *)NULL)
|
||||
out_of_mem();
|
||||
hp->ht_next = (struct hostlist *)NULL;
|
||||
hp->ht_flag = 0;
|
||||
return (hp);
|
||||
}
|
||||
|
||||
@ -1494,6 +1563,9 @@ do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
|
||||
struct ufs_args ua;
|
||||
struct iso_args ia;
|
||||
struct mfs_args ma;
|
||||
#ifdef __NetBSD__
|
||||
struct msdosfs_args da;
|
||||
#endif
|
||||
} args;
|
||||
u_long net;
|
||||
|
||||
@ -1569,7 +1641,11 @@ do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
|
||||
* Also, needs to know how to export all types of local
|
||||
* exportable file systems and not just MOUNT_UFS.
|
||||
*/
|
||||
#ifdef __NetBSD__
|
||||
while (mount(fsb->f_fstypename, dirp,
|
||||
#else
|
||||
while (mount(fsb->f_type, dirp,
|
||||
#endif
|
||||
fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) {
|
||||
if (cp)
|
||||
*cp-- = savedc;
|
||||
@ -2033,15 +2109,30 @@ check_dirpath(dirp)
|
||||
while (*cp && ret) {
|
||||
if (*cp == '/') {
|
||||
*cp = '\0';
|
||||
if (lstat(dirp, &sb) < 0 ||
|
||||
(sb.st_mode & S_IFMT) != S_IFDIR)
|
||||
if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode))
|
||||
ret = 0;
|
||||
*cp = '/';
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
if (lstat(dirp, &sb) < 0 ||
|
||||
(sb.st_mode & S_IFMT) != S_IFDIR)
|
||||
if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode))
|
||||
ret = 0;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Just translate an ascii string to an integer.
|
||||
*/
|
||||
int
|
||||
get_num(cp)
|
||||
register char *cp;
|
||||
{
|
||||
register int res = 0;
|
||||
|
||||
while (*cp) {
|
||||
if (*cp < '0' || *cp > '9')
|
||||
return (-1);
|
||||
res = res * 10 + (*cp++ - '0');
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
@ -98,7 +98,8 @@ listens for service requests at the port indicated in the
|
||||
.Tn NFS
|
||||
server specification; see
|
||||
.%T "Network File System Protocol Specification" ,
|
||||
RFC1094.
|
||||
RFC1094 and
|
||||
.%T "NFS: Network File System Version 3 Protocol Specification" .
|
||||
.Pp
|
||||
If
|
||||
.Nm nfsd
|
||||
|
@ -63,10 +63,10 @@ static char sccsid[] = "@(#)nfsd.c 8.7 (Berkeley) 2/22/94";
|
||||
#include <netiso/iso.h>
|
||||
#endif
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
|
||||
#ifdef KERBEROS
|
||||
#ifdef NFSKERB
|
||||
#include <kerberosIV/des.h>
|
||||
#include <kerberosIV/krb.h>
|
||||
#endif
|
||||
@ -94,16 +94,23 @@ struct nfsd_srvargs nsd;
|
||||
char **Argv = NULL; /* pointer to argument vector */
|
||||
char *LastArg = NULL; /* end of argv */
|
||||
|
||||
#ifdef KERBEROS
|
||||
#ifdef NFSKERB
|
||||
char lnam[ANAME_SZ];
|
||||
KTEXT_ST kt;
|
||||
AUTH_DAT auth;
|
||||
AUTH_DAT kauth;
|
||||
char inst[INST_SZ];
|
||||
struct nfsrpc_fullblock kin, kout;
|
||||
struct nfsrpc_fullverf kverf;
|
||||
NFSKERBKEY_T kivec;
|
||||
struct timeval ktv;
|
||||
NFSKERBKEYSCHED_T kerb_keysched;
|
||||
#endif
|
||||
|
||||
void nonfs __P((int));
|
||||
void reapchild __P((int));
|
||||
#ifdef __FreeBSD__
|
||||
void setproctitle __P((char *));
|
||||
#endif
|
||||
void usage __P((void));
|
||||
|
||||
/*
|
||||
@ -139,11 +146,13 @@ main(argc, argv, envp)
|
||||
#ifdef ISO
|
||||
struct sockaddr_iso isoaddr, isopeer;
|
||||
#endif
|
||||
struct timeval ktv;
|
||||
fd_set ready, sockbits;
|
||||
int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
|
||||
int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
|
||||
int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag;
|
||||
char *cp, **cpp;
|
||||
#ifdef __FreeBSD__
|
||||
struct vfsconf *vfc;
|
||||
|
||||
vfc = getvfsbyname("nfs");
|
||||
@ -156,6 +165,7 @@ main(argc, argv, envp)
|
||||
if(!vfc) {
|
||||
errx(1, "NFS is not available in the running kernel");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Save start and extent of argv for setproctitle. */
|
||||
Argv = argv;
|
||||
@ -241,10 +251,12 @@ main(argc, argv, envp)
|
||||
|
||||
if (reregister) {
|
||||
if (udpflag &&
|
||||
!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT))
|
||||
(!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
|
||||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)))
|
||||
err(1, "can't register with portmap for UDP.");
|
||||
if (tcpflag &&
|
||||
!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT))
|
||||
(!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
|
||||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)))
|
||||
err(1, "can't register with portmap for TCP.");
|
||||
exit(0);
|
||||
}
|
||||
@ -261,11 +273,17 @@ main(argc, argv, envp)
|
||||
continue;
|
||||
}
|
||||
|
||||
setproctitle("nfsd-srv");
|
||||
setproctitle("server");
|
||||
nfssvc_flag = NFSSVC_NFSD;
|
||||
nsd.nsd_nfsd = NULL;
|
||||
#ifdef KERBEROS
|
||||
nsd.nsd_authstr = (char *)kt.dat;
|
||||
#ifdef NFSKERB
|
||||
if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF ||
|
||||
sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK)
|
||||
syslog(LOG_ERR, "Yikes NFSKERB structs not packed!");
|
||||
nsd.nsd_authstr = (u_char *)&kt;
|
||||
nsd.nsd_authlen = sizeof (kt);
|
||||
nsd.nsd_verfstr = (u_char *)&kverf;
|
||||
nsd.nsd_verflen = sizeof (kverf);
|
||||
#endif
|
||||
while (nfssvc(nfssvc_flag, &nsd) < 0) {
|
||||
if (errno != ENEEDAUTH) {
|
||||
@ -273,14 +291,27 @@ main(argc, argv, envp)
|
||||
exit(1);
|
||||
}
|
||||
nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
|
||||
#ifdef KERBEROS
|
||||
kt.length = nsd.nsd_authlen;
|
||||
kt.mbz = 0;
|
||||
(void)strcpy(inst, "*");
|
||||
if (krb_rd_req(&kt, "rcmd",
|
||||
inst, nsd.nsd_haddr, &auth, "") == RD_AP_OK &&
|
||||
krb_kntoln(&auth, lnam) == KSUCCESS &&
|
||||
(pwd = getpwnam(lnam)) != NULL) {
|
||||
#ifdef NFSKERB
|
||||
/*
|
||||
* Get the Kerberos ticket out of the authenticator
|
||||
* verify it and convert the principal name to a user
|
||||
* name. The user name is then converted to a set of
|
||||
* user credentials via the password and group file.
|
||||
* Finally, decrypt the timestamp and validate it.
|
||||
* For more info see the IETF Draft "Authentication
|
||||
* in ONC RPC".
|
||||
*/
|
||||
kt.length = ntohl(kt.length);
|
||||
if (gettimeofday(&ktv, (struct timezone *)0) == 0 &&
|
||||
kt.length > 0 && kt.length <=
|
||||
(RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) {
|
||||
kin.w1 = NFS_KERBW1(kt);
|
||||
kt.mbz = 0;
|
||||
(void)strcpy(inst, "*");
|
||||
if (krb_rd_req(&kt, NFS_KERBSRV,
|
||||
inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK &&
|
||||
krb_kntoln(&kauth, lnam) == KSUCCESS &&
|
||||
(pwd = getpwnam(lnam)) != NULL) {
|
||||
cr = &nsd.nsd_cr;
|
||||
cr->cr_uid = pwd->pw_uid;
|
||||
cr->cr_groups[0] = pwd->pw_gid;
|
||||
@ -301,9 +332,34 @@ main(argc, argv, envp)
|
||||
break;
|
||||
}
|
||||
endgrent();
|
||||
nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
|
||||
|
||||
/*
|
||||
* Get the timestamp verifier out of the
|
||||
* authenticator and verifier strings.
|
||||
*/
|
||||
kin.t1 = kverf.t1;
|
||||
kin.t2 = kverf.t2;
|
||||
kin.w2 = kverf.w2;
|
||||
bzero((caddr_t)kivec, sizeof (kivec));
|
||||
bcopy((caddr_t)kauth.session,
|
||||
(caddr_t)nsd.nsd_key,sizeof(kauth.session));
|
||||
|
||||
/*
|
||||
* Decrypt the timestamp verifier in CBC mode.
|
||||
*/
|
||||
XXX
|
||||
|
||||
/*
|
||||
* Validate the timestamp verifier, to
|
||||
* check that the session key is ok.
|
||||
*/
|
||||
nsd.nsd_timestamp.tv_sec = ntohl(kout.t1);
|
||||
nsd.nsd_timestamp.tv_usec = ntohl(kout.t2);
|
||||
nsd.nsd_ttl = ntohl(kout.w1);
|
||||
if ((nsd.nsd_ttl - 1) == ntohl(kout.w2))
|
||||
nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
|
||||
}
|
||||
#endif /* KERBEROS */
|
||||
#endif /* NFSKERB */
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
@ -323,7 +379,8 @@ main(argc, argv, envp)
|
||||
syslog(LOG_ERR, "can't bind udp addr");
|
||||
exit(1);
|
||||
}
|
||||
if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
|
||||
if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
|
||||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
|
||||
syslog(LOG_ERR, "can't register with udp portmap");
|
||||
exit(1);
|
||||
}
|
||||
@ -403,7 +460,8 @@ main(argc, argv, envp)
|
||||
syslog(LOG_ERR, "listen failed");
|
||||
exit(1);
|
||||
}
|
||||
if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
|
||||
if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
|
||||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
|
||||
syslog(LOG_ERR, "can't register tcp with portmap");
|
||||
exit(1);
|
||||
}
|
||||
@ -492,7 +550,7 @@ main(argc, argv, envp)
|
||||
if (connect_type_cnt == 0)
|
||||
exit(0);
|
||||
|
||||
setproctitle("nfsd-master");
|
||||
setproctitle("master");
|
||||
|
||||
/*
|
||||
* Loop forever accepting connections and passing the sockets
|
||||
@ -566,7 +624,7 @@ main(argc, argv, envp)
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "nfsd %s\n", USAGE);
|
||||
(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -582,9 +640,10 @@ reapchild(signo)
|
||||
int signo;
|
||||
{
|
||||
|
||||
while (wait3(NULL, WNOHANG, NULL));
|
||||
while (wait3(NULL, WNOHANG, NULL) > 0);
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
void
|
||||
setproctitle(a)
|
||||
char *a;
|
||||
@ -593,9 +652,10 @@ setproctitle(a)
|
||||
char buf[80];
|
||||
|
||||
cp = Argv[0];
|
||||
(void)snprintf(buf, sizeof(buf), "%s", a);
|
||||
(void)snprintf(buf, sizeof(buf), "nfsd-%s", a);
|
||||
(void)strncpy(cp, buf, LastArg - cp);
|
||||
cp += strlen(cp);
|
||||
while (cp < LastArg)
|
||||
*cp++ = '\0';
|
||||
}
|
||||
#endif /* __FreeBSD__ */
|
||||
|
@ -54,6 +54,8 @@ static char sccsid[] = "@(#)pstat.c 8.9 (Berkeley) 2/16/94";
|
||||
#undef NFS
|
||||
#undef KERNEL
|
||||
#include <sys/stat.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/ioctl_compat.h> /* XXX NTTYDISC is too well hidden */
|
||||
|
Loading…
Reference in New Issue
Block a user