nfs_syscalls.c revision 1.10 1 /*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: @(#)nfs_syscalls.c 8.3 (Berkeley) 1/4/94
37 * $Id: nfs_syscalls.c,v 1.10 1994/06/08 11:37:02 mycroft Exp $
38 */
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/file.h>
44 #include <sys/stat.h>
45 #include <sys/vnode.h>
46 #include <sys/mount.h>
47 #include <sys/proc.h>
48 #include <sys/uio.h>
49 #include <sys/malloc.h>
50 #include <sys/buf.h>
51 #include <sys/mbuf.h>
52 #include <sys/socket.h>
53 #include <sys/socketvar.h>
54 #include <sys/domain.h>
55 #include <sys/protosw.h>
56 #include <sys/namei.h>
57 #include <sys/syslog.h>
58
59 #include <netinet/in.h>
60 #include <netinet/tcp.h>
61 #ifdef ISO
62 #include <netiso/iso.h>
63 #endif
64 #include <nfs/rpcv2.h>
65 #include <nfs/nfsv2.h>
66 #include <nfs/nfs.h>
67 #include <nfs/nfsrvcache.h>
68 #include <nfs/nfsmount.h>
69 #include <nfs/nfsnode.h>
70 #include <nfs/nqnfs.h>
71 #include <nfs/nfsrtt.h>
72
73 /* Global defs. */
74 extern u_long nfs_prog, nfs_vers;
75 extern int (*nfsrv_procs[NFS_NPROCS])();
76 extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
77 extern int nfs_numasync;
78 extern time_t nqnfsstarttime;
79 extern struct nfsrv_req nsrvq_head;
80 extern struct nfsd nfsd_head;
81 extern int nqsrv_writeslack;
82 extern int nfsrtton;
83 struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock;
84 int nuidhash_max = NFS_MAXUIDHASH;
85 static int nfs_numnfsd = 0;
86 int nfsd_waiting = 0;
87 static int notstarted = 1;
88 static int modify_flag = 0;
89 static struct nfsdrt nfsdrt;
90 void nfsrv_cleancache(), nfsrv_rcv(), nfsrv_wakenfsd(), nfs_sndunlock();
91 static void nfsd_rt();
92 void nfsrv_slpderef(), nfsrv_init();
93
94 #define TRUE 1
95 #define FALSE 0
96
97 static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON];
98 /*
99 * NFS server system calls
100 * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c
101 */
102
103 /*
104 * Get file handle system call
105 */
106 struct getfh_args {
107 char *fname;
108 fhandle_t *fhp;
109 };
110 getfh(p, uap, retval)
111 struct proc *p;
112 register struct getfh_args *uap;
113 int *retval;
114 {
115 register struct vnode *vp;
116 fhandle_t fh;
117 int error;
118 struct nameidata nd;
119
120 /*
121 * Must be super user
122 */
123 if (error = suser(p->p_ucred, &p->p_acflag))
124 return (error);
125 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
126 if (error = namei(&nd))
127 return (error);
128 vp = nd.ni_vp;
129 bzero((caddr_t)&fh, sizeof(fh));
130 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
131 error = VFS_VPTOFH(vp, &fh.fh_fid);
132 vput(vp);
133 if (error)
134 return (error);
135 error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh));
136 return (error);
137 }
138
139 static struct nfssvc_sock nfssvc_sockhead;
140
141 /*
142 * Nfs server psuedo system call for the nfsd's
143 * Based on the flag value it either:
144 * - adds a socket to the selection list
145 * - remains in the kernel as an nfsd
146 * - remains in the kernel as an nfsiod
147 */
148 struct nfssvc_args {
149 int flag;
150 caddr_t argp;
151 };
152 nfssvc(p, uap, retval)
153 struct proc *p;
154 register struct nfssvc_args *uap;
155 int *retval;
156 {
157 struct nameidata nd;
158 struct file *fp;
159 struct mbuf *nam;
160 struct nfsd_args nfsdarg;
161 struct nfsd_srvargs nfsd_srvargs, *nsd = &nfsd_srvargs;
162 struct nfsd_cargs ncd;
163 struct nfsd *nfsd;
164 struct nfssvc_sock *slp;
165 struct nfsuid *nuidp, **nuh;
166 struct nfsmount *nmp;
167 int error;
168
169 /*
170 * Must be super user
171 */
172 if (error = suser(p->p_ucred, &p->p_acflag))
173 return (error);
174 while (nfssvc_sockhead.ns_flag & SLP_INIT) {
175 nfssvc_sockhead.ns_flag |= SLP_WANTINIT;
176 (void) tsleep((caddr_t)&nfssvc_sockhead, PSOCK, "nfsd init", 0);
177 }
178 if (uap->flag & NFSSVC_BIOD) {
179 #ifndef NFSCLIENT
180 error = ENOSYS;
181 #else /* !NFSCLIENT */
182 error = nfssvc_iod(p);
183 #endif /* !NFSCLIENT */
184 } else if (uap->flag & NFSSVC_MNTD) {
185 #ifndef NFSCLIENT
186 error = ENOSYS;
187 #else /* !NFSCLIENT */
188 if (error = copyin(uap->argp, (caddr_t)&ncd, sizeof (ncd)))
189 return (error);
190 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
191 ncd.ncd_dirp, p);
192 if (error = namei(&nd))
193 return (error);
194 if ((nd.ni_vp->v_flag & VROOT) == 0)
195 error = EINVAL;
196 nmp = VFSTONFS(nd.ni_vp->v_mount);
197 vput(nd.ni_vp);
198 if (error)
199 return (error);
200 if ((nmp->nm_flag & NFSMNT_MNTD) &&
201 (uap->flag & NFSSVC_GOTAUTH) == 0)
202 return (0);
203 nmp->nm_flag |= NFSMNT_MNTD;
204 error = nqnfs_clientd(nmp, p->p_ucred, &ncd, uap->flag,
205 uap->argp, p);
206 #endif /* !NFSCLIENT */
207 } else if (uap->flag & NFSSVC_ADDSOCK) {
208 #ifndef NFSSERVER
209 error = ENOSYS;
210 #else /* !NFSSERVER */
211 if (error = copyin(uap->argp, (caddr_t)&nfsdarg,
212 sizeof(nfsdarg)))
213 return (error);
214 if (error = getsock(p->p_fd, nfsdarg.sock, &fp))
215 return (error);
216 /*
217 * Get the client address for connected sockets.
218 */
219 if (nfsdarg.name == NULL || nfsdarg.namelen == 0)
220 nam = (struct mbuf *)0;
221 else if (error = sockargs(&nam, nfsdarg.name, nfsdarg.namelen,
222 MT_SONAME))
223 return (error);
224 error = nfssvc_addsock(fp, nam);
225 #endif /* !NFSSERVER */
226 } else {
227 #ifndef NFSSERVER
228 error = ENOSYS;
229 #else /* !NFSSERVER */
230 if (error = copyin(uap->argp, (caddr_t)nsd, sizeof (*nsd)))
231 return (error);
232 if ((uap->flag & NFSSVC_AUTHIN) && (nfsd = nsd->nsd_nfsd) &&
233 (nfsd->nd_slp->ns_flag & SLP_VALID)) {
234 slp = nfsd->nd_slp;
235
236 /*
237 * First check to see if another nfsd has already
238 * added this credential.
239 */
240 nuidp = slp->ns_uidh[NUIDHASH(nsd->nsd_uid)];
241 while (nuidp) {
242 if (nuidp->nu_uid == nsd->nsd_uid)
243 break;
244 nuidp = nuidp->nu_hnext;
245 }
246 if (!nuidp) {
247 /*
248 * Nope, so we will.
249 */
250 if (slp->ns_numuids < nuidhash_max) {
251 slp->ns_numuids++;
252 nuidp = (struct nfsuid *)
253 malloc(sizeof (struct nfsuid), M_NFSUID,
254 M_WAITOK);
255 } else
256 nuidp = (struct nfsuid *)0;
257 if ((slp->ns_flag & SLP_VALID) == 0) {
258 if (nuidp)
259 free((caddr_t)nuidp, M_NFSUID);
260 } else {
261 if (nuidp == (struct nfsuid *)0) {
262 nuidp = slp->ns_lruprev;
263 remque(nuidp);
264 if (nuidp->nu_hprev)
265 nuidp->nu_hprev->nu_hnext =
266 nuidp->nu_hnext;
267 if (nuidp->nu_hnext)
268 nuidp->nu_hnext->nu_hprev =
269 nuidp->nu_hprev;
270 }
271 nuidp->nu_cr = nsd->nsd_cr;
272 if (nuidp->nu_cr.cr_ngroups > NGROUPS)
273 nuidp->nu_cr.cr_ngroups = NGROUPS;
274 nuidp->nu_cr.cr_ref = 1;
275 nuidp->nu_uid = nsd->nsd_uid;
276 insque(nuidp, (struct nfsuid *)slp);
277 nuh = &slp->ns_uidh[NUIDHASH(nsd->nsd_uid)];
278 if (nuidp->nu_hnext = *nuh)
279 nuidp->nu_hnext->nu_hprev = nuidp;
280 nuidp->nu_hprev = (struct nfsuid *)0;
281 *nuh = nuidp;
282 }
283 }
284 }
285 if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd))
286 nfsd->nd_flag |= NFSD_AUTHFAIL;
287 error = nfssvc_nfsd(nsd, uap->argp, p);
288 #endif /* !NFSSERVER */
289 }
290 if (error == EINTR || error == ERESTART)
291 error = 0;
292 return (error);
293 }
294
295 #ifdef NFSSERVER
296 /*
297 * Adds a socket to the list for servicing by nfsds.
298 */
299 nfssvc_addsock(fp, mynam)
300 struct file *fp;
301 struct mbuf *mynam;
302 {
303 register struct mbuf *m;
304 register int siz;
305 register struct nfssvc_sock *slp;
306 register struct socket *so;
307 struct nfssvc_sock *tslp;
308 int error, s;
309
310 so = (struct socket *)fp->f_data;
311 tslp = (struct nfssvc_sock *)0;
312 /*
313 * Add it to the list, as required.
314 */
315 if (so->so_proto->pr_protocol == IPPROTO_UDP) {
316 tslp = nfs_udpsock;
317 if (tslp->ns_flag & SLP_VALID) {
318 m_freem(mynam);
319 return (EPERM);
320 }
321 #ifdef ISO
322 } else if (so->so_proto->pr_protocol == ISOPROTO_CLTP) {
323 tslp = nfs_cltpsock;
324 if (tslp->ns_flag & SLP_VALID) {
325 m_freem(mynam);
326 return (EPERM);
327 }
328 #endif /* ISO */
329 }
330 if (so->so_type == SOCK_STREAM)
331 siz = NFS_MAXPACKET + sizeof (u_long);
332 else
333 siz = NFS_MAXPACKET;
334 if (error = soreserve(so, siz, siz)) {
335 m_freem(mynam);
336 return (error);
337 }
338
339 /*
340 * Set protocol specific options { for now TCP only } and
341 * reserve some space. For datagram sockets, this can get called
342 * repeatedly for the same socket, but that isn't harmful.
343 */
344 if (so->so_type == SOCK_STREAM) {
345 MGET(m, M_WAIT, MT_SOOPTS);
346 *mtod(m, int *) = 1;
347 m->m_len = sizeof(int);
348 sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m);
349 }
350 if (so->so_proto->pr_domain->dom_family == AF_INET &&
351 so->so_proto->pr_protocol == IPPROTO_TCP) {
352 MGET(m, M_WAIT, MT_SOOPTS);
353 *mtod(m, int *) = 1;
354 m->m_len = sizeof(int);
355 sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m);
356 }
357 so->so_rcv.sb_flags &= ~SB_NOINTR;
358 so->so_rcv.sb_timeo = 0;
359 so->so_snd.sb_flags &= ~SB_NOINTR;
360 so->so_snd.sb_timeo = 0;
361 if (tslp)
362 slp = tslp;
363 else {
364 slp = (struct nfssvc_sock *)
365 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
366 bzero((caddr_t)slp, sizeof (struct nfssvc_sock));
367 slp->ns_prev = nfssvc_sockhead.ns_prev;
368 slp->ns_prev->ns_next = slp;
369 slp->ns_next = &nfssvc_sockhead;
370 nfssvc_sockhead.ns_prev = slp;
371 slp->ns_lrunext = slp->ns_lruprev = (struct nfsuid *)slp;
372 }
373 slp->ns_so = so;
374 slp->ns_nam = mynam;
375 fp->f_count++;
376 slp->ns_fp = fp;
377 s = splnet();
378 so->so_upcallarg = (caddr_t)slp;
379 so->so_upcall = nfsrv_rcv;
380 slp->ns_flag = (SLP_VALID | SLP_NEEDQ);
381 nfsrv_wakenfsd(slp);
382 splx(s);
383 return (0);
384 }
385
386 /*
387 * Called by nfssvc() for nfsds. Just loops around servicing rpc requests
388 * until it is killed by a signal.
389 */
390 nfssvc_nfsd(nsd, argp, p)
391 struct nfsd_srvargs *nsd;
392 caddr_t argp;
393 struct proc *p;
394 {
395 register struct mbuf *m, *nam2;
396 register int siz;
397 register struct nfssvc_sock *slp;
398 register struct socket *so;
399 register int *solockp;
400 struct nfsd *nd = nsd->nsd_nfsd;
401 struct mbuf *mreq, *nam;
402 struct timeval starttime;
403 struct nfsuid *uidp;
404 int error, cacherep, s;
405 int sotype;
406
407 s = splnet();
408 if (nd == (struct nfsd *)0) {
409 nsd->nsd_nfsd = nd = (struct nfsd *)
410 malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK);
411 bzero((caddr_t)nd, sizeof (struct nfsd));
412 nd->nd_procp = p;
413 nd->nd_cr.cr_ref = 1;
414 insque(nd, &nfsd_head);
415 nd->nd_nqlflag = NQL_NOVAL;
416 nfs_numnfsd++;
417 }
418 /*
419 * Loop getting rpc requests until SIGKILL.
420 */
421 for (;;) {
422 if ((nd->nd_flag & NFSD_REQINPROG) == 0) {
423 while (nd->nd_slp == (struct nfssvc_sock *)0 &&
424 (nfsd_head.nd_flag & NFSD_CHECKSLP) == 0) {
425 nd->nd_flag |= NFSD_WAITING;
426 nfsd_waiting++;
427 error = tsleep((caddr_t)nd, PSOCK | PCATCH, "nfsd", 0);
428 nfsd_waiting--;
429 if (error)
430 goto done;
431 }
432 if (nd->nd_slp == (struct nfssvc_sock *)0 &&
433 (nfsd_head.nd_flag & NFSD_CHECKSLP)) {
434 slp = nfssvc_sockhead.ns_next;
435 while (slp != &nfssvc_sockhead) {
436 if ((slp->ns_flag & (SLP_VALID | SLP_DOREC))
437 == (SLP_VALID | SLP_DOREC)) {
438 slp->ns_flag &= ~SLP_DOREC;
439 slp->ns_sref++;
440 nd->nd_slp = slp;
441 break;
442 }
443 slp = slp->ns_next;
444 }
445 if (slp == &nfssvc_sockhead)
446 nfsd_head.nd_flag &= ~NFSD_CHECKSLP;
447 }
448 if ((slp = nd->nd_slp) == (struct nfssvc_sock *)0)
449 continue;
450 if (slp->ns_flag & SLP_VALID) {
451 if (slp->ns_flag & SLP_DISCONN)
452 nfsrv_zapsock(slp);
453 else if (slp->ns_flag & SLP_NEEDQ) {
454 slp->ns_flag &= ~SLP_NEEDQ;
455 (void) nfs_sndlock(&slp->ns_solock,
456 (struct nfsreq *)0);
457 nfsrv_rcv(slp->ns_so, (caddr_t)slp,
458 M_WAIT);
459 nfs_sndunlock(&slp->ns_solock);
460 }
461 error = nfsrv_dorec(slp, nd);
462 nd->nd_flag |= NFSD_REQINPROG;
463 }
464 } else {
465 error = 0;
466 slp = nd->nd_slp;
467 }
468 if (error || (slp->ns_flag & SLP_VALID) == 0) {
469 nd->nd_slp = (struct nfssvc_sock *)0;
470 nd->nd_flag &= ~NFSD_REQINPROG;
471 nfsrv_slpderef(slp);
472 continue;
473 }
474 splx(s);
475 so = slp->ns_so;
476 sotype = so->so_type;
477 starttime = time;
478 if (so->so_proto->pr_flags & PR_CONNREQUIRED)
479 solockp = &slp->ns_solock;
480 else
481 solockp = (int *)0;
482 /*
483 * nam == nam2 for connectionless protocols such as UDP
484 * nam2 == NULL for connection based protocols to disable
485 * recent request caching.
486 */
487 if (nam2 = nd->nd_nam) {
488 nam = nam2;
489 cacherep = RC_CHECKIT;
490 } else {
491 nam = slp->ns_nam;
492 cacherep = RC_DOIT;
493 }
494
495 /*
496 * Check to see if authorization is needed.
497 */
498 if (nd->nd_flag & NFSD_NEEDAUTH) {
499 static int logauth = 0;
500
501 nd->nd_flag &= ~NFSD_NEEDAUTH;
502 /*
503 * Check for a mapping already installed.
504 */
505 uidp = slp->ns_uidh[NUIDHASH(nd->nd_cr.cr_uid)];
506 while (uidp) {
507 if (uidp->nu_uid == nd->nd_cr.cr_uid)
508 break;
509 uidp = uidp->nu_hnext;
510 }
511 if (!uidp) {
512 nsd->nsd_uid = nd->nd_cr.cr_uid;
513 if (nam2 && logauth++ == 0)
514 log(LOG_WARNING, "Kerberized NFS using UDP\n");
515 nsd->nsd_haddr =
516 mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
517 nsd->nsd_authlen = nd->nd_authlen;
518 if (copyout(nd->nd_authstr, nsd->nsd_authstr,
519 nd->nd_authlen) == 0 &&
520 copyout((caddr_t)nsd, argp, sizeof (*nsd)) == 0)
521 return (ENEEDAUTH);
522 cacherep = RC_DROPIT;
523 }
524 }
525 if (cacherep == RC_CHECKIT)
526 cacherep = nfsrv_getcache(nam2, nd, &mreq);
527
528 /*
529 * Check for just starting up for NQNFS and send
530 * fake "try again later" replies to the NQNFS clients.
531 */
532 if (notstarted && nqnfsstarttime <= time.tv_sec) {
533 if (modify_flag) {
534 nqnfsstarttime = time.tv_sec + nqsrv_writeslack;
535 modify_flag = 0;
536 } else
537 notstarted = 0;
538 }
539 if (notstarted) {
540 if (nd->nd_nqlflag == NQL_NOVAL)
541 cacherep = RC_DROPIT;
542 else if (nd->nd_procnum != NFSPROC_WRITE) {
543 nd->nd_procnum = NFSPROC_NOOP;
544 nd->nd_repstat = NQNFS_TRYLATER;
545 cacherep = RC_DOIT;
546 } else
547 modify_flag = 1;
548 } else if (nd->nd_flag & NFSD_AUTHFAIL) {
549 nd->nd_flag &= ~NFSD_AUTHFAIL;
550 nd->nd_procnum = NFSPROC_NOOP;
551 nd->nd_repstat = NQNFS_AUTHERR;
552 cacherep = RC_DOIT;
553 }
554
555 switch (cacherep) {
556 case RC_DOIT:
557 error = (*(nfsrv_procs[nd->nd_procnum]))(nd,
558 nd->nd_mrep, nd->nd_md, nd->nd_dpos, &nd->nd_cr,
559 nam, &mreq);
560 if (nd->nd_cr.cr_ref != 1) {
561 printf("nfssvc cref=%d\n", nd->nd_cr.cr_ref);
562 panic("nfssvc cref");
563 }
564 if (error) {
565 if (nd->nd_procnum != NQNFSPROC_VACATED)
566 nfsstats.srv_errs++;
567 if (nam2) {
568 nfsrv_updatecache(nam2, nd, FALSE, mreq);
569 m_freem(nam2);
570 }
571 break;
572 }
573 nfsstats.srvrpccnt[nd->nd_procnum]++;
574 if (nam2)
575 nfsrv_updatecache(nam2, nd, TRUE, mreq);
576 nd->nd_mrep = (struct mbuf *)0;
577 case RC_REPLY:
578 m = mreq;
579 siz = 0;
580 while (m) {
581 siz += m->m_len;
582 m = m->m_next;
583 }
584 if (siz <= 0 || siz > NFS_MAXPACKET) {
585 printf("mbuf siz=%d\n",siz);
586 panic("Bad nfs svc reply");
587 }
588 m = mreq;
589 m->m_pkthdr.len = siz;
590 m->m_pkthdr.rcvif = (struct ifnet *)0;
591 /*
592 * For stream protocols, prepend a Sun RPC
593 * Record Mark.
594 */
595 if (sotype == SOCK_STREAM) {
596 M_PREPEND(m, NFSX_UNSIGNED, M_WAIT);
597 *mtod(m, u_long *) = htonl(0x80000000 | siz);
598 }
599 if (solockp)
600 (void) nfs_sndlock(solockp, (struct nfsreq *)0);
601 if (slp->ns_flag & SLP_VALID)
602 error = nfs_send(so, nam2, m, (struct nfsreq *)0);
603 else {
604 error = EPIPE;
605 m_freem(m);
606 }
607 if (nfsrtton)
608 nfsd_rt(&starttime, sotype, nd, nam, cacherep);
609 if (nam2)
610 MFREE(nam2, m);
611 if (nd->nd_mrep)
612 m_freem(nd->nd_mrep);
613 if (error == EPIPE)
614 nfsrv_zapsock(slp);
615 if (solockp)
616 nfs_sndunlock(solockp);
617 if (error == EINTR || error == ERESTART) {
618 nfsrv_slpderef(slp);
619 s = splnet();
620 goto done;
621 }
622 break;
623 case RC_DROPIT:
624 if (nfsrtton)
625 nfsd_rt(&starttime, sotype, nd, nam, cacherep);
626 m_freem(nd->nd_mrep);
627 m_freem(nam2);
628 break;
629 };
630 s = splnet();
631 if (nfsrv_dorec(slp, nd)) {
632 nd->nd_flag &= ~NFSD_REQINPROG;
633 nd->nd_slp = (struct nfssvc_sock *)0;
634 nfsrv_slpderef(slp);
635 }
636 }
637 done:
638 remque(nd);
639 splx(s);
640 free((caddr_t)nd, M_NFSD);
641 nsd->nsd_nfsd = (struct nfsd *)0;
642 if (--nfs_numnfsd == 0)
643 nfsrv_init(TRUE); /* Reinitialize everything */
644 return (error);
645 }
646
647 /*
648 * Shut down a socket associated with an nfssvc_sock structure.
649 * Should be called with the send lock set, if required.
650 * The trick here is to increment the sref at the start, so that the nfsds
651 * will stop using it and clear ns_flag at the end so that it will not be
652 * reassigned during cleanup.
653 */
654 nfsrv_zapsock(slp)
655 register struct nfssvc_sock *slp;
656 {
657 register struct nfsuid *nuidp, *onuidp;
658 register int i;
659 struct socket *so;
660 struct file *fp;
661 struct mbuf *m;
662
663 slp->ns_flag &= ~SLP_ALLFLAGS;
664 if (fp = slp->ns_fp) {
665 slp->ns_fp = (struct file *)0;
666 so = slp->ns_so;
667 so->so_upcall = NULL;
668 soshutdown(so, 2);
669 closef(fp, (struct proc *)0);
670 if (slp->ns_nam)
671 MFREE(slp->ns_nam, m);
672 m_freem(slp->ns_raw);
673 m_freem(slp->ns_rec);
674 nuidp = slp->ns_lrunext;
675 while (nuidp != (struct nfsuid *)slp) {
676 onuidp = nuidp;
677 nuidp = nuidp->nu_lrunext;
678 free((caddr_t)onuidp, M_NFSUID);
679 }
680 slp->ns_lrunext = slp->ns_lruprev = (struct nfsuid *)slp;
681 for (i = 0; i < NUIDHASHSIZ; i++)
682 slp->ns_uidh[i] = (struct nfsuid *)0;
683 }
684 }
685
686 /*
687 * Derefence a server socket structure. If it has no more references and
688 * is no longer valid, you can throw it away.
689 */
690 void
691 nfsrv_slpderef(slp)
692 register struct nfssvc_sock *slp;
693 {
694 if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) {
695 slp->ns_prev->ns_next = slp->ns_next;
696 slp->ns_next->ns_prev = slp->ns_prev;
697 free((caddr_t)slp, M_NFSSVC);
698 }
699 }
700
701 /*
702 * Initialize the data structures for the server.
703 * Handshake with any new nfsds starting up to avoid any chance of
704 * corruption.
705 */
706 void
707 nfsrv_init(terminating)
708 int terminating;
709 {
710 register struct nfssvc_sock *slp;
711 struct nfssvc_sock *oslp;
712
713 if (nfssvc_sockhead.ns_flag & SLP_INIT)
714 panic("nfsd init");
715 nfssvc_sockhead.ns_flag |= SLP_INIT;
716 if (terminating) {
717 slp = nfssvc_sockhead.ns_next;
718 while (slp != &nfssvc_sockhead) {
719 if (slp->ns_flag & SLP_VALID)
720 nfsrv_zapsock(slp);
721 slp->ns_next->ns_prev = slp->ns_prev;
722 slp->ns_prev->ns_next = slp->ns_next;
723 oslp = slp;
724 slp = slp->ns_next;
725 free((caddr_t)oslp, M_NFSSVC);
726 }
727 nfsrv_cleancache(); /* And clear out server cache */
728 }
729 nfs_udpsock = (struct nfssvc_sock *)
730 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
731 bzero((caddr_t)nfs_udpsock, sizeof (struct nfssvc_sock));
732 nfs_cltpsock = (struct nfssvc_sock *)
733 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
734 bzero((caddr_t)nfs_cltpsock, sizeof (struct nfssvc_sock));
735 nfssvc_sockhead.ns_next = nfs_udpsock;
736 nfs_udpsock->ns_next = nfs_cltpsock;
737 nfs_cltpsock->ns_next = &nfssvc_sockhead;
738 nfssvc_sockhead.ns_prev = nfs_cltpsock;
739 nfs_cltpsock->ns_prev = nfs_udpsock;
740 nfs_udpsock->ns_prev = &nfssvc_sockhead;
741 nfs_udpsock->ns_lrunext = nfs_udpsock->ns_lruprev =
742 (struct nfsuid *)nfs_udpsock;
743 nfs_cltpsock->ns_lrunext = nfs_cltpsock->ns_lruprev =
744 (struct nfsuid *)nfs_cltpsock;
745 nfsd_head.nd_next = nfsd_head.nd_prev = &nfsd_head;
746 nfsd_head.nd_flag = 0;
747 nfssvc_sockhead.ns_flag &= ~SLP_INIT;
748 if (nfssvc_sockhead.ns_flag & SLP_WANTINIT) {
749 nfssvc_sockhead.ns_flag &= ~SLP_WANTINIT;
750 wakeup((caddr_t)&nfssvc_sockhead);
751 }
752 }
753
754 /*
755 * Add entries to the server monitor log.
756 */
757 static void
758 nfsd_rt(startp, sotype, nd, nam, cacherep)
759 struct timeval *startp;
760 int sotype;
761 register struct nfsd *nd;
762 struct mbuf *nam;
763 int cacherep;
764 {
765 register struct drt *rt;
766
767 rt = &nfsdrt.drt[nfsdrt.pos];
768 if (cacherep == RC_DOIT)
769 rt->flag = 0;
770 else if (cacherep == RC_REPLY)
771 rt->flag = DRT_CACHEREPLY;
772 else
773 rt->flag = DRT_CACHEDROP;
774 if (sotype == SOCK_STREAM)
775 rt->flag |= DRT_TCP;
776 if (nd->nd_nqlflag != NQL_NOVAL)
777 rt->flag |= DRT_NQNFS;
778 rt->proc = nd->nd_procnum;
779 if (mtod(nam, struct sockaddr *)->sa_family == AF_INET)
780 rt->ipadr = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
781 else
782 rt->ipadr = INADDR_ANY;
783 rt->resptime = ((time.tv_sec - startp->tv_sec) * 1000000) +
784 (time.tv_usec - startp->tv_usec);
785 rt->tstamp = time;
786 nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ;
787 }
788 #endif /* NFSSERVER */
789
790 #ifdef NFSCLIENT
791 /*
792 * Asynchronous I/O daemons for client nfs.
793 * They do read-ahead and write-behind operations on the block I/O cache.
794 * Never returns unless it fails or gets killed.
795 */
796 nfssvc_iod(p)
797 struct proc *p;
798 {
799 register struct buf *bp;
800 register int i, myiod;
801 int error = 0;
802
803 /*
804 * Assign my position or return error if too many already running
805 */
806 myiod = -1;
807 for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
808 if (nfs_asyncdaemon[i] == 0) {
809 nfs_asyncdaemon[i]++;
810 myiod = i;
811 break;
812 }
813 if (myiod == -1)
814 return (EBUSY);
815 nfs_numasync++;
816 /*
817 * Just loop around doin our stuff until SIGKILL
818 */
819 for (;;) {
820 while (nfs_bufq.tqh_first == NULL && error == 0) {
821 nfs_iodwant[myiod] = p;
822 error = tsleep((caddr_t)&nfs_iodwant[myiod],
823 PWAIT | PCATCH, "nfsidl", 0);
824 }
825 while ((bp = nfs_bufq.tqh_first) != NULL) {
826 /* Take one off the front of the list */
827 TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);
828 if (bp->b_flags & B_READ)
829 (void) nfs_doio(bp, bp->b_rcred, (struct proc *)0);
830 else
831 (void) nfs_doio(bp, bp->b_wcred, (struct proc *)0);
832 }
833 if (error) {
834 nfs_asyncdaemon[myiod] = 0;
835 nfs_numasync--;
836 return (error);
837 }
838 }
839 }
840
841 /*
842 * Get an authorization string for the uid by having the mount_nfs sitting
843 * on this mount point porpous out of the kernel and do it.
844 */
845 nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
846 register struct nfsmount *nmp;
847 struct nfsreq *rep;
848 struct ucred *cred;
849 int *auth_type;
850 char **auth_str;
851 int *auth_len;
852 {
853 int error = 0;
854
855 while ((nmp->nm_flag & NFSMNT_WAITAUTH) == 0) {
856 nmp->nm_flag |= NFSMNT_WANTAUTH;
857 (void) tsleep((caddr_t)&nmp->nm_authtype, PSOCK,
858 "nfsauth1", 2 * hz);
859 if (error = nfs_sigintr(nmp, rep, rep->r_procp)) {
860 nmp->nm_flag &= ~NFSMNT_WANTAUTH;
861 return (error);
862 }
863 }
864 nmp->nm_flag &= ~(NFSMNT_WAITAUTH | NFSMNT_WANTAUTH);
865 nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK);
866 nmp->nm_authuid = cred->cr_uid;
867 wakeup((caddr_t)&nmp->nm_authstr);
868
869 /*
870 * And wait for mount_nfs to do its stuff.
871 */
872 while ((nmp->nm_flag & NFSMNT_HASAUTH) == 0 && error == 0) {
873 (void) tsleep((caddr_t)&nmp->nm_authlen, PSOCK,
874 "nfsauth2", 2 * hz);
875 error = nfs_sigintr(nmp, rep, rep->r_procp);
876 }
877 if (nmp->nm_flag & NFSMNT_AUTHERR) {
878 nmp->nm_flag &= ~NFSMNT_AUTHERR;
879 error = EAUTH;
880 }
881 if (error)
882 free((caddr_t)*auth_str, M_TEMP);
883 else {
884 *auth_type = nmp->nm_authtype;
885 *auth_len = nmp->nm_authlen;
886 }
887 nmp->nm_flag &= ~NFSMNT_HASAUTH;
888 nmp->nm_flag |= NFSMNT_WAITAUTH;
889 if (nmp->nm_flag & NFSMNT_WANTAUTH) {
890 nmp->nm_flag &= ~NFSMNT_WANTAUTH;
891 wakeup((caddr_t)&nmp->nm_authtype);
892 }
893 return (error);
894 }
895 #endif /* NFSCLIENT */
896