|
|
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 is only permitted until one year after the first shipment ! 9: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 10: * binary forms are permitted provided that: (1) source distributions retain ! 11: * this entire copyright notice and comment, and (2) distributions including ! 12: * binaries display the following acknowledgement: This product includes ! 13: * software developed by the University of California, Berkeley and its ! 14: * contributors'' in the documentation or other materials provided with the ! 15: * distribution and in all advertising materials mentioning features or use ! 16: * of this software. Neither the name of the University nor the names of ! 17: * its contributors may be used to endorse or promote products derived from ! 18: * this software without specific prior written permission. ! 19: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 20: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 21: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 22: * ! 23: * @(#)nfs_subs.c 7.29 (Berkeley) 7/26/90 ! 24: */ ! 25: ! 26: /* ! 27: * These functions support the macros and help fiddle mbuf chains for ! 28: * the nfs op functions. They do things like create the rpc header and ! 29: * copy data between mbuf chains and uio lists. ! 30: */ ! 31: #include "param.h" ! 32: #include "user.h" ! 33: #include "proc.h" ! 34: #include "systm.h" ! 35: #include "kernel.h" ! 36: #include "mount.h" ! 37: #include "file.h" ! 38: #include "vnode.h" ! 39: #include "mbuf.h" ! 40: #include "errno.h" ! 41: #include "map.h" ! 42: #include "rpcv2.h" ! 43: #include "nfsv2.h" ! 44: #include "nfsnode.h" ! 45: #include "nfs.h" ! 46: #include "nfsiom.h" ! 47: #include "xdr_subs.h" ! 48: #include "nfsm_subs.h" ! 49: ! 50: #define TRUE 1 ! 51: #define FALSE 0 ! 52: ! 53: /* ! 54: * Data items converted to xdr at startup, since they are constant ! 55: * This is kinda hokey, but may save a little time doing byte swaps ! 56: */ ! 57: u_long nfs_procids[NFS_NPROCS]; ! 58: u_long nfs_xdrneg1; ! 59: u_long rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, ! 60: rpc_mismatch, rpc_auth_unix, rpc_msgaccepted; ! 61: u_long nfs_vers, nfs_prog, nfs_true, nfs_false; ! 62: /* And other global data */ ! 63: static u_long *rpc_uidp = (u_long *)0; ! 64: static u_long nfs_xid = 1; ! 65: static char *rpc_unixauth; ! 66: extern long hostid; ! 67: enum vtype ntov_type[7] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON }; ! 68: extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; ! 69: extern struct map nfsmap[NFS_MSIZ]; ! 70: extern struct nfsreq nfsreqh; ! 71: ! 72: /* Function ret types */ ! 73: static char *nfs_unixauth(); ! 74: ! 75: /* ! 76: * Maximum number of groups passed through to NFS server. ! 77: * According to RFC1057 it should be 16. ! 78: * For release 3.X systems, the maximum value is 8. ! 79: * For some other servers, the maximum value is 10. ! 80: */ ! 81: int numgrps = 8; ! 82: ! 83: /* ! 84: * Create the header for an rpc request packet ! 85: * The function nfs_unixauth() creates a unix style authorization string ! 86: * and returns a ptr to it. ! 87: * The hsiz is the size of the rest of the nfs request header. ! 88: * (just used to decide if a cluster is a good idea) ! 89: * nb: Note that the prog, vers and procid args are already in xdr byte order ! 90: */ ! 91: struct mbuf *nfsm_reqh(prog, vers, procid, cred, hsiz, bpos, mb, retxid) ! 92: u_long prog; ! 93: u_long vers; ! 94: u_long procid; ! 95: struct ucred *cred; ! 96: int hsiz; ! 97: caddr_t *bpos; ! 98: struct mbuf **mb; ! 99: u_long *retxid; ! 100: { ! 101: register struct mbuf *mreq, *m; ! 102: register u_long *p; ! 103: struct mbuf *m1; ! 104: char *ap; ! 105: int asiz, siz; ! 106: ! 107: NFSMGETHDR(mreq); ! 108: asiz = ((((cred->cr_ngroups - 1) > numgrps) ? numgrps : ! 109: (cred->cr_ngroups - 1)) << 2); ! 110: #ifdef FILLINHOST ! 111: asiz += nfsm_rndup(hostnamelen)+(9*NFSX_UNSIGNED); ! 112: #else ! 113: asiz += 9*NFSX_UNSIGNED; ! 114: #endif ! 115: ! 116: /* If we need a lot, alloc a cluster ?? */ ! 117: if ((asiz+hsiz+RPC_SIZ) > MHLEN) ! 118: MCLGET(mreq, M_WAIT); ! 119: mreq->m_len = NFSMSIZ(mreq); ! 120: siz = mreq->m_len; ! 121: m1 = mreq; ! 122: /* ! 123: * Alloc enough mbufs ! 124: * We do it now to avoid all sleeps after the call to nfs_unixauth() ! 125: */ ! 126: while ((asiz+RPC_SIZ) > siz) { ! 127: MGET(m, M_WAIT, MT_DATA); ! 128: m1->m_next = m; ! 129: m->m_len = MLEN; ! 130: siz += MLEN; ! 131: m1 = m; ! 132: } ! 133: p = mtod(mreq, u_long *); ! 134: *p++ = *retxid = txdr_unsigned(++nfs_xid); ! 135: *p++ = rpc_call; ! 136: *p++ = rpc_vers; ! 137: *p++ = prog; ! 138: *p++ = vers; ! 139: *p++ = procid; ! 140: ! 141: /* Now we can call nfs_unixauth() and copy it in */ ! 142: ap = nfs_unixauth(cred); ! 143: m = mreq; ! 144: siz = m->m_len-RPC_SIZ; ! 145: if (asiz <= siz) { ! 146: bcopy(ap, (caddr_t)p, asiz); ! 147: m->m_len = asiz+RPC_SIZ; ! 148: } else { ! 149: bcopy(ap, (caddr_t)p, siz); ! 150: ap += siz; ! 151: asiz -= siz; ! 152: while (asiz > 0) { ! 153: siz = (asiz > MLEN) ? MLEN : asiz; ! 154: m = m->m_next; ! 155: bcopy(ap, mtod(m, caddr_t), siz); ! 156: m->m_len = siz; ! 157: asiz -= siz; ! 158: ap += siz; ! 159: } ! 160: } ! 161: ! 162: /* Finally, return values */ ! 163: *mb = m; ! 164: *bpos = mtod(m, caddr_t)+m->m_len; ! 165: return (mreq); ! 166: } ! 167: ! 168: /* ! 169: * copies mbuf chain to the uio scatter/gather list ! 170: */ ! 171: nfsm_mbuftouio(mrep, uiop, siz, dpos) ! 172: struct mbuf **mrep; ! 173: register struct uio *uiop; ! 174: int siz; ! 175: caddr_t *dpos; ! 176: { ! 177: register char *mbufcp, *uiocp; ! 178: register int xfer, left, len; ! 179: register struct mbuf *mp; ! 180: long uiosiz, rem; ! 181: int error = 0; ! 182: ! 183: mp = *mrep; ! 184: mbufcp = *dpos; ! 185: len = mtod(mp, caddr_t)+mp->m_len-mbufcp; ! 186: rem = nfsm_rndup(siz)-siz; ! 187: while (siz > 0) { ! 188: if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) ! 189: return (EFBIG); ! 190: left = uiop->uio_iov->iov_len; ! 191: uiocp = uiop->uio_iov->iov_base; ! 192: if (left > siz) ! 193: left = siz; ! 194: uiosiz = left; ! 195: while (left > 0) { ! 196: while (len == 0) { ! 197: mp = mp->m_next; ! 198: if (mp == NULL) ! 199: return (EBADRPC); ! 200: mbufcp = mtod(mp, caddr_t); ! 201: len = mp->m_len; ! 202: } ! 203: xfer = (left > len) ? len : left; ! 204: #ifdef notdef ! 205: /* Not Yet.. */ ! 206: if (uiop->uio_iov->iov_op != NULL) ! 207: (*(uiop->uio_iov->iov_op)) ! 208: (mbufcp, uiocp, xfer); ! 209: else ! 210: #endif ! 211: if (uiop->uio_segflg == UIO_SYSSPACE) ! 212: bcopy(mbufcp, uiocp, xfer); ! 213: else ! 214: copyout(mbufcp, uiocp, xfer); ! 215: left -= xfer; ! 216: len -= xfer; ! 217: mbufcp += xfer; ! 218: uiocp += xfer; ! 219: uiop->uio_offset += xfer; ! 220: uiop->uio_resid -= xfer; ! 221: } ! 222: if (uiop->uio_iov->iov_len <= siz) { ! 223: uiop->uio_iovcnt--; ! 224: uiop->uio_iov++; ! 225: } else { ! 226: uiop->uio_iov->iov_base += uiosiz; ! 227: uiop->uio_iov->iov_len -= uiosiz; ! 228: } ! 229: siz -= uiosiz; ! 230: } ! 231: *dpos = mbufcp; ! 232: *mrep = mp; ! 233: if (rem > 0) { ! 234: if (len < rem) ! 235: error = nfs_adv(mrep, dpos, rem, len); ! 236: else ! 237: *dpos += rem; ! 238: } ! 239: return (error); ! 240: } ! 241: ! 242: /* ! 243: * copies a uio scatter/gather list to an mbuf chain... ! 244: */ ! 245: nfsm_uiotombuf(uiop, mq, siz, bpos) ! 246: register struct uio *uiop; ! 247: struct mbuf **mq; ! 248: int siz; ! 249: caddr_t *bpos; ! 250: { ! 251: register char *uiocp; ! 252: register struct mbuf *mp, *mp2; ! 253: register int xfer, left, len; ! 254: int uiosiz, clflg, rem; ! 255: char *cp; ! 256: ! 257: if (siz > MLEN) /* or should it >= MCLBYTES ?? */ ! 258: clflg = 1; ! 259: else ! 260: clflg = 0; ! 261: rem = nfsm_rndup(siz)-siz; ! 262: mp2 = *mq; ! 263: while (siz > 0) { ! 264: if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) ! 265: return (EINVAL); ! 266: left = uiop->uio_iov->iov_len; ! 267: uiocp = uiop->uio_iov->iov_base; ! 268: if (left > siz) ! 269: left = siz; ! 270: uiosiz = left; ! 271: while (left > 0) { ! 272: MGET(mp, M_WAIT, MT_DATA); ! 273: if (clflg) ! 274: MCLGET(mp, M_WAIT); ! 275: mp->m_len = NFSMSIZ(mp); ! 276: mp2->m_next = mp; ! 277: mp2 = mp; ! 278: xfer = (left > mp->m_len) ? mp->m_len : left; ! 279: #ifdef notdef ! 280: /* Not Yet.. */ ! 281: if (uiop->uio_iov->iov_op != NULL) ! 282: (*(uiop->uio_iov->iov_op)) ! 283: (uiocp, mtod(mp, caddr_t), xfer); ! 284: else ! 285: #endif ! 286: if (uiop->uio_segflg == UIO_SYSSPACE) ! 287: bcopy(uiocp, mtod(mp, caddr_t), xfer); ! 288: else ! 289: copyin(uiocp, mtod(mp, caddr_t), xfer); ! 290: len = mp->m_len; ! 291: mp->m_len = xfer; ! 292: left -= xfer; ! 293: uiocp += xfer; ! 294: uiop->uio_offset += xfer; ! 295: uiop->uio_resid -= xfer; ! 296: } ! 297: if (uiop->uio_iov->iov_len <= siz) { ! 298: uiop->uio_iovcnt--; ! 299: uiop->uio_iov++; ! 300: } else { ! 301: uiop->uio_iov->iov_base += uiosiz; ! 302: uiop->uio_iov->iov_len -= uiosiz; ! 303: } ! 304: siz -= uiosiz; ! 305: } ! 306: if (rem > 0) { ! 307: if (rem > (len-mp->m_len)) { ! 308: MGET(mp, M_WAIT, MT_DATA); ! 309: mp->m_len = 0; ! 310: mp2->m_next = mp; ! 311: } ! 312: cp = mtod(mp, caddr_t)+mp->m_len; ! 313: for (left = 0; left < rem; left++) ! 314: *cp++ = '\0'; ! 315: mp->m_len += rem; ! 316: *bpos = cp; ! 317: } else ! 318: *bpos = mtod(mp, caddr_t)+mp->m_len; ! 319: *mq = mp; ! 320: return (0); ! 321: } ! 322: ! 323: /* ! 324: * Help break down an mbuf chain by setting the first siz bytes contiguous ! 325: * pointed to by returned val. ! 326: * If Updateflg == True we can overwrite the first part of the mbuf data ! 327: * This is used by the macros nfsm_disect and nfsm_disecton for tough ! 328: * cases. (The macros use the vars. dpos and dpos2) ! 329: */ ! 330: nfsm_disct(mdp, dposp, siz, left, updateflg, cp2) ! 331: struct mbuf **mdp; ! 332: caddr_t *dposp; ! 333: int siz; ! 334: int left; ! 335: int updateflg; ! 336: caddr_t *cp2; ! 337: { ! 338: register struct mbuf *mp, *mp2; ! 339: register int siz2, xfer; ! 340: register caddr_t p; ! 341: ! 342: mp = *mdp; ! 343: while (left == 0) { ! 344: *mdp = mp = mp->m_next; ! 345: if (mp == NULL) ! 346: return (EBADRPC); ! 347: left = mp->m_len; ! 348: *dposp = mtod(mp, caddr_t); ! 349: } ! 350: if (left >= siz) { ! 351: *cp2 = *dposp; ! 352: *dposp += siz; ! 353: } else if (mp->m_next == NULL) { ! 354: return (EBADRPC); ! 355: } else if (siz > MHLEN) { ! 356: panic("nfs S too big"); ! 357: } else { ! 358: /* Iff update, you can overwrite, else must alloc new mbuf */ ! 359: if (updateflg) { ! 360: NFSMINOFF(mp); ! 361: } else { ! 362: MGET(mp2, M_WAIT, MT_DATA); ! 363: mp2->m_next = mp->m_next; ! 364: mp->m_next = mp2; ! 365: mp->m_len -= left; ! 366: mp = mp2; ! 367: } ! 368: *cp2 = p = mtod(mp, caddr_t); ! 369: bcopy(*dposp, p, left); /* Copy what was left */ ! 370: siz2 = siz-left; ! 371: p += left; ! 372: mp2 = mp->m_next; ! 373: /* Loop around copying up the siz2 bytes */ ! 374: while (siz2 > 0) { ! 375: if (mp2 == NULL) ! 376: return (EBADRPC); ! 377: xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2; ! 378: if (xfer > 0) { ! 379: bcopy(mtod(mp2, caddr_t), p, xfer); ! 380: NFSMADV(mp2, xfer); ! 381: mp2->m_len -= xfer; ! 382: p += xfer; ! 383: siz2 -= xfer; ! 384: } ! 385: if (siz2 > 0) ! 386: mp2 = mp2->m_next; ! 387: } ! 388: mp->m_len = siz; ! 389: *mdp = mp2; ! 390: *dposp = mtod(mp2, caddr_t); ! 391: } ! 392: return (0); ! 393: } ! 394: ! 395: /* ! 396: * Advance the position in the mbuf chain. ! 397: */ ! 398: nfs_adv(mdp, dposp, offs, left) ! 399: struct mbuf **mdp; ! 400: caddr_t *dposp; ! 401: int offs; ! 402: int left; ! 403: { ! 404: register struct mbuf *m; ! 405: register int s; ! 406: ! 407: m = *mdp; ! 408: s = left; ! 409: while (s < offs) { ! 410: offs -= s; ! 411: m = m->m_next; ! 412: if (m == NULL) ! 413: return (EBADRPC); ! 414: s = m->m_len; ! 415: } ! 416: *mdp = m; ! 417: *dposp = mtod(m, caddr_t)+offs; ! 418: return (0); ! 419: } ! 420: ! 421: /* ! 422: * Copy a string into mbufs for the hard cases... ! 423: */ ! 424: nfsm_strtmbuf(mb, bpos, cp, siz) ! 425: struct mbuf **mb; ! 426: char **bpos; ! 427: char *cp; ! 428: long siz; ! 429: { ! 430: register struct mbuf *m1, *m2; ! 431: long left, xfer, len, tlen; ! 432: u_long *p; ! 433: int putsize; ! 434: ! 435: putsize = 1; ! 436: m2 = *mb; ! 437: left = NFSMSIZ(m2)-m2->m_len; ! 438: if (left > 0) { ! 439: p = ((u_long *)(*bpos)); ! 440: *p++ = txdr_unsigned(siz); ! 441: putsize = 0; ! 442: left -= NFSX_UNSIGNED; ! 443: m2->m_len += NFSX_UNSIGNED; ! 444: if (left > 0) { ! 445: bcopy(cp, (caddr_t) p, left); ! 446: siz -= left; ! 447: cp += left; ! 448: m2->m_len += left; ! 449: left = 0; ! 450: } ! 451: } ! 452: /* Loop arround adding mbufs */ ! 453: while (siz > 0) { ! 454: MGET(m1, M_WAIT, MT_DATA); ! 455: if (siz > MLEN) ! 456: MCLGET(m1, M_WAIT); ! 457: m1->m_len = NFSMSIZ(m1); ! 458: m2->m_next = m1; ! 459: m2 = m1; ! 460: p = mtod(m1, u_long *); ! 461: tlen = 0; ! 462: if (putsize) { ! 463: *p++ = txdr_unsigned(siz); ! 464: m1->m_len -= NFSX_UNSIGNED; ! 465: tlen = NFSX_UNSIGNED; ! 466: putsize = 0; ! 467: } ! 468: if (siz < m1->m_len) { ! 469: len = nfsm_rndup(siz); ! 470: xfer = siz; ! 471: if (xfer < len) ! 472: *(p+(xfer>>2)) = 0; ! 473: } else { ! 474: xfer = len = m1->m_len; ! 475: } ! 476: bcopy(cp, (caddr_t) p, xfer); ! 477: m1->m_len = len+tlen; ! 478: siz -= xfer; ! 479: cp += xfer; ! 480: } ! 481: *mb = m1; ! 482: *bpos = mtod(m1, caddr_t)+m1->m_len; ! 483: return (0); ! 484: } ! 485: ! 486: /* ! 487: * Called once to initialize data structures... ! 488: */ ! 489: nfs_init() ! 490: { ! 491: register int i; ! 492: ! 493: rpc_vers = txdr_unsigned(RPC_VER2); ! 494: rpc_call = txdr_unsigned(RPC_CALL); ! 495: rpc_reply = txdr_unsigned(RPC_REPLY); ! 496: rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED); ! 497: rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED); ! 498: rpc_mismatch = txdr_unsigned(RPC_MISMATCH); ! 499: rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX); ! 500: nfs_vers = txdr_unsigned(NFS_VER2); ! 501: nfs_prog = txdr_unsigned(NFS_PROG); ! 502: nfs_true = txdr_unsigned(TRUE); ! 503: nfs_false = txdr_unsigned(FALSE); ! 504: /* Loop thru nfs procids */ ! 505: for (i = 0; i < NFS_NPROCS; i++) ! 506: nfs_procids[i] = txdr_unsigned(i); ! 507: /* Ensure async daemons disabled */ ! 508: for (i = 0; i < NFS_MAXASYNCDAEMON; i++) ! 509: nfs_iodwant[i] = (struct proc *)0; ! 510: nfs_xdrneg1 = txdr_unsigned(-1); ! 511: nfs_nhinit(); /* Init the nfsnode table */ ! 512: nfsrv_initcache(); /* Init the server request cache */ ! 513: rminit(nfsmap, (long)NFS_MAPREG, (long)1, "nfs mapreg", NFS_MSIZ); ! 514: ! 515: /* ! 516: * Initialize reply list and start timer ! 517: */ ! 518: nfsreqh.r_prev = nfsreqh.r_next = &nfsreqh; ! 519: nfs_timer(); ! 520: } ! 521: ! 522: /* ! 523: * Fill in the rest of the rpc_unixauth and return it ! 524: */ ! 525: static char *nfs_unixauth(cr) ! 526: register struct ucred *cr; ! 527: { ! 528: register u_long *p; ! 529: register int i; ! 530: int ngr; ! 531: ! 532: /* Maybe someday there should be a cache of AUTH_SHORT's */ ! 533: if ((p = rpc_uidp) == NULL) { ! 534: #ifdef FILLINHOST ! 535: i = nfsm_rndup(hostnamelen)+(25*NFSX_UNSIGNED); ! 536: #else ! 537: i = 25*NFSX_UNSIGNED; ! 538: #endif ! 539: MALLOC(p, u_long *, i, M_TEMP, M_WAITOK); ! 540: bzero((caddr_t)p, i); ! 541: rpc_unixauth = (caddr_t)p; ! 542: *p++ = txdr_unsigned(RPCAUTH_UNIX); ! 543: p++; /* Fill in size later */ ! 544: *p++ = hostid; ! 545: #ifdef FILLINHOST ! 546: *p++ = txdr_unsigned(hostnamelen); ! 547: i = nfsm_rndup(hostnamelen); ! 548: bcopy(hostname, (caddr_t)p, hostnamelen); ! 549: p += (i>>2); ! 550: #else ! 551: *p++ = 0; ! 552: #endif ! 553: rpc_uidp = p; ! 554: } ! 555: *p++ = txdr_unsigned(cr->cr_uid); ! 556: *p++ = txdr_unsigned(cr->cr_groups[0]); ! 557: ngr = ((cr->cr_ngroups - 1) > numgrps) ? numgrps : (cr->cr_ngroups - 1); ! 558: *p++ = txdr_unsigned(ngr); ! 559: for (i = 1; i <= ngr; i++) ! 560: *p++ = txdr_unsigned(cr->cr_groups[i]); ! 561: /* And add the AUTH_NULL */ ! 562: *p++ = 0; ! 563: *p = 0; ! 564: i = (((caddr_t)p)-rpc_unixauth)-12; ! 565: p = (u_long *)(rpc_unixauth+4); ! 566: *p = txdr_unsigned(i); ! 567: return (rpc_unixauth); ! 568: } ! 569: ! 570: /* ! 571: * Attribute cache routines. ! 572: * nfs_loadattrcache() - loads or updates the cache contents from attributes ! 573: * that are on the mbuf list ! 574: * nfs_getattrcache() - returns valid attributes if found in cache, returns ! 575: * error otherwise ! 576: */ ! 577: ! 578: /* ! 579: * Load the attribute cache (that lives in the nfsnode entry) with ! 580: * the values on the mbuf list and ! 581: * Iff vap not NULL ! 582: * copy the attributes to *vaper ! 583: */ ! 584: nfs_loadattrcache(vpp, mdp, dposp, vaper) ! 585: struct vnode **vpp; ! 586: struct mbuf **mdp; ! 587: caddr_t *dposp; ! 588: struct vattr *vaper; ! 589: { ! 590: register struct vnode *vp = *vpp; ! 591: register struct vattr *vap; ! 592: register struct nfsv2_fattr *fp; ! 593: extern struct vnodeops spec_nfsv2nodeops; ! 594: register struct nfsnode *np; ! 595: register long t1; ! 596: caddr_t dpos, cp2; ! 597: int error = 0; ! 598: struct mbuf *md; ! 599: enum vtype type; ! 600: long rdev; ! 601: struct timeval mtime; ! 602: struct vnode *nvp; ! 603: ! 604: md = *mdp; ! 605: dpos = *dposp; ! 606: t1 = (mtod(md, caddr_t)+md->m_len)-dpos; ! 607: if (error = nfsm_disct(&md, &dpos, NFSX_FATTR, t1, TRUE, &cp2)) ! 608: return (error); ! 609: fp = (struct nfsv2_fattr *)cp2; ! 610: type = nfstov_type(fp->fa_type); ! 611: rdev = fxdr_unsigned(long, fp->fa_rdev); ! 612: fxdr_time(&fp->fa_mtime, &mtime); ! 613: /* ! 614: * If v_type == VNON it is a new node, so fill in the v_type, ! 615: * n_mtime fields. Check to see if it represents a special ! 616: * device, and if so, check for a possible alias. Once the ! 617: * correct vnode has been obtained, fill in the rest of the ! 618: * information. ! 619: */ ! 620: np = VTONFS(vp); ! 621: if (vp->v_type == VNON) { ! 622: if (type == VCHR && rdev == 0xffffffff) ! 623: vp->v_type = type = VFIFO; ! 624: else ! 625: vp->v_type = type; ! 626: if (vp->v_type == VFIFO) { ! 627: #ifdef FIFO ! 628: extern struct vnodeops fifo_nfsv2nodeops; ! 629: vp->v_op = &fifo_nfsv2nodeops; ! 630: #else ! 631: return (EOPNOTSUPP); ! 632: #endif /* FIFO */ ! 633: } ! 634: if (vp->v_type == VCHR || vp->v_type == VBLK) { ! 635: vp->v_op = &spec_nfsv2nodeops; ! 636: if (nvp = checkalias(vp, (dev_t)rdev, vp->v_mount)) { ! 637: /* ! 638: * Reinitialize aliased node. ! 639: */ ! 640: np = VTONFS(nvp); ! 641: np->n_vnode = nvp; ! 642: np->n_flag = 0; ! 643: nfs_lock(nvp); ! 644: bcopy((caddr_t)&VTONFS(vp)->n_fh, ! 645: (caddr_t)&np->n_fh, NFSX_FH); ! 646: insque(np, nfs_hash(&np->n_fh)); ! 647: np->n_attrstamp = 0; ! 648: np->n_sillyrename = (struct sillyrename *)0; ! 649: /* ! 650: * Discard unneeded vnode and update actual one ! 651: */ ! 652: vput(vp); ! 653: *vpp = nvp; ! 654: } ! 655: } ! 656: np->n_mtime = mtime.tv_sec; ! 657: } ! 658: vap = &np->n_vattr; ! 659: vap->va_type = type; ! 660: vap->va_mode = nfstov_mode(fp->fa_mode); ! 661: vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink); ! 662: vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid); ! 663: vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid); ! 664: vap->va_size = fxdr_unsigned(u_long, fp->fa_size); ! 665: if ((np->n_flag & NMODIFIED) == 0 || vap->va_size > np->n_size) ! 666: np->n_size = vap->va_size; ! 667: vap->va_size_rsv = 0; ! 668: vap->va_blocksize = fxdr_unsigned(long, fp->fa_blocksize); ! 669: vap->va_rdev = (dev_t)rdev; ! 670: vap->va_bytes = fxdr_unsigned(long, fp->fa_blocks) * NFS_FABLKSIZE; ! 671: vap->va_bytes_rsv = 0; ! 672: vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; ! 673: vap->va_fileid = fxdr_unsigned(long, fp->fa_fileid); ! 674: vap->va_atime.tv_sec = fxdr_unsigned(long, fp->fa_atime.tv_sec); ! 675: vap->va_atime.tv_usec = 0; ! 676: vap->va_flags = fxdr_unsigned(u_long, fp->fa_atime.tv_usec); ! 677: vap->va_mtime = mtime; ! 678: vap->va_ctime.tv_sec = fxdr_unsigned(long, fp->fa_ctime.tv_sec); ! 679: vap->va_ctime.tv_usec = 0; ! 680: vap->va_gen = fxdr_unsigned(u_long, fp->fa_ctime.tv_usec); ! 681: np->n_attrstamp = time.tv_sec; ! 682: *dposp = dpos; ! 683: *mdp = md; ! 684: if (vaper != NULL) { ! 685: bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap)); ! 686: if ((np->n_flag & NMODIFIED) && (np->n_size > vap->va_size)) ! 687: vaper->va_size = np->n_size; ! 688: } ! 689: return (0); ! 690: } ! 691: ! 692: /* ! 693: * Check the time stamp ! 694: * If the cache is valid, copy contents to *vap and return 0 ! 695: * otherwise return an error ! 696: */ ! 697: nfs_getattrcache(vp, vap) ! 698: register struct vnode *vp; ! 699: struct vattr *vap; ! 700: { ! 701: register struct nfsnode *np; ! 702: ! 703: np = VTONFS(vp); ! 704: if ((time.tv_sec-np->n_attrstamp) < NFS_ATTRTIMEO) { ! 705: nfsstats.attrcache_hits++; ! 706: bcopy((caddr_t)&np->n_vattr,(caddr_t)vap,sizeof(struct vattr)); ! 707: if ((np->n_flag & NMODIFIED) == 0) ! 708: np->n_size = vap->va_size; ! 709: else if (np->n_size > vap->va_size) ! 710: vap->va_size = np->n_size; ! 711: return (0); ! 712: } else { ! 713: nfsstats.attrcache_misses++; ! 714: return (ENOENT); ! 715: } ! 716: } ! 717: ! 718: /* ! 719: * Set up nameidata for a namei() call and do it ! 720: */ ! 721: nfs_namei(ndp, fhp, len, mdp, dposp) ! 722: register struct nameidata *ndp; ! 723: fhandle_t *fhp; ! 724: int len; ! 725: struct mbuf **mdp; ! 726: caddr_t *dposp; ! 727: { ! 728: register int i, rem; ! 729: register struct mbuf *md; ! 730: register char *cp; ! 731: struct vnode *dp; ! 732: int flag; ! 733: int error; ! 734: ! 735: if ((ndp->ni_nameiop & HASBUF) == 0) { ! 736: flag = ndp->ni_nameiop & OPFLAG; ! 737: /* ! 738: * Copy the name from the mbuf list to the d_name field of ndp ! 739: * and set the various ndp fields appropriately. ! 740: */ ! 741: cp = *dposp; ! 742: md = *mdp; ! 743: rem = mtod(md, caddr_t)+md->m_len-cp; ! 744: ndp->ni_hash = 0; ! 745: for (i = 0; i < len;) { ! 746: while (rem == 0) { ! 747: md = md->m_next; ! 748: if (md == NULL) ! 749: return (EBADRPC); ! 750: cp = mtod(md, caddr_t); ! 751: rem = md->m_len; ! 752: } ! 753: if (*cp == '\0' || *cp == '/') ! 754: return (EINVAL); ! 755: if (*cp & 0200) ! 756: if ((*cp&0377) == ('/'|0200) || flag != DELETE) ! 757: return (EINVAL); ! 758: ndp->ni_dent.d_name[i++] = *cp; ! 759: ndp->ni_hash += (unsigned char)*cp * i; ! 760: cp++; ! 761: rem--; ! 762: } ! 763: *mdp = md; ! 764: *dposp = cp; ! 765: len = nfsm_rndup(len)-len; ! 766: if (len > 0) { ! 767: if (rem < len) { ! 768: if (error = nfs_adv(mdp, dposp, len, rem)) ! 769: return (error); ! 770: } else ! 771: *dposp += len; ! 772: } ! 773: } else ! 774: i = len; ! 775: ndp->ni_namelen = i; ! 776: ndp->ni_dent.d_namlen = i; ! 777: ndp->ni_dent.d_name[i] = '\0'; ! 778: ndp->ni_segflg = UIO_SYSSPACE; ! 779: ndp->ni_pathlen = 1; ! 780: ndp->ni_pnbuf = ndp->ni_dirp = ndp->ni_ptr = &ndp->ni_dent.d_name[0]; ! 781: ndp->ni_next = &ndp->ni_dent.d_name[i]; ! 782: ndp->ni_nameiop |= (NOCROSSMOUNT | REMOTE | HASBUF); ! 783: ! 784: if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cred)) ! 785: return (error); ! 786: if (dp->v_type != VDIR) { ! 787: vrele(dp); ! 788: return (ENOTDIR); ! 789: } ! 790: /* ! 791: * Must set current directory here to avoid confusion in namei() ! 792: * called from rename() ! 793: */ ! 794: ndp->ni_cdir = dp; ! 795: ndp->ni_rdir = NULLVP; ! 796: ! 797: /* ! 798: * And call namei() to do the real work ! 799: */ ! 800: error = namei(ndp); ! 801: vrele(dp); ! 802: return (error); ! 803: } ! 804: ! 805: /* ! 806: * A fiddled version of m_adj() that ensures null fill to a long ! 807: * boundary and only trims off the back end ! 808: */ ! 809: nfsm_adj(mp, len, nul) ! 810: struct mbuf *mp; ! 811: register int len; ! 812: int nul; ! 813: { ! 814: register struct mbuf *m; ! 815: register int count, i; ! 816: register char *cp; ! 817: ! 818: /* ! 819: * Trim from tail. Scan the mbuf chain, ! 820: * calculating its length and finding the last mbuf. ! 821: * If the adjustment only affects this mbuf, then just ! 822: * adjust and return. Otherwise, rescan and truncate ! 823: * after the remaining size. ! 824: */ ! 825: count = 0; ! 826: m = mp; ! 827: for (;;) { ! 828: count += m->m_len; ! 829: if (m->m_next == (struct mbuf *)0) ! 830: break; ! 831: m = m->m_next; ! 832: } ! 833: if (m->m_len > len) { ! 834: m->m_len -= len; ! 835: if (nul > 0) { ! 836: cp = mtod(m, caddr_t)+m->m_len-nul; ! 837: for (i = 0; i < nul; i++) ! 838: *cp++ = '\0'; ! 839: } ! 840: return; ! 841: } ! 842: count -= len; ! 843: if (count < 0) ! 844: count = 0; ! 845: /* ! 846: * Correct length for chain is "count". ! 847: * Find the mbuf with last data, adjust its length, ! 848: * and toss data from remaining mbufs on chain. ! 849: */ ! 850: for (m = mp; m; m = m->m_next) { ! 851: if (m->m_len >= count) { ! 852: m->m_len = count; ! 853: if (nul > 0) { ! 854: cp = mtod(m, caddr_t)+m->m_len-nul; ! 855: for (i = 0; i < nul; i++) ! 856: *cp++ = '\0'; ! 857: } ! 858: break; ! 859: } ! 860: count -= m->m_len; ! 861: } ! 862: while (m = m->m_next) ! 863: m->m_len = 0; ! 864: } ! 865: ! 866: /* ! 867: * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked) ! 868: * - look up fsid in mount list (if not found ret error) ! 869: * - check that it is exported ! 870: * - get vp by calling VFS_FHTOVP() macro ! 871: * - if not lockflag unlock it with VOP_UNLOCK() ! 872: * - if cred->cr_uid == 0 set it to m_exroot ! 873: */ ! 874: nfsrv_fhtovp(fhp, lockflag, vpp, cred) ! 875: fhandle_t *fhp; ! 876: int lockflag; ! 877: struct vnode **vpp; ! 878: struct ucred *cred; ! 879: { ! 880: register struct mount *mp; ! 881: ! 882: if ((mp = getvfs(&fhp->fh_fsid)) == NULL) ! 883: return (ESTALE); ! 884: if ((mp->mnt_flag & MNT_EXPORTED) == 0) ! 885: return (EACCES); ! 886: if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp)) ! 887: return (ESTALE); ! 888: if (cred->cr_uid == 0) ! 889: cred->cr_uid = mp->mnt_exroot; ! 890: if (!lockflag) ! 891: VOP_UNLOCK(*vpp); ! 892: return (0); ! 893: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.