|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1989, 1991, 1993, 1995
28: * The Regents of the University of California. All rights reserved.
29: *
30: * This code is derived from software contributed to Berkeley by
31: * Rick Macklem at The University of Guelph.
32: *
33: * Redistribution and use in source and binary forms, with or without
34: * modification, are permitted provided that the following conditions
35: * are met:
36: * 1. Redistributions of source code must retain the above copyright
37: * notice, this list of conditions and the following disclaimer.
38: * 2. Redistributions in binary form must reproduce the above copyright
39: * notice, this list of conditions and the following disclaimer in the
40: * documentation and/or other materials provided with the distribution.
41: * 3. All advertising materials mentioning features or use of this software
42: * must display the following acknowledgement:
43: * This product includes software developed by the University of
44: * California, Berkeley and its contributors.
45: * 4. Neither the name of the University nor the names of its contributors
46: * may be used to endorse or promote products derived from this software
47: * without specific prior written permission.
48: *
49: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59: * SUCH DAMAGE.
60: *
61: * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95
62: * FreeBSD-Id: nfs_socket.c,v 1.30 1997/10/28 15:59:07 bde Exp $
63: */
64:
65: /*
66: * Socket operations for use by nfs
67: */
68:
69: #include <sys/param.h>
70: #include <sys/systm.h>
71: #include <sys/proc.h>
72: #include <sys/mount.h>
73: #include <sys/kernel.h>
74: #include <sys/mbuf.h>
75: #include <sys/malloc.h>
76: #include <sys/vnode.h>
77: #include <sys/domain.h>
78: #include <sys/protosw.h>
79: #include <sys/socket.h>
80: #include <sys/socketvar.h>
81: #include <sys/syslog.h>
82: #include <sys/tprintf.h>
83: #include <machine/spl.h>
84:
85: #include <netinet/in.h>
86: #include <netinet/tcp.h>
87:
88: #include <nfs/rpcv2.h>
89: #include <nfs/nfsproto.h>
90: #include <nfs/nfs.h>
91: #include <nfs/xdr_subs.h>
92: #include <nfs/nfsm_subs.h>
93: #include <nfs/nfsmount.h>
94: #include <nfs/nfsnode.h>
95: #include <nfs/nfsrtt.h>
96: #include <nfs/nqnfs.h>
97:
98: #define TRUE 1
99: #define FALSE 0
100:
101: /*
102: * Estimate rto for an nfs rpc sent via. an unreliable datagram.
103: * Use the mean and mean deviation of rtt for the appropriate type of rpc
104: * for the frequent rpcs and a default for the others.
105: * The justification for doing "other" this way is that these rpcs
106: * happen so infrequently that timer est. would probably be stale.
107: * Also, since many of these rpcs are
108: * non-idempotent, a conservative timeout is desired.
109: * getattr, lookup - A+2D
110: * read, write - A+4D
111: * other - nm_timeo
112: */
113: #define NFS_RTO(n, t) \
114: ((t) == 0 ? (n)->nm_timeo : \
115: ((t) < 3 ? \
116: (((((n)->nm_srtt[t-1] + 3) >> 2) + (n)->nm_sdrtt[t-1] + 1) >> 1) : \
117: ((((n)->nm_srtt[t-1] + 7) >> 3) + (n)->nm_sdrtt[t-1] + 1)))
118: #define NFS_SRTT(r) (r)->r_nmp->nm_srtt[proct[(r)->r_procnum] - 1]
119: #define NFS_SDRTT(r) (r)->r_nmp->nm_sdrtt[proct[(r)->r_procnum] - 1]
120: /*
121: * External data, mostly RPC constants in XDR form
122: */
123: extern u_long rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers, rpc_auth_unix,
124: rpc_msgaccepted, rpc_call, rpc_autherr,
125: rpc_auth_kerb;
126: extern u_long nfs_prog, nqnfs_prog;
127: extern time_t nqnfsstarttime;
128: extern struct nfsstats nfsstats;
129: extern int nfsv3_procid[NFS_NPROCS];
130: extern int nfs_ticks;
131:
132: /*
133: * Defines which timer to use for the procnum.
134: * 0 - default
135: * 1 - getattr
136: * 2 - lookup
137: * 3 - read
138: * 4 - write
139: */
140: static int proct[NFS_NPROCS] = {
141: 0, 1, 0, 2, 1, 3, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0,
142: 0, 0, 0,
143: };
144:
145: /*
146: * There is a congestion window for outstanding rpcs maintained per mount
147: * point. The cwnd size is adjusted in roughly the way that:
148: * Van Jacobson, Congestion avoidance and Control, In "Proceedings of
149: * SIGCOMM '88". ACM, August 1988.
150: * describes for TCP. The cwnd size is chopped in half on a retransmit timeout
151: * and incremented by 1/cwnd when each rpc reply is received and a full cwnd
152: * of rpcs is in progress.
153: * (The sent count and cwnd are scaled for integer arith.)
154: * Variants of "slow start" were tried and were found to be too much of a
155: * performance hit (ave. rtt 3 times larger),
156: * I suspect due to the large rtt that nfs rpcs have.
157: */
158: #define NFS_CWNDSCALE 256
159: #define NFS_MAXCWND (NFS_CWNDSCALE * 32)
160: static int nfs_backoff[8] = { 2, 4, 8, 16, 32, 64, 128, 256, };
161: int nfsrtton = 0;
162: struct nfsrtt nfsrtt;
163:
164: static int nfs_msg __P((struct proc *,char *,char *));
165: static int nfs_rcvlock __P((struct nfsreq *));
166: static void nfs_rcvunlock __P((int *flagp));
167: static int nfs_receive __P((struct nfsreq *rep, struct mbuf **aname,
168: struct mbuf **mp));
169: static int nfs_reconnect __P((struct nfsreq *rep));
170: #ifndef NFS_NOSERVER
171: static int nfsrv_getstream __P((struct nfssvc_sock *,int));
172:
173: int (*nfsrv3_procs[NFS_NPROCS]) __P((struct nfsrv_descript *nd,
174: struct nfssvc_sock *slp,
175: struct proc *procp,
176: struct mbuf **mreqp)) = {
177: nfsrv_null,
178: nfsrv_getattr,
179: nfsrv_setattr,
180: nfsrv_lookup,
181: nfsrv3_access,
182: nfsrv_readlink,
183: nfsrv_read,
184: nfsrv_write,
185: nfsrv_create,
186: nfsrv_mkdir,
187: nfsrv_symlink,
188: nfsrv_mknod,
189: nfsrv_remove,
190: nfsrv_rmdir,
191: nfsrv_rename,
192: nfsrv_link,
193: nfsrv_readdir,
194: nfsrv_readdirplus,
195: nfsrv_statfs,
196: nfsrv_fsinfo,
197: nfsrv_pathconf,
198: nfsrv_commit,
199: nqnfsrv_getlease,
200: nqnfsrv_vacated,
201: nfsrv_noop,
202: nfsrv_noop
203: };
204: #endif /* NFS_NOSERVER */
205:
206: /*
207: * Initialize sockets and congestion for a new NFS connection.
208: * We do not free the sockaddr if error.
209: */
210: int
211: nfs_connect(nmp, rep)
212: register struct nfsmount *nmp;
213: struct nfsreq *rep;
214: {
215: register struct socket *so;
216: int s, error, rcvreserve, sndreserve;
217: struct sockaddr *saddr;
218: struct sockaddr_in *sin;
219: struct mbuf *m;
220: u_short tport;
221:
222: nmp->nm_so = (struct socket *)0;
223: saddr = mtod(nmp->nm_nam, struct sockaddr *);
224: error = socreate(saddr->sa_family, &nmp->nm_so, nmp->nm_sotype,
225: nmp->nm_soproto);
226: if (error)
227: goto bad;
228: so = nmp->nm_so;
229: nmp->nm_soflags = so->so_proto->pr_flags;
230:
231: /*
232: * Some servers require that the client port be a reserved port number.
233: */
234: if (saddr->sa_family == AF_INET && (nmp->nm_flag & NFSMNT_RESVPORT)) {
235: MGET(m, M_WAIT, MT_SONAME);
236: sin = mtod(m, struct sockaddr_in *);
237: sin->sin_len = m->m_len = sizeof (struct sockaddr_in);
238: sin->sin_family = AF_INET;
239: sin->sin_addr.s_addr = INADDR_ANY;
240: tport = IPPORT_RESERVED - 1;
241: sin->sin_port = htons(tport);
242: while ((error = sobind(so, m)) == EADDRINUSE &&
243: --tport > IPPORT_RESERVED / 2)
244: sin->sin_port = htons(tport);
245: m_freem(m);
246: if (error)
247: goto bad;
248: }
249:
250: /*
251: * Protocols that do not require connections may be optionally left
252: * unconnected for servers that reply from a port other than NFS_PORT.
253: */
254: if (nmp->nm_flag & NFSMNT_NOCONN) {
255: if (nmp->nm_soflags & PR_CONNREQUIRED) {
256: error = ENOTCONN;
257: goto bad;
258: }
259: } else {
260: error = soconnect(so, nmp->nm_nam);
261: if (error)
262: goto bad;
263:
264: /*
265: * Wait for the connection to complete. Cribbed from the
266: * connect system call but with the wait timing out so
267: * that interruptible mounts don't hang here for a long time.
268: */
269: s = splnet();
270: while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
271: (void) tsleep((caddr_t)&so->so_timeo, PSOCK,
272: "nfscon", 2 * hz);
273: if ((so->so_state & SS_ISCONNECTING) &&
274: so->so_error == 0 && rep &&
275: (error = nfs_sigintr(nmp, rep, rep->r_procp))) {
276: so->so_state &= ~SS_ISCONNECTING;
277: splx(s);
278: goto bad;
279: }
280: }
281: if (so->so_error) {
282: error = so->so_error;
283: so->so_error = 0;
284: splx(s);
285: goto bad;
286: }
287: splx(s);
288: }
289: if (nmp->nm_flag & (NFSMNT_SOFT | NFSMNT_INT)) {
290: so->so_rcv.sb_timeo = (5 * hz);
291: so->so_snd.sb_timeo = (5 * hz);
292: } else {
293: so->so_rcv.sb_timeo = 0;
294: so->so_snd.sb_timeo = 0;
295: }
296: if (nmp->nm_sotype == SOCK_DGRAM) {
297: sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR) * 2;
298: rcvreserve = (nmp->nm_rsize + NFS_MAXPKTHDR) * 2;
299: } else if (nmp->nm_sotype == SOCK_SEQPACKET) {
300: sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR) * 2;
301: rcvreserve = (nmp->nm_rsize + NFS_MAXPKTHDR) * 2;
302: } else {
303: if (nmp->nm_sotype != SOCK_STREAM)
304: panic("nfscon sotype");
305: if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
306: MGET(m, M_WAIT, MT_SOOPTS);
307: *mtod(m, int *) = 1;
308: m->m_len = sizeof(int);
309: sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m);
310: }
311: if (so->so_proto->pr_protocol == IPPROTO_TCP) {
312: MGET(m, M_WAIT, MT_SOOPTS);
313: *mtod(m, int *) = 1;
314: m->m_len = sizeof(int);
315: sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m);
316: }
317: sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR + sizeof (u_long))
318: * 2;
319: rcvreserve = (nmp->nm_rsize + NFS_MAXPKTHDR + sizeof (u_long))
320: * 2;
321: }
322: error = soreserve(so, sndreserve, rcvreserve);
323: if (error)
324: goto bad;
325: so->so_rcv.sb_flags |= SB_NOINTR;
326: so->so_snd.sb_flags |= SB_NOINTR;
327:
328: /* Initialize other non-zero congestion variables */
329: nmp->nm_srtt[0] = nmp->nm_srtt[1] = nmp->nm_srtt[2] = nmp->nm_srtt[3] =
330: nmp->nm_srtt[4] = (NFS_TIMEO << 3);
331: nmp->nm_sdrtt[0] = nmp->nm_sdrtt[1] = nmp->nm_sdrtt[2] =
332: nmp->nm_sdrtt[3] = nmp->nm_sdrtt[4] = 0;
333: nmp->nm_cwnd = NFS_MAXCWND / 2; /* Initial send window */
334: nmp->nm_sent = 0;
335: nmp->nm_timeouts = 0;
336: return (0);
337:
338: bad:
339: nfs_disconnect(nmp);
340: return (error);
341: }
342:
343: /*
344: * Reconnect routine:
345: * Called when a connection is broken on a reliable protocol.
346: * - clean up the old socket
347: * - nfs_connect() again
348: * - set R_MUSTRESEND for all outstanding requests on mount point
349: * If this fails the mount point is DEAD!
350: * nb: Must be called with the nfs_sndlock() set on the mount point.
351: */
352: static int
353: nfs_reconnect(rep)
354: register struct nfsreq *rep;
355: {
356: register struct nfsreq *rp;
357: register struct nfsmount *nmp = rep->r_nmp;
358: int error;
359:
360: nfs_disconnect(nmp);
361: while ((error = nfs_connect(nmp, rep))) {
362: if (error == EINTR || error == ERESTART)
363: return (EINTR);
364: (void) tsleep((caddr_t)&lbolt, PSOCK, "nfscon", 0);
365: }
366:
367: /*
368: * Loop through outstanding request list and fix up all requests
369: * on old socket.
370: */
371: for (rp = nfs_reqq.tqh_first; rp != 0; rp = rp->r_chain.tqe_next) {
372: if (rp->r_nmp == nmp)
373: rp->r_flags |= R_MUSTRESEND;
374: }
375: return (0);
376: }
377:
378: /*
379: * NFS disconnect. Clean up and unlink.
380: */
381: void
382: nfs_disconnect(nmp)
383: register struct nfsmount *nmp;
384: {
385: register struct socket *so;
386:
387: if (nmp->nm_so) {
388: so = nmp->nm_so;
389: nmp->nm_so = (struct socket *)0;
390: soshutdown(so, 2);
391: soclose(so);
392: }
393: }
394:
395: /*
396: * This is the nfs send routine. For connection based socket types, it
397: * must be called with an nfs_sndlock() on the socket.
398: * "rep == NULL" indicates that it has been called from a server.
399: * For the client side:
400: * - return EINTR if the RPC is terminated, 0 otherwise
401: * - set R_MUSTRESEND if the send fails for any reason
402: * - do any cleanup required by recoverable socket errors (???)
403: * For the server side:
404: * - return EINTR or ERESTART if interrupted by a signal
405: * - return EPIPE if a connection is lost for connection based sockets (TCP...)
406: * - do any cleanup required by recoverable socket errors (???)
407: */
408: int
409: nfs_send(so, nam, top, rep)
410: register struct socket *so;
411: struct mbuf *nam;
412: register struct mbuf *top;
413: struct nfsreq *rep;
414: {
415: struct mbuf *sendnam;
416: int error, soflags, flags;
417:
418: if (rep) {
419: if (rep->r_flags & R_SOFTTERM) {
420: m_freem(top);
421: return (EINTR);
422: }
423: if ((so = rep->r_nmp->nm_so) == NULL) {
424: rep->r_flags |= R_MUSTRESEND;
425: m_freem(top);
426: return (0);
427: }
428: rep->r_flags &= ~R_MUSTRESEND;
429: soflags = rep->r_nmp->nm_soflags;
430: } else
431: soflags = so->so_proto->pr_flags;
432: if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED))
433: sendnam = (struct mbuf *)0;
434: else
435: sendnam = nam;
436: if (so->so_type == SOCK_SEQPACKET)
437: flags = MSG_EOR;
438: else
439: flags = 0;
440:
441: error = sosend(so, sendnam, (struct uio *)0, top,
442: (struct mbuf *)0, flags);
443: if (error) {
444: if (rep) {
445: log(LOG_INFO, "nfs send error %d for server %s\n",
446: error,
447: rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
448: /*
449: * Deal with errors for the client side.
450: */
451: if (rep->r_flags & R_SOFTTERM)
452: error = EINTR;
453: else
454: rep->r_flags |= R_MUSTRESEND;
455: } else
456: log(LOG_INFO, "nfsd send error %d\n", error);
457:
458: /*
459: * Handle any recoverable (soft) socket errors here. (???)
460: */
461: if (error != EINTR && error != ERESTART &&
462: error != EWOULDBLOCK && error != EPIPE)
463: error = 0;
464: }
465: return (error);
466: }
467:
468: /*
469: * Receive a Sun RPC Request/Reply. For SOCK_DGRAM, the work is all
470: * done by soreceive(), but for SOCK_STREAM we must deal with the Record
471: * Mark and consolidate the data into a new mbuf list.
472: * nb: Sometimes TCP passes the data up to soreceive() in long lists of
473: * small mbufs.
474: * For SOCK_STREAM we must be very careful to read an entire record once
475: * we have read any of it, even if the system call has been interrupted.
476: */
477: static int
478: nfs_receive(rep, aname, mp)
479: register struct nfsreq *rep;
480: struct mbuf **aname;
481: struct mbuf **mp;
482: {
483: register struct socket *so;
484: struct uio auio;
485: struct iovec aio;
486: register struct mbuf *m;
487: struct mbuf *control;
488: u_long len;
489: struct mbuf **getnam;
490: int error, sotype, rcvflg;
491: struct proc *p = current_proc(); /* XXX */
492:
493: /*
494: * Set up arguments for soreceive()
495: */
496: *mp = (struct mbuf *)0;
497: *aname = (struct mbuf *)0;
498: sotype = rep->r_nmp->nm_sotype;
499:
500: /*
501: * For reliable protocols, lock against other senders/receivers
502: * in case a reconnect is necessary.
503: * For SOCK_STREAM, first get the Record Mark to find out how much
504: * more there is to get.
505: * We must lock the socket against other receivers
506: * until we have an entire rpc request/reply.
507: */
508: if (sotype != SOCK_DGRAM) {
509: error = nfs_sndlock(&rep->r_nmp->nm_flag, rep);
510: if (error)
511: return (error);
512: tryagain:
513: /*
514: * Check for fatal errors and resending request.
515: */
516: /*
517: * Ugh: If a reconnect attempt just happened, nm_so
518: * would have changed. NULL indicates a failed
519: * attempt that has essentially shut down this
520: * mount point.
521: */
522: if (rep->r_mrep || (rep->r_flags & R_SOFTTERM)) {
523: nfs_sndunlock(&rep->r_nmp->nm_flag);
524: return (EINTR);
525: }
526: so = rep->r_nmp->nm_so;
527: if (!so) {
528: error = nfs_reconnect(rep);
529: if (error) {
530: nfs_sndunlock(&rep->r_nmp->nm_flag);
531: return (error);
532: }
533: goto tryagain;
534: }
535: while (rep->r_flags & R_MUSTRESEND) {
536: m = m_copym(rep->r_mreq, 0, M_COPYALL, M_WAIT);
537: nfsstats.rpcretries++;
538: #if DIAGNOSTIC
539: kprintf("nfs_receive %s flg=0x%x\n", rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname, rep->r_nmp->nm_flag);
540: #endif
541: error = nfs_send(so, rep->r_nmp->nm_nam, m, rep);
542: if (error) {
543: if (error == EINTR || error == ERESTART ||
544: (error = nfs_reconnect(rep))) {
545: nfs_sndunlock(&rep->r_nmp->nm_flag);
546: return (error);
547: }
548: goto tryagain;
549: }
550: }
551: nfs_sndunlock(&rep->r_nmp->nm_flag);
552: if (sotype == SOCK_STREAM) {
553: aio.iov_base = (caddr_t) &len;
554: aio.iov_len = sizeof(u_long);
555: auio.uio_iov = &aio;
556: auio.uio_iovcnt = 1;
557: auio.uio_segflg = UIO_SYSSPACE;
558: auio.uio_rw = UIO_READ;
559: auio.uio_offset = 0;
560: auio.uio_resid = sizeof(u_long);
561: auio.uio_procp = p;
562: do {
563: rcvflg = MSG_WAITALL;
564: error = soreceive(so, (struct mbuf **)0, &auio,
565: (struct mbuf **)0, (struct mbuf **)0, &rcvflg);
566: if (!rep->r_nmp) /* if unmounted then bailout */
567: goto shutout;
568: if (error == EWOULDBLOCK && rep) {
569: if (rep->r_flags & R_SOFTTERM)
570: return (EINTR);
571: }
572: } while (error == EWOULDBLOCK);
573: if (!error && auio.uio_resid > 0) {
574: log(LOG_INFO,
575: "short receive (%d/%d) from nfs server %s\n",
576: sizeof(u_long) - auio.uio_resid,
577: sizeof(u_long),
578: rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
579: error = EPIPE;
580: }
581: if (error)
582: goto errout;
583: len = ntohl(len) & ~0x80000000;
584: /*
585: * This is SERIOUS! We are out of sync with the sender
586: * and forcing a disconnect/reconnect is all I can do.
587: */
588: if (len > NFS_MAXPACKET) {
589: log(LOG_ERR, "%s (%d) from nfs server %s\n",
590: "impossible packet length",
591: len,
592: rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
593: error = EFBIG;
594: goto errout;
595: }
596: auio.uio_resid = len;
597: do {
598: rcvflg = MSG_WAITALL;
599: error = soreceive(so, (struct mbuf **)0,
600: &auio, mp, (struct mbuf **)0, &rcvflg);
601: if (!rep->r_nmp) /* if unmounted then bailout */
602: goto shutout;
603: } while (error == EWOULDBLOCK || error == EINTR ||
604: error == ERESTART);
605: if (!error && auio.uio_resid > 0) {
606: log(LOG_INFO,
607: "short receive (%d/%d) from nfs server %s\n",
608: len - auio.uio_resid, len,
609: rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
610: error = EPIPE;
611: }
612: } else {
613: /*
614: * NB: Since uio_resid is big, MSG_WAITALL is ignored
615: * and soreceive() will return when it has either a
616: * control msg or a data msg.
617: * We have no use for control msg., but must grab them
618: * and then throw them away so we know what is going
619: * on.
620: */
621: auio.uio_resid = len = 100000000; /* Anything Big */
622: auio.uio_procp = p;
623: do {
624: rcvflg = 0;
625: error = soreceive(so, (struct mbuf **)0,
626: &auio, mp, &control, &rcvflg);
627: if (!rep->r_nmp) /* if unmounted then bailout */
628: goto shutout;
629: if (control)
630: m_freem(control);
631: if (error == EWOULDBLOCK && rep) {
632: if (rep->r_flags & R_SOFTTERM)
633: return (EINTR);
634: }
635: } while (error == EWOULDBLOCK ||
636: (!error && *mp == NULL && control));
637: if ((rcvflg & MSG_EOR) == 0)
638: printf("Egad!!\n");
639: if (!error && *mp == NULL)
640: error = EPIPE;
641: len -= auio.uio_resid;
642: }
643: errout:
644: if (error && error != EINTR && error != ERESTART) {
645: m_freem(*mp);
646: *mp = (struct mbuf *)0;
647: if (error != EPIPE)
648: log(LOG_INFO,
649: "receive error %d from nfs server %s\n",
650: error,
651: rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
652: error = nfs_sndlock(&rep->r_nmp->nm_flag, rep);
653: if (!error)
654: error = nfs_reconnect(rep);
655: if (!error)
656: goto tryagain;
657: }
658: } else {
659: if ((so = rep->r_nmp->nm_so) == NULL)
660: return (EACCES);
661: if (so->so_state & SS_ISCONNECTED)
662: getnam = (struct mbuf **)0;
663: else
664: getnam = aname;
665: auio.uio_resid = len = 1000000;
666: auio.uio_procp = p;
667: do {
668: rcvflg = 0;
669: error = soreceive(so, getnam, &auio, mp,
670: (struct mbuf **)0, &rcvflg);
671: if (!rep->r_nmp) /* if unmounted then bailout */
672: goto shutout;
673: if (error == EWOULDBLOCK &&
674: (rep->r_flags & R_SOFTTERM))
675: return (EINTR);
676: } while (error == EWOULDBLOCK);
677: len -= auio.uio_resid;
678: }
679: shutout:
680: if (error) {
681: m_freem(*mp);
682: *mp = (struct mbuf *)0;
683: }
684: return (error);
685: }
686:
687: /*
688: * Implement receipt of reply on a socket.
689: * We must search through the list of received datagrams matching them
690: * with outstanding requests using the xid, until ours is found.
691: */
692: /* ARGSUSED */
693: int
694: nfs_reply(myrep)
695: struct nfsreq *myrep;
696: {
697: register struct nfsreq *rep;
698: register struct nfsmount *nmp = myrep->r_nmp;
699: register long t1;
700: struct mbuf *mrep, *md;
701: struct mbuf *nam;
702: u_long rxid, *tl;
703: caddr_t dpos, cp2;
704: int error;
705:
706: /*
707: * Loop around until we get our own reply
708: */
709: for (;;) {
710: /*
711: * Lock against other receivers so that I don't get stuck in
712: * sbwait() after someone else has received my reply for me.
713: * Also necessary for connection based protocols to avoid
714: * race conditions during a reconnect.
715: * If nfs_rcvlock() returns EALREADY, that means that
716: * the reply has already been recieved by another
717: * process and we can return immediately. In this
718: * case, the lock is not taken to avoid races with
719: * other processes.
720: */
721: error = nfs_rcvlock(myrep);
722: if (error == EALREADY)
723: return (0);
724: if (error)
725: return (error);
726: /*
727: * Get the next Rpc reply off the socket
728: */
729: error = nfs_receive(myrep, &nam, &mrep);
730: /*
731: * Bailout asap if nfsmount struct gone (unmounted)
732: */
733: if (!myrep->r_nmp)
734: return(ECONNABORTED);
735: nfs_rcvunlock(&nmp->nm_flag);
736: if (error) {
737:
738: /*
739: * Ignore routing errors on connectionless protocols??
740: */
741: if (NFSIGNORE_SOERROR(nmp->nm_soflags, error)) {
742: nmp->nm_so->so_error = 0;
743: if (myrep->r_flags & R_GETONEREP)
744: return (0);
745: continue;
746: }
747: return (error);
748: }
749: if (nam)
750: m_freem(nam);
751:
752: /*
753: * Get the xid and check that it is an rpc reply
754: */
755: md = mrep;
756: dpos = mtod(md, caddr_t);
757: nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
758: rxid = *tl++;
759: if (*tl != rpc_reply) {
760: #ifndef NFS_NOSERVER
761: if (nmp->nm_flag & NFSMNT_NQNFS) {
762: if (nqnfs_callback(nmp, mrep, md, dpos))
763: nfsstats.rpcinvalid++;
764: } else {
765: nfsstats.rpcinvalid++;
766: m_freem(mrep);
767: }
768: #else
769: nfsstats.rpcinvalid++;
770: m_freem(mrep);
771: #endif
772: nfsmout:
773: if (myrep->r_flags & R_GETONEREP)
774: return (0);
775: continue;
776: }
777:
778: /*
779: * Loop through the request list to match up the reply
780: * Iff no match, just drop the datagram
781: */
782: for (rep = nfs_reqq.tqh_first; rep != 0;
783: rep = rep->r_chain.tqe_next) {
784: if (rep->r_mrep == NULL && rxid == rep->r_xid) {
785: /* Found it.. */
786: rep->r_mrep = mrep;
787: rep->r_md = md;
788: rep->r_dpos = dpos;
789: if (nfsrtton) {
790: struct rttl *rt;
791:
792: rt = &nfsrtt.rttl[nfsrtt.pos];
793: rt->proc = rep->r_procnum;
794: rt->rto = NFS_RTO(nmp, proct[rep->r_procnum]);
795: rt->sent = nmp->nm_sent;
796: rt->cwnd = nmp->nm_cwnd;
797: rt->srtt = nmp->nm_srtt[proct[rep->r_procnum] - 1];
798: rt->sdrtt = nmp->nm_sdrtt[proct[rep->r_procnum] - 1];
799: rt->fsid = nmp->nm_mountp->mnt_stat.f_fsid;
800: rt->tstamp = time;
801: if (rep->r_flags & R_TIMING)
802: rt->rtt = rep->r_rtt;
803: else
804: rt->rtt = 1000000;
805: nfsrtt.pos = (nfsrtt.pos + 1) % NFSRTTLOGSIZ;
806: }
807: /*
808: * Update congestion window.
809: * Do the additive increase of
810: * one rpc/rtt.
811: */
812: if (nmp->nm_cwnd <= nmp->nm_sent) {
813: nmp->nm_cwnd +=
814: (NFS_CWNDSCALE * NFS_CWNDSCALE +
815: (nmp->nm_cwnd >> 1)) / nmp->nm_cwnd;
816: if (nmp->nm_cwnd > NFS_MAXCWND)
817: nmp->nm_cwnd = NFS_MAXCWND;
818: }
819: rep->r_flags &= ~R_SENT;
820: nmp->nm_sent -= NFS_CWNDSCALE;
821: /*
822: * Update rtt using a gain of 0.125 on the mean
823: * and a gain of 0.25 on the deviation.
824: */
825: if (rep->r_flags & R_TIMING) {
826: /*
827: * Since the timer resolution of
828: * NFS_HZ is so course, it can often
829: * result in r_rtt == 0. Since
830: * r_rtt == N means that the actual
831: * rtt is between N+dt and N+2-dt ticks,
832: * add 1.
833: */
834: t1 = rep->r_rtt + 1;
835: t1 -= (NFS_SRTT(rep) >> 3);
836: NFS_SRTT(rep) += t1;
837: if (t1 < 0)
838: t1 = -t1;
839: t1 -= (NFS_SDRTT(rep) >> 2);
840: NFS_SDRTT(rep) += t1;
841: }
842: nmp->nm_timeouts = 0;
843: break;
844: }
845: }
846: /*
847: * If not matched to a request, drop it.
848: * If it's mine, get out.
849: */
850: if (rep == 0) {
851: nfsstats.rpcunexpected++;
852: m_freem(mrep);
853: } else if (rep == myrep) {
854: if (rep->r_mrep == NULL)
855: panic("nfsreply nil");
856: return (0);
857: }
858: if (myrep->r_flags & R_GETONEREP)
859: return (0);
860: }
861: }
862:
863: /*
864: * nfs_request - goes something like this
865: * - fill in request struct
866: * - links it into list
867: * - calls nfs_send() for first transmit
868: * - calls nfs_receive() to get reply
869: * - break down rpc header and return with nfs reply pointed to
870: * by mrep or error
871: * nb: always frees up mreq mbuf list
872: */
873: int
874: nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
875: struct vnode *vp;
876: struct mbuf *mrest;
877: int procnum;
878: struct proc *procp;
879: struct ucred *cred;
880: struct mbuf **mrp;
881: struct mbuf **mdp;
882: caddr_t *dposp;
883: {
884: register struct mbuf *m, *mrep;
885: register struct nfsreq *rep;
886: register u_long *tl;
887: register int i;
888: struct nfsmount *nmp;
889: struct mbuf *md, *mheadend;
890: struct nfsnode *np;
891: char nickv[RPCX_NICKVERF];
892: time_t reqtime, waituntil;
893: caddr_t dpos, cp2;
894: int t1, nqlflag, cachable, s, error = 0, mrest_len, auth_len, auth_type;
895: int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0, failed_auth = 0;
896: int verf_len, verf_type;
897: u_long xid;
898: u_quad_t frev;
899: char *auth_str, *verf_str;
900: NFSKERBKEY_T key; /* save session key */
901:
902: NFSTRACE4(NFSTRC_REQ, vp, procnum, 0, 0);
903: nmp = VFSTONFS(vp->v_mount);
904: MALLOC_ZONE(rep, struct nfsreq *,
905: sizeof(struct nfsreq), M_NFSREQ, M_WAITOK);
906: rep->r_nmp = nmp;
907: rep->r_vp = vp;
908: rep->r_procp = procp;
909: rep->r_procnum = procnum;
910: i = 0;
911: m = mrest;
912: while (m) {
913: i += m->m_len;
914: m = m->m_next;
915: }
916: mrest_len = i;
917:
918: /*
919: * Get the RPC header with authorization.
920: */
921: kerbauth:
922: verf_str = auth_str = (char *)0;
923: if (nmp->nm_flag & NFSMNT_KERB) {
924: verf_str = nickv;
925: verf_len = sizeof (nickv);
926: auth_type = RPCAUTH_KERB4;
927: bzero((caddr_t)key, sizeof (key));
928: if (failed_auth || nfs_getnickauth(nmp, cred, &auth_str,
929: &auth_len, verf_str, verf_len)) {
930: error = nfs_getauth(nmp, rep, cred, &auth_str,
931: &auth_len, verf_str, &verf_len, key);
932: if (error) {
933: _FREE_ZONE((caddr_t)rep,
934: sizeof (struct nfsreq), M_NFSREQ);
935: m_freem(mrest);
936: return (error);
937: }
938: }
939: } else {
940: auth_type = RPCAUTH_UNIX;
941: if (cred->cr_ngroups < 1)
942: panic("nfsreq nogrps");
943: auth_len = ((((cred->cr_ngroups - 1) > nmp->nm_numgrps) ?
944: nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) +
945: 5 * NFSX_UNSIGNED;
946: }
947: m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len,
948: auth_str, verf_len, verf_str, mrest, mrest_len, &mheadend, &xid);
949: if (auth_str)
950: _FREE(auth_str, M_TEMP);
951:
952: /*
953: * For stream protocols, insert a Sun RPC Record Mark.
954: */
955: if (nmp->nm_sotype == SOCK_STREAM) {
956: M_PREPEND(m, NFSX_UNSIGNED, M_WAIT);
957: *mtod(m, u_long *) = htonl(0x80000000 |
958: (m->m_pkthdr.len - NFSX_UNSIGNED));
959: }
960: rep->r_mreq = m;
961: rep->r_xid = xid;
962: tryagain:
963: if (nmp->nm_flag & NFSMNT_SOFT)
964: rep->r_retry = nmp->nm_retry;
965: else
966: rep->r_retry = NFS_MAXREXMIT + 1; /* past clip limit */
967: rep->r_rtt = rep->r_rexmit = 0;
968: if (proct[procnum] > 0)
969: rep->r_flags = R_TIMING;
970: else
971: rep->r_flags = 0;
972: rep->r_mrep = NULL;
973:
974: /*
975: * Do the client side RPC.
976: */
977: nfsstats.rpcrequests++;
978: /*
979: * Chain request into list of outstanding requests. Be sure
980: * to put it LAST so timer finds oldest requests first.
981: */
982: s = splsoftclock();
983: TAILQ_INSERT_TAIL(&nfs_reqq, rep, r_chain);
984:
985: /* Get send time for nqnfs */
986: reqtime = time.tv_sec;
987:
988: /*
989: * If backing off another request or avoiding congestion, don't
990: * send this one now but let timer do it. If not timing a request,
991: * do it now.
992: */
993: if (nmp->nm_so && (nmp->nm_sotype != SOCK_DGRAM ||
994: (nmp->nm_flag & NFSMNT_DUMBTIMR) ||
995: nmp->nm_sent < nmp->nm_cwnd)) {
996: splx(s);
997: if (nmp->nm_soflags & PR_CONNREQUIRED)
998: error = nfs_sndlock(&nmp->nm_flag, rep);
999: if (!error) {
1000: m = m_copym(m, 0, M_COPYALL, M_WAIT);
1001: error = nfs_send(nmp->nm_so, nmp->nm_nam, m, rep);
1002: if (nmp->nm_soflags & PR_CONNREQUIRED)
1003: nfs_sndunlock(&nmp->nm_flag);
1004: }
1005: if (!error && (rep->r_flags & R_MUSTRESEND) == 0) {
1006: nmp->nm_sent += NFS_CWNDSCALE;
1007: rep->r_flags |= R_SENT;
1008: }
1009: } else {
1010: splx(s);
1011: rep->r_rtt = -1;
1012: }
1013:
1014: /*
1015: * Wait for the reply from our send or the timer's.
1016: */
1017: if (!error || error == EPIPE)
1018: error = nfs_reply(rep);
1019:
1020: /*
1021: * RPC done, unlink the request.
1022: */
1023: s = splsoftclock();
1024: TAILQ_REMOVE(&nfs_reqq, rep, r_chain);
1025: splx(s);
1026:
1027: /*
1028: * Decrement the outstanding request count.
1029: */
1030: if (rep->r_flags & R_SENT) {
1031: rep->r_flags &= ~R_SENT; /* paranoia */
1032: nmp->nm_sent -= NFS_CWNDSCALE;
1033: }
1034:
1035: /*
1036: * If there was a successful reply and a tprintf msg.
1037: * tprintf a response.
1038: */
1039: if (!error && (rep->r_flags & R_TPRINTFMSG))
1040: nfs_msg(rep->r_procp, nmp->nm_mountp->mnt_stat.f_mntfromname,
1041: "is alive again");
1042: mrep = rep->r_mrep;
1043: md = rep->r_md;
1044: dpos = rep->r_dpos;
1045: if (error) {
1046: m_freem(rep->r_mreq);
1047: _FREE_ZONE((caddr_t)rep, sizeof (struct nfsreq), M_NFSREQ);
1048: return (error);
1049: }
1050:
1051: /*
1052: * break down the rpc header and check if ok
1053: */
1054: nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
1055: if (*tl++ == rpc_msgdenied) {
1056: if (*tl == rpc_mismatch)
1057: error = EOPNOTSUPP;
1058: else if ((nmp->nm_flag & NFSMNT_KERB) && *tl++ == rpc_autherr) {
1059: if (!failed_auth) {
1060: failed_auth++;
1061: mheadend->m_next = (struct mbuf *)0;
1062: m_freem(mrep);
1063: m_freem(rep->r_mreq);
1064: goto kerbauth;
1065: } else
1066: error = EAUTH;
1067: } else
1068: error = EACCES;
1069: m_freem(mrep);
1070: m_freem(rep->r_mreq);
1071: _FREE_ZONE((caddr_t)rep, sizeof (struct nfsreq), M_NFSREQ);
1072: return (error);
1073: }
1074:
1075: /*
1076: * Grab any Kerberos verifier, otherwise just throw it away.
1077: */
1078: verf_type = fxdr_unsigned(int, *tl++);
1079: i = fxdr_unsigned(int, *tl);
1080: if ((nmp->nm_flag & NFSMNT_KERB) && verf_type == RPCAUTH_KERB4) {
1081: error = nfs_savenickauth(nmp, cred, i, key, &md, &dpos, mrep);
1082: if (error)
1083: goto nfsmout;
1084: } else if (i > 0)
1085: nfsm_adv(nfsm_rndup(i));
1086: nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
1087: /* 0 == ok */
1088: if (*tl == 0) {
1089: nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
1090: if (*tl != 0) {
1091: error = fxdr_unsigned(int, *tl);
1092: if ((nmp->nm_flag & NFSMNT_NFSV3) &&
1093: error == NFSERR_TRYLATER) {
1094: m_freem(mrep);
1095: error = 0;
1096: waituntil = time.tv_sec + trylater_delay;
1097: #if DIAGNOSTIC
1098: kprintf("nfs_request %s flag=%x trylater_cnt=%x waituntil=%lx trylater_delay=%x\n", nmp->nm_mountp->mnt_stat.f_mntfromname, nmp->nm_flag, trylater_cnt, waituntil, trylater_delay);
1099: #endif
1100: while (time.tv_sec < waituntil)
1101: (void) tsleep((caddr_t)&lbolt,
1102: PSOCK, "nqnfstry", 0);
1103: trylater_delay *= nfs_backoff[trylater_cnt];
1104: if (trylater_cnt < 7)
1105: trylater_cnt++;
1106: goto tryagain;
1107: }
1108:
1109: /*
1110: * If the File Handle was stale, invalidate the
1111: * lookup cache, just in case.
1112: */
1113: if (error == ESTALE)
1114: cache_purge(vp);
1115: if (nmp->nm_flag & NFSMNT_NFSV3) {
1116: *mrp = mrep;
1117: *mdp = md;
1118: *dposp = dpos;
1119: error |= NFSERR_RETERR;
1120: } else
1121: m_freem(mrep);
1122: m_freem(rep->r_mreq);
1123: _FREE_ZONE((caddr_t)rep,
1124: sizeof (struct nfsreq), M_NFSREQ);
1125: return (error);
1126: }
1127:
1128: /*
1129: * For nqnfs, get any lease in reply
1130: */
1131: if (nmp->nm_flag & NFSMNT_NQNFS) {
1132: nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
1133: if (*tl) {
1134: np = VTONFS(vp);
1135: nqlflag = fxdr_unsigned(int, *tl);
1136: nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED);
1137: cachable = fxdr_unsigned(int, *tl++);
1138: reqtime += fxdr_unsigned(int, *tl++);
1139: if (reqtime > time.tv_sec) {
1140: fxdr_hyper(tl, &frev);
1141: nqnfs_clientlease(nmp, np, nqlflag,
1142: cachable, reqtime, frev);
1143: }
1144: }
1145: }
1146: *mrp = mrep;
1147: *mdp = md;
1148: *dposp = dpos;
1149: m_freem(rep->r_mreq);
1150: FREE_ZONE((caddr_t)rep, sizeof (struct nfsreq), M_NFSREQ);
1151: return (0);
1152: }
1153: m_freem(mrep);
1154: error = EPROTONOSUPPORT;
1155: nfsmout:
1156: m_freem(rep->r_mreq);
1157: _FREE_ZONE((caddr_t)rep, sizeof (struct nfsreq), M_NFSREQ);
1158: return (error);
1159: }
1160:
1161: #ifndef NFS_NOSERVER
1162: /*
1163: * Generate the rpc reply header
1164: * siz arg. is used to decide if adding a cluster is worthwhile
1165: */
1166: int
1167: nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
1168: int siz;
1169: struct nfsrv_descript *nd;
1170: struct nfssvc_sock *slp;
1171: int err;
1172: int cache;
1173: u_quad_t *frev;
1174: struct mbuf **mrq;
1175: struct mbuf **mbp;
1176: caddr_t *bposp;
1177: {
1178: register u_long *tl;
1179: register struct mbuf *mreq;
1180: caddr_t bpos;
1181: struct mbuf *mb, *mb2;
1182:
1183: MGETHDR(mreq, M_WAIT, MT_DATA);
1184: mb = mreq;
1185: /*
1186: * If this is a big reply, use a cluster else
1187: * try and leave leading space for the lower level headers.
1188: */
1189: siz += RPC_REPLYSIZ;
1190: if (siz >= MINCLSIZE) {
1191: MCLGET(mreq, M_WAIT);
1192: } else
1193: mreq->m_data += max_hdr;
1194: tl = mtod(mreq, u_long *);
1195: mreq->m_len = 6 * NFSX_UNSIGNED;
1196: bpos = ((caddr_t)tl) + mreq->m_len;
1197: *tl++ = txdr_unsigned(nd->nd_retxid);
1198: *tl++ = rpc_reply;
1199: if (err == ERPCMISMATCH || (err & NFSERR_AUTHERR)) {
1200: *tl++ = rpc_msgdenied;
1201: if (err & NFSERR_AUTHERR) {
1202: *tl++ = rpc_autherr;
1203: *tl = txdr_unsigned(err & ~NFSERR_AUTHERR);
1204: mreq->m_len -= NFSX_UNSIGNED;
1205: bpos -= NFSX_UNSIGNED;
1206: } else {
1207: *tl++ = rpc_mismatch;
1208: *tl++ = txdr_unsigned(RPC_VER2);
1209: *tl = txdr_unsigned(RPC_VER2);
1210: }
1211: } else {
1212: *tl++ = rpc_msgaccepted;
1213:
1214: /*
1215: * For Kerberos authentication, we must send the nickname
1216: * verifier back, otherwise just RPCAUTH_NULL.
1217: */
1218: if (nd->nd_flag & ND_KERBFULL) {
1219: register struct nfsuid *nuidp;
1220: struct timeval ktvin, ktvout;
1221:
1222: for (nuidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
1223: nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
1224: if (nuidp->nu_cr.cr_uid == nd->nd_cr.cr_uid &&
1225: (!nd->nd_nam2 || netaddr_match(NU_NETFAM(nuidp),
1226: &nuidp->nu_haddr, nd->nd_nam2)))
1227: break;
1228: }
1229: if (nuidp) {
1230: ktvin.tv_sec =
1231: txdr_unsigned(nuidp->nu_timestamp.tv_sec - 1);
1232: ktvin.tv_usec =
1233: txdr_unsigned(nuidp->nu_timestamp.tv_usec);
1234:
1235: /*
1236: * Encrypt the timestamp in ecb mode using the
1237: * session key.
1238: */
1239: #if NFSKERB
1240: XXX
1241: #endif
1242:
1243: *tl++ = rpc_auth_kerb;
1244: *tl++ = txdr_unsigned(3 * NFSX_UNSIGNED);
1245: *tl = ktvout.tv_sec;
1246: nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
1247: *tl++ = ktvout.tv_usec;
1248: *tl++ = txdr_unsigned(nuidp->nu_cr.cr_uid);
1249: } else {
1250: *tl++ = 0;
1251: *tl++ = 0;
1252: }
1253: } else {
1254: *tl++ = 0;
1255: *tl++ = 0;
1256: }
1257: switch (err) {
1258: case EPROGUNAVAIL:
1259: *tl = txdr_unsigned(RPC_PROGUNAVAIL);
1260: break;
1261: case EPROGMISMATCH:
1262: *tl = txdr_unsigned(RPC_PROGMISMATCH);
1263: nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
1264: if (nd->nd_flag & ND_NQNFS) {
1265: *tl++ = txdr_unsigned(3);
1266: *tl = txdr_unsigned(3);
1267: } else {
1268: *tl++ = txdr_unsigned(2);
1269: *tl = txdr_unsigned(3);
1270: }
1271: break;
1272: case EPROCUNAVAIL:
1273: *tl = txdr_unsigned(RPC_PROCUNAVAIL);
1274: break;
1275: case EBADRPC:
1276: *tl = txdr_unsigned(RPC_GARBAGE);
1277: break;
1278: default:
1279: *tl = 0;
1280: if (err != NFSERR_RETVOID) {
1281: nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1282: if (err)
1283: *tl = txdr_unsigned(nfsrv_errmap(nd, err));
1284: else
1285: *tl = 0;
1286: }
1287: break;
1288: };
1289: }
1290:
1291: /*
1292: * For nqnfs, piggyback lease as requested.
1293: */
1294: if ((nd->nd_flag & ND_NQNFS) && err == 0) {
1295: if (nd->nd_flag & ND_LEASE) {
1296: nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED);
1297: *tl++ = txdr_unsigned(nd->nd_flag & ND_LEASE);
1298: *tl++ = txdr_unsigned(cache);
1299: *tl++ = txdr_unsigned(nd->nd_duration);
1300: txdr_hyper(frev, tl);
1301: } else {
1302: nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1303: *tl = 0;
1304: }
1305: }
1306: if (mrq != NULL)
1307: *mrq = mreq;
1308: *mbp = mb;
1309: *bposp = bpos;
1310: if (err != 0 && err != NFSERR_RETVOID)
1311: nfsstats.srvrpc_errs++;
1312: return (0);
1313: }
1314:
1315:
1316: #endif /* NFS_NOSERVER */
1317:
1318: #if DIAGNOSTIC
1319: int nfsprnttimo = 2;
1320: #endif
1321:
1322: /*
1323: * Nfs timer routine
1324: * Scan the nfsreq list and retranmit any requests that have timed out
1325: * To avoid retransmission attempts on STREAM sockets (in the future) make
1326: * sure to set the r_retry field to 0 (implies nm_retry == 0).
1327: */
1328: void
1329: nfs_timer(arg)
1330: void *arg; /* never used */
1331: {
1332: register struct nfsreq *rep;
1333: register struct mbuf *m;
1334: register struct socket *so;
1335: register struct nfsmount *nmp;
1336: register int timeo;
1337: int s, error;
1338: #ifndef NFS_NOSERVER
1339: static long lasttime = 0;
1340: register struct nfssvc_sock *slp;
1341: u_quad_t cur_usec;
1342: #endif /* NFS_NOSERVER */
1343: #if DIAGNOSTIC
1344: int rttdiag;
1345: #endif
1346:
1347: s = splnet();
1348: for (rep = nfs_reqq.tqh_first; rep != 0; rep = rep->r_chain.tqe_next) {
1349: nmp = rep->r_nmp;
1350: if (rep->r_mrep || (rep->r_flags & R_SOFTTERM))
1351: continue;
1352: if (nfs_sigintr(nmp, rep, rep->r_procp)) {
1353: rep->r_flags |= R_SOFTTERM;
1354: continue;
1355: }
1356: if (rep->r_rtt >= 0) {
1357: rep->r_rtt++;
1358: if (nmp->nm_flag & NFSMNT_DUMBTIMR)
1359: timeo = nmp->nm_timeo;
1360: else
1361: timeo = NFS_RTO(nmp, proct[rep->r_procnum]);
1362: if (nmp->nm_timeouts > 0)
1363: timeo *= nfs_backoff[nmp->nm_timeouts - 1];
1364: if (rep->r_rtt <= timeo)
1365: continue;
1366: if (nmp->nm_timeouts < 8)
1367: nmp->nm_timeouts++;
1368: }
1369: /*
1370: * Check for server not responding
1371: */
1372: if ((rep->r_flags & R_TPRINTFMSG) == 0 &&
1373: rep->r_rexmit > nmp->nm_deadthresh) {
1374: nfs_msg(rep->r_procp,
1375: nmp->nm_mountp->mnt_stat.f_mntfromname,
1376: "not responding");
1377: rep->r_flags |= R_TPRINTFMSG;
1378: }
1379: if (rep->r_rexmit >= rep->r_retry) { /* too many */
1380: nfsstats.rpctimeouts++;
1381: rep->r_flags |= R_SOFTTERM;
1382: continue;
1383: }
1384: if (nmp->nm_sotype != SOCK_DGRAM) {
1385: if (++rep->r_rexmit > NFS_MAXREXMIT)
1386: rep->r_rexmit = NFS_MAXREXMIT;
1387: continue;
1388: }
1389: if ((so = nmp->nm_so) == NULL)
1390: continue;
1391:
1392: /*
1393: * If there is enough space and the window allows..
1394: * Resend it
1395: * Set r_rtt to -1 in case we fail to send it now.
1396: */
1397: #if DIAGNOSTIC
1398: rttdiag = rep->r_rtt;
1399: #endif
1400: rep->r_rtt = -1;
1401: if (sbspace(&so->so_snd) >= rep->r_mreq->m_pkthdr.len &&
1402: ((nmp->nm_flag & NFSMNT_DUMBTIMR) ||
1403: (rep->r_flags & R_SENT) ||
1404: nmp->nm_sent < nmp->nm_cwnd) &&
1405: (m = m_copym(rep->r_mreq, 0, M_COPYALL, M_DONTWAIT))){
1406: #if DIAGNOSTIC
1407: if (rep->r_flags & R_SENT) { /* retry? */
1408: if (nfsprnttimo && nmp->nm_timeouts >= nfsprnttimo)
1409: kprintf("nfs_timer %s f=0x%x nmtm=%d tms=%d rtt=%d tm=%d p#=%d\n",
1410: nmp->nm_mountp->mnt_stat.f_mntfromname, nmp->nm_flag, nmp->nm_timeo, nmp->nm_timeouts, rttdiag, timeo, rep->r_procnum);
1411: }
1412: #endif
1413: if ((nmp->nm_flag & NFSMNT_NOCONN) == 0)
1414: error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, m,
1415: (struct mbuf *)0, (struct mbuf *)0);
1416: else
1417: error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, m,
1418: nmp->nm_nam, (struct mbuf *)0);
1419: if (error) {
1420: if (NFSIGNORE_SOERROR(nmp->nm_soflags, error))
1421: so->so_error = 0;
1422: } else {
1423: /*
1424: * Iff first send, start timing
1425: * else turn timing off, backoff timer
1426: * and divide congestion window by 2.
1427: */
1428: if (rep->r_flags & R_SENT) {
1429: rep->r_flags &= ~R_TIMING;
1430: if (++rep->r_rexmit > NFS_MAXREXMIT)
1431: rep->r_rexmit = NFS_MAXREXMIT;
1432: nmp->nm_cwnd >>= 1;
1433: if (nmp->nm_cwnd < NFS_CWNDSCALE)
1434: nmp->nm_cwnd = NFS_CWNDSCALE;
1435: nfsstats.rpcretries++;
1436: } else {
1437: rep->r_flags |= R_SENT;
1438: nmp->nm_sent += NFS_CWNDSCALE;
1439: }
1440: rep->r_rtt = 0;
1441: }
1442: }
1443: }
1444: #ifndef NFS_NOSERVER
1445: /*
1446: * Call the nqnfs server timer once a second to handle leases.
1447: */
1448: if (lasttime != time.tv_sec) {
1449: lasttime = time.tv_sec;
1450: nqnfs_serverd();
1451: }
1452:
1453: /*
1454: * Scan the write gathering queues for writes that need to be
1455: * completed now.
1456: */
1457: cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
1458: for (slp = nfssvc_sockhead.tqh_first; slp != 0;
1459: slp = slp->ns_chain.tqe_next) {
1460: if (slp->ns_tq.lh_first && slp->ns_tq.lh_first->nd_time<=cur_usec)
1461: nfsrv_wakenfsd(slp);
1462: }
1463: #endif /* NFS_NOSERVER */
1464: splx(s);
1465: timeout(nfs_timer, (void *)0, nfs_ticks);
1466: }
1467:
1468:
1469: /*
1470: * Test for a termination condition pending on the process.
1471: * This is used for NFSMNT_INT mounts.
1472: */
1473: int
1474: nfs_sigintr(nmp, rep, p)
1475: struct nfsmount *nmp;
1476: struct nfsreq *rep;
1477: register struct proc *p;
1478: {
1479:
1480: if (rep && (rep->r_flags & R_SOFTTERM))
1481: return (EINTR);
1482: if (!(nmp->nm_flag & NFSMNT_INT))
1483: return (0);
1484: if (p && p->p_siglist &&
1485: (((p->p_siglist & ~p->p_sigmask) & ~p->p_sigignore) &
1486: NFSINT_SIGMASK))
1487: return (EINTR);
1488: return (0);
1489: }
1490:
1491: /*
1492: * Lock a socket against others.
1493: * Necessary for STREAM sockets to ensure you get an entire rpc request/reply
1494: * and also to avoid race conditions between the processes with nfs requests
1495: * in progress when a reconnect is necessary.
1496: */
1497: int
1498: nfs_sndlock(flagp, rep)
1499: register int *flagp;
1500: struct nfsreq *rep;
1501: {
1502: struct proc *p;
1503: int slpflag = 0, slptimeo = 0;
1504:
1505: if (rep) {
1506: p = rep->r_procp;
1507: if (rep->r_nmp->nm_flag & NFSMNT_INT)
1508: slpflag = PCATCH;
1509: } else
1510: p = (struct proc *)0;
1511: while (*flagp & NFSMNT_SNDLOCK) {
1512: if (nfs_sigintr(rep->r_nmp, rep, p))
1513: return (EINTR);
1514: *flagp |= NFSMNT_WANTSND;
1515: (void) tsleep((caddr_t)flagp, slpflag | (PZERO - 1), "nfsndlck",
1516: slptimeo);
1517: if (slpflag == PCATCH) {
1518: slpflag = 0;
1519: slptimeo = 2 * hz;
1520: }
1521: }
1522: *flagp |= NFSMNT_SNDLOCK;
1523: return (0);
1524: }
1525:
1526: /*
1527: * Unlock the stream socket for others.
1528: */
1529: void
1530: nfs_sndunlock(flagp)
1531: register int *flagp;
1532: {
1533:
1534: if ((*flagp & NFSMNT_SNDLOCK) == 0)
1535: panic("nfs sndunlock");
1536: *flagp &= ~NFSMNT_SNDLOCK;
1537: if (*flagp & NFSMNT_WANTSND) {
1538: *flagp &= ~NFSMNT_WANTSND;
1539: wakeup((caddr_t)flagp);
1540: }
1541: }
1542:
1543: #if DIAGNOSTIC
1544: uint nfstraceindx = 0;
1545: struct nfstracerec nfstracebuf[NFSTBUFSIZ] = {{0,0,0,0}};
1546: uint nfstracemask = 0; /* enables trace points 0 to 31 (right to left) */
1547: #endif /* DIAGNOSTIC */
1548:
1549: static int
1550: nfs_rcvlock(rep)
1551: register struct nfsreq *rep;
1552: {
1553: register int *flagp = &rep->r_nmp->nm_flag;
1554: int slpflag, slptimeo = 0;
1555:
1556: if (*flagp & NFSMNT_INT)
1557: slpflag = PCATCH;
1558: else
1559: slpflag = 0;
1560: while (*flagp & NFSMNT_RCVLOCK) {
1561: NFSTRACE(NFSTRC_RCVLCKW, flagp);
1562: if (nfs_sigintr(rep->r_nmp, rep, rep->r_procp))
1563: return (EINTR);
1564: *flagp |= NFSMNT_WANTRCV;
1565: (void) tsleep((caddr_t)flagp, slpflag | (PZERO - 1), "nfsrcvlk",
1566: slptimeo);
1567: /*
1568: * If our reply was recieved while we were sleeping,
1569: * then just return without taking the lock to avoid a
1570: * situation where a single iod could 'capture' the
1571: * recieve lock.
1572: */
1573: if (rep->r_mrep != NULL)
1574: return (EALREADY);
1575: if (slpflag == PCATCH) {
1576: slpflag = 0;
1577: slptimeo = 2 * hz;
1578: }
1579: }
1580: NFSTRACE(NFSTRC_RCVLCK, flagp);
1581: *flagp |= NFSMNT_RCVLOCK;
1582: return (0);
1583: }
1584:
1585: /*
1586: * Unlock the stream socket for others.
1587: */
1588: static void
1589: nfs_rcvunlock(flagp)
1590: register int *flagp;
1591: {
1592:
1593: if ((*flagp & NFSMNT_RCVLOCK) == 0)
1594: panic("nfs rcvunlock");
1595: *flagp &= ~NFSMNT_RCVLOCK;
1596: if (*flagp & NFSMNT_WANTRCV) {
1597: NFSTRACE(NFSTRC_RCVUNLW, flagp);
1598: *flagp &= ~NFSMNT_WANTRCV;
1599: wakeup((caddr_t)flagp);
1600: } else {
1601: NFSTRACE(NFSTRC_RCVUNL, flagp);
1602: }
1603: }
1604:
1605:
1606: #ifndef NFS_NOSERVER
1607: /*
1608: * Socket upcall routine for the nfsd sockets.
1609: * The caddr_t arg is a pointer to the "struct nfssvc_sock".
1610: * Essentially do as much as possible non-blocking, else punt and it will
1611: * be called with M_WAIT from an nfsd.
1612: */
1613: void
1614: nfsrv_rcv(so, arg, waitflag)
1615: struct socket *so;
1616: caddr_t arg;
1617: int waitflag;
1618: {
1619: register struct nfssvc_sock *slp = (struct nfssvc_sock *)arg;
1620: register struct mbuf *m;
1621: struct mbuf *mp;
1622: struct mbuf *nam;
1623: struct uio auio;
1624: int flags, error;
1625:
1626: if ((slp->ns_flag & SLP_VALID) == 0)
1627: return;
1628: #ifdef notdef
1629: /*
1630: * Define this to test for nfsds handling this under heavy load.
1631: */
1632: if (waitflag == M_DONTWAIT) {
1633: slp->ns_flag |= SLP_NEEDQ; goto dorecs;
1634: }
1635: #endif
1636: auio.uio_procp = NULL;
1637: if (so->so_type == SOCK_STREAM) {
1638: /*
1639: * If there are already records on the queue, defer soreceive()
1640: * to an nfsd so that there is feedback to the TCP layer that
1641: * the nfs servers are heavily loaded.
1642: */
1643: if (slp->ns_rec && waitflag == M_DONTWAIT) {
1644: slp->ns_flag |= SLP_NEEDQ;
1645: goto dorecs;
1646: }
1647:
1648: /*
1649: * Do soreceive().
1650: */
1651: auio.uio_resid = 1000000000;
1652: flags = MSG_DONTWAIT;
1653: error = soreceive(so, &nam, &auio, &mp, (struct mbuf **)0, &flags);
1654: if (error || mp == (struct mbuf *)0) {
1655: if (error == EWOULDBLOCK)
1656: slp->ns_flag |= SLP_NEEDQ;
1657: else
1658: slp->ns_flag |= SLP_DISCONN;
1659: goto dorecs;
1660: }
1661: m = mp;
1662: if (slp->ns_rawend) {
1663: slp->ns_rawend->m_next = m;
1664: slp->ns_cc += 1000000000 - auio.uio_resid;
1665: } else {
1666: slp->ns_raw = m;
1667: slp->ns_cc = 1000000000 - auio.uio_resid;
1668: }
1669: while (m->m_next)
1670: m = m->m_next;
1671: slp->ns_rawend = m;
1672:
1673: /*
1674: * Now try and parse record(s) out of the raw stream data.
1675: */
1676: error = nfsrv_getstream(slp, waitflag);
1677: if (error) {
1678: if (error == EPERM)
1679: slp->ns_flag |= SLP_DISCONN;
1680: else
1681: slp->ns_flag |= SLP_NEEDQ;
1682: }
1683: } else {
1684: do {
1685: auio.uio_resid = 1000000000;
1686: flags = MSG_DONTWAIT;
1687: error = soreceive(so, &nam, &auio, &mp,
1688: (struct mbuf **)0, &flags);
1689: if (mp) {
1690: if (nam) {
1691: m = nam;
1692: m->m_next = mp;
1693: } else
1694: m = mp;
1695: if (slp->ns_recend)
1696: slp->ns_recend->m_nextpkt = m;
1697: else
1698: slp->ns_rec = m;
1699: slp->ns_recend = m;
1700: m->m_nextpkt = (struct mbuf *)0;
1701: }
1702: if (error) {
1703: if ((so->so_proto->pr_flags & PR_CONNREQUIRED)
1704: && error != EWOULDBLOCK) {
1705: slp->ns_flag |= SLP_DISCONN;
1706: goto dorecs;
1707: }
1708: }
1709: } while (mp);
1710: }
1711:
1712: /*
1713: * Now try and process the request records, non-blocking.
1714: */
1715: dorecs:
1716: if (waitflag == M_DONTWAIT &&
1717: (slp->ns_rec || (slp->ns_flag & (SLP_NEEDQ | SLP_DISCONN))))
1718: nfsrv_wakenfsd(slp);
1719: }
1720:
1721: /*
1722: * Try and extract an RPC request from the mbuf data list received on a
1723: * stream socket. The "waitflag" argument indicates whether or not it
1724: * can sleep.
1725: */
1726: static int
1727: nfsrv_getstream(slp, waitflag)
1728: register struct nfssvc_sock *slp;
1729: int waitflag;
1730: {
1731: register struct mbuf *m, **mpp;
1732: register char *cp1, *cp2;
1733: register int len;
1734: struct mbuf *om, *m2, *recm = 0;
1735: u_long recmark;
1736:
1737: if (slp->ns_flag & SLP_GETSTREAM)
1738: panic("nfs getstream");
1739: slp->ns_flag |= SLP_GETSTREAM;
1740: for (;;) {
1741: if (slp->ns_reclen == 0) {
1742: if (slp->ns_cc < NFSX_UNSIGNED) {
1743: slp->ns_flag &= ~SLP_GETSTREAM;
1744: return (0);
1745: }
1746: m = slp->ns_raw;
1747: if (m->m_len >= NFSX_UNSIGNED) {
1748: bcopy(mtod(m, caddr_t), (caddr_t)&recmark, NFSX_UNSIGNED);
1749: m->m_data += NFSX_UNSIGNED;
1750: m->m_len -= NFSX_UNSIGNED;
1751: } else {
1752: cp1 = (caddr_t)&recmark;
1753: cp2 = mtod(m, caddr_t);
1754: while (cp1 < ((caddr_t)&recmark) + NFSX_UNSIGNED) {
1755: while (m->m_len == 0) {
1756: m = m->m_next;
1757: cp2 = mtod(m, caddr_t);
1758: }
1759: *cp1++ = *cp2++;
1760: m->m_data++;
1761: m->m_len--;
1762: }
1763: }
1764: slp->ns_cc -= NFSX_UNSIGNED;
1765: recmark = ntohl(recmark);
1766: slp->ns_reclen = recmark & ~0x80000000;
1767: if (recmark & 0x80000000)
1768: slp->ns_flag |= SLP_LASTFRAG;
1769: else
1770: slp->ns_flag &= ~SLP_LASTFRAG;
1771: if (slp->ns_reclen < NFS_MINPACKET || slp->ns_reclen > NFS_MAXPACKET) {
1772: slp->ns_flag &= ~SLP_GETSTREAM;
1773: return (EPERM);
1774: }
1775: }
1776:
1777: /*
1778: * Now get the record part.
1779: */
1780: if (slp->ns_cc == slp->ns_reclen) {
1781: recm = slp->ns_raw;
1782: slp->ns_raw = slp->ns_rawend = (struct mbuf *)0;
1783: slp->ns_cc = slp->ns_reclen = 0;
1784: } else if (slp->ns_cc > slp->ns_reclen) {
1785: len = 0;
1786: m = slp->ns_raw;
1787: om = (struct mbuf *)0;
1788: while (len < slp->ns_reclen) {
1789: if ((len + m->m_len) > slp->ns_reclen) {
1790: m2 = m_copym(m, 0, slp->ns_reclen - len,
1791: waitflag);
1792: if (m2) {
1793: if (om) {
1794: om->m_next = m2;
1795: recm = slp->ns_raw;
1796: } else
1797: recm = m2;
1798: m->m_data += slp->ns_reclen - len;
1799: m->m_len -= slp->ns_reclen - len;
1800: len = slp->ns_reclen;
1801: } else {
1802: slp->ns_flag &= ~SLP_GETSTREAM;
1803: return (EWOULDBLOCK);
1804: }
1805: } else if ((len + m->m_len) == slp->ns_reclen) {
1806: om = m;
1807: len += m->m_len;
1808: m = m->m_next;
1809: recm = slp->ns_raw;
1810: om->m_next = (struct mbuf *)0;
1811: } else {
1812: om = m;
1813: len += m->m_len;
1814: m = m->m_next;
1815: }
1816: }
1817: slp->ns_raw = m;
1818: slp->ns_cc -= len;
1819: slp->ns_reclen = 0;
1820: } else {
1821: slp->ns_flag &= ~SLP_GETSTREAM;
1822: return (0);
1823: }
1824:
1825: /*
1826: * Accumulate the fragments into a record.
1827: */
1828: mpp = &slp->ns_frag;
1829: while (*mpp)
1830: mpp = &((*mpp)->m_next);
1831: *mpp = recm;
1832: if (slp->ns_flag & SLP_LASTFRAG) {
1833: if (slp->ns_recend)
1834: slp->ns_recend->m_nextpkt = slp->ns_frag;
1835: else
1836: slp->ns_rec = slp->ns_frag;
1837: slp->ns_recend = slp->ns_frag;
1838: slp->ns_frag = (struct mbuf *)0;
1839: }
1840: }
1841: }
1842:
1843: /*
1844: * Parse an RPC header.
1845: */
1846: int
1847: nfsrv_dorec(slp, nfsd, ndp)
1848: register struct nfssvc_sock *slp;
1849: struct nfsd *nfsd;
1850: struct nfsrv_descript **ndp;
1851: {
1852: register struct mbuf *m;
1853: register struct mbuf *nam;
1854: register struct nfsrv_descript *nd;
1855: int error;
1856:
1857: *ndp = NULL;
1858: if ((slp->ns_flag & SLP_VALID) == 0 ||
1859: (m = slp->ns_rec) == (struct mbuf *)0)
1860: return (ENOBUFS);
1861: slp->ns_rec = m->m_nextpkt;
1862: if (slp->ns_rec)
1863: m->m_nextpkt = (struct mbuf *)0;
1864: else
1865: slp->ns_recend = (struct mbuf *)0;
1866: if (m->m_type == MT_SONAME) {
1867: nam = m;
1868: m = m->m_next;
1869: nam->m_next = NULL;
1870: } else
1871: nam = NULL;
1872: MALLOC_ZONE(nd, struct nfsrv_descript *,
1873: sizeof (struct nfsrv_descript), M_NFSRVDESC, M_WAITOK);
1874: nd->nd_md = nd->nd_mrep = m;
1875: nd->nd_nam2 = nam;
1876: nd->nd_dpos = mtod(m, caddr_t);
1877: error = nfs_getreq(nd, nfsd, TRUE);
1878: if (error) {
1879: m_freem(nam);
1880: _FREE_ZONE((caddr_t)nd, sizeof *nd, M_NFSRVDESC);
1881: return (error);
1882: }
1883: *ndp = nd;
1884: nfsd->nfsd_nd = nd;
1885: return (0);
1886: }
1887:
1888: /*
1889: * Parse an RPC request
1890: * - verify it
1891: * - fill in the cred struct.
1892: */
1893: int
1894: nfs_getreq(nd, nfsd, has_header)
1895: register struct nfsrv_descript *nd;
1896: struct nfsd *nfsd;
1897: int has_header;
1898: {
1899: register int len, i;
1900: register u_long *tl;
1901: register long t1;
1902: struct uio uio;
1903: struct iovec iov;
1904: caddr_t dpos, cp2, cp;
1905: u_long nfsvers, auth_type;
1906: uid_t nickuid;
1907: int error = 0, nqnfs = 0, ticklen;
1908: struct mbuf *mrep, *md;
1909: register struct nfsuid *nuidp;
1910: struct timeval tvin, tvout;
1911: #if 0 /* until encrypted keys are implemented */
1912: NFSKERBKEYSCHED_T keys; /* stores key schedule */
1913: #endif
1914:
1915: mrep = nd->nd_mrep;
1916: md = nd->nd_md;
1917: dpos = nd->nd_dpos;
1918: if (has_header) {
1919: nfsm_dissect(tl, u_long *, 10 * NFSX_UNSIGNED);
1920: nd->nd_retxid = fxdr_unsigned(u_long, *tl++);
1921: if (*tl++ != rpc_call) {
1922: m_freem(mrep);
1923: return (EBADRPC);
1924: }
1925: } else
1926: nfsm_dissect(tl, u_long *, 8 * NFSX_UNSIGNED);
1927: nd->nd_repstat = 0;
1928: nd->nd_flag = 0;
1929: if (*tl++ != rpc_vers) {
1930: nd->nd_repstat = ERPCMISMATCH;
1931: nd->nd_procnum = NFSPROC_NOOP;
1932: return (0);
1933: }
1934: if (*tl != nfs_prog) {
1935: if (*tl == nqnfs_prog)
1936: nqnfs++;
1937: else {
1938: nd->nd_repstat = EPROGUNAVAIL;
1939: nd->nd_procnum = NFSPROC_NOOP;
1940: return (0);
1941: }
1942: }
1943: tl++;
1944: nfsvers = fxdr_unsigned(u_long, *tl++);
1945: if (((nfsvers < NFS_VER2 || nfsvers > NFS_VER3) && !nqnfs) ||
1946: (nfsvers != NQNFS_VER3 && nqnfs)) {
1947: nd->nd_repstat = EPROGMISMATCH;
1948: nd->nd_procnum = NFSPROC_NOOP;
1949: return (0);
1950: }
1951: if (nqnfs)
1952: nd->nd_flag = (ND_NFSV3 | ND_NQNFS);
1953: else if (nfsvers == NFS_VER3)
1954: nd->nd_flag = ND_NFSV3;
1955: nd->nd_procnum = fxdr_unsigned(u_long, *tl++);
1956: if (nd->nd_procnum == NFSPROC_NULL)
1957: return (0);
1958: if (nd->nd_procnum >= NFS_NPROCS ||
1959: (!nqnfs && nd->nd_procnum >= NQNFSPROC_GETLEASE) ||
1960: (!nd->nd_flag && nd->nd_procnum > NFSV2PROC_STATFS)) {
1961: nd->nd_repstat = EPROCUNAVAIL;
1962: nd->nd_procnum = NFSPROC_NOOP;
1963: return (0);
1964: }
1965: if ((nd->nd_flag & ND_NFSV3) == 0)
1966: nd->nd_procnum = nfsv3_procid[nd->nd_procnum];
1967: auth_type = *tl++;
1968: len = fxdr_unsigned(int, *tl++);
1969: if (len < 0 || len > RPCAUTH_MAXSIZ) {
1970: m_freem(mrep);
1971: return (EBADRPC);
1972: }
1973:
1974: nd->nd_flag &= ~ND_KERBAUTH;
1975: /*
1976: * Handle auth_unix or auth_kerb.
1977: */
1978: if (auth_type == rpc_auth_unix) {
1979: len = fxdr_unsigned(int, *++tl);
1980: if (len < 0 || len > NFS_MAXNAMLEN) {
1981: m_freem(mrep);
1982: return (EBADRPC);
1983: }
1984: nfsm_adv(nfsm_rndup(len));
1985: nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
1986: bzero((caddr_t)&nd->nd_cr, sizeof (struct ucred));
1987: nd->nd_cr.cr_ref = 1;
1988: nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
1989: nd->nd_cr.cr_gid = fxdr_unsigned(gid_t, *tl++);
1990: len = fxdr_unsigned(int, *tl);
1991: if (len < 0 || len > RPCAUTH_UNIXGIDS) {
1992: m_freem(mrep);
1993: return (EBADRPC);
1994: }
1995: nfsm_dissect(tl, u_long *, (len + 2) * NFSX_UNSIGNED);
1996: for (i = 1; i <= len; i++)
1997: if (i < NGROUPS)
1998: nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
1999: else
2000: tl++;
2001: nd->nd_cr.cr_ngroups = (len >= NGROUPS) ? NGROUPS : (len + 1);
2002: if (nd->nd_cr.cr_ngroups > 1)
2003: nfsrvw_sort(nd->nd_cr.cr_groups, nd->nd_cr.cr_ngroups);
2004: len = fxdr_unsigned(int, *++tl);
2005: if (len < 0 || len > RPCAUTH_MAXSIZ) {
2006: m_freem(mrep);
2007: return (EBADRPC);
2008: }
2009: if (len > 0)
2010: nfsm_adv(nfsm_rndup(len));
2011: } else if (auth_type == rpc_auth_kerb) {
2012: switch (fxdr_unsigned(int, *tl++)) {
2013: case RPCAKN_FULLNAME:
2014: ticklen = fxdr_unsigned(int, *tl);
2015: *((u_long *)nfsd->nfsd_authstr) = *tl;
2016: uio.uio_resid = nfsm_rndup(ticklen) + NFSX_UNSIGNED;
2017: nfsd->nfsd_authlen = uio.uio_resid + NFSX_UNSIGNED;
2018: if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
2019: m_freem(mrep);
2020: return (EBADRPC);
2021: }
2022: uio.uio_offset = 0;
2023: uio.uio_iov = &iov;
2024: uio.uio_iovcnt = 1;
2025: uio.uio_segflg = UIO_SYSSPACE;
2026: iov.iov_base = (caddr_t)&nfsd->nfsd_authstr[4];
2027: iov.iov_len = RPCAUTH_MAXSIZ - 4;
2028: nfsm_mtouio(&uio, uio.uio_resid);
2029: nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
2030: if (*tl++ != rpc_auth_kerb ||
2031: fxdr_unsigned(int, *tl) != 4 * NFSX_UNSIGNED) {
2032: printf("Bad kerb verifier\n");
2033: nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
2034: nd->nd_procnum = NFSPROC_NOOP;
2035: return (0);
2036: }
2037: nfsm_dissect(cp, caddr_t, 4 * NFSX_UNSIGNED);
2038: tl = (u_long *)cp;
2039: if (fxdr_unsigned(int, *tl) != RPCAKN_FULLNAME) {
2040: printf("Not fullname kerb verifier\n");
2041: nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
2042: nd->nd_procnum = NFSPROC_NOOP;
2043: return (0);
2044: }
2045: cp += NFSX_UNSIGNED;
2046: bcopy(cp, nfsd->nfsd_verfstr, 3 * NFSX_UNSIGNED);
2047: nfsd->nfsd_verflen = 3 * NFSX_UNSIGNED;
2048: nd->nd_flag |= ND_KERBFULL;
2049: nfsd->nfsd_flag |= NFSD_NEEDAUTH;
2050: break;
2051: case RPCAKN_NICKNAME:
2052: if (len != 2 * NFSX_UNSIGNED) {
2053: printf("Kerb nickname short\n");
2054: nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADCRED);
2055: nd->nd_procnum = NFSPROC_NOOP;
2056: return (0);
2057: }
2058: nickuid = fxdr_unsigned(uid_t, *tl);
2059: nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
2060: if (*tl++ != rpc_auth_kerb ||
2061: fxdr_unsigned(int, *tl) != 3 * NFSX_UNSIGNED) {
2062: printf("Kerb nick verifier bad\n");
2063: nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
2064: nd->nd_procnum = NFSPROC_NOOP;
2065: return (0);
2066: }
2067: nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2068: tvin.tv_sec = *tl++;
2069: tvin.tv_usec = *tl;
2070:
2071: for (nuidp = NUIDHASH(nfsd->nfsd_slp,nickuid)->lh_first;
2072: nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
2073: if (nuidp->nu_cr.cr_uid == nickuid &&
2074: (!nd->nd_nam2 ||
2075: netaddr_match(NU_NETFAM(nuidp),
2076: &nuidp->nu_haddr, nd->nd_nam2)))
2077: break;
2078: }
2079: if (!nuidp) {
2080: nd->nd_repstat =
2081: (NFSERR_AUTHERR|AUTH_REJECTCRED);
2082: nd->nd_procnum = NFSPROC_NOOP;
2083: return (0);
2084: }
2085:
2086: /*
2087: * Now, decrypt the timestamp using the session key
2088: * and validate it.
2089: */
2090: #if NFSKERB
2091: XXX
2092: #endif
2093:
2094: tvout.tv_sec = fxdr_unsigned(long, tvout.tv_sec);
2095: tvout.tv_usec = fxdr_unsigned(long, tvout.tv_usec);
2096: if (nuidp->nu_expire < time.tv_sec ||
2097: nuidp->nu_timestamp.tv_sec > tvout.tv_sec ||
2098: (nuidp->nu_timestamp.tv_sec == tvout.tv_sec &&
2099: nuidp->nu_timestamp.tv_usec > tvout.tv_usec)) {
2100: nuidp->nu_expire = 0;
2101: nd->nd_repstat =
2102: (NFSERR_AUTHERR|AUTH_REJECTVERF);
2103: nd->nd_procnum = NFSPROC_NOOP;
2104: return (0);
2105: }
2106: nfsrv_setcred(&nuidp->nu_cr, &nd->nd_cr);
2107: nd->nd_flag |= ND_KERBNICK;
2108: };
2109: } else {
2110: nd->nd_repstat = (NFSERR_AUTHERR | AUTH_REJECTCRED);
2111: nd->nd_procnum = NFSPROC_NOOP;
2112: return (0);
2113: }
2114:
2115: /*
2116: * For nqnfs, get piggybacked lease request.
2117: */
2118: if (nqnfs && nd->nd_procnum != NQNFSPROC_EVICTED) {
2119: nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2120: nd->nd_flag |= fxdr_unsigned(int, *tl);
2121: if (nd->nd_flag & ND_LEASE) {
2122: nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2123: nd->nd_duration = fxdr_unsigned(int, *tl);
2124: } else
2125: nd->nd_duration = NQ_MINLEASE;
2126: } else
2127: nd->nd_duration = NQ_MINLEASE;
2128: nd->nd_md = md;
2129: nd->nd_dpos = dpos;
2130: return (0);
2131: nfsmout:
2132: return (error);
2133: }
2134:
2135: /*
2136: * Search for a sleeping nfsd and wake it up.
2137: * SIDE EFFECT: If none found, set NFSD_CHECKSLP flag, so that one of the
2138: * running nfsds will go look for the work in the nfssvc_sock list.
2139: */
2140: void
2141: nfsrv_wakenfsd(slp)
2142: struct nfssvc_sock *slp;
2143: {
2144: register struct nfsd *nd;
2145:
2146: if ((slp->ns_flag & SLP_VALID) == 0)
2147: return;
2148: for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nfsd_chain.tqe_next) {
2149: if (nd->nfsd_flag & NFSD_WAITING) {
2150: nd->nfsd_flag &= ~NFSD_WAITING;
2151: if (nd->nfsd_slp)
2152: panic("nfsd wakeup");
2153: slp->ns_sref++;
2154: nd->nfsd_slp = slp;
2155: wakeup((caddr_t)nd);
2156: return;
2157: }
2158: }
2159: slp->ns_flag |= SLP_DOREC;
2160: nfsd_head_flag |= NFSD_CHECKSLP;
2161: }
2162: #endif /* NFS_NOSERVER */
2163:
2164: static int
2165: nfs_msg(p, server, msg)
2166: struct proc *p;
2167: char *server, *msg;
2168: {
2169: tpr_t tpr;
2170:
2171: if (p)
2172: tpr = tprintf_open(p);
2173: else
2174: tpr = NULL;
2175: tprintf(tpr, "nfs server %s: %s\n", server, msg);
2176: tprintf_close(tpr);
2177: return (0);
2178: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.