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