|
|
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: *
1.1.1.4 ! root 36: * from: @(#)nfs_subs.c 7.41 (Berkeley) 5/15/91
! 37: * nfs_subs.c,v 1.6 1993/07/13 10:40:07 cgd Exp
1.1 root 38: */
39:
40: /*
41: * These functions support the macros and help fiddle mbuf chains for
42: * the nfs op functions. They do things like create the rpc header and
43: * copy data between mbuf chains and uio lists.
44: */
45: #include "param.h"
46: #include "proc.h"
47: #include "filedesc.h"
48: #include "systm.h"
49: #include "kernel.h"
50: #include "mount.h"
51: #include "file.h"
52: #include "vnode.h"
53: #include "namei.h"
54: #include "mbuf.h"
55:
56: #include "../ufs/quota.h"
57: #include "../ufs/inode.h"
58:
59: #include "rpcv2.h"
60: #include "nfsv2.h"
61: #include "nfsnode.h"
62: #include "nfs.h"
63: #include "nfsiom.h"
64: #include "xdr_subs.h"
65: #include "nfsm_subs.h"
66: #include "nfscompress.h"
67:
68: #define TRUE 1
69: #define FALSE 0
70:
71: /*
72: * Data items converted to xdr at startup, since they are constant
73: * This is kinda hokey, but may save a little time doing byte swaps
74: */
75: u_long nfs_procids[NFS_NPROCS];
76: u_long nfs_xdrneg1;
77: u_long rpc_call, rpc_vers, rpc_reply, rpc_msgdenied,
78: rpc_mismatch, rpc_auth_unix, rpc_msgaccepted;
79: u_long nfs_vers, nfs_prog, nfs_true, nfs_false;
80: /* And other global data */
81: static u_long *rpc_uidp = (u_long *)0;
82: static u_long nfs_xid = 1;
83: static char *rpc_unixauth;
84: extern long hostid;
1.1.1.3 root 85:
1.1 root 86: extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
87: extern struct nfsreq nfsreqh;
88:
89: /* Function ret types */
90: static char *nfs_unixauth();
91:
92: /*
93: * Maximum number of groups passed through to NFS server.
94: * According to RFC1057 it should be 16.
95: * For release 3.X systems, the maximum value is 8.
96: * For some other servers, the maximum value is 10.
97: */
98: int numgrps = 8;
99:
100: /*
101: * Create the header for an rpc request packet
102: * The function nfs_unixauth() creates a unix style authorization string
103: * and returns a ptr to it.
104: * The hsiz is the size of the rest of the nfs request header.
105: * (just used to decide if a cluster is a good idea)
106: * nb: Note that the prog, vers and procid args are already in xdr byte order
107: */
108: struct mbuf *nfsm_reqh(prog, vers, procid, cred, hsiz, bpos, mb, retxid)
109: u_long prog;
110: u_long vers;
111: u_long procid;
112: struct ucred *cred;
113: int hsiz;
1.1.1.4 ! root 114: caddr_t **bpos;
1.1 root 115: struct mbuf **mb;
116: u_long *retxid;
117: {
118: register struct mbuf *mreq, *m;
119: register u_long *tl;
120: struct mbuf *m1;
121: char *ap;
122: int asiz, siz;
1.1.1.4 ! root 123: static char authnull[4*NFSX_UNSIGNED];
1.1 root 124:
125: NFSMGETHDR(mreq);
1.1.1.4 ! root 126: if (cred != NOCRED) {
! 127: asiz = ((((cred->cr_ngroups - 1) > numgrps) ? numgrps :
! 128: (cred->cr_ngroups - 1)) << 2);
1.1 root 129: #ifdef FILLINHOST
1.1.1.4 ! root 130: asiz += nfsm_rndup(hostnamelen)+(9*NFSX_UNSIGNED);
1.1 root 131: #else
1.1.1.4 ! root 132: asiz += 9*NFSX_UNSIGNED;
1.1 root 133: #endif
1.1.1.4 ! root 134: } else
! 135: asiz = 4 * NFSX_UNSIGNED;
1.1 root 136:
137: /* If we need a lot, alloc a cluster ?? */
138: if ((asiz+hsiz+RPC_SIZ) > MHLEN)
139: MCLGET(mreq, M_WAIT);
140: mreq->m_len = NFSMSIZ(mreq);
141: siz = mreq->m_len;
142: m1 = mreq;
143: /*
144: * Alloc enough mbufs
145: * We do it now to avoid all sleeps after the call to nfs_unixauth()
146: */
147: while ((asiz+RPC_SIZ) > siz) {
148: MGET(m, M_WAIT, MT_DATA);
149: m1->m_next = m;
150: m->m_len = MLEN;
151: siz += MLEN;
152: m1 = m;
153: }
154: tl = mtod(mreq, u_long *);
155: *tl++ = *retxid = txdr_unsigned(++nfs_xid);
156: *tl++ = rpc_call;
157: *tl++ = rpc_vers;
158: *tl++ = prog;
159: *tl++ = vers;
160: *tl++ = procid;
161:
162: /* Now we can call nfs_unixauth() and copy it in */
1.1.1.4 ! root 163: if (cred != NOCRED)
! 164: ap = nfs_unixauth(cred);
! 165: else
! 166: ap = authnull;
1.1 root 167: m = mreq;
168: siz = m->m_len-RPC_SIZ;
169: if (asiz <= siz) {
170: bcopy(ap, (caddr_t)tl, asiz);
171: m->m_len = asiz+RPC_SIZ;
172: } else {
173: bcopy(ap, (caddr_t)tl, siz);
174: ap += siz;
175: asiz -= siz;
176: while (asiz > 0) {
177: siz = (asiz > MLEN) ? MLEN : asiz;
178: m = m->m_next;
179: bcopy(ap, mtod(m, caddr_t), siz);
180: m->m_len = siz;
181: asiz -= siz;
182: ap += siz;
183: }
184: }
185:
186: /* Finally, return values */
187: *mb = m;
188: *bpos = mtod(m, caddr_t)+m->m_len;
189: return (mreq);
190: }
191:
192: /*
193: * copies mbuf chain to the uio scatter/gather list
194: */
195: nfsm_mbuftouio(mrep, uiop, siz, dpos)
196: struct mbuf **mrep;
197: register struct uio *uiop;
198: int siz;
199: caddr_t *dpos;
200: {
201: register char *mbufcp, *uiocp;
202: register int xfer, left, len;
203: register struct mbuf *mp;
204: long uiosiz, rem;
205: int error = 0;
206:
207: mp = *mrep;
208: mbufcp = *dpos;
209: len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
210: rem = nfsm_rndup(siz)-siz;
211: while (siz > 0) {
212: if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
213: return (EFBIG);
214: left = uiop->uio_iov->iov_len;
215: uiocp = uiop->uio_iov->iov_base;
216: if (left > siz)
217: left = siz;
218: uiosiz = left;
219: while (left > 0) {
220: while (len == 0) {
221: mp = mp->m_next;
222: if (mp == NULL)
223: return (EBADRPC);
224: mbufcp = mtod(mp, caddr_t);
225: len = mp->m_len;
226: }
227: xfer = (left > len) ? len : left;
228: #ifdef notdef
229: /* Not Yet.. */
230: if (uiop->uio_iov->iov_op != NULL)
231: (*(uiop->uio_iov->iov_op))
232: (mbufcp, uiocp, xfer);
233: else
234: #endif
235: if (uiop->uio_segflg == UIO_SYSSPACE)
236: bcopy(mbufcp, uiocp, xfer);
237: else
238: copyout(mbufcp, uiocp, xfer);
239: left -= xfer;
240: len -= xfer;
241: mbufcp += xfer;
242: uiocp += xfer;
243: uiop->uio_offset += xfer;
244: uiop->uio_resid -= xfer;
245: }
246: if (uiop->uio_iov->iov_len <= siz) {
247: uiop->uio_iovcnt--;
248: uiop->uio_iov++;
249: } else {
250: uiop->uio_iov->iov_base += uiosiz;
251: uiop->uio_iov->iov_len -= uiosiz;
252: }
253: siz -= uiosiz;
254: }
255: *dpos = mbufcp;
256: *mrep = mp;
257: if (rem > 0) {
258: if (len < rem)
259: error = nfs_adv(mrep, dpos, rem, len);
260: else
261: *dpos += rem;
262: }
263: return (error);
264: }
265:
266: /*
267: * copies a uio scatter/gather list to an mbuf chain...
268: */
269: nfsm_uiotombuf(uiop, mq, siz, bpos)
270: register struct uio *uiop;
271: struct mbuf **mq;
272: int siz;
273: caddr_t *bpos;
274: {
275: register char *uiocp;
276: register struct mbuf *mp, *mp2;
277: register int xfer, left, len;
278: int uiosiz, clflg, rem;
279: char *cp;
280:
281: if (siz > MLEN) /* or should it >= MCLBYTES ?? */
282: clflg = 1;
283: else
284: clflg = 0;
285: rem = nfsm_rndup(siz)-siz;
286: mp2 = *mq;
287: while (siz > 0) {
288: if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
289: return (EINVAL);
290: left = uiop->uio_iov->iov_len;
291: uiocp = uiop->uio_iov->iov_base;
292: if (left > siz)
293: left = siz;
294: uiosiz = left;
295: while (left > 0) {
296: MGET(mp, M_WAIT, MT_DATA);
297: if (clflg)
298: MCLGET(mp, M_WAIT);
299: mp->m_len = NFSMSIZ(mp);
300: mp2->m_next = mp;
301: mp2 = mp;
302: xfer = (left > mp->m_len) ? mp->m_len : left;
303: #ifdef notdef
304: /* Not Yet.. */
305: if (uiop->uio_iov->iov_op != NULL)
306: (*(uiop->uio_iov->iov_op))
307: (uiocp, mtod(mp, caddr_t), xfer);
308: else
309: #endif
310: if (uiop->uio_segflg == UIO_SYSSPACE)
311: bcopy(uiocp, mtod(mp, caddr_t), xfer);
312: else
313: copyin(uiocp, mtod(mp, caddr_t), xfer);
314: len = mp->m_len;
315: mp->m_len = xfer;
316: left -= xfer;
317: uiocp += xfer;
318: uiop->uio_offset += xfer;
319: uiop->uio_resid -= xfer;
320: }
321: if (uiop->uio_iov->iov_len <= siz) {
322: uiop->uio_iovcnt--;
323: uiop->uio_iov++;
324: } else {
325: uiop->uio_iov->iov_base += uiosiz;
326: uiop->uio_iov->iov_len -= uiosiz;
327: }
328: siz -= uiosiz;
329: }
330: if (rem > 0) {
331: if (rem > (len-mp->m_len)) {
332: MGET(mp, M_WAIT, MT_DATA);
333: mp->m_len = 0;
334: mp2->m_next = mp;
335: }
336: cp = mtod(mp, caddr_t)+mp->m_len;
337: for (left = 0; left < rem; left++)
338: *cp++ = '\0';
339: mp->m_len += rem;
340: *bpos = cp;
341: } else
342: *bpos = mtod(mp, caddr_t)+mp->m_len;
343: *mq = mp;
344: return (0);
345: }
346:
347: /*
348: * Help break down an mbuf chain by setting the first siz bytes contiguous
349: * pointed to by returned val.
350: * If Updateflg == True we can overwrite the first part of the mbuf data
351: * This is used by the macros nfsm_disect and nfsm_disecton for tough
352: * cases. (The macros use the vars. dpos and dpos2)
353: */
354: nfsm_disct(mdp, dposp, siz, left, updateflg, cp2)
355: struct mbuf **mdp;
356: caddr_t *dposp;
357: int siz;
358: int left;
359: int updateflg;
360: caddr_t *cp2;
361: {
362: register struct mbuf *mp, *mp2;
363: register int siz2, xfer;
364: register caddr_t tl;
365:
366: mp = *mdp;
367: while (left == 0) {
368: *mdp = mp = mp->m_next;
369: if (mp == NULL)
370: return (EBADRPC);
371: left = mp->m_len;
372: *dposp = mtod(mp, caddr_t);
373: }
374: if (left >= siz) {
375: *cp2 = *dposp;
376: *dposp += siz;
377: } else if (mp->m_next == NULL) {
378: return (EBADRPC);
379: } else if (siz > MHLEN) {
380: panic("nfs S too big");
381: } else {
382: /* Iff update, you can overwrite, else must alloc new mbuf */
383: if (updateflg) {
384: NFSMINOFF(mp);
385: } else {
386: MGET(mp2, M_WAIT, MT_DATA);
387: mp2->m_next = mp->m_next;
388: mp->m_next = mp2;
389: mp->m_len -= left;
390: mp = mp2;
391: }
392: *cp2 = tl = mtod(mp, caddr_t);
393: bcopy(*dposp, tl, left); /* Copy what was left */
394: siz2 = siz-left;
395: tl += left;
396: mp2 = mp->m_next;
397: /* Loop around copying up the siz2 bytes */
398: while (siz2 > 0) {
399: if (mp2 == NULL)
400: return (EBADRPC);
401: xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
402: if (xfer > 0) {
403: bcopy(mtod(mp2, caddr_t), tl, xfer);
404: NFSMADV(mp2, xfer);
405: mp2->m_len -= xfer;
406: tl += xfer;
407: siz2 -= xfer;
408: }
409: if (siz2 > 0)
410: mp2 = mp2->m_next;
411: }
412: mp->m_len = siz;
413: *mdp = mp2;
414: *dposp = mtod(mp2, caddr_t);
415: }
416: return (0);
417: }
418:
419: /*
420: * Advance the position in the mbuf chain.
421: */
422: nfs_adv(mdp, dposp, offs, left)
423: struct mbuf **mdp;
424: caddr_t *dposp;
425: int offs;
426: int left;
427: {
428: register struct mbuf *m;
429: register int s;
430:
431: m = *mdp;
432: s = left;
433: while (s < offs) {
434: offs -= s;
435: m = m->m_next;
436: if (m == NULL)
437: return (EBADRPC);
438: s = m->m_len;
439: }
440: *mdp = m;
441: *dposp = mtod(m, caddr_t)+offs;
442: return (0);
443: }
444:
445: /*
446: * Copy a string into mbufs for the hard cases...
447: */
448: nfsm_strtmbuf(mb, bpos, cp, siz)
449: struct mbuf **mb;
450: char **bpos;
451: char *cp;
452: long siz;
453: {
454: register struct mbuf *m1, *m2;
455: long left, xfer, len, tlen;
456: u_long *tl;
457: int putsize;
458:
459: putsize = 1;
460: m2 = *mb;
461: left = NFSMSIZ(m2)-m2->m_len;
462: if (left > 0) {
463: tl = ((u_long *)(*bpos));
464: *tl++ = txdr_unsigned(siz);
465: putsize = 0;
466: left -= NFSX_UNSIGNED;
467: m2->m_len += NFSX_UNSIGNED;
468: if (left > 0) {
469: bcopy(cp, (caddr_t) tl, left);
470: siz -= left;
471: cp += left;
472: m2->m_len += left;
473: left = 0;
474: }
475: }
476: /* Loop arround adding mbufs */
477: while (siz > 0) {
478: MGET(m1, M_WAIT, MT_DATA);
479: if (siz > MLEN)
480: MCLGET(m1, M_WAIT);
481: m1->m_len = NFSMSIZ(m1);
482: m2->m_next = m1;
483: m2 = m1;
484: tl = mtod(m1, u_long *);
485: tlen = 0;
486: if (putsize) {
487: *tl++ = txdr_unsigned(siz);
488: m1->m_len -= NFSX_UNSIGNED;
489: tlen = NFSX_UNSIGNED;
490: putsize = 0;
491: }
492: if (siz < m1->m_len) {
493: len = nfsm_rndup(siz);
494: xfer = siz;
495: if (xfer < len)
496: *(tl+(xfer>>2)) = 0;
497: } else {
498: xfer = len = m1->m_len;
499: }
500: bcopy(cp, (caddr_t) tl, xfer);
501: m1->m_len = len+tlen;
502: siz -= xfer;
503: cp += xfer;
504: }
505: *mb = m1;
506: *bpos = mtod(m1, caddr_t)+m1->m_len;
507: return (0);
508: }
509:
510: /*
511: * Called once to initialize data structures...
512: */
513: nfs_init()
514: {
515: register int i;
516:
517: rpc_vers = txdr_unsigned(RPC_VER2);
518: rpc_call = txdr_unsigned(RPC_CALL);
519: rpc_reply = txdr_unsigned(RPC_REPLY);
520: rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
521: rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
522: rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
523: rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
524: nfs_vers = txdr_unsigned(NFS_VER2);
525: nfs_prog = txdr_unsigned(NFS_PROG);
526: nfs_true = txdr_unsigned(TRUE);
527: nfs_false = txdr_unsigned(FALSE);
528: /* Loop thru nfs procids */
529: for (i = 0; i < NFS_NPROCS; i++)
530: nfs_procids[i] = txdr_unsigned(i);
531: /* Ensure async daemons disabled */
1.1.1.3 root 532: nfs_xdrneg1 = txdr_unsigned(-1);
533: #ifdef NFSCLIENT
1.1 root 534: for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
535: nfs_iodwant[i] = (struct proc *)0;
536: nfs_nhinit(); /* Init the nfsnode table */
1.1.1.3 root 537: #endif /* NFSCLIENT */
538: #ifdef NFSSERVER
1.1 root 539: nfsrv_initcache(); /* Init the server request cache */
1.1.1.3 root 540: #endif /*NFSSERVER */
1.1 root 541: /*
542: * Initialize reply list and start timer
543: */
544: nfsreqh.r_prev = nfsreqh.r_next = &nfsreqh;
545: nfs_timer();
546: }
547:
548: /*
549: * Fill in the rest of the rpc_unixauth and return it
550: */
551: static char *nfs_unixauth(cr)
552: register struct ucred *cr;
553: {
554: register u_long *tl;
555: register int i;
556: int ngr;
557:
558: /* Maybe someday there should be a cache of AUTH_SHORT's */
559: if ((tl = rpc_uidp) == NULL) {
560: #ifdef FILLINHOST
561: i = nfsm_rndup(hostnamelen)+(25*NFSX_UNSIGNED);
562: #else
563: i = 25*NFSX_UNSIGNED;
564: #endif
565: MALLOC(tl, u_long *, i, M_TEMP, M_WAITOK);
566: bzero((caddr_t)tl, i);
567: rpc_unixauth = (caddr_t)tl;
568: *tl++ = txdr_unsigned(RPCAUTH_UNIX);
569: tl++; /* Fill in size later */
570: *tl++ = hostid;
571: #ifdef FILLINHOST
572: *tl++ = txdr_unsigned(hostnamelen);
573: i = nfsm_rndup(hostnamelen);
574: bcopy(hostname, (caddr_t)tl, hostnamelen);
575: tl += (i>>2);
576: #else
577: *tl++ = 0;
578: #endif
579: rpc_uidp = tl;
580: }
581: *tl++ = txdr_unsigned(cr->cr_uid);
582: *tl++ = txdr_unsigned(cr->cr_groups[0]);
583: ngr = ((cr->cr_ngroups - 1) > numgrps) ? numgrps : (cr->cr_ngroups - 1);
584: *tl++ = txdr_unsigned(ngr);
585: for (i = 1; i <= ngr; i++)
586: *tl++ = txdr_unsigned(cr->cr_groups[i]);
587: /* And add the AUTH_NULL */
588: *tl++ = 0;
589: *tl = 0;
590: i = (((caddr_t)tl)-rpc_unixauth)-12;
591: tl = (u_long *)(rpc_unixauth+4);
592: *tl = txdr_unsigned(i);
593: return (rpc_unixauth);
594: }
595:
596: /*
597: * Set up nameidata for a namei() call and do it
598: */
599: nfs_namei(ndp, fhp, len, mdp, dposp, p)
600: register struct nameidata *ndp;
601: fhandle_t *fhp;
602: int len;
603: struct mbuf **mdp;
604: caddr_t *dposp;
605: struct proc *p;
606: {
607: register int i, rem;
608: register struct mbuf *md;
609: register char *fromcp, *tocp;
610: struct vnode *dp;
611: int flag;
612: int error;
613:
614: flag = ndp->ni_nameiop & OPMASK;
615: MALLOC(ndp->ni_pnbuf, char *, len + 1, M_NAMEI, M_WAITOK);
616: /*
617: * Copy the name from the mbuf list to ndp->ni_pnbuf
618: * and set the various ndp fields appropriately.
619: */
620: fromcp = *dposp;
621: tocp = ndp->ni_pnbuf;
622: md = *mdp;
623: rem = mtod(md, caddr_t) + md->m_len - fromcp;
624: ndp->ni_hash = 0;
625: for (i = 0; i < len; i++) {
626: while (rem == 0) {
627: md = md->m_next;
628: if (md == NULL) {
629: error = EBADRPC;
630: goto out;
631: }
632: fromcp = mtod(md, caddr_t);
633: rem = md->m_len;
634: }
635: if (*fromcp == '\0' || *fromcp == '/') {
636: error = EINVAL;
637: goto out;
638: }
639: if (*fromcp & 0200)
640: if ((*fromcp&0377) == ('/'|0200) || flag != DELETE) {
641: error = EINVAL;
642: goto out;
643: }
644: ndp->ni_hash += (unsigned char)*fromcp;
645: *tocp++ = *fromcp++;
646: rem--;
647: }
648: *tocp = '\0';
649: *mdp = md;
650: *dposp = fromcp;
651: len = nfsm_rndup(len)-len;
652: if (len > 0) {
653: if (rem >= len)
654: *dposp += len;
655: else if (error = nfs_adv(mdp, dposp, len, rem))
656: goto out;
657: }
658: ndp->ni_pathlen = tocp - ndp->ni_pnbuf;
659: ndp->ni_ptr = ndp->ni_pnbuf;
660: /*
661: * Extract and set starting directory.
662: */
663: if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cred))
664: goto out;
665: if (dp->v_type != VDIR) {
666: vrele(dp);
667: error = ENOTDIR;
668: goto out;
669: }
670: ndp->ni_startdir = dp;
671: ndp->ni_nameiop |= (NOCROSSMOUNT | REMOTE);
672: /*
673: * And call lookup() to do the real work
674: */
675: if (error = lookup(ndp, p))
676: goto out;
677: /*
678: * Check for encountering a symbolic link
679: */
680: if (ndp->ni_more) {
681: if ((ndp->ni_nameiop & LOCKPARENT) && ndp->ni_pathlen == 1)
682: vput(ndp->ni_dvp);
683: else
684: vrele(ndp->ni_dvp);
685: vput(ndp->ni_vp);
686: ndp->ni_vp = NULL;
687: error = EINVAL;
688: goto out;
689: }
690: /*
691: * Check for saved name request
692: */
693: if (ndp->ni_nameiop & (SAVENAME | SAVESTART)) {
694: ndp->ni_nameiop |= HASBUF;
695: return (0);
696: }
697: out:
698: FREE(ndp->ni_pnbuf, M_NAMEI);
699: return (error);
700: }
701:
702: /*
703: * A fiddled version of m_adj() that ensures null fill to a long
704: * boundary and only trims off the back end
705: */
706: nfsm_adj(mp, len, nul)
707: struct mbuf *mp;
708: register int len;
709: int nul;
710: {
711: register struct mbuf *m;
712: register int count, i;
713: register char *cp;
714:
715: /*
716: * Trim from tail. Scan the mbuf chain,
717: * calculating its length and finding the last mbuf.
718: * If the adjustment only affects this mbuf, then just
719: * adjust and return. Otherwise, rescan and truncate
720: * after the remaining size.
721: */
722: count = 0;
723: m = mp;
724: for (;;) {
725: count += m->m_len;
726: if (m->m_next == (struct mbuf *)0)
727: break;
728: m = m->m_next;
729: }
730: if (m->m_len > len) {
731: m->m_len -= len;
732: if (nul > 0) {
733: cp = mtod(m, caddr_t)+m->m_len-nul;
734: for (i = 0; i < nul; i++)
735: *cp++ = '\0';
736: }
737: return;
738: }
739: count -= len;
740: if (count < 0)
741: count = 0;
742: /*
743: * Correct length for chain is "count".
744: * Find the mbuf with last data, adjust its length,
745: * and toss data from remaining mbufs on chain.
746: */
747: for (m = mp; m; m = m->m_next) {
748: if (m->m_len >= count) {
749: m->m_len = count;
750: if (nul > 0) {
751: cp = mtod(m, caddr_t)+m->m_len-nul;
752: for (i = 0; i < nul; i++)
753: *cp++ = '\0';
754: }
755: break;
756: }
757: count -= m->m_len;
758: }
759: while (m = m->m_next)
760: m->m_len = 0;
761: }
762:
763: /*
764: * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
765: * - look up fsid in mount list (if not found ret error)
766: * - check that it is exported
767: * - get vp by calling VFS_FHTOVP() macro
768: * - if not lockflag unlock it with VOP_UNLOCK()
769: * - if cred->cr_uid == 0 set it to m_exroot
770: */
771: nfsrv_fhtovp(fhp, lockflag, vpp, cred)
772: fhandle_t *fhp;
773: int lockflag;
774: struct vnode **vpp;
775: struct ucred *cred;
776: {
777: register struct mount *mp;
778:
779: if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
780: return (ESTALE);
781: if ((mp->mnt_flag & MNT_EXPORTED) == 0)
782: return (EACCES);
783: if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp))
784: return (ESTALE);
785: if (cred->cr_uid == 0)
786: cred->cr_uid = mp->mnt_exroot;
787: if (!lockflag)
788: VOP_UNLOCK(*vpp);
789: return (0);
790: }
791:
792: /*
793: * These two functions implement nfs rpc compression.
794: * The algorithm is a trivial run length encoding of '\0' bytes. The high
795: * order nibble of hex "e" is or'd with the number of zeroes - 2 in four
796: * bits. (2 - 17 zeros) Any data byte with a high order nibble of hex "e"
797: * is byte stuffed.
798: * The compressed data is padded with 0x0 bytes to an even multiple of
799: * 4 bytes in length to avoid any weird long pointer alignments.
800: * If compression/uncompression is unsuccessful, the original mbuf list
801: * is returned.
802: * The first four bytes (the XID) are left uncompressed and the fifth
803: * byte is set to 0x1 for request and 0x2 for reply.
804: * An uncompressed RPC will always have the fifth byte == 0x0.
805: */
806: struct mbuf *
807: nfs_compress(m0)
808: struct mbuf *m0;
809: {
810: register u_char ch, nextch;
811: register int i, rlelast;
812: register u_char *ip, *op;
813: register int ileft, oleft, noteof;
814: register struct mbuf *m, *om;
815: struct mbuf **mp, *retm;
816: int olen, clget;
817:
818: i = rlelast = 0;
819: noteof = 1;
820: m = m0;
821: if (m->m_len < 12)
822: return (m0);
823: if (m->m_pkthdr.len >= MINCLSIZE)
824: clget = 1;
825: else
826: clget = 0;
827: ileft = m->m_len - 9;
828: ip = mtod(m, u_char *);
829: MGETHDR(om, M_WAIT, MT_DATA);
830: if (clget)
831: MCLGET(om, M_WAIT);
832: retm = om;
833: mp = &om->m_next;
834: olen = om->m_len = 5;
835: oleft = M_TRAILINGSPACE(om);
836: op = mtod(om, u_char *);
837: *((u_long *)op) = *((u_long *)ip);
838: ip += 7;
839: op += 4;
840: *op++ = *ip++ + 1;
841: nextch = *ip++;
842: while (noteof) {
843: ch = nextch;
844: if (ileft == 0) {
845: do {
846: m = m->m_next;
847: } while (m && m->m_len == 0);
848: if (m) {
849: ileft = m->m_len;
850: ip = mtod(m, u_char *);
851: } else {
852: noteof = 0;
853: nextch = 0x1;
854: goto doit;
855: }
856: }
857: nextch = *ip++;
858: ileft--;
859: doit:
860: if (ch == '\0') {
861: if (++i == NFSC_MAX || nextch != '\0') {
862: if (i < 2) {
863: nfscput('\0');
864: } else {
865: if (rlelast == i) {
866: nfscput('\0');
867: i--;
868: }
869: if (NFSCRLE(i) == (nextch & 0xff)) {
870: i--;
871: if (i < 2) {
872: nfscput('\0');
873: } else {
874: nfscput(NFSCRLE(i));
875: }
876: nfscput('\0');
877: rlelast = 0;
878: } else {
879: nfscput(NFSCRLE(i));
880: rlelast = i;
881: }
882: }
883: i = 0;
884: }
885: } else {
886: if ((ch & NFSCRL) == NFSCRL) {
887: nfscput(ch);
888: }
889: nfscput(ch);
890: i = rlelast = 0;
891: }
892: }
893: if (olen < m0->m_pkthdr.len) {
894: m_freem(m0);
895: if (i = (olen & 0x3)) {
896: i = 4 - i;
897: while (i-- > 0) {
898: nfscput('\0');
899: }
900: }
901: retm->m_pkthdr.len = olen;
902: retm->m_pkthdr.rcvif = (struct ifnet *)0;
903: return (retm);
904: } else {
905: m_freem(retm);
906: return (m0);
907: }
908: }
909:
910: struct mbuf *
911: nfs_uncompress(m0)
912: struct mbuf *m0;
913: {
914: register u_char cp, nextcp, *ip, *op;
915: register struct mbuf *m, *om;
916: struct mbuf *retm, **mp;
917: int i, j, noteof, clget, ileft, oleft, olen;
918:
919: m = m0;
920: i = 0;
921: while (m && i < MINCLSIZE) {
922: i += m->m_len;
923: m = m->m_next;
924: }
925: if (i < 6)
926: return (m0);
927: if (i >= MINCLSIZE)
928: clget = 1;
929: else
930: clget = 0;
931: m = m0;
932: MGET(om, M_WAIT, MT_DATA);
933: if (clget)
934: MCLGET(om, M_WAIT);
935: olen = om->m_len = 8;
936: oleft = M_TRAILINGSPACE(om);
937: op = mtod(om, u_char *);
938: retm = om;
939: mp = &om->m_next;
940: if (m->m_len >= 6) {
941: ileft = m->m_len - 6;
942: ip = mtod(m, u_char *);
943: *((u_long *)op) = *((u_long *)ip);
944: bzero(op + 4, 3);
945: ip += 4;
946: op += 7;
947: if (*ip == '\0') {
948: m_freem(om);
949: return (m0);
950: }
951: *op++ = *ip++ - 1;
952: cp = *ip++;
953: } else {
954: ileft = m->m_len;
955: ip = mtod(m, u_char *);
956: nfscget(*op++);
957: nfscget(*op++);
958: nfscget(*op++);
959: nfscget(*op++);
960: bzero(op, 3);
961: op += 3;
962: nfscget(*op);
963: if (*op == '\0') {
964: m_freem(om);
965: return (m0);
966: }
967: (*op)--;
968: op++;
969: nfscget(cp);
970: }
971: noteof = 1;
972: while (noteof) {
973: if ((cp & NFSCRL) == NFSCRL) {
974: nfscget(nextcp);
975: if (cp == nextcp) {
976: nfscput(cp);
977: goto readit;
978: } else {
979: i = (cp & 0xf) + 2;
980: for (j = 0; j < i; j++) {
981: nfscput('\0');
982: }
983: cp = nextcp;
984: }
985: } else {
986: nfscput(cp);
987: readit:
988: nfscget(cp);
989: }
990: }
991: m_freem(m0);
992: if (i = (olen & 0x3))
993: om->m_len -= i;
994: return (retm);
995: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.