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