Annotation of kernel/bsd/nfs/nfs_subs.c, revision 1.1

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

unix.superglobalmegacorp.com

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