|
|
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:
593: /*
594: * Create the header for an rpc request packet
595: * The hsiz is the size of the rest of the nfs request header.
596: * (just used to decide if a cluster is a good idea)
597: */
598: struct mbuf *
599: nfsm_reqh(vp, procid, hsiz, bposp)
600: struct vnode *vp;
601: u_long procid;
602: int hsiz;
603: caddr_t *bposp;
604: {
605: register struct mbuf *mb;
606: register u_long *tl;
607: register caddr_t bpos;
608: struct mbuf *mb2;
609: struct nfsmount *nmp;
610: int nqflag;
611:
612: MGET(mb, M_WAIT, MT_DATA);
613: if (hsiz >= MINCLSIZE)
614: MCLGET(mb, M_WAIT);
615: mb->m_len = 0;
616: bpos = mtod(mb, caddr_t);
617:
618: /*
619: * For NQNFS, add lease request.
620: */
621: if (vp) {
622: nmp = VFSTONFS(vp->v_mount);
623: if (nmp->nm_flag & NFSMNT_NQNFS) {
624: nqflag = NQNFS_NEEDLEASE(vp, procid);
625: if (nqflag) {
626: nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
627: *tl++ = txdr_unsigned(nqflag);
628: *tl = txdr_unsigned(nmp->nm_leaseterm);
629: } else {
630: nfsm_build(tl, u_long *, NFSX_UNSIGNED);
631: *tl = 0;
632: }
633: }
634: }
635: /* Finally, return values */
636: *bposp = bpos;
637: return (mb);
638: }
639:
640: /*
641: * Build the RPC header and fill in the authorization info.
642: * The authorization string argument is only used when the credentials
643: * come from outside of the kernel.
644: * Returns the head of the mbuf list.
645: */
646: struct mbuf *
647: nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
648: verf_str, mrest, mrest_len, mbp, xidp)
649: register struct ucred *cr;
650: int nmflag;
651: int procid;
652: int auth_type;
653: int auth_len;
654: char *auth_str;
655: int verf_len;
656: char *verf_str;
657: struct mbuf *mrest;
658: int mrest_len;
659: struct mbuf **mbp;
660: u_long *xidp;
661: {
662: register struct mbuf *mb;
663: register u_long *tl;
664: register caddr_t bpos;
665: register int i;
666: struct mbuf *mreq, *mb2;
667: int siz, grpsiz, authsiz;
668: struct timeval tv;
669: static u_long base;
670:
671: authsiz = nfsm_rndup(auth_len);
672: MGETHDR(mb, M_WAIT, MT_DATA);
673: if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) {
674: MCLGET(mb, M_WAIT);
675: } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) {
676: MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
677: } else {
678: MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
679: }
680: mb->m_len = 0;
681: mreq = mb;
682: bpos = mtod(mb, caddr_t);
683:
684: /*
685: * First the RPC header.
686: */
687: nfsm_build(tl, u_long *, 8 * NFSX_UNSIGNED);
688:
689: /*
690: * derive initial xid from system time
691: * XXX time is invalid if root not yet mounted
692: */
693: if (!base && (rootvp)) {
694: microtime(&tv);
695: base = tv.tv_sec << 12;
696: nfs_xid = base;
697: }
698: /*
699: * Skip zero xid if it should ever happen.
700: */
701: if (++nfs_xid == 0)
702: nfs_xid++;
703:
704: *tl++ = *xidp = txdr_unsigned(nfs_xid);
705: *tl++ = rpc_call;
706: *tl++ = rpc_vers;
707: if (nmflag & NFSMNT_NQNFS) {
708: *tl++ = txdr_unsigned(NQNFS_PROG);
709: *tl++ = txdr_unsigned(NQNFS_VER3);
710: } else {
711: *tl++ = txdr_unsigned(NFS_PROG);
712: if (nmflag & NFSMNT_NFSV3)
713: *tl++ = txdr_unsigned(NFS_VER3);
714: else
715: *tl++ = txdr_unsigned(NFS_VER2);
716: }
717: if (nmflag & NFSMNT_NFSV3)
718: *tl++ = txdr_unsigned(procid);
719: else
720: *tl++ = txdr_unsigned(nfsv2_procid[procid]);
721:
722: /*
723: * And then the authorization cred.
724: */
725: *tl++ = txdr_unsigned(auth_type);
726: *tl = txdr_unsigned(authsiz);
727: switch (auth_type) {
728: case RPCAUTH_UNIX:
729: nfsm_build(tl, u_long *, auth_len);
730: *tl++ = 0; /* stamp ?? */
731: *tl++ = 0; /* NULL hostname */
732: *tl++ = txdr_unsigned(cr->cr_uid);
733: *tl++ = txdr_unsigned(cr->cr_groups[0]);
734: grpsiz = (auth_len >> 2) - 5;
735: *tl++ = txdr_unsigned(grpsiz);
736: for (i = 1; i <= grpsiz; i++)
737: *tl++ = txdr_unsigned(cr->cr_groups[i]);
738: break;
739: case RPCAUTH_KERB4:
740: siz = auth_len;
741: while (siz > 0) {
742: if (M_TRAILINGSPACE(mb) == 0) {
743: MGET(mb2, M_WAIT, MT_DATA);
744: if (siz >= MINCLSIZE)
745: MCLGET(mb2, M_WAIT);
746: mb->m_next = mb2;
747: mb = mb2;
748: mb->m_len = 0;
749: bpos = mtod(mb, caddr_t);
750: }
751: i = min(siz, M_TRAILINGSPACE(mb));
752: bcopy(auth_str, bpos, i);
753: mb->m_len += i;
754: auth_str += i;
755: bpos += i;
756: siz -= i;
757: }
758: if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) {
759: for (i = 0; i < siz; i++)
760: *bpos++ = '\0';
761: mb->m_len += siz;
762: }
763: break;
764: };
765:
766: /*
767: * And the verifier...
768: */
769: nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
770: if (verf_str) {
771: *tl++ = txdr_unsigned(RPCAUTH_KERB4);
772: *tl = txdr_unsigned(verf_len);
773: siz = verf_len;
774: while (siz > 0) {
775: if (M_TRAILINGSPACE(mb) == 0) {
776: MGET(mb2, M_WAIT, MT_DATA);
777: if (siz >= MINCLSIZE)
778: MCLGET(mb2, M_WAIT);
779: mb->m_next = mb2;
780: mb = mb2;
781: mb->m_len = 0;
782: bpos = mtod(mb, caddr_t);
783: }
784: i = min(siz, M_TRAILINGSPACE(mb));
785: bcopy(verf_str, bpos, i);
786: mb->m_len += i;
787: verf_str += i;
788: bpos += i;
789: siz -= i;
790: }
791: if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) {
792: for (i = 0; i < siz; i++)
793: *bpos++ = '\0';
794: mb->m_len += siz;
795: }
796: } else {
797: *tl++ = txdr_unsigned(RPCAUTH_NULL);
798: *tl = 0;
799: }
800: mb->m_next = mrest;
801: mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
802: mreq->m_pkthdr.rcvif = (struct ifnet *)0;
803: *mbp = mb;
804: return (mreq);
805: }
806:
807: /*
808: * copies mbuf chain to the uio scatter/gather list
809: */
810: int
811: nfsm_mbuftouio(mrep, uiop, siz, dpos)
812: struct mbuf **mrep;
813: register struct uio *uiop;
814: int siz;
815: caddr_t *dpos;
816: {
817: register char *mbufcp, *uiocp;
818: register int xfer, left, len;
819: register struct mbuf *mp;
820: long uiosiz, rem;
821: int error = 0;
822:
823: mp = *mrep;
824: mbufcp = *dpos;
825: len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
826: rem = nfsm_rndup(siz)-siz;
827: while (siz > 0) {
828: if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
829: return (EFBIG);
830: left = uiop->uio_iov->iov_len;
831: uiocp = uiop->uio_iov->iov_base;
832: if (left > siz)
833: left = siz;
834: uiosiz = left;
835: while (left > 0) {
836: while (len == 0) {
837: mp = mp->m_next;
838: if (mp == NULL)
839: return (EBADRPC);
840: mbufcp = mtod(mp, caddr_t);
841: len = mp->m_len;
842: }
843: xfer = (left > len) ? len : left;
844: #ifdef notdef
845: /* Not Yet.. */
846: if (uiop->uio_iov->iov_op != NULL)
847: (*(uiop->uio_iov->iov_op))
848: (mbufcp, uiocp, xfer);
849: else
850: #endif
851: if (uiop->uio_segflg == UIO_SYSSPACE)
852: bcopy(mbufcp, uiocp, xfer);
853: else
854: copyout(mbufcp, uiocp, xfer);
855: left -= xfer;
856: len -= xfer;
857: mbufcp += xfer;
858: uiocp += xfer;
859: uiop->uio_offset += xfer;
860: uiop->uio_resid -= xfer;
861: }
862: if (uiop->uio_iov->iov_len <= siz) {
863: uiop->uio_iovcnt--;
864: uiop->uio_iov++;
865: } else {
866: uiop->uio_iov->iov_base += uiosiz;
867: uiop->uio_iov->iov_len -= uiosiz;
868: }
869: siz -= uiosiz;
870: }
871: *dpos = mbufcp;
872: *mrep = mp;
873: if (rem > 0) {
874: if (len < rem)
875: error = nfs_adv(mrep, dpos, rem, len);
876: else
877: *dpos += rem;
878: }
879: return (error);
880: }
881:
882: /*
883: * copies a uio scatter/gather list to an mbuf chain.
884: * NOTE: can ony handle iovcnt == 1
885: */
886: int
887: nfsm_uiotombuf(uiop, mq, siz, bpos)
888: register struct uio *uiop;
889: struct mbuf **mq;
890: int siz;
891: caddr_t *bpos;
892: {
893: register char *uiocp;
894: register struct mbuf *mp, *mp2;
895: register int xfer, left, mlen;
896: int uiosiz, clflg, rem;
897: char *cp;
898:
899: if (uiop->uio_iovcnt != 1)
900: panic("nfsm_uiotombuf: iovcnt != 1");
901:
902: if (siz > MLEN) /* or should it >= MCLBYTES ?? */
903: clflg = 1;
904: else
905: clflg = 0;
906: rem = nfsm_rndup(siz)-siz;
907: mp = mp2 = *mq;
908: while (siz > 0) {
909: left = uiop->uio_iov->iov_len;
910: uiocp = uiop->uio_iov->iov_base;
911: if (left > siz)
912: left = siz;
913: uiosiz = left;
914: while (left > 0) {
915: mlen = M_TRAILINGSPACE(mp);
916: if (mlen == 0) {
917: MGET(mp, M_WAIT, MT_DATA);
918: if (clflg)
919: MCLGET(mp, M_WAIT);
920: mp->m_len = 0;
921: mp2->m_next = mp;
922: mp2 = mp;
923: mlen = M_TRAILINGSPACE(mp);
924: }
925: xfer = (left > mlen) ? mlen : left;
926: #ifdef notdef
927: /* Not Yet.. */
928: if (uiop->uio_iov->iov_op != NULL)
929: (*(uiop->uio_iov->iov_op))
930: (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
931: else
932: #endif
933: if (uiop->uio_segflg == UIO_SYSSPACE)
934: bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
935: else
936: copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
937: mp->m_len += xfer;
938: left -= xfer;
939: uiocp += xfer;
940: uiop->uio_offset += xfer;
941: uiop->uio_resid -= xfer;
942: }
943: uiop->uio_iov->iov_base += uiosiz;
944: uiop->uio_iov->iov_len -= uiosiz;
945: siz -= uiosiz;
946: }
947: if (rem > 0) {
948: if (rem > M_TRAILINGSPACE(mp)) {
949: MGET(mp, M_WAIT, MT_DATA);
950: mp->m_len = 0;
951: mp2->m_next = mp;
952: }
953: cp = mtod(mp, caddr_t)+mp->m_len;
954: for (left = 0; left < rem; left++)
955: *cp++ = '\0';
956: mp->m_len += rem;
957: *bpos = cp;
958: } else
959: *bpos = mtod(mp, caddr_t)+mp->m_len;
960: *mq = mp;
961: return (0);
962: }
963:
964: /*
965: * Help break down an mbuf chain by setting the first siz bytes contiguous
966: * pointed to by returned val.
967: * This is used by the macros nfsm_dissect and nfsm_dissecton for tough
968: * cases. (The macros use the vars. dpos and dpos2)
969: */
970: int
971: nfsm_disct(mdp, dposp, siz, left, cp2)
972: struct mbuf **mdp;
973: caddr_t *dposp;
974: int siz;
975: int left;
976: caddr_t *cp2;
977: {
978: register struct mbuf *mp, *mp2;
979: register int siz2, xfer;
980: register caddr_t p;
981:
982: mp = *mdp;
983: while (left == 0) {
984: *mdp = mp = mp->m_next;
985: if (mp == NULL)
986: return (EBADRPC);
987: left = mp->m_len;
988: *dposp = mtod(mp, caddr_t);
989: }
990: if (left >= siz) {
991: *cp2 = *dposp;
992: *dposp += siz;
993: } else if (mp->m_next == NULL) {
994: return (EBADRPC);
995: } else if (siz > MHLEN) {
996: panic("nfs S too big");
997: } else {
998: MGET(mp2, M_WAIT, MT_DATA);
999: mp2->m_next = mp->m_next;
1000: mp->m_next = mp2;
1001: mp->m_len -= left;
1002: mp = mp2;
1003: *cp2 = p = mtod(mp, caddr_t);
1004: bcopy(*dposp, p, left); /* Copy what was left */
1005: siz2 = siz-left;
1006: p += left;
1007: mp2 = mp->m_next;
1008: /* Loop around copying up the siz2 bytes */
1009: while (siz2 > 0) {
1010: if (mp2 == NULL)
1011: return (EBADRPC);
1012: xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
1013: if (xfer > 0) {
1014: bcopy(mtod(mp2, caddr_t), p, xfer);
1015: NFSMADV(mp2, xfer);
1016: mp2->m_len -= xfer;
1017: p += xfer;
1018: siz2 -= xfer;
1019: }
1020: if (siz2 > 0)
1021: mp2 = mp2->m_next;
1022: }
1023: mp->m_len = siz;
1024: *mdp = mp2;
1025: *dposp = mtod(mp2, caddr_t);
1026: }
1027: return (0);
1028: }
1029:
1030: /*
1031: * Advance the position in the mbuf chain.
1032: */
1033: int
1034: nfs_adv(mdp, dposp, offs, left)
1035: struct mbuf **mdp;
1036: caddr_t *dposp;
1037: int offs;
1038: int left;
1039: {
1040: register struct mbuf *m;
1041: register int s;
1042:
1043: m = *mdp;
1044: s = left;
1045: while (s < offs) {
1046: offs -= s;
1047: m = m->m_next;
1048: if (m == NULL)
1049: return (EBADRPC);
1050: s = m->m_len;
1051: }
1052: *mdp = m;
1053: *dposp = mtod(m, caddr_t)+offs;
1054: return (0);
1055: }
1056:
1057: /*
1058: * Copy a string into mbufs for the hard cases...
1059: */
1060: int
1061: nfsm_strtmbuf(mb, bpos, cp, siz)
1062: struct mbuf **mb;
1063: char **bpos;
1064: char *cp;
1065: long siz;
1066: {
1067: register struct mbuf *m1 = 0, *m2;
1068: long left, xfer, len, tlen;
1069: u_long *tl;
1070: int putsize;
1071:
1072: putsize = 1;
1073: m2 = *mb;
1074: left = M_TRAILINGSPACE(m2);
1075: if (left > 0) {
1076: tl = ((u_long *)(*bpos));
1077: *tl++ = txdr_unsigned(siz);
1078: putsize = 0;
1079: left -= NFSX_UNSIGNED;
1080: m2->m_len += NFSX_UNSIGNED;
1081: if (left > 0) {
1082: bcopy(cp, (caddr_t) tl, left);
1083: siz -= left;
1084: cp += left;
1085: m2->m_len += left;
1086: left = 0;
1087: }
1088: }
1089: /* Loop around adding mbufs */
1090: while (siz > 0) {
1091: MGET(m1, M_WAIT, MT_DATA);
1092: if (siz > MLEN)
1093: MCLGET(m1, M_WAIT);
1094: m1->m_len = NFSMSIZ(m1);
1095: m2->m_next = m1;
1096: m2 = m1;
1097: tl = mtod(m1, u_long *);
1098: tlen = 0;
1099: if (putsize) {
1100: *tl++ = txdr_unsigned(siz);
1101: m1->m_len -= NFSX_UNSIGNED;
1102: tlen = NFSX_UNSIGNED;
1103: putsize = 0;
1104: }
1105: if (siz < m1->m_len) {
1106: len = nfsm_rndup(siz);
1107: xfer = siz;
1108: if (xfer < len)
1109: *(tl+(xfer>>2)) = 0;
1110: } else {
1111: xfer = len = m1->m_len;
1112: }
1113: bcopy(cp, (caddr_t) tl, xfer);
1114: m1->m_len = len+tlen;
1115: siz -= xfer;
1116: cp += xfer;
1117: }
1118: *mb = m1;
1119: *bpos = mtod(m1, caddr_t)+m1->m_len;
1120: return (0);
1121: }
1122:
1123: /*
1124: * Called once to initialize data structures...
1125: */
1126: int
1127: nfs_init(vfsp)
1128: struct vfsconf *vfsp;
1129: {
1130: register int i;
1131:
1132: /*
1133: * Check to see if major data structures haven't bloated.
1134: */
1135: if (sizeof (struct nfsnode) > NFS_NODEALLOC) {
1136: printf("struct nfsnode bloated (> %dbytes)\n", NFS_NODEALLOC);
1137: printf("Try reducing NFS_SMALLFH\n");
1138: }
1139: if (sizeof (struct nfsmount) > NFS_MNTALLOC) {
1140: printf("struct nfsmount bloated (> %dbytes)\n", NFS_MNTALLOC);
1141: printf("Try reducing NFS_MUIDHASHSIZ\n");
1142: }
1143: if (sizeof (struct nfssvc_sock) > NFS_SVCALLOC) {
1144: printf("struct nfssvc_sock bloated (> %dbytes)\n",NFS_SVCALLOC);
1145: printf("Try reducing NFS_UIDHASHSIZ\n");
1146: }
1147: if (sizeof (struct nfsuid) > NFS_UIDALLOC) {
1148: printf("struct nfsuid bloated (> %dbytes)\n",NFS_UIDALLOC);
1149: printf("Try unionizing the nu_nickname and nu_flag fields\n");
1150: }
1151: nfs_mount_type = vfsp->vfc_typenum;
1152: nfsrtt.pos = 0;
1153: rpc_vers = txdr_unsigned(RPC_VER2);
1154: rpc_call = txdr_unsigned(RPC_CALL);
1155: rpc_reply = txdr_unsigned(RPC_REPLY);
1156: rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
1157: rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
1158: rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
1159: rpc_autherr = txdr_unsigned(RPC_AUTHERR);
1160: rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
1161: rpc_auth_kerb = txdr_unsigned(RPCAUTH_KERB4);
1162: nfs_prog = txdr_unsigned(NFS_PROG);
1163: nqnfs_prog = txdr_unsigned(NQNFS_PROG);
1164: nfs_true = txdr_unsigned(TRUE);
1165: nfs_false = txdr_unsigned(FALSE);
1166: nfs_xdrneg1 = txdr_unsigned(-1);
1167: nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
1168: if (nfs_ticks < 1)
1169: nfs_ticks = 1;
1170: /* Ensure async daemons disabled */
1171: for (i = 0; i < NFS_MAXASYNCDAEMON; i++) {
1172: nfs_iodwant[i] = (struct proc *)0;
1173: nfs_iodmount[i] = (struct nfsmount *)0;
1174: }
1175: nfs_nhinit(); /* Init the nfsnode table */
1176: #ifndef NFS_NOSERVER
1177: nfsrv_init(0); /* Init server data structures */
1178: nfsrv_initcache(); /* Init the server request cache */
1179: #endif
1180:
1181: /*
1182: * Initialize the nqnfs server stuff.
1183: */
1184: if (nqnfsstarttime == 0) {
1185: nqnfsstarttime = boottime.tv_sec + nqsrv_maxlease
1186: + nqsrv_clockskew + nqsrv_writeslack;
1187: NQLOADNOVRAM(nqnfsstarttime);
1188: CIRCLEQ_INIT(&nqtimerhead);
1189: nqfhhashtbl = hashinit(NQLCHSZ, M_NQLEASE, &nqfhhash);
1190: }
1191:
1192: /*
1193: * Initialize reply list and start timer
1194: */
1195: TAILQ_INIT(&nfs_reqq);
1196:
1197: nfs_timer(0);
1198:
1199:
1200: /* XXX CSM 12/4/97 Where are these declared in FreeBSD? */
1201: #ifdef notyet
1202: /*
1203: * Set up lease_check and lease_updatetime so that other parts
1204: * of the system can call us, if we are loadable.
1205: */
1206: #ifndef NFS_NOSERVER
1207: default_vnodeop_p[VOFFSET(vop_lease)] = (vop_t *)nqnfs_vop_lease_check;
1208: #endif
1209: lease_updatetime = nfs_lease_updatetime;
1210: #endif
1211: vfsp->vfc_refcount++; /* make us non-unloadable */
1212: sysent[SYS_nfssvc].sy_narg = 2;
1213: sysent[SYS_nfssvc].sy_call = nfssvc;
1214: #ifndef NFS_NOSERVER
1215: sysent[SYS_getfh].sy_narg = 2;
1216: sysent[SYS_getfh].sy_call = getfh;
1217: #endif
1218:
1219: return (0);
1220: }
1221:
1222: /*
1223: * Attribute cache routines.
1224: * nfs_loadattrcache() - loads or updates the cache contents from attributes
1225: * that are on the mbuf list
1226: * nfs_getattrcache() - returns valid attributes if found in cache, returns
1227: * error otherwise
1228: */
1229:
1230: /*
1231: * Load the attribute cache (that lives in the nfsnode entry) with
1232: * the values on the mbuf list and
1233: * Iff vap not NULL
1234: * copy the attributes to *vaper
1235: */
1236: int
1237: nfs_loadattrcache(vpp, mdp, dposp, vaper)
1238: struct vnode **vpp;
1239: struct mbuf **mdp;
1240: caddr_t *dposp;
1241: struct vattr *vaper;
1242: {
1243: register struct vnode *vp = *vpp;
1244: register struct vattr *vap;
1245: register struct nfs_fattr *fp;
1246: register struct nfsnode *np;
1247: register long t1;
1248: caddr_t cp2;
1249: int error = 0, rdev;
1250: struct mbuf *md;
1251: enum vtype vtyp;
1252: u_short vmode;
1253: struct timespec mtime;
1254: struct vnode *nvp;
1255: int v3 = NFS_ISV3(vp);
1256:
1257: NFSTRACE(NFSTRC_LAC, vp);
1258: md = *mdp;
1259: t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
1260: if ((error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2)))
1261: return (error);
1262: fp = (struct nfs_fattr *)cp2;
1263: if (v3) {
1264: vtyp = nfsv3tov_type(fp->fa_type);
1265: vmode = fxdr_unsigned(u_short, fp->fa_mode);
1266: rdev = makedev(fxdr_unsigned(int, fp->fa3_rdev.specdata1),
1267: fxdr_unsigned(int, fp->fa3_rdev.specdata2));
1268: fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
1269: } else {
1270: vtyp = nfsv2tov_type(fp->fa_type);
1271: vmode = fxdr_unsigned(u_short, fp->fa_mode);
1272: /*
1273: * XXX
1274: *
1275: * The duplicate information returned in fa_type and fa_mode
1276: * is an ambiguity in the NFS version 2 protocol.
1277: *
1278: * VREG should be taken literally as a regular file. If a
1279: * server intents to return some type information differently
1280: * in the upper bits of the mode field (e.g. for sockets, or
1281: * FIFOs), NFSv2 mandates fa_type to be VNON. Anyway, we
1282: * leave the examination of the mode bits even in the VREG
1283: * case to avoid breakage for bogus servers, but we make sure
1284: * that there are actually type bits set in the upper part of
1285: * fa_mode (and failing that, trust the va_type field).
1286: *
1287: * NFSv3 cleared the issue, and requires fa_mode to not
1288: * contain any type information (while also introduing sockets
1289: * and FIFOs for fa_type).
1290: */
1291: if (vtyp == VNON || (vtyp == VREG && (vmode & S_IFMT) != 0))
1292: vtyp = IFTOVT(vmode);
1293: rdev = fxdr_unsigned(long, fp->fa2_rdev);
1294: fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
1295:
1296: /*
1297: * Really ugly NFSv2 kludge.
1298: */
1299: if (vtyp == VCHR && rdev == 0xffffffff)
1300: vtyp = VFIFO;
1301: }
1302:
1303: /*
1304: * If v_type == VNON it is a new node, so fill in the v_type,
1305: * n_mtime fields. Check to see if it represents a special
1306: * device, and if so, check for a possible alias. Once the
1307: * correct vnode has been obtained, fill in the rest of the
1308: * information.
1309: */
1310: np = VTONFS(vp);
1311: if (vp->v_type != vtyp) {
1312: vp->v_type = vtyp;
1313: #if MACH_NBC
1314: if ((vp->v_type == VREG) && !(vp->v_vm_info)){
1315: vm_info_init(vp);
1316: }
1317: #endif /* MACH_NBC */
1318: if (vp->v_type == VFIFO) {
1319: vp->v_op = fifo_nfsv2nodeop_p;
1320: }
1321: if (vp->v_type == VCHR || vp->v_type == VBLK) {
1322: vp->v_op = spec_nfsv2nodeop_p;
1323: nvp = checkalias(vp, (dev_t)rdev, vp->v_mount);
1324: if (nvp) {
1325: /*
1326: * Discard unneeded vnode, but save its nfsnode.
1327: * Since the nfsnode does not have a lock, its
1328: * vnode lock has to be carried over.
1329: */
1330: nvp->v_vnlock = vp->v_vnlock;
1331: vp->v_vnlock = NULL;
1332: nvp->v_data = vp->v_data;
1333: vp->v_data = NULL;
1334: vp->v_op = spec_vnodeop_p;
1335: vrele(vp);
1336: vgone(vp);
1337: /*
1338: * Reinitialize aliased node.
1339: */
1340: np->n_vnode = nvp;
1341: *vpp = vp = nvp;
1342: }
1343: }
1344: np->n_mtime = mtime.tv_sec;
1345: NFSTRACE(NFSTRC_LAC_INIT, vp);
1346: }
1347: vap = &np->n_vattr;
1348: vap->va_type = vtyp;
1349: vap->va_mode = (vmode & 07777);
1350: vap->va_rdev = (dev_t)rdev;
1351: vap->va_mtime = mtime;
1352: vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
1353: if (v3) {
1354: vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
1355: vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
1356: vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
1357: fxdr_hyper(&fp->fa3_size, &vap->va_size);
1358: vap->va_blocksize = NFS_FABLKSIZE;
1359: fxdr_hyper(&fp->fa3_used, &vap->va_bytes);
1360: vap->va_fileid = fxdr_unsigned(int, fp->fa3_fileid.nfsuquad[1]);
1361: fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
1362: fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
1363: vap->va_flags = 0;
1364: vap->va_filerev = 0;
1365: } else {
1366: vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
1367: vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
1368: vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
1369: vap->va_size = fxdr_unsigned(u_long, fp->fa2_size);
1370: vap->va_blocksize = fxdr_unsigned(long, fp->fa2_blocksize);
1371: vap->va_bytes = fxdr_unsigned(long, fp->fa2_blocks) * NFS_FABLKSIZE;
1372: vap->va_fileid = fxdr_unsigned(long, fp->fa2_fileid);
1373: fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
1374: vap->va_flags = 0;
1375: vap->va_ctime.tv_sec = fxdr_unsigned(long, fp->fa2_ctime.nfsv2_sec);
1376: vap->va_ctime.tv_nsec = 0;
1377: vap->va_gen = fxdr_unsigned(u_long, fp->fa2_ctime.nfsv2_usec);
1378: vap->va_filerev = 0;
1379: }
1380:
1381: if (vap->va_size != np->n_size) {
1382: NFSTRACE4(NFSTRC_LAC_NP, vp, vap->va_size, np->n_size,
1383: (vap->va_type == VREG) |
1384: (np->n_flag & NMODIFIED ? 2 : 0));
1385: if (vap->va_type == VREG) {
1386: if (np->n_flag & NMODIFIED) {
1387: if (vap->va_size < np->n_size)
1388: vap->va_size = np->n_size;
1389: else
1390: np->n_size = vap->va_size;
1391: } else
1392: np->n_size = vap->va_size;
1393: #if !MACH_NBC
1394: vnode_pager_setsize(vp, (u_long)np->n_size);
1395: #endif /* MACH_NBC */
1396: } else
1397: np->n_size = vap->va_size;
1398: }
1399:
1400: #if MACH_NBC
1401: if (vap->va_type == VREG && vp->v_vm_info && vp->v_vm_info->mapped &&
1402: vap->va_size != vp->v_vm_info->vnode_size) {
1403: struct vm_info *vmp = vp->v_vm_info;
1404:
1405: NFSTRACE4(NFSTRC_LAC_MAP, vp, vap->va_size, vmp->vnode_size,
1406: ((long)(vmp->lock.thread) > 0 ? 0x1000 : 0) |
1407: (vmp->lock.thread == current_thread() ? 0x2000 : 0) |
1408: (vmp->lock.want_write ? 0x0100 : 0) |
1409: (vmp->lock.want_upgrade ? 0x0200 : 0) |
1410: (vmp->lock.read_count ? 0x0400 : 0) |
1411: (vmp->nfsdirty ? 0x0010 : 0) |
1412: (np->n_flag & NMODIFIED ? 0x0001 : 0));
1413: if (vmp->nfsdirty || np->n_flag & NMODIFIED) {
1414: np->n_size = vap->va_size = vmp->vnode_size;
1415: } else if (vmp->lock.want_write || vmp->lock.want_upgrade ||
1416: vmp->lock.read_count) {
1417: vmp->invalidate = TRUE; /* vmp_put will do it */
1418: #if DIAGNOSTIC
1419: kprintf("nfs_loadattrcache: invalidate vp %x\n",
1420: (unsigned)vp);
1421: #endif /* DIAGNOSTIC */
1422: } else { /* clear the way for server's dirt */
1423: mapfs_memfree(vmp, TRUE);
1424: vmp->vnode_size = vap->va_size;
1425: #if DIAGNOSTIC
1426: kprintf("nfs_loadattrcache: memfree vp %x\n",
1427: (unsigned)vp);
1428: #endif /* DIAGNOSTIC */
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 */
1506: #if DIAGNOSTIC
1507: kprintf("nfs_getattrcache: invalidate vp %x\n",
1508: (unsigned)vp);
1509: #endif /* DIAGNOSTIC */
1510: } else { /* clear the way for server's dirt */
1511: mapfs_memfree(vmp, TRUE);
1512: vmp->vnode_size = vap->va_size;
1513: #if DIAGNOSTIC
1514: kprintf("nfs_getattrcache: memfree vp %x\n",
1515: (unsigned)vp);
1516: #endif /* DIAGNOSTIC */
1517: }
1518: }
1519: #endif /* MACH_NBC */
1520:
1521: bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));
1522: if (np->n_flag & NCHG) {
1523: if (np->n_flag & NACC)
1524: vaper->va_atime = np->n_atim;
1525: if (np->n_flag & NUPD)
1526: vaper->va_mtime = np->n_mtim;
1527: }
1528: return (0);
1529: }
1530:
1531: #ifndef NFS_NOSERVER
1532: /*
1533: * Set up nameidata for a lookup() call and do it.
1534: *
1535: * If pubflag is set, this call is done for a lookup operation on the
1536: * public filehandle. In that case we allow crossing mountpoints and
1537: * absolute pathnames. However, the caller is expected to check that
1538: * the lookup result is within the public fs, and deny access if
1539: * it is not.
1540: */
1541: int
1542: nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag, pubflag)
1543: register struct nameidata *ndp;
1544: fhandle_t *fhp;
1545: int len;
1546: struct nfssvc_sock *slp;
1547: struct mbuf *nam;
1548: struct mbuf **mdp;
1549: caddr_t *dposp;
1550: struct vnode **retdirp;
1551: struct proc *p;
1552: int kerbflag, pubflag;
1553: {
1554: register int i, rem;
1555: register struct mbuf *md;
1556: register char *fromcp, *tocp, *cp;
1557: struct iovec aiov;
1558: struct uio auio;
1559: struct vnode *dp;
1560: int error, rdonly, linklen;
1561: struct componentname *cnp = &ndp->ni_cnd;
1562: int olen = len;
1563:
1564: *retdirp = (struct vnode *)0;
1565: MALLOC_ZONE(cnp->cn_pnbuf, char *, len + 1, M_NAMEI, M_WAITOK);
1566: cnp->cn_pnlen = len + 1;
1567:
1568: /*
1569: * Copy the name from the mbuf list to ndp->ni_pnbuf
1570: * and set the various ndp fields appropriately.
1571: */
1572: fromcp = *dposp;
1573: tocp = cnp->cn_pnbuf;
1574: md = *mdp;
1575: rem = mtod(md, caddr_t) + md->m_len - fromcp;
1576: cnp->cn_hash = 0;
1577: for (i = 1; i <= len; i++) {
1578: while (rem == 0) {
1579: md = md->m_next;
1580: if (md == NULL) {
1581: error = EBADRPC;
1582: goto out;
1583: }
1584: fromcp = mtod(md, caddr_t);
1585: rem = md->m_len;
1586: }
1587: /* XXX CSM 12/4/97 Revisit when enabling WebNFS */
1588: #ifdef notdef
1589: if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) {
1590: #else
1591: if (*fromcp == '\0' || *fromcp == '/') {
1592: #endif
1593: error = EACCES;
1594: goto out;
1595: }
1596: cnp->cn_hash += (unsigned char)*fromcp * i;
1597: *tocp++ = *fromcp++;
1598: rem--;
1599: }
1600: *tocp = '\0';
1601: *mdp = md;
1602: *dposp = fromcp;
1603: len = nfsm_rndup(len)-len;
1604: if (len > 0) {
1605: if (rem >= len)
1606: *dposp += len;
1607: else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0)
1608: goto out;
1609: }
1610:
1611: /*
1612: * Extract and set starting directory.
1613: */
1614: error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
1615: nam, &rdonly, kerbflag, pubflag);
1616: if (error)
1617: goto out;
1618: if (dp->v_type != VDIR) {
1619: vrele(dp);
1620: error = ENOTDIR;
1621: goto out;
1622: }
1623:
1624: if (rdonly)
1625: cnp->cn_flags |= RDONLY;
1626:
1627: *retdirp = dp;
1628:
1629: /* XXX CSM 12/4/97 Revisit when enabling WebNFS */
1630: /* XXX debo 12/15/97 Need to fix M_NAMEI allocations to use zone protocol */
1631: #ifdef notyet
1632: if (pubflag) {
1633: /*
1634: * Oh joy. For WebNFS, handle those pesky '%' escapes,
1635: * and the 'native path' indicator.
1636: */
1637: MALLOC(cp, char *, olen + 1, M_NAMEI, M_WAITOK);
1638: fromcp = cnp->cn_pnbuf;
1639: tocp = cp;
1640: if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) {
1641: switch ((unsigned char)*fromcp) {
1642: case WEBNFS_NATIVE_CHAR:
1643: /*
1644: * 'Native' path for us is the same
1645: * as a path according to the NFS spec,
1646: * just skip the escape char.
1647: */
1648: fromcp++;
1649: break;
1650: /*
1651: * More may be added in the future, range 0x80-0xff
1652: */
1653: default:
1654: error = EIO;
1655: FREE(cp, M_NAMEI);
1656: goto out;
1657: }
1658: }
1659: /*
1660: * Translate the '%' escapes, URL-style.
1661: */
1662: while (*fromcp != '\0') {
1663: if (*fromcp == WEBNFS_ESC_CHAR) {
1664: if (fromcp[1] != '\0' && fromcp[2] != '\0') {
1665: fromcp++;
1666: *tocp++ = HEXSTRTOI(fromcp);
1667: fromcp += 2;
1668: continue;
1669: } else {
1670: error = ENOENT;
1671: FREE(cp, M_NAMEI);
1672: goto out;
1673: }
1674: } else
1675: *tocp++ = *fromcp++;
1676: }
1677: *tocp = '\0';
1678: FREE(cnp->cn_pnbuf, M_NAMEI);
1679: cnp->cn_pnbuf = cp;
1680: }
1681: #endif
1682:
1683: ndp->ni_pathlen = (tocp - cnp->cn_pnbuf) + 1;
1684: ndp->ni_segflg = UIO_SYSSPACE;
1685:
1686: /* XXX CSM 12/4/97 Revisit when enabling WebNFS */
1687: #ifdef notyet
1688: if (pubflag) {
1689: ndp->ni_rootdir = rootvnode;
1690: ndp->ni_loopcnt = 0;
1691: if (cnp->cn_pnbuf[0] == '/')
1692: dp = rootvnode;
1693: } else {
1694: cnp->cn_flags |= NOCROSSMOUNT;
1695: }
1696: #else
1697: cnp->cn_flags |= NOCROSSMOUNT;
1698: #endif
1699:
1700: cnp->cn_proc = p;
1701: VREF(dp);
1702:
1703: for (;;) {
1704: cnp->cn_nameptr = cnp->cn_pnbuf;
1705: ndp->ni_startdir = dp;
1706: /*
1707: * And call lookup() to do the real work
1708: */
1709: error = lookup(ndp);
1710: if (error)
1711: break;
1712: /*
1713: * Check for encountering a symbolic link
1714: */
1715: if ((cnp->cn_flags & ISSYMLINK) == 0) {
1716: nfsrv_object_create(ndp->ni_vp);
1717: if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
1718: cnp->cn_flags |= HASBUF;
1719: return (0);
1720: }
1721: break;
1722: } else {
1723: if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
1724: VOP_UNLOCK(ndp->ni_dvp, 0, p);
1725: /* XXX CSM 12/4/97 Revisit when enabling WebNFS */
1726: #ifdef notyet
1727: if (!pubflag) {
1728: #endif
1729: vrele(ndp->ni_dvp);
1730: vput(ndp->ni_vp);
1731: ndp->ni_vp = NULL;
1732: error = EINVAL;
1733: break;
1734: /* XXX CSM 12/4/97 Revisit when enabling WebNFS */
1735: /* XXX debo 12/15/97 Need to fix M_NAMEI allocations to use zone protocol */
1736: #ifdef notyet
1737: }
1738:
1739: if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
1740: error = ELOOP;
1741: break;
1742: }
1743: if (ndp->ni_pathlen > 1)
1744: MALLOC(cp, char *, olen + 1, M_NAMEI, M_WAITOK);
1745: else
1746: cp = cnp->cn_pnbuf;
1747: aiov.iov_base = cp;
1748: aiov.iov_len = MAXPATHLEN;
1749: auio.uio_iov = &aiov;
1750: auio.uio_iovcnt = 1;
1751: auio.uio_offset = 0;
1752: auio.uio_rw = UIO_READ;
1753: auio.uio_segflg = UIO_SYSSPACE;
1754: auio.uio_procp = (struct proc *)0;
1755: auio.uio_resid = MAXPATHLEN;
1756: error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
1757: if (error) {
1758: badlink:
1759: if (ndp->ni_pathlen > 1)
1760: FREE(cp, M_NAMEI);
1761: break;
1762: }
1763: linklen = MAXPATHLEN - auio.uio_resid;
1764: if (linklen == 0) {
1765: error = ENOENT;
1766: goto badlink;
1767: }
1768: if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
1769: error = ENAMETOOLONG;
1770: goto badlink;
1771: }
1772: if (ndp->ni_pathlen > 1) {
1773: bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
1774: FREE(cnp->cn_pnbuf, M_NAMEI);
1775: cnp->cn_pnbuf = cp;
1776: } else
1777: cnp->cn_pnbuf[linklen] = '\0';
1778: ndp->ni_pathlen += linklen;
1779: vput(ndp->ni_vp);
1780: dp = ndp->ni_dvp;
1781: /*
1782: * Check if root directory should replace current directory.
1783: */
1784: if (cnp->cn_pnbuf[0] == '/') {
1785: vrele(dp);
1786: dp = ndp->ni_rootdir;
1787: VREF(dp);
1788: }
1789: #endif
1790: }
1791: }
1792: out:
1793: FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1794: return (error);
1795: }
1796:
1797: /*
1798: * A fiddled version of m_adj() that ensures null fill to a long
1799: * boundary and only trims off the back end
1800: */
1801: void
1802: nfsm_adj(mp, len, nul)
1803: struct mbuf *mp;
1804: register int len;
1805: int nul;
1806: {
1807: register struct mbuf *m;
1808: register int count, i;
1809: register char *cp;
1810:
1811: /*
1812: * Trim from tail. Scan the mbuf chain,
1813: * calculating its length and finding the last mbuf.
1814: * If the adjustment only affects this mbuf, then just
1815: * adjust and return. Otherwise, rescan and truncate
1816: * after the remaining size.
1817: */
1818: count = 0;
1819: m = mp;
1820: for (;;) {
1821: count += m->m_len;
1822: if (m->m_next == (struct mbuf *)0)
1823: break;
1824: m = m->m_next;
1825: }
1826: if (m->m_len > len) {
1827: m->m_len -= len;
1828: if (nul > 0) {
1829: cp = mtod(m, caddr_t)+m->m_len-nul;
1830: for (i = 0; i < nul; i++)
1831: *cp++ = '\0';
1832: }
1833: return;
1834: }
1835: count -= len;
1836: if (count < 0)
1837: count = 0;
1838: /*
1839: * Correct length for chain is "count".
1840: * Find the mbuf with last data, adjust its length,
1841: * and toss data from remaining mbufs on chain.
1842: */
1843: for (m = mp; m; m = m->m_next) {
1844: if (m->m_len >= count) {
1845: m->m_len = count;
1846: if (nul > 0) {
1847: cp = mtod(m, caddr_t)+m->m_len-nul;
1848: for (i = 0; i < nul; i++)
1849: *cp++ = '\0';
1850: }
1851: break;
1852: }
1853: count -= m->m_len;
1854: }
1855: for (m = m->m_next;m;m = m->m_next)
1856: m->m_len = 0;
1857: }
1858:
1859: /*
1860: * Make these functions instead of macros, so that the kernel text size
1861: * doesn't get too big...
1862: */
1863: void
1864: nfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp)
1865: struct nfsrv_descript *nfsd;
1866: int before_ret;
1867: register struct vattr *before_vap;
1868: int after_ret;
1869: struct vattr *after_vap;
1870: struct mbuf **mbp;
1871: char **bposp;
1872: {
1873: register struct mbuf *mb = *mbp, *mb2;
1874: register char *bpos = *bposp;
1875: register u_long *tl;
1876:
1877: if (before_ret) {
1878: nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1879: *tl = nfs_false;
1880: } else {
1881: nfsm_build(tl, u_long *, 7 * NFSX_UNSIGNED);
1882: *tl++ = nfs_true;
1883: txdr_hyper(&(before_vap->va_size), tl);
1884: tl += 2;
1885: txdr_nfsv3time(&(before_vap->va_mtime), tl);
1886: tl += 2;
1887: txdr_nfsv3time(&(before_vap->va_ctime), tl);
1888: }
1889: *bposp = bpos;
1890: *mbp = mb;
1891: nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
1892: }
1893:
1894: void
1895: nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp)
1896: struct nfsrv_descript *nfsd;
1897: int after_ret;
1898: struct vattr *after_vap;
1899: struct mbuf **mbp;
1900: char **bposp;
1901: {
1902: register struct mbuf *mb = *mbp, *mb2;
1903: register char *bpos = *bposp;
1904: register u_long *tl;
1905: register struct nfs_fattr *fp;
1906:
1907: if (after_ret) {
1908: nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1909: *tl = nfs_false;
1910: } else {
1911: nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FATTR);
1912: *tl++ = nfs_true;
1913: fp = (struct nfs_fattr *)tl;
1914: nfsm_srvfattr(nfsd, after_vap, fp);
1915: }
1916: *mbp = mb;
1917: *bposp = bpos;
1918: }
1919:
1920: void
1921: nfsm_srvfattr(nfsd, vap, fp)
1922: register struct nfsrv_descript *nfsd;
1923: register struct vattr *vap;
1924: register struct nfs_fattr *fp;
1925: {
1926:
1927: fp->fa_nlink = txdr_unsigned(vap->va_nlink);
1928: fp->fa_uid = txdr_unsigned(vap->va_uid);
1929: fp->fa_gid = txdr_unsigned(vap->va_gid);
1930: if (nfsd->nd_flag & ND_NFSV3) {
1931: fp->fa_type = vtonfsv3_type(vap->va_type);
1932: fp->fa_mode = vtonfsv3_mode(vap->va_mode);
1933: txdr_hyper(&vap->va_size, &fp->fa3_size);
1934: txdr_hyper(&vap->va_bytes, &fp->fa3_used);
1935: fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev));
1936: fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev));
1937: fp->fa3_fsid.nfsuquad[0] = 0;
1938: fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
1939: fp->fa3_fileid.nfsuquad[0] = 0;
1940: fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
1941: txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
1942: txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
1943: txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
1944: } else {
1945: fp->fa_type = vtonfsv2_type(vap->va_type);
1946: fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1947: fp->fa2_size = txdr_unsigned(vap->va_size);
1948: fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
1949: if (vap->va_type == VFIFO)
1950: fp->fa2_rdev = 0xffffffff;
1951: else
1952: fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
1953: fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
1954: fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
1955: fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
1956: txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
1957: txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
1958: txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
1959: }
1960: }
1961:
1962: /*
1963: * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
1964: * - look up fsid in mount list (if not found ret error)
1965: * - get vp and export rights by calling VFS_FHTOVP()
1966: * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
1967: * - if not lockflag unlock it with VOP_UNLOCK()
1968: */
1969: int
1970: nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag)
1971: fhandle_t *fhp;
1972: int lockflag;
1973: struct vnode **vpp;
1974: struct ucred *cred;
1975: struct nfssvc_sock *slp;
1976: struct mbuf *nam;
1977: int *rdonlyp;
1978: int kerbflag;
1979: int pubflag;
1980: {
1981: struct proc *p = current_proc(); /* XXX */
1982: register struct mount *mp;
1983: register int i;
1984: struct ucred *credanon;
1985: int error, exflags;
1986:
1987: *vpp = (struct vnode *)0;
1988:
1989: /* XXX CSM 12/4/97 Revisit when enabling WebNFS */
1990: #ifdef notyet
1991: if (nfs_ispublicfh(fhp)) {
1992: if (!pubflag || !nfs_pub.np_valid)
1993: return (ESTALE);
1994: fhp = &nfs_pub.np_handle;
1995: }
1996: #endif
1997:
1998: mp = vfs_getvfs(&fhp->fh_fsid);
1999: if (!mp)
2000: return (ESTALE);
2001: error = VFS_FHTOVP(mp, &fhp->fh_fid, nam, vpp, &exflags, &credanon);
2002: if (error)
2003: return (error);
2004: /*
2005: * Check/setup credentials.
2006: */
2007: if (exflags & MNT_EXKERB) {
2008: if (!kerbflag) {
2009: vput(*vpp);
2010: return (NFSERR_AUTHERR | AUTH_TOOWEAK);
2011: }
2012: } else if (kerbflag) {
2013: vput(*vpp);
2014: return (NFSERR_AUTHERR | AUTH_TOOWEAK);
2015: } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
2016: cred->cr_uid = credanon->cr_uid;
2017: for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
2018: cred->cr_groups[i] = credanon->cr_groups[i];
2019: cred->cr_ngroups = i;
2020: }
2021: if (exflags & MNT_EXRDONLY)
2022: *rdonlyp = 1;
2023: else
2024: *rdonlyp = 0;
2025:
2026: nfsrv_object_create(*vpp);
2027:
2028: if (!lockflag)
2029: VOP_UNLOCK(*vpp, 0, p);
2030: return (0);
2031: }
2032:
2033:
2034: /*
2035: * WebNFS: check if a filehandle is a public filehandle. For v3, this
2036: * means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has
2037: * transformed this to all zeroes in both cases, so check for it.
2038: */
2039: int
2040: nfs_ispublicfh(fhp)
2041: fhandle_t *fhp;
2042: {
2043: char *cp = (char *)fhp;
2044: int i;
2045:
2046: for (i = 0; i < NFSX_V3FH; i++)
2047: if (*cp++ != 0)
2048: return (FALSE);
2049: return (TRUE);
2050: }
2051:
2052: #endif /* NFS_NOSERVER */
2053: /*
2054: * This function compares two net addresses by family and returns TRUE
2055: * if they are the same host.
2056: * If there is any doubt, return FALSE.
2057: * The AF_INET family is handled as a special case so that address mbufs
2058: * don't need to be saved to store "struct in_addr", which is only 4 bytes.
2059: */
2060: int
2061: netaddr_match(family, haddr, nam)
2062: int family;
2063: union nethostaddr *haddr;
2064: struct mbuf *nam;
2065: {
2066: register struct sockaddr_in *inetaddr;
2067:
2068: switch (family) {
2069: case AF_INET:
2070: inetaddr = mtod(nam, struct sockaddr_in *);
2071: if (inetaddr->sin_family == AF_INET &&
2072: inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
2073: return (1);
2074: break;
2075: #if ISO
2076: case AF_ISO:
2077: {
2078: register struct sockaddr_iso *isoaddr1, *isoaddr2;
2079:
2080: isoaddr1 = mtod(nam, struct sockaddr_iso *);
2081: isoaddr2 = mtod(haddr->had_nam, struct sockaddr_iso *);
2082: if (isoaddr1->siso_family == AF_ISO &&
2083: isoaddr1->siso_nlen > 0 &&
2084: isoaddr1->siso_nlen == isoaddr2->siso_nlen &&
2085: SAME_ISOADDR(isoaddr1, isoaddr2))
2086: return (1);
2087: break;
2088: }
2089: #endif /* ISO */
2090: default:
2091: break;
2092: };
2093: return (0);
2094: }
2095:
2096: static nfsuint64 nfs_nullcookie = { 0, 0 };
2097: /*
2098: * This function finds the directory cookie that corresponds to the
2099: * logical byte offset given.
2100: */
2101: nfsuint64 *
2102: nfs_getcookie(np, off, add)
2103: register struct nfsnode *np;
2104: off_t off;
2105: int add;
2106: {
2107: register struct nfsdmap *dp, *dp2;
2108: register int pos;
2109:
2110: pos = off / NFS_DIRBLKSIZ;
2111: if (pos == 0) {
2112: #if DIAGNOSTIC
2113: if (add)
2114: panic("nfs getcookie add at 0");
2115: #endif
2116: return (&nfs_nullcookie);
2117: }
2118: pos--;
2119: dp = np->n_cookies.lh_first;
2120: if (!dp) {
2121: if (add) {
2122: MALLOC_ZONE(dp, struct nfsdmap *,
2123: sizeof (struct nfsdmap),
2124: M_NFSDIROFF, M_WAITOK);
2125: dp->ndm_eocookie = 0;
2126: LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
2127: } else
2128: return ((nfsuint64 *)0);
2129: }
2130: while (pos >= NFSNUMCOOKIES) {
2131: pos -= NFSNUMCOOKIES;
2132: if (dp->ndm_list.le_next) {
2133: if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
2134: pos >= dp->ndm_eocookie)
2135: return ((nfsuint64 *)0);
2136: dp = dp->ndm_list.le_next;
2137: } else if (add) {
2138: MALLOC_ZONE(dp2, struct nfsdmap *,
2139: sizeof (struct nfsdmap),
2140: M_NFSDIROFF, M_WAITOK);
2141: dp2->ndm_eocookie = 0;
2142: LIST_INSERT_AFTER(dp, dp2, ndm_list);
2143: dp = dp2;
2144: } else
2145: return ((nfsuint64 *)0);
2146: }
2147: if (pos >= dp->ndm_eocookie) {
2148: if (add)
2149: dp->ndm_eocookie = pos + 1;
2150: else
2151: return ((nfsuint64 *)0);
2152: }
2153: return (&dp->ndm_cookies[pos]);
2154: }
2155:
2156: /*
2157: * Invalidate cached directory information, except for the actual directory
2158: * blocks (which are invalidated separately).
2159: * Done mainly to avoid the use of stale offset cookies.
2160: */
2161: void
2162: nfs_invaldir(vp)
2163: register struct vnode *vp;
2164: {
2165: register struct nfsnode *np = VTONFS(vp);
2166:
2167: #if DIAGNOSTIC
2168: if (vp->v_type != VDIR)
2169: panic("nfs: invaldir not dir");
2170: #endif
2171: np->n_direofoffset = 0;
2172: np->n_cookieverf.nfsuquad[0] = 0;
2173: np->n_cookieverf.nfsuquad[1] = 0;
2174: if (np->n_cookies.lh_first)
2175: np->n_cookies.lh_first->ndm_eocookie = 0;
2176: }
2177:
2178: /*
2179: * The write verifier has changed (probably due to a server reboot), so all
2180: * B_NEEDCOMMIT blocks will have to be written again. Since they are on the
2181: * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT
2182: * flag. Once done the new write verifier can be set for the mount point.
2183: */
2184: void
2185: nfs_clearcommit(mp)
2186: struct mount *mp;
2187: {
2188: register struct vnode *vp, *nvp;
2189: register struct buf *bp, *nbp;
2190: int s;
2191:
2192: s = splbio();
2193: loop:
2194: for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
2195: if (vp->v_mount != mp) /* Paranoia */
2196: goto loop;
2197: nvp = vp->v_mntvnodes.le_next;
2198: for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
2199: nbp = bp->b_vnbufs.le_next;
2200: if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
2201: == (B_DELWRI | B_NEEDCOMMIT))
2202: bp->b_flags &= ~B_NEEDCOMMIT;
2203: }
2204: }
2205: splx(s);
2206: }
2207:
2208: #ifndef NFS_NOSERVER
2209: /*
2210: * Map errnos to NFS error numbers. For Version 3 also filter out error
2211: * numbers not specified for the associated procedure.
2212: */
2213: int
2214: nfsrv_errmap(nd, err)
2215: struct nfsrv_descript *nd;
2216: register int err;
2217: {
2218: register short *defaulterrp, *errp;
2219:
2220: if (nd->nd_flag & ND_NFSV3) {
2221: if (nd->nd_procnum <= NFSPROC_COMMIT) {
2222: errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
2223: while (*++errp) {
2224: if (*errp == err)
2225: return (err);
2226: else if (*errp > err)
2227: break;
2228: }
2229: return ((int)*defaulterrp);
2230: } else
2231: return (err & 0xffff);
2232: }
2233: if (err <= ELAST)
2234: return ((int)nfsrv_v2errmap[err - 1]);
2235: return (NFSERR_IO);
2236: }
2237:
2238: /* XXX CSM 11/25/97 Revisit when Ramesh merges vm with buffer cache */
2239: #define vfs_object_create(v, p, c, l) (0)
2240:
2241: int
2242: nfsrv_object_create(struct vnode *vp) {
2243: struct proc *curproc = current_proc();
2244:
2245: if ((vp == NULL) || (vp->v_type != VREG))
2246: return 1;
2247: return vfs_object_create(vp, curproc, curproc?curproc->p_ucred:NULL, 1);
2248: }
2249: #endif /* NFS_NOSERVER */
2250:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.