2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1989, 1993
25 * The Regents of the University of California. All rights reserved.
27 * This code is derived from software contributed to Berkeley by
28 * Rick Macklem at The University of Guelph.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95
59 * FreeBSD-Id: nfs_syscalls.c,v 1.32 1997/11/07 08:53:25 phk Exp $
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 /* XXX CSM 11/25/97 FreeBSD's generated syscall prototypes */
66 #include <sys/sysproto.h>
68 #include <sys/kernel.h>
70 #include <sys/filedesc.h>
72 #include <sys/vnode.h>
73 #include <sys/mount.h>
75 #include <sys/sysctl.h>
78 #include <sys/malloc.h>
80 #include <sys/socket.h>
81 #include <sys/socketvar.h>
82 #include <sys/domain.h>
83 #include <sys/protosw.h>
84 #include <sys/namei.h>
85 #include <sys/fcntl.h>
86 #include <sys/lockf.h>
87 #include <sys/syslog.h>
89 #include <machine/spl.h>
91 #include <bsm/audit_kernel.h>
93 #include <netinet/in.h>
94 #include <netinet/tcp.h>
96 #include <netiso/iso.h>
98 #include <nfs/xdr_subs.h>
99 #include <nfs/rpcv2.h>
100 #include <nfs/nfsproto.h>
102 #include <nfs/nfsm_subs.h>
103 #include <nfs/nfsrvcache.h>
104 #include <nfs/nfsmount.h>
105 #include <nfs/nfsnode.h>
106 #include <nfs/nqnfs.h>
107 #include <nfs/nfsrtt.h>
108 #include <nfs/nfs_lock.h>
111 extern int (*nfsrv3_procs
[NFS_NPROCS
]) __P((struct nfsrv_descript
*nd
,
112 struct nfssvc_sock
*slp
,
114 struct mbuf
**mreqp
));
115 extern int nfs_numasync
;
116 extern int nfs_ioddelwri
;
117 extern time_t nqnfsstarttime
;
118 extern int nqsrv_writeslack
;
120 extern struct nfsstats nfsstats
;
121 extern int nfsrvw_procrastinate
;
122 extern int nfsrvw_procrastinate_v3
;
123 struct nfssvc_sock
*nfs_udpsock
, *nfs_cltpsock
;
124 static int nuidhash_max
= NFS_MAXUIDHASH
;
126 static void nfsrv_zapsock
__P((struct nfssvc_sock
*slp
));
127 static int nfssvc_iod
__P((struct proc
*));
132 static int nfs_asyncdaemon
[NFS_MAXASYNCDAEMON
];
135 int nfsd_waiting
= 0;
136 static struct nfsdrt nfsdrt
;
137 static int nfs_numnfsd
= 0;
138 static int notstarted
= 1;
139 static int modify_flag
= 0;
140 static void nfsd_rt
__P((int sotype
, struct nfsrv_descript
*nd
,
142 static int nfssvc_addsock
__P((struct file
*, struct mbuf
*,
144 static int nfssvc_nfsd
__P((struct nfsd_srvargs
*,caddr_t
,struct proc
*));
146 static int nfs_privport
= 0;
147 /* XXX CSM 11/25/97 Upgrade sysctl.h someday */
149 SYSCTL_INT(_vfs_nfs
, NFS_NFSPRIVPORT
, nfs_privport
, CTLFLAG_RW
, &nfs_privport
, 0, "");
150 SYSCTL_INT(_vfs_nfs
, OID_AUTO
, gatherdelay
, CTLFLAG_RW
, &nfsrvw_procrastinate
, 0, "");
151 SYSCTL_INT(_vfs_nfs
, OID_AUTO
, gatherdelay_v3
, CTLFLAG_RW
, &nfsrvw_procrastinate_v3
, 0, "");
155 * NFS server system calls
156 * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c
160 * Get file handle system call
162 #ifndef _SYS_SYSPROTO_H_
171 register struct getfh_args
*uap
;
173 register struct vnode
*vp
;
181 error
= suser(p
->p_ucred
, &p
->p_acflag
);
184 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| AUDITVNPATH1
, UIO_USERSPACE
, uap
->fname
, p
);
189 bzero((caddr_t
)&fh
, sizeof(fh
));
190 fh
.fh_fsid
= vp
->v_mount
->mnt_stat
.f_fsid
;
191 error
= VFS_VPTOFH(vp
, &fh
.fh_fid
);
195 error
= copyout((caddr_t
)&fh
, (caddr_t
)uap
->fhp
, sizeof (fh
));
199 #endif /* NFS_NOSERVER */
202 * syscall for the rpc.lockd to use to translate a NFS file handle into
203 * an open descriptor.
205 * warning: do not remove the suser() call or this becomes one giant
208 #ifndef _SYS_SYSPROTO_H_
210 const struct fhandle
*u_fhp
;
215 fhopen(p
, uap
, retval
)
217 register struct fhopen_args
*uap
;
224 struct vattr
*vap
= &vat
;
227 register struct filedesc
*fdp
= p
->p_fd
;
228 int fmode
, mode
, error
, type
;
231 struct ucred
*credanon
;
233 struct ucred
*cred
= p
->p_ucred
;
235 extern struct fileops vnops
;
240 error
= suser(cred
, &p
->p_acflag
);
244 fmode
= FFLAGS(uap
->flags
);
245 /* why not allow a non-read/write open for our lockd? */
246 if (((fmode
& (FREAD
| FWRITE
)) == 0) || (fmode
& O_CREAT
))
248 error
= copyin((void*)uap
->u_fhp
, &fhp
, sizeof(fhp
));
251 /* find the mount point */
252 mp
= vfs_getvfs(&fhp
.fh_fsid
);
255 /* now give me my vnode, it gets returned to me locked */
256 /* XXX CSM need to split VFS_CHECKEXP out of VFS_FHTOVP? */
257 error
= VFS_FHTOVP(mp
, &fhp
.fh_fid
, NULL
, &vp
, &exflags
, &credanon
);
261 * from now on we have to make sure not
262 * to forget about the vnode
263 * any error that causes an abort must vput(vp)
264 * just set error = err and 'goto bad;'.
270 if (vp
->v_type
== VSOCK
) {
275 if (UBCINFOEXISTS(vp
) && ((didhold
= ubc_hold(vp
)) == 0)) {
280 if (fmode
& FREAD
&& fmode
& (FWRITE
| O_TRUNC
)) {
282 if (vp
->v_type
== VDIR
)
285 err
= vn_writechk(vp
);
286 if (err
&& !(error
= VOP_ACCESS(vp
, VREAD
, cred
, p
)))
288 if (error
|| (error
= VOP_ACCESS(vp
, VREAD
|VWRITE
, cred
, p
)))
290 } else if (fmode
& FREAD
) {
291 if ((error
= VOP_ACCESS(vp
, VREAD
, cred
, p
)))
293 } else if (fmode
& (FWRITE
| O_TRUNC
)) {
294 if (vp
->v_type
== VDIR
) {
298 if ((error
= vn_writechk(vp
)) ||
299 (error
= VOP_ACCESS(vp
, VWRITE
, cred
, p
)))
302 if (fmode
& O_TRUNC
) {
303 VOP_UNLOCK(vp
, 0, p
); /* XXX */
304 VOP_LEASE(vp
, p
, cred
, LEASE_WRITE
);
305 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
); /* XXX */
308 error
= VOP_SETATTR(vp
, vap
, cred
, p
);
313 error
= VOP_OPEN(vp
, fmode
, cred
, p
);
318 if (++vp
->v_writecount
<= 0)
319 panic("fhopen: v_writecount");
321 * end of vn_open code
324 if ((error
= falloc(p
, &nfp
, &indx
)) != 0) {
332 * Hold an extra reference to avoid having fp ripped out
333 * from under us while we block in the lock op
336 nfp
->f_data
= (caddr_t
)vp
;
337 nfp
->f_flag
= fmode
& FMASK
;
339 nfp
->f_type
= DTYPE_VNODE
;
340 if (fmode
& (O_EXLOCK
| O_SHLOCK
)) {
341 lf
.l_whence
= SEEK_SET
;
344 if (fmode
& O_EXLOCK
)
349 if ((fmode
& FNONBLOCK
) == 0)
351 VOP_UNLOCK(vp
, 0, p
);
352 if ((error
= VOP_ADVLOCK(vp
, (caddr_t
)fp
, F_SETLK
, &lf
,
354 (void) vn_close(vp
, fp
->f_flag
, fp
->f_cred
, p
);
358 * release our private reference
364 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
365 fp
->f_flag
|= FHASLOCK
;
368 VOP_UNLOCK(vp
, 0, p
);
369 *fdflags(p
, indx
) &= ~UF_RESERVED
;
375 VOP_UNLOCK(vp
, 0, p
);
383 * Nfs server psuedo system call for the nfsd's
384 * Based on the flag value it either:
385 * - adds a socket to the selection list
386 * - remains in the kernel as an nfsd
387 * - remains in the kernel as an nfsiod
389 #ifndef _SYS_SYSPROTO_H_
398 register struct nfssvc_args
*uap
;
404 struct nfsd_args nfsdarg
;
405 struct nfsd_srvargs nfsd_srvargs
, *nsd
= &nfsd_srvargs
;
406 struct nfsd_cargs ncd
;
408 struct nfssvc_sock
*slp
;
409 struct nfsuid
*nuidp
;
410 struct nfsmount
*nmp
;
412 #endif /* NFS_NOSERVER */
415 AUDIT_ARG(cmd
, uap
->flag
);
420 error
= suser(p
->p_ucred
, &p
->p_acflag
);
423 while (nfssvc_sockhead_flag
& SLP_INIT
) {
424 nfssvc_sockhead_flag
|= SLP_WANTINIT
;
425 (void) tsleep((caddr_t
)&nfssvc_sockhead
, PSOCK
, "nfsd init", 0);
427 if (uap
->flag
& NFSSVC_BIOD
)
428 error
= nfssvc_iod(p
);
432 #else /* !NFS_NOSERVER */
433 else if (uap
->flag
& NFSSVC_MNTD
) {
434 error
= copyin(uap
->argp
, (caddr_t
)&ncd
, sizeof (ncd
));
437 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| AUDITVNPATH1
,
438 UIO_USERSPACE
, ncd
.ncd_dirp
, p
);
442 if ((nd
.ni_vp
->v_flag
& VROOT
) == 0)
444 nmp
= VFSTONFS(nd
.ni_vp
->v_mount
);
449 if ((nmp
->nm_state
& NFSSTA_MNTD
) &&
450 (uap
->flag
& NFSSVC_GOTAUTH
) == 0)
452 nmp
->nm_state
|= NFSSTA_MNTD
;
453 error
= nqnfs_clientd(nmp
, p
->p_ucred
, &ncd
, uap
->flag
,
455 } else if (uap
->flag
& NFSSVC_ADDSOCK
) {
456 error
= copyin(uap
->argp
, (caddr_t
)&nfsdarg
, sizeof(nfsdarg
));
459 error
= getsock(p
->p_fd
, nfsdarg
.sock
, &fp
);
463 * Get the client address for connected sockets.
465 if (nfsdarg
.name
== NULL
|| nfsdarg
.namelen
== 0)
466 nam
= (struct mbuf
*)0;
468 error
= sockargs(&nam
, nfsdarg
.name
, nfsdarg
.namelen
,
473 error
= nfssvc_addsock(fp
, nam
, p
);
475 error
= copyin(uap
->argp
, (caddr_t
)nsd
, sizeof (*nsd
));
479 if ((uap
->flag
& NFSSVC_AUTHIN
) && ((nfsd
= nsd
->nsd_nfsd
)) &&
480 (nfsd
->nfsd_slp
->ns_flag
& SLP_VALID
)) {
481 slp
= nfsd
->nfsd_slp
;
484 * First check to see if another nfsd has already
485 * added this credential.
487 for (nuidp
= NUIDHASH(slp
,nsd
->nsd_cr
.cr_uid
)->lh_first
;
488 nuidp
!= 0; nuidp
= nuidp
->nu_hash
.le_next
) {
489 if (nuidp
->nu_cr
.cr_uid
== nsd
->nsd_cr
.cr_uid
&&
490 (!nfsd
->nfsd_nd
->nd_nam2
||
491 netaddr_match(NU_NETFAM(nuidp
),
492 &nuidp
->nu_haddr
, nfsd
->nfsd_nd
->nd_nam2
)))
496 nfsrv_setcred(&nuidp
->nu_cr
,&nfsd
->nfsd_nd
->nd_cr
);
497 nfsd
->nfsd_nd
->nd_flag
|= ND_KERBFULL
;
502 if (slp
->ns_numuids
< nuidhash_max
) {
504 nuidp
= (struct nfsuid
*)
505 _MALLOC_ZONE(sizeof (struct nfsuid
),
508 nuidp
= (struct nfsuid
*)0;
509 if ((slp
->ns_flag
& SLP_VALID
) == 0) {
511 FREE_ZONE((caddr_t
)nuidp
,
512 sizeof (struct nfsuid
), M_NFSUID
);
514 if (nuidp
== (struct nfsuid
*)0) {
515 nuidp
= slp
->ns_uidlruhead
.tqh_first
;
516 LIST_REMOVE(nuidp
, nu_hash
);
517 TAILQ_REMOVE(&slp
->ns_uidlruhead
, nuidp
,
519 if (nuidp
->nu_flag
& NU_NAM
)
520 m_freem(nuidp
->nu_nam
);
523 nuidp
->nu_cr
= nsd
->nsd_cr
;
524 if (nuidp
->nu_cr
.cr_ngroups
> NGROUPS
)
525 nuidp
->nu_cr
.cr_ngroups
= NGROUPS
;
526 nuidp
->nu_cr
.cr_ref
= 1;
527 nuidp
->nu_timestamp
= nsd
->nsd_timestamp
;
529 nuidp
->nu_expire
= now
.tv_sec
+ nsd
->nsd_ttl
;
531 * and save the session key in nu_key.
533 bcopy(nsd
->nsd_key
, nuidp
->nu_key
,
534 sizeof (nsd
->nsd_key
));
535 if (nfsd
->nfsd_nd
->nd_nam2
) {
536 struct sockaddr_in
*saddr
;
538 saddr
= mtod(nfsd
->nfsd_nd
->nd_nam2
,
539 struct sockaddr_in
*);
540 switch (saddr
->sin_family
) {
542 nuidp
->nu_flag
|= NU_INETADDR
;
544 saddr
->sin_addr
.s_addr
;
548 nuidp
->nu_flag
|= NU_NAM
;
549 nuidp
->nu_nam
= m_copym(
550 nfsd
->nfsd_nd
->nd_nam2
, 0,
555 TAILQ_INSERT_TAIL(&slp
->ns_uidlruhead
, nuidp
,
557 LIST_INSERT_HEAD(NUIDHASH(slp
, nsd
->nsd_uid
),
559 nfsrv_setcred(&nuidp
->nu_cr
,
560 &nfsd
->nfsd_nd
->nd_cr
);
561 nfsd
->nfsd_nd
->nd_flag
|= ND_KERBFULL
;
565 if ((uap
->flag
& NFSSVC_AUTHINFAIL
) && (nfsd
= nsd
->nsd_nfsd
))
566 nfsd
->nfsd_flag
|= NFSD_AUTHFAIL
;
567 error
= nfssvc_nfsd(nsd
, uap
->argp
, p
);
569 #endif /* NFS_NOSERVER */
570 if (error
== EINTR
|| error
== ERESTART
)
577 * Adds a socket to the list for servicing by nfsds.
580 nfssvc_addsock(fp
, mynam
, p
)
585 register struct mbuf
*m
;
587 register struct nfssvc_sock
*slp
;
588 register struct socket
*so
;
589 struct nfssvc_sock
*tslp
;
592 so
= (struct socket
*)fp
->f_data
;
593 tslp
= (struct nfssvc_sock
*)0;
595 * Add it to the list, as required.
597 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
598 if (so
->so_proto
->pr_protocol
== IPPROTO_UDP
) {
600 if (tslp
->ns_flag
& SLP_VALID
) {
602 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
606 } else if (so
->so_proto
->pr_protocol
== ISOPROTO_CLTP
) {
608 if (tslp
->ns_flag
& SLP_VALID
) {
610 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
615 /* reserve buffer space for 2 maximally-sized packets */
617 if (so
->so_type
== SOCK_STREAM
)
618 siz
+= sizeof (u_long
);
620 if (siz
> NFS_MAXSOCKBUF
)
621 siz
= NFS_MAXSOCKBUF
;
622 error
= soreserve(so
, siz
, siz
);
625 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
630 * Set protocol specific options { for now TCP only } and
631 * reserve some space. For datagram sockets, this can get called
632 * repeatedly for the same socket, but that isn't harmful.
634 if (so
->so_type
== SOCK_STREAM
) {
638 bzero(&sopt
, sizeof sopt
);
639 sopt
.sopt_dir
= SOPT_SET
;
640 sopt
.sopt_level
= SOL_SOCKET
;
641 sopt
.sopt_name
= SO_KEEPALIVE
;
642 sopt
.sopt_val
= &val
;
643 sopt
.sopt_valsize
= sizeof val
;
647 if (so
->so_proto
->pr_domain
->dom_family
== AF_INET
&&
648 so
->so_proto
->pr_protocol
== IPPROTO_TCP
) {
652 bzero(&sopt
, sizeof sopt
);
653 sopt
.sopt_dir
= SOPT_SET
;
654 sopt
.sopt_level
= IPPROTO_TCP
;
655 sopt
.sopt_name
= TCP_NODELAY
;
656 sopt
.sopt_val
= &val
;
657 sopt
.sopt_valsize
= sizeof val
;
662 so
->so_rcv
.sb_flags
&= ~SB_NOINTR
;
663 so
->so_rcv
.sb_timeo
= 0;
664 so
->so_snd
.sb_flags
&= ~SB_NOINTR
;
665 so
->so_snd
.sb_timeo
= 0;
666 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
670 MALLOC(slp
, struct nfssvc_sock
*, sizeof(struct nfssvc_sock
),
672 bzero((caddr_t
)slp
, sizeof (struct nfssvc_sock
));
673 TAILQ_INIT(&slp
->ns_uidlruhead
);
674 TAILQ_INSERT_TAIL(&nfssvc_sockhead
, slp
, ns_chain
);
680 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
682 so
->so_upcallarg
= (caddr_t
)slp
;
683 so
->so_upcall
= nfsrv_rcv
;
684 so
->so_rcv
.sb_flags
|= SB_UPCALL
; /* required for freebsd merge */
685 slp
->ns_nflag
= SLPN_NEEDQ
;
686 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
687 slp
->ns_flag
= SLP_VALID
;
694 * Called by nfssvc() for nfsds. Just loops around servicing rpc requests
695 * until it is killed by a signal.
698 nfssvc_nfsd(nsd
, argp
, p
)
699 struct nfsd_srvargs
*nsd
;
703 register struct mbuf
*m
;
705 register struct nfssvc_sock
*slp
;
706 register struct socket
*so
;
707 struct nfsd
*nfsd
= nsd
->nsd_nfsd
;
708 struct nfsrv_descript
*nd
= NULL
;
710 int error
= 0, cacherep
, s
, sotype
, writes_todo
;
720 if (nfsd
== (struct nfsd
*)0) {
721 MALLOC(nfsd
, struct nfsd
*, sizeof(struct nfsd
), M_NFSD
, M_WAITOK
);
722 nsd
->nsd_nfsd
= nfsd
;
723 bzero((caddr_t
)nfsd
, sizeof (struct nfsd
));
724 nfsd
->nfsd_procp
= p
;
725 TAILQ_INSERT_TAIL(&nfsd_head
, nfsd
, nfsd_chain
);
729 * Loop getting rpc requests until SIGKILL.
732 if ((nfsd
->nfsd_flag
& NFSD_REQINPROG
) == 0) {
733 while (nfsd
->nfsd_slp
== (struct nfssvc_sock
*)0 &&
734 (nfsd_head_flag
& NFSD_CHECKSLP
) == 0) {
735 nfsd
->nfsd_flag
|= NFSD_WAITING
;
737 error
= tsleep((caddr_t
)nfsd
, PSOCK
| PCATCH
,
743 if (nfsd
->nfsd_slp
== (struct nfssvc_sock
*)0 &&
744 (nfsd_head_flag
& NFSD_CHECKSLP
) != 0) {
745 for (slp
= nfssvc_sockhead
.tqh_first
; slp
!= 0;
746 slp
= slp
->ns_chain
.tqe_next
) {
747 if ((slp
->ns_flag
& (SLP_VALID
| SLP_DOREC
))
748 == (SLP_VALID
| SLP_DOREC
)) {
749 slp
->ns_flag
&= ~SLP_DOREC
;
751 nfsd
->nfsd_slp
= slp
;
756 nfsd_head_flag
&= ~NFSD_CHECKSLP
;
758 if ((slp
= nfsd
->nfsd_slp
) == (struct nfssvc_sock
*)0)
760 if (slp
->ns_flag
& SLP_VALID
) {
762 if (slp
->ns_nflag
& SLPN_DISCONN
) {
764 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
765 } else if (slp
->ns_nflag
& SLPN_NEEDQ
) {
766 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
767 slp
->ns_nflag
&= ~SLPN_NEEDQ
;
768 nfsrv_rcv(slp
->ns_so
, (caddr_t
)slp
,
771 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
772 error
= nfsrv_dorec(slp
, nfsd
, &nd
);
773 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
776 cur_usec
= (u_quad_t
)now
.tv_sec
* 1000000 +
777 (u_quad_t
)now
.tv_usec
;
778 if (error
&& slp
->ns_tq
.lh_first
&&
779 slp
->ns_tq
.lh_first
->nd_time
<= cur_usec
) {
785 nfsd
->nfsd_flag
|= NFSD_REQINPROG
;
789 slp
= nfsd
->nfsd_slp
;
791 if (error
|| (slp
->ns_flag
& SLP_VALID
) == 0) {
794 m_freem(nd
->nd_nam2
);
795 FREE_ZONE((caddr_t
)nd
,
796 sizeof *nd
, M_NFSRVDESC
);
799 nfsd
->nfsd_slp
= (struct nfssvc_sock
*)0;
800 nfsd
->nfsd_flag
&= ~NFSD_REQINPROG
;
806 sotype
= so
->so_type
;
808 microuptime(&nd
->nd_starttime
);
810 nd
->nd_nam
= nd
->nd_nam2
;
812 nd
->nd_nam
= slp
->ns_nam
;
815 * Check to see if authorization is needed.
817 if (nfsd
->nfsd_flag
& NFSD_NEEDAUTH
) {
818 nfsd
->nfsd_flag
&= ~NFSD_NEEDAUTH
;
819 nsd
->nsd_haddr
= mtod(nd
->nd_nam
,
820 struct sockaddr_in
*)->sin_addr
.s_addr
;
821 nsd
->nsd_authlen
= nfsd
->nfsd_authlen
;
822 nsd
->nsd_verflen
= nfsd
->nfsd_verflen
;
823 if (!copyout(nfsd
->nfsd_authstr
,nsd
->nsd_authstr
,
824 nfsd
->nfsd_authlen
) &&
825 !copyout(nfsd
->nfsd_verfstr
, nsd
->nsd_verfstr
,
826 nfsd
->nfsd_verflen
) &&
827 !copyout((caddr_t
)nsd
, argp
, sizeof (*nsd
)))
829 cacherep
= RC_DROPIT
;
831 cacherep
= nfsrv_getcache(nd
, slp
, &mreq
);
834 * Check for just starting up for NQNFS and send
835 * fake "try again later" replies to the NQNFS clients.
838 if (notstarted
&& nqnfsstarttime
<= now
.tv_sec
) {
840 nqnfsstarttime
= now
.tv_sec
+ nqsrv_writeslack
;
846 if ((nd
->nd_flag
& ND_NQNFS
) == 0)
847 cacherep
= RC_DROPIT
;
848 else if (nd
->nd_procnum
!= NFSPROC_WRITE
) {
849 nd
->nd_procnum
= NFSPROC_NOOP
;
850 nd
->nd_repstat
= NQNFS_TRYLATER
;
854 } else if (nfsd
->nfsd_flag
& NFSD_AUTHFAIL
) {
855 nfsd
->nfsd_flag
&= ~NFSD_AUTHFAIL
;
856 nd
->nd_procnum
= NFSPROC_NOOP
;
857 nd
->nd_repstat
= (NFSERR_AUTHERR
| AUTH_TOOWEAK
);
859 } else if (nfs_privport
) {
860 /* Check if source port is privileged */
862 struct sockaddr
*nam
= mtod(nd
->nd_nam
, struct sockaddr
*);
863 struct sockaddr_in
*sin
;
865 sin
= (struct sockaddr_in
*)nam
;
866 port
= ntohs(sin
->sin_port
);
867 if (port
>= IPPORT_RESERVED
&&
868 nd
->nd_procnum
!= NFSPROC_NULL
) {
869 nd
->nd_procnum
= NFSPROC_NOOP
;
870 nd
->nd_repstat
= (NFSERR_AUTHERR
| AUTH_TOOWEAK
);
872 printf("NFS request from unprivileged port (%s:%d)\n",
873 (char *)(inet_ntoa(sin
->sin_addr
)), port
);
880 * Loop to get all the write rpc relies that have been
886 if (nd
&& (nd
->nd_flag
& ND_NFSV3
))
887 procrastinate
= nfsrvw_procrastinate_v3
;
889 procrastinate
= nfsrvw_procrastinate
;
890 if (writes_todo
|| (nd
->nd_procnum
== NFSPROC_WRITE
&&
891 procrastinate
> 0 && !notstarted
))
892 error
= nfsrv_writegather(&nd
, slp
,
893 nfsd
->nfsd_procp
, &mreq
);
895 error
= (*(nfsrv3_procs
[nd
->nd_procnum
]))(nd
,
896 slp
, nfsd
->nfsd_procp
, &mreq
);
900 if (nd
->nd_procnum
!= NQNFSPROC_VACATED
)
902 nfsrv_updatecache(nd
, FALSE
, mreq
);
904 m_freem(nd
->nd_nam2
);
909 nfsstats
.srvrpccnt
[nd
->nd_procnum
]++;
910 nfsrv_updatecache(nd
, TRUE
, mreq
);
911 nd
->nd_mrep
= (struct mbuf
*)0;
919 if (siz
<= 0 || siz
> NFS_MAXPACKET
) {
920 printf("mbuf siz=%d\n",siz
);
921 panic("Bad nfs svc reply");
924 m
->m_pkthdr
.len
= siz
;
925 m
->m_pkthdr
.rcvif
= (struct ifnet
*)0;
927 * For stream protocols, prepend a Sun RPC
930 if (sotype
== SOCK_STREAM
) {
931 M_PREPEND(m
, NFSX_UNSIGNED
, M_WAIT
);
932 *mtod(m
, u_long
*) = htonl(0x80000000 | siz
);
934 if (so
->so_proto
->pr_flags
& PR_CONNREQUIRED
)
935 (void) nfs_slplock(slp
, 1);
936 if (slp
->ns_flag
& SLP_VALID
)
937 error
= nfs_send(so
, nd
->nd_nam2
, m
, NULL
);
944 nfsd_rt(sotype
, nd
, cacherep
);
946 MFREE(nd
->nd_nam2
, m
);
950 m_freem(nd
->nd_mrep
);
955 if (so
->so_proto
->pr_flags
& PR_CONNREQUIRED
)
957 if (error
== EINTR
|| error
== ERESTART
) {
958 FREE_ZONE((caddr_t
)nd
,
959 sizeof *nd
, M_NFSRVDESC
);
967 nfsd_rt(sotype
, nd
, cacherep
);
968 m_freem(nd
->nd_mrep
);
969 m_freem(nd
->nd_nam2
);
970 nd
->nd_mrep
= nd
->nd_nam2
= NULL
;
975 m_freem(nd
->nd_mrep
);
977 m_freem(nd
->nd_nam2
);
978 FREE_ZONE((caddr_t
)nd
, sizeof *nd
, M_NFSRVDESC
);
983 * Check to see if there are outstanding writes that
984 * need to be serviced.
987 cur_usec
= (u_quad_t
)now
.tv_sec
* 1000000 +
988 (u_quad_t
)now
.tv_usec
;
990 if (slp
->ns_tq
.lh_first
&&
991 slp
->ns_tq
.lh_first
->nd_time
<= cur_usec
) {
997 } while (writes_todo
);
999 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
1000 if (nfsrv_dorec(slp
, nfsd
, &nd
)) {
1001 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
1002 nfsd
->nfsd_flag
&= ~NFSD_REQINPROG
;
1003 nfsd
->nfsd_slp
= NULL
;
1004 nfsrv_slpderef(slp
);
1006 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
1009 TAILQ_REMOVE(&nfsd_head
, nfsd
, nfsd_chain
);
1011 _FREE((caddr_t
)nfsd
, M_NFSD
);
1012 nsd
->nsd_nfsd
= (struct nfsd
*)0;
1013 if (--nfs_numnfsd
== 0)
1014 nfsrv_init(TRUE
); /* Reinitialize everything */
1017 #endif /* NFS_NOSERVER */
1020 /* XXX CSM 11/25/97 Upgrade sysctl.h someday */
1022 SYSCTL_INT(_vfs_nfs
, OID_AUTO
, defect
, CTLFLAG_RW
, &nfs_defect
, 0, "");
1025 #ifndef _SYS_SYSPROTO_H_
1026 struct nfsclnt_args
{
1032 nfsclnt(struct proc
*p
, struct nfsclnt_args
*uap
)
1034 struct lockd_ans la
;
1037 if (uap
->flag
== NFSCLNT_LOCKDWAIT
) {
1038 return (nfslockdwait(p
));
1040 if (uap
->flag
== NFSCLNT_LOCKDANS
) {
1041 error
= copyin(uap
->argp
, &la
, sizeof(la
));
1042 return (error
!= 0 ? error
: nfslockdans(p
, &la
));
1044 if (uap
->flag
== NFSCLNT_LOCKDFD
)
1045 return (nfslockdfd(p
, (int)uap
->argp
));
1050 static int nfssvc_iod_continue(int);
1053 * Asynchronous I/O daemons for client nfs.
1054 * They do read-ahead and write-behind operations on the block I/O cache.
1055 * Never returns unless it fails or gets killed.
1061 register int i
, myiod
;
1062 struct nfsmount
*nmp
;
1067 * Assign my position or return error if too many already running
1070 for (i
= 0; i
< NFS_MAXASYNCDAEMON
; i
++)
1071 if (nfs_asyncdaemon
[i
] == 0) {
1072 nfs_asyncdaemon
[i
]++;
1080 /* stuff myiod into uthread to get off local stack for continuation */
1082 ut
= (struct uthread
*)get_bsdthread_info(current_act());
1083 ut
->uu_state
.uu_nfs_myiod
= myiod
; /* squirrel away for continuation */
1085 nfssvc_iod_continue(0);
1091 * Continuation for Asynchronous I/O daemons for client nfs.
1094 nfssvc_iod_continue(error
)
1096 register struct nfsbuf
*bp
;
1097 register int i
, myiod
;
1098 struct nfsmount
*nmp
;
1103 * real myiod is stored in uthread, recover it
1105 ut
= (struct uthread
*)get_bsdthread_info(current_act());
1106 myiod
= ut
->uu_state
.uu_nfs_myiod
;
1110 * Just loop around doin our stuff until SIGKILL
1111 * - actually we don't loop with continuations...
1114 while (((nmp
= nfs_iodmount
[myiod
]) == NULL
1115 || nmp
->nm_bufq
.tqh_first
== NULL
)
1116 && error
== 0 && nfs_ioddelwri
== 0) {
1119 nfs_iodwant
[myiod
] = p
;
1120 nfs_iodmount
[myiod
] = NULL
;
1121 error
= tsleep0((caddr_t
)&nfs_iodwant
[myiod
],
1122 PWAIT
| PCATCH
, "nfsidl", 0, nfssvc_iod_continue
);
1126 nfs_asyncdaemon
[myiod
] = 0;
1127 if (nmp
) nmp
->nm_bufqiods
--;
1128 nfs_iodwant
[myiod
] = NULL
;
1129 nfs_iodmount
[myiod
] = NULL
;
1131 if (error
== EINTR
|| error
== ERESTART
)
1133 unix_syscall_return(error
);
1136 while ((bp
= nmp
->nm_bufq
.tqh_first
) != NULL
) {
1137 /* Take one off the front of the list */
1138 TAILQ_REMOVE(&nmp
->nm_bufq
, bp
, nb_free
);
1139 bp
->nb_free
.tqe_next
= NFSNOLIST
;
1141 if (nmp
->nm_bufqwant
&& nmp
->nm_bufqlen
< 2 * nfs_numasync
) {
1142 nmp
->nm_bufqwant
= FALSE
;
1143 wakeup(&nmp
->nm_bufq
);
1145 if (ISSET(bp
->nb_flags
, NB_READ
))
1146 (void) nfs_doio(bp
, bp
->nb_rcred
, (struct proc
*)0);
1148 (void) nfs_doio(bp
, bp
->nb_wcred
, (struct proc
*)0);
1151 * If there are more than one iod on this mount, then defect
1152 * so that the iods can be shared out fairly between the mounts
1154 if (nfs_defect
&& nmp
->nm_bufqiods
> 1) {
1156 ("nfssvc_iod: iod %d defecting from mount %p\n",
1158 nfs_iodmount
[myiod
] = NULL
;
1164 if (nfs_ioddelwri
) {
1167 while (i
< 8 && (bp
= TAILQ_FIRST(&nfsbufdelwri
)) != NULL
) {
1168 struct nfsnode
*np
= VTONFS(bp
->nb_vp
);
1169 nfs_buf_remfree(bp
);
1170 if (ISSET(bp
->nb_flags
, NB_NEEDCOMMIT
)) {
1171 /* put buffer at end of delwri list */
1172 TAILQ_INSERT_TAIL(&nfsbufdelwri
, bp
, nb_free
);
1174 nfs_flushcommits(np
->n_vnode
, (struct proc
*)0);
1176 SET(bp
->nb_flags
, (NB_BUSY
| NB_ASYNC
| NB_IOD
));
1186 * Shut down a socket associated with an nfssvc_sock structure.
1187 * Should be called with the send lock set, if required.
1188 * The trick here is to increment the sref at the start, so that the nfsds
1189 * will stop using it and clear ns_flag at the end so that it will not be
1190 * reassigned during cleanup.
1194 register struct nfssvc_sock
*slp
;
1196 register struct nfsuid
*nuidp
, *nnuidp
;
1197 register struct nfsrv_descript
*nwp
, *nnwp
;
1203 slp
->ns_flag
&= ~SLP_ALLFLAGS
;
1204 slp
->ns_nflag
&= ~SLP_ALLFLAGS
;
1207 slp
->ns_fp
= (struct file
*)0;
1209 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
1210 so
->so_upcall
= NULL
;
1211 so
->so_rcv
.sb_flags
&= ~SB_UPCALL
;
1214 MFREE(slp
->ns_nam
, m
);
1215 m_freem(slp
->ns_raw
);
1216 m_freem(slp
->ns_rec
);
1217 slp
->ns_nam
= slp
->ns_raw
= slp
->ns_rec
= NULL
;
1218 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
1219 closef(fp
, (struct proc
*)0);
1220 for (nuidp
= slp
->ns_uidlruhead
.tqh_first
; nuidp
!= 0;
1222 nnuidp
= nuidp
->nu_lru
.tqe_next
;
1223 LIST_REMOVE(nuidp
, nu_hash
);
1224 TAILQ_REMOVE(&slp
->ns_uidlruhead
, nuidp
, nu_lru
);
1225 if (nuidp
->nu_flag
& NU_NAM
)
1226 m_freem(nuidp
->nu_nam
);
1227 FREE_ZONE((caddr_t
)nuidp
,
1228 sizeof (struct nfsuid
), M_NFSUID
);
1231 for (nwp
= slp
->ns_tq
.lh_first
; nwp
; nwp
= nnwp
) {
1232 nnwp
= nwp
->nd_tq
.le_next
;
1233 LIST_REMOVE(nwp
, nd_tq
);
1234 FREE_ZONE((caddr_t
)nwp
, sizeof *nwp
, M_NFSRVDESC
);
1236 LIST_INIT(&slp
->ns_tq
);
1242 * Get an authorization string for the uid by having the mount_nfs sitting
1243 * on this mount point porpous out of the kernel and do it.
1246 nfs_getauth(nmp
, rep
, cred
, auth_str
, auth_len
, verf_str
, verf_len
, key
)
1247 register struct nfsmount
*nmp
;
1254 NFSKERBKEY_T key
; /* return session key */
1258 while ((nmp
->nm_state
& NFSSTA_WAITAUTH
) == 0) {
1259 nmp
->nm_state
|= NFSSTA_WANTAUTH
;
1260 (void) tsleep((caddr_t
)&nmp
->nm_authtype
, PSOCK
,
1261 "nfsauth1", 2 * hz
);
1262 error
= nfs_sigintr(nmp
, rep
, rep
->r_procp
);
1264 nmp
->nm_state
&= ~NFSSTA_WANTAUTH
;
1268 nmp
->nm_state
&= ~(NFSSTA_WAITAUTH
| NFSSTA_WANTAUTH
);
1269 MALLOC(*auth_str
, char *, RPCAUTH_MAXSIZ
, M_TEMP
, M_WAITOK
);
1270 nmp
->nm_authstr
= *auth_str
;
1271 nmp
->nm_authlen
= RPCAUTH_MAXSIZ
;
1272 nmp
->nm_verfstr
= verf_str
;
1273 nmp
->nm_verflen
= *verf_len
;
1274 nmp
->nm_authuid
= cred
->cr_uid
;
1275 wakeup((caddr_t
)&nmp
->nm_authstr
);
1278 * And wait for mount_nfs to do its stuff.
1280 while ((nmp
->nm_state
& NFSSTA_HASAUTH
) == 0 && error
== 0) {
1281 (void) tsleep((caddr_t
)&nmp
->nm_authlen
, PSOCK
,
1282 "nfsauth2", 2 * hz
);
1283 error
= nfs_sigintr(nmp
, rep
, rep
->r_procp
);
1285 if (nmp
->nm_state
& NFSSTA_AUTHERR
) {
1286 nmp
->nm_state
&= ~NFSSTA_AUTHERR
;
1290 _FREE((caddr_t
)*auth_str
, M_TEMP
);
1292 *auth_len
= nmp
->nm_authlen
;
1293 *verf_len
= nmp
->nm_verflen
;
1294 bcopy((caddr_t
)nmp
->nm_key
, (caddr_t
)key
, sizeof (key
));
1296 nmp
->nm_state
&= ~NFSSTA_HASAUTH
;
1297 nmp
->nm_state
|= NFSSTA_WAITAUTH
;
1298 if (nmp
->nm_state
& NFSSTA_WANTAUTH
) {
1299 nmp
->nm_state
&= ~NFSSTA_WANTAUTH
;
1300 wakeup((caddr_t
)&nmp
->nm_authtype
);
1306 * Get a nickname authenticator and verifier.
1309 nfs_getnickauth(nmp
, cred
, auth_str
, auth_len
, verf_str
, verf_len
)
1310 struct nfsmount
*nmp
;
1317 register struct nfsuid
*nuidp
;
1318 register u_long
*nickp
, *verfp
;
1319 struct timeval ktvin
, ktvout
, now
;
1322 if (verf_len
< (4 * NFSX_UNSIGNED
))
1323 panic("nfs_getnickauth verf too small");
1325 for (nuidp
= NMUIDHASH(nmp
, cred
->cr_uid
)->lh_first
;
1326 nuidp
!= 0; nuidp
= nuidp
->nu_hash
.le_next
) {
1327 if (nuidp
->nu_cr
.cr_uid
== cred
->cr_uid
)
1331 if (!nuidp
|| nuidp
->nu_expire
< now
.tv_sec
)
1335 * Move to the end of the lru list (end of lru == most recently used).
1337 TAILQ_REMOVE(&nmp
->nm_uidlruhead
, nuidp
, nu_lru
);
1338 TAILQ_INSERT_TAIL(&nmp
->nm_uidlruhead
, nuidp
, nu_lru
);
1340 MALLOC(nickp
, u_long
*, 2 * NFSX_UNSIGNED
, M_TEMP
, M_WAITOK
);
1341 *nickp
++ = txdr_unsigned(RPCAKN_NICKNAME
);
1342 *nickp
= txdr_unsigned(nuidp
->nu_nickname
);
1343 *auth_str
= (char *)nickp
;
1344 *auth_len
= 2 * NFSX_UNSIGNED
;
1347 * Now we must encrypt the verifier and package it up.
1349 verfp
= (u_long
*)verf_str
;
1350 *verfp
++ = txdr_unsigned(RPCAKN_NICKNAME
);
1352 if (now
.tv_sec
> nuidp
->nu_timestamp
.tv_sec
||
1353 (now
.tv_sec
== nuidp
->nu_timestamp
.tv_sec
&&
1354 now
.tv_usec
> nuidp
->nu_timestamp
.tv_usec
))
1355 nuidp
->nu_timestamp
= now
;
1357 nuidp
->nu_timestamp
.tv_usec
++;
1358 ktvin
.tv_sec
= txdr_unsigned(nuidp
->nu_timestamp
.tv_sec
);
1359 ktvin
.tv_usec
= txdr_unsigned(nuidp
->nu_timestamp
.tv_usec
);
1362 * Now encrypt the timestamp verifier in ecb mode using the session
1369 *verfp
++ = ktvout
.tv_sec
;
1370 *verfp
++ = ktvout
.tv_usec
;
1376 * Save the current nickname in a hash list entry on the mount point.
1379 nfs_savenickauth(nmp
, cred
, len
, key
, mdp
, dposp
, mrep
)
1380 register struct nfsmount
*nmp
;
1388 register struct nfsuid
*nuidp
;
1389 register u_long
*tl
;
1391 struct mbuf
*md
= *mdp
;
1392 struct timeval ktvin
, ktvout
, now
;
1394 char *dpos
= *dposp
, *cp2
;
1395 int deltasec
, error
= 0;
1397 if (len
== (3 * NFSX_UNSIGNED
)) {
1398 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
1399 ktvin
.tv_sec
= *tl
++;
1400 ktvin
.tv_usec
= *tl
++;
1401 nick
= fxdr_unsigned(u_long
, *tl
);
1404 * Decrypt the timestamp in ecb mode.
1409 ktvout
.tv_sec
= fxdr_unsigned(long, ktvout
.tv_sec
);
1410 ktvout
.tv_usec
= fxdr_unsigned(long, ktvout
.tv_usec
);
1412 deltasec
= now
.tv_sec
- ktvout
.tv_sec
;
1414 deltasec
= -deltasec
;
1416 * If ok, add it to the hash list for the mount point.
1418 if (deltasec
<= NFS_KERBCLOCKSKEW
) {
1419 if (nmp
->nm_numuids
< nuidhash_max
) {
1421 MALLOC_ZONE(nuidp
, struct nfsuid
*,
1422 sizeof (struct nfsuid
),
1423 M_NFSUID
, M_WAITOK
);
1425 nuidp
= nmp
->nm_uidlruhead
.tqh_first
;
1426 LIST_REMOVE(nuidp
, nu_hash
);
1427 TAILQ_REMOVE(&nmp
->nm_uidlruhead
, nuidp
,
1431 nuidp
->nu_cr
.cr_uid
= cred
->cr_uid
;
1432 nuidp
->nu_expire
= now
.tv_sec
+ NFS_KERBTTL
;
1433 nuidp
->nu_timestamp
= ktvout
;
1434 nuidp
->nu_nickname
= nick
;
1435 bcopy(key
, nuidp
->nu_key
, sizeof (key
));
1436 TAILQ_INSERT_TAIL(&nmp
->nm_uidlruhead
, nuidp
,
1438 LIST_INSERT_HEAD(NMUIDHASH(nmp
, cred
->cr_uid
),
1442 nfsm_adv(nfsm_rndup(len
));
1449 #ifndef NFS_NOSERVER
1452 * Derefence a server socket structure. If it has no more references and
1453 * is no longer valid, you can throw it away.
1457 register struct nfssvc_sock
*slp
;
1459 if (--(slp
->ns_sref
) == 0 && (slp
->ns_flag
& SLP_VALID
) == 0) {
1460 TAILQ_REMOVE(&nfssvc_sockhead
, slp
, ns_chain
);
1461 _FREE((caddr_t
)slp
, M_NFSSVC
);
1466 * Lock a socket against others.
1469 nfs_slplock(slp
, wait
)
1470 register struct nfssvc_sock
*slp
;
1473 int *statep
= &slp
->ns_solock
;
1475 if (!wait
&& (*statep
& NFSSTA_SNDLOCK
))
1476 return(0); /* already locked, fail */
1477 while (*statep
& NFSSTA_SNDLOCK
) {
1478 *statep
|= NFSSTA_WANTSND
;
1479 (void) tsleep((caddr_t
)statep
, PZERO
- 1, "nfsslplck", 0);
1481 *statep
|= NFSSTA_SNDLOCK
;
1486 * Unlock the stream socket for others.
1490 struct nfssvc_sock
*slp
;
1492 int *statep
= &slp
->ns_solock
;
1494 if ((*statep
& NFSSTA_SNDLOCK
) == 0)
1495 panic("nfs slpunlock");
1496 *statep
&= ~NFSSTA_SNDLOCK
;
1497 if (*statep
& NFSSTA_WANTSND
) {
1498 *statep
&= ~NFSSTA_WANTSND
;
1499 wakeup((caddr_t
)statep
);
1504 * Initialize the data structures for the server.
1505 * Handshake with any new nfsds starting up to avoid any chance of
1509 nfsrv_init(terminating
)
1512 register struct nfssvc_sock
*slp
, *nslp
;
1514 if (nfssvc_sockhead_flag
& SLP_INIT
)
1516 nfssvc_sockhead_flag
|= SLP_INIT
;
1518 for (slp
= nfssvc_sockhead
.tqh_first
; slp
!= 0; slp
= nslp
) {
1519 nslp
= slp
->ns_chain
.tqe_next
;
1520 if (slp
->ns_flag
& SLP_VALID
)
1522 TAILQ_REMOVE(&nfssvc_sockhead
, slp
, ns_chain
);
1523 _FREE((caddr_t
)slp
, M_NFSSVC
);
1525 nfsrv_cleancache(); /* And clear out server cache */
1526 /* XXX CSM 12/4/97 Revisit when enabling WebNFS */
1529 nfs_pub
.np_valid
= 0;
1534 TAILQ_INIT(&nfssvc_sockhead
);
1535 nfssvc_sockhead_flag
&= ~SLP_INIT
;
1536 if (nfssvc_sockhead_flag
& SLP_WANTINIT
) {
1537 nfssvc_sockhead_flag
&= ~SLP_WANTINIT
;
1538 wakeup((caddr_t
)&nfssvc_sockhead
);
1541 TAILQ_INIT(&nfsd_head
);
1542 nfsd_head_flag
&= ~NFSD_CHECKSLP
;
1544 MALLOC(nfs_udpsock
, struct nfssvc_sock
*, sizeof(struct nfssvc_sock
),
1545 M_NFSSVC
, M_WAITOK
);
1546 bzero((caddr_t
)nfs_udpsock
, sizeof (struct nfssvc_sock
));
1547 TAILQ_INIT(&nfs_udpsock
->ns_uidlruhead
);
1548 TAILQ_INSERT_HEAD(&nfssvc_sockhead
, nfs_udpsock
, ns_chain
);
1550 MALLOC(nfs_cltpsock
, struct nfssvc_sock
*, sizeof(struct nfssvc_sock
),
1551 M_NFSSVC
, M_WAITOK
);
1552 bzero((caddr_t
)nfs_cltpsock
, sizeof (struct nfssvc_sock
));
1553 TAILQ_INIT(&nfs_cltpsock
->ns_uidlruhead
);
1554 TAILQ_INSERT_TAIL(&nfssvc_sockhead
, nfs_cltpsock
, ns_chain
);
1558 * Add entries to the server monitor log.
1561 nfsd_rt(sotype
, nd
, cacherep
)
1563 register struct nfsrv_descript
*nd
;
1566 register struct drt
*rt
;
1569 rt
= &nfsdrt
.drt
[nfsdrt
.pos
];
1570 if (cacherep
== RC_DOIT
)
1572 else if (cacherep
== RC_REPLY
)
1573 rt
->flag
= DRT_CACHEREPLY
;
1575 rt
->flag
= DRT_CACHEDROP
;
1576 if (sotype
== SOCK_STREAM
)
1577 rt
->flag
|= DRT_TCP
;
1578 if (nd
->nd_flag
& ND_NQNFS
)
1579 rt
->flag
|= DRT_NQNFS
;
1580 else if (nd
->nd_flag
& ND_NFSV3
)
1581 rt
->flag
|= DRT_NFSV3
;
1582 rt
->proc
= nd
->nd_procnum
;
1583 if (mtod(nd
->nd_nam
, struct sockaddr
*)->sa_family
== AF_INET
)
1584 rt
->ipadr
= mtod(nd
->nd_nam
, struct sockaddr_in
*)->sin_addr
.s_addr
;
1586 rt
->ipadr
= INADDR_ANY
;
1588 rt
->resptime
= ((now
.tv_sec
- nd
->nd_starttime
.tv_sec
) * 1000000) +
1589 (now
.tv_usec
- nd
->nd_starttime
.tv_usec
);
1590 microtime(&rt
->tstamp
); // XXX unused
1591 nfsdrt
.pos
= (nfsdrt
.pos
+ 1) % NFSRTTLOGSIZ
;
1593 #endif /* NFS_NOSERVER */