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