Deleted Added
full compact
nfs_srvsubs.c (9456) nfs_srvsubs.c (9507)
1/*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)nfs_subs.c 8.3 (Berkeley) 1/4/94
1/*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)nfs_subs.c 8.3 (Berkeley) 1/4/94
37 * $Id: nfs_subs.c,v 1.18 1995/06/28 12:01:05 davidg Exp $
37 * $Id: nfs_subs.c,v 1.19 1995/07/09 06:57:59 davidg Exp $
38 */
39
40/*
41 * These functions support the macros and help fiddle mbuf chains for
42 * the nfs op functions. They do things like create the rpc header and
43 * copy data between mbuf chains and uio lists.
44 */
45#include <sys/param.h>
46#include <sys/proc.h>
47#include <sys/systm.h>
48#include <sys/kernel.h>
49#include <sys/mount.h>
50#include <sys/vnode.h>
51#include <sys/namei.h>
52#include <sys/mbuf.h>
53#include <sys/socket.h>
54#include <sys/stat.h>
55#include <sys/malloc.h>
56#ifdef VFS_LKM
57#include <sys/sysent.h>
58#include <sys/syscall.h>
59#endif
60
61#include <vm/vm.h>
38 */
39
40/*
41 * These functions support the macros and help fiddle mbuf chains for
42 * the nfs op functions. They do things like create the rpc header and
43 * copy data between mbuf chains and uio lists.
44 */
45#include <sys/param.h>
46#include <sys/proc.h>
47#include <sys/systm.h>
48#include <sys/kernel.h>
49#include <sys/mount.h>
50#include <sys/vnode.h>
51#include <sys/namei.h>
52#include <sys/mbuf.h>
53#include <sys/socket.h>
54#include <sys/stat.h>
55#include <sys/malloc.h>
56#ifdef VFS_LKM
57#include <sys/sysent.h>
58#include <sys/syscall.h>
59#endif
60
61#include <vm/vm.h>
62#include <vm/vnode_pager.h>
62
63#include <nfs/rpcv2.h>
64#include <nfs/nfsproto.h>
65#include <nfs/nfsnode.h>
66#include <nfs/nfs.h>
67#include <nfs/xdr_subs.h>
68#include <nfs/nfsm_subs.h>
69#include <nfs/nfsmount.h>
70#include <nfs/nqnfs.h>
71#include <nfs/nfsrtt.h>
72
73#include <miscfs/specfs/specdev.h>
74
63
64#include <nfs/rpcv2.h>
65#include <nfs/nfsproto.h>
66#include <nfs/nfsnode.h>
67#include <nfs/nfs.h>
68#include <nfs/xdr_subs.h>
69#include <nfs/nfsm_subs.h>
70#include <nfs/nfsmount.h>
71#include <nfs/nqnfs.h>
72#include <nfs/nfsrtt.h>
73
74#include <miscfs/specfs/specdev.h>
75
75#include <vm/vnode_pager.h>
76
77#include <netinet/in.h>
78#ifdef ISO
79#include <netiso/iso.h>
80#endif
81
82/*
83 * Data items converted to xdr at startup, since they are constant
84 * This is kinda hokey, but may save a little time doing byte swaps
85 */
86u_long nfs_xdrneg1;
87u_long rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
88 rpc_mismatch, rpc_auth_unix, rpc_msgaccepted,
89 rpc_auth_kerb;
90u_long nfs_prog, nqnfs_prog, nfs_true, nfs_false;
91
92/* And other global data */
93static u_long nfs_xid = 0;
94enum vtype nv2tov_type[8] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON };
95enum vtype nv3tov_type[8]={ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO };
96int nfs_ticks;
97
98/*
99 * Mapping of old NFS Version 2 RPC numbers to generic numbers.
100 */
101int nfsv3_procid[NFS_NPROCS] = {
102 NFSPROC_NULL,
103 NFSPROC_GETATTR,
104 NFSPROC_SETATTR,
105 NFSPROC_NOOP,
106 NFSPROC_LOOKUP,
107 NFSPROC_READLINK,
108 NFSPROC_READ,
109 NFSPROC_NOOP,
110 NFSPROC_WRITE,
111 NFSPROC_CREATE,
112 NFSPROC_REMOVE,
113 NFSPROC_RENAME,
114 NFSPROC_LINK,
115 NFSPROC_SYMLINK,
116 NFSPROC_MKDIR,
117 NFSPROC_RMDIR,
118 NFSPROC_READDIR,
119 NFSPROC_FSSTAT,
120 NFSPROC_NOOP,
121 NFSPROC_NOOP,
122 NFSPROC_NOOP,
123 NFSPROC_NOOP,
124 NFSPROC_NOOP,
125 NFSPROC_NOOP,
126 NFSPROC_NOOP,
127 NFSPROC_NOOP
128};
129
130/*
131 * and the reverse mapping from generic to Version 2 procedure numbers
132 */
133int nfsv2_procid[NFS_NPROCS] = {
134 NFSV2PROC_NULL,
135 NFSV2PROC_GETATTR,
136 NFSV2PROC_SETATTR,
137 NFSV2PROC_LOOKUP,
138 NFSV2PROC_NOOP,
139 NFSV2PROC_READLINK,
140 NFSV2PROC_READ,
141 NFSV2PROC_WRITE,
142 NFSV2PROC_CREATE,
143 NFSV2PROC_MKDIR,
144 NFSV2PROC_SYMLINK,
145 NFSV2PROC_CREATE,
146 NFSV2PROC_REMOVE,
147 NFSV2PROC_RMDIR,
148 NFSV2PROC_RENAME,
149 NFSV2PROC_LINK,
150 NFSV2PROC_READDIR,
151 NFSV2PROC_NOOP,
152 NFSV2PROC_STATFS,
153 NFSV2PROC_NOOP,
154 NFSV2PROC_NOOP,
155 NFSV2PROC_NOOP,
156 NFSV2PROC_NOOP,
157 NFSV2PROC_NOOP,
158 NFSV2PROC_NOOP,
159 NFSV2PROC_NOOP,
160};
161
162/*
163 * Maps errno values to nfs error numbers.
164 * Use NFSERR_IO as the catch all for ones not specifically defined in
165 * RFC 1094.
166 */
167static u_char nfsrv_v2errmap[ELAST] = {
168 NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO,
169 NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
170 NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO,
171 NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR,
172 NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
173 NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS,
174 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
175 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
176 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
177 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
178 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
179 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
180 NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO,
181 NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE,
182 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
183 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
184 NFSERR_IO,
185};
186
187/*
188 * Maps errno values to nfs error numbers.
189 * Although it is not obvious whether or not NFS clients really care if
190 * a returned error value is in the specified list for the procedure, the
191 * safest thing to do is filter them appropriately. For Version 2, the
192 * X/Open XNFS document is the only specification that defines error values
193 * for each RPC (The RFC simply lists all possible error values for all RPCs),
194 * so I have decided to not do this for Version 2.
195 * The first entry is the default error return and the rest are the valid
196 * errors for that RPC in increasing numeric order.
197 */
198static short nfsv3err_null[] = {
199 0,
200 0,
201};
202
203static short nfsv3err_getattr[] = {
204 NFSERR_IO,
205 NFSERR_IO,
206 NFSERR_STALE,
207 NFSERR_BADHANDLE,
208 NFSERR_SERVERFAULT,
209 0,
210};
211
212static short nfsv3err_setattr[] = {
213 NFSERR_IO,
214 NFSERR_PERM,
215 NFSERR_IO,
216 NFSERR_ACCES,
217 NFSERR_INVAL,
218 NFSERR_NOSPC,
219 NFSERR_ROFS,
220 NFSERR_DQUOT,
221 NFSERR_STALE,
222 NFSERR_BADHANDLE,
223 NFSERR_NOT_SYNC,
224 NFSERR_SERVERFAULT,
225 0,
226};
227
228static short nfsv3err_lookup[] = {
229 NFSERR_IO,
230 NFSERR_NOENT,
231 NFSERR_IO,
232 NFSERR_ACCES,
233 NFSERR_NOTDIR,
234 NFSERR_NAMETOL,
235 NFSERR_STALE,
236 NFSERR_BADHANDLE,
237 NFSERR_SERVERFAULT,
238 0,
239};
240
241static short nfsv3err_access[] = {
242 NFSERR_IO,
243 NFSERR_IO,
244 NFSERR_STALE,
245 NFSERR_BADHANDLE,
246 NFSERR_SERVERFAULT,
247 0,
248};
249
250static short nfsv3err_readlink[] = {
251 NFSERR_IO,
252 NFSERR_IO,
253 NFSERR_ACCES,
254 NFSERR_INVAL,
255 NFSERR_STALE,
256 NFSERR_BADHANDLE,
257 NFSERR_NOTSUPP,
258 NFSERR_SERVERFAULT,
259 0,
260};
261
262static short nfsv3err_read[] = {
263 NFSERR_IO,
264 NFSERR_IO,
265 NFSERR_NXIO,
266 NFSERR_ACCES,
267 NFSERR_INVAL,
268 NFSERR_STALE,
269 NFSERR_BADHANDLE,
270 NFSERR_SERVERFAULT,
271 0,
272};
273
274static short nfsv3err_write[] = {
275 NFSERR_IO,
276 NFSERR_IO,
277 NFSERR_ACCES,
278 NFSERR_INVAL,
279 NFSERR_FBIG,
280 NFSERR_NOSPC,
281 NFSERR_ROFS,
282 NFSERR_DQUOT,
283 NFSERR_STALE,
284 NFSERR_BADHANDLE,
285 NFSERR_SERVERFAULT,
286 0,
287};
288
289static short nfsv3err_create[] = {
290 NFSERR_IO,
291 NFSERR_IO,
292 NFSERR_ACCES,
293 NFSERR_EXIST,
294 NFSERR_NOTDIR,
295 NFSERR_NOSPC,
296 NFSERR_ROFS,
297 NFSERR_NAMETOL,
298 NFSERR_DQUOT,
299 NFSERR_STALE,
300 NFSERR_BADHANDLE,
301 NFSERR_NOTSUPP,
302 NFSERR_SERVERFAULT,
303 0,
304};
305
306static short nfsv3err_mkdir[] = {
307 NFSERR_IO,
308 NFSERR_IO,
309 NFSERR_ACCES,
310 NFSERR_EXIST,
311 NFSERR_NOTDIR,
312 NFSERR_NOSPC,
313 NFSERR_ROFS,
314 NFSERR_NAMETOL,
315 NFSERR_DQUOT,
316 NFSERR_STALE,
317 NFSERR_BADHANDLE,
318 NFSERR_NOTSUPP,
319 NFSERR_SERVERFAULT,
320 0,
321};
322
323static short nfsv3err_symlink[] = {
324 NFSERR_IO,
325 NFSERR_IO,
326 NFSERR_ACCES,
327 NFSERR_EXIST,
328 NFSERR_NOTDIR,
329 NFSERR_NOSPC,
330 NFSERR_ROFS,
331 NFSERR_NAMETOL,
332 NFSERR_DQUOT,
333 NFSERR_STALE,
334 NFSERR_BADHANDLE,
335 NFSERR_NOTSUPP,
336 NFSERR_SERVERFAULT,
337 0,
338};
339
340static short nfsv3err_mknod[] = {
341 NFSERR_IO,
342 NFSERR_IO,
343 NFSERR_ACCES,
344 NFSERR_EXIST,
345 NFSERR_NOTDIR,
346 NFSERR_NOSPC,
347 NFSERR_ROFS,
348 NFSERR_NAMETOL,
349 NFSERR_DQUOT,
350 NFSERR_STALE,
351 NFSERR_BADHANDLE,
352 NFSERR_NOTSUPP,
353 NFSERR_SERVERFAULT,
354 NFSERR_BADTYPE,
355 0,
356};
357
358static short nfsv3err_remove[] = {
359 NFSERR_IO,
360 NFSERR_NOENT,
361 NFSERR_IO,
362 NFSERR_ACCES,
363 NFSERR_NOTDIR,
364 NFSERR_ROFS,
365 NFSERR_NAMETOL,
366 NFSERR_STALE,
367 NFSERR_BADHANDLE,
368 NFSERR_SERVERFAULT,
369 0,
370};
371
372static short nfsv3err_rmdir[] = {
373 NFSERR_IO,
374 NFSERR_NOENT,
375 NFSERR_IO,
376 NFSERR_ACCES,
377 NFSERR_EXIST,
378 NFSERR_NOTDIR,
379 NFSERR_INVAL,
380 NFSERR_ROFS,
381 NFSERR_NAMETOL,
382 NFSERR_NOTEMPTY,
383 NFSERR_STALE,
384 NFSERR_BADHANDLE,
385 NFSERR_NOTSUPP,
386 NFSERR_SERVERFAULT,
387 0,
388};
389
390static short nfsv3err_rename[] = {
391 NFSERR_IO,
392 NFSERR_NOENT,
393 NFSERR_IO,
394 NFSERR_ACCES,
395 NFSERR_EXIST,
396 NFSERR_XDEV,
397 NFSERR_NOTDIR,
398 NFSERR_ISDIR,
399 NFSERR_INVAL,
400 NFSERR_NOSPC,
401 NFSERR_ROFS,
402 NFSERR_MLINK,
403 NFSERR_NAMETOL,
404 NFSERR_NOTEMPTY,
405 NFSERR_DQUOT,
406 NFSERR_STALE,
407 NFSERR_BADHANDLE,
408 NFSERR_NOTSUPP,
409 NFSERR_SERVERFAULT,
410 0,
411};
412
413static short nfsv3err_link[] = {
414 NFSERR_IO,
415 NFSERR_IO,
416 NFSERR_ACCES,
417 NFSERR_EXIST,
418 NFSERR_XDEV,
419 NFSERR_NOTDIR,
420 NFSERR_INVAL,
421 NFSERR_NOSPC,
422 NFSERR_ROFS,
423 NFSERR_MLINK,
424 NFSERR_NAMETOL,
425 NFSERR_DQUOT,
426 NFSERR_STALE,
427 NFSERR_BADHANDLE,
428 NFSERR_NOTSUPP,
429 NFSERR_SERVERFAULT,
430 0,
431};
432
433static short nfsv3err_readdir[] = {
434 NFSERR_IO,
435 NFSERR_IO,
436 NFSERR_ACCES,
437 NFSERR_NOTDIR,
438 NFSERR_STALE,
439 NFSERR_BADHANDLE,
440 NFSERR_BAD_COOKIE,
441 NFSERR_TOOSMALL,
442 NFSERR_SERVERFAULT,
443 0,
444};
445
446static short nfsv3err_readdirplus[] = {
447 NFSERR_IO,
448 NFSERR_IO,
449 NFSERR_ACCES,
450 NFSERR_NOTDIR,
451 NFSERR_STALE,
452 NFSERR_BADHANDLE,
453 NFSERR_BAD_COOKIE,
454 NFSERR_NOTSUPP,
455 NFSERR_TOOSMALL,
456 NFSERR_SERVERFAULT,
457 0,
458};
459
460static short nfsv3err_fsstat[] = {
461 NFSERR_IO,
462 NFSERR_IO,
463 NFSERR_STALE,
464 NFSERR_BADHANDLE,
465 NFSERR_SERVERFAULT,
466 0,
467};
468
469static short nfsv3err_fsinfo[] = {
470 NFSERR_STALE,
471 NFSERR_STALE,
472 NFSERR_BADHANDLE,
473 NFSERR_SERVERFAULT,
474 0,
475};
476
477static short nfsv3err_pathconf[] = {
478 NFSERR_STALE,
479 NFSERR_STALE,
480 NFSERR_BADHANDLE,
481 NFSERR_SERVERFAULT,
482 0,
483};
484
485static short nfsv3err_commit[] = {
486 NFSERR_IO,
487 NFSERR_IO,
488 NFSERR_STALE,
489 NFSERR_BADHANDLE,
490 NFSERR_SERVERFAULT,
491 0,
492};
493
494static short *nfsrv_v3errmap[] = {
495 nfsv3err_null,
496 nfsv3err_getattr,
497 nfsv3err_setattr,
498 nfsv3err_lookup,
499 nfsv3err_access,
500 nfsv3err_readlink,
501 nfsv3err_read,
502 nfsv3err_write,
503 nfsv3err_create,
504 nfsv3err_mkdir,
505 nfsv3err_symlink,
506 nfsv3err_mknod,
507 nfsv3err_remove,
508 nfsv3err_rmdir,
509 nfsv3err_rename,
510 nfsv3err_link,
511 nfsv3err_readdir,
512 nfsv3err_readdirplus,
513 nfsv3err_fsstat,
514 nfsv3err_fsinfo,
515 nfsv3err_pathconf,
516 nfsv3err_commit,
517};
518
519extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
520extern struct nfsrtt nfsrtt;
521extern time_t nqnfsstarttime;
522extern int nqsrv_clockskew;
523extern int nqsrv_writeslack;
524extern int nqsrv_maxlease;
525extern struct nfsstats nfsstats;
526extern int nqnfs_piggy[NFS_NPROCS];
527extern nfstype nfsv2_type[9];
528extern nfstype nfsv3_type[9];
529extern struct nfsnodehashhead *nfsnodehashtbl;
530extern u_long nfsnodehash;
531
532#ifdef VFS_LKM
533struct getfh_args;
534extern int getfh(struct proc *, struct getfh_args *, int *);
535struct nfssvc_args;
536extern int nfssvc(struct proc *, struct nfssvc_args *, int *);
537#endif
538
539LIST_HEAD(nfsnodehashhead, nfsnode);
540
541/*
542 * Create the header for an rpc request packet
543 * The hsiz is the size of the rest of the nfs request header.
544 * (just used to decide if a cluster is a good idea)
545 */
546struct mbuf *
547nfsm_reqh(vp, procid, hsiz, bposp)
548 struct vnode *vp;
549 u_long procid;
550 int hsiz;
551 caddr_t *bposp;
552{
553 register struct mbuf *mb;
554 register u_long *tl;
555 register caddr_t bpos;
556 struct mbuf *mb2;
557 struct nfsmount *nmp;
558 int nqflag;
559
560 MGET(mb, M_WAIT, MT_DATA);
561 if (hsiz >= MINCLSIZE)
562 MCLGET(mb, M_WAIT);
563 mb->m_len = 0;
564 bpos = mtod(mb, caddr_t);
565
566 /*
567 * For NQNFS, add lease request.
568 */
569 if (vp) {
570 nmp = VFSTONFS(vp->v_mount);
571 if (nmp->nm_flag & NFSMNT_NQNFS) {
572 nqflag = NQNFS_NEEDLEASE(vp, procid);
573 if (nqflag) {
574 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
575 *tl++ = txdr_unsigned(nqflag);
576 *tl = txdr_unsigned(nmp->nm_leaseterm);
577 } else {
578 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
579 *tl = 0;
580 }
581 }
582 }
583 /* Finally, return values */
584 *bposp = bpos;
585 return (mb);
586}
587
588/*
589 * Build the RPC header and fill in the authorization info.
590 * The authorization string argument is only used when the credentials
591 * come from outside of the kernel.
592 * Returns the head of the mbuf list.
593 */
594struct mbuf *
595nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
596 verf_str, mrest, mrest_len, mbp, xidp)
597 register struct ucred *cr;
598 int nmflag;
599 int procid;
600 int auth_type;
601 int auth_len;
602 char *auth_str;
603 int verf_len;
604 char *verf_str;
605 struct mbuf *mrest;
606 int mrest_len;
607 struct mbuf **mbp;
608 u_long *xidp;
609{
610 register struct mbuf *mb;
611 register u_long *tl;
612 register caddr_t bpos;
613 register int i;
614 struct mbuf *mreq, *mb2;
615 int siz, grpsiz, authsiz;
616
617 authsiz = nfsm_rndup(auth_len);
618 MGETHDR(mb, M_WAIT, MT_DATA);
619 if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) {
620 MCLGET(mb, M_WAIT);
621 } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) {
622 MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
623 } else {
624 MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
625 }
626 mb->m_len = 0;
627 mreq = mb;
628 bpos = mtod(mb, caddr_t);
629
630 /*
631 * First the RPC header.
632 */
633 nfsm_build(tl, u_long *, 8 * NFSX_UNSIGNED);
634 if (++nfs_xid == 0)
635 nfs_xid++;
636 *tl++ = *xidp = txdr_unsigned(nfs_xid);
637 *tl++ = rpc_call;
638 *tl++ = rpc_vers;
639 if (nmflag & NFSMNT_NQNFS) {
640 *tl++ = txdr_unsigned(NQNFS_PROG);
641 *tl++ = txdr_unsigned(NQNFS_VER3);
642 } else {
643 *tl++ = txdr_unsigned(NFS_PROG);
644 if (nmflag & NFSMNT_NFSV3)
645 *tl++ = txdr_unsigned(NFS_VER3);
646 else
647 *tl++ = txdr_unsigned(NFS_VER2);
648 }
649 if (nmflag & NFSMNT_NFSV3)
650 *tl++ = txdr_unsigned(procid);
651 else
652 *tl++ = txdr_unsigned(nfsv2_procid[procid]);
653
654 /*
655 * And then the authorization cred.
656 */
657 *tl++ = txdr_unsigned(auth_type);
658 *tl = txdr_unsigned(authsiz);
659 switch (auth_type) {
660 case RPCAUTH_UNIX:
661 nfsm_build(tl, u_long *, auth_len);
662 *tl++ = 0; /* stamp ?? */
663 *tl++ = 0; /* NULL hostname */
664 *tl++ = txdr_unsigned(cr->cr_uid);
665 *tl++ = txdr_unsigned(cr->cr_groups[0]);
666 grpsiz = (auth_len >> 2) - 5;
667 *tl++ = txdr_unsigned(grpsiz);
668 for (i = 1; i <= grpsiz; i++)
669 *tl++ = txdr_unsigned(cr->cr_groups[i]);
670 break;
671 case RPCAUTH_KERB4:
672 siz = auth_len;
673 while (siz > 0) {
674 if (M_TRAILINGSPACE(mb) == 0) {
675 MGET(mb2, M_WAIT, MT_DATA);
676 if (siz >= MINCLSIZE)
677 MCLGET(mb2, M_WAIT);
678 mb->m_next = mb2;
679 mb = mb2;
680 mb->m_len = 0;
681 bpos = mtod(mb, caddr_t);
682 }
683 i = min(siz, M_TRAILINGSPACE(mb));
684 bcopy(auth_str, bpos, i);
685 mb->m_len += i;
686 auth_str += i;
687 bpos += i;
688 siz -= i;
689 }
690 if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) {
691 for (i = 0; i < siz; i++)
692 *bpos++ = '\0';
693 mb->m_len += siz;
694 }
695 break;
696 };
697
698 /*
699 * And the verifier...
700 */
701 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
702 if (verf_str) {
703 *tl++ = txdr_unsigned(RPCAUTH_KERB4);
704 *tl = txdr_unsigned(verf_len);
705 siz = verf_len;
706 while (siz > 0) {
707 if (M_TRAILINGSPACE(mb) == 0) {
708 MGET(mb2, M_WAIT, MT_DATA);
709 if (siz >= MINCLSIZE)
710 MCLGET(mb2, M_WAIT);
711 mb->m_next = mb2;
712 mb = mb2;
713 mb->m_len = 0;
714 bpos = mtod(mb, caddr_t);
715 }
716 i = min(siz, M_TRAILINGSPACE(mb));
717 bcopy(verf_str, bpos, i);
718 mb->m_len += i;
719 verf_str += i;
720 bpos += i;
721 siz -= i;
722 }
723 if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) {
724 for (i = 0; i < siz; i++)
725 *bpos++ = '\0';
726 mb->m_len += siz;
727 }
728 } else {
729 *tl++ = txdr_unsigned(RPCAUTH_NULL);
730 *tl = 0;
731 }
732 mb->m_next = mrest;
733 mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
734 mreq->m_pkthdr.rcvif = (struct ifnet *)0;
735 *mbp = mb;
736 return (mreq);
737}
738
739/*
740 * copies mbuf chain to the uio scatter/gather list
741 */
742int
743nfsm_mbuftouio(mrep, uiop, siz, dpos)
744 struct mbuf **mrep;
745 register struct uio *uiop;
746 int siz;
747 caddr_t *dpos;
748{
749 register char *mbufcp, *uiocp;
750 register int xfer, left, len;
751 register struct mbuf *mp;
752 long uiosiz, rem;
753 int error = 0;
754
755 mp = *mrep;
756 mbufcp = *dpos;
757 len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
758 rem = nfsm_rndup(siz)-siz;
759 while (siz > 0) {
760 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
761 return (EFBIG);
762 left = uiop->uio_iov->iov_len;
763 uiocp = uiop->uio_iov->iov_base;
764 if (left > siz)
765 left = siz;
766 uiosiz = left;
767 while (left > 0) {
768 while (len == 0) {
769 mp = mp->m_next;
770 if (mp == NULL)
771 return (EBADRPC);
772 mbufcp = mtod(mp, caddr_t);
773 len = mp->m_len;
774 }
775 xfer = (left > len) ? len : left;
776#ifdef notdef
777 /* Not Yet.. */
778 if (uiop->uio_iov->iov_op != NULL)
779 (*(uiop->uio_iov->iov_op))
780 (mbufcp, uiocp, xfer);
781 else
782#endif
783 if (uiop->uio_segflg == UIO_SYSSPACE)
784 bcopy(mbufcp, uiocp, xfer);
785 else
786 copyout(mbufcp, uiocp, xfer);
787 left -= xfer;
788 len -= xfer;
789 mbufcp += xfer;
790 uiocp += xfer;
791 uiop->uio_offset += xfer;
792 uiop->uio_resid -= xfer;
793 }
794 if (uiop->uio_iov->iov_len <= siz) {
795 uiop->uio_iovcnt--;
796 uiop->uio_iov++;
797 } else {
798 uiop->uio_iov->iov_base += uiosiz;
799 uiop->uio_iov->iov_len -= uiosiz;
800 }
801 siz -= uiosiz;
802 }
803 *dpos = mbufcp;
804 *mrep = mp;
805 if (rem > 0) {
806 if (len < rem)
807 error = nfs_adv(mrep, dpos, rem, len);
808 else
809 *dpos += rem;
810 }
811 return (error);
812}
813
814/*
815 * copies a uio scatter/gather list to an mbuf chain...
816 */
817int
818nfsm_uiotombuf(uiop, mq, siz, bpos)
819 register struct uio *uiop;
820 struct mbuf **mq;
821 int siz;
822 caddr_t *bpos;
823{
824 register char *uiocp;
825 register struct mbuf *mp, *mp2;
826 register int xfer, left, mlen;
827 int uiosiz, clflg, rem;
828 char *cp;
829
830 if (siz > MLEN) /* or should it >= MCLBYTES ?? */
831 clflg = 1;
832 else
833 clflg = 0;
834 rem = nfsm_rndup(siz)-siz;
835 mp = mp2 = *mq;
836 while (siz > 0) {
837 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
838 return (EINVAL);
839 left = uiop->uio_iov->iov_len;
840 uiocp = uiop->uio_iov->iov_base;
841 if (left > siz)
842 left = siz;
843 uiosiz = left;
844 while (left > 0) {
845 mlen = M_TRAILINGSPACE(mp);
846 if (mlen == 0) {
847 MGET(mp, M_WAIT, MT_DATA);
848 if (clflg)
849 MCLGET(mp, M_WAIT);
850 mp->m_len = 0;
851 mp2->m_next = mp;
852 mp2 = mp;
853 mlen = M_TRAILINGSPACE(mp);
854 }
855 xfer = (left > mlen) ? mlen : left;
856#ifdef notdef
857 /* Not Yet.. */
858 if (uiop->uio_iov->iov_op != NULL)
859 (*(uiop->uio_iov->iov_op))
860 (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
861 else
862#endif
863 if (uiop->uio_segflg == UIO_SYSSPACE)
864 bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
865 else
866 copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
867 mp->m_len += xfer;
868 left -= xfer;
869 uiocp += xfer;
870 uiop->uio_offset += xfer;
871 uiop->uio_resid -= xfer;
872 }
873 if (uiop->uio_iov->iov_len <= siz) {
874 uiop->uio_iovcnt--;
875 uiop->uio_iov++;
876 } else {
877 uiop->uio_iov->iov_base += uiosiz;
878 uiop->uio_iov->iov_len -= uiosiz;
879 }
880 siz -= uiosiz;
881 }
882 if (rem > 0) {
883 if (rem > M_TRAILINGSPACE(mp)) {
884 MGET(mp, M_WAIT, MT_DATA);
885 mp->m_len = 0;
886 mp2->m_next = mp;
887 }
888 cp = mtod(mp, caddr_t)+mp->m_len;
889 for (left = 0; left < rem; left++)
890 *cp++ = '\0';
891 mp->m_len += rem;
892 *bpos = cp;
893 } else
894 *bpos = mtod(mp, caddr_t)+mp->m_len;
895 *mq = mp;
896 return (0);
897}
898
899/*
900 * Help break down an mbuf chain by setting the first siz bytes contiguous
901 * pointed to by returned val.
902 * This is used by the macros nfsm_dissect and nfsm_dissecton for tough
903 * cases. (The macros use the vars. dpos and dpos2)
904 */
905int
906nfsm_disct(mdp, dposp, siz, left, cp2)
907 struct mbuf **mdp;
908 caddr_t *dposp;
909 int siz;
910 int left;
911 caddr_t *cp2;
912{
913 register struct mbuf *mp, *mp2;
914 register int siz2, xfer;
915 register caddr_t p;
916
917 mp = *mdp;
918 while (left == 0) {
919 *mdp = mp = mp->m_next;
920 if (mp == NULL)
921 return (EBADRPC);
922 left = mp->m_len;
923 *dposp = mtod(mp, caddr_t);
924 }
925 if (left >= siz) {
926 *cp2 = *dposp;
927 *dposp += siz;
928 } else if (mp->m_next == NULL) {
929 return (EBADRPC);
930 } else if (siz > MHLEN) {
931 panic("nfs S too big");
932 } else {
933 MGET(mp2, M_WAIT, MT_DATA);
934 mp2->m_next = mp->m_next;
935 mp->m_next = mp2;
936 mp->m_len -= left;
937 mp = mp2;
938 *cp2 = p = mtod(mp, caddr_t);
939 bcopy(*dposp, p, left); /* Copy what was left */
940 siz2 = siz-left;
941 p += left;
942 mp2 = mp->m_next;
943 /* Loop around copying up the siz2 bytes */
944 while (siz2 > 0) {
945 if (mp2 == NULL)
946 return (EBADRPC);
947 xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
948 if (xfer > 0) {
949 bcopy(mtod(mp2, caddr_t), p, xfer);
950 NFSMADV(mp2, xfer);
951 mp2->m_len -= xfer;
952 p += xfer;
953 siz2 -= xfer;
954 }
955 if (siz2 > 0)
956 mp2 = mp2->m_next;
957 }
958 mp->m_len = siz;
959 *mdp = mp2;
960 *dposp = mtod(mp2, caddr_t);
961 }
962 return (0);
963}
964
965/*
966 * Advance the position in the mbuf chain.
967 */
968int
969nfs_adv(mdp, dposp, offs, left)
970 struct mbuf **mdp;
971 caddr_t *dposp;
972 int offs;
973 int left;
974{
975 register struct mbuf *m;
976 register int s;
977
978 m = *mdp;
979 s = left;
980 while (s < offs) {
981 offs -= s;
982 m = m->m_next;
983 if (m == NULL)
984 return (EBADRPC);
985 s = m->m_len;
986 }
987 *mdp = m;
988 *dposp = mtod(m, caddr_t)+offs;
989 return (0);
990}
991
992/*
993 * Copy a string into mbufs for the hard cases...
994 */
995int
996nfsm_strtmbuf(mb, bpos, cp, siz)
997 struct mbuf **mb;
998 char **bpos;
999 char *cp;
1000 long siz;
1001{
1002 register struct mbuf *m1 = 0, *m2;
1003 long left, xfer, len, tlen;
1004 u_long *tl;
1005 int putsize;
1006
1007 putsize = 1;
1008 m2 = *mb;
1009 left = M_TRAILINGSPACE(m2);
1010 if (left > 0) {
1011 tl = ((u_long *)(*bpos));
1012 *tl++ = txdr_unsigned(siz);
1013 putsize = 0;
1014 left -= NFSX_UNSIGNED;
1015 m2->m_len += NFSX_UNSIGNED;
1016 if (left > 0) {
1017 bcopy(cp, (caddr_t) tl, left);
1018 siz -= left;
1019 cp += left;
1020 m2->m_len += left;
1021 left = 0;
1022 }
1023 }
1024 /* Loop around adding mbufs */
1025 while (siz > 0) {
1026 MGET(m1, M_WAIT, MT_DATA);
1027 if (siz > MLEN)
1028 MCLGET(m1, M_WAIT);
1029 m1->m_len = NFSMSIZ(m1);
1030 m2->m_next = m1;
1031 m2 = m1;
1032 tl = mtod(m1, u_long *);
1033 tlen = 0;
1034 if (putsize) {
1035 *tl++ = txdr_unsigned(siz);
1036 m1->m_len -= NFSX_UNSIGNED;
1037 tlen = NFSX_UNSIGNED;
1038 putsize = 0;
1039 }
1040 if (siz < m1->m_len) {
1041 len = nfsm_rndup(siz);
1042 xfer = siz;
1043 if (xfer < len)
1044 *(tl+(xfer>>2)) = 0;
1045 } else {
1046 xfer = len = m1->m_len;
1047 }
1048 bcopy(cp, (caddr_t) tl, xfer);
1049 m1->m_len = len+tlen;
1050 siz -= xfer;
1051 cp += xfer;
1052 }
1053 *mb = m1;
1054 *bpos = mtod(m1, caddr_t)+m1->m_len;
1055 return (0);
1056}
1057
1058/*
1059 * Called once to initialize data structures...
1060 */
1061int
1062nfs_init()
1063{
1064 register int i;
1065
1066 /*
1067 * Check to see if major data structures haven't bloated.
1068 */
1069 if (sizeof (struct nfsnode) > NFS_NODEALLOC) {
1070 printf("struct nfsnode bloated (> %dbytes)\n", NFS_NODEALLOC);
1071 printf("Try reducing NFS_SMALLFH\n");
1072 }
1073 if (sizeof (struct nfsmount) > NFS_MNTALLOC) {
1074 printf("struct nfsmount bloated (> %dbytes)\n", NFS_MNTALLOC);
1075 printf("Try reducing NFS_MUIDHASHSIZ\n");
1076 }
1077 if (sizeof (struct nfssvc_sock) > NFS_SVCALLOC) {
1078 printf("struct nfssvc_sock bloated (> %dbytes)\n",NFS_SVCALLOC);
1079 printf("Try reducing NFS_UIDHASHSIZ\n");
1080 }
1081 if (sizeof (struct nfsuid) > NFS_UIDALLOC) {
1082 printf("struct nfsuid bloated (> %dbytes)\n",NFS_UIDALLOC);
1083 printf("Try unionizing the nu_nickname and nu_flag fields\n");
1084 }
1085 nfsrtt.pos = 0;
1086 rpc_vers = txdr_unsigned(RPC_VER2);
1087 rpc_call = txdr_unsigned(RPC_CALL);
1088 rpc_reply = txdr_unsigned(RPC_REPLY);
1089 rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
1090 rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
1091 rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
1092 rpc_autherr = txdr_unsigned(RPC_AUTHERR);
1093 rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
1094 rpc_auth_kerb = txdr_unsigned(RPCAUTH_KERB4);
1095 nfs_prog = txdr_unsigned(NFS_PROG);
1096 nqnfs_prog = txdr_unsigned(NQNFS_PROG);
1097 nfs_true = txdr_unsigned(TRUE);
1098 nfs_false = txdr_unsigned(FALSE);
1099 nfs_xdrneg1 = txdr_unsigned(-1);
1100 nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
1101 if (nfs_ticks < 1)
1102 nfs_ticks = 1;
1103 /* Ensure async daemons disabled */
1104 for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1105 nfs_iodwant[i] = (struct proc *)0;
1106 TAILQ_INIT(&nfs_bufq);
1107 nfs_nhinit(); /* Init the nfsnode table */
1108 nfsrv_init(0); /* Init server data structures */
1109 nfsrv_initcache(); /* Init the server request cache */
1110
1111 /*
1112 * Initialize the nqnfs server stuff.
1113 */
1114 if (nqnfsstarttime == 0) {
1115 nqnfsstarttime = boottime.tv_sec + nqsrv_maxlease
1116 + nqsrv_clockskew + nqsrv_writeslack;
1117 NQLOADNOVRAM(nqnfsstarttime);
1118 CIRCLEQ_INIT(&nqtimerhead);
1119 nqfhhashtbl = hashinit(NQLCHSZ, M_NQLEASE, &nqfhhash);
1120 }
1121
1122 /*
1123 * Initialize reply list and start timer
1124 */
1125 TAILQ_INIT(&nfs_reqq);
1126 nfs_timer(0);
1127
1128#ifdef __FreeBSD__
1129 /*
1130 * Set up lease_check and lease_updatetime so that other parts
1131 * of the system can call us, if we are loadable.
1132 */
1133 lease_check = nfs_lease_check;
1134 lease_updatetime = nfs_lease_updatetime;
1135 vfsconf[MOUNT_NFS]->vfc_refcount++; /* make us non-unloadable */
1136#ifdef VFS_LKM
1137 sysent[SYS_nfssvc].sy_narg = 2;
1138 sysent[SYS_nfssvc].sy_call = nfssvc;
1139 sysent[SYS_getfh].sy_narg = 2;
1140 sysent[SYS_getfh].sy_call = getfh;
1141#endif
1142#endif
1143
1144 return (0);
1145}
1146
1147/*
1148 * Attribute cache routines.
1149 * nfs_loadattrcache() - loads or updates the cache contents from attributes
1150 * that are on the mbuf list
1151 * nfs_getattrcache() - returns valid attributes if found in cache, returns
1152 * error otherwise
1153 */
1154
1155/*
1156 * Load the attribute cache (that lives in the nfsnode entry) with
1157 * the values on the mbuf list and
1158 * Iff vap not NULL
1159 * copy the attributes to *vaper
1160 */
1161int
1162nfs_loadattrcache(vpp, mdp, dposp, vaper)
1163 struct vnode **vpp;
1164 struct mbuf **mdp;
1165 caddr_t *dposp;
1166 struct vattr *vaper;
1167{
1168 register struct vnode *vp = *vpp;
1169 register struct vattr *vap;
1170 register struct nfs_fattr *fp;
1171 register struct nfsnode *np;
1172 register struct nfsnodehashhead *nhpp;
1173 register long t1;
1174 caddr_t cp2;
1175 int error = 0, rdev;
1176 struct mbuf *md;
1177 enum vtype vtyp;
1178 u_short vmode;
1179 struct timespec mtime;
1180 struct vnode *nvp;
1181 quad_t tval;
1182 int v3 = NFS_ISV3(vp);
1183
1184 md = *mdp;
1185 t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
1186 if (error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2))
1187 return (error);
1188 fp = (struct nfs_fattr *)cp2;
1189 if (v3) {
1190 vtyp = nfsv3tov_type(fp->fa_type);
1191 vmode = fxdr_unsigned(u_short, fp->fa_mode);
1192 rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1),
1193 fxdr_unsigned(u_char, fp->fa3_rdev.specdata2));
1194 fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
1195 } else {
1196 vtyp = nfsv2tov_type(fp->fa_type);
1197 vmode = fxdr_unsigned(u_short, fp->fa_mode);
1198 /*
1199 * XXX
1200 *
1201 * The duplicate information returned in fa_type and fa_mode
1202 * is an ambiguity in the NFS version 2 protocol.
1203 *
1204 * VREG should be taken literally as a regular file. If a
1205 * server intents to return some type information differently
1206 * in the upper bits of the mode field (e.g. for sockets, or
1207 * FIFOs), NFSv2 mandates fa_type to be VNON. Anyway, we
1208 * leave the examination of the mode bits even in the VREG
1209 * case to avoid breakage for bogus servers, but we make sure
1210 * that there are actually type bits set in the upper part of
1211 * fa_mode (and failing that, trust the va_type field).
1212 *
1213 * NFSv3 cleared the issue, and requires fa_mode to not
1214 * contain any type information (while also introduing sockets
1215 * and FIFOs for fa_type).
1216 */
1217 if (vtyp == VNON || (vtyp == VREG && (vmode & S_IFMT) != 0))
1218 vtyp = IFTOVT(vmode);
1219 rdev = fxdr_unsigned(long, fp->fa2_rdev);
1220 fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
1221
1222 /*
1223 * Really ugly NFSv2 kludge.
1224 */
1225 if (vtyp == VCHR && rdev == 0xffffffff)
1226 vtyp = VFIFO;
1227 }
1228
1229 /*
1230 * If v_type == VNON it is a new node, so fill in the v_type,
1231 * n_mtime fields. Check to see if it represents a special
1232 * device, and if so, check for a possible alias. Once the
1233 * correct vnode has been obtained, fill in the rest of the
1234 * information.
1235 */
1236 np = VTONFS(vp);
1237 if (vp->v_type == VNON) {
1238 /*
1239 * If we had a lock and it turns out that the vnode
1240 * is an object which we don't want to lock (e.g. VDIR)
1241 * to avoid nasty hanging problems on a server crash,
1242 * then release it here.
1243 */
1244 if (vtyp != VREG && VOP_ISLOCKED(vp))
1245 VOP_UNLOCK(vp);
1246 vp->v_type = vtyp;
1247 if (vp->v_type == VFIFO) {
1248 vp->v_op = fifo_nfsv2nodeop_p;
1249 }
1250 if (vp->v_type == VCHR || vp->v_type == VBLK) {
1251 vp->v_op = spec_nfsv2nodeop_p;
1252 nvp = checkalias(vp, (dev_t)rdev, vp->v_mount);
1253 if (nvp) {
1254 /*
1255 * Discard unneeded vnode, but save its nfsnode.
1256 */
1257 LIST_REMOVE(np, n_hash);
1258 nvp->v_data = vp->v_data;
1259 vp->v_data = NULL;
1260 vp->v_op = spec_vnodeop_p;
1261 vrele(vp);
1262 vgone(vp);
1263 /*
1264 * Reinitialize aliased node.
1265 */
1266 np->n_vnode = nvp;
1267 nhpp = NFSNOHASH(nfs_hash(np->n_fhp, np->n_fhsize));
1268 LIST_INSERT_HEAD(nhpp, np, n_hash);
1269 *vpp = vp = nvp;
1270 }
1271 }
1272 np->n_mtime = mtime.ts_sec;
1273 }
1274 vap = &np->n_vattr;
1275 vap->va_type = vtyp;
1276 vap->va_mode = (vmode & 07777);
1277 vap->va_rdev = (dev_t)rdev;
1278 vap->va_mtime = mtime;
1279 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
1280 if (v3) {
1281 vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
1282 vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
1283 vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
1284 fxdr_hyper(&fp->fa3_size, &vap->va_size);
1285 vap->va_blocksize = NFS_FABLKSIZE;
1286 fxdr_hyper(&fp->fa3_used, &vap->va_bytes);
1287 vap->va_fileid = fxdr_unsigned(int, fp->fa3_fileid.nfsuquad[1]);
1288 fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
1289 fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
1290 vap->va_flags = 0;
1291 vap->va_filerev = 0;
1292 } else {
1293 vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
1294 vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
1295 vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
1296 vap->va_size = fxdr_unsigned(u_long, fp->fa2_size);
1297 vap->va_blocksize = fxdr_unsigned(long, fp->fa2_blocksize);
1298 vap->va_bytes = fxdr_unsigned(long, fp->fa2_blocks) * NFS_FABLKSIZE;
1299 vap->va_fileid = fxdr_unsigned(long, fp->fa2_fileid);
1300 fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
1301 vap->va_flags = 0;
1302 vap->va_ctime.ts_sec = fxdr_unsigned(long, fp->fa2_ctime.nfsv2_sec);
1303 vap->va_ctime.ts_nsec = 0;
1304 vap->va_gen = fxdr_unsigned(u_long, fp->fa2_ctime.nfsv2_usec);
1305 vap->va_filerev = 0;
1306 }
1307 if (vap->va_size != np->n_size) {
1308 if (vap->va_type == VREG) {
1309 if (np->n_flag & NMODIFIED) {
1310 if (vap->va_size < np->n_size)
1311 vap->va_size = np->n_size;
1312 else
1313 np->n_size = vap->va_size;
1314 } else
1315 np->n_size = vap->va_size;
1316 vnode_pager_setsize(vp, (u_long)np->n_size);
1317 } else
1318 np->n_size = vap->va_size;
1319 }
1320 np->n_attrstamp = time.tv_sec;
1321 if (vaper != NULL) {
1322 bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
1323 if (np->n_flag & NCHG) {
1324 if (np->n_flag & NACC)
1325 vaper->va_atime = np->n_atim;
1326 if (np->n_flag & NUPD)
1327 vaper->va_mtime = np->n_mtim;
1328 }
1329 }
1330 return (0);
1331}
1332
1333/*
1334 * Check the time stamp
1335 * If the cache is valid, copy contents to *vap and return 0
1336 * otherwise return an error
1337 */
1338int
1339nfs_getattrcache(vp, vaper)
1340 register struct vnode *vp;
1341 struct vattr *vaper;
1342{
1343 register struct nfsnode *np = VTONFS(vp);
1344 register struct vattr *vap;
1345
1346 if ((time.tv_sec - np->n_attrstamp) >= NFS_ATTRTIMEO(np)) {
1347 nfsstats.attrcache_misses++;
1348 return (ENOENT);
1349 }
1350 nfsstats.attrcache_hits++;
1351 vap = &np->n_vattr;
1352 if (vap->va_size != np->n_size) {
1353 if (vap->va_type == VREG) {
1354 if (np->n_flag & NMODIFIED) {
1355 if (vap->va_size < np->n_size)
1356 vap->va_size = np->n_size;
1357 else
1358 np->n_size = vap->va_size;
1359 } else
1360 np->n_size = vap->va_size;
1361 vnode_pager_setsize(vp, (u_long)np->n_size);
1362 } else
1363 np->n_size = vap->va_size;
1364 }
1365 bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));
1366 if (np->n_flag & NCHG) {
1367 if (np->n_flag & NACC)
1368 vaper->va_atime = np->n_atim;
1369 if (np->n_flag & NUPD)
1370 vaper->va_mtime = np->n_mtim;
1371 }
1372 return (0);
1373}
1374
1375/*
1376 * Set up nameidata for a lookup() call and do it
1377 */
1378int
1379nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
1380 register struct nameidata *ndp;
1381 fhandle_t *fhp;
1382 int len;
1383 struct nfssvc_sock *slp;
1384 struct mbuf *nam;
1385 struct mbuf **mdp;
1386 caddr_t *dposp;
1387 struct vnode **retdirp;
1388 struct proc *p;
1389 int kerbflag;
1390{
1391 register int i, rem;
1392 register struct mbuf *md;
1393 register char *fromcp, *tocp;
1394 struct vnode *dp;
1395 int error, rdonly;
1396 struct componentname *cnp = &ndp->ni_cnd;
1397
1398 *retdirp = (struct vnode *)0;
1399 MALLOC(cnp->cn_pnbuf, char *, len + 1, M_NAMEI, M_WAITOK);
1400 /*
1401 * Copy the name from the mbuf list to ndp->ni_pnbuf
1402 * and set the various ndp fields appropriately.
1403 */
1404 fromcp = *dposp;
1405 tocp = cnp->cn_pnbuf;
1406 md = *mdp;
1407 rem = mtod(md, caddr_t) + md->m_len - fromcp;
1408 cnp->cn_hash = 0;
1409 for (i = 0; i < len; i++) {
1410 while (rem == 0) {
1411 md = md->m_next;
1412 if (md == NULL) {
1413 error = EBADRPC;
1414 goto out;
1415 }
1416 fromcp = mtod(md, caddr_t);
1417 rem = md->m_len;
1418 }
1419 if (*fromcp == '\0' || *fromcp == '/') {
1420 error = EACCES;
1421 goto out;
1422 }
1423 cnp->cn_hash += (unsigned char)*fromcp;
1424 *tocp++ = *fromcp++;
1425 rem--;
1426 }
1427 *tocp = '\0';
1428 *mdp = md;
1429 *dposp = fromcp;
1430 len = nfsm_rndup(len)-len;
1431 if (len > 0) {
1432 if (rem >= len)
1433 *dposp += len;
1434 else if (error = nfs_adv(mdp, dposp, len, rem))
1435 goto out;
1436 }
1437 ndp->ni_pathlen = tocp - cnp->cn_pnbuf;
1438 cnp->cn_nameptr = cnp->cn_pnbuf;
1439 /*
1440 * Extract and set starting directory.
1441 */
1442 if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
1443 nam, &rdonly, kerbflag))
1444 goto out;
1445 if (dp->v_type != VDIR) {
1446 nfsrv_vrele(dp);
1447 error = ENOTDIR;
1448 goto out;
1449 }
1450 VREF(dp);
1451 *retdirp = dp;
1452 ndp->ni_startdir = dp;
1453 if (rdonly)
1454 cnp->cn_flags |= (NOCROSSMOUNT | RDONLY);
1455 else
1456 cnp->cn_flags |= NOCROSSMOUNT;
1457 /*
1458 * And call lookup() to do the real work
1459 */
1460 cnp->cn_proc = p;
1461 if (error = lookup(ndp))
1462 goto out;
1463 /*
1464 * Check for encountering a symbolic link
1465 */
1466 if (cnp->cn_flags & ISSYMLINK) {
1467 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
1468 vput(ndp->ni_dvp);
1469 else
1470 vrele(ndp->ni_dvp);
1471 vput(ndp->ni_vp);
1472 ndp->ni_vp = NULL;
1473 error = EINVAL;
1474 goto out;
1475 }
1476
1477 nfsrv_vmio(ndp->ni_vp);
1478
1479 /*
1480 * Check for saved name request
1481 */
1482 if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
1483 cnp->cn_flags |= HASBUF;
1484 return (0);
1485 }
1486out:
1487 FREE(cnp->cn_pnbuf, M_NAMEI);
1488 return (error);
1489}
1490
1491/*
1492 * A fiddled version of m_adj() that ensures null fill to a long
1493 * boundary and only trims off the back end
1494 */
1495void
1496nfsm_adj(mp, len, nul)
1497 struct mbuf *mp;
1498 register int len;
1499 int nul;
1500{
1501 register struct mbuf *m;
1502 register int count, i;
1503 register char *cp;
1504
1505 /*
1506 * Trim from tail. Scan the mbuf chain,
1507 * calculating its length and finding the last mbuf.
1508 * If the adjustment only affects this mbuf, then just
1509 * adjust and return. Otherwise, rescan and truncate
1510 * after the remaining size.
1511 */
1512 count = 0;
1513 m = mp;
1514 for (;;) {
1515 count += m->m_len;
1516 if (m->m_next == (struct mbuf *)0)
1517 break;
1518 m = m->m_next;
1519 }
1520 if (m->m_len > len) {
1521 m->m_len -= len;
1522 if (nul > 0) {
1523 cp = mtod(m, caddr_t)+m->m_len-nul;
1524 for (i = 0; i < nul; i++)
1525 *cp++ = '\0';
1526 }
1527 return;
1528 }
1529 count -= len;
1530 if (count < 0)
1531 count = 0;
1532 /*
1533 * Correct length for chain is "count".
1534 * Find the mbuf with last data, adjust its length,
1535 * and toss data from remaining mbufs on chain.
1536 */
1537 for (m = mp; m; m = m->m_next) {
1538 if (m->m_len >= count) {
1539 m->m_len = count;
1540 if (nul > 0) {
1541 cp = mtod(m, caddr_t)+m->m_len-nul;
1542 for (i = 0; i < nul; i++)
1543 *cp++ = '\0';
1544 }
1545 break;
1546 }
1547 count -= m->m_len;
1548 }
1549 for (m = m->m_next;m;m = m->m_next)
1550 m->m_len = 0;
1551}
1552
1553/*
1554 * Make these functions instead of macros, so that the kernel text size
1555 * doesn't get too big...
1556 */
1557void
1558nfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp)
1559 struct nfsrv_descript *nfsd;
1560 int before_ret;
1561 register struct vattr *before_vap;
1562 int after_ret;
1563 struct vattr *after_vap;
1564 struct mbuf **mbp;
1565 char **bposp;
1566{
1567 register struct mbuf *mb = *mbp, *mb2;
1568 register char *bpos = *bposp;
1569 register u_long *tl;
1570
1571 if (before_ret) {
1572 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1573 *tl = nfs_false;
1574 } else {
1575 nfsm_build(tl, u_long *, 7 * NFSX_UNSIGNED);
1576 *tl++ = nfs_true;
1577 txdr_hyper(&(before_vap->va_size), tl);
1578 tl += 2;
1579 txdr_nfsv3time(&(before_vap->va_mtime), tl);
1580 tl += 2;
1581 txdr_nfsv3time(&(before_vap->va_ctime), tl);
1582 }
1583 *bposp = bpos;
1584 *mbp = mb;
1585 nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
1586}
1587
1588void
1589nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp)
1590 struct nfsrv_descript *nfsd;
1591 int after_ret;
1592 struct vattr *after_vap;
1593 struct mbuf **mbp;
1594 char **bposp;
1595{
1596 register struct mbuf *mb = *mbp, *mb2;
1597 register char *bpos = *bposp;
1598 register u_long *tl;
1599 register struct nfs_fattr *fp;
1600
1601 if (after_ret) {
1602 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1603 *tl = nfs_false;
1604 } else {
1605 nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FATTR);
1606 *tl++ = nfs_true;
1607 fp = (struct nfs_fattr *)tl;
1608 nfsm_srvfattr(nfsd, after_vap, fp);
1609 }
1610 *mbp = mb;
1611 *bposp = bpos;
1612}
1613
1614void
1615nfsm_srvfattr(nfsd, vap, fp)
1616 register struct nfsrv_descript *nfsd;
1617 register struct vattr *vap;
1618 register struct nfs_fattr *fp;
1619{
1620
1621 fp->fa_nlink = txdr_unsigned(vap->va_nlink);
1622 fp->fa_uid = txdr_unsigned(vap->va_uid);
1623 fp->fa_gid = txdr_unsigned(vap->va_gid);
1624 if (nfsd->nd_flag & ND_NFSV3) {
1625 fp->fa_type = vtonfsv3_type(vap->va_type);
1626 fp->fa_mode = vtonfsv3_mode(vap->va_mode);
1627 txdr_hyper(&vap->va_size, &fp->fa3_size);
1628 txdr_hyper(&vap->va_bytes, &fp->fa3_used);
1629 fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev));
1630 fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev));
1631 fp->fa3_fsid.nfsuquad[0] = 0;
1632 fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
1633 fp->fa3_fileid.nfsuquad[0] = 0;
1634 fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
1635 txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
1636 txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
1637 txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
1638 } else {
1639 fp->fa_type = vtonfsv2_type(vap->va_type);
1640 fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1641 fp->fa2_size = txdr_unsigned(vap->va_size);
1642 fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
1643 if (vap->va_type == VFIFO)
1644 fp->fa2_rdev = 0xffffffff;
1645 else
1646 fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
1647 fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
1648 fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
1649 fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
1650 txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
1651 txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
1652 txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
1653 }
1654}
1655
1656/*
1657 * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
1658 * - look up fsid in mount list (if not found ret error)
1659 * - get vp and export rights by calling VFS_FHTOVP()
1660 * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
1661 * - if not lockflag unlock it with VOP_UNLOCK()
1662 */
1663int
1664nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
1665 fhandle_t *fhp;
1666 int lockflag;
1667 struct vnode **vpp;
1668 struct ucred *cred;
1669 struct nfssvc_sock *slp;
1670 struct mbuf *nam;
1671 int *rdonlyp;
1672 int kerbflag;
1673{
1674 register struct mount *mp;
1675 register struct nfsuid *uidp;
1676 register int i;
1677 struct ucred *credanon;
1678 int error, exflags;
1679
1680 *vpp = (struct vnode *)0;
1681 mp = getvfs(&fhp->fh_fsid);
1682 if (!mp)
1683 return (ESTALE);
1684 error = VFS_FHTOVP(mp, &fhp->fh_fid, nam, vpp, &exflags, &credanon);
1685 if (error)
1686 return (error);
1687 /*
1688 * Check/setup credentials.
1689 */
1690 if (exflags & MNT_EXKERB) {
1691 if (!kerbflag) {
1692 vput(*vpp);
1693 return (NFSERR_AUTHERR | AUTH_TOOWEAK);
1694 }
1695 } else if (kerbflag) {
1696 vput(*vpp);
1697 return (NFSERR_AUTHERR | AUTH_TOOWEAK);
1698 } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
1699 cred->cr_uid = credanon->cr_uid;
1700 for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
1701 cred->cr_groups[i] = credanon->cr_groups[i];
1702 cred->cr_ngroups = i;
1703 }
1704 if (exflags & MNT_EXRDONLY)
1705 *rdonlyp = 1;
1706 else
1707 *rdonlyp = 0;
1708
1709 nfsrv_vmio(*vpp);
1710
1711 if (!lockflag)
1712 VOP_UNLOCK(*vpp);
1713 return (0);
1714}
1715
1716/*
1717 * This function compares two net addresses by family and returns TRUE
1718 * if they are the same host.
1719 * If there is any doubt, return FALSE.
1720 * The AF_INET family is handled as a special case so that address mbufs
1721 * don't need to be saved to store "struct in_addr", which is only 4 bytes.
1722 */
1723int
1724netaddr_match(family, haddr, nam)
1725 int family;
1726 union nethostaddr *haddr;
1727 struct mbuf *nam;
1728{
1729 register struct sockaddr_in *inetaddr;
1730
1731 switch (family) {
1732 case AF_INET:
1733 inetaddr = mtod(nam, struct sockaddr_in *);
1734 if (inetaddr->sin_family == AF_INET &&
1735 inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
1736 return (1);
1737 break;
1738#ifdef ISO
1739 case AF_ISO:
1740 {
1741 register struct sockaddr_iso *isoaddr1, *isoaddr2;
1742
1743 isoaddr1 = mtod(nam, struct sockaddr_iso *);
1744 isoaddr2 = mtod(haddr->had_nam, struct sockaddr_iso *);
1745 if (isoaddr1->siso_family == AF_ISO &&
1746 isoaddr1->siso_nlen > 0 &&
1747 isoaddr1->siso_nlen == isoaddr2->siso_nlen &&
1748 SAME_ISOADDR(isoaddr1, isoaddr2))
1749 return (1);
1750 break;
1751 }
1752#endif /* ISO */
1753 default:
1754 break;
1755 };
1756 return (0);
1757}
1758
1759static nfsuint64 nfs_nullcookie = { 0, 0 };
1760/*
1761 * This function finds the directory cookie that corresponds to the
1762 * logical byte offset given.
1763 */
1764nfsuint64 *
1765nfs_getcookie(np, off, add)
1766 register struct nfsnode *np;
1767 off_t off;
1768 int add;
1769{
1770 register struct nfsdmap *dp, *dp2;
1771 register int pos;
1772
1773 pos = off / NFS_DIRBLKSIZ;
1774 if (pos == 0) {
1775#ifdef DIAGNOSTIC
1776 if (add)
1777 panic("nfs getcookie add at 0");
1778#endif
1779 return (&nfs_nullcookie);
1780 }
1781 pos--;
1782 dp = np->n_cookies.lh_first;
1783 if (!dp) {
1784 if (add) {
1785 MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
1786 M_NFSDIROFF, M_WAITOK);
1787 dp->ndm_eocookie = 0;
1788 LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
1789 } else
1790 return ((nfsuint64 *)0);
1791 }
1792 while (pos >= NFSNUMCOOKIES) {
1793 pos -= NFSNUMCOOKIES;
1794 if (dp->ndm_list.le_next) {
1795 if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
1796 pos >= dp->ndm_eocookie)
1797 return ((nfsuint64 *)0);
1798 dp = dp->ndm_list.le_next;
1799 } else if (add) {
1800 MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
1801 M_NFSDIROFF, M_WAITOK);
1802 dp2->ndm_eocookie = 0;
1803 LIST_INSERT_AFTER(dp, dp2, ndm_list);
1804 dp = dp2;
1805 } else
1806 return ((nfsuint64 *)0);
1807 }
1808 if (pos >= dp->ndm_eocookie) {
1809 if (add)
1810 dp->ndm_eocookie = pos + 1;
1811 else
1812 return ((nfsuint64 *)0);
1813 }
1814 return (&dp->ndm_cookies[pos]);
1815}
1816
1817/*
1818 * Invalidate cached directory information, except for the actual directory
1819 * blocks (which are invalidated separately).
1820 * Done mainly to avoid the use of stale offset cookies.
1821 */
1822void
1823nfs_invaldir(vp)
1824 register struct vnode *vp;
1825{
1826 register struct nfsnode *np = VTONFS(vp);
1827
1828#ifdef DIAGNOSTIC
1829 if (vp->v_type != VDIR)
1830 panic("nfs: invaldir not dir");
1831#endif
1832 np->n_direofoffset = 0;
1833 np->n_cookieverf.nfsuquad[0] = 0;
1834 np->n_cookieverf.nfsuquad[1] = 0;
1835 if (np->n_cookies.lh_first)
1836 np->n_cookies.lh_first->ndm_eocookie = 0;
1837}
1838
1839/*
1840 * The write verifier has changed (probably due to a server reboot), so all
1841 * B_NEEDCOMMIT blocks will have to be written again. Since they are on the
1842 * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT
1843 * flag. Once done the new write verifier can be set for the mount point.
1844 */
1845void
1846nfs_clearcommit(mp)
1847 struct mount *mp;
1848{
1849 register struct vnode *vp, *nvp;
1850 register struct buf *bp, *nbp;
1851 int s;
1852
1853 s = splbio();
1854loop:
1855 for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
1856 if (vp->v_mount != mp) /* Paranoia */
1857 goto loop;
1858 nvp = vp->v_mntvnodes.le_next;
1859 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
1860 nbp = bp->b_vnbufs.le_next;
1861 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
1862 == (B_DELWRI | B_NEEDCOMMIT))
1863 bp->b_flags &= ~B_NEEDCOMMIT;
1864 }
1865 }
1866 splx(s);
1867}
1868
1869/*
1870 * Map errnos to NFS error numbers. For Version 3 also filter out error
1871 * numbers not specified for the associated procedure.
1872 */
1873int
1874nfsrv_errmap(nd, err)
1875 struct nfsrv_descript *nd;
1876 register int err;
1877{
1878 register short *defaulterrp, *errp;
1879
1880 if (nd->nd_flag & ND_NFSV3) {
1881 if (nd->nd_procnum <= NFSPROC_COMMIT) {
1882 errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
1883 while (*++errp) {
1884 if (*errp == err)
1885 return (err);
1886 else if (*errp > err)
1887 break;
1888 }
1889 return ((int)*defaulterrp);
1890 } else
1891 return (err & 0xffff);
1892 }
1893 if (err <= ELAST)
1894 return ((int)nfsrv_v2errmap[err - 1]);
1895 return (NFSERR_IO);
1896}
1897
1898int
1899nfsrv_vmio(struct vnode *vp) {
1900 vm_object_t object;
76#include <netinet/in.h>
77#ifdef ISO
78#include <netiso/iso.h>
79#endif
80
81/*
82 * Data items converted to xdr at startup, since they are constant
83 * This is kinda hokey, but may save a little time doing byte swaps
84 */
85u_long nfs_xdrneg1;
86u_long rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
87 rpc_mismatch, rpc_auth_unix, rpc_msgaccepted,
88 rpc_auth_kerb;
89u_long nfs_prog, nqnfs_prog, nfs_true, nfs_false;
90
91/* And other global data */
92static u_long nfs_xid = 0;
93enum vtype nv2tov_type[8] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON };
94enum vtype nv3tov_type[8]={ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO };
95int nfs_ticks;
96
97/*
98 * Mapping of old NFS Version 2 RPC numbers to generic numbers.
99 */
100int nfsv3_procid[NFS_NPROCS] = {
101 NFSPROC_NULL,
102 NFSPROC_GETATTR,
103 NFSPROC_SETATTR,
104 NFSPROC_NOOP,
105 NFSPROC_LOOKUP,
106 NFSPROC_READLINK,
107 NFSPROC_READ,
108 NFSPROC_NOOP,
109 NFSPROC_WRITE,
110 NFSPROC_CREATE,
111 NFSPROC_REMOVE,
112 NFSPROC_RENAME,
113 NFSPROC_LINK,
114 NFSPROC_SYMLINK,
115 NFSPROC_MKDIR,
116 NFSPROC_RMDIR,
117 NFSPROC_READDIR,
118 NFSPROC_FSSTAT,
119 NFSPROC_NOOP,
120 NFSPROC_NOOP,
121 NFSPROC_NOOP,
122 NFSPROC_NOOP,
123 NFSPROC_NOOP,
124 NFSPROC_NOOP,
125 NFSPROC_NOOP,
126 NFSPROC_NOOP
127};
128
129/*
130 * and the reverse mapping from generic to Version 2 procedure numbers
131 */
132int nfsv2_procid[NFS_NPROCS] = {
133 NFSV2PROC_NULL,
134 NFSV2PROC_GETATTR,
135 NFSV2PROC_SETATTR,
136 NFSV2PROC_LOOKUP,
137 NFSV2PROC_NOOP,
138 NFSV2PROC_READLINK,
139 NFSV2PROC_READ,
140 NFSV2PROC_WRITE,
141 NFSV2PROC_CREATE,
142 NFSV2PROC_MKDIR,
143 NFSV2PROC_SYMLINK,
144 NFSV2PROC_CREATE,
145 NFSV2PROC_REMOVE,
146 NFSV2PROC_RMDIR,
147 NFSV2PROC_RENAME,
148 NFSV2PROC_LINK,
149 NFSV2PROC_READDIR,
150 NFSV2PROC_NOOP,
151 NFSV2PROC_STATFS,
152 NFSV2PROC_NOOP,
153 NFSV2PROC_NOOP,
154 NFSV2PROC_NOOP,
155 NFSV2PROC_NOOP,
156 NFSV2PROC_NOOP,
157 NFSV2PROC_NOOP,
158 NFSV2PROC_NOOP,
159};
160
161/*
162 * Maps errno values to nfs error numbers.
163 * Use NFSERR_IO as the catch all for ones not specifically defined in
164 * RFC 1094.
165 */
166static u_char nfsrv_v2errmap[ELAST] = {
167 NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO,
168 NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
169 NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO,
170 NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR,
171 NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
172 NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS,
173 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
174 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
175 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
176 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
177 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
178 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
179 NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO,
180 NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE,
181 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
182 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
183 NFSERR_IO,
184};
185
186/*
187 * Maps errno values to nfs error numbers.
188 * Although it is not obvious whether or not NFS clients really care if
189 * a returned error value is in the specified list for the procedure, the
190 * safest thing to do is filter them appropriately. For Version 2, the
191 * X/Open XNFS document is the only specification that defines error values
192 * for each RPC (The RFC simply lists all possible error values for all RPCs),
193 * so I have decided to not do this for Version 2.
194 * The first entry is the default error return and the rest are the valid
195 * errors for that RPC in increasing numeric order.
196 */
197static short nfsv3err_null[] = {
198 0,
199 0,
200};
201
202static short nfsv3err_getattr[] = {
203 NFSERR_IO,
204 NFSERR_IO,
205 NFSERR_STALE,
206 NFSERR_BADHANDLE,
207 NFSERR_SERVERFAULT,
208 0,
209};
210
211static short nfsv3err_setattr[] = {
212 NFSERR_IO,
213 NFSERR_PERM,
214 NFSERR_IO,
215 NFSERR_ACCES,
216 NFSERR_INVAL,
217 NFSERR_NOSPC,
218 NFSERR_ROFS,
219 NFSERR_DQUOT,
220 NFSERR_STALE,
221 NFSERR_BADHANDLE,
222 NFSERR_NOT_SYNC,
223 NFSERR_SERVERFAULT,
224 0,
225};
226
227static short nfsv3err_lookup[] = {
228 NFSERR_IO,
229 NFSERR_NOENT,
230 NFSERR_IO,
231 NFSERR_ACCES,
232 NFSERR_NOTDIR,
233 NFSERR_NAMETOL,
234 NFSERR_STALE,
235 NFSERR_BADHANDLE,
236 NFSERR_SERVERFAULT,
237 0,
238};
239
240static short nfsv3err_access[] = {
241 NFSERR_IO,
242 NFSERR_IO,
243 NFSERR_STALE,
244 NFSERR_BADHANDLE,
245 NFSERR_SERVERFAULT,
246 0,
247};
248
249static short nfsv3err_readlink[] = {
250 NFSERR_IO,
251 NFSERR_IO,
252 NFSERR_ACCES,
253 NFSERR_INVAL,
254 NFSERR_STALE,
255 NFSERR_BADHANDLE,
256 NFSERR_NOTSUPP,
257 NFSERR_SERVERFAULT,
258 0,
259};
260
261static short nfsv3err_read[] = {
262 NFSERR_IO,
263 NFSERR_IO,
264 NFSERR_NXIO,
265 NFSERR_ACCES,
266 NFSERR_INVAL,
267 NFSERR_STALE,
268 NFSERR_BADHANDLE,
269 NFSERR_SERVERFAULT,
270 0,
271};
272
273static short nfsv3err_write[] = {
274 NFSERR_IO,
275 NFSERR_IO,
276 NFSERR_ACCES,
277 NFSERR_INVAL,
278 NFSERR_FBIG,
279 NFSERR_NOSPC,
280 NFSERR_ROFS,
281 NFSERR_DQUOT,
282 NFSERR_STALE,
283 NFSERR_BADHANDLE,
284 NFSERR_SERVERFAULT,
285 0,
286};
287
288static short nfsv3err_create[] = {
289 NFSERR_IO,
290 NFSERR_IO,
291 NFSERR_ACCES,
292 NFSERR_EXIST,
293 NFSERR_NOTDIR,
294 NFSERR_NOSPC,
295 NFSERR_ROFS,
296 NFSERR_NAMETOL,
297 NFSERR_DQUOT,
298 NFSERR_STALE,
299 NFSERR_BADHANDLE,
300 NFSERR_NOTSUPP,
301 NFSERR_SERVERFAULT,
302 0,
303};
304
305static short nfsv3err_mkdir[] = {
306 NFSERR_IO,
307 NFSERR_IO,
308 NFSERR_ACCES,
309 NFSERR_EXIST,
310 NFSERR_NOTDIR,
311 NFSERR_NOSPC,
312 NFSERR_ROFS,
313 NFSERR_NAMETOL,
314 NFSERR_DQUOT,
315 NFSERR_STALE,
316 NFSERR_BADHANDLE,
317 NFSERR_NOTSUPP,
318 NFSERR_SERVERFAULT,
319 0,
320};
321
322static short nfsv3err_symlink[] = {
323 NFSERR_IO,
324 NFSERR_IO,
325 NFSERR_ACCES,
326 NFSERR_EXIST,
327 NFSERR_NOTDIR,
328 NFSERR_NOSPC,
329 NFSERR_ROFS,
330 NFSERR_NAMETOL,
331 NFSERR_DQUOT,
332 NFSERR_STALE,
333 NFSERR_BADHANDLE,
334 NFSERR_NOTSUPP,
335 NFSERR_SERVERFAULT,
336 0,
337};
338
339static short nfsv3err_mknod[] = {
340 NFSERR_IO,
341 NFSERR_IO,
342 NFSERR_ACCES,
343 NFSERR_EXIST,
344 NFSERR_NOTDIR,
345 NFSERR_NOSPC,
346 NFSERR_ROFS,
347 NFSERR_NAMETOL,
348 NFSERR_DQUOT,
349 NFSERR_STALE,
350 NFSERR_BADHANDLE,
351 NFSERR_NOTSUPP,
352 NFSERR_SERVERFAULT,
353 NFSERR_BADTYPE,
354 0,
355};
356
357static short nfsv3err_remove[] = {
358 NFSERR_IO,
359 NFSERR_NOENT,
360 NFSERR_IO,
361 NFSERR_ACCES,
362 NFSERR_NOTDIR,
363 NFSERR_ROFS,
364 NFSERR_NAMETOL,
365 NFSERR_STALE,
366 NFSERR_BADHANDLE,
367 NFSERR_SERVERFAULT,
368 0,
369};
370
371static short nfsv3err_rmdir[] = {
372 NFSERR_IO,
373 NFSERR_NOENT,
374 NFSERR_IO,
375 NFSERR_ACCES,
376 NFSERR_EXIST,
377 NFSERR_NOTDIR,
378 NFSERR_INVAL,
379 NFSERR_ROFS,
380 NFSERR_NAMETOL,
381 NFSERR_NOTEMPTY,
382 NFSERR_STALE,
383 NFSERR_BADHANDLE,
384 NFSERR_NOTSUPP,
385 NFSERR_SERVERFAULT,
386 0,
387};
388
389static short nfsv3err_rename[] = {
390 NFSERR_IO,
391 NFSERR_NOENT,
392 NFSERR_IO,
393 NFSERR_ACCES,
394 NFSERR_EXIST,
395 NFSERR_XDEV,
396 NFSERR_NOTDIR,
397 NFSERR_ISDIR,
398 NFSERR_INVAL,
399 NFSERR_NOSPC,
400 NFSERR_ROFS,
401 NFSERR_MLINK,
402 NFSERR_NAMETOL,
403 NFSERR_NOTEMPTY,
404 NFSERR_DQUOT,
405 NFSERR_STALE,
406 NFSERR_BADHANDLE,
407 NFSERR_NOTSUPP,
408 NFSERR_SERVERFAULT,
409 0,
410};
411
412static short nfsv3err_link[] = {
413 NFSERR_IO,
414 NFSERR_IO,
415 NFSERR_ACCES,
416 NFSERR_EXIST,
417 NFSERR_XDEV,
418 NFSERR_NOTDIR,
419 NFSERR_INVAL,
420 NFSERR_NOSPC,
421 NFSERR_ROFS,
422 NFSERR_MLINK,
423 NFSERR_NAMETOL,
424 NFSERR_DQUOT,
425 NFSERR_STALE,
426 NFSERR_BADHANDLE,
427 NFSERR_NOTSUPP,
428 NFSERR_SERVERFAULT,
429 0,
430};
431
432static short nfsv3err_readdir[] = {
433 NFSERR_IO,
434 NFSERR_IO,
435 NFSERR_ACCES,
436 NFSERR_NOTDIR,
437 NFSERR_STALE,
438 NFSERR_BADHANDLE,
439 NFSERR_BAD_COOKIE,
440 NFSERR_TOOSMALL,
441 NFSERR_SERVERFAULT,
442 0,
443};
444
445static short nfsv3err_readdirplus[] = {
446 NFSERR_IO,
447 NFSERR_IO,
448 NFSERR_ACCES,
449 NFSERR_NOTDIR,
450 NFSERR_STALE,
451 NFSERR_BADHANDLE,
452 NFSERR_BAD_COOKIE,
453 NFSERR_NOTSUPP,
454 NFSERR_TOOSMALL,
455 NFSERR_SERVERFAULT,
456 0,
457};
458
459static short nfsv3err_fsstat[] = {
460 NFSERR_IO,
461 NFSERR_IO,
462 NFSERR_STALE,
463 NFSERR_BADHANDLE,
464 NFSERR_SERVERFAULT,
465 0,
466};
467
468static short nfsv3err_fsinfo[] = {
469 NFSERR_STALE,
470 NFSERR_STALE,
471 NFSERR_BADHANDLE,
472 NFSERR_SERVERFAULT,
473 0,
474};
475
476static short nfsv3err_pathconf[] = {
477 NFSERR_STALE,
478 NFSERR_STALE,
479 NFSERR_BADHANDLE,
480 NFSERR_SERVERFAULT,
481 0,
482};
483
484static short nfsv3err_commit[] = {
485 NFSERR_IO,
486 NFSERR_IO,
487 NFSERR_STALE,
488 NFSERR_BADHANDLE,
489 NFSERR_SERVERFAULT,
490 0,
491};
492
493static short *nfsrv_v3errmap[] = {
494 nfsv3err_null,
495 nfsv3err_getattr,
496 nfsv3err_setattr,
497 nfsv3err_lookup,
498 nfsv3err_access,
499 nfsv3err_readlink,
500 nfsv3err_read,
501 nfsv3err_write,
502 nfsv3err_create,
503 nfsv3err_mkdir,
504 nfsv3err_symlink,
505 nfsv3err_mknod,
506 nfsv3err_remove,
507 nfsv3err_rmdir,
508 nfsv3err_rename,
509 nfsv3err_link,
510 nfsv3err_readdir,
511 nfsv3err_readdirplus,
512 nfsv3err_fsstat,
513 nfsv3err_fsinfo,
514 nfsv3err_pathconf,
515 nfsv3err_commit,
516};
517
518extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
519extern struct nfsrtt nfsrtt;
520extern time_t nqnfsstarttime;
521extern int nqsrv_clockskew;
522extern int nqsrv_writeslack;
523extern int nqsrv_maxlease;
524extern struct nfsstats nfsstats;
525extern int nqnfs_piggy[NFS_NPROCS];
526extern nfstype nfsv2_type[9];
527extern nfstype nfsv3_type[9];
528extern struct nfsnodehashhead *nfsnodehashtbl;
529extern u_long nfsnodehash;
530
531#ifdef VFS_LKM
532struct getfh_args;
533extern int getfh(struct proc *, struct getfh_args *, int *);
534struct nfssvc_args;
535extern int nfssvc(struct proc *, struct nfssvc_args *, int *);
536#endif
537
538LIST_HEAD(nfsnodehashhead, nfsnode);
539
540/*
541 * Create the header for an rpc request packet
542 * The hsiz is the size of the rest of the nfs request header.
543 * (just used to decide if a cluster is a good idea)
544 */
545struct mbuf *
546nfsm_reqh(vp, procid, hsiz, bposp)
547 struct vnode *vp;
548 u_long procid;
549 int hsiz;
550 caddr_t *bposp;
551{
552 register struct mbuf *mb;
553 register u_long *tl;
554 register caddr_t bpos;
555 struct mbuf *mb2;
556 struct nfsmount *nmp;
557 int nqflag;
558
559 MGET(mb, M_WAIT, MT_DATA);
560 if (hsiz >= MINCLSIZE)
561 MCLGET(mb, M_WAIT);
562 mb->m_len = 0;
563 bpos = mtod(mb, caddr_t);
564
565 /*
566 * For NQNFS, add lease request.
567 */
568 if (vp) {
569 nmp = VFSTONFS(vp->v_mount);
570 if (nmp->nm_flag & NFSMNT_NQNFS) {
571 nqflag = NQNFS_NEEDLEASE(vp, procid);
572 if (nqflag) {
573 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
574 *tl++ = txdr_unsigned(nqflag);
575 *tl = txdr_unsigned(nmp->nm_leaseterm);
576 } else {
577 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
578 *tl = 0;
579 }
580 }
581 }
582 /* Finally, return values */
583 *bposp = bpos;
584 return (mb);
585}
586
587/*
588 * Build the RPC header and fill in the authorization info.
589 * The authorization string argument is only used when the credentials
590 * come from outside of the kernel.
591 * Returns the head of the mbuf list.
592 */
593struct mbuf *
594nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
595 verf_str, mrest, mrest_len, mbp, xidp)
596 register struct ucred *cr;
597 int nmflag;
598 int procid;
599 int auth_type;
600 int auth_len;
601 char *auth_str;
602 int verf_len;
603 char *verf_str;
604 struct mbuf *mrest;
605 int mrest_len;
606 struct mbuf **mbp;
607 u_long *xidp;
608{
609 register struct mbuf *mb;
610 register u_long *tl;
611 register caddr_t bpos;
612 register int i;
613 struct mbuf *mreq, *mb2;
614 int siz, grpsiz, authsiz;
615
616 authsiz = nfsm_rndup(auth_len);
617 MGETHDR(mb, M_WAIT, MT_DATA);
618 if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) {
619 MCLGET(mb, M_WAIT);
620 } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) {
621 MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
622 } else {
623 MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
624 }
625 mb->m_len = 0;
626 mreq = mb;
627 bpos = mtod(mb, caddr_t);
628
629 /*
630 * First the RPC header.
631 */
632 nfsm_build(tl, u_long *, 8 * NFSX_UNSIGNED);
633 if (++nfs_xid == 0)
634 nfs_xid++;
635 *tl++ = *xidp = txdr_unsigned(nfs_xid);
636 *tl++ = rpc_call;
637 *tl++ = rpc_vers;
638 if (nmflag & NFSMNT_NQNFS) {
639 *tl++ = txdr_unsigned(NQNFS_PROG);
640 *tl++ = txdr_unsigned(NQNFS_VER3);
641 } else {
642 *tl++ = txdr_unsigned(NFS_PROG);
643 if (nmflag & NFSMNT_NFSV3)
644 *tl++ = txdr_unsigned(NFS_VER3);
645 else
646 *tl++ = txdr_unsigned(NFS_VER2);
647 }
648 if (nmflag & NFSMNT_NFSV3)
649 *tl++ = txdr_unsigned(procid);
650 else
651 *tl++ = txdr_unsigned(nfsv2_procid[procid]);
652
653 /*
654 * And then the authorization cred.
655 */
656 *tl++ = txdr_unsigned(auth_type);
657 *tl = txdr_unsigned(authsiz);
658 switch (auth_type) {
659 case RPCAUTH_UNIX:
660 nfsm_build(tl, u_long *, auth_len);
661 *tl++ = 0; /* stamp ?? */
662 *tl++ = 0; /* NULL hostname */
663 *tl++ = txdr_unsigned(cr->cr_uid);
664 *tl++ = txdr_unsigned(cr->cr_groups[0]);
665 grpsiz = (auth_len >> 2) - 5;
666 *tl++ = txdr_unsigned(grpsiz);
667 for (i = 1; i <= grpsiz; i++)
668 *tl++ = txdr_unsigned(cr->cr_groups[i]);
669 break;
670 case RPCAUTH_KERB4:
671 siz = auth_len;
672 while (siz > 0) {
673 if (M_TRAILINGSPACE(mb) == 0) {
674 MGET(mb2, M_WAIT, MT_DATA);
675 if (siz >= MINCLSIZE)
676 MCLGET(mb2, M_WAIT);
677 mb->m_next = mb2;
678 mb = mb2;
679 mb->m_len = 0;
680 bpos = mtod(mb, caddr_t);
681 }
682 i = min(siz, M_TRAILINGSPACE(mb));
683 bcopy(auth_str, bpos, i);
684 mb->m_len += i;
685 auth_str += i;
686 bpos += i;
687 siz -= i;
688 }
689 if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) {
690 for (i = 0; i < siz; i++)
691 *bpos++ = '\0';
692 mb->m_len += siz;
693 }
694 break;
695 };
696
697 /*
698 * And the verifier...
699 */
700 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
701 if (verf_str) {
702 *tl++ = txdr_unsigned(RPCAUTH_KERB4);
703 *tl = txdr_unsigned(verf_len);
704 siz = verf_len;
705 while (siz > 0) {
706 if (M_TRAILINGSPACE(mb) == 0) {
707 MGET(mb2, M_WAIT, MT_DATA);
708 if (siz >= MINCLSIZE)
709 MCLGET(mb2, M_WAIT);
710 mb->m_next = mb2;
711 mb = mb2;
712 mb->m_len = 0;
713 bpos = mtod(mb, caddr_t);
714 }
715 i = min(siz, M_TRAILINGSPACE(mb));
716 bcopy(verf_str, bpos, i);
717 mb->m_len += i;
718 verf_str += i;
719 bpos += i;
720 siz -= i;
721 }
722 if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) {
723 for (i = 0; i < siz; i++)
724 *bpos++ = '\0';
725 mb->m_len += siz;
726 }
727 } else {
728 *tl++ = txdr_unsigned(RPCAUTH_NULL);
729 *tl = 0;
730 }
731 mb->m_next = mrest;
732 mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
733 mreq->m_pkthdr.rcvif = (struct ifnet *)0;
734 *mbp = mb;
735 return (mreq);
736}
737
738/*
739 * copies mbuf chain to the uio scatter/gather list
740 */
741int
742nfsm_mbuftouio(mrep, uiop, siz, dpos)
743 struct mbuf **mrep;
744 register struct uio *uiop;
745 int siz;
746 caddr_t *dpos;
747{
748 register char *mbufcp, *uiocp;
749 register int xfer, left, len;
750 register struct mbuf *mp;
751 long uiosiz, rem;
752 int error = 0;
753
754 mp = *mrep;
755 mbufcp = *dpos;
756 len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
757 rem = nfsm_rndup(siz)-siz;
758 while (siz > 0) {
759 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
760 return (EFBIG);
761 left = uiop->uio_iov->iov_len;
762 uiocp = uiop->uio_iov->iov_base;
763 if (left > siz)
764 left = siz;
765 uiosiz = left;
766 while (left > 0) {
767 while (len == 0) {
768 mp = mp->m_next;
769 if (mp == NULL)
770 return (EBADRPC);
771 mbufcp = mtod(mp, caddr_t);
772 len = mp->m_len;
773 }
774 xfer = (left > len) ? len : left;
775#ifdef notdef
776 /* Not Yet.. */
777 if (uiop->uio_iov->iov_op != NULL)
778 (*(uiop->uio_iov->iov_op))
779 (mbufcp, uiocp, xfer);
780 else
781#endif
782 if (uiop->uio_segflg == UIO_SYSSPACE)
783 bcopy(mbufcp, uiocp, xfer);
784 else
785 copyout(mbufcp, uiocp, xfer);
786 left -= xfer;
787 len -= xfer;
788 mbufcp += xfer;
789 uiocp += xfer;
790 uiop->uio_offset += xfer;
791 uiop->uio_resid -= xfer;
792 }
793 if (uiop->uio_iov->iov_len <= siz) {
794 uiop->uio_iovcnt--;
795 uiop->uio_iov++;
796 } else {
797 uiop->uio_iov->iov_base += uiosiz;
798 uiop->uio_iov->iov_len -= uiosiz;
799 }
800 siz -= uiosiz;
801 }
802 *dpos = mbufcp;
803 *mrep = mp;
804 if (rem > 0) {
805 if (len < rem)
806 error = nfs_adv(mrep, dpos, rem, len);
807 else
808 *dpos += rem;
809 }
810 return (error);
811}
812
813/*
814 * copies a uio scatter/gather list to an mbuf chain...
815 */
816int
817nfsm_uiotombuf(uiop, mq, siz, bpos)
818 register struct uio *uiop;
819 struct mbuf **mq;
820 int siz;
821 caddr_t *bpos;
822{
823 register char *uiocp;
824 register struct mbuf *mp, *mp2;
825 register int xfer, left, mlen;
826 int uiosiz, clflg, rem;
827 char *cp;
828
829 if (siz > MLEN) /* or should it >= MCLBYTES ?? */
830 clflg = 1;
831 else
832 clflg = 0;
833 rem = nfsm_rndup(siz)-siz;
834 mp = mp2 = *mq;
835 while (siz > 0) {
836 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
837 return (EINVAL);
838 left = uiop->uio_iov->iov_len;
839 uiocp = uiop->uio_iov->iov_base;
840 if (left > siz)
841 left = siz;
842 uiosiz = left;
843 while (left > 0) {
844 mlen = M_TRAILINGSPACE(mp);
845 if (mlen == 0) {
846 MGET(mp, M_WAIT, MT_DATA);
847 if (clflg)
848 MCLGET(mp, M_WAIT);
849 mp->m_len = 0;
850 mp2->m_next = mp;
851 mp2 = mp;
852 mlen = M_TRAILINGSPACE(mp);
853 }
854 xfer = (left > mlen) ? mlen : left;
855#ifdef notdef
856 /* Not Yet.. */
857 if (uiop->uio_iov->iov_op != NULL)
858 (*(uiop->uio_iov->iov_op))
859 (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
860 else
861#endif
862 if (uiop->uio_segflg == UIO_SYSSPACE)
863 bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
864 else
865 copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
866 mp->m_len += xfer;
867 left -= xfer;
868 uiocp += xfer;
869 uiop->uio_offset += xfer;
870 uiop->uio_resid -= xfer;
871 }
872 if (uiop->uio_iov->iov_len <= siz) {
873 uiop->uio_iovcnt--;
874 uiop->uio_iov++;
875 } else {
876 uiop->uio_iov->iov_base += uiosiz;
877 uiop->uio_iov->iov_len -= uiosiz;
878 }
879 siz -= uiosiz;
880 }
881 if (rem > 0) {
882 if (rem > M_TRAILINGSPACE(mp)) {
883 MGET(mp, M_WAIT, MT_DATA);
884 mp->m_len = 0;
885 mp2->m_next = mp;
886 }
887 cp = mtod(mp, caddr_t)+mp->m_len;
888 for (left = 0; left < rem; left++)
889 *cp++ = '\0';
890 mp->m_len += rem;
891 *bpos = cp;
892 } else
893 *bpos = mtod(mp, caddr_t)+mp->m_len;
894 *mq = mp;
895 return (0);
896}
897
898/*
899 * Help break down an mbuf chain by setting the first siz bytes contiguous
900 * pointed to by returned val.
901 * This is used by the macros nfsm_dissect and nfsm_dissecton for tough
902 * cases. (The macros use the vars. dpos and dpos2)
903 */
904int
905nfsm_disct(mdp, dposp, siz, left, cp2)
906 struct mbuf **mdp;
907 caddr_t *dposp;
908 int siz;
909 int left;
910 caddr_t *cp2;
911{
912 register struct mbuf *mp, *mp2;
913 register int siz2, xfer;
914 register caddr_t p;
915
916 mp = *mdp;
917 while (left == 0) {
918 *mdp = mp = mp->m_next;
919 if (mp == NULL)
920 return (EBADRPC);
921 left = mp->m_len;
922 *dposp = mtod(mp, caddr_t);
923 }
924 if (left >= siz) {
925 *cp2 = *dposp;
926 *dposp += siz;
927 } else if (mp->m_next == NULL) {
928 return (EBADRPC);
929 } else if (siz > MHLEN) {
930 panic("nfs S too big");
931 } else {
932 MGET(mp2, M_WAIT, MT_DATA);
933 mp2->m_next = mp->m_next;
934 mp->m_next = mp2;
935 mp->m_len -= left;
936 mp = mp2;
937 *cp2 = p = mtod(mp, caddr_t);
938 bcopy(*dposp, p, left); /* Copy what was left */
939 siz2 = siz-left;
940 p += left;
941 mp2 = mp->m_next;
942 /* Loop around copying up the siz2 bytes */
943 while (siz2 > 0) {
944 if (mp2 == NULL)
945 return (EBADRPC);
946 xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
947 if (xfer > 0) {
948 bcopy(mtod(mp2, caddr_t), p, xfer);
949 NFSMADV(mp2, xfer);
950 mp2->m_len -= xfer;
951 p += xfer;
952 siz2 -= xfer;
953 }
954 if (siz2 > 0)
955 mp2 = mp2->m_next;
956 }
957 mp->m_len = siz;
958 *mdp = mp2;
959 *dposp = mtod(mp2, caddr_t);
960 }
961 return (0);
962}
963
964/*
965 * Advance the position in the mbuf chain.
966 */
967int
968nfs_adv(mdp, dposp, offs, left)
969 struct mbuf **mdp;
970 caddr_t *dposp;
971 int offs;
972 int left;
973{
974 register struct mbuf *m;
975 register int s;
976
977 m = *mdp;
978 s = left;
979 while (s < offs) {
980 offs -= s;
981 m = m->m_next;
982 if (m == NULL)
983 return (EBADRPC);
984 s = m->m_len;
985 }
986 *mdp = m;
987 *dposp = mtod(m, caddr_t)+offs;
988 return (0);
989}
990
991/*
992 * Copy a string into mbufs for the hard cases...
993 */
994int
995nfsm_strtmbuf(mb, bpos, cp, siz)
996 struct mbuf **mb;
997 char **bpos;
998 char *cp;
999 long siz;
1000{
1001 register struct mbuf *m1 = 0, *m2;
1002 long left, xfer, len, tlen;
1003 u_long *tl;
1004 int putsize;
1005
1006 putsize = 1;
1007 m2 = *mb;
1008 left = M_TRAILINGSPACE(m2);
1009 if (left > 0) {
1010 tl = ((u_long *)(*bpos));
1011 *tl++ = txdr_unsigned(siz);
1012 putsize = 0;
1013 left -= NFSX_UNSIGNED;
1014 m2->m_len += NFSX_UNSIGNED;
1015 if (left > 0) {
1016 bcopy(cp, (caddr_t) tl, left);
1017 siz -= left;
1018 cp += left;
1019 m2->m_len += left;
1020 left = 0;
1021 }
1022 }
1023 /* Loop around adding mbufs */
1024 while (siz > 0) {
1025 MGET(m1, M_WAIT, MT_DATA);
1026 if (siz > MLEN)
1027 MCLGET(m1, M_WAIT);
1028 m1->m_len = NFSMSIZ(m1);
1029 m2->m_next = m1;
1030 m2 = m1;
1031 tl = mtod(m1, u_long *);
1032 tlen = 0;
1033 if (putsize) {
1034 *tl++ = txdr_unsigned(siz);
1035 m1->m_len -= NFSX_UNSIGNED;
1036 tlen = NFSX_UNSIGNED;
1037 putsize = 0;
1038 }
1039 if (siz < m1->m_len) {
1040 len = nfsm_rndup(siz);
1041 xfer = siz;
1042 if (xfer < len)
1043 *(tl+(xfer>>2)) = 0;
1044 } else {
1045 xfer = len = m1->m_len;
1046 }
1047 bcopy(cp, (caddr_t) tl, xfer);
1048 m1->m_len = len+tlen;
1049 siz -= xfer;
1050 cp += xfer;
1051 }
1052 *mb = m1;
1053 *bpos = mtod(m1, caddr_t)+m1->m_len;
1054 return (0);
1055}
1056
1057/*
1058 * Called once to initialize data structures...
1059 */
1060int
1061nfs_init()
1062{
1063 register int i;
1064
1065 /*
1066 * Check to see if major data structures haven't bloated.
1067 */
1068 if (sizeof (struct nfsnode) > NFS_NODEALLOC) {
1069 printf("struct nfsnode bloated (> %dbytes)\n", NFS_NODEALLOC);
1070 printf("Try reducing NFS_SMALLFH\n");
1071 }
1072 if (sizeof (struct nfsmount) > NFS_MNTALLOC) {
1073 printf("struct nfsmount bloated (> %dbytes)\n", NFS_MNTALLOC);
1074 printf("Try reducing NFS_MUIDHASHSIZ\n");
1075 }
1076 if (sizeof (struct nfssvc_sock) > NFS_SVCALLOC) {
1077 printf("struct nfssvc_sock bloated (> %dbytes)\n",NFS_SVCALLOC);
1078 printf("Try reducing NFS_UIDHASHSIZ\n");
1079 }
1080 if (sizeof (struct nfsuid) > NFS_UIDALLOC) {
1081 printf("struct nfsuid bloated (> %dbytes)\n",NFS_UIDALLOC);
1082 printf("Try unionizing the nu_nickname and nu_flag fields\n");
1083 }
1084 nfsrtt.pos = 0;
1085 rpc_vers = txdr_unsigned(RPC_VER2);
1086 rpc_call = txdr_unsigned(RPC_CALL);
1087 rpc_reply = txdr_unsigned(RPC_REPLY);
1088 rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
1089 rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
1090 rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
1091 rpc_autherr = txdr_unsigned(RPC_AUTHERR);
1092 rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
1093 rpc_auth_kerb = txdr_unsigned(RPCAUTH_KERB4);
1094 nfs_prog = txdr_unsigned(NFS_PROG);
1095 nqnfs_prog = txdr_unsigned(NQNFS_PROG);
1096 nfs_true = txdr_unsigned(TRUE);
1097 nfs_false = txdr_unsigned(FALSE);
1098 nfs_xdrneg1 = txdr_unsigned(-1);
1099 nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
1100 if (nfs_ticks < 1)
1101 nfs_ticks = 1;
1102 /* Ensure async daemons disabled */
1103 for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1104 nfs_iodwant[i] = (struct proc *)0;
1105 TAILQ_INIT(&nfs_bufq);
1106 nfs_nhinit(); /* Init the nfsnode table */
1107 nfsrv_init(0); /* Init server data structures */
1108 nfsrv_initcache(); /* Init the server request cache */
1109
1110 /*
1111 * Initialize the nqnfs server stuff.
1112 */
1113 if (nqnfsstarttime == 0) {
1114 nqnfsstarttime = boottime.tv_sec + nqsrv_maxlease
1115 + nqsrv_clockskew + nqsrv_writeslack;
1116 NQLOADNOVRAM(nqnfsstarttime);
1117 CIRCLEQ_INIT(&nqtimerhead);
1118 nqfhhashtbl = hashinit(NQLCHSZ, M_NQLEASE, &nqfhhash);
1119 }
1120
1121 /*
1122 * Initialize reply list and start timer
1123 */
1124 TAILQ_INIT(&nfs_reqq);
1125 nfs_timer(0);
1126
1127#ifdef __FreeBSD__
1128 /*
1129 * Set up lease_check and lease_updatetime so that other parts
1130 * of the system can call us, if we are loadable.
1131 */
1132 lease_check = nfs_lease_check;
1133 lease_updatetime = nfs_lease_updatetime;
1134 vfsconf[MOUNT_NFS]->vfc_refcount++; /* make us non-unloadable */
1135#ifdef VFS_LKM
1136 sysent[SYS_nfssvc].sy_narg = 2;
1137 sysent[SYS_nfssvc].sy_call = nfssvc;
1138 sysent[SYS_getfh].sy_narg = 2;
1139 sysent[SYS_getfh].sy_call = getfh;
1140#endif
1141#endif
1142
1143 return (0);
1144}
1145
1146/*
1147 * Attribute cache routines.
1148 * nfs_loadattrcache() - loads or updates the cache contents from attributes
1149 * that are on the mbuf list
1150 * nfs_getattrcache() - returns valid attributes if found in cache, returns
1151 * error otherwise
1152 */
1153
1154/*
1155 * Load the attribute cache (that lives in the nfsnode entry) with
1156 * the values on the mbuf list and
1157 * Iff vap not NULL
1158 * copy the attributes to *vaper
1159 */
1160int
1161nfs_loadattrcache(vpp, mdp, dposp, vaper)
1162 struct vnode **vpp;
1163 struct mbuf **mdp;
1164 caddr_t *dposp;
1165 struct vattr *vaper;
1166{
1167 register struct vnode *vp = *vpp;
1168 register struct vattr *vap;
1169 register struct nfs_fattr *fp;
1170 register struct nfsnode *np;
1171 register struct nfsnodehashhead *nhpp;
1172 register long t1;
1173 caddr_t cp2;
1174 int error = 0, rdev;
1175 struct mbuf *md;
1176 enum vtype vtyp;
1177 u_short vmode;
1178 struct timespec mtime;
1179 struct vnode *nvp;
1180 quad_t tval;
1181 int v3 = NFS_ISV3(vp);
1182
1183 md = *mdp;
1184 t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
1185 if (error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2))
1186 return (error);
1187 fp = (struct nfs_fattr *)cp2;
1188 if (v3) {
1189 vtyp = nfsv3tov_type(fp->fa_type);
1190 vmode = fxdr_unsigned(u_short, fp->fa_mode);
1191 rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1),
1192 fxdr_unsigned(u_char, fp->fa3_rdev.specdata2));
1193 fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
1194 } else {
1195 vtyp = nfsv2tov_type(fp->fa_type);
1196 vmode = fxdr_unsigned(u_short, fp->fa_mode);
1197 /*
1198 * XXX
1199 *
1200 * The duplicate information returned in fa_type and fa_mode
1201 * is an ambiguity in the NFS version 2 protocol.
1202 *
1203 * VREG should be taken literally as a regular file. If a
1204 * server intents to return some type information differently
1205 * in the upper bits of the mode field (e.g. for sockets, or
1206 * FIFOs), NFSv2 mandates fa_type to be VNON. Anyway, we
1207 * leave the examination of the mode bits even in the VREG
1208 * case to avoid breakage for bogus servers, but we make sure
1209 * that there are actually type bits set in the upper part of
1210 * fa_mode (and failing that, trust the va_type field).
1211 *
1212 * NFSv3 cleared the issue, and requires fa_mode to not
1213 * contain any type information (while also introduing sockets
1214 * and FIFOs for fa_type).
1215 */
1216 if (vtyp == VNON || (vtyp == VREG && (vmode & S_IFMT) != 0))
1217 vtyp = IFTOVT(vmode);
1218 rdev = fxdr_unsigned(long, fp->fa2_rdev);
1219 fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
1220
1221 /*
1222 * Really ugly NFSv2 kludge.
1223 */
1224 if (vtyp == VCHR && rdev == 0xffffffff)
1225 vtyp = VFIFO;
1226 }
1227
1228 /*
1229 * If v_type == VNON it is a new node, so fill in the v_type,
1230 * n_mtime fields. Check to see if it represents a special
1231 * device, and if so, check for a possible alias. Once the
1232 * correct vnode has been obtained, fill in the rest of the
1233 * information.
1234 */
1235 np = VTONFS(vp);
1236 if (vp->v_type == VNON) {
1237 /*
1238 * If we had a lock and it turns out that the vnode
1239 * is an object which we don't want to lock (e.g. VDIR)
1240 * to avoid nasty hanging problems on a server crash,
1241 * then release it here.
1242 */
1243 if (vtyp != VREG && VOP_ISLOCKED(vp))
1244 VOP_UNLOCK(vp);
1245 vp->v_type = vtyp;
1246 if (vp->v_type == VFIFO) {
1247 vp->v_op = fifo_nfsv2nodeop_p;
1248 }
1249 if (vp->v_type == VCHR || vp->v_type == VBLK) {
1250 vp->v_op = spec_nfsv2nodeop_p;
1251 nvp = checkalias(vp, (dev_t)rdev, vp->v_mount);
1252 if (nvp) {
1253 /*
1254 * Discard unneeded vnode, but save its nfsnode.
1255 */
1256 LIST_REMOVE(np, n_hash);
1257 nvp->v_data = vp->v_data;
1258 vp->v_data = NULL;
1259 vp->v_op = spec_vnodeop_p;
1260 vrele(vp);
1261 vgone(vp);
1262 /*
1263 * Reinitialize aliased node.
1264 */
1265 np->n_vnode = nvp;
1266 nhpp = NFSNOHASH(nfs_hash(np->n_fhp, np->n_fhsize));
1267 LIST_INSERT_HEAD(nhpp, np, n_hash);
1268 *vpp = vp = nvp;
1269 }
1270 }
1271 np->n_mtime = mtime.ts_sec;
1272 }
1273 vap = &np->n_vattr;
1274 vap->va_type = vtyp;
1275 vap->va_mode = (vmode & 07777);
1276 vap->va_rdev = (dev_t)rdev;
1277 vap->va_mtime = mtime;
1278 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
1279 if (v3) {
1280 vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
1281 vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
1282 vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
1283 fxdr_hyper(&fp->fa3_size, &vap->va_size);
1284 vap->va_blocksize = NFS_FABLKSIZE;
1285 fxdr_hyper(&fp->fa3_used, &vap->va_bytes);
1286 vap->va_fileid = fxdr_unsigned(int, fp->fa3_fileid.nfsuquad[1]);
1287 fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
1288 fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
1289 vap->va_flags = 0;
1290 vap->va_filerev = 0;
1291 } else {
1292 vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
1293 vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
1294 vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
1295 vap->va_size = fxdr_unsigned(u_long, fp->fa2_size);
1296 vap->va_blocksize = fxdr_unsigned(long, fp->fa2_blocksize);
1297 vap->va_bytes = fxdr_unsigned(long, fp->fa2_blocks) * NFS_FABLKSIZE;
1298 vap->va_fileid = fxdr_unsigned(long, fp->fa2_fileid);
1299 fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
1300 vap->va_flags = 0;
1301 vap->va_ctime.ts_sec = fxdr_unsigned(long, fp->fa2_ctime.nfsv2_sec);
1302 vap->va_ctime.ts_nsec = 0;
1303 vap->va_gen = fxdr_unsigned(u_long, fp->fa2_ctime.nfsv2_usec);
1304 vap->va_filerev = 0;
1305 }
1306 if (vap->va_size != np->n_size) {
1307 if (vap->va_type == VREG) {
1308 if (np->n_flag & NMODIFIED) {
1309 if (vap->va_size < np->n_size)
1310 vap->va_size = np->n_size;
1311 else
1312 np->n_size = vap->va_size;
1313 } else
1314 np->n_size = vap->va_size;
1315 vnode_pager_setsize(vp, (u_long)np->n_size);
1316 } else
1317 np->n_size = vap->va_size;
1318 }
1319 np->n_attrstamp = time.tv_sec;
1320 if (vaper != NULL) {
1321 bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
1322 if (np->n_flag & NCHG) {
1323 if (np->n_flag & NACC)
1324 vaper->va_atime = np->n_atim;
1325 if (np->n_flag & NUPD)
1326 vaper->va_mtime = np->n_mtim;
1327 }
1328 }
1329 return (0);
1330}
1331
1332/*
1333 * Check the time stamp
1334 * If the cache is valid, copy contents to *vap and return 0
1335 * otherwise return an error
1336 */
1337int
1338nfs_getattrcache(vp, vaper)
1339 register struct vnode *vp;
1340 struct vattr *vaper;
1341{
1342 register struct nfsnode *np = VTONFS(vp);
1343 register struct vattr *vap;
1344
1345 if ((time.tv_sec - np->n_attrstamp) >= NFS_ATTRTIMEO(np)) {
1346 nfsstats.attrcache_misses++;
1347 return (ENOENT);
1348 }
1349 nfsstats.attrcache_hits++;
1350 vap = &np->n_vattr;
1351 if (vap->va_size != np->n_size) {
1352 if (vap->va_type == VREG) {
1353 if (np->n_flag & NMODIFIED) {
1354 if (vap->va_size < np->n_size)
1355 vap->va_size = np->n_size;
1356 else
1357 np->n_size = vap->va_size;
1358 } else
1359 np->n_size = vap->va_size;
1360 vnode_pager_setsize(vp, (u_long)np->n_size);
1361 } else
1362 np->n_size = vap->va_size;
1363 }
1364 bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));
1365 if (np->n_flag & NCHG) {
1366 if (np->n_flag & NACC)
1367 vaper->va_atime = np->n_atim;
1368 if (np->n_flag & NUPD)
1369 vaper->va_mtime = np->n_mtim;
1370 }
1371 return (0);
1372}
1373
1374/*
1375 * Set up nameidata for a lookup() call and do it
1376 */
1377int
1378nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
1379 register struct nameidata *ndp;
1380 fhandle_t *fhp;
1381 int len;
1382 struct nfssvc_sock *slp;
1383 struct mbuf *nam;
1384 struct mbuf **mdp;
1385 caddr_t *dposp;
1386 struct vnode **retdirp;
1387 struct proc *p;
1388 int kerbflag;
1389{
1390 register int i, rem;
1391 register struct mbuf *md;
1392 register char *fromcp, *tocp;
1393 struct vnode *dp;
1394 int error, rdonly;
1395 struct componentname *cnp = &ndp->ni_cnd;
1396
1397 *retdirp = (struct vnode *)0;
1398 MALLOC(cnp->cn_pnbuf, char *, len + 1, M_NAMEI, M_WAITOK);
1399 /*
1400 * Copy the name from the mbuf list to ndp->ni_pnbuf
1401 * and set the various ndp fields appropriately.
1402 */
1403 fromcp = *dposp;
1404 tocp = cnp->cn_pnbuf;
1405 md = *mdp;
1406 rem = mtod(md, caddr_t) + md->m_len - fromcp;
1407 cnp->cn_hash = 0;
1408 for (i = 0; i < len; i++) {
1409 while (rem == 0) {
1410 md = md->m_next;
1411 if (md == NULL) {
1412 error = EBADRPC;
1413 goto out;
1414 }
1415 fromcp = mtod(md, caddr_t);
1416 rem = md->m_len;
1417 }
1418 if (*fromcp == '\0' || *fromcp == '/') {
1419 error = EACCES;
1420 goto out;
1421 }
1422 cnp->cn_hash += (unsigned char)*fromcp;
1423 *tocp++ = *fromcp++;
1424 rem--;
1425 }
1426 *tocp = '\0';
1427 *mdp = md;
1428 *dposp = fromcp;
1429 len = nfsm_rndup(len)-len;
1430 if (len > 0) {
1431 if (rem >= len)
1432 *dposp += len;
1433 else if (error = nfs_adv(mdp, dposp, len, rem))
1434 goto out;
1435 }
1436 ndp->ni_pathlen = tocp - cnp->cn_pnbuf;
1437 cnp->cn_nameptr = cnp->cn_pnbuf;
1438 /*
1439 * Extract and set starting directory.
1440 */
1441 if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
1442 nam, &rdonly, kerbflag))
1443 goto out;
1444 if (dp->v_type != VDIR) {
1445 nfsrv_vrele(dp);
1446 error = ENOTDIR;
1447 goto out;
1448 }
1449 VREF(dp);
1450 *retdirp = dp;
1451 ndp->ni_startdir = dp;
1452 if (rdonly)
1453 cnp->cn_flags |= (NOCROSSMOUNT | RDONLY);
1454 else
1455 cnp->cn_flags |= NOCROSSMOUNT;
1456 /*
1457 * And call lookup() to do the real work
1458 */
1459 cnp->cn_proc = p;
1460 if (error = lookup(ndp))
1461 goto out;
1462 /*
1463 * Check for encountering a symbolic link
1464 */
1465 if (cnp->cn_flags & ISSYMLINK) {
1466 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
1467 vput(ndp->ni_dvp);
1468 else
1469 vrele(ndp->ni_dvp);
1470 vput(ndp->ni_vp);
1471 ndp->ni_vp = NULL;
1472 error = EINVAL;
1473 goto out;
1474 }
1475
1476 nfsrv_vmio(ndp->ni_vp);
1477
1478 /*
1479 * Check for saved name request
1480 */
1481 if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
1482 cnp->cn_flags |= HASBUF;
1483 return (0);
1484 }
1485out:
1486 FREE(cnp->cn_pnbuf, M_NAMEI);
1487 return (error);
1488}
1489
1490/*
1491 * A fiddled version of m_adj() that ensures null fill to a long
1492 * boundary and only trims off the back end
1493 */
1494void
1495nfsm_adj(mp, len, nul)
1496 struct mbuf *mp;
1497 register int len;
1498 int nul;
1499{
1500 register struct mbuf *m;
1501 register int count, i;
1502 register char *cp;
1503
1504 /*
1505 * Trim from tail. Scan the mbuf chain,
1506 * calculating its length and finding the last mbuf.
1507 * If the adjustment only affects this mbuf, then just
1508 * adjust and return. Otherwise, rescan and truncate
1509 * after the remaining size.
1510 */
1511 count = 0;
1512 m = mp;
1513 for (;;) {
1514 count += m->m_len;
1515 if (m->m_next == (struct mbuf *)0)
1516 break;
1517 m = m->m_next;
1518 }
1519 if (m->m_len > len) {
1520 m->m_len -= len;
1521 if (nul > 0) {
1522 cp = mtod(m, caddr_t)+m->m_len-nul;
1523 for (i = 0; i < nul; i++)
1524 *cp++ = '\0';
1525 }
1526 return;
1527 }
1528 count -= len;
1529 if (count < 0)
1530 count = 0;
1531 /*
1532 * Correct length for chain is "count".
1533 * Find the mbuf with last data, adjust its length,
1534 * and toss data from remaining mbufs on chain.
1535 */
1536 for (m = mp; m; m = m->m_next) {
1537 if (m->m_len >= count) {
1538 m->m_len = count;
1539 if (nul > 0) {
1540 cp = mtod(m, caddr_t)+m->m_len-nul;
1541 for (i = 0; i < nul; i++)
1542 *cp++ = '\0';
1543 }
1544 break;
1545 }
1546 count -= m->m_len;
1547 }
1548 for (m = m->m_next;m;m = m->m_next)
1549 m->m_len = 0;
1550}
1551
1552/*
1553 * Make these functions instead of macros, so that the kernel text size
1554 * doesn't get too big...
1555 */
1556void
1557nfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp)
1558 struct nfsrv_descript *nfsd;
1559 int before_ret;
1560 register struct vattr *before_vap;
1561 int after_ret;
1562 struct vattr *after_vap;
1563 struct mbuf **mbp;
1564 char **bposp;
1565{
1566 register struct mbuf *mb = *mbp, *mb2;
1567 register char *bpos = *bposp;
1568 register u_long *tl;
1569
1570 if (before_ret) {
1571 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1572 *tl = nfs_false;
1573 } else {
1574 nfsm_build(tl, u_long *, 7 * NFSX_UNSIGNED);
1575 *tl++ = nfs_true;
1576 txdr_hyper(&(before_vap->va_size), tl);
1577 tl += 2;
1578 txdr_nfsv3time(&(before_vap->va_mtime), tl);
1579 tl += 2;
1580 txdr_nfsv3time(&(before_vap->va_ctime), tl);
1581 }
1582 *bposp = bpos;
1583 *mbp = mb;
1584 nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
1585}
1586
1587void
1588nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp)
1589 struct nfsrv_descript *nfsd;
1590 int after_ret;
1591 struct vattr *after_vap;
1592 struct mbuf **mbp;
1593 char **bposp;
1594{
1595 register struct mbuf *mb = *mbp, *mb2;
1596 register char *bpos = *bposp;
1597 register u_long *tl;
1598 register struct nfs_fattr *fp;
1599
1600 if (after_ret) {
1601 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1602 *tl = nfs_false;
1603 } else {
1604 nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FATTR);
1605 *tl++ = nfs_true;
1606 fp = (struct nfs_fattr *)tl;
1607 nfsm_srvfattr(nfsd, after_vap, fp);
1608 }
1609 *mbp = mb;
1610 *bposp = bpos;
1611}
1612
1613void
1614nfsm_srvfattr(nfsd, vap, fp)
1615 register struct nfsrv_descript *nfsd;
1616 register struct vattr *vap;
1617 register struct nfs_fattr *fp;
1618{
1619
1620 fp->fa_nlink = txdr_unsigned(vap->va_nlink);
1621 fp->fa_uid = txdr_unsigned(vap->va_uid);
1622 fp->fa_gid = txdr_unsigned(vap->va_gid);
1623 if (nfsd->nd_flag & ND_NFSV3) {
1624 fp->fa_type = vtonfsv3_type(vap->va_type);
1625 fp->fa_mode = vtonfsv3_mode(vap->va_mode);
1626 txdr_hyper(&vap->va_size, &fp->fa3_size);
1627 txdr_hyper(&vap->va_bytes, &fp->fa3_used);
1628 fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev));
1629 fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev));
1630 fp->fa3_fsid.nfsuquad[0] = 0;
1631 fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
1632 fp->fa3_fileid.nfsuquad[0] = 0;
1633 fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
1634 txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
1635 txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
1636 txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
1637 } else {
1638 fp->fa_type = vtonfsv2_type(vap->va_type);
1639 fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1640 fp->fa2_size = txdr_unsigned(vap->va_size);
1641 fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
1642 if (vap->va_type == VFIFO)
1643 fp->fa2_rdev = 0xffffffff;
1644 else
1645 fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
1646 fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
1647 fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
1648 fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
1649 txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
1650 txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
1651 txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
1652 }
1653}
1654
1655/*
1656 * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
1657 * - look up fsid in mount list (if not found ret error)
1658 * - get vp and export rights by calling VFS_FHTOVP()
1659 * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
1660 * - if not lockflag unlock it with VOP_UNLOCK()
1661 */
1662int
1663nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
1664 fhandle_t *fhp;
1665 int lockflag;
1666 struct vnode **vpp;
1667 struct ucred *cred;
1668 struct nfssvc_sock *slp;
1669 struct mbuf *nam;
1670 int *rdonlyp;
1671 int kerbflag;
1672{
1673 register struct mount *mp;
1674 register struct nfsuid *uidp;
1675 register int i;
1676 struct ucred *credanon;
1677 int error, exflags;
1678
1679 *vpp = (struct vnode *)0;
1680 mp = getvfs(&fhp->fh_fsid);
1681 if (!mp)
1682 return (ESTALE);
1683 error = VFS_FHTOVP(mp, &fhp->fh_fid, nam, vpp, &exflags, &credanon);
1684 if (error)
1685 return (error);
1686 /*
1687 * Check/setup credentials.
1688 */
1689 if (exflags & MNT_EXKERB) {
1690 if (!kerbflag) {
1691 vput(*vpp);
1692 return (NFSERR_AUTHERR | AUTH_TOOWEAK);
1693 }
1694 } else if (kerbflag) {
1695 vput(*vpp);
1696 return (NFSERR_AUTHERR | AUTH_TOOWEAK);
1697 } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
1698 cred->cr_uid = credanon->cr_uid;
1699 for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
1700 cred->cr_groups[i] = credanon->cr_groups[i];
1701 cred->cr_ngroups = i;
1702 }
1703 if (exflags & MNT_EXRDONLY)
1704 *rdonlyp = 1;
1705 else
1706 *rdonlyp = 0;
1707
1708 nfsrv_vmio(*vpp);
1709
1710 if (!lockflag)
1711 VOP_UNLOCK(*vpp);
1712 return (0);
1713}
1714
1715/*
1716 * This function compares two net addresses by family and returns TRUE
1717 * if they are the same host.
1718 * If there is any doubt, return FALSE.
1719 * The AF_INET family is handled as a special case so that address mbufs
1720 * don't need to be saved to store "struct in_addr", which is only 4 bytes.
1721 */
1722int
1723netaddr_match(family, haddr, nam)
1724 int family;
1725 union nethostaddr *haddr;
1726 struct mbuf *nam;
1727{
1728 register struct sockaddr_in *inetaddr;
1729
1730 switch (family) {
1731 case AF_INET:
1732 inetaddr = mtod(nam, struct sockaddr_in *);
1733 if (inetaddr->sin_family == AF_INET &&
1734 inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
1735 return (1);
1736 break;
1737#ifdef ISO
1738 case AF_ISO:
1739 {
1740 register struct sockaddr_iso *isoaddr1, *isoaddr2;
1741
1742 isoaddr1 = mtod(nam, struct sockaddr_iso *);
1743 isoaddr2 = mtod(haddr->had_nam, struct sockaddr_iso *);
1744 if (isoaddr1->siso_family == AF_ISO &&
1745 isoaddr1->siso_nlen > 0 &&
1746 isoaddr1->siso_nlen == isoaddr2->siso_nlen &&
1747 SAME_ISOADDR(isoaddr1, isoaddr2))
1748 return (1);
1749 break;
1750 }
1751#endif /* ISO */
1752 default:
1753 break;
1754 };
1755 return (0);
1756}
1757
1758static nfsuint64 nfs_nullcookie = { 0, 0 };
1759/*
1760 * This function finds the directory cookie that corresponds to the
1761 * logical byte offset given.
1762 */
1763nfsuint64 *
1764nfs_getcookie(np, off, add)
1765 register struct nfsnode *np;
1766 off_t off;
1767 int add;
1768{
1769 register struct nfsdmap *dp, *dp2;
1770 register int pos;
1771
1772 pos = off / NFS_DIRBLKSIZ;
1773 if (pos == 0) {
1774#ifdef DIAGNOSTIC
1775 if (add)
1776 panic("nfs getcookie add at 0");
1777#endif
1778 return (&nfs_nullcookie);
1779 }
1780 pos--;
1781 dp = np->n_cookies.lh_first;
1782 if (!dp) {
1783 if (add) {
1784 MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
1785 M_NFSDIROFF, M_WAITOK);
1786 dp->ndm_eocookie = 0;
1787 LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
1788 } else
1789 return ((nfsuint64 *)0);
1790 }
1791 while (pos >= NFSNUMCOOKIES) {
1792 pos -= NFSNUMCOOKIES;
1793 if (dp->ndm_list.le_next) {
1794 if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
1795 pos >= dp->ndm_eocookie)
1796 return ((nfsuint64 *)0);
1797 dp = dp->ndm_list.le_next;
1798 } else if (add) {
1799 MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
1800 M_NFSDIROFF, M_WAITOK);
1801 dp2->ndm_eocookie = 0;
1802 LIST_INSERT_AFTER(dp, dp2, ndm_list);
1803 dp = dp2;
1804 } else
1805 return ((nfsuint64 *)0);
1806 }
1807 if (pos >= dp->ndm_eocookie) {
1808 if (add)
1809 dp->ndm_eocookie = pos + 1;
1810 else
1811 return ((nfsuint64 *)0);
1812 }
1813 return (&dp->ndm_cookies[pos]);
1814}
1815
1816/*
1817 * Invalidate cached directory information, except for the actual directory
1818 * blocks (which are invalidated separately).
1819 * Done mainly to avoid the use of stale offset cookies.
1820 */
1821void
1822nfs_invaldir(vp)
1823 register struct vnode *vp;
1824{
1825 register struct nfsnode *np = VTONFS(vp);
1826
1827#ifdef DIAGNOSTIC
1828 if (vp->v_type != VDIR)
1829 panic("nfs: invaldir not dir");
1830#endif
1831 np->n_direofoffset = 0;
1832 np->n_cookieverf.nfsuquad[0] = 0;
1833 np->n_cookieverf.nfsuquad[1] = 0;
1834 if (np->n_cookies.lh_first)
1835 np->n_cookies.lh_first->ndm_eocookie = 0;
1836}
1837
1838/*
1839 * The write verifier has changed (probably due to a server reboot), so all
1840 * B_NEEDCOMMIT blocks will have to be written again. Since they are on the
1841 * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT
1842 * flag. Once done the new write verifier can be set for the mount point.
1843 */
1844void
1845nfs_clearcommit(mp)
1846 struct mount *mp;
1847{
1848 register struct vnode *vp, *nvp;
1849 register struct buf *bp, *nbp;
1850 int s;
1851
1852 s = splbio();
1853loop:
1854 for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
1855 if (vp->v_mount != mp) /* Paranoia */
1856 goto loop;
1857 nvp = vp->v_mntvnodes.le_next;
1858 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
1859 nbp = bp->b_vnbufs.le_next;
1860 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
1861 == (B_DELWRI | B_NEEDCOMMIT))
1862 bp->b_flags &= ~B_NEEDCOMMIT;
1863 }
1864 }
1865 splx(s);
1866}
1867
1868/*
1869 * Map errnos to NFS error numbers. For Version 3 also filter out error
1870 * numbers not specified for the associated procedure.
1871 */
1872int
1873nfsrv_errmap(nd, err)
1874 struct nfsrv_descript *nd;
1875 register int err;
1876{
1877 register short *defaulterrp, *errp;
1878
1879 if (nd->nd_flag & ND_NFSV3) {
1880 if (nd->nd_procnum <= NFSPROC_COMMIT) {
1881 errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
1882 while (*++errp) {
1883 if (*errp == err)
1884 return (err);
1885 else if (*errp > err)
1886 break;
1887 }
1888 return ((int)*defaulterrp);
1889 } else
1890 return (err & 0xffff);
1891 }
1892 if (err <= ELAST)
1893 return ((int)nfsrv_v2errmap[err - 1]);
1894 return (NFSERR_IO);
1895}
1896
1897int
1898nfsrv_vmio(struct vnode *vp) {
1899 vm_object_t object;
1901 vm_pager_t pager;
1902
1903 if ((vp == NULL) || (vp->v_type != VREG))
1904 return 1;
1905
1906retry:
1907 if ((vp->v_flag & VVMIO) == 0) {
1908 struct vattr vat;
1909 struct proc *p = curproc;
1910
1911 if (VOP_GETATTR(vp, &vat, p->p_ucred, p) != 0)
1912 panic("nfsrv_vmio: VOP_GETATTR failed");
1913
1914 if (vnode_pager_alloc(vp, vat.va_size, 0, 0) == NULL)
1915 panic("nfsrv_vmio: vnode_pager_alloc failed");
1916
1917 vp->v_flag |= VVMIO;
1918 } else {
1919 if ((object = vp->v_object) &&
1920 (object->flags & OBJ_DEAD)) {
1921 tsleep(object, PVM, "nfdead", 0);
1922 goto retry;
1923 }
1924 if (!object)
1925 panic("nfsrv_vmio: VMIO object missing");
1900
1901 if ((vp == NULL) || (vp->v_type != VREG))
1902 return 1;
1903
1904retry:
1905 if ((vp->v_flag & VVMIO) == 0) {
1906 struct vattr vat;
1907 struct proc *p = curproc;
1908
1909 if (VOP_GETATTR(vp, &vat, p->p_ucred, p) != 0)
1910 panic("nfsrv_vmio: VOP_GETATTR failed");
1911
1912 if (vnode_pager_alloc(vp, vat.va_size, 0, 0) == NULL)
1913 panic("nfsrv_vmio: vnode_pager_alloc failed");
1914
1915 vp->v_flag |= VVMIO;
1916 } else {
1917 if ((object = vp->v_object) &&
1918 (object->flags & OBJ_DEAD)) {
1919 tsleep(object, PVM, "nfdead", 0);
1920 goto retry;
1921 }
1922 if (!object)
1923 panic("nfsrv_vmio: VMIO object missing");
1926 pager = object->pager;
1927 if (!pager)
1928 panic("nfsrv_vmio: VMIO pager missing");
1929 (void) vm_object_lookup(pager);
1924 vm_object_reference(object);
1930 }
1931 return 0;
1932}
1933int
1934nfsrv_vput(struct vnode *vp) {
1935 if ((vp->v_flag & VVMIO) && vp->v_object) {
1936 vput(vp);
1937 vm_object_deallocate(vp->v_object);
1938 } else {
1939 vput(vp);
1940 }
1941 return 0;
1942}
1943int
1944nfsrv_vrele(struct vnode *vp) {
1945 if ((vp->v_flag & VVMIO) && vp->v_object) {
1946 vrele(vp);
1947 vm_object_deallocate(vp->v_object);
1948 } else {
1949 vrele(vp);
1950 }
1951 return 0;
1952}
1925 }
1926 return 0;
1927}
1928int
1929nfsrv_vput(struct vnode *vp) {
1930 if ((vp->v_flag & VVMIO) && vp->v_object) {
1931 vput(vp);
1932 vm_object_deallocate(vp->v_object);
1933 } else {
1934 vput(vp);
1935 }
1936 return 0;
1937}
1938int
1939nfsrv_vrele(struct vnode *vp) {
1940 if ((vp->v_flag & VVMIO) && vp->v_object) {
1941 vrele(vp);
1942 vm_object_deallocate(vp->v_object);
1943 } else {
1944 vrele(vp);
1945 }
1946 return 0;
1947}