[BACK]Return to nfs_subs.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / nfs

Annotation of src/sys/nfs/nfs_subs.c, Revision 1.39

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

CVSweb <webmaster@jp.NetBSD.org>