|
|
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;
1.1.1.3 ! root 84:
1.1 root 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 */
1.1.1.3 ! root 524: nfs_xdrneg1 = txdr_unsigned(-1);
! 525: #ifdef NFSCLIENT
1.1 root 526: for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
527: nfs_iodwant[i] = (struct proc *)0;
528: nfs_nhinit(); /* Init the nfsnode table */
1.1.1.3 ! root 529: #endif /* NFSCLIENT */
! 530: #ifdef NFSSERVER
1.1 root 531: nfsrv_initcache(); /* Init the server request cache */
1.1.1.3 ! root 532: #endif /*NFSSERVER */
1.1 root 533: /*
534: * Initialize reply list and start timer
535: */
536: nfsreqh.r_prev = nfsreqh.r_next = &nfsreqh;
537: nfs_timer();
538: }
539:
540: /*
541: * Fill in the rest of the rpc_unixauth and return it
542: */
543: static char *nfs_unixauth(cr)
544: register struct ucred *cr;
545: {
546: register u_long *tl;
547: register int i;
548: int ngr;
549:
550: /* Maybe someday there should be a cache of AUTH_SHORT's */
551: if ((tl = rpc_uidp) == NULL) {
552: #ifdef FILLINHOST
553: i = nfsm_rndup(hostnamelen)+(25*NFSX_UNSIGNED);
554: #else
555: i = 25*NFSX_UNSIGNED;
556: #endif
557: MALLOC(tl, u_long *, i, M_TEMP, M_WAITOK);
558: bzero((caddr_t)tl, i);
559: rpc_unixauth = (caddr_t)tl;
560: *tl++ = txdr_unsigned(RPCAUTH_UNIX);
561: tl++; /* Fill in size later */
562: *tl++ = hostid;
563: #ifdef FILLINHOST
564: *tl++ = txdr_unsigned(hostnamelen);
565: i = nfsm_rndup(hostnamelen);
566: bcopy(hostname, (caddr_t)tl, hostnamelen);
567: tl += (i>>2);
568: #else
569: *tl++ = 0;
570: #endif
571: rpc_uidp = tl;
572: }
573: *tl++ = txdr_unsigned(cr->cr_uid);
574: *tl++ = txdr_unsigned(cr->cr_groups[0]);
575: ngr = ((cr->cr_ngroups - 1) > numgrps) ? numgrps : (cr->cr_ngroups - 1);
576: *tl++ = txdr_unsigned(ngr);
577: for (i = 1; i <= ngr; i++)
578: *tl++ = txdr_unsigned(cr->cr_groups[i]);
579: /* And add the AUTH_NULL */
580: *tl++ = 0;
581: *tl = 0;
582: i = (((caddr_t)tl)-rpc_unixauth)-12;
583: tl = (u_long *)(rpc_unixauth+4);
584: *tl = txdr_unsigned(i);
585: return (rpc_unixauth);
586: }
587:
588: /*
589: * Set up nameidata for a namei() call and do it
590: */
591: nfs_namei(ndp, fhp, len, mdp, dposp, p)
592: register struct nameidata *ndp;
593: fhandle_t *fhp;
594: int len;
595: struct mbuf **mdp;
596: caddr_t *dposp;
597: struct proc *p;
598: {
599: register int i, rem;
600: register struct mbuf *md;
601: register char *fromcp, *tocp;
602: struct vnode *dp;
603: int flag;
604: int error;
605:
606: flag = ndp->ni_nameiop & OPMASK;
607: MALLOC(ndp->ni_pnbuf, char *, len + 1, M_NAMEI, M_WAITOK);
608: /*
609: * Copy the name from the mbuf list to ndp->ni_pnbuf
610: * and set the various ndp fields appropriately.
611: */
612: fromcp = *dposp;
613: tocp = ndp->ni_pnbuf;
614: md = *mdp;
615: rem = mtod(md, caddr_t) + md->m_len - fromcp;
616: ndp->ni_hash = 0;
617: for (i = 0; i < len; i++) {
618: while (rem == 0) {
619: md = md->m_next;
620: if (md == NULL) {
621: error = EBADRPC;
622: goto out;
623: }
624: fromcp = mtod(md, caddr_t);
625: rem = md->m_len;
626: }
627: if (*fromcp == '\0' || *fromcp == '/') {
628: error = EINVAL;
629: goto out;
630: }
631: if (*fromcp & 0200)
632: if ((*fromcp&0377) == ('/'|0200) || flag != DELETE) {
633: error = EINVAL;
634: goto out;
635: }
636: ndp->ni_hash += (unsigned char)*fromcp;
637: *tocp++ = *fromcp++;
638: rem--;
639: }
640: *tocp = '\0';
641: *mdp = md;
642: *dposp = fromcp;
643: len = nfsm_rndup(len)-len;
644: if (len > 0) {
645: if (rem >= len)
646: *dposp += len;
647: else if (error = nfs_adv(mdp, dposp, len, rem))
648: goto out;
649: }
650: ndp->ni_pathlen = tocp - ndp->ni_pnbuf;
651: ndp->ni_ptr = ndp->ni_pnbuf;
652: /*
653: * Extract and set starting directory.
654: */
655: if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cred))
656: goto out;
657: if (dp->v_type != VDIR) {
658: vrele(dp);
659: error = ENOTDIR;
660: goto out;
661: }
662: ndp->ni_startdir = dp;
663: ndp->ni_nameiop |= (NOCROSSMOUNT | REMOTE);
664: /*
665: * And call lookup() to do the real work
666: */
667: if (error = lookup(ndp, p))
668: goto out;
669: /*
670: * Check for encountering a symbolic link
671: */
672: if (ndp->ni_more) {
673: if ((ndp->ni_nameiop & LOCKPARENT) && ndp->ni_pathlen == 1)
674: vput(ndp->ni_dvp);
675: else
676: vrele(ndp->ni_dvp);
677: vput(ndp->ni_vp);
678: ndp->ni_vp = NULL;
679: error = EINVAL;
680: goto out;
681: }
682: /*
683: * Check for saved name request
684: */
685: if (ndp->ni_nameiop & (SAVENAME | SAVESTART)) {
686: ndp->ni_nameiop |= HASBUF;
687: return (0);
688: }
689: out:
690: FREE(ndp->ni_pnbuf, M_NAMEI);
691: return (error);
692: }
693:
694: /*
695: * A fiddled version of m_adj() that ensures null fill to a long
696: * boundary and only trims off the back end
697: */
698: nfsm_adj(mp, len, nul)
699: struct mbuf *mp;
700: register int len;
701: int nul;
702: {
703: register struct mbuf *m;
704: register int count, i;
705: register char *cp;
706:
707: /*
708: * Trim from tail. Scan the mbuf chain,
709: * calculating its length and finding the last mbuf.
710: * If the adjustment only affects this mbuf, then just
711: * adjust and return. Otherwise, rescan and truncate
712: * after the remaining size.
713: */
714: count = 0;
715: m = mp;
716: for (;;) {
717: count += m->m_len;
718: if (m->m_next == (struct mbuf *)0)
719: break;
720: m = m->m_next;
721: }
722: if (m->m_len > len) {
723: m->m_len -= len;
724: if (nul > 0) {
725: cp = mtod(m, caddr_t)+m->m_len-nul;
726: for (i = 0; i < nul; i++)
727: *cp++ = '\0';
728: }
729: return;
730: }
731: count -= len;
732: if (count < 0)
733: count = 0;
734: /*
735: * Correct length for chain is "count".
736: * Find the mbuf with last data, adjust its length,
737: * and toss data from remaining mbufs on chain.
738: */
739: for (m = mp; m; m = m->m_next) {
740: if (m->m_len >= count) {
741: m->m_len = count;
742: if (nul > 0) {
743: cp = mtod(m, caddr_t)+m->m_len-nul;
744: for (i = 0; i < nul; i++)
745: *cp++ = '\0';
746: }
747: break;
748: }
749: count -= m->m_len;
750: }
751: while (m = m->m_next)
752: m->m_len = 0;
753: }
754:
755: /*
756: * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
757: * - look up fsid in mount list (if not found ret error)
758: * - check that it is exported
759: * - get vp by calling VFS_FHTOVP() macro
760: * - if not lockflag unlock it with VOP_UNLOCK()
761: * - if cred->cr_uid == 0 set it to m_exroot
762: */
763: nfsrv_fhtovp(fhp, lockflag, vpp, cred)
764: fhandle_t *fhp;
765: int lockflag;
766: struct vnode **vpp;
767: struct ucred *cred;
768: {
769: register struct mount *mp;
770:
771: if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
772: return (ESTALE);
773: if ((mp->mnt_flag & MNT_EXPORTED) == 0)
774: return (EACCES);
775: if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp))
776: return (ESTALE);
777: if (cred->cr_uid == 0)
778: cred->cr_uid = mp->mnt_exroot;
779: if (!lockflag)
780: VOP_UNLOCK(*vpp);
781: return (0);
782: }
783:
784: /*
785: * These two functions implement nfs rpc compression.
786: * The algorithm is a trivial run length encoding of '\0' bytes. The high
787: * order nibble of hex "e" is or'd with the number of zeroes - 2 in four
788: * bits. (2 - 17 zeros) Any data byte with a high order nibble of hex "e"
789: * is byte stuffed.
790: * The compressed data is padded with 0x0 bytes to an even multiple of
791: * 4 bytes in length to avoid any weird long pointer alignments.
792: * If compression/uncompression is unsuccessful, the original mbuf list
793: * is returned.
794: * The first four bytes (the XID) are left uncompressed and the fifth
795: * byte is set to 0x1 for request and 0x2 for reply.
796: * An uncompressed RPC will always have the fifth byte == 0x0.
797: */
798: struct mbuf *
799: nfs_compress(m0)
800: struct mbuf *m0;
801: {
802: register u_char ch, nextch;
803: register int i, rlelast;
804: register u_char *ip, *op;
805: register int ileft, oleft, noteof;
806: register struct mbuf *m, *om;
807: struct mbuf **mp, *retm;
808: int olen, clget;
809:
810: i = rlelast = 0;
811: noteof = 1;
812: m = m0;
813: if (m->m_len < 12)
814: return (m0);
815: if (m->m_pkthdr.len >= MINCLSIZE)
816: clget = 1;
817: else
818: clget = 0;
819: ileft = m->m_len - 9;
820: ip = mtod(m, u_char *);
821: MGETHDR(om, M_WAIT, MT_DATA);
822: if (clget)
823: MCLGET(om, M_WAIT);
824: retm = om;
825: mp = &om->m_next;
826: olen = om->m_len = 5;
827: oleft = M_TRAILINGSPACE(om);
828: op = mtod(om, u_char *);
829: *((u_long *)op) = *((u_long *)ip);
830: ip += 7;
831: op += 4;
832: *op++ = *ip++ + 1;
833: nextch = *ip++;
834: while (noteof) {
835: ch = nextch;
836: if (ileft == 0) {
837: do {
838: m = m->m_next;
839: } while (m && m->m_len == 0);
840: if (m) {
841: ileft = m->m_len;
842: ip = mtod(m, u_char *);
843: } else {
844: noteof = 0;
845: nextch = 0x1;
846: goto doit;
847: }
848: }
849: nextch = *ip++;
850: ileft--;
851: doit:
852: if (ch == '\0') {
853: if (++i == NFSC_MAX || nextch != '\0') {
854: if (i < 2) {
855: nfscput('\0');
856: } else {
857: if (rlelast == i) {
858: nfscput('\0');
859: i--;
860: }
861: if (NFSCRLE(i) == (nextch & 0xff)) {
862: i--;
863: if (i < 2) {
864: nfscput('\0');
865: } else {
866: nfscput(NFSCRLE(i));
867: }
868: nfscput('\0');
869: rlelast = 0;
870: } else {
871: nfscput(NFSCRLE(i));
872: rlelast = i;
873: }
874: }
875: i = 0;
876: }
877: } else {
878: if ((ch & NFSCRL) == NFSCRL) {
879: nfscput(ch);
880: }
881: nfscput(ch);
882: i = rlelast = 0;
883: }
884: }
885: if (olen < m0->m_pkthdr.len) {
886: m_freem(m0);
887: if (i = (olen & 0x3)) {
888: i = 4 - i;
889: while (i-- > 0) {
890: nfscput('\0');
891: }
892: }
893: retm->m_pkthdr.len = olen;
894: retm->m_pkthdr.rcvif = (struct ifnet *)0;
895: return (retm);
896: } else {
897: m_freem(retm);
898: return (m0);
899: }
900: }
901:
902: struct mbuf *
903: nfs_uncompress(m0)
904: struct mbuf *m0;
905: {
906: register u_char cp, nextcp, *ip, *op;
907: register struct mbuf *m, *om;
908: struct mbuf *retm, **mp;
909: int i, j, noteof, clget, ileft, oleft, olen;
910:
911: m = m0;
912: i = 0;
913: while (m && i < MINCLSIZE) {
914: i += m->m_len;
915: m = m->m_next;
916: }
917: if (i < 6)
918: return (m0);
919: if (i >= MINCLSIZE)
920: clget = 1;
921: else
922: clget = 0;
923: m = m0;
924: MGET(om, M_WAIT, MT_DATA);
925: if (clget)
926: MCLGET(om, M_WAIT);
927: olen = om->m_len = 8;
928: oleft = M_TRAILINGSPACE(om);
929: op = mtod(om, u_char *);
930: retm = om;
931: mp = &om->m_next;
932: if (m->m_len >= 6) {
933: ileft = m->m_len - 6;
934: ip = mtod(m, u_char *);
935: *((u_long *)op) = *((u_long *)ip);
936: bzero(op + 4, 3);
937: ip += 4;
938: op += 7;
939: if (*ip == '\0') {
940: m_freem(om);
941: return (m0);
942: }
943: *op++ = *ip++ - 1;
944: cp = *ip++;
945: } else {
946: ileft = m->m_len;
947: ip = mtod(m, u_char *);
948: nfscget(*op++);
949: nfscget(*op++);
950: nfscget(*op++);
951: nfscget(*op++);
952: bzero(op, 3);
953: op += 3;
954: nfscget(*op);
955: if (*op == '\0') {
956: m_freem(om);
957: return (m0);
958: }
959: (*op)--;
960: op++;
961: nfscget(cp);
962: }
963: noteof = 1;
964: while (noteof) {
965: if ((cp & NFSCRL) == NFSCRL) {
966: nfscget(nextcp);
967: if (cp == nextcp) {
968: nfscput(cp);
969: goto readit;
970: } else {
971: i = (cp & 0xf) + 2;
972: for (j = 0; j < i; j++) {
973: nfscput('\0');
974: }
975: cp = nextcp;
976: }
977: } else {
978: nfscput(cp);
979: readit:
980: nfscget(cp);
981: }
982: }
983: m_freem(m0);
984: if (i = (olen & 0x3))
985: om->m_len -= i;
986: return (retm);
987: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.