Annotation of Net2/nfs/nfs_subs.c, revision 1.1.1.2

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.