[BACK]Return to nfs_subs.c CVS log [TXT][DIR] Up to [local] / sys / nfs

Annotation of sys/nfs/nfs_subs.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: nfs_subs.c,v 1.61 2007/04/19 14:46:44 thib Exp $      */
                      2: /*     $NetBSD: nfs_subs.c,v 1.27.4.3 1996/07/08 20:34:24 jtc Exp $    */
                      3:
                      4: /*
                      5:  * Copyright (c) 1989, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to Berkeley by
                      9:  * Rick Macklem at The University of Guelph.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  *
                     35:  *     @(#)nfs_subs.c  8.8 (Berkeley) 5/22/95
                     36:  */
                     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 <sys/param.h>
                     45: #include <sys/proc.h>
                     46: #include <sys/systm.h>
                     47: #include <sys/kernel.h>
                     48: #include <sys/mount.h>
                     49: #include <sys/vnode.h>
                     50: #include <sys/namei.h>
                     51: #include <sys/mbuf.h>
                     52: #include <sys/socket.h>
                     53: #include <sys/socketvar.h>
                     54: #include <sys/stat.h>
                     55: #include <sys/malloc.h>
                     56: #include <sys/pool.h>
                     57: #include <sys/time.h>
                     58:
                     59: #include <uvm/uvm_extern.h>
                     60:
                     61: #include <nfs/rpcv2.h>
                     62: #include <nfs/nfsproto.h>
                     63: #include <nfs/nfsnode.h>
                     64: #include <nfs/nfs.h>
                     65: #include <nfs/xdr_subs.h>
                     66: #include <nfs/nfsm_subs.h>
                     67: #include <nfs/nfsmount.h>
                     68: #include <nfs/nfsrtt.h>
                     69: #include <nfs/nfs_var.h>
                     70:
                     71: #include <miscfs/specfs/specdev.h>
                     72:
                     73: #include <netinet/in.h>
                     74:
                     75: #include <dev/rndvar.h>
                     76:
                     77: #ifdef __GNUC__
                     78: #define INLINE __inline
                     79: #else
                     80: #define INLINE
                     81: #endif
                     82:
                     83: int    nfs_attrtimeo(struct nfsnode *np);
                     84:
                     85: /*
                     86:  * Data items converted to xdr at startup, since they are constant
                     87:  * This is kinda hokey, but may save a little time doing byte swaps
                     88:  */
                     89: u_int32_t nfs_xdrneg1;
                     90: u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
                     91:        rpc_mismatch, rpc_auth_unix, rpc_msgaccepted,
                     92:        rpc_auth_kerb;
                     93: u_int32_t nfs_prog, nfs_true, nfs_false;
                     94:
                     95: /* And other global data */
                     96: static u_int32_t nfs_xid = 0;
                     97: static u_int32_t nfs_xid_touched = 0;
                     98: nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
                     99:                      NFCHR, NFNON };
                    100: nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
                    101:                      NFFIFO, NFNON };
                    102: enum vtype nv2tov_type[8] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON };
                    103: enum vtype nv3tov_type[8]={ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO };
                    104: int nfs_ticks;
                    105: struct nfsstats nfsstats;
                    106:
                    107: /*
                    108:  * Mapping of old NFS Version 2 RPC numbers to generic numbers.
                    109:  */
                    110: int nfsv3_procid[NFS_NPROCS] = {
                    111:        NFSPROC_NULL,
                    112:        NFSPROC_GETATTR,
                    113:        NFSPROC_SETATTR,
                    114:        NFSPROC_NOOP,
                    115:        NFSPROC_LOOKUP,
                    116:        NFSPROC_READLINK,
                    117:        NFSPROC_READ,
                    118:        NFSPROC_NOOP,
                    119:        NFSPROC_WRITE,
                    120:        NFSPROC_CREATE,
                    121:        NFSPROC_REMOVE,
                    122:        NFSPROC_RENAME,
                    123:        NFSPROC_LINK,
                    124:        NFSPROC_SYMLINK,
                    125:        NFSPROC_MKDIR,
                    126:        NFSPROC_RMDIR,
                    127:        NFSPROC_READDIR,
                    128:        NFSPROC_FSSTAT,
                    129:        NFSPROC_NOOP,
                    130:        NFSPROC_NOOP,
                    131:        NFSPROC_NOOP,
                    132:        NFSPROC_NOOP,
                    133:        NFSPROC_NOOP,
                    134:        NFSPROC_NOOP,
                    135:        NFSPROC_NOOP,
                    136:        NFSPROC_NOOP
                    137: };
                    138:
                    139: /*
                    140:  * and the reverse mapping from generic to Version 2 procedure numbers
                    141:  */
                    142: int nfsv2_procid[NFS_NPROCS] = {
                    143:        NFSV2PROC_NULL,
                    144:        NFSV2PROC_GETATTR,
                    145:        NFSV2PROC_SETATTR,
                    146:        NFSV2PROC_LOOKUP,
                    147:        NFSV2PROC_NOOP,
                    148:        NFSV2PROC_READLINK,
                    149:        NFSV2PROC_READ,
                    150:        NFSV2PROC_WRITE,
                    151:        NFSV2PROC_CREATE,
                    152:        NFSV2PROC_MKDIR,
                    153:        NFSV2PROC_SYMLINK,
                    154:        NFSV2PROC_CREATE,
                    155:        NFSV2PROC_REMOVE,
                    156:        NFSV2PROC_RMDIR,
                    157:        NFSV2PROC_RENAME,
                    158:        NFSV2PROC_LINK,
                    159:        NFSV2PROC_READDIR,
                    160:        NFSV2PROC_NOOP,
                    161:        NFSV2PROC_STATFS,
                    162:        NFSV2PROC_NOOP,
                    163:        NFSV2PROC_NOOP,
                    164:        NFSV2PROC_NOOP,
                    165:        NFSV2PROC_NOOP,
                    166:        NFSV2PROC_NOOP,
                    167:        NFSV2PROC_NOOP,
                    168:        NFSV2PROC_NOOP,
                    169: };
                    170:
                    171: /*
                    172:  * Maps errno values to nfs error numbers.
                    173:  * Use NFSERR_IO as the catch all for ones not specifically defined in
                    174:  * RFC 1094.
                    175:  */
                    176: static u_char nfsrv_v2errmap[ELAST] = {
                    177:   NFSERR_PERM, NFSERR_NOENT,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    178:   NFSERR_NXIO, NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    179:   NFSERR_IO,   NFSERR_IO,      NFSERR_ACCES,   NFSERR_IO,      NFSERR_IO,
                    180:   NFSERR_IO,   NFSERR_EXIST,   NFSERR_IO,      NFSERR_NODEV,   NFSERR_NOTDIR,
                    181:   NFSERR_ISDIR,        NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    182:   NFSERR_IO,   NFSERR_FBIG,    NFSERR_NOSPC,   NFSERR_IO,      NFSERR_ROFS,
                    183:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    184:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    185:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    186:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    187:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    188:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    189:   NFSERR_IO,   NFSERR_IO,      NFSERR_NAMETOL, NFSERR_IO,      NFSERR_IO,
                    190:   NFSERR_NOTEMPTY, NFSERR_IO,  NFSERR_IO,      NFSERR_DQUOT,   NFSERR_STALE,
                    191:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    192:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    193:   NFSERR_IO,
                    194: };
                    195:
                    196: /*
                    197:  * Maps errno values to nfs error numbers.
                    198:  * Although it is not obvious whether or not NFS clients really care if
                    199:  * a returned error value is in the specified list for the procedure, the
                    200:  * safest thing to do is filter them appropriately. For Version 2, the
                    201:  * X/Open XNFS document is the only specification that defines error values
                    202:  * for each RPC (The RFC simply lists all possible error values for all RPCs),
                    203:  * so I have decided to not do this for Version 2.
                    204:  * The first entry is the default error return and the rest are the valid
                    205:  * errors for that RPC in increasing numeric order.
                    206:  */
                    207: static short nfsv3err_null[] = {
                    208:        0,
                    209:        0,
                    210: };
                    211:
                    212: static short nfsv3err_getattr[] = {
                    213:        NFSERR_IO,
                    214:        NFSERR_IO,
                    215:        NFSERR_STALE,
                    216:        NFSERR_BADHANDLE,
                    217:        NFSERR_SERVERFAULT,
                    218:        0,
                    219: };
                    220:
                    221: static short nfsv3err_setattr[] = {
                    222:        NFSERR_IO,
                    223:        NFSERR_PERM,
                    224:        NFSERR_IO,
                    225:        NFSERR_ACCES,
                    226:        NFSERR_INVAL,
                    227:        NFSERR_NOSPC,
                    228:        NFSERR_ROFS,
                    229:        NFSERR_DQUOT,
                    230:        NFSERR_STALE,
                    231:        NFSERR_BADHANDLE,
                    232:        NFSERR_NOT_SYNC,
                    233:        NFSERR_SERVERFAULT,
                    234:        0,
                    235: };
                    236:
                    237: static short nfsv3err_lookup[] = {
                    238:        NFSERR_IO,
                    239:        NFSERR_NOENT,
                    240:        NFSERR_IO,
                    241:        NFSERR_ACCES,
                    242:        NFSERR_NOTDIR,
                    243:        NFSERR_NAMETOL,
                    244:        NFSERR_STALE,
                    245:        NFSERR_BADHANDLE,
                    246:        NFSERR_SERVERFAULT,
                    247:        0,
                    248: };
                    249:
                    250: static short nfsv3err_access[] = {
                    251:        NFSERR_IO,
                    252:        NFSERR_IO,
                    253:        NFSERR_STALE,
                    254:        NFSERR_BADHANDLE,
                    255:        NFSERR_SERVERFAULT,
                    256:        0,
                    257: };
                    258:
                    259: static short nfsv3err_readlink[] = {
                    260:        NFSERR_IO,
                    261:        NFSERR_IO,
                    262:        NFSERR_ACCES,
                    263:        NFSERR_INVAL,
                    264:        NFSERR_STALE,
                    265:        NFSERR_BADHANDLE,
                    266:        NFSERR_NOTSUPP,
                    267:        NFSERR_SERVERFAULT,
                    268:        0,
                    269: };
                    270:
                    271: static short nfsv3err_read[] = {
                    272:        NFSERR_IO,
                    273:        NFSERR_IO,
                    274:        NFSERR_NXIO,
                    275:        NFSERR_ACCES,
                    276:        NFSERR_INVAL,
                    277:        NFSERR_STALE,
                    278:        NFSERR_BADHANDLE,
                    279:        NFSERR_SERVERFAULT,
                    280:        0,
                    281: };
                    282:
                    283: static short nfsv3err_write[] = {
                    284:        NFSERR_IO,
                    285:        NFSERR_IO,
                    286:        NFSERR_ACCES,
                    287:        NFSERR_INVAL,
                    288:        NFSERR_FBIG,
                    289:        NFSERR_NOSPC,
                    290:        NFSERR_ROFS,
                    291:        NFSERR_DQUOT,
                    292:        NFSERR_STALE,
                    293:        NFSERR_BADHANDLE,
                    294:        NFSERR_SERVERFAULT,
                    295:        0,
                    296: };
                    297:
                    298: static short nfsv3err_create[] = {
                    299:        NFSERR_IO,
                    300:        NFSERR_IO,
                    301:        NFSERR_ACCES,
                    302:        NFSERR_EXIST,
                    303:        NFSERR_NOTDIR,
                    304:        NFSERR_NOSPC,
                    305:        NFSERR_ROFS,
                    306:        NFSERR_NAMETOL,
                    307:        NFSERR_DQUOT,
                    308:        NFSERR_STALE,
                    309:        NFSERR_BADHANDLE,
                    310:        NFSERR_NOTSUPP,
                    311:        NFSERR_SERVERFAULT,
                    312:        0,
                    313: };
                    314:
                    315: static short nfsv3err_mkdir[] = {
                    316:        NFSERR_IO,
                    317:        NFSERR_IO,
                    318:        NFSERR_ACCES,
                    319:        NFSERR_EXIST,
                    320:        NFSERR_NOTDIR,
                    321:        NFSERR_NOSPC,
                    322:        NFSERR_ROFS,
                    323:        NFSERR_NAMETOL,
                    324:        NFSERR_DQUOT,
                    325:        NFSERR_STALE,
                    326:        NFSERR_BADHANDLE,
                    327:        NFSERR_NOTSUPP,
                    328:        NFSERR_SERVERFAULT,
                    329:        0,
                    330: };
                    331:
                    332: static short nfsv3err_symlink[] = {
                    333:        NFSERR_IO,
                    334:        NFSERR_IO,
                    335:        NFSERR_ACCES,
                    336:        NFSERR_EXIST,
                    337:        NFSERR_NOTDIR,
                    338:        NFSERR_NOSPC,
                    339:        NFSERR_ROFS,
                    340:        NFSERR_NAMETOL,
                    341:        NFSERR_DQUOT,
                    342:        NFSERR_STALE,
                    343:        NFSERR_BADHANDLE,
                    344:        NFSERR_NOTSUPP,
                    345:        NFSERR_SERVERFAULT,
                    346:        0,
                    347: };
                    348:
                    349: static short nfsv3err_mknod[] = {
                    350:        NFSERR_IO,
                    351:        NFSERR_IO,
                    352:        NFSERR_ACCES,
                    353:        NFSERR_EXIST,
                    354:        NFSERR_NOTDIR,
                    355:        NFSERR_NOSPC,
                    356:        NFSERR_ROFS,
                    357:        NFSERR_NAMETOL,
                    358:        NFSERR_DQUOT,
                    359:        NFSERR_STALE,
                    360:        NFSERR_BADHANDLE,
                    361:        NFSERR_NOTSUPP,
                    362:        NFSERR_SERVERFAULT,
                    363:        NFSERR_BADTYPE,
                    364:        0,
                    365: };
                    366:
                    367: static short nfsv3err_remove[] = {
                    368:        NFSERR_IO,
                    369:        NFSERR_NOENT,
                    370:        NFSERR_IO,
                    371:        NFSERR_ACCES,
                    372:        NFSERR_NOTDIR,
                    373:        NFSERR_ROFS,
                    374:        NFSERR_NAMETOL,
                    375:        NFSERR_STALE,
                    376:        NFSERR_BADHANDLE,
                    377:        NFSERR_SERVERFAULT,
                    378:        0,
                    379: };
                    380:
                    381: static short nfsv3err_rmdir[] = {
                    382:        NFSERR_IO,
                    383:        NFSERR_NOENT,
                    384:        NFSERR_IO,
                    385:        NFSERR_ACCES,
                    386:        NFSERR_EXIST,
                    387:        NFSERR_NOTDIR,
                    388:        NFSERR_INVAL,
                    389:        NFSERR_ROFS,
                    390:        NFSERR_NAMETOL,
                    391:        NFSERR_NOTEMPTY,
                    392:        NFSERR_STALE,
                    393:        NFSERR_BADHANDLE,
                    394:        NFSERR_NOTSUPP,
                    395:        NFSERR_SERVERFAULT,
                    396:        0,
                    397: };
                    398:
                    399: static short nfsv3err_rename[] = {
                    400:        NFSERR_IO,
                    401:        NFSERR_NOENT,
                    402:        NFSERR_IO,
                    403:        NFSERR_ACCES,
                    404:        NFSERR_EXIST,
                    405:        NFSERR_XDEV,
                    406:        NFSERR_NOTDIR,
                    407:        NFSERR_ISDIR,
                    408:        NFSERR_INVAL,
                    409:        NFSERR_NOSPC,
                    410:        NFSERR_ROFS,
                    411:        NFSERR_MLINK,
                    412:        NFSERR_NAMETOL,
                    413:        NFSERR_NOTEMPTY,
                    414:        NFSERR_DQUOT,
                    415:        NFSERR_STALE,
                    416:        NFSERR_BADHANDLE,
                    417:        NFSERR_NOTSUPP,
                    418:        NFSERR_SERVERFAULT,
                    419:        0,
                    420: };
                    421:
                    422: static short nfsv3err_link[] = {
                    423:        NFSERR_IO,
                    424:        NFSERR_IO,
                    425:        NFSERR_ACCES,
                    426:        NFSERR_EXIST,
                    427:        NFSERR_XDEV,
                    428:        NFSERR_NOTDIR,
                    429:        NFSERR_INVAL,
                    430:        NFSERR_NOSPC,
                    431:        NFSERR_ROFS,
                    432:        NFSERR_MLINK,
                    433:        NFSERR_NAMETOL,
                    434:        NFSERR_DQUOT,
                    435:        NFSERR_STALE,
                    436:        NFSERR_BADHANDLE,
                    437:        NFSERR_NOTSUPP,
                    438:        NFSERR_SERVERFAULT,
                    439:        0,
                    440: };
                    441:
                    442: static short nfsv3err_readdir[] = {
                    443:        NFSERR_IO,
                    444:        NFSERR_IO,
                    445:        NFSERR_ACCES,
                    446:        NFSERR_NOTDIR,
                    447:        NFSERR_STALE,
                    448:        NFSERR_BADHANDLE,
                    449:        NFSERR_BAD_COOKIE,
                    450:        NFSERR_TOOSMALL,
                    451:        NFSERR_SERVERFAULT,
                    452:        0,
                    453: };
                    454:
                    455: static short nfsv3err_readdirplus[] = {
                    456:        NFSERR_IO,
                    457:        NFSERR_IO,
                    458:        NFSERR_ACCES,
                    459:        NFSERR_NOTDIR,
                    460:        NFSERR_STALE,
                    461:        NFSERR_BADHANDLE,
                    462:        NFSERR_BAD_COOKIE,
                    463:        NFSERR_NOTSUPP,
                    464:        NFSERR_TOOSMALL,
                    465:        NFSERR_SERVERFAULT,
                    466:        0,
                    467: };
                    468:
                    469: static short nfsv3err_fsstat[] = {
                    470:        NFSERR_IO,
                    471:        NFSERR_IO,
                    472:        NFSERR_STALE,
                    473:        NFSERR_BADHANDLE,
                    474:        NFSERR_SERVERFAULT,
                    475:        0,
                    476: };
                    477:
                    478: static short nfsv3err_fsinfo[] = {
                    479:        NFSERR_STALE,
                    480:        NFSERR_STALE,
                    481:        NFSERR_BADHANDLE,
                    482:        NFSERR_SERVERFAULT,
                    483:        0,
                    484: };
                    485:
                    486: static short nfsv3err_pathconf[] = {
                    487:        NFSERR_STALE,
                    488:        NFSERR_STALE,
                    489:        NFSERR_BADHANDLE,
                    490:        NFSERR_SERVERFAULT,
                    491:        0,
                    492: };
                    493:
                    494: static short nfsv3err_commit[] = {
                    495:        NFSERR_IO,
                    496:        NFSERR_IO,
                    497:        NFSERR_STALE,
                    498:        NFSERR_BADHANDLE,
                    499:        NFSERR_SERVERFAULT,
                    500:        0,
                    501: };
                    502:
                    503: static short *nfsrv_v3errmap[] = {
                    504:        nfsv3err_null,
                    505:        nfsv3err_getattr,
                    506:        nfsv3err_setattr,
                    507:        nfsv3err_lookup,
                    508:        nfsv3err_access,
                    509:        nfsv3err_readlink,
                    510:        nfsv3err_read,
                    511:        nfsv3err_write,
                    512:        nfsv3err_create,
                    513:        nfsv3err_mkdir,
                    514:        nfsv3err_symlink,
                    515:        nfsv3err_mknod,
                    516:        nfsv3err_remove,
                    517:        nfsv3err_rmdir,
                    518:        nfsv3err_rename,
                    519:        nfsv3err_link,
                    520:        nfsv3err_readdir,
                    521:        nfsv3err_readdirplus,
                    522:        nfsv3err_fsstat,
                    523:        nfsv3err_fsinfo,
                    524:        nfsv3err_pathconf,
                    525:        nfsv3err_commit,
                    526: };
                    527:
                    528: extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
                    529: extern struct nfsrtt nfsrtt;
                    530:
                    531: struct pool nfsreqpl;
                    532:
                    533: /*
                    534:  * Create the header for an rpc request packet
                    535:  * The hsiz is the size of the rest of the nfs request header.
                    536:  * (just used to decide if a cluster is a good idea)
                    537:  */
                    538: struct mbuf *
                    539: nfsm_reqh(vp, procid, hsiz, bposp)
                    540:        struct vnode *vp;
                    541:        u_long procid;
                    542:        int hsiz;
                    543:        caddr_t *bposp;
                    544: {
                    545:        struct mbuf *mb;
                    546:        caddr_t bpos;
                    547:
                    548:        MGET(mb, M_WAIT, MT_DATA);
                    549:        if (hsiz >= MINCLSIZE)
                    550:                MCLGET(mb, M_WAIT);
                    551:        mb->m_len = 0;
                    552:        bpos = mtod(mb, caddr_t);
                    553:
                    554:        /* Finally, return values */
                    555:        *bposp = bpos;
                    556:        return (mb);
                    557: }
                    558:
                    559: /*
                    560:  * Build the RPC header and fill in the authorization info.
                    561:  * The authorization string argument is only used when the credentials
                    562:  * come from outside of the kernel.
                    563:  * Returns the head of the mbuf list.
                    564:  */
                    565: struct mbuf *
                    566: nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
                    567:        verf_str, mrest, mrest_len, mbp, xidp)
                    568:        struct ucred *cr;
                    569:        int nmflag;
                    570:        int procid;
                    571:        int auth_type;
                    572:        int auth_len;
                    573:        char *auth_str;
                    574:        int verf_len;
                    575:        char *verf_str;
                    576:        struct mbuf *mrest;
                    577:        int mrest_len;
                    578:        struct mbuf **mbp;
                    579:        u_int32_t *xidp;
                    580: {
                    581:        struct mbuf *mb;
                    582:        u_int32_t *tl;
                    583:        caddr_t bpos;
                    584:        int i;
                    585:        struct mbuf *mreq, *mb2;
                    586:        int siz, grpsiz, authsiz;
                    587:
                    588:        authsiz = nfsm_rndup(auth_len);
                    589:        MGETHDR(mb, M_WAIT, MT_DATA);
                    590:        if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) {
                    591:                MCLGET(mb, M_WAIT);
                    592:        } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) {
                    593:                MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
                    594:        } else {
                    595:                MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
                    596:        }
                    597:        mb->m_len = 0;
                    598:        mreq = mb;
                    599:        bpos = mtod(mb, caddr_t);
                    600:
                    601:        /*
                    602:         * First the RPC header.
                    603:         */
                    604:        nfsm_build(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
                    605:
                    606:        /* Get a new (non-zero) xid */
                    607:
                    608:        if ((nfs_xid == 0) && (nfs_xid_touched == 0)) {
                    609:                nfs_xid = arc4random();
                    610:                nfs_xid_touched = 1;
                    611:        } else {
                    612:                while ((*xidp = arc4random() % 256) == 0)
                    613:                        ;
                    614:                nfs_xid += *xidp;
                    615:        }
                    616:
                    617:        *tl++ = *xidp = txdr_unsigned(nfs_xid);
                    618:        *tl++ = rpc_call;
                    619:        *tl++ = rpc_vers;
                    620:        *tl++ = txdr_unsigned(NFS_PROG);
                    621:        if (nmflag & NFSMNT_NFSV3)
                    622:                *tl++ = txdr_unsigned(NFS_VER3);
                    623:        else
                    624:                *tl++ = txdr_unsigned(NFS_VER2);
                    625:        if (nmflag & NFSMNT_NFSV3)
                    626:                *tl++ = txdr_unsigned(procid);
                    627:        else
                    628:                *tl++ = txdr_unsigned(nfsv2_procid[procid]);
                    629:
                    630:        /*
                    631:         * And then the authorization cred.
                    632:         */
                    633:        *tl++ = txdr_unsigned(auth_type);
                    634:        *tl = txdr_unsigned(authsiz);
                    635:        switch (auth_type) {
                    636:        case RPCAUTH_UNIX:
                    637:                nfsm_build(tl, u_int32_t *, auth_len);
                    638:                *tl++ = 0;              /* stamp ?? */
                    639:                *tl++ = 0;              /* NULL hostname */
                    640:                *tl++ = txdr_unsigned(cr->cr_uid);
                    641:                *tl++ = txdr_unsigned(cr->cr_gid);
                    642:                grpsiz = (auth_len >> 2) - 5;
                    643:                *tl++ = txdr_unsigned(grpsiz);
                    644:                for (i = 0; i < grpsiz; i++)
                    645:                        *tl++ = txdr_unsigned(cr->cr_groups[i]);
                    646:                break;
                    647:        case RPCAUTH_KERB4:
                    648:                siz = auth_len;
                    649:                while (siz > 0) {
                    650:                        if (M_TRAILINGSPACE(mb) == 0) {
                    651:                                MGET(mb2, M_WAIT, MT_DATA);
                    652:                                if (siz >= MINCLSIZE)
                    653:                                        MCLGET(mb2, M_WAIT);
                    654:                                mb->m_next = mb2;
                    655:                                mb = mb2;
                    656:                                mb->m_len = 0;
                    657:                                bpos = mtod(mb, caddr_t);
                    658:                        }
                    659:                        i = min(siz, M_TRAILINGSPACE(mb));
                    660:                        bcopy(auth_str, bpos, i);
                    661:                        mb->m_len += i;
                    662:                        auth_str += i;
                    663:                        bpos += i;
                    664:                        siz -= i;
                    665:                }
                    666:                if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) {
                    667:                        for (i = 0; i < siz; i++)
                    668:                                *bpos++ = '\0';
                    669:                        mb->m_len += siz;
                    670:                }
                    671:                break;
                    672:        };
                    673:
                    674:        /*
                    675:         * And the verifier...
                    676:         */
                    677:        nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
                    678:        if (verf_str) {
                    679:                *tl++ = txdr_unsigned(RPCAUTH_KERB4);
                    680:                *tl = txdr_unsigned(verf_len);
                    681:                siz = verf_len;
                    682:                while (siz > 0) {
                    683:                        if (M_TRAILINGSPACE(mb) == 0) {
                    684:                                MGET(mb2, M_WAIT, MT_DATA);
                    685:                                if (siz >= MINCLSIZE)
                    686:                                        MCLGET(mb2, M_WAIT);
                    687:                                mb->m_next = mb2;
                    688:                                mb = mb2;
                    689:                                mb->m_len = 0;
                    690:                                bpos = mtod(mb, caddr_t);
                    691:                        }
                    692:                        i = min(siz, M_TRAILINGSPACE(mb));
                    693:                        bcopy(verf_str, bpos, i);
                    694:                        mb->m_len += i;
                    695:                        verf_str += i;
                    696:                        bpos += i;
                    697:                        siz -= i;
                    698:                }
                    699:                if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) {
                    700:                        for (i = 0; i < siz; i++)
                    701:                                *bpos++ = '\0';
                    702:                        mb->m_len += siz;
                    703:                }
                    704:        } else {
                    705:                *tl++ = txdr_unsigned(RPCAUTH_NULL);
                    706:                *tl = 0;
                    707:        }
                    708:        mb->m_next = mrest;
                    709:        mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
                    710:        mreq->m_pkthdr.rcvif = (struct ifnet *)0;
                    711:        *mbp = mb;
                    712:        return (mreq);
                    713: }
                    714:
                    715: /*
                    716:  * copies mbuf chain to the uio scatter/gather list
                    717:  */
                    718: int
                    719: nfsm_mbuftouio(mrep, uiop, siz, dpos)
                    720:        struct mbuf **mrep;
                    721:        struct uio *uiop;
                    722:        int siz;
                    723:        caddr_t *dpos;
                    724: {
                    725:        char *mbufcp, *uiocp;
                    726:        int xfer, left, len;
                    727:        struct mbuf *mp;
                    728:        long uiosiz, rem;
                    729:        int error = 0;
                    730:
                    731:        mp = *mrep;
                    732:        mbufcp = *dpos;
                    733:        len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
                    734:        rem = nfsm_rndup(siz)-siz;
                    735:        while (siz > 0) {
                    736:                if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
                    737:                        return (EFBIG);
                    738:                left = uiop->uio_iov->iov_len;
                    739:                uiocp = uiop->uio_iov->iov_base;
                    740:                if (left > siz)
                    741:                        left = siz;
                    742:                uiosiz = left;
                    743:                while (left > 0) {
                    744:                        while (len == 0) {
                    745:                                mp = mp->m_next;
                    746:                                if (mp == NULL)
                    747:                                        return (EBADRPC);
                    748:                                mbufcp = mtod(mp, caddr_t);
                    749:                                len = mp->m_len;
                    750:                        }
                    751:                        xfer = (left > len) ? len : left;
                    752: #ifdef notdef
                    753:                        /* Not Yet.. */
                    754:                        if (uiop->uio_iov->iov_op != NULL)
                    755:                                (*(uiop->uio_iov->iov_op))
                    756:                                (mbufcp, uiocp, xfer);
                    757:                        else
                    758: #endif
                    759:                        if (uiop->uio_segflg == UIO_SYSSPACE)
                    760:                                bcopy(mbufcp, uiocp, xfer);
                    761:                        else
                    762:                                copyout(mbufcp, uiocp, xfer);
                    763:                        left -= xfer;
                    764:                        len -= xfer;
                    765:                        mbufcp += xfer;
                    766:                        uiocp += xfer;
                    767:                        uiop->uio_offset += xfer;
                    768:                        uiop->uio_resid -= xfer;
                    769:                }
                    770:                if (uiop->uio_iov->iov_len <= siz) {
                    771:                        uiop->uio_iovcnt--;
                    772:                        uiop->uio_iov++;
                    773:                } else {
                    774:                        (char *)uiop->uio_iov->iov_base += uiosiz;
                    775:                        uiop->uio_iov->iov_len -= uiosiz;
                    776:                }
                    777:                siz -= uiosiz;
                    778:        }
                    779:        *dpos = mbufcp;
                    780:        *mrep = mp;
                    781:        if (rem > 0) {
                    782:                if (len < rem)
                    783:                        error = nfs_adv(mrep, dpos, rem, len);
                    784:                else
                    785:                        *dpos += rem;
                    786:        }
                    787:        return (error);
                    788: }
                    789:
                    790: /*
                    791:  * copies a uio scatter/gather list to an mbuf chain.
                    792:  * NOTE: can ony handle iovcnt == 1
                    793:  */
                    794: int
                    795: nfsm_uiotombuf(uiop, mq, siz, bpos)
                    796:        struct uio *uiop;
                    797:        struct mbuf **mq;
                    798:        int siz;
                    799:        caddr_t *bpos;
                    800: {
                    801:        char *uiocp;
                    802:        struct mbuf *mp, *mp2;
                    803:        int xfer, left, mlen;
                    804:        int uiosiz, clflg, rem;
                    805:        char *cp;
                    806:
                    807: #ifdef DIAGNOSTIC
                    808:        if (uiop->uio_iovcnt != 1)
                    809:                panic("nfsm_uiotombuf: iovcnt != 1");
                    810: #endif
                    811:
                    812:        if (siz > MLEN)         /* or should it >= MCLBYTES ?? */
                    813:                clflg = 1;
                    814:        else
                    815:                clflg = 0;
                    816:        rem = nfsm_rndup(siz)-siz;
                    817:        mp = mp2 = *mq;
                    818:        while (siz > 0) {
                    819:                left = uiop->uio_iov->iov_len;
                    820:                uiocp = uiop->uio_iov->iov_base;
                    821:                if (left > siz)
                    822:                        left = siz;
                    823:                uiosiz = left;
                    824:                while (left > 0) {
                    825:                        mlen = M_TRAILINGSPACE(mp);
                    826:                        if (mlen == 0) {
                    827:                                MGET(mp, M_WAIT, MT_DATA);
                    828:                                if (clflg)
                    829:                                        MCLGET(mp, M_WAIT);
                    830:                                mp->m_len = 0;
                    831:                                mp2->m_next = mp;
                    832:                                mp2 = mp;
                    833:                                mlen = M_TRAILINGSPACE(mp);
                    834:                        }
                    835:                        xfer = (left > mlen) ? mlen : left;
                    836: #ifdef notdef
                    837:                        /* Not Yet.. */
                    838:                        if (uiop->uio_iov->iov_op != NULL)
                    839:                                (*(uiop->uio_iov->iov_op))
                    840:                                (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
                    841:                        else
                    842: #endif
                    843:                        if (uiop->uio_segflg == UIO_SYSSPACE)
                    844:                                bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
                    845:                        else
                    846:                                copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
                    847:                        mp->m_len += xfer;
                    848:                        left -= xfer;
                    849:                        uiocp += xfer;
                    850:                        uiop->uio_offset += xfer;
                    851:                        uiop->uio_resid -= xfer;
                    852:                }
                    853:                (char *)uiop->uio_iov->iov_base += uiosiz;
                    854:                uiop->uio_iov->iov_len -= uiosiz;
                    855:                siz -= uiosiz;
                    856:        }
                    857:        if (rem > 0) {
                    858:                if (rem > M_TRAILINGSPACE(mp)) {
                    859:                        MGET(mp, M_WAIT, MT_DATA);
                    860:                        mp->m_len = 0;
                    861:                        mp2->m_next = mp;
                    862:                }
                    863:                cp = mtod(mp, caddr_t)+mp->m_len;
                    864:                for (left = 0; left < rem; left++)
                    865:                        *cp++ = '\0';
                    866:                mp->m_len += rem;
                    867:                *bpos = cp;
                    868:        } else
                    869:                *bpos = mtod(mp, caddr_t)+mp->m_len;
                    870:        *mq = mp;
                    871:        return (0);
                    872: }
                    873:
                    874: /*
                    875:  * Help break down an mbuf chain by setting the first siz bytes contiguous
                    876:  * pointed to by returned val.
                    877:  * This is used by the macros nfsm_dissect and nfsm_dissecton for tough
                    878:  * cases. (The macros use the vars. dpos and dpos2)
                    879:  */
                    880: int
                    881: nfsm_disct(mdp, dposp, siz, left, cp2)
                    882:        struct mbuf **mdp;
                    883:        caddr_t *dposp;
                    884:        int siz;
                    885:        int left;
                    886:        caddr_t *cp2;
                    887: {
                    888:        struct mbuf *mp, *mp2;
                    889:        int siz2, xfer;
                    890:        caddr_t p;
                    891:
                    892:        mp = *mdp;
                    893:        while (left == 0) {
                    894:                *mdp = mp = mp->m_next;
                    895:                if (mp == NULL)
                    896:                        return (EBADRPC);
                    897:                left = mp->m_len;
                    898:                *dposp = mtod(mp, caddr_t);
                    899:        }
                    900:        if (left >= siz) {
                    901:                *cp2 = *dposp;
                    902:                *dposp += siz;
                    903:        } else if (mp->m_next == NULL) {
                    904:                return (EBADRPC);
                    905:        } else if (siz > MHLEN) {
                    906:                panic("nfs S too big");
                    907:        } else {
                    908:                MGET(mp2, M_WAIT, MT_DATA);
                    909:                mp2->m_next = mp->m_next;
                    910:                mp->m_next = mp2;
                    911:                mp->m_len -= left;
                    912:                mp = mp2;
                    913:                *cp2 = p = mtod(mp, caddr_t);
                    914:                bcopy(*dposp, p, left);         /* Copy what was left */
                    915:                siz2 = siz-left;
                    916:                p += left;
                    917:                mp2 = mp->m_next;
                    918:                /* Loop around copying up the siz2 bytes */
                    919:                while (siz2 > 0) {
                    920:                        if (mp2 == NULL)
                    921:                                return (EBADRPC);
                    922:                        xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
                    923:                        if (xfer > 0) {
                    924:                                bcopy(mtod(mp2, caddr_t), p, xfer);
                    925:                                NFSMADV(mp2, xfer);
                    926:                                mp2->m_len -= xfer;
                    927:                                p += xfer;
                    928:                                siz2 -= xfer;
                    929:                        }
                    930:                        if (siz2 > 0)
                    931:                                mp2 = mp2->m_next;
                    932:                }
                    933:                mp->m_len = siz;
                    934:                *mdp = mp2;
                    935:                *dposp = mtod(mp2, caddr_t);
                    936:        }
                    937:        return (0);
                    938: }
                    939:
                    940: /*
                    941:  * Advance the position in the mbuf chain.
                    942:  */
                    943: int
                    944: nfs_adv(mdp, dposp, offs, left)
                    945:        struct mbuf **mdp;
                    946:        caddr_t *dposp;
                    947:        int offs;
                    948:        int left;
                    949: {
                    950:        struct mbuf *m;
                    951:        int s;
                    952:
                    953:        m = *mdp;
                    954:        s = left;
                    955:        while (s < offs) {
                    956:                offs -= s;
                    957:                m = m->m_next;
                    958:                if (m == NULL)
                    959:                        return (EBADRPC);
                    960:                s = m->m_len;
                    961:        }
                    962:        *mdp = m;
                    963:        *dposp = mtod(m, caddr_t)+offs;
                    964:        return (0);
                    965: }
                    966:
                    967: /*
                    968:  * Copy a string into mbufs for the hard cases...
                    969:  */
                    970: int
                    971: nfsm_strtmbuf(mb, bpos, cp, siz)
                    972:        struct mbuf **mb;
                    973:        char **bpos;
                    974:        char *cp;
                    975:        long siz;
                    976: {
                    977:        struct mbuf *m1 = NULL, *m2;
                    978:        long left, xfer, len, tlen;
                    979:        u_int32_t *tl;
                    980:        int putsize;
                    981:
                    982:        putsize = 1;
                    983:        m2 = *mb;
                    984:        left = M_TRAILINGSPACE(m2);
                    985:        if (left > 0) {
                    986:                tl = ((u_int32_t *)(*bpos));
                    987:                *tl++ = txdr_unsigned(siz);
                    988:                putsize = 0;
                    989:                left -= NFSX_UNSIGNED;
                    990:                m2->m_len += NFSX_UNSIGNED;
                    991:                if (left > 0) {
                    992:                        bcopy(cp, (caddr_t) tl, left);
                    993:                        siz -= left;
                    994:                        cp += left;
                    995:                        m2->m_len += left;
                    996:                        left = 0;
                    997:                }
                    998:        }
                    999:        /* Loop around adding mbufs */
                   1000:        while (siz > 0) {
                   1001:                MGET(m1, M_WAIT, MT_DATA);
                   1002:                if (siz > MLEN)
                   1003:                        MCLGET(m1, M_WAIT);
                   1004:                m1->m_len = NFSMSIZ(m1);
                   1005:                m2->m_next = m1;
                   1006:                m2 = m1;
                   1007:                tl = mtod(m1, u_int32_t *);
                   1008:                tlen = 0;
                   1009:                if (putsize) {
                   1010:                        *tl++ = txdr_unsigned(siz);
                   1011:                        m1->m_len -= NFSX_UNSIGNED;
                   1012:                        tlen = NFSX_UNSIGNED;
                   1013:                        putsize = 0;
                   1014:                }
                   1015:                if (siz < m1->m_len) {
                   1016:                        len = nfsm_rndup(siz);
                   1017:                        xfer = siz;
                   1018:                        if (xfer < len)
                   1019:                                *(tl+(xfer>>2)) = 0;
                   1020:                } else {
                   1021:                        xfer = len = m1->m_len;
                   1022:                }
                   1023:                bcopy(cp, (caddr_t) tl, xfer);
                   1024:                m1->m_len = len+tlen;
                   1025:                siz -= xfer;
                   1026:                cp += xfer;
                   1027:        }
                   1028:        *mb = m1;
                   1029:        *bpos = mtod(m1, caddr_t)+m1->m_len;
                   1030:        return (0);
                   1031: }
                   1032:
                   1033: /*
                   1034:  * Called once to initialize data structures...
                   1035:  */
                   1036: void
                   1037: nfs_init()
                   1038: {
                   1039:        static struct timeout nfs_timer_to;
                   1040:
                   1041:        nfsrtt.pos = 0;
                   1042:        rpc_vers = txdr_unsigned(RPC_VER2);
                   1043:        rpc_call = txdr_unsigned(RPC_CALL);
                   1044:        rpc_reply = txdr_unsigned(RPC_REPLY);
                   1045:        rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
                   1046:        rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
                   1047:        rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
                   1048:        rpc_autherr = txdr_unsigned(RPC_AUTHERR);
                   1049:        rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
                   1050:        rpc_auth_kerb = txdr_unsigned(RPCAUTH_KERB4);
                   1051:        nfs_prog = txdr_unsigned(NFS_PROG);
                   1052:        nfs_true = txdr_unsigned(TRUE);
                   1053:        nfs_false = txdr_unsigned(FALSE);
                   1054:        nfs_xdrneg1 = txdr_unsigned(-1);
                   1055:        nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
                   1056:        if (nfs_ticks < 1)
                   1057:                nfs_ticks = 1;
                   1058: #ifdef NFSSERVER
                   1059:        nfsrv_init(0);                  /* Init server data structures */
                   1060:        nfsrv_initcache();              /* Init the server request cache */
                   1061: #endif /* NFSSERVER */
                   1062:
                   1063:        pool_init(&nfsreqpl, sizeof(struct nfsreq), 0, 0, 0, "nfsreqpl",
                   1064:            &pool_allocator_nointr);
                   1065:
                   1066:        /*
                   1067:         * Initialize reply list and start timer
                   1068:         */
                   1069:        TAILQ_INIT(&nfs_reqq);
                   1070:
                   1071:        timeout_set(&nfs_timer_to, nfs_timer, &nfs_timer_to);
                   1072:        nfs_timer(&nfs_timer_to);
                   1073: }
                   1074:
                   1075: #ifdef NFSCLIENT
                   1076: int
                   1077: nfs_vfs_init(vfsp)
                   1078:        struct vfsconf *vfsp;
                   1079: {
                   1080:        int i;
                   1081:
                   1082:        /* Ensure async daemons disabled */
                   1083:        for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
                   1084:                nfs_iodwant[i] = (struct proc *)0;
                   1085:        TAILQ_INIT(&nfs_bufq);
                   1086:        nfs_nhinit();                   /* Init the nfsnode table */
                   1087:
                   1088:        return (0);
                   1089: }
                   1090:
                   1091: /*
                   1092:  * Attribute cache routines.
                   1093:  * nfs_loadattrcache() - loads or updates the cache contents from attributes
                   1094:  *     that are on the mbuf list
                   1095:  * nfs_getattrcache() - returns valid attributes if found in cache, returns
                   1096:  *     error otherwise
                   1097:  */
                   1098:
                   1099: /*
                   1100:  * Load the attribute cache (that lives in the nfsnode entry) with
                   1101:  * the values on the mbuf list and
                   1102:  * Iff vap not NULL
                   1103:  *    copy the attributes to *vaper
                   1104:  */
                   1105: int
                   1106: nfs_loadattrcache(vpp, mdp, dposp, vaper)
                   1107:        struct vnode **vpp;
                   1108:        struct mbuf **mdp;
                   1109:        caddr_t *dposp;
                   1110:        struct vattr *vaper;
                   1111: {
                   1112:        struct vnode *vp = *vpp;
                   1113:        struct vattr *vap;
                   1114:        struct nfs_fattr *fp;
                   1115:        extern int (**spec_nfsv2nodeop_p)(void *);
                   1116:        struct nfsnode *np;
                   1117:        int32_t t1;
                   1118:        caddr_t cp2;
                   1119:        int error = 0;
                   1120:        int32_t rdev;
                   1121:        struct mbuf *md;
                   1122:        enum vtype vtyp;
                   1123:        mode_t vmode;
                   1124:        struct timespec mtime;
                   1125:        struct vnode *nvp;
                   1126:        int v3 = NFS_ISV3(vp);
                   1127:
                   1128:        md = *mdp;
                   1129:        t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
                   1130:        error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2);
                   1131:        if (error)
                   1132:                return (error);
                   1133:        fp = (struct nfs_fattr *)cp2;
                   1134:        if (v3) {
                   1135:                vtyp = nfsv3tov_type(fp->fa_type);
                   1136:                vmode = fxdr_unsigned(mode_t, fp->fa_mode);
                   1137:                rdev = makedev(fxdr_unsigned(u_int32_t, fp->fa3_rdev.specdata1),
                   1138:                        fxdr_unsigned(u_int32_t, fp->fa3_rdev.specdata2));
                   1139:                fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
                   1140:        } else {
                   1141:                vtyp = nfsv2tov_type(fp->fa_type);
                   1142:                vmode = fxdr_unsigned(mode_t, fp->fa_mode);
                   1143:                if (vtyp == VNON || vtyp == VREG)
                   1144:                        vtyp = IFTOVT(vmode);
                   1145:                rdev = fxdr_unsigned(int32_t, fp->fa2_rdev);
                   1146:                fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
                   1147:
                   1148:                /*
                   1149:                 * Really ugly NFSv2 kludge.
                   1150:                 */
                   1151:                if (vtyp == VCHR && rdev == 0xffffffff)
                   1152:                        vtyp = VFIFO;
                   1153:        }
                   1154:
                   1155:        /*
                   1156:         * If v_type == VNON it is a new node, so fill in the v_type,
                   1157:         * n_mtime fields. Check to see if it represents a special
                   1158:         * device, and if so, check for a possible alias. Once the
                   1159:         * correct vnode has been obtained, fill in the rest of the
                   1160:         * information.
                   1161:         */
                   1162:        np = VTONFS(vp);
                   1163:        if (vp->v_type != vtyp) {
                   1164:                vp->v_type = vtyp;
                   1165:                if (vp->v_type == VFIFO) {
                   1166: #ifndef FIFO
                   1167:                        return (EOPNOTSUPP);
                   1168: #else
                   1169:                        extern int (**fifo_nfsv2nodeop_p)(void *);
                   1170:                        vp->v_op = fifo_nfsv2nodeop_p;
                   1171: #endif /* FIFO */
                   1172:                }
                   1173:                if (vp->v_type == VCHR || vp->v_type == VBLK) {
                   1174:                        vp->v_op = spec_nfsv2nodeop_p;
                   1175:                        nvp = checkalias(vp, (dev_t)rdev, vp->v_mount);
                   1176:                        if (nvp) {
                   1177:                                /*
                   1178:                                 * Discard unneeded vnode, but save its nfsnode.
                   1179:                                 * Since the nfsnode does not have a lock, its
                   1180:                                 * vnode lock has to be carried over.
                   1181:                                 */
                   1182:
                   1183:                                nvp->v_data = vp->v_data;
                   1184:                                vp->v_data = NULL;
                   1185:                                vp->v_op = spec_vnodeop_p;
                   1186:                                vrele(vp);
                   1187:                                vgone(vp);
                   1188:                                /*
                   1189:                                 * Reinitialize aliased node.
                   1190:                                 */
                   1191:                                np->n_vnode = nvp;
                   1192:                                *vpp = vp = nvp;
                   1193:                        }
                   1194:                }
                   1195:                np->n_mtime = mtime.tv_sec;
                   1196:        }
                   1197:        vap = &np->n_vattr;
                   1198:        vap->va_type = vtyp;
                   1199:        vap->va_mode = (vmode & 07777);
                   1200:        vap->va_rdev = (dev_t)rdev;
                   1201:        vap->va_mtime = mtime;
                   1202:        vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
                   1203:        if (v3) {
                   1204:                vap->va_nlink = fxdr_unsigned(nlink_t, fp->fa_nlink);
                   1205:                vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
                   1206:                vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
                   1207:                vap->va_size = fxdr_hyper(&fp->fa3_size);
                   1208:                vap->va_blocksize = NFS_FABLKSIZE;
                   1209:                vap->va_bytes = fxdr_hyper(&fp->fa3_used);
                   1210:                vap->va_fileid = fxdr_unsigned(int32_t,
                   1211:                    fp->fa3_fileid.nfsuquad[1]);
                   1212:                fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
                   1213:                fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
                   1214:                vap->va_flags = 0;
                   1215:                vap->va_filerev = 0;
                   1216:        } else {
                   1217:                vap->va_nlink = fxdr_unsigned(nlink_t, fp->fa_nlink);
                   1218:                vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
                   1219:                vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
                   1220:                vap->va_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
                   1221:                vap->va_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
                   1222:                vap->va_bytes =
                   1223:                    (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) *
                   1224:                    NFS_FABLKSIZE;
                   1225:                vap->va_fileid = fxdr_unsigned(int32_t, fp->fa2_fileid);
                   1226:                fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
                   1227:                vap->va_flags = 0;
                   1228:                vap->va_ctime.tv_sec = fxdr_unsigned(u_int32_t,
                   1229:                    fp->fa2_ctime.nfsv2_sec);
                   1230:                vap->va_ctime.tv_nsec = 0;
                   1231:                vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
                   1232:                vap->va_filerev = 0;
                   1233:        }
                   1234:        if (vap->va_size != np->n_size) {
                   1235:                if (vap->va_type == VREG) {
                   1236:                        if (np->n_flag & NMODIFIED) {
                   1237:                                if (vap->va_size < np->n_size)
                   1238:                                        vap->va_size = np->n_size;
                   1239:                                else
                   1240:                                        np->n_size = vap->va_size;
                   1241:                        } else
                   1242:                                np->n_size = vap->va_size;
                   1243:                        uvm_vnp_setsize(vp, np->n_size);
                   1244:                } else
                   1245:                        np->n_size = vap->va_size;
                   1246:        }
                   1247:        np->n_attrstamp = time_second;
                   1248:        if (vaper != NULL) {
                   1249:                bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
                   1250:                if (np->n_flag & NCHG) {
                   1251:                        if (np->n_flag & NACC)
                   1252:                                vaper->va_atime = np->n_atim;
                   1253:                        if (np->n_flag & NUPD)
                   1254:                                vaper->va_mtime = np->n_mtim;
                   1255:                }
                   1256:        }
                   1257:        return (0);
                   1258: }
                   1259:
                   1260: INLINE int
                   1261: nfs_attrtimeo (np)
                   1262:        struct nfsnode *np;
                   1263: {
                   1264:        struct vnode *vp = np->n_vnode;
                   1265:        struct nfsmount *nmp = VFSTONFS(vp->v_mount);
                   1266:        int tenthage = (time_second - np->n_mtime) / 10;
                   1267:        int minto, maxto;
                   1268:
                   1269:        if (vp->v_type == VDIR) {
                   1270:                maxto = nmp->nm_acdirmax;
                   1271:                minto = nmp->nm_acdirmin;
                   1272:        }
                   1273:        else {
                   1274:                maxto = nmp->nm_acregmax;
                   1275:                minto = nmp->nm_acregmin;
                   1276:        }
                   1277:
                   1278:        if (np->n_flag & NMODIFIED || tenthage < minto)
                   1279:                return minto;
                   1280:        else if (tenthage < maxto)
                   1281:                return tenthage;
                   1282:        else
                   1283:                return maxto;
                   1284: }
                   1285:
                   1286: /*
                   1287:  * Check the time stamp
                   1288:  * If the cache is valid, copy contents to *vap and return 0
                   1289:  * otherwise return an error
                   1290:  */
                   1291: int
                   1292: nfs_getattrcache(vp, vaper)
                   1293:        struct vnode *vp;
                   1294:        struct vattr *vaper;
                   1295: {
                   1296:        struct nfsnode *np = VTONFS(vp);
                   1297:        struct vattr *vap;
                   1298:
                   1299:        if (np->n_attrstamp == 0 ||
                   1300:            (time_second - np->n_attrstamp) >= nfs_attrtimeo(np)) {
                   1301:                nfsstats.attrcache_misses++;
                   1302:                return (ENOENT);
                   1303:        }
                   1304:        nfsstats.attrcache_hits++;
                   1305:        vap = &np->n_vattr;
                   1306:        if (vap->va_size != np->n_size) {
                   1307:                if (vap->va_type == VREG) {
                   1308:                        if (np->n_flag & NMODIFIED) {
                   1309:                                if (vap->va_size < np->n_size)
                   1310:                                        vap->va_size = np->n_size;
                   1311:                                else
                   1312:                                        np->n_size = vap->va_size;
                   1313:                        } else
                   1314:                                np->n_size = vap->va_size;
                   1315:                        uvm_vnp_setsize(vp, np->n_size);
                   1316:                } else
                   1317:                        np->n_size = vap->va_size;
                   1318:        }
                   1319:        bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));
                   1320:        if (np->n_flag & NCHG) {
                   1321:                if (np->n_flag & NACC)
                   1322:                        vaper->va_atime = np->n_atim;
                   1323:                if (np->n_flag & NUPD)
                   1324:                        vaper->va_mtime = np->n_mtim;
                   1325:        }
                   1326:        return (0);
                   1327: }
                   1328: #endif /* NFSCLIENT */
                   1329:
                   1330: /*
                   1331:  * Set up nameidata for a lookup() call and do it
                   1332:  */
                   1333: int
                   1334: nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
                   1335:        struct nameidata *ndp;
                   1336:        fhandle_t *fhp;
                   1337:        int len;
                   1338:        struct nfssvc_sock *slp;
                   1339:        struct mbuf *nam;
                   1340:        struct mbuf **mdp;
                   1341:        caddr_t *dposp;
                   1342:        struct vnode **retdirp;
                   1343:        struct proc *p;
                   1344:        int kerbflag;
                   1345: {
                   1346:        int i, rem;
                   1347:        struct mbuf *md;
                   1348:        char *fromcp, *tocp;
                   1349:        struct vnode *dp;
                   1350:        int error, rdonly;
                   1351:        struct componentname *cnp = &ndp->ni_cnd;
                   1352:
                   1353:        *retdirp = (struct vnode *)0;
                   1354:        cnp->cn_pnbuf = pool_get(&namei_pool, PR_WAITOK);
                   1355:        /*
                   1356:         * Copy the name from the mbuf list to ndp->ni_pnbuf
                   1357:         * and set the various ndp fields appropriately.
                   1358:         */
                   1359:        fromcp = *dposp;
                   1360:        tocp = cnp->cn_pnbuf;
                   1361:        md = *mdp;
                   1362:        rem = mtod(md, caddr_t) + md->m_len - fromcp;
                   1363:        cnp->cn_hash = 0;
                   1364:        for (i = 0; i < len; i++) {
                   1365:                while (rem == 0) {
                   1366:                        md = md->m_next;
                   1367:                        if (md == NULL) {
                   1368:                                error = EBADRPC;
                   1369:                                goto out;
                   1370:                        }
                   1371:                        fromcp = mtod(md, caddr_t);
                   1372:                        rem = md->m_len;
                   1373:                }
                   1374:                if (*fromcp == '\0' || *fromcp == '/') {
                   1375:                        error = EACCES;
                   1376:                        goto out;
                   1377:                }
                   1378:                cnp->cn_hash += (u_char)*fromcp;
                   1379:                *tocp++ = *fromcp++;
                   1380:                rem--;
                   1381:        }
                   1382:        *tocp = '\0';
                   1383:        *mdp = md;
                   1384:        *dposp = fromcp;
                   1385:        len = nfsm_rndup(len)-len;
                   1386:        if (len > 0) {
                   1387:                if (rem >= len)
                   1388:                        *dposp += len;
                   1389:                else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0)
                   1390:                        goto out;
                   1391:        }
                   1392:        ndp->ni_pathlen = tocp - cnp->cn_pnbuf;
                   1393:        cnp->cn_nameptr = cnp->cn_pnbuf;
                   1394:        /*
                   1395:         * Extract and set starting directory.
                   1396:         */
                   1397:        error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
                   1398:            nam, &rdonly, kerbflag);
                   1399:        if (error)
                   1400:                goto out;
                   1401:        if (dp->v_type != VDIR) {
                   1402:                vrele(dp);
                   1403:                error = ENOTDIR;
                   1404:                goto out;
                   1405:        }
                   1406:        VREF(dp);
                   1407:        *retdirp = dp;
                   1408:        ndp->ni_startdir = dp;
                   1409:        if (rdonly)
                   1410:                cnp->cn_flags |= (NOCROSSMOUNT | RDONLY);
                   1411:        else
                   1412:                cnp->cn_flags |= NOCROSSMOUNT;
                   1413:        /*
                   1414:         * And call lookup() to do the real work
                   1415:         */
                   1416:        cnp->cn_proc = p;
                   1417:        error = lookup(ndp);
                   1418:        if (error)
                   1419:                goto out;
                   1420:        /*
                   1421:         * Check for encountering a symbolic link
                   1422:         */
                   1423:        if (cnp->cn_flags & ISSYMLINK) {
                   1424:                if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
                   1425:                        vput(ndp->ni_dvp);
                   1426:                else
                   1427:                        vrele(ndp->ni_dvp);
                   1428:                vput(ndp->ni_vp);
                   1429:                ndp->ni_vp = NULL;
                   1430:                error = EINVAL;
                   1431:                goto out;
                   1432:        }
                   1433:        /*
                   1434:         * Check for saved name request
                   1435:         */
                   1436:        if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
                   1437:                cnp->cn_flags |= HASBUF;
                   1438:                return (0);
                   1439:        }
                   1440: out:
                   1441:        pool_put(&namei_pool, cnp->cn_pnbuf);
                   1442:        return (error);
                   1443: }
                   1444:
                   1445: /*
                   1446:  * A fiddled version of m_adj() that ensures null fill to a long
                   1447:  * boundary and only trims off the back end
                   1448:  */
                   1449: void
                   1450: nfsm_adj(mp, len, nul)
                   1451:        struct mbuf *mp;
                   1452:        int len;
                   1453:        int nul;
                   1454: {
                   1455:        struct mbuf *m;
                   1456:        int count, i;
                   1457:        char *cp;
                   1458:
                   1459:        /*
                   1460:         * Trim from tail.  Scan the mbuf chain,
                   1461:         * calculating its length and finding the last mbuf.
                   1462:         * If the adjustment only affects this mbuf, then just
                   1463:         * adjust and return.  Otherwise, rescan and truncate
                   1464:         * after the remaining size.
                   1465:         */
                   1466:        count = 0;
                   1467:        m = mp;
                   1468:        for (;;) {
                   1469:                count += m->m_len;
                   1470:                if (m->m_next == (struct mbuf *)0)
                   1471:                        break;
                   1472:                m = m->m_next;
                   1473:        }
                   1474:        if (m->m_len > len) {
                   1475:                m->m_len -= len;
                   1476:                if (nul > 0) {
                   1477:                        cp = mtod(m, caddr_t)+m->m_len-nul;
                   1478:                        for (i = 0; i < nul; i++)
                   1479:                                *cp++ = '\0';
                   1480:                }
                   1481:                return;
                   1482:        }
                   1483:        count -= len;
                   1484:        if (count < 0)
                   1485:                count = 0;
                   1486:        /*
                   1487:         * Correct length for chain is "count".
                   1488:         * Find the mbuf with last data, adjust its length,
                   1489:         * and toss data from remaining mbufs on chain.
                   1490:         */
                   1491:        for (m = mp; m; m = m->m_next) {
                   1492:                if (m->m_len >= count) {
                   1493:                        m->m_len = count;
                   1494:                        if (nul > 0) {
                   1495:                                cp = mtod(m, caddr_t)+m->m_len-nul;
                   1496:                                for (i = 0; i < nul; i++)
                   1497:                                        *cp++ = '\0';
                   1498:                        }
                   1499:                        break;
                   1500:                }
                   1501:                count -= m->m_len;
                   1502:        }
                   1503:        for (m = m->m_next;m;m = m->m_next)
                   1504:                m->m_len = 0;
                   1505: }
                   1506:
                   1507: /*
                   1508:  * Make these functions instead of macros, so that the kernel text size
                   1509:  * doesn't get too big...
                   1510:  */
                   1511: void
                   1512: nfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp)
                   1513:        struct nfsrv_descript *nfsd;
                   1514:        int before_ret;
                   1515:        struct vattr *before_vap;
                   1516:        int after_ret;
                   1517:        struct vattr *after_vap;
                   1518:        struct mbuf **mbp;
                   1519:        char **bposp;
                   1520: {
                   1521:        struct mbuf *mb = *mbp, *mb2;
                   1522:        char *bpos = *bposp;
                   1523:        u_int32_t *tl;
                   1524:
                   1525:        if (before_ret) {
                   1526:                nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
                   1527:                *tl = nfs_false;
                   1528:        } else {
                   1529:                nfsm_build(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
                   1530:                *tl++ = nfs_true;
                   1531:                txdr_hyper(before_vap->va_size, tl);
                   1532:                tl += 2;
                   1533:                txdr_nfsv3time(&(before_vap->va_mtime), tl);
                   1534:                tl += 2;
                   1535:                txdr_nfsv3time(&(before_vap->va_ctime), tl);
                   1536:        }
                   1537:        *bposp = bpos;
                   1538:        *mbp = mb;
                   1539:        nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
                   1540: }
                   1541:
                   1542: void
                   1543: nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp)
                   1544:        struct nfsrv_descript *nfsd;
                   1545:        int after_ret;
                   1546:        struct vattr *after_vap;
                   1547:        struct mbuf **mbp;
                   1548:        char **bposp;
                   1549: {
                   1550:        struct mbuf *mb = *mbp, *mb2;
                   1551:        char *bpos = *bposp;
                   1552:        u_int32_t *tl;
                   1553:        struct nfs_fattr *fp;
                   1554:
                   1555:        if (after_ret) {
                   1556:                nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
                   1557:                *tl = nfs_false;
                   1558:        } else {
                   1559:                nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR);
                   1560:                *tl++ = nfs_true;
                   1561:                fp = (struct nfs_fattr *)tl;
                   1562:                nfsm_srvfattr(nfsd, after_vap, fp);
                   1563:        }
                   1564:        *mbp = mb;
                   1565:        *bposp = bpos;
                   1566: }
                   1567:
                   1568: void
                   1569: nfsm_srvfattr(nfsd, vap, fp)
                   1570:        struct nfsrv_descript *nfsd;
                   1571:        struct vattr *vap;
                   1572:        struct nfs_fattr *fp;
                   1573: {
                   1574:
                   1575:        fp->fa_nlink = txdr_unsigned(vap->va_nlink);
                   1576:        fp->fa_uid = txdr_unsigned(vap->va_uid);
                   1577:        fp->fa_gid = txdr_unsigned(vap->va_gid);
                   1578:        if (nfsd->nd_flag & ND_NFSV3) {
                   1579:                fp->fa_type = vtonfsv3_type(vap->va_type);
                   1580:                fp->fa_mode = vtonfsv3_mode(vap->va_mode);
                   1581:                txdr_hyper(vap->va_size, &fp->fa3_size);
                   1582:                txdr_hyper(vap->va_bytes, &fp->fa3_used);
                   1583:                fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev));
                   1584:                fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev));
                   1585:                fp->fa3_fsid.nfsuquad[0] = 0;
                   1586:                fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
                   1587:                fp->fa3_fileid.nfsuquad[0] = 0;
                   1588:                fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
                   1589:                txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
                   1590:                txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
                   1591:                txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
                   1592:        } else {
                   1593:                fp->fa_type = vtonfsv2_type(vap->va_type);
                   1594:                fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
                   1595:                fp->fa2_size = txdr_unsigned(vap->va_size);
                   1596:                fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
                   1597:                if (vap->va_type == VFIFO)
                   1598:                        fp->fa2_rdev = 0xffffffff;
                   1599:                else
                   1600:                        fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
                   1601:                fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
                   1602:                fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
                   1603:                fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
                   1604:                txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
                   1605:                txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
                   1606:                txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
                   1607:        }
                   1608: }
                   1609:
                   1610: /*
                   1611:  * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
                   1612:  *     - look up fsid in mount list (if not found ret error)
                   1613:  *     - get vp and export rights by calling VFS_FHTOVP() and VFS_CHECKEXP()
                   1614:  *     - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
                   1615:  *     - if not lockflag unlock it with VOP_UNLOCK()
                   1616:  */
                   1617: int
                   1618: nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
                   1619:        fhandle_t *fhp;
                   1620:        int lockflag;
                   1621:        struct vnode **vpp;
                   1622:        struct ucred *cred;
                   1623:        struct nfssvc_sock *slp;
                   1624:        struct mbuf *nam;
                   1625:        int *rdonlyp;
                   1626:        int kerbflag;
                   1627: {
                   1628:        struct proc *p = curproc;       /* XXX */
                   1629:        struct mount *mp;
                   1630:        int i;
                   1631:        struct ucred *credanon;
                   1632:        int error, exflags;
                   1633:        struct sockaddr_in *saddr;
                   1634:
                   1635:        *vpp = (struct vnode *)0;
                   1636:        mp = vfs_getvfs(&fhp->fh_fsid);
                   1637:
                   1638:        if (!mp)
                   1639:                return (ESTALE);
                   1640:        error = VFS_CHECKEXP(mp, nam, &exflags, &credanon);
                   1641:        if (error)
                   1642:                return (error);
                   1643:        error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
                   1644:        if (error)
                   1645:                return (error);
                   1646:
                   1647:        saddr = mtod(nam, struct sockaddr_in *);
                   1648:        if (saddr->sin_family == AF_INET &&
                   1649:            (ntohs(saddr->sin_port) >= IPPORT_RESERVED ||
                   1650:            (slp->ns_so->so_type == SOCK_STREAM && ntohs(saddr->sin_port) == 20))) {
                   1651:                vput(*vpp);
                   1652:                return (NFSERR_AUTHERR | AUTH_TOOWEAK);
                   1653:        }
                   1654:
                   1655:        /*
                   1656:         * Check/setup credentials.
                   1657:         */
                   1658:        if (exflags & MNT_EXKERB) {
                   1659:                if (!kerbflag) {
                   1660:                        vput(*vpp);
                   1661:                        return (NFSERR_AUTHERR | AUTH_TOOWEAK);
                   1662:                }
                   1663:        } else if (kerbflag) {
                   1664:                vput(*vpp);
                   1665:                return (NFSERR_AUTHERR | AUTH_TOOWEAK);
                   1666:        } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
                   1667:                cred->cr_uid = credanon->cr_uid;
                   1668:                cred->cr_gid = credanon->cr_gid;
                   1669:                for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
                   1670:                        cred->cr_groups[i] = credanon->cr_groups[i];
                   1671:                cred->cr_ngroups = i;
                   1672:        }
                   1673:        if (exflags & MNT_EXRDONLY)
                   1674:                *rdonlyp = 1;
                   1675:        else
                   1676:                *rdonlyp = 0;
                   1677:        if (!lockflag)
                   1678:                VOP_UNLOCK(*vpp, 0, p);
                   1679:
                   1680:        return (0);
                   1681: }
                   1682:
                   1683: /*
                   1684:  * This function compares two net addresses by family and returns TRUE
                   1685:  * if they are the same host.
                   1686:  * If there is any doubt, return FALSE.
                   1687:  * The AF_INET family is handled as a special case so that address mbufs
                   1688:  * don't need to be saved to store "struct in_addr", which is only 4 bytes.
                   1689:  */
                   1690: int
                   1691: netaddr_match(family, haddr, nam)
                   1692:        int family;
                   1693:        union nethostaddr *haddr;
                   1694:        struct mbuf *nam;
                   1695: {
                   1696:        struct sockaddr_in *inetaddr;
                   1697:
                   1698:        switch (family) {
                   1699:        case AF_INET:
                   1700:                inetaddr = mtod(nam, struct sockaddr_in *);
                   1701:                if (inetaddr->sin_family == AF_INET &&
                   1702:                    inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
                   1703:                        return (1);
                   1704:                break;
                   1705:        default:
                   1706:                break;
                   1707:        };
                   1708:        return (0);
                   1709: }
                   1710:
                   1711: /*
                   1712:  * The write verifier has changed (probably due to a server reboot), so all
                   1713:  * B_NEEDCOMMIT blocks will have to be written again. Since they are on the
                   1714:  * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT
                   1715:  * flag. Once done the new write verifier can be set for the mount point.
                   1716:  */
                   1717: void
                   1718: nfs_clearcommit(mp)
                   1719:        struct mount *mp;
                   1720: {
                   1721:        struct vnode *vp, *nvp;
                   1722:        struct buf *bp, *nbp;
                   1723:        int s;
                   1724:
                   1725:        s = splbio();
                   1726: loop:
                   1727:        for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp != NULL; vp = nvp) {
                   1728:                if (vp->v_mount != mp)  /* Paranoia */
                   1729:                        goto loop;
                   1730:                nvp = LIST_NEXT(vp, v_mntvnodes);
                   1731:                for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) {
                   1732:                        nbp = LIST_NEXT(bp, b_vnbufs);
                   1733:                        if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
                   1734:                                == (B_DELWRI | B_NEEDCOMMIT))
                   1735:                                bp->b_flags &= ~B_NEEDCOMMIT;
                   1736:                }
                   1737:        }
                   1738:        splx(s);
                   1739: }
                   1740:
                   1741: void
                   1742: nfs_merge_commit_ranges(vp)
                   1743:        struct vnode *vp;
                   1744: {
                   1745:        struct nfsnode *np = VTONFS(vp);
                   1746:
                   1747:        if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) {
                   1748:                np->n_pushedlo = np->n_pushlo;
                   1749:                np->n_pushedhi = np->n_pushhi;
                   1750:                np->n_commitflags |= NFS_COMMIT_PUSHED_VALID;
                   1751:        } else {
                   1752:                if (np->n_pushlo < np->n_pushedlo)
                   1753:                        np->n_pushedlo = np->n_pushlo;
                   1754:                if (np->n_pushhi > np->n_pushedhi)
                   1755:                        np->n_pushedhi = np->n_pushhi;
                   1756:        }
                   1757:
                   1758:        np->n_pushlo = np->n_pushhi = 0;
                   1759:        np->n_commitflags &= ~NFS_COMMIT_PUSH_VALID;
                   1760: }
                   1761:
                   1762: int
                   1763: nfs_in_committed_range(vp, bp)
                   1764:        struct vnode *vp;
                   1765:        struct buf *bp;
                   1766: {
                   1767:        struct nfsnode *np = VTONFS(vp);
                   1768:        off_t lo, hi;
                   1769:
                   1770:        if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID))
                   1771:                return 0;
                   1772:        lo = (off_t)bp->b_blkno * DEV_BSIZE;
                   1773:        hi = lo + bp->b_dirtyend;
                   1774:
                   1775:        return (lo >= np->n_pushedlo && hi <= np->n_pushedhi);
                   1776: }
                   1777:
                   1778: int
                   1779: nfs_in_tobecommitted_range(vp, bp)
                   1780:        struct vnode *vp;
                   1781:        struct buf *bp;
                   1782: {
                   1783:        struct nfsnode *np = VTONFS(vp);
                   1784:        off_t lo, hi;
                   1785:
                   1786:        if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID))
                   1787:                return 0;
                   1788:        lo = (off_t)bp->b_blkno * DEV_BSIZE;
                   1789:        hi = lo + bp->b_dirtyend;
                   1790:
                   1791:        return (lo >= np->n_pushlo && hi <= np->n_pushhi);
                   1792: }
                   1793:
                   1794: void
                   1795: nfs_add_committed_range(vp, bp)
                   1796:        struct vnode *vp;
                   1797:        struct buf *bp;
                   1798: {
                   1799:        struct nfsnode *np = VTONFS(vp);
                   1800:        off_t lo, hi;
                   1801:
                   1802:        lo = (off_t)bp->b_blkno * DEV_BSIZE;
                   1803:        hi = lo + bp->b_dirtyend;
                   1804:
                   1805:        if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) {
                   1806:                np->n_pushedlo = lo;
                   1807:                np->n_pushedhi = hi;
                   1808:                np->n_commitflags |= NFS_COMMIT_PUSHED_VALID;
                   1809:        } else {
                   1810:                if (hi > np->n_pushedhi)
                   1811:                        np->n_pushedhi = hi;
                   1812:                if (lo < np->n_pushedlo)
                   1813:                        np->n_pushedlo = lo;
                   1814:        }
                   1815: }
                   1816:
                   1817: void
                   1818: nfs_del_committed_range(vp, bp)
                   1819:        struct vnode *vp;
                   1820:        struct buf *bp;
                   1821: {
                   1822:        struct nfsnode *np = VTONFS(vp);
                   1823:        off_t lo, hi;
                   1824:
                   1825:        if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID))
                   1826:                return;
                   1827:
                   1828:        lo = (off_t)bp->b_blkno * DEV_BSIZE;
                   1829:        hi = lo + bp->b_dirtyend;
                   1830:
                   1831:        if (lo > np->n_pushedhi || hi < np->n_pushedlo)
                   1832:                return;
                   1833:        if (lo <= np->n_pushedlo)
                   1834:                np->n_pushedlo = hi;
                   1835:        else if (hi >= np->n_pushedhi)
                   1836:                np->n_pushedhi = lo;
                   1837:        else {
                   1838:                /*
                   1839:                 * XXX There's only one range. If the deleted range
                   1840:                 * is in the middle, pick the largest of the
                   1841:                 * contiguous ranges that it leaves.
                   1842:                 */
                   1843:                if ((np->n_pushedlo - lo) > (hi - np->n_pushedhi))
                   1844:                        np->n_pushedhi = lo;
                   1845:                else
                   1846:                        np->n_pushedlo = hi;
                   1847:        }
                   1848: }
                   1849:
                   1850: void
                   1851: nfs_add_tobecommitted_range(vp, bp)
                   1852:        struct vnode *vp;
                   1853:        struct buf *bp;
                   1854: {
                   1855:        struct nfsnode *np = VTONFS(vp);
                   1856:        off_t lo, hi;
                   1857:
                   1858:        lo = (off_t)bp->b_blkno * DEV_BSIZE;
                   1859:        hi = lo + bp->b_dirtyend;
                   1860:
                   1861:        if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID)) {
                   1862:                np->n_pushlo = lo;
                   1863:                np->n_pushhi = hi;
                   1864:                np->n_commitflags |= NFS_COMMIT_PUSH_VALID;
                   1865:        } else {
                   1866:                if (lo < np->n_pushlo)
                   1867:                        np->n_pushlo = lo;
                   1868:                if (hi > np->n_pushhi)
                   1869:                        np->n_pushhi = hi;
                   1870:        }
                   1871: }
                   1872:
                   1873: void
                   1874: nfs_del_tobecommitted_range(vp, bp)
                   1875:        struct vnode *vp;
                   1876:        struct buf *bp;
                   1877: {
                   1878:        struct nfsnode *np = VTONFS(vp);
                   1879:        off_t lo, hi;
                   1880:
                   1881:        if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID))
                   1882:                return;
                   1883:
                   1884:        lo = (off_t)bp->b_blkno * DEV_BSIZE;
                   1885:        hi = lo + bp->b_dirtyend;
                   1886:
                   1887:        if (lo > np->n_pushhi || hi < np->n_pushlo)
                   1888:                return;
                   1889:
                   1890:        if (lo <= np->n_pushlo)
                   1891:                np->n_pushlo = hi;
                   1892:        else if (hi >= np->n_pushhi)
                   1893:                np->n_pushhi = lo;
                   1894:        else {
                   1895:                /*
                   1896:                 * XXX There's only one range. If the deleted range
                   1897:                 * is in the middle, pick the largest of the
                   1898:                 * contiguous ranges that it leaves.
                   1899:                 */
                   1900:                if ((np->n_pushlo - lo) > (hi - np->n_pushhi))
                   1901:                        np->n_pushhi = lo;
                   1902:                else
                   1903:                        np->n_pushlo = hi;
                   1904:        }
                   1905: }
                   1906:
                   1907: /*
                   1908:  * Map errnos to NFS error numbers. For Version 3 also filter out error
                   1909:  * numbers not specified for the associated procedure.
                   1910:  */
                   1911: int
                   1912: nfsrv_errmap(nd, err)
                   1913:        struct nfsrv_descript *nd;
                   1914:        int err;
                   1915: {
                   1916:        short *defaulterrp, *errp;
                   1917:
                   1918:        if (nd->nd_flag & ND_NFSV3) {
                   1919:            if (nd->nd_procnum <= NFSPROC_COMMIT) {
                   1920:                errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
                   1921:                while (*++errp) {
                   1922:                        if (*errp == err)
                   1923:                                return (err);
                   1924:                        else if (*errp > err)
                   1925:                                break;
                   1926:                }
                   1927:                return ((int)*defaulterrp);
                   1928:            } else
                   1929:                return (err & 0xffff);
                   1930:        }
                   1931:        if (err <= ELAST)
                   1932:                return ((int)nfsrv_v2errmap[err - 1]);
                   1933:        return (NFSERR_IO);
                   1934: }
                   1935:
                   1936: /*
                   1937:  * Sort the group list in increasing numerical order.
                   1938:  * (Insertion sort by Chris Torek, who was grossed out by the bubble sort
                   1939:  *  that used to be here.)
                   1940:  */
                   1941: void
                   1942: nfsrvw_sort(list, num)
                   1943:         gid_t *list;
                   1944:         int num;
                   1945: {
                   1946:        int i, j;
                   1947:        gid_t v;
                   1948:
                   1949:        /* Insertion sort. */
                   1950:        for (i = 1; i < num; i++) {
                   1951:                v = list[i];
                   1952:                /* find correct slot for value v, moving others up */
                   1953:                for (j = i; --j >= 0 && v < list[j];)
                   1954:                        list[j + 1] = list[j];
                   1955:                list[j + 1] = v;
                   1956:        }
                   1957: }
                   1958:
                   1959: /*
                   1960:  * copy credentials making sure that the result can be compared with bcmp().
                   1961:  */
                   1962: void
                   1963: nfsrv_setcred(incred, outcred)
                   1964:        struct ucred *incred, *outcred;
                   1965: {
                   1966:        int i;
                   1967:
                   1968:        bzero((caddr_t)outcred, sizeof (struct ucred));
                   1969:        outcred->cr_ref = 1;
                   1970:        outcred->cr_uid = incred->cr_uid;
                   1971:        outcred->cr_gid = incred->cr_gid;
                   1972:        outcred->cr_ngroups = incred->cr_ngroups;
                   1973:        for (i = 0; i < incred->cr_ngroups; i++)
                   1974:                outcred->cr_groups[i] = incred->cr_groups[i];
                   1975:        nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups);
                   1976: }

CVSweb