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