|
|
1.1 root 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Rick Macklem at The University of Guelph.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
36: * @(#)nfs_subs.c 7.41 (Berkeley) 5/15/91
37: */
38:
39: /*
40: * These functions support the macros and help fiddle mbuf chains for
41: * the nfs op functions. They do things like create the rpc header and
42: * copy data between mbuf chains and uio lists.
43: */
44: #include "param.h"
45: #include "proc.h"
46: #include "filedesc.h"
47: #include "systm.h"
48: #include "kernel.h"
49: #include "mount.h"
50: #include "file.h"
51: #include "vnode.h"
52: #include "namei.h"
53: #include "mbuf.h"
54:
55: #include "../ufs/quota.h"
56: #include "../ufs/inode.h"
57:
58: #include "rpcv2.h"
59: #include "nfsv2.h"
60: #include "nfsnode.h"
61: #include "nfs.h"
62: #include "nfsiom.h"
63: #include "xdr_subs.h"
64: #include "nfsm_subs.h"
65: #include "nfscompress.h"
66:
67: #define TRUE 1
68: #define FALSE 0
69:
70: /*
71: * Data items converted to xdr at startup, since they are constant
72: * This is kinda hokey, but may save a little time doing byte swaps
73: */
74: u_long nfs_procids[NFS_NPROCS];
75: u_long nfs_xdrneg1;
76: u_long rpc_call, rpc_vers, rpc_reply, rpc_msgdenied,
77: rpc_mismatch, rpc_auth_unix, rpc_msgaccepted;
78: u_long nfs_vers, nfs_prog, nfs_true, nfs_false;
79: /* And other global data */
80: static u_long *rpc_uidp = (u_long *)0;
81: static u_long nfs_xid = 1;
82: static char *rpc_unixauth;
83: extern long hostid;
84: enum vtype ntov_type[7] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON };
85: extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
86: extern struct nfsreq nfsreqh;
87:
88: /* Function ret types */
89: static char *nfs_unixauth();
90:
91: /*
92: * Maximum number of groups passed through to NFS server.
93: * According to RFC1057 it should be 16.
94: * For release 3.X systems, the maximum value is 8.
95: * For some other servers, the maximum value is 10.
96: */
97: int numgrps = 8;
98:
99: /*
100: * Create the header for an rpc request packet
101: * The function nfs_unixauth() creates a unix style authorization string
102: * and returns a ptr to it.
103: * The hsiz is the size of the rest of the nfs request header.
104: * (just used to decide if a cluster is a good idea)
105: * nb: Note that the prog, vers and procid args are already in xdr byte order
106: */
107: struct mbuf *nfsm_reqh(prog, vers, procid, cred, hsiz, bpos, mb, retxid)
108: u_long prog;
109: u_long vers;
110: u_long procid;
111: struct ucred *cred;
112: int hsiz;
113: caddr_t *bpos;
114: struct mbuf **mb;
115: u_long *retxid;
116: {
117: register struct mbuf *mreq, *m;
118: register u_long *tl;
119: struct mbuf *m1;
120: char *ap;
121: int asiz, siz;
122:
123: NFSMGETHDR(mreq);
124: asiz = ((((cred->cr_ngroups - 1) > numgrps) ? numgrps :
125: (cred->cr_ngroups - 1)) << 2);
126: #ifdef FILLINHOST
127: asiz += nfsm_rndup(hostnamelen)+(9*NFSX_UNSIGNED);
128: #else
129: asiz += 9*NFSX_UNSIGNED;
130: #endif
131:
132: /* If we need a lot, alloc a cluster ?? */
133: if ((asiz+hsiz+RPC_SIZ) > MHLEN)
134: MCLGET(mreq, M_WAIT);
135: mreq->m_len = NFSMSIZ(mreq);
136: siz = mreq->m_len;
137: m1 = mreq;
138: /*
139: * Alloc enough mbufs
140: * We do it now to avoid all sleeps after the call to nfs_unixauth()
141: */
142: while ((asiz+RPC_SIZ) > siz) {
143: MGET(m, M_WAIT, MT_DATA);
144: m1->m_next = m;
145: m->m_len = MLEN;
146: siz += MLEN;
147: m1 = m;
148: }
149: tl = mtod(mreq, u_long *);
150: *tl++ = *retxid = txdr_unsigned(++nfs_xid);
151: *tl++ = rpc_call;
152: *tl++ = rpc_vers;
153: *tl++ = prog;
154: *tl++ = vers;
155: *tl++ = procid;
156:
157: /* Now we can call nfs_unixauth() and copy it in */
158: ap = nfs_unixauth(cred);
159: m = mreq;
160: siz = m->m_len-RPC_SIZ;
161: if (asiz <= siz) {
162: bcopy(ap, (caddr_t)tl, asiz);
163: m->m_len = asiz+RPC_SIZ;
164: } else {
165: bcopy(ap, (caddr_t)tl, siz);
166: ap += siz;
167: asiz -= siz;
168: while (asiz > 0) {
169: siz = (asiz > MLEN) ? MLEN : asiz;
170: m = m->m_next;
171: bcopy(ap, mtod(m, caddr_t), siz);
172: m->m_len = siz;
173: asiz -= siz;
174: ap += siz;
175: }
176: }
177:
178: /* Finally, return values */
179: *mb = m;
180: *bpos = mtod(m, caddr_t)+m->m_len;
181: return (mreq);
182: }
183:
184: /*
185: * copies mbuf chain to the uio scatter/gather list
186: */
187: nfsm_mbuftouio(mrep, uiop, siz, dpos)
188: struct mbuf **mrep;
189: register struct uio *uiop;
190: int siz;
191: caddr_t *dpos;
192: {
193: register char *mbufcp, *uiocp;
194: register int xfer, left, len;
195: register struct mbuf *mp;
196: long uiosiz, rem;
197: int error = 0;
198:
199: mp = *mrep;
200: mbufcp = *dpos;
201: len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
202: rem = nfsm_rndup(siz)-siz;
203: while (siz > 0) {
204: if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
205: return (EFBIG);
206: left = uiop->uio_iov->iov_len;
207: uiocp = uiop->uio_iov->iov_base;
208: if (left > siz)
209: left = siz;
210: uiosiz = left;
211: while (left > 0) {
212: while (len == 0) {
213: mp = mp->m_next;
214: if (mp == NULL)
215: return (EBADRPC);
216: mbufcp = mtod(mp, caddr_t);
217: len = mp->m_len;
218: }
219: xfer = (left > len) ? len : left;
220: #ifdef notdef
221: /* Not Yet.. */
222: if (uiop->uio_iov->iov_op != NULL)
223: (*(uiop->uio_iov->iov_op))
224: (mbufcp, uiocp, xfer);
225: else
226: #endif
227: if (uiop->uio_segflg == UIO_SYSSPACE)
228: bcopy(mbufcp, uiocp, xfer);
229: else
230: copyout(mbufcp, uiocp, xfer);
231: left -= xfer;
232: len -= xfer;
233: mbufcp += xfer;
234: uiocp += xfer;
235: uiop->uio_offset += xfer;
236: uiop->uio_resid -= xfer;
237: }
238: if (uiop->uio_iov->iov_len <= siz) {
239: uiop->uio_iovcnt--;
240: uiop->uio_iov++;
241: } else {
242: uiop->uio_iov->iov_base += uiosiz;
243: uiop->uio_iov->iov_len -= uiosiz;
244: }
245: siz -= uiosiz;
246: }
247: *dpos = mbufcp;
248: *mrep = mp;
249: if (rem > 0) {
250: if (len < rem)
251: error = nfs_adv(mrep, dpos, rem, len);
252: else
253: *dpos += rem;
254: }
255: return (error);
256: }
257:
258: /*
259: * copies a uio scatter/gather list to an mbuf chain...
260: */
261: nfsm_uiotombuf(uiop, mq, siz, bpos)
262: register struct uio *uiop;
263: struct mbuf **mq;
264: int siz;
265: caddr_t *bpos;
266: {
267: register char *uiocp;
268: register struct mbuf *mp, *mp2;
269: register int xfer, left, len;
270: int uiosiz, clflg, rem;
271: char *cp;
272:
273: if (siz > MLEN) /* or should it >= MCLBYTES ?? */
274: clflg = 1;
275: else
276: clflg = 0;
277: rem = nfsm_rndup(siz)-siz;
278: mp2 = *mq;
279: while (siz > 0) {
280: if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
281: return (EINVAL);
282: left = uiop->uio_iov->iov_len;
283: uiocp = uiop->uio_iov->iov_base;
284: if (left > siz)
285: left = siz;
286: uiosiz = left;
287: while (left > 0) {
288: MGET(mp, M_WAIT, MT_DATA);
289: if (clflg)
290: MCLGET(mp, M_WAIT);
291: mp->m_len = NFSMSIZ(mp);
292: mp2->m_next = mp;
293: mp2 = mp;
294: xfer = (left > mp->m_len) ? mp->m_len : left;
295: #ifdef notdef
296: /* Not Yet.. */
297: if (uiop->uio_iov->iov_op != NULL)
298: (*(uiop->uio_iov->iov_op))
299: (uiocp, mtod(mp, caddr_t), xfer);
300: else
301: #endif
302: if (uiop->uio_segflg == UIO_SYSSPACE)
303: bcopy(uiocp, mtod(mp, caddr_t), xfer);
304: else
305: copyin(uiocp, mtod(mp, caddr_t), xfer);
306: len = mp->m_len;
307: mp->m_len = xfer;
308: left -= xfer;
309: uiocp += xfer;
310: uiop->uio_offset += xfer;
311: uiop->uio_resid -= xfer;
312: }
313: if (uiop->uio_iov->iov_len <= siz) {
314: uiop->uio_iovcnt--;
315: uiop->uio_iov++;
316: } else {
317: uiop->uio_iov->iov_base += uiosiz;
318: uiop->uio_iov->iov_len -= uiosiz;
319: }
320: siz -= uiosiz;
321: }
322: if (rem > 0) {
323: if (rem > (len-mp->m_len)) {
324: MGET(mp, M_WAIT, MT_DATA);
325: mp->m_len = 0;
326: mp2->m_next = mp;
327: }
328: cp = mtod(mp, caddr_t)+mp->m_len;
329: for (left = 0; left < rem; left++)
330: *cp++ = '\0';
331: mp->m_len += rem;
332: *bpos = cp;
333: } else
334: *bpos = mtod(mp, caddr_t)+mp->m_len;
335: *mq = mp;
336: return (0);
337: }
338:
339: /*
340: * Help break down an mbuf chain by setting the first siz bytes contiguous
341: * pointed to by returned val.
342: * If Updateflg == True we can overwrite the first part of the mbuf data
343: * This is used by the macros nfsm_disect and nfsm_disecton for tough
344: * cases. (The macros use the vars. dpos and dpos2)
345: */
346: nfsm_disct(mdp, dposp, siz, left, updateflg, cp2)
347: struct mbuf **mdp;
348: caddr_t *dposp;
349: int siz;
350: int left;
351: int updateflg;
352: caddr_t *cp2;
353: {
354: register struct mbuf *mp, *mp2;
355: register int siz2, xfer;
356: register caddr_t tl;
357:
358: mp = *mdp;
359: while (left == 0) {
360: *mdp = mp = mp->m_next;
361: if (mp == NULL)
362: return (EBADRPC);
363: left = mp->m_len;
364: *dposp = mtod(mp, caddr_t);
365: }
366: if (left >= siz) {
367: *cp2 = *dposp;
368: *dposp += siz;
369: } else if (mp->m_next == NULL) {
370: return (EBADRPC);
371: } else if (siz > MHLEN) {
372: panic("nfs S too big");
373: } else {
374: /* Iff update, you can overwrite, else must alloc new mbuf */
375: if (updateflg) {
376: NFSMINOFF(mp);
377: } else {
378: MGET(mp2, M_WAIT, MT_DATA);
379: mp2->m_next = mp->m_next;
380: mp->m_next = mp2;
381: mp->m_len -= left;
382: mp = mp2;
383: }
384: *cp2 = tl = mtod(mp, caddr_t);
385: bcopy(*dposp, tl, left); /* Copy what was left */
386: siz2 = siz-left;
387: tl += left;
388: mp2 = mp->m_next;
389: /* Loop around copying up the siz2 bytes */
390: while (siz2 > 0) {
391: if (mp2 == NULL)
392: return (EBADRPC);
393: xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
394: if (xfer > 0) {
395: bcopy(mtod(mp2, caddr_t), tl, xfer);
396: NFSMADV(mp2, xfer);
397: mp2->m_len -= xfer;
398: tl += xfer;
399: siz2 -= xfer;
400: }
401: if (siz2 > 0)
402: mp2 = mp2->m_next;
403: }
404: mp->m_len = siz;
405: *mdp = mp2;
406: *dposp = mtod(mp2, caddr_t);
407: }
408: return (0);
409: }
410:
411: /*
412: * Advance the position in the mbuf chain.
413: */
414: nfs_adv(mdp, dposp, offs, left)
415: struct mbuf **mdp;
416: caddr_t *dposp;
417: int offs;
418: int left;
419: {
420: register struct mbuf *m;
421: register int s;
422:
423: m = *mdp;
424: s = left;
425: while (s < offs) {
426: offs -= s;
427: m = m->m_next;
428: if (m == NULL)
429: return (EBADRPC);
430: s = m->m_len;
431: }
432: *mdp = m;
433: *dposp = mtod(m, caddr_t)+offs;
434: return (0);
435: }
436:
437: /*
438: * Copy a string into mbufs for the hard cases...
439: */
440: nfsm_strtmbuf(mb, bpos, cp, siz)
441: struct mbuf **mb;
442: char **bpos;
443: char *cp;
444: long siz;
445: {
446: register struct mbuf *m1, *m2;
447: long left, xfer, len, tlen;
448: u_long *tl;
449: int putsize;
450:
451: putsize = 1;
452: m2 = *mb;
453: left = NFSMSIZ(m2)-m2->m_len;
454: if (left > 0) {
455: tl = ((u_long *)(*bpos));
456: *tl++ = txdr_unsigned(siz);
457: putsize = 0;
458: left -= NFSX_UNSIGNED;
459: m2->m_len += NFSX_UNSIGNED;
460: if (left > 0) {
461: bcopy(cp, (caddr_t) tl, left);
462: siz -= left;
463: cp += left;
464: m2->m_len += left;
465: left = 0;
466: }
467: }
468: /* Loop arround adding mbufs */
469: while (siz > 0) {
470: MGET(m1, M_WAIT, MT_DATA);
471: if (siz > MLEN)
472: MCLGET(m1, M_WAIT);
473: m1->m_len = NFSMSIZ(m1);
474: m2->m_next = m1;
475: m2 = m1;
476: tl = mtod(m1, u_long *);
477: tlen = 0;
478: if (putsize) {
479: *tl++ = txdr_unsigned(siz);
480: m1->m_len -= NFSX_UNSIGNED;
481: tlen = NFSX_UNSIGNED;
482: putsize = 0;
483: }
484: if (siz < m1->m_len) {
485: len = nfsm_rndup(siz);
486: xfer = siz;
487: if (xfer < len)
488: *(tl+(xfer>>2)) = 0;
489: } else {
490: xfer = len = m1->m_len;
491: }
492: bcopy(cp, (caddr_t) tl, xfer);
493: m1->m_len = len+tlen;
494: siz -= xfer;
495: cp += xfer;
496: }
497: *mb = m1;
498: *bpos = mtod(m1, caddr_t)+m1->m_len;
499: return (0);
500: }
501:
502: /*
503: * Called once to initialize data structures...
504: */
505: nfs_init()
506: {
507: register int i;
508:
509: rpc_vers = txdr_unsigned(RPC_VER2);
510: rpc_call = txdr_unsigned(RPC_CALL);
511: rpc_reply = txdr_unsigned(RPC_REPLY);
512: rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
513: rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
514: rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
515: rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
516: nfs_vers = txdr_unsigned(NFS_VER2);
517: nfs_prog = txdr_unsigned(NFS_PROG);
518: nfs_true = txdr_unsigned(TRUE);
519: nfs_false = txdr_unsigned(FALSE);
520: /* Loop thru nfs procids */
521: for (i = 0; i < NFS_NPROCS; i++)
522: nfs_procids[i] = txdr_unsigned(i);
523: /* Ensure async daemons disabled */
524: for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
525: nfs_iodwant[i] = (struct proc *)0;
526: nfs_xdrneg1 = txdr_unsigned(-1);
527: nfs_nhinit(); /* Init the nfsnode table */
528: nfsrv_initcache(); /* Init the server request cache */
529:
530: /*
531: * Initialize reply list and start timer
532: */
533: nfsreqh.r_prev = nfsreqh.r_next = &nfsreqh;
534: nfs_timer();
535: }
536:
537: /*
538: * Fill in the rest of the rpc_unixauth and return it
539: */
540: static char *nfs_unixauth(cr)
541: register struct ucred *cr;
542: {
543: register u_long *tl;
544: register int i;
545: int ngr;
546:
547: /* Maybe someday there should be a cache of AUTH_SHORT's */
548: if ((tl = rpc_uidp) == NULL) {
549: #ifdef FILLINHOST
550: i = nfsm_rndup(hostnamelen)+(25*NFSX_UNSIGNED);
551: #else
552: i = 25*NFSX_UNSIGNED;
553: #endif
554: MALLOC(tl, u_long *, i, M_TEMP, M_WAITOK);
555: bzero((caddr_t)tl, i);
556: rpc_unixauth = (caddr_t)tl;
557: *tl++ = txdr_unsigned(RPCAUTH_UNIX);
558: tl++; /* Fill in size later */
559: *tl++ = hostid;
560: #ifdef FILLINHOST
561: *tl++ = txdr_unsigned(hostnamelen);
562: i = nfsm_rndup(hostnamelen);
563: bcopy(hostname, (caddr_t)tl, hostnamelen);
564: tl += (i>>2);
565: #else
566: *tl++ = 0;
567: #endif
568: rpc_uidp = tl;
569: }
570: *tl++ = txdr_unsigned(cr->cr_uid);
571: *tl++ = txdr_unsigned(cr->cr_groups[0]);
572: ngr = ((cr->cr_ngroups - 1) > numgrps) ? numgrps : (cr->cr_ngroups - 1);
573: *tl++ = txdr_unsigned(ngr);
574: for (i = 1; i <= ngr; i++)
575: *tl++ = txdr_unsigned(cr->cr_groups[i]);
576: /* And add the AUTH_NULL */
577: *tl++ = 0;
578: *tl = 0;
579: i = (((caddr_t)tl)-rpc_unixauth)-12;
580: tl = (u_long *)(rpc_unixauth+4);
581: *tl = txdr_unsigned(i);
582: return (rpc_unixauth);
583: }
584:
585: /*
586: * Attribute cache routines.
587: * nfs_loadattrcache() - loads or updates the cache contents from attributes
588: * that are on the mbuf list
589: * nfs_getattrcache() - returns valid attributes if found in cache, returns
590: * error otherwise
591: */
592:
593: /*
594: * Load the attribute cache (that lives in the nfsnode entry) with
595: * the values on the mbuf list and
596: * Iff vap not NULL
597: * copy the attributes to *vaper
598: */
599: nfs_loadattrcache(vpp, mdp, dposp, vaper)
600: struct vnode **vpp;
601: struct mbuf **mdp;
602: caddr_t *dposp;
603: struct vattr *vaper;
604: {
605: register struct vnode *vp = *vpp;
606: register struct vattr *vap;
607: register struct nfsv2_fattr *fp;
608: extern struct vnodeops spec_nfsv2nodeops;
609: register struct nfsnode *np;
610: register long t1;
611: caddr_t dpos, cp2;
612: int error = 0;
613: struct mbuf *md;
614: enum vtype type;
615: u_short mode;
616: long rdev;
617: struct timeval mtime;
618: struct vnode *nvp;
619:
620: md = *mdp;
621: dpos = *dposp;
622: t1 = (mtod(md, caddr_t)+md->m_len)-dpos;
623: if (error = nfsm_disct(&md, &dpos, NFSX_FATTR, t1, TRUE, &cp2))
624: return (error);
625: fp = (struct nfsv2_fattr *)cp2;
626: type = nfstov_type(fp->fa_type);
627: mode = fxdr_unsigned(u_short, fp->fa_mode);
628: if (type == VNON)
629: type = IFTOVT(mode);
630: rdev = fxdr_unsigned(long, fp->fa_rdev);
631: fxdr_time(&fp->fa_mtime, &mtime);
632: /*
633: * If v_type == VNON it is a new node, so fill in the v_type,
634: * n_mtime fields. Check to see if it represents a special
635: * device, and if so, check for a possible alias. Once the
636: * correct vnode has been obtained, fill in the rest of the
637: * information.
638: */
639: np = VTONFS(vp);
640: if (vp->v_type == VNON) {
641: if (type == VCHR && rdev == 0xffffffff)
642: vp->v_type = type = VFIFO;
643: else
644: vp->v_type = type;
645: if (vp->v_type == VFIFO) {
646: #ifdef FIFO
647: extern struct vnodeops fifo_nfsv2nodeops;
648: vp->v_op = &fifo_nfsv2nodeops;
649: #else
650: return (EOPNOTSUPP);
651: #endif /* FIFO */
652: }
653: if (vp->v_type == VCHR || vp->v_type == VBLK) {
654: vp->v_op = &spec_nfsv2nodeops;
655: if (nvp = checkalias(vp, (dev_t)rdev, vp->v_mount)) {
656: /*
657: * Reinitialize aliased node.
658: */
659: np = VTONFS(nvp);
660: np->n_vnode = nvp;
661: np->n_flag = 0;
662: nfs_lock(nvp);
663: bcopy((caddr_t)&VTONFS(vp)->n_fh,
664: (caddr_t)&np->n_fh, NFSX_FH);
665: insque(np, nfs_hash(&np->n_fh));
666: np->n_attrstamp = 0;
667: np->n_sillyrename = (struct sillyrename *)0;
668: /*
669: * Discard unneeded vnode and update actual one
670: */
671: vput(vp);
672: *vpp = nvp;
673: }
674: }
675: np->n_mtime = mtime.tv_sec;
676: }
677: vap = &np->n_vattr;
678: vap->va_type = type;
679: vap->va_mode = (mode & 07777);
680: vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
681: vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
682: vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
683: vap->va_size = fxdr_unsigned(u_long, fp->fa_size);
684: if ((np->n_flag & NMODIFIED) == 0 || vap->va_size > np->n_size) {
685: np->n_size = vap->va_size;
686: vnode_pager_setsize(vp, np->n_size);
687: }
688: vap->va_size_rsv = 0;
689: vap->va_blocksize = fxdr_unsigned(long, fp->fa_blocksize);
690: vap->va_rdev = (dev_t)rdev;
691: vap->va_bytes = fxdr_unsigned(long, fp->fa_blocks) * NFS_FABLKSIZE;
692: vap->va_bytes_rsv = 0;
693: vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
694: vap->va_fileid = fxdr_unsigned(long, fp->fa_fileid);
695: vap->va_atime.tv_sec = fxdr_unsigned(long, fp->fa_atime.tv_sec);
696: vap->va_atime.tv_usec = 0;
697: vap->va_flags = fxdr_unsigned(u_long, fp->fa_atime.tv_usec);
698: vap->va_mtime = mtime;
699: vap->va_ctime.tv_sec = fxdr_unsigned(long, fp->fa_ctime.tv_sec);
700: vap->va_ctime.tv_usec = 0;
701: vap->va_gen = fxdr_unsigned(u_long, fp->fa_ctime.tv_usec);
702: np->n_attrstamp = time.tv_sec;
703: *dposp = dpos;
704: *mdp = md;
705: if (vaper != NULL) {
706: bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
707: if ((np->n_flag & NMODIFIED) && (np->n_size > vap->va_size))
708: vaper->va_size = np->n_size;
709: }
710: return (0);
711: }
712:
713: /*
714: * Check the time stamp
715: * If the cache is valid, copy contents to *vap and return 0
716: * otherwise return an error
717: */
718: nfs_getattrcache(vp, vap)
719: register struct vnode *vp;
720: struct vattr *vap;
721: {
722: register struct nfsnode *np;
723:
724: np = VTONFS(vp);
725: if ((time.tv_sec-np->n_attrstamp) < NFS_ATTRTIMEO) {
726: nfsstats.attrcache_hits++;
727: bcopy((caddr_t)&np->n_vattr,(caddr_t)vap,sizeof(struct vattr));
728: if ((np->n_flag & NMODIFIED) == 0) {
729: np->n_size = vap->va_size;
730: vnode_pager_setsize(vp, np->n_size);
731: } else if (np->n_size > vap->va_size)
732: vap->va_size = np->n_size;
733: return (0);
734: } else {
735: nfsstats.attrcache_misses++;
736: return (ENOENT);
737: }
738: }
739:
740: /*
741: * Set up nameidata for a namei() call and do it
742: */
743: nfs_namei(ndp, fhp, len, mdp, dposp, p)
744: register struct nameidata *ndp;
745: fhandle_t *fhp;
746: int len;
747: struct mbuf **mdp;
748: caddr_t *dposp;
749: struct proc *p;
750: {
751: register int i, rem;
752: register struct mbuf *md;
753: register char *fromcp, *tocp;
754: struct vnode *dp;
755: int flag;
756: int error;
757:
758: flag = ndp->ni_nameiop & OPMASK;
759: MALLOC(ndp->ni_pnbuf, char *, len + 1, M_NAMEI, M_WAITOK);
760: /*
761: * Copy the name from the mbuf list to ndp->ni_pnbuf
762: * and set the various ndp fields appropriately.
763: */
764: fromcp = *dposp;
765: tocp = ndp->ni_pnbuf;
766: md = *mdp;
767: rem = mtod(md, caddr_t) + md->m_len - fromcp;
768: ndp->ni_hash = 0;
769: for (i = 0; i < len; i++) {
770: while (rem == 0) {
771: md = md->m_next;
772: if (md == NULL) {
773: error = EBADRPC;
774: goto out;
775: }
776: fromcp = mtod(md, caddr_t);
777: rem = md->m_len;
778: }
779: if (*fromcp == '\0' || *fromcp == '/') {
780: error = EINVAL;
781: goto out;
782: }
783: if (*fromcp & 0200)
784: if ((*fromcp&0377) == ('/'|0200) || flag != DELETE) {
785: error = EINVAL;
786: goto out;
787: }
788: ndp->ni_hash += (unsigned char)*fromcp;
789: *tocp++ = *fromcp++;
790: rem--;
791: }
792: *tocp = '\0';
793: *mdp = md;
794: *dposp = fromcp;
795: len = nfsm_rndup(len)-len;
796: if (len > 0) {
797: if (rem >= len)
798: *dposp += len;
799: else if (error = nfs_adv(mdp, dposp, len, rem))
800: goto out;
801: }
802: ndp->ni_pathlen = tocp - ndp->ni_pnbuf;
803: ndp->ni_ptr = ndp->ni_pnbuf;
804: /*
805: * Extract and set starting directory.
806: */
807: if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cred))
808: goto out;
809: if (dp->v_type != VDIR) {
810: vrele(dp);
811: error = ENOTDIR;
812: goto out;
813: }
814: ndp->ni_startdir = dp;
815: ndp->ni_nameiop |= (NOCROSSMOUNT | REMOTE);
816: /*
817: * And call lookup() to do the real work
818: */
819: if (error = lookup(ndp, p))
820: goto out;
821: /*
822: * Check for encountering a symbolic link
823: */
824: if (ndp->ni_more) {
825: if ((ndp->ni_nameiop & LOCKPARENT) && ndp->ni_pathlen == 1)
826: vput(ndp->ni_dvp);
827: else
828: vrele(ndp->ni_dvp);
829: vput(ndp->ni_vp);
830: ndp->ni_vp = NULL;
831: error = EINVAL;
832: goto out;
833: }
834: /*
835: * Check for saved name request
836: */
837: if (ndp->ni_nameiop & (SAVENAME | SAVESTART)) {
838: ndp->ni_nameiop |= HASBUF;
839: return (0);
840: }
841: out:
842: FREE(ndp->ni_pnbuf, M_NAMEI);
843: return (error);
844: }
845:
846: /*
847: * A fiddled version of m_adj() that ensures null fill to a long
848: * boundary and only trims off the back end
849: */
850: nfsm_adj(mp, len, nul)
851: struct mbuf *mp;
852: register int len;
853: int nul;
854: {
855: register struct mbuf *m;
856: register int count, i;
857: register char *cp;
858:
859: /*
860: * Trim from tail. Scan the mbuf chain,
861: * calculating its length and finding the last mbuf.
862: * If the adjustment only affects this mbuf, then just
863: * adjust and return. Otherwise, rescan and truncate
864: * after the remaining size.
865: */
866: count = 0;
867: m = mp;
868: for (;;) {
869: count += m->m_len;
870: if (m->m_next == (struct mbuf *)0)
871: break;
872: m = m->m_next;
873: }
874: if (m->m_len > len) {
875: m->m_len -= len;
876: if (nul > 0) {
877: cp = mtod(m, caddr_t)+m->m_len-nul;
878: for (i = 0; i < nul; i++)
879: *cp++ = '\0';
880: }
881: return;
882: }
883: count -= len;
884: if (count < 0)
885: count = 0;
886: /*
887: * Correct length for chain is "count".
888: * Find the mbuf with last data, adjust its length,
889: * and toss data from remaining mbufs on chain.
890: */
891: for (m = mp; m; m = m->m_next) {
892: if (m->m_len >= count) {
893: m->m_len = count;
894: if (nul > 0) {
895: cp = mtod(m, caddr_t)+m->m_len-nul;
896: for (i = 0; i < nul; i++)
897: *cp++ = '\0';
898: }
899: break;
900: }
901: count -= m->m_len;
902: }
903: while (m = m->m_next)
904: m->m_len = 0;
905: }
906:
907: /*
908: * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
909: * - look up fsid in mount list (if not found ret error)
910: * - check that it is exported
911: * - get vp by calling VFS_FHTOVP() macro
912: * - if not lockflag unlock it with VOP_UNLOCK()
913: * - if cred->cr_uid == 0 set it to m_exroot
914: */
915: nfsrv_fhtovp(fhp, lockflag, vpp, cred)
916: fhandle_t *fhp;
917: int lockflag;
918: struct vnode **vpp;
919: struct ucred *cred;
920: {
921: register struct mount *mp;
922:
923: if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
924: return (ESTALE);
925: if ((mp->mnt_flag & MNT_EXPORTED) == 0)
926: return (EACCES);
927: if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp))
928: return (ESTALE);
929: if (cred->cr_uid == 0)
930: cred->cr_uid = mp->mnt_exroot;
931: if (!lockflag)
932: VOP_UNLOCK(*vpp);
933: return (0);
934: }
935:
936: /*
937: * These two functions implement nfs rpc compression.
938: * The algorithm is a trivial run length encoding of '\0' bytes. The high
939: * order nibble of hex "e" is or'd with the number of zeroes - 2 in four
940: * bits. (2 - 17 zeros) Any data byte with a high order nibble of hex "e"
941: * is byte stuffed.
942: * The compressed data is padded with 0x0 bytes to an even multiple of
943: * 4 bytes in length to avoid any weird long pointer alignments.
944: * If compression/uncompression is unsuccessful, the original mbuf list
945: * is returned.
946: * The first four bytes (the XID) are left uncompressed and the fifth
947: * byte is set to 0x1 for request and 0x2 for reply.
948: * An uncompressed RPC will always have the fifth byte == 0x0.
949: */
950: struct mbuf *
951: nfs_compress(m0)
952: struct mbuf *m0;
953: {
954: register u_char ch, nextch;
955: register int i, rlelast;
956: register u_char *ip, *op;
957: register int ileft, oleft, noteof;
958: register struct mbuf *m, *om;
959: struct mbuf **mp, *retm;
960: int olen, clget;
961:
962: i = rlelast = 0;
963: noteof = 1;
964: m = m0;
965: if (m->m_len < 12)
966: return (m0);
967: if (m->m_pkthdr.len >= MINCLSIZE)
968: clget = 1;
969: else
970: clget = 0;
971: ileft = m->m_len - 9;
972: ip = mtod(m, u_char *);
973: MGETHDR(om, M_WAIT, MT_DATA);
974: if (clget)
975: MCLGET(om, M_WAIT);
976: retm = om;
977: mp = &om->m_next;
978: olen = om->m_len = 5;
979: oleft = M_TRAILINGSPACE(om);
980: op = mtod(om, u_char *);
981: *((u_long *)op) = *((u_long *)ip);
982: ip += 7;
983: op += 4;
984: *op++ = *ip++ + 1;
985: nextch = *ip++;
986: while (noteof) {
987: ch = nextch;
988: if (ileft == 0) {
989: do {
990: m = m->m_next;
991: } while (m && m->m_len == 0);
992: if (m) {
993: ileft = m->m_len;
994: ip = mtod(m, u_char *);
995: } else {
996: noteof = 0;
997: nextch = 0x1;
998: goto doit;
999: }
1000: }
1001: nextch = *ip++;
1002: ileft--;
1003: doit:
1004: if (ch == '\0') {
1005: if (++i == NFSC_MAX || nextch != '\0') {
1006: if (i < 2) {
1007: nfscput('\0');
1008: } else {
1009: if (rlelast == i) {
1010: nfscput('\0');
1011: i--;
1012: }
1013: if (NFSCRLE(i) == (nextch & 0xff)) {
1014: i--;
1015: if (i < 2) {
1016: nfscput('\0');
1017: } else {
1018: nfscput(NFSCRLE(i));
1019: }
1020: nfscput('\0');
1021: rlelast = 0;
1022: } else {
1023: nfscput(NFSCRLE(i));
1024: rlelast = i;
1025: }
1026: }
1027: i = 0;
1028: }
1029: } else {
1030: if ((ch & NFSCRL) == NFSCRL) {
1031: nfscput(ch);
1032: }
1033: nfscput(ch);
1034: i = rlelast = 0;
1035: }
1036: }
1037: if (olen < m0->m_pkthdr.len) {
1038: m_freem(m0);
1039: if (i = (olen & 0x3)) {
1040: i = 4 - i;
1041: while (i-- > 0) {
1042: nfscput('\0');
1043: }
1044: }
1045: retm->m_pkthdr.len = olen;
1046: retm->m_pkthdr.rcvif = (struct ifnet *)0;
1047: return (retm);
1048: } else {
1049: m_freem(retm);
1050: return (m0);
1051: }
1052: }
1053:
1054: struct mbuf *
1055: nfs_uncompress(m0)
1056: struct mbuf *m0;
1057: {
1058: register u_char cp, nextcp, *ip, *op;
1059: register struct mbuf *m, *om;
1060: struct mbuf *retm, **mp;
1061: int i, j, noteof, clget, ileft, oleft, olen;
1062:
1063: m = m0;
1064: i = 0;
1065: while (m && i < MINCLSIZE) {
1066: i += m->m_len;
1067: m = m->m_next;
1068: }
1069: if (i < 6)
1070: return (m0);
1071: if (i >= MINCLSIZE)
1072: clget = 1;
1073: else
1074: clget = 0;
1075: m = m0;
1076: MGET(om, M_WAIT, MT_DATA);
1077: if (clget)
1078: MCLGET(om, M_WAIT);
1079: olen = om->m_len = 8;
1080: oleft = M_TRAILINGSPACE(om);
1081: op = mtod(om, u_char *);
1082: retm = om;
1083: mp = &om->m_next;
1084: if (m->m_len >= 6) {
1085: ileft = m->m_len - 6;
1086: ip = mtod(m, u_char *);
1087: *((u_long *)op) = *((u_long *)ip);
1088: bzero(op + 4, 3);
1089: ip += 4;
1090: op += 7;
1091: if (*ip == '\0') {
1092: m_freem(om);
1093: return (m0);
1094: }
1095: *op++ = *ip++ - 1;
1096: cp = *ip++;
1097: } else {
1098: ileft = m->m_len;
1099: ip = mtod(m, u_char *);
1100: nfscget(*op++);
1101: nfscget(*op++);
1102: nfscget(*op++);
1103: nfscget(*op++);
1104: bzero(op, 3);
1105: op += 3;
1106: nfscget(*op);
1107: if (*op == '\0') {
1108: m_freem(om);
1109: return (m0);
1110: }
1111: (*op)--;
1112: op++;
1113: nfscget(cp);
1114: }
1115: noteof = 1;
1116: while (noteof) {
1117: if ((cp & NFSCRL) == NFSCRL) {
1118: nfscget(nextcp);
1119: if (cp == nextcp) {
1120: nfscput(cp);
1121: goto readit;
1122: } else {
1123: i = (cp & 0xf) + 2;
1124: for (j = 0; j < i; j++) {
1125: nfscput('\0');
1126: }
1127: cp = nextcp;
1128: }
1129: } else {
1130: nfscput(cp);
1131: readit:
1132: nfscget(cp);
1133: }
1134: }
1135: m_freem(m0);
1136: if (i = (olen & 0x3))
1137: om->m_len -= i;
1138: return (retm);
1139: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.