This source file includes following definitions.
- nfsm_reqh
- nfsm_rpchead
- nfsm_mbuftouio
- nfsm_uiotombuf
- nfsm_disct
- nfs_adv
- nfsm_strtmbuf
- nfs_init
- nfs_vfs_init
- nfs_loadattrcache
- nfs_attrtimeo
- nfs_getattrcache
- nfs_namei
- nfsm_adj
- nfsm_srvwcc
- nfsm_srvpostopattr
- nfsm_srvfattr
- nfsrv_fhtovp
- netaddr_match
- nfs_clearcommit
- nfs_merge_commit_ranges
- nfs_in_committed_range
- nfs_in_tobecommitted_range
- nfs_add_committed_range
- nfs_del_committed_range
- nfs_add_tobecommitted_range
- nfs_del_tobecommitted_range
- nfsrv_errmap
- nfsrvw_sort
- nfsrv_setcred
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 #include <sys/param.h>
45 #include <sys/proc.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/mount.h>
49 #include <sys/vnode.h>
50 #include <sys/namei.h>
51 #include <sys/mbuf.h>
52 #include <sys/socket.h>
53 #include <sys/socketvar.h>
54 #include <sys/stat.h>
55 #include <sys/malloc.h>
56 #include <sys/pool.h>
57 #include <sys/time.h>
58
59 #include <uvm/uvm_extern.h>
60
61 #include <nfs/rpcv2.h>
62 #include <nfs/nfsproto.h>
63 #include <nfs/nfsnode.h>
64 #include <nfs/nfs.h>
65 #include <nfs/xdr_subs.h>
66 #include <nfs/nfsm_subs.h>
67 #include <nfs/nfsmount.h>
68 #include <nfs/nfsrtt.h>
69 #include <nfs/nfs_var.h>
70
71 #include <miscfs/specfs/specdev.h>
72
73 #include <netinet/in.h>
74
75 #include <dev/rndvar.h>
76
77 #ifdef __GNUC__
78 #define INLINE __inline
79 #else
80 #define INLINE
81 #endif
82
83 int nfs_attrtimeo(struct nfsnode *np);
84
85
86
87
88
89 u_int32_t nfs_xdrneg1;
90 u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
91 rpc_mismatch, rpc_auth_unix, rpc_msgaccepted,
92 rpc_auth_kerb;
93 u_int32_t nfs_prog, nfs_true, nfs_false;
94
95
96 static u_int32_t nfs_xid = 0;
97 static u_int32_t nfs_xid_touched = 0;
98 nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
99 NFCHR, NFNON };
100 nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
101 NFFIFO, NFNON };
102 enum vtype nv2tov_type[8] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON };
103 enum vtype nv3tov_type[8]={ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO };
104 int nfs_ticks;
105 struct nfsstats nfsstats;
106
107
108
109
110 int nfsv3_procid[NFS_NPROCS] = {
111 NFSPROC_NULL,
112 NFSPROC_GETATTR,
113 NFSPROC_SETATTR,
114 NFSPROC_NOOP,
115 NFSPROC_LOOKUP,
116 NFSPROC_READLINK,
117 NFSPROC_READ,
118 NFSPROC_NOOP,
119 NFSPROC_WRITE,
120 NFSPROC_CREATE,
121 NFSPROC_REMOVE,
122 NFSPROC_RENAME,
123 NFSPROC_LINK,
124 NFSPROC_SYMLINK,
125 NFSPROC_MKDIR,
126 NFSPROC_RMDIR,
127 NFSPROC_READDIR,
128 NFSPROC_FSSTAT,
129 NFSPROC_NOOP,
130 NFSPROC_NOOP,
131 NFSPROC_NOOP,
132 NFSPROC_NOOP,
133 NFSPROC_NOOP,
134 NFSPROC_NOOP,
135 NFSPROC_NOOP,
136 NFSPROC_NOOP
137 };
138
139
140
141
142 int nfsv2_procid[NFS_NPROCS] = {
143 NFSV2PROC_NULL,
144 NFSV2PROC_GETATTR,
145 NFSV2PROC_SETATTR,
146 NFSV2PROC_LOOKUP,
147 NFSV2PROC_NOOP,
148 NFSV2PROC_READLINK,
149 NFSV2PROC_READ,
150 NFSV2PROC_WRITE,
151 NFSV2PROC_CREATE,
152 NFSV2PROC_MKDIR,
153 NFSV2PROC_SYMLINK,
154 NFSV2PROC_CREATE,
155 NFSV2PROC_REMOVE,
156 NFSV2PROC_RMDIR,
157 NFSV2PROC_RENAME,
158 NFSV2PROC_LINK,
159 NFSV2PROC_READDIR,
160 NFSV2PROC_NOOP,
161 NFSV2PROC_STATFS,
162 NFSV2PROC_NOOP,
163 NFSV2PROC_NOOP,
164 NFSV2PROC_NOOP,
165 NFSV2PROC_NOOP,
166 NFSV2PROC_NOOP,
167 NFSV2PROC_NOOP,
168 NFSV2PROC_NOOP,
169 };
170
171
172
173
174
175
176 static u_char nfsrv_v2errmap[ELAST] = {
177 NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO,
178 NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
179 NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO,
180 NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR,
181 NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
182 NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS,
183 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
184 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
185 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
186 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
187 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
188 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
189 NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO,
190 NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE,
191 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
192 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
193 NFSERR_IO,
194 };
195
196
197
198
199
200
201
202
203
204
205
206
207 static short nfsv3err_null[] = {
208 0,
209 0,
210 };
211
212 static short nfsv3err_getattr[] = {
213 NFSERR_IO,
214 NFSERR_IO,
215 NFSERR_STALE,
216 NFSERR_BADHANDLE,
217 NFSERR_SERVERFAULT,
218 0,
219 };
220
221 static short nfsv3err_setattr[] = {
222 NFSERR_IO,
223 NFSERR_PERM,
224 NFSERR_IO,
225 NFSERR_ACCES,
226 NFSERR_INVAL,
227 NFSERR_NOSPC,
228 NFSERR_ROFS,
229 NFSERR_DQUOT,
230 NFSERR_STALE,
231 NFSERR_BADHANDLE,
232 NFSERR_NOT_SYNC,
233 NFSERR_SERVERFAULT,
234 0,
235 };
236
237 static short nfsv3err_lookup[] = {
238 NFSERR_IO,
239 NFSERR_NOENT,
240 NFSERR_IO,
241 NFSERR_ACCES,
242 NFSERR_NOTDIR,
243 NFSERR_NAMETOL,
244 NFSERR_STALE,
245 NFSERR_BADHANDLE,
246 NFSERR_SERVERFAULT,
247 0,
248 };
249
250 static short nfsv3err_access[] = {
251 NFSERR_IO,
252 NFSERR_IO,
253 NFSERR_STALE,
254 NFSERR_BADHANDLE,
255 NFSERR_SERVERFAULT,
256 0,
257 };
258
259 static short nfsv3err_readlink[] = {
260 NFSERR_IO,
261 NFSERR_IO,
262 NFSERR_ACCES,
263 NFSERR_INVAL,
264 NFSERR_STALE,
265 NFSERR_BADHANDLE,
266 NFSERR_NOTSUPP,
267 NFSERR_SERVERFAULT,
268 0,
269 };
270
271 static short nfsv3err_read[] = {
272 NFSERR_IO,
273 NFSERR_IO,
274 NFSERR_NXIO,
275 NFSERR_ACCES,
276 NFSERR_INVAL,
277 NFSERR_STALE,
278 NFSERR_BADHANDLE,
279 NFSERR_SERVERFAULT,
280 0,
281 };
282
283 static short nfsv3err_write[] = {
284 NFSERR_IO,
285 NFSERR_IO,
286 NFSERR_ACCES,
287 NFSERR_INVAL,
288 NFSERR_FBIG,
289 NFSERR_NOSPC,
290 NFSERR_ROFS,
291 NFSERR_DQUOT,
292 NFSERR_STALE,
293 NFSERR_BADHANDLE,
294 NFSERR_SERVERFAULT,
295 0,
296 };
297
298 static short nfsv3err_create[] = {
299 NFSERR_IO,
300 NFSERR_IO,
301 NFSERR_ACCES,
302 NFSERR_EXIST,
303 NFSERR_NOTDIR,
304 NFSERR_NOSPC,
305 NFSERR_ROFS,
306 NFSERR_NAMETOL,
307 NFSERR_DQUOT,
308 NFSERR_STALE,
309 NFSERR_BADHANDLE,
310 NFSERR_NOTSUPP,
311 NFSERR_SERVERFAULT,
312 0,
313 };
314
315 static short nfsv3err_mkdir[] = {
316 NFSERR_IO,
317 NFSERR_IO,
318 NFSERR_ACCES,
319 NFSERR_EXIST,
320 NFSERR_NOTDIR,
321 NFSERR_NOSPC,
322 NFSERR_ROFS,
323 NFSERR_NAMETOL,
324 NFSERR_DQUOT,
325 NFSERR_STALE,
326 NFSERR_BADHANDLE,
327 NFSERR_NOTSUPP,
328 NFSERR_SERVERFAULT,
329 0,
330 };
331
332 static short nfsv3err_symlink[] = {
333 NFSERR_IO,
334 NFSERR_IO,
335 NFSERR_ACCES,
336 NFSERR_EXIST,
337 NFSERR_NOTDIR,
338 NFSERR_NOSPC,
339 NFSERR_ROFS,
340 NFSERR_NAMETOL,
341 NFSERR_DQUOT,
342 NFSERR_STALE,
343 NFSERR_BADHANDLE,
344 NFSERR_NOTSUPP,
345 NFSERR_SERVERFAULT,
346 0,
347 };
348
349 static short nfsv3err_mknod[] = {
350 NFSERR_IO,
351 NFSERR_IO,
352 NFSERR_ACCES,
353 NFSERR_EXIST,
354 NFSERR_NOTDIR,
355 NFSERR_NOSPC,
356 NFSERR_ROFS,
357 NFSERR_NAMETOL,
358 NFSERR_DQUOT,
359 NFSERR_STALE,
360 NFSERR_BADHANDLE,
361 NFSERR_NOTSUPP,
362 NFSERR_SERVERFAULT,
363 NFSERR_BADTYPE,
364 0,
365 };
366
367 static short nfsv3err_remove[] = {
368 NFSERR_IO,
369 NFSERR_NOENT,
370 NFSERR_IO,
371 NFSERR_ACCES,
372 NFSERR_NOTDIR,
373 NFSERR_ROFS,
374 NFSERR_NAMETOL,
375 NFSERR_STALE,
376 NFSERR_BADHANDLE,
377 NFSERR_SERVERFAULT,
378 0,
379 };
380
381 static short nfsv3err_rmdir[] = {
382 NFSERR_IO,
383 NFSERR_NOENT,
384 NFSERR_IO,
385 NFSERR_ACCES,
386 NFSERR_EXIST,
387 NFSERR_NOTDIR,
388 NFSERR_INVAL,
389 NFSERR_ROFS,
390 NFSERR_NAMETOL,
391 NFSERR_NOTEMPTY,
392 NFSERR_STALE,
393 NFSERR_BADHANDLE,
394 NFSERR_NOTSUPP,
395 NFSERR_SERVERFAULT,
396 0,
397 };
398
399 static short nfsv3err_rename[] = {
400 NFSERR_IO,
401 NFSERR_NOENT,
402 NFSERR_IO,
403 NFSERR_ACCES,
404 NFSERR_EXIST,
405 NFSERR_XDEV,
406 NFSERR_NOTDIR,
407 NFSERR_ISDIR,
408 NFSERR_INVAL,
409 NFSERR_NOSPC,
410 NFSERR_ROFS,
411 NFSERR_MLINK,
412 NFSERR_NAMETOL,
413 NFSERR_NOTEMPTY,
414 NFSERR_DQUOT,
415 NFSERR_STALE,
416 NFSERR_BADHANDLE,
417 NFSERR_NOTSUPP,
418 NFSERR_SERVERFAULT,
419 0,
420 };
421
422 static short nfsv3err_link[] = {
423 NFSERR_IO,
424 NFSERR_IO,
425 NFSERR_ACCES,
426 NFSERR_EXIST,
427 NFSERR_XDEV,
428 NFSERR_NOTDIR,
429 NFSERR_INVAL,
430 NFSERR_NOSPC,
431 NFSERR_ROFS,
432 NFSERR_MLINK,
433 NFSERR_NAMETOL,
434 NFSERR_DQUOT,
435 NFSERR_STALE,
436 NFSERR_BADHANDLE,
437 NFSERR_NOTSUPP,
438 NFSERR_SERVERFAULT,
439 0,
440 };
441
442 static short nfsv3err_readdir[] = {
443 NFSERR_IO,
444 NFSERR_IO,
445 NFSERR_ACCES,
446 NFSERR_NOTDIR,
447 NFSERR_STALE,
448 NFSERR_BADHANDLE,
449 NFSERR_BAD_COOKIE,
450 NFSERR_TOOSMALL,
451 NFSERR_SERVERFAULT,
452 0,
453 };
454
455 static short nfsv3err_readdirplus[] = {
456 NFSERR_IO,
457 NFSERR_IO,
458 NFSERR_ACCES,
459 NFSERR_NOTDIR,
460 NFSERR_STALE,
461 NFSERR_BADHANDLE,
462 NFSERR_BAD_COOKIE,
463 NFSERR_NOTSUPP,
464 NFSERR_TOOSMALL,
465 NFSERR_SERVERFAULT,
466 0,
467 };
468
469 static short nfsv3err_fsstat[] = {
470 NFSERR_IO,
471 NFSERR_IO,
472 NFSERR_STALE,
473 NFSERR_BADHANDLE,
474 NFSERR_SERVERFAULT,
475 0,
476 };
477
478 static short nfsv3err_fsinfo[] = {
479 NFSERR_STALE,
480 NFSERR_STALE,
481 NFSERR_BADHANDLE,
482 NFSERR_SERVERFAULT,
483 0,
484 };
485
486 static short nfsv3err_pathconf[] = {
487 NFSERR_STALE,
488 NFSERR_STALE,
489 NFSERR_BADHANDLE,
490 NFSERR_SERVERFAULT,
491 0,
492 };
493
494 static short nfsv3err_commit[] = {
495 NFSERR_IO,
496 NFSERR_IO,
497 NFSERR_STALE,
498 NFSERR_BADHANDLE,
499 NFSERR_SERVERFAULT,
500 0,
501 };
502
503 static short *nfsrv_v3errmap[] = {
504 nfsv3err_null,
505 nfsv3err_getattr,
506 nfsv3err_setattr,
507 nfsv3err_lookup,
508 nfsv3err_access,
509 nfsv3err_readlink,
510 nfsv3err_read,
511 nfsv3err_write,
512 nfsv3err_create,
513 nfsv3err_mkdir,
514 nfsv3err_symlink,
515 nfsv3err_mknod,
516 nfsv3err_remove,
517 nfsv3err_rmdir,
518 nfsv3err_rename,
519 nfsv3err_link,
520 nfsv3err_readdir,
521 nfsv3err_readdirplus,
522 nfsv3err_fsstat,
523 nfsv3err_fsinfo,
524 nfsv3err_pathconf,
525 nfsv3err_commit,
526 };
527
528 extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
529 extern struct nfsrtt nfsrtt;
530
531 struct pool nfsreqpl;
532
533
534
535
536
537
538 struct mbuf *
539 nfsm_reqh(vp, procid, hsiz, bposp)
540 struct vnode *vp;
541 u_long procid;
542 int hsiz;
543 caddr_t *bposp;
544 {
545 struct mbuf *mb;
546 caddr_t bpos;
547
548 MGET(mb, M_WAIT, MT_DATA);
549 if (hsiz >= MINCLSIZE)
550 MCLGET(mb, M_WAIT);
551 mb->m_len = 0;
552 bpos = mtod(mb, caddr_t);
553
554
555 *bposp = bpos;
556 return (mb);
557 }
558
559
560
561
562
563
564
565 struct mbuf *
566 nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
567 verf_str, mrest, mrest_len, mbp, xidp)
568 struct ucred *cr;
569 int nmflag;
570 int procid;
571 int auth_type;
572 int auth_len;
573 char *auth_str;
574 int verf_len;
575 char *verf_str;
576 struct mbuf *mrest;
577 int mrest_len;
578 struct mbuf **mbp;
579 u_int32_t *xidp;
580 {
581 struct mbuf *mb;
582 u_int32_t *tl;
583 caddr_t bpos;
584 int i;
585 struct mbuf *mreq, *mb2;
586 int siz, grpsiz, authsiz;
587
588 authsiz = nfsm_rndup(auth_len);
589 MGETHDR(mb, M_WAIT, MT_DATA);
590 if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) {
591 MCLGET(mb, M_WAIT);
592 } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) {
593 MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
594 } else {
595 MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
596 }
597 mb->m_len = 0;
598 mreq = mb;
599 bpos = mtod(mb, caddr_t);
600
601
602
603
604 nfsm_build(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
605
606
607
608 if ((nfs_xid == 0) && (nfs_xid_touched == 0)) {
609 nfs_xid = arc4random();
610 nfs_xid_touched = 1;
611 } else {
612 while ((*xidp = arc4random() % 256) == 0)
613 ;
614 nfs_xid += *xidp;
615 }
616
617 *tl++ = *xidp = txdr_unsigned(nfs_xid);
618 *tl++ = rpc_call;
619 *tl++ = rpc_vers;
620 *tl++ = txdr_unsigned(NFS_PROG);
621 if (nmflag & NFSMNT_NFSV3)
622 *tl++ = txdr_unsigned(NFS_VER3);
623 else
624 *tl++ = txdr_unsigned(NFS_VER2);
625 if (nmflag & NFSMNT_NFSV3)
626 *tl++ = txdr_unsigned(procid);
627 else
628 *tl++ = txdr_unsigned(nfsv2_procid[procid]);
629
630
631
632
633 *tl++ = txdr_unsigned(auth_type);
634 *tl = txdr_unsigned(authsiz);
635 switch (auth_type) {
636 case RPCAUTH_UNIX:
637 nfsm_build(tl, u_int32_t *, auth_len);
638 *tl++ = 0;
639 *tl++ = 0;
640 *tl++ = txdr_unsigned(cr->cr_uid);
641 *tl++ = txdr_unsigned(cr->cr_gid);
642 grpsiz = (auth_len >> 2) - 5;
643 *tl++ = txdr_unsigned(grpsiz);
644 for (i = 0; i < grpsiz; i++)
645 *tl++ = txdr_unsigned(cr->cr_groups[i]);
646 break;
647 case RPCAUTH_KERB4:
648 siz = auth_len;
649 while (siz > 0) {
650 if (M_TRAILINGSPACE(mb) == 0) {
651 MGET(mb2, M_WAIT, MT_DATA);
652 if (siz >= MINCLSIZE)
653 MCLGET(mb2, M_WAIT);
654 mb->m_next = mb2;
655 mb = mb2;
656 mb->m_len = 0;
657 bpos = mtod(mb, caddr_t);
658 }
659 i = min(siz, M_TRAILINGSPACE(mb));
660 bcopy(auth_str, bpos, i);
661 mb->m_len += i;
662 auth_str += i;
663 bpos += i;
664 siz -= i;
665 }
666 if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) {
667 for (i = 0; i < siz; i++)
668 *bpos++ = '\0';
669 mb->m_len += siz;
670 }
671 break;
672 };
673
674
675
676
677 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
678 if (verf_str) {
679 *tl++ = txdr_unsigned(RPCAUTH_KERB4);
680 *tl = txdr_unsigned(verf_len);
681 siz = verf_len;
682 while (siz > 0) {
683 if (M_TRAILINGSPACE(mb) == 0) {
684 MGET(mb2, M_WAIT, MT_DATA);
685 if (siz >= MINCLSIZE)
686 MCLGET(mb2, M_WAIT);
687 mb->m_next = mb2;
688 mb = mb2;
689 mb->m_len = 0;
690 bpos = mtod(mb, caddr_t);
691 }
692 i = min(siz, M_TRAILINGSPACE(mb));
693 bcopy(verf_str, bpos, i);
694 mb->m_len += i;
695 verf_str += i;
696 bpos += i;
697 siz -= i;
698 }
699 if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) {
700 for (i = 0; i < siz; i++)
701 *bpos++ = '\0';
702 mb->m_len += siz;
703 }
704 } else {
705 *tl++ = txdr_unsigned(RPCAUTH_NULL);
706 *tl = 0;
707 }
708 mb->m_next = mrest;
709 mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
710 mreq->m_pkthdr.rcvif = (struct ifnet *)0;
711 *mbp = mb;
712 return (mreq);
713 }
714
715
716
717
718 int
719 nfsm_mbuftouio(mrep, uiop, siz, dpos)
720 struct mbuf **mrep;
721 struct uio *uiop;
722 int siz;
723 caddr_t *dpos;
724 {
725 char *mbufcp, *uiocp;
726 int xfer, left, len;
727 struct mbuf *mp;
728 long uiosiz, rem;
729 int error = 0;
730
731 mp = *mrep;
732 mbufcp = *dpos;
733 len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
734 rem = nfsm_rndup(siz)-siz;
735 while (siz > 0) {
736 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
737 return (EFBIG);
738 left = uiop->uio_iov->iov_len;
739 uiocp = uiop->uio_iov->iov_base;
740 if (left > siz)
741 left = siz;
742 uiosiz = left;
743 while (left > 0) {
744 while (len == 0) {
745 mp = mp->m_next;
746 if (mp == NULL)
747 return (EBADRPC);
748 mbufcp = mtod(mp, caddr_t);
749 len = mp->m_len;
750 }
751 xfer = (left > len) ? len : left;
752 #ifdef notdef
753
754 if (uiop->uio_iov->iov_op != NULL)
755 (*(uiop->uio_iov->iov_op))
756 (mbufcp, uiocp, xfer);
757 else
758 #endif
759 if (uiop->uio_segflg == UIO_SYSSPACE)
760 bcopy(mbufcp, uiocp, xfer);
761 else
762 copyout(mbufcp, uiocp, xfer);
763 left -= xfer;
764 len -= xfer;
765 mbufcp += xfer;
766 uiocp += xfer;
767 uiop->uio_offset += xfer;
768 uiop->uio_resid -= xfer;
769 }
770 if (uiop->uio_iov->iov_len <= siz) {
771 uiop->uio_iovcnt--;
772 uiop->uio_iov++;
773 } else {
774 (char *)uiop->uio_iov->iov_base += uiosiz;
775 uiop->uio_iov->iov_len -= uiosiz;
776 }
777 siz -= uiosiz;
778 }
779 *dpos = mbufcp;
780 *mrep = mp;
781 if (rem > 0) {
782 if (len < rem)
783 error = nfs_adv(mrep, dpos, rem, len);
784 else
785 *dpos += rem;
786 }
787 return (error);
788 }
789
790
791
792
793
794 int
795 nfsm_uiotombuf(uiop, mq, siz, bpos)
796 struct uio *uiop;
797 struct mbuf **mq;
798 int siz;
799 caddr_t *bpos;
800 {
801 char *uiocp;
802 struct mbuf *mp, *mp2;
803 int xfer, left, mlen;
804 int uiosiz, clflg, rem;
805 char *cp;
806
807 #ifdef DIAGNOSTIC
808 if (uiop->uio_iovcnt != 1)
809 panic("nfsm_uiotombuf: iovcnt != 1");
810 #endif
811
812 if (siz > MLEN)
813 clflg = 1;
814 else
815 clflg = 0;
816 rem = nfsm_rndup(siz)-siz;
817 mp = mp2 = *mq;
818 while (siz > 0) {
819 left = uiop->uio_iov->iov_len;
820 uiocp = uiop->uio_iov->iov_base;
821 if (left > siz)
822 left = siz;
823 uiosiz = left;
824 while (left > 0) {
825 mlen = M_TRAILINGSPACE(mp);
826 if (mlen == 0) {
827 MGET(mp, M_WAIT, MT_DATA);
828 if (clflg)
829 MCLGET(mp, M_WAIT);
830 mp->m_len = 0;
831 mp2->m_next = mp;
832 mp2 = mp;
833 mlen = M_TRAILINGSPACE(mp);
834 }
835 xfer = (left > mlen) ? mlen : left;
836 #ifdef notdef
837
838 if (uiop->uio_iov->iov_op != NULL)
839 (*(uiop->uio_iov->iov_op))
840 (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
841 else
842 #endif
843 if (uiop->uio_segflg == UIO_SYSSPACE)
844 bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
845 else
846 copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
847 mp->m_len += xfer;
848 left -= xfer;
849 uiocp += xfer;
850 uiop->uio_offset += xfer;
851 uiop->uio_resid -= xfer;
852 }
853 (char *)uiop->uio_iov->iov_base += uiosiz;
854 uiop->uio_iov->iov_len -= uiosiz;
855 siz -= uiosiz;
856 }
857 if (rem > 0) {
858 if (rem > M_TRAILINGSPACE(mp)) {
859 MGET(mp, M_WAIT, MT_DATA);
860 mp->m_len = 0;
861 mp2->m_next = mp;
862 }
863 cp = mtod(mp, caddr_t)+mp->m_len;
864 for (left = 0; left < rem; left++)
865 *cp++ = '\0';
866 mp->m_len += rem;
867 *bpos = cp;
868 } else
869 *bpos = mtod(mp, caddr_t)+mp->m_len;
870 *mq = mp;
871 return (0);
872 }
873
874
875
876
877
878
879
880 int
881 nfsm_disct(mdp, dposp, siz, left, cp2)
882 struct mbuf **mdp;
883 caddr_t *dposp;
884 int siz;
885 int left;
886 caddr_t *cp2;
887 {
888 struct mbuf *mp, *mp2;
889 int siz2, xfer;
890 caddr_t p;
891
892 mp = *mdp;
893 while (left == 0) {
894 *mdp = mp = mp->m_next;
895 if (mp == NULL)
896 return (EBADRPC);
897 left = mp->m_len;
898 *dposp = mtod(mp, caddr_t);
899 }
900 if (left >= siz) {
901 *cp2 = *dposp;
902 *dposp += siz;
903 } else if (mp->m_next == NULL) {
904 return (EBADRPC);
905 } else if (siz > MHLEN) {
906 panic("nfs S too big");
907 } else {
908 MGET(mp2, M_WAIT, MT_DATA);
909 mp2->m_next = mp->m_next;
910 mp->m_next = mp2;
911 mp->m_len -= left;
912 mp = mp2;
913 *cp2 = p = mtod(mp, caddr_t);
914 bcopy(*dposp, p, left);
915 siz2 = siz-left;
916 p += left;
917 mp2 = mp->m_next;
918
919 while (siz2 > 0) {
920 if (mp2 == NULL)
921 return (EBADRPC);
922 xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
923 if (xfer > 0) {
924 bcopy(mtod(mp2, caddr_t), p, xfer);
925 NFSMADV(mp2, xfer);
926 mp2->m_len -= xfer;
927 p += xfer;
928 siz2 -= xfer;
929 }
930 if (siz2 > 0)
931 mp2 = mp2->m_next;
932 }
933 mp->m_len = siz;
934 *mdp = mp2;
935 *dposp = mtod(mp2, caddr_t);
936 }
937 return (0);
938 }
939
940
941
942
943 int
944 nfs_adv(mdp, dposp, offs, left)
945 struct mbuf **mdp;
946 caddr_t *dposp;
947 int offs;
948 int left;
949 {
950 struct mbuf *m;
951 int s;
952
953 m = *mdp;
954 s = left;
955 while (s < offs) {
956 offs -= s;
957 m = m->m_next;
958 if (m == NULL)
959 return (EBADRPC);
960 s = m->m_len;
961 }
962 *mdp = m;
963 *dposp = mtod(m, caddr_t)+offs;
964 return (0);
965 }
966
967
968
969
970 int
971 nfsm_strtmbuf(mb, bpos, cp, siz)
972 struct mbuf **mb;
973 char **bpos;
974 char *cp;
975 long siz;
976 {
977 struct mbuf *m1 = NULL, *m2;
978 long left, xfer, len, tlen;
979 u_int32_t *tl;
980 int putsize;
981
982 putsize = 1;
983 m2 = *mb;
984 left = M_TRAILINGSPACE(m2);
985 if (left > 0) {
986 tl = ((u_int32_t *)(*bpos));
987 *tl++ = txdr_unsigned(siz);
988 putsize = 0;
989 left -= NFSX_UNSIGNED;
990 m2->m_len += NFSX_UNSIGNED;
991 if (left > 0) {
992 bcopy(cp, (caddr_t) tl, left);
993 siz -= left;
994 cp += left;
995 m2->m_len += left;
996 left = 0;
997 }
998 }
999
1000 while (siz > 0) {
1001 MGET(m1, M_WAIT, MT_DATA);
1002 if (siz > MLEN)
1003 MCLGET(m1, M_WAIT);
1004 m1->m_len = NFSMSIZ(m1);
1005 m2->m_next = m1;
1006 m2 = m1;
1007 tl = mtod(m1, u_int32_t *);
1008 tlen = 0;
1009 if (putsize) {
1010 *tl++ = txdr_unsigned(siz);
1011 m1->m_len -= NFSX_UNSIGNED;
1012 tlen = NFSX_UNSIGNED;
1013 putsize = 0;
1014 }
1015 if (siz < m1->m_len) {
1016 len = nfsm_rndup(siz);
1017 xfer = siz;
1018 if (xfer < len)
1019 *(tl+(xfer>>2)) = 0;
1020 } else {
1021 xfer = len = m1->m_len;
1022 }
1023 bcopy(cp, (caddr_t) tl, xfer);
1024 m1->m_len = len+tlen;
1025 siz -= xfer;
1026 cp += xfer;
1027 }
1028 *mb = m1;
1029 *bpos = mtod(m1, caddr_t)+m1->m_len;
1030 return (0);
1031 }
1032
1033
1034
1035
1036 void
1037 nfs_init()
1038 {
1039 static struct timeout nfs_timer_to;
1040
1041 nfsrtt.pos = 0;
1042 rpc_vers = txdr_unsigned(RPC_VER2);
1043 rpc_call = txdr_unsigned(RPC_CALL);
1044 rpc_reply = txdr_unsigned(RPC_REPLY);
1045 rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
1046 rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
1047 rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
1048 rpc_autherr = txdr_unsigned(RPC_AUTHERR);
1049 rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
1050 rpc_auth_kerb = txdr_unsigned(RPCAUTH_KERB4);
1051 nfs_prog = txdr_unsigned(NFS_PROG);
1052 nfs_true = txdr_unsigned(TRUE);
1053 nfs_false = txdr_unsigned(FALSE);
1054 nfs_xdrneg1 = txdr_unsigned(-1);
1055 nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
1056 if (nfs_ticks < 1)
1057 nfs_ticks = 1;
1058 #ifdef NFSSERVER
1059 nfsrv_init(0);
1060 nfsrv_initcache();
1061 #endif
1062
1063 pool_init(&nfsreqpl, sizeof(struct nfsreq), 0, 0, 0, "nfsreqpl",
1064 &pool_allocator_nointr);
1065
1066
1067
1068
1069 TAILQ_INIT(&nfs_reqq);
1070
1071 timeout_set(&nfs_timer_to, nfs_timer, &nfs_timer_to);
1072 nfs_timer(&nfs_timer_to);
1073 }
1074
1075 #ifdef NFSCLIENT
1076 int
1077 nfs_vfs_init(vfsp)
1078 struct vfsconf *vfsp;
1079 {
1080 int i;
1081
1082
1083 for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1084 nfs_iodwant[i] = (struct proc *)0;
1085 TAILQ_INIT(&nfs_bufq);
1086 nfs_nhinit();
1087
1088 return (0);
1089 }
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105 int
1106 nfs_loadattrcache(vpp, mdp, dposp, vaper)
1107 struct vnode **vpp;
1108 struct mbuf **mdp;
1109 caddr_t *dposp;
1110 struct vattr *vaper;
1111 {
1112 struct vnode *vp = *vpp;
1113 struct vattr *vap;
1114 struct nfs_fattr *fp;
1115 extern int (**spec_nfsv2nodeop_p)(void *);
1116 struct nfsnode *np;
1117 int32_t t1;
1118 caddr_t cp2;
1119 int error = 0;
1120 int32_t rdev;
1121 struct mbuf *md;
1122 enum vtype vtyp;
1123 mode_t vmode;
1124 struct timespec mtime;
1125 struct vnode *nvp;
1126 int v3 = NFS_ISV3(vp);
1127
1128 md = *mdp;
1129 t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
1130 error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2);
1131 if (error)
1132 return (error);
1133 fp = (struct nfs_fattr *)cp2;
1134 if (v3) {
1135 vtyp = nfsv3tov_type(fp->fa_type);
1136 vmode = fxdr_unsigned(mode_t, fp->fa_mode);
1137 rdev = makedev(fxdr_unsigned(u_int32_t, fp->fa3_rdev.specdata1),
1138 fxdr_unsigned(u_int32_t, fp->fa3_rdev.specdata2));
1139 fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
1140 } else {
1141 vtyp = nfsv2tov_type(fp->fa_type);
1142 vmode = fxdr_unsigned(mode_t, fp->fa_mode);
1143 if (vtyp == VNON || vtyp == VREG)
1144 vtyp = IFTOVT(vmode);
1145 rdev = fxdr_unsigned(int32_t, fp->fa2_rdev);
1146 fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
1147
1148
1149
1150
1151 if (vtyp == VCHR && rdev == 0xffffffff)
1152 vtyp = VFIFO;
1153 }
1154
1155
1156
1157
1158
1159
1160
1161
1162 np = VTONFS(vp);
1163 if (vp->v_type != vtyp) {
1164 vp->v_type = vtyp;
1165 if (vp->v_type == VFIFO) {
1166 #ifndef FIFO
1167 return (EOPNOTSUPP);
1168 #else
1169 extern int (**fifo_nfsv2nodeop_p)(void *);
1170 vp->v_op = fifo_nfsv2nodeop_p;
1171 #endif
1172 }
1173 if (vp->v_type == VCHR || vp->v_type == VBLK) {
1174 vp->v_op = spec_nfsv2nodeop_p;
1175 nvp = checkalias(vp, (dev_t)rdev, vp->v_mount);
1176 if (nvp) {
1177
1178
1179
1180
1181
1182
1183 nvp->v_data = vp->v_data;
1184 vp->v_data = NULL;
1185 vp->v_op = spec_vnodeop_p;
1186 vrele(vp);
1187 vgone(vp);
1188
1189
1190
1191 np->n_vnode = nvp;
1192 *vpp = vp = nvp;
1193 }
1194 }
1195 np->n_mtime = mtime.tv_sec;
1196 }
1197 vap = &np->n_vattr;
1198 vap->va_type = vtyp;
1199 vap->va_mode = (vmode & 07777);
1200 vap->va_rdev = (dev_t)rdev;
1201 vap->va_mtime = mtime;
1202 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
1203 if (v3) {
1204 vap->va_nlink = fxdr_unsigned(nlink_t, fp->fa_nlink);
1205 vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
1206 vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
1207 vap->va_size = fxdr_hyper(&fp->fa3_size);
1208 vap->va_blocksize = NFS_FABLKSIZE;
1209 vap->va_bytes = fxdr_hyper(&fp->fa3_used);
1210 vap->va_fileid = fxdr_unsigned(int32_t,
1211 fp->fa3_fileid.nfsuquad[1]);
1212 fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
1213 fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
1214 vap->va_flags = 0;
1215 vap->va_filerev = 0;
1216 } else {
1217 vap->va_nlink = fxdr_unsigned(nlink_t, fp->fa_nlink);
1218 vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
1219 vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
1220 vap->va_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
1221 vap->va_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
1222 vap->va_bytes =
1223 (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) *
1224 NFS_FABLKSIZE;
1225 vap->va_fileid = fxdr_unsigned(int32_t, fp->fa2_fileid);
1226 fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
1227 vap->va_flags = 0;
1228 vap->va_ctime.tv_sec = fxdr_unsigned(u_int32_t,
1229 fp->fa2_ctime.nfsv2_sec);
1230 vap->va_ctime.tv_nsec = 0;
1231 vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
1232 vap->va_filerev = 0;
1233 }
1234 if (vap->va_size != np->n_size) {
1235 if (vap->va_type == VREG) {
1236 if (np->n_flag & NMODIFIED) {
1237 if (vap->va_size < np->n_size)
1238 vap->va_size = np->n_size;
1239 else
1240 np->n_size = vap->va_size;
1241 } else
1242 np->n_size = vap->va_size;
1243 uvm_vnp_setsize(vp, np->n_size);
1244 } else
1245 np->n_size = vap->va_size;
1246 }
1247 np->n_attrstamp = time_second;
1248 if (vaper != NULL) {
1249 bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
1250 if (np->n_flag & NCHG) {
1251 if (np->n_flag & NACC)
1252 vaper->va_atime = np->n_atim;
1253 if (np->n_flag & NUPD)
1254 vaper->va_mtime = np->n_mtim;
1255 }
1256 }
1257 return (0);
1258 }
1259
1260 INLINE int
1261 nfs_attrtimeo (np)
1262 struct nfsnode *np;
1263 {
1264 struct vnode *vp = np->n_vnode;
1265 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1266 int tenthage = (time_second - np->n_mtime) / 10;
1267 int minto, maxto;
1268
1269 if (vp->v_type == VDIR) {
1270 maxto = nmp->nm_acdirmax;
1271 minto = nmp->nm_acdirmin;
1272 }
1273 else {
1274 maxto = nmp->nm_acregmax;
1275 minto = nmp->nm_acregmin;
1276 }
1277
1278 if (np->n_flag & NMODIFIED || tenthage < minto)
1279 return minto;
1280 else if (tenthage < maxto)
1281 return tenthage;
1282 else
1283 return maxto;
1284 }
1285
1286
1287
1288
1289
1290
1291 int
1292 nfs_getattrcache(vp, vaper)
1293 struct vnode *vp;
1294 struct vattr *vaper;
1295 {
1296 struct nfsnode *np = VTONFS(vp);
1297 struct vattr *vap;
1298
1299 if (np->n_attrstamp == 0 ||
1300 (time_second - np->n_attrstamp) >= nfs_attrtimeo(np)) {
1301 nfsstats.attrcache_misses++;
1302 return (ENOENT);
1303 }
1304 nfsstats.attrcache_hits++;
1305 vap = &np->n_vattr;
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 uvm_vnp_setsize(vp, np->n_size);
1316 } else
1317 np->n_size = vap->va_size;
1318 }
1319 bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));
1320 if (np->n_flag & NCHG) {
1321 if (np->n_flag & NACC)
1322 vaper->va_atime = np->n_atim;
1323 if (np->n_flag & NUPD)
1324 vaper->va_mtime = np->n_mtim;
1325 }
1326 return (0);
1327 }
1328 #endif
1329
1330
1331
1332
1333 int
1334 nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
1335 struct nameidata *ndp;
1336 fhandle_t *fhp;
1337 int len;
1338 struct nfssvc_sock *slp;
1339 struct mbuf *nam;
1340 struct mbuf **mdp;
1341 caddr_t *dposp;
1342 struct vnode **retdirp;
1343 struct proc *p;
1344 int kerbflag;
1345 {
1346 int i, rem;
1347 struct mbuf *md;
1348 char *fromcp, *tocp;
1349 struct vnode *dp;
1350 int error, rdonly;
1351 struct componentname *cnp = &ndp->ni_cnd;
1352
1353 *retdirp = (struct vnode *)0;
1354 cnp->cn_pnbuf = pool_get(&namei_pool, PR_WAITOK);
1355
1356
1357
1358
1359 fromcp = *dposp;
1360 tocp = cnp->cn_pnbuf;
1361 md = *mdp;
1362 rem = mtod(md, caddr_t) + md->m_len - fromcp;
1363 cnp->cn_hash = 0;
1364 for (i = 0; i < len; i++) {
1365 while (rem == 0) {
1366 md = md->m_next;
1367 if (md == NULL) {
1368 error = EBADRPC;
1369 goto out;
1370 }
1371 fromcp = mtod(md, caddr_t);
1372 rem = md->m_len;
1373 }
1374 if (*fromcp == '\0' || *fromcp == '/') {
1375 error = EACCES;
1376 goto out;
1377 }
1378 cnp->cn_hash += (u_char)*fromcp;
1379 *tocp++ = *fromcp++;
1380 rem--;
1381 }
1382 *tocp = '\0';
1383 *mdp = md;
1384 *dposp = fromcp;
1385 len = nfsm_rndup(len)-len;
1386 if (len > 0) {
1387 if (rem >= len)
1388 *dposp += len;
1389 else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0)
1390 goto out;
1391 }
1392 ndp->ni_pathlen = tocp - cnp->cn_pnbuf;
1393 cnp->cn_nameptr = cnp->cn_pnbuf;
1394
1395
1396
1397 error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
1398 nam, &rdonly, kerbflag);
1399 if (error)
1400 goto out;
1401 if (dp->v_type != VDIR) {
1402 vrele(dp);
1403 error = ENOTDIR;
1404 goto out;
1405 }
1406 VREF(dp);
1407 *retdirp = dp;
1408 ndp->ni_startdir = dp;
1409 if (rdonly)
1410 cnp->cn_flags |= (NOCROSSMOUNT | RDONLY);
1411 else
1412 cnp->cn_flags |= NOCROSSMOUNT;
1413
1414
1415
1416 cnp->cn_proc = p;
1417 error = lookup(ndp);
1418 if (error)
1419 goto out;
1420
1421
1422
1423 if (cnp->cn_flags & ISSYMLINK) {
1424 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
1425 vput(ndp->ni_dvp);
1426 else
1427 vrele(ndp->ni_dvp);
1428 vput(ndp->ni_vp);
1429 ndp->ni_vp = NULL;
1430 error = EINVAL;
1431 goto out;
1432 }
1433
1434
1435
1436 if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
1437 cnp->cn_flags |= HASBUF;
1438 return (0);
1439 }
1440 out:
1441 pool_put(&namei_pool, cnp->cn_pnbuf);
1442 return (error);
1443 }
1444
1445
1446
1447
1448
1449 void
1450 nfsm_adj(mp, len, nul)
1451 struct mbuf *mp;
1452 int len;
1453 int nul;
1454 {
1455 struct mbuf *m;
1456 int count, i;
1457 char *cp;
1458
1459
1460
1461
1462
1463
1464
1465
1466 count = 0;
1467 m = mp;
1468 for (;;) {
1469 count += m->m_len;
1470 if (m->m_next == (struct mbuf *)0)
1471 break;
1472 m = m->m_next;
1473 }
1474 if (m->m_len > len) {
1475 m->m_len -= len;
1476 if (nul > 0) {
1477 cp = mtod(m, caddr_t)+m->m_len-nul;
1478 for (i = 0; i < nul; i++)
1479 *cp++ = '\0';
1480 }
1481 return;
1482 }
1483 count -= len;
1484 if (count < 0)
1485 count = 0;
1486
1487
1488
1489
1490
1491 for (m = mp; m; m = m->m_next) {
1492 if (m->m_len >= count) {
1493 m->m_len = count;
1494 if (nul > 0) {
1495 cp = mtod(m, caddr_t)+m->m_len-nul;
1496 for (i = 0; i < nul; i++)
1497 *cp++ = '\0';
1498 }
1499 break;
1500 }
1501 count -= m->m_len;
1502 }
1503 for (m = m->m_next;m;m = m->m_next)
1504 m->m_len = 0;
1505 }
1506
1507
1508
1509
1510
1511 void
1512 nfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp)
1513 struct nfsrv_descript *nfsd;
1514 int before_ret;
1515 struct vattr *before_vap;
1516 int after_ret;
1517 struct vattr *after_vap;
1518 struct mbuf **mbp;
1519 char **bposp;
1520 {
1521 struct mbuf *mb = *mbp, *mb2;
1522 char *bpos = *bposp;
1523 u_int32_t *tl;
1524
1525 if (before_ret) {
1526 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
1527 *tl = nfs_false;
1528 } else {
1529 nfsm_build(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
1530 *tl++ = nfs_true;
1531 txdr_hyper(before_vap->va_size, tl);
1532 tl += 2;
1533 txdr_nfsv3time(&(before_vap->va_mtime), tl);
1534 tl += 2;
1535 txdr_nfsv3time(&(before_vap->va_ctime), tl);
1536 }
1537 *bposp = bpos;
1538 *mbp = mb;
1539 nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
1540 }
1541
1542 void
1543 nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp)
1544 struct nfsrv_descript *nfsd;
1545 int after_ret;
1546 struct vattr *after_vap;
1547 struct mbuf **mbp;
1548 char **bposp;
1549 {
1550 struct mbuf *mb = *mbp, *mb2;
1551 char *bpos = *bposp;
1552 u_int32_t *tl;
1553 struct nfs_fattr *fp;
1554
1555 if (after_ret) {
1556 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
1557 *tl = nfs_false;
1558 } else {
1559 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR);
1560 *tl++ = nfs_true;
1561 fp = (struct nfs_fattr *)tl;
1562 nfsm_srvfattr(nfsd, after_vap, fp);
1563 }
1564 *mbp = mb;
1565 *bposp = bpos;
1566 }
1567
1568 void
1569 nfsm_srvfattr(nfsd, vap, fp)
1570 struct nfsrv_descript *nfsd;
1571 struct vattr *vap;
1572 struct nfs_fattr *fp;
1573 {
1574
1575 fp->fa_nlink = txdr_unsigned(vap->va_nlink);
1576 fp->fa_uid = txdr_unsigned(vap->va_uid);
1577 fp->fa_gid = txdr_unsigned(vap->va_gid);
1578 if (nfsd->nd_flag & ND_NFSV3) {
1579 fp->fa_type = vtonfsv3_type(vap->va_type);
1580 fp->fa_mode = vtonfsv3_mode(vap->va_mode);
1581 txdr_hyper(vap->va_size, &fp->fa3_size);
1582 txdr_hyper(vap->va_bytes, &fp->fa3_used);
1583 fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev));
1584 fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev));
1585 fp->fa3_fsid.nfsuquad[0] = 0;
1586 fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
1587 fp->fa3_fileid.nfsuquad[0] = 0;
1588 fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
1589 txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
1590 txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
1591 txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
1592 } else {
1593 fp->fa_type = vtonfsv2_type(vap->va_type);
1594 fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1595 fp->fa2_size = txdr_unsigned(vap->va_size);
1596 fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
1597 if (vap->va_type == VFIFO)
1598 fp->fa2_rdev = 0xffffffff;
1599 else
1600 fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
1601 fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
1602 fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
1603 fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
1604 txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
1605 txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
1606 txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
1607 }
1608 }
1609
1610
1611
1612
1613
1614
1615
1616
1617 int
1618 nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
1619 fhandle_t *fhp;
1620 int lockflag;
1621 struct vnode **vpp;
1622 struct ucred *cred;
1623 struct nfssvc_sock *slp;
1624 struct mbuf *nam;
1625 int *rdonlyp;
1626 int kerbflag;
1627 {
1628 struct proc *p = curproc;
1629 struct mount *mp;
1630 int i;
1631 struct ucred *credanon;
1632 int error, exflags;
1633 struct sockaddr_in *saddr;
1634
1635 *vpp = (struct vnode *)0;
1636 mp = vfs_getvfs(&fhp->fh_fsid);
1637
1638 if (!mp)
1639 return (ESTALE);
1640 error = VFS_CHECKEXP(mp, nam, &exflags, &credanon);
1641 if (error)
1642 return (error);
1643 error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
1644 if (error)
1645 return (error);
1646
1647 saddr = mtod(nam, struct sockaddr_in *);
1648 if (saddr->sin_family == AF_INET &&
1649 (ntohs(saddr->sin_port) >= IPPORT_RESERVED ||
1650 (slp->ns_so->so_type == SOCK_STREAM && ntohs(saddr->sin_port) == 20))) {
1651 vput(*vpp);
1652 return (NFSERR_AUTHERR | AUTH_TOOWEAK);
1653 }
1654
1655
1656
1657
1658 if (exflags & MNT_EXKERB) {
1659 if (!kerbflag) {
1660 vput(*vpp);
1661 return (NFSERR_AUTHERR | AUTH_TOOWEAK);
1662 }
1663 } else if (kerbflag) {
1664 vput(*vpp);
1665 return (NFSERR_AUTHERR | AUTH_TOOWEAK);
1666 } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
1667 cred->cr_uid = credanon->cr_uid;
1668 cred->cr_gid = credanon->cr_gid;
1669 for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
1670 cred->cr_groups[i] = credanon->cr_groups[i];
1671 cred->cr_ngroups = i;
1672 }
1673 if (exflags & MNT_EXRDONLY)
1674 *rdonlyp = 1;
1675 else
1676 *rdonlyp = 0;
1677 if (!lockflag)
1678 VOP_UNLOCK(*vpp, 0, p);
1679
1680 return (0);
1681 }
1682
1683
1684
1685
1686
1687
1688
1689
1690 int
1691 netaddr_match(family, haddr, nam)
1692 int family;
1693 union nethostaddr *haddr;
1694 struct mbuf *nam;
1695 {
1696 struct sockaddr_in *inetaddr;
1697
1698 switch (family) {
1699 case AF_INET:
1700 inetaddr = mtod(nam, struct sockaddr_in *);
1701 if (inetaddr->sin_family == AF_INET &&
1702 inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
1703 return (1);
1704 break;
1705 default:
1706 break;
1707 };
1708 return (0);
1709 }
1710
1711
1712
1713
1714
1715
1716
1717 void
1718 nfs_clearcommit(mp)
1719 struct mount *mp;
1720 {
1721 struct vnode *vp, *nvp;
1722 struct buf *bp, *nbp;
1723 int s;
1724
1725 s = splbio();
1726 loop:
1727 for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp != NULL; vp = nvp) {
1728 if (vp->v_mount != mp)
1729 goto loop;
1730 nvp = LIST_NEXT(vp, v_mntvnodes);
1731 for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) {
1732 nbp = LIST_NEXT(bp, b_vnbufs);
1733 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
1734 == (B_DELWRI | B_NEEDCOMMIT))
1735 bp->b_flags &= ~B_NEEDCOMMIT;
1736 }
1737 }
1738 splx(s);
1739 }
1740
1741 void
1742 nfs_merge_commit_ranges(vp)
1743 struct vnode *vp;
1744 {
1745 struct nfsnode *np = VTONFS(vp);
1746
1747 if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) {
1748 np->n_pushedlo = np->n_pushlo;
1749 np->n_pushedhi = np->n_pushhi;
1750 np->n_commitflags |= NFS_COMMIT_PUSHED_VALID;
1751 } else {
1752 if (np->n_pushlo < np->n_pushedlo)
1753 np->n_pushedlo = np->n_pushlo;
1754 if (np->n_pushhi > np->n_pushedhi)
1755 np->n_pushedhi = np->n_pushhi;
1756 }
1757
1758 np->n_pushlo = np->n_pushhi = 0;
1759 np->n_commitflags &= ~NFS_COMMIT_PUSH_VALID;
1760 }
1761
1762 int
1763 nfs_in_committed_range(vp, bp)
1764 struct vnode *vp;
1765 struct buf *bp;
1766 {
1767 struct nfsnode *np = VTONFS(vp);
1768 off_t lo, hi;
1769
1770 if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID))
1771 return 0;
1772 lo = (off_t)bp->b_blkno * DEV_BSIZE;
1773 hi = lo + bp->b_dirtyend;
1774
1775 return (lo >= np->n_pushedlo && hi <= np->n_pushedhi);
1776 }
1777
1778 int
1779 nfs_in_tobecommitted_range(vp, bp)
1780 struct vnode *vp;
1781 struct buf *bp;
1782 {
1783 struct nfsnode *np = VTONFS(vp);
1784 off_t lo, hi;
1785
1786 if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID))
1787 return 0;
1788 lo = (off_t)bp->b_blkno * DEV_BSIZE;
1789 hi = lo + bp->b_dirtyend;
1790
1791 return (lo >= np->n_pushlo && hi <= np->n_pushhi);
1792 }
1793
1794 void
1795 nfs_add_committed_range(vp, bp)
1796 struct vnode *vp;
1797 struct buf *bp;
1798 {
1799 struct nfsnode *np = VTONFS(vp);
1800 off_t lo, hi;
1801
1802 lo = (off_t)bp->b_blkno * DEV_BSIZE;
1803 hi = lo + bp->b_dirtyend;
1804
1805 if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) {
1806 np->n_pushedlo = lo;
1807 np->n_pushedhi = hi;
1808 np->n_commitflags |= NFS_COMMIT_PUSHED_VALID;
1809 } else {
1810 if (hi > np->n_pushedhi)
1811 np->n_pushedhi = hi;
1812 if (lo < np->n_pushedlo)
1813 np->n_pushedlo = lo;
1814 }
1815 }
1816
1817 void
1818 nfs_del_committed_range(vp, bp)
1819 struct vnode *vp;
1820 struct buf *bp;
1821 {
1822 struct nfsnode *np = VTONFS(vp);
1823 off_t lo, hi;
1824
1825 if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID))
1826 return;
1827
1828 lo = (off_t)bp->b_blkno * DEV_BSIZE;
1829 hi = lo + bp->b_dirtyend;
1830
1831 if (lo > np->n_pushedhi || hi < np->n_pushedlo)
1832 return;
1833 if (lo <= np->n_pushedlo)
1834 np->n_pushedlo = hi;
1835 else if (hi >= np->n_pushedhi)
1836 np->n_pushedhi = lo;
1837 else {
1838
1839
1840
1841
1842
1843 if ((np->n_pushedlo - lo) > (hi - np->n_pushedhi))
1844 np->n_pushedhi = lo;
1845 else
1846 np->n_pushedlo = hi;
1847 }
1848 }
1849
1850 void
1851 nfs_add_tobecommitted_range(vp, bp)
1852 struct vnode *vp;
1853 struct buf *bp;
1854 {
1855 struct nfsnode *np = VTONFS(vp);
1856 off_t lo, hi;
1857
1858 lo = (off_t)bp->b_blkno * DEV_BSIZE;
1859 hi = lo + bp->b_dirtyend;
1860
1861 if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID)) {
1862 np->n_pushlo = lo;
1863 np->n_pushhi = hi;
1864 np->n_commitflags |= NFS_COMMIT_PUSH_VALID;
1865 } else {
1866 if (lo < np->n_pushlo)
1867 np->n_pushlo = lo;
1868 if (hi > np->n_pushhi)
1869 np->n_pushhi = hi;
1870 }
1871 }
1872
1873 void
1874 nfs_del_tobecommitted_range(vp, bp)
1875 struct vnode *vp;
1876 struct buf *bp;
1877 {
1878 struct nfsnode *np = VTONFS(vp);
1879 off_t lo, hi;
1880
1881 if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID))
1882 return;
1883
1884 lo = (off_t)bp->b_blkno * DEV_BSIZE;
1885 hi = lo + bp->b_dirtyend;
1886
1887 if (lo > np->n_pushhi || hi < np->n_pushlo)
1888 return;
1889
1890 if (lo <= np->n_pushlo)
1891 np->n_pushlo = hi;
1892 else if (hi >= np->n_pushhi)
1893 np->n_pushhi = lo;
1894 else {
1895
1896
1897
1898
1899
1900 if ((np->n_pushlo - lo) > (hi - np->n_pushhi))
1901 np->n_pushhi = lo;
1902 else
1903 np->n_pushlo = hi;
1904 }
1905 }
1906
1907
1908
1909
1910
1911 int
1912 nfsrv_errmap(nd, err)
1913 struct nfsrv_descript *nd;
1914 int err;
1915 {
1916 short *defaulterrp, *errp;
1917
1918 if (nd->nd_flag & ND_NFSV3) {
1919 if (nd->nd_procnum <= NFSPROC_COMMIT) {
1920 errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
1921 while (*++errp) {
1922 if (*errp == err)
1923 return (err);
1924 else if (*errp > err)
1925 break;
1926 }
1927 return ((int)*defaulterrp);
1928 } else
1929 return (err & 0xffff);
1930 }
1931 if (err <= ELAST)
1932 return ((int)nfsrv_v2errmap[err - 1]);
1933 return (NFSERR_IO);
1934 }
1935
1936
1937
1938
1939
1940
1941 void
1942 nfsrvw_sort(list, num)
1943 gid_t *list;
1944 int num;
1945 {
1946 int i, j;
1947 gid_t v;
1948
1949
1950 for (i = 1; i < num; i++) {
1951 v = list[i];
1952
1953 for (j = i; --j >= 0 && v < list[j];)
1954 list[j + 1] = list[j];
1955 list[j + 1] = v;
1956 }
1957 }
1958
1959
1960
1961
1962 void
1963 nfsrv_setcred(incred, outcred)
1964 struct ucred *incred, *outcred;
1965 {
1966 int i;
1967
1968 bzero((caddr_t)outcred, sizeof (struct ucred));
1969 outcred->cr_ref = 1;
1970 outcred->cr_uid = incred->cr_uid;
1971 outcred->cr_gid = incred->cr_gid;
1972 outcred->cr_ngroups = incred->cr_ngroups;
1973 for (i = 0; i < incred->cr_ngroups; i++)
1974 outcred->cr_groups[i] = incred->cr_groups[i];
1975 nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups);
1976 }