Home | History | Annotate | Line # | Download | only in common
nfs_commonsubs.c revision 1.1.1.1.4.2
      1  1.1.1.1.4.2  rmind /*	$NetBSD: nfs_commonsubs.c,v 1.1.1.1.4.2 2014/05/18 17:46:05 rmind Exp $	*/
      2  1.1.1.1.4.2  rmind /*-
      3  1.1.1.1.4.2  rmind  * Copyright (c) 1989, 1993
      4  1.1.1.1.4.2  rmind  *	The Regents of the University of California.  All rights reserved.
      5  1.1.1.1.4.2  rmind  *
      6  1.1.1.1.4.2  rmind  * This code is derived from software contributed to Berkeley by
      7  1.1.1.1.4.2  rmind  * Rick Macklem at The University of Guelph.
      8  1.1.1.1.4.2  rmind  *
      9  1.1.1.1.4.2  rmind  * Redistribution and use in source and binary forms, with or without
     10  1.1.1.1.4.2  rmind  * modification, are permitted provided that the following conditions
     11  1.1.1.1.4.2  rmind  * are met:
     12  1.1.1.1.4.2  rmind  * 1. Redistributions of source code must retain the above copyright
     13  1.1.1.1.4.2  rmind  *    notice, this list of conditions and the following disclaimer.
     14  1.1.1.1.4.2  rmind  * 2. Redistributions in binary form must reproduce the above copyright
     15  1.1.1.1.4.2  rmind  *    notice, this list of conditions and the following disclaimer in the
     16  1.1.1.1.4.2  rmind  *    documentation and/or other materials provided with the distribution.
     17  1.1.1.1.4.2  rmind  * 4. Neither the name of the University nor the names of its contributors
     18  1.1.1.1.4.2  rmind  *    may be used to endorse or promote products derived from this software
     19  1.1.1.1.4.2  rmind  *    without specific prior written permission.
     20  1.1.1.1.4.2  rmind  *
     21  1.1.1.1.4.2  rmind  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  1.1.1.1.4.2  rmind  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  1.1.1.1.4.2  rmind  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  1.1.1.1.4.2  rmind  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  1.1.1.1.4.2  rmind  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  1.1.1.1.4.2  rmind  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  1.1.1.1.4.2  rmind  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  1.1.1.1.4.2  rmind  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  1.1.1.1.4.2  rmind  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  1.1.1.1.4.2  rmind  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  1.1.1.1.4.2  rmind  * SUCH DAMAGE.
     32  1.1.1.1.4.2  rmind  *
     33  1.1.1.1.4.2  rmind  */
     34  1.1.1.1.4.2  rmind 
     35  1.1.1.1.4.2  rmind #include <sys/cdefs.h>
     36  1.1.1.1.4.2  rmind /* __FBSDID("FreeBSD: head/sys/fs/nfs/nfs_commonsubs.c 253506 2013-07-20 22:35:32Z rmacklem "); */
     37  1.1.1.1.4.2  rmind __RCSID("$NetBSD: nfs_commonsubs.c,v 1.1.1.1.4.2 2014/05/18 17:46:05 rmind Exp $");
     38  1.1.1.1.4.2  rmind 
     39  1.1.1.1.4.2  rmind /*
     40  1.1.1.1.4.2  rmind  * These functions support the macros and help fiddle mbuf chains for
     41  1.1.1.1.4.2  rmind  * the nfs op functions. They do things like create the rpc header and
     42  1.1.1.1.4.2  rmind  * copy data between mbuf chains and uio lists.
     43  1.1.1.1.4.2  rmind  */
     44  1.1.1.1.4.2  rmind #ifndef APPLEKEXT
     45  1.1.1.1.4.2  rmind #include "opt_inet6.h"
     46  1.1.1.1.4.2  rmind 
     47  1.1.1.1.4.2  rmind #include <fs/nfs/nfsport.h>
     48  1.1.1.1.4.2  rmind 
     49  1.1.1.1.4.2  rmind /*
     50  1.1.1.1.4.2  rmind  * Data items converted to xdr at startup, since they are constant
     51  1.1.1.1.4.2  rmind  * This is kinda hokey, but may save a little time doing byte swaps
     52  1.1.1.1.4.2  rmind  */
     53  1.1.1.1.4.2  rmind u_int32_t newnfs_true, newnfs_false, newnfs_xdrneg1;
     54  1.1.1.1.4.2  rmind 
     55  1.1.1.1.4.2  rmind /* And other global data */
     56  1.1.1.1.4.2  rmind nfstype nfsv34_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
     57  1.1.1.1.4.2  rmind 		      NFFIFO, NFNON };
     58  1.1.1.1.4.2  rmind enum vtype newnv2tov_type[8] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON };
     59  1.1.1.1.4.2  rmind enum vtype nv34tov_type[8]={ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO };
     60  1.1.1.1.4.2  rmind struct timeval nfsboottime;	/* Copy boottime once, so it never changes */
     61  1.1.1.1.4.2  rmind int nfscl_ticks;
     62  1.1.1.1.4.2  rmind int nfsrv_useacl = 1;
     63  1.1.1.1.4.2  rmind struct nfssockreq nfsrv_nfsuserdsock;
     64  1.1.1.1.4.2  rmind int nfsrv_nfsuserd = 0;
     65  1.1.1.1.4.2  rmind struct nfsreqhead nfsd_reqq;
     66  1.1.1.1.4.2  rmind uid_t nfsrv_defaultuid;
     67  1.1.1.1.4.2  rmind gid_t nfsrv_defaultgid;
     68  1.1.1.1.4.2  rmind int nfsrv_lease = NFSRV_LEASE;
     69  1.1.1.1.4.2  rmind int ncl_mbuf_mlen = MLEN;
     70  1.1.1.1.4.2  rmind NFSNAMEIDMUTEX;
     71  1.1.1.1.4.2  rmind NFSSOCKMUTEX;
     72  1.1.1.1.4.2  rmind 
     73  1.1.1.1.4.2  rmind /*
     74  1.1.1.1.4.2  rmind  * This array of structures indicates, for V4:
     75  1.1.1.1.4.2  rmind  * retfh - which of 3 types of calling args are used
     76  1.1.1.1.4.2  rmind  *	0 - doesn't change cfh or use a sfh
     77  1.1.1.1.4.2  rmind  *	1 - replaces cfh with a new one (unless it returns an error status)
     78  1.1.1.1.4.2  rmind  *	2 - uses cfh and sfh
     79  1.1.1.1.4.2  rmind  * needscfh - if the op wants a cfh and premtime
     80  1.1.1.1.4.2  rmind  *	0 - doesn't use a cfh
     81  1.1.1.1.4.2  rmind  *	1 - uses a cfh, but doesn't want pre-op attributes
     82  1.1.1.1.4.2  rmind  *	2 - uses a cfh and wants pre-op attributes
     83  1.1.1.1.4.2  rmind  * savereply - indicates a non-idempotent Op
     84  1.1.1.1.4.2  rmind  *	0 - not non-idempotent
     85  1.1.1.1.4.2  rmind  *	1 - non-idempotent
     86  1.1.1.1.4.2  rmind  * Ops that are ordered via seqid# are handled separately from these
     87  1.1.1.1.4.2  rmind  * non-idempotent Ops.
     88  1.1.1.1.4.2  rmind  * Define it here, since it is used by both the client and server.
     89  1.1.1.1.4.2  rmind  */
     90  1.1.1.1.4.2  rmind struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS] = {
     91  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* undef */
     92  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* undef */
     93  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* undef */
     94  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_SHARED, 1 },			/* Access */
     95  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* Close */
     96  1.1.1.1.4.2  rmind 	{ 0, 2, 0, 1, LK_EXCLUSIVE, 1 },		/* Commit */
     97  1.1.1.1.4.2  rmind 	{ 1, 2, 1, 1, LK_EXCLUSIVE, 1 },		/* Create */
     98  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* Delegpurge */
     99  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* Delegreturn */
    100  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_SHARED, 1 },			/* Getattr */
    101  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* GetFH */
    102  1.1.1.1.4.2  rmind 	{ 2, 1, 1, 1, LK_EXCLUSIVE, 1 },		/* Link */
    103  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* Lock */
    104  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* LockT */
    105  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* LockU */
    106  1.1.1.1.4.2  rmind 	{ 1, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* Lookup */
    107  1.1.1.1.4.2  rmind 	{ 1, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* Lookupp */
    108  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* NVerify */
    109  1.1.1.1.4.2  rmind 	{ 1, 1, 0, 1, LK_EXCLUSIVE, 1 },		/* Open */
    110  1.1.1.1.4.2  rmind 	{ 1, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* OpenAttr */
    111  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* OpenConfirm */
    112  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* OpenDowngrade */
    113  1.1.1.1.4.2  rmind 	{ 1, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* PutFH */
    114  1.1.1.1.4.2  rmind 	{ 1, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* PutPubFH */
    115  1.1.1.1.4.2  rmind 	{ 1, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* PutRootFH */
    116  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_SHARED, 1 },			/* Read */
    117  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_SHARED, 1 },			/* Readdir */
    118  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_SHARED, 1 },			/* ReadLink */
    119  1.1.1.1.4.2  rmind 	{ 0, 2, 1, 1, LK_EXCLUSIVE, 1 },		/* Remove */
    120  1.1.1.1.4.2  rmind 	{ 2, 1, 1, 1, LK_EXCLUSIVE, 1 },		/* Rename */
    121  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* Renew */
    122  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* RestoreFH */
    123  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* SaveFH */
    124  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* SecInfo */
    125  1.1.1.1.4.2  rmind 	{ 0, 2, 1, 1, LK_EXCLUSIVE, 1 },		/* Setattr */
    126  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* SetClientID */
    127  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* SetClientIDConfirm */
    128  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* Verify */
    129  1.1.1.1.4.2  rmind 	{ 0, 2, 1, 1, LK_EXCLUSIVE, 1 },		/* Write */
    130  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* ReleaseLockOwner */
    131  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* Backchannel Ctrl */
    132  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* Bind Conn to Sess */
    133  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 0 },		/* Exchange ID */
    134  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 0 },		/* Create Session */
    135  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 0 },		/* Destroy Session */
    136  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* Free StateID */
    137  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* Get Dir Deleg */
    138  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* Get Device Info */
    139  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* Get Device List */
    140  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* Layout Commit */
    141  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* Layout Get */
    142  1.1.1.1.4.2  rmind 	{ 0, 1, 0, 0, LK_EXCLUSIVE, 1 },		/* Layout Return */
    143  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* Secinfo No name */
    144  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* Sequence */
    145  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* Set SSV */
    146  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* Test StateID */
    147  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* Want Delegation */
    148  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 0 },		/* Destroy ClientID */
    149  1.1.1.1.4.2  rmind 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1 },		/* Reclaim Complete */
    150  1.1.1.1.4.2  rmind };
    151  1.1.1.1.4.2  rmind #endif	/* !APPLEKEXT */
    152  1.1.1.1.4.2  rmind 
    153  1.1.1.1.4.2  rmind static int ncl_mbuf_mhlen = MHLEN;
    154  1.1.1.1.4.2  rmind static int nfsrv_usercnt = 0;
    155  1.1.1.1.4.2  rmind static int nfsrv_dnsnamelen;
    156  1.1.1.1.4.2  rmind static u_char *nfsrv_dnsname = NULL;
    157  1.1.1.1.4.2  rmind static int nfsrv_usermax = 999999999;
    158  1.1.1.1.4.2  rmind static struct nfsuserhashhead nfsuserhash[NFSUSERHASHSIZE];
    159  1.1.1.1.4.2  rmind static struct nfsuserhashhead nfsusernamehash[NFSUSERHASHSIZE];
    160  1.1.1.1.4.2  rmind static struct nfsuserhashhead nfsgrouphash[NFSGROUPHASHSIZE];
    161  1.1.1.1.4.2  rmind static struct nfsuserhashhead nfsgroupnamehash[NFSGROUPHASHSIZE];
    162  1.1.1.1.4.2  rmind static struct nfsuserlruhead nfsuserlruhead;
    163  1.1.1.1.4.2  rmind 
    164  1.1.1.1.4.2  rmind /*
    165  1.1.1.1.4.2  rmind  * This static array indicates whether or not the RPC generates a large
    166  1.1.1.1.4.2  rmind  * reply. This is used by nfs_reply() to decide whether or not an mbuf
    167  1.1.1.1.4.2  rmind  * cluster should be allocated. (If a cluster is required by an RPC
    168  1.1.1.1.4.2  rmind  * marked 0 in this array, the code will still work, just not quite as
    169  1.1.1.1.4.2  rmind  * efficiently.)
    170  1.1.1.1.4.2  rmind  */
    171  1.1.1.1.4.2  rmind int nfs_bigreply[NFSV41_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0,
    172  1.1.1.1.4.2  rmind     0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    173  1.1.1.1.4.2  rmind     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
    174  1.1.1.1.4.2  rmind 
    175  1.1.1.1.4.2  rmind /* local functions */
    176  1.1.1.1.4.2  rmind static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
    177  1.1.1.1.4.2  rmind static void nfsv4_wanted(struct nfsv4lock *lp);
    178  1.1.1.1.4.2  rmind static int nfsrv_cmpmixedcase(u_char *cp, u_char *cp2, int len);
    179  1.1.1.1.4.2  rmind static int nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name,
    180  1.1.1.1.4.2  rmind     NFSPROC_T *p);
    181  1.1.1.1.4.2  rmind static void nfsrv_removeuser(struct nfsusrgrp *usrp);
    182  1.1.1.1.4.2  rmind static int nfsrv_getrefstr(struct nfsrv_descript *, u_char **, u_char **,
    183  1.1.1.1.4.2  rmind     int *, int *);
    184  1.1.1.1.4.2  rmind static void nfsrv_refstrbigenough(int, u_char **, u_char **, int *);
    185  1.1.1.1.4.2  rmind 
    186  1.1.1.1.4.2  rmind 
    187  1.1.1.1.4.2  rmind #ifndef APPLE
    188  1.1.1.1.4.2  rmind /*
    189  1.1.1.1.4.2  rmind  * copies mbuf chain to the uio scatter/gather list
    190  1.1.1.1.4.2  rmind  */
    191  1.1.1.1.4.2  rmind int
    192  1.1.1.1.4.2  rmind nfsm_mbufuio(struct nfsrv_descript *nd, struct uio *uiop, int siz)
    193  1.1.1.1.4.2  rmind {
    194  1.1.1.1.4.2  rmind 	char *mbufcp, *uiocp;
    195  1.1.1.1.4.2  rmind 	int xfer, left, len;
    196  1.1.1.1.4.2  rmind 	mbuf_t mp;
    197  1.1.1.1.4.2  rmind 	long uiosiz, rem;
    198  1.1.1.1.4.2  rmind 	int error = 0;
    199  1.1.1.1.4.2  rmind 
    200  1.1.1.1.4.2  rmind 	mp = nd->nd_md;
    201  1.1.1.1.4.2  rmind 	mbufcp = nd->nd_dpos;
    202  1.1.1.1.4.2  rmind 	len = NFSMTOD(mp, caddr_t) + mbuf_len(mp) - mbufcp;
    203  1.1.1.1.4.2  rmind 	rem = NFSM_RNDUP(siz) - siz;
    204  1.1.1.1.4.2  rmind 	while (siz > 0) {
    205  1.1.1.1.4.2  rmind 		if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) {
    206  1.1.1.1.4.2  rmind 			error = EBADRPC;
    207  1.1.1.1.4.2  rmind 			goto out;
    208  1.1.1.1.4.2  rmind 		}
    209  1.1.1.1.4.2  rmind 		left = uiop->uio_iov->iov_len;
    210  1.1.1.1.4.2  rmind 		uiocp = uiop->uio_iov->iov_base;
    211  1.1.1.1.4.2  rmind 		if (left > siz)
    212  1.1.1.1.4.2  rmind 			left = siz;
    213  1.1.1.1.4.2  rmind 		uiosiz = left;
    214  1.1.1.1.4.2  rmind 		while (left > 0) {
    215  1.1.1.1.4.2  rmind 			while (len == 0) {
    216  1.1.1.1.4.2  rmind 				mp = mbuf_next(mp);
    217  1.1.1.1.4.2  rmind 				if (mp == NULL) {
    218  1.1.1.1.4.2  rmind 					error = EBADRPC;
    219  1.1.1.1.4.2  rmind 					goto out;
    220  1.1.1.1.4.2  rmind 				}
    221  1.1.1.1.4.2  rmind 				mbufcp = NFSMTOD(mp, caddr_t);
    222  1.1.1.1.4.2  rmind 				len = mbuf_len(mp);
    223  1.1.1.1.4.2  rmind 				KASSERT(len > 0, ("len %d", len));
    224  1.1.1.1.4.2  rmind 			}
    225  1.1.1.1.4.2  rmind 			xfer = (left > len) ? len : left;
    226  1.1.1.1.4.2  rmind #ifdef notdef
    227  1.1.1.1.4.2  rmind 			/* Not Yet.. */
    228  1.1.1.1.4.2  rmind 			if (uiop->uio_iov->iov_op != NULL)
    229  1.1.1.1.4.2  rmind 				(*(uiop->uio_iov->iov_op))
    230  1.1.1.1.4.2  rmind 				(mbufcp, uiocp, xfer);
    231  1.1.1.1.4.2  rmind 			else
    232  1.1.1.1.4.2  rmind #endif
    233  1.1.1.1.4.2  rmind 			if (uiop->uio_segflg == UIO_SYSSPACE)
    234  1.1.1.1.4.2  rmind 				NFSBCOPY(mbufcp, uiocp, xfer);
    235  1.1.1.1.4.2  rmind 			else
    236  1.1.1.1.4.2  rmind 				copyout(mbufcp, CAST_USER_ADDR_T(uiocp), xfer);
    237  1.1.1.1.4.2  rmind 			left -= xfer;
    238  1.1.1.1.4.2  rmind 			len -= xfer;
    239  1.1.1.1.4.2  rmind 			mbufcp += xfer;
    240  1.1.1.1.4.2  rmind 			uiocp += xfer;
    241  1.1.1.1.4.2  rmind 			uiop->uio_offset += xfer;
    242  1.1.1.1.4.2  rmind 			uiop->uio_resid -= xfer;
    243  1.1.1.1.4.2  rmind 		}
    244  1.1.1.1.4.2  rmind 		if (uiop->uio_iov->iov_len <= siz) {
    245  1.1.1.1.4.2  rmind 			uiop->uio_iovcnt--;
    246  1.1.1.1.4.2  rmind 			uiop->uio_iov++;
    247  1.1.1.1.4.2  rmind 		} else {
    248  1.1.1.1.4.2  rmind 			uiop->uio_iov->iov_base = (void *)
    249  1.1.1.1.4.2  rmind 				((char *)uiop->uio_iov->iov_base + uiosiz);
    250  1.1.1.1.4.2  rmind 			uiop->uio_iov->iov_len -= uiosiz;
    251  1.1.1.1.4.2  rmind 		}
    252  1.1.1.1.4.2  rmind 		siz -= uiosiz;
    253  1.1.1.1.4.2  rmind 	}
    254  1.1.1.1.4.2  rmind 	nd->nd_dpos = mbufcp;
    255  1.1.1.1.4.2  rmind 	nd->nd_md = mp;
    256  1.1.1.1.4.2  rmind 	if (rem > 0) {
    257  1.1.1.1.4.2  rmind 		if (len < rem)
    258  1.1.1.1.4.2  rmind 			error = nfsm_advance(nd, rem, len);
    259  1.1.1.1.4.2  rmind 		else
    260  1.1.1.1.4.2  rmind 			nd->nd_dpos += rem;
    261  1.1.1.1.4.2  rmind 	}
    262  1.1.1.1.4.2  rmind 
    263  1.1.1.1.4.2  rmind out:
    264  1.1.1.1.4.2  rmind 	NFSEXITCODE2(error, nd);
    265  1.1.1.1.4.2  rmind 	return (error);
    266  1.1.1.1.4.2  rmind }
    267  1.1.1.1.4.2  rmind #endif	/* !APPLE */
    268  1.1.1.1.4.2  rmind 
    269  1.1.1.1.4.2  rmind /*
    270  1.1.1.1.4.2  rmind  * Help break down an mbuf chain by setting the first siz bytes contiguous
    271  1.1.1.1.4.2  rmind  * pointed to by returned val.
    272  1.1.1.1.4.2  rmind  * This is used by the macro NFSM_DISSECT for tough
    273  1.1.1.1.4.2  rmind  * cases.
    274  1.1.1.1.4.2  rmind  */
    275  1.1.1.1.4.2  rmind APPLESTATIC void *
    276  1.1.1.1.4.2  rmind nfsm_dissct(struct nfsrv_descript *nd, int siz, int how)
    277  1.1.1.1.4.2  rmind {
    278  1.1.1.1.4.2  rmind 	mbuf_t mp2;
    279  1.1.1.1.4.2  rmind 	int siz2, xfer;
    280  1.1.1.1.4.2  rmind 	caddr_t p;
    281  1.1.1.1.4.2  rmind 	int left;
    282  1.1.1.1.4.2  rmind 	caddr_t retp;
    283  1.1.1.1.4.2  rmind 
    284  1.1.1.1.4.2  rmind 	retp = NULL;
    285  1.1.1.1.4.2  rmind 	left = NFSMTOD(nd->nd_md, caddr_t) + mbuf_len(nd->nd_md) - nd->nd_dpos;
    286  1.1.1.1.4.2  rmind 	while (left == 0) {
    287  1.1.1.1.4.2  rmind 		nd->nd_md = mbuf_next(nd->nd_md);
    288  1.1.1.1.4.2  rmind 		if (nd->nd_md == NULL)
    289  1.1.1.1.4.2  rmind 			return (retp);
    290  1.1.1.1.4.2  rmind 		left = mbuf_len(nd->nd_md);
    291  1.1.1.1.4.2  rmind 		nd->nd_dpos = NFSMTOD(nd->nd_md, caddr_t);
    292  1.1.1.1.4.2  rmind 	}
    293  1.1.1.1.4.2  rmind 	if (left >= siz) {
    294  1.1.1.1.4.2  rmind 		retp = nd->nd_dpos;
    295  1.1.1.1.4.2  rmind 		nd->nd_dpos += siz;
    296  1.1.1.1.4.2  rmind 	} else if (mbuf_next(nd->nd_md) == NULL) {
    297  1.1.1.1.4.2  rmind 		return (retp);
    298  1.1.1.1.4.2  rmind 	} else if (siz > ncl_mbuf_mhlen) {
    299  1.1.1.1.4.2  rmind 		panic("nfs S too big");
    300  1.1.1.1.4.2  rmind 	} else {
    301  1.1.1.1.4.2  rmind 		MGET(mp2, MT_DATA, how);
    302  1.1.1.1.4.2  rmind 		if (mp2 == NULL)
    303  1.1.1.1.4.2  rmind 			return (NULL);
    304  1.1.1.1.4.2  rmind 		mbuf_setnext(mp2, mbuf_next(nd->nd_md));
    305  1.1.1.1.4.2  rmind 		mbuf_setnext(nd->nd_md, mp2);
    306  1.1.1.1.4.2  rmind 		mbuf_setlen(nd->nd_md, mbuf_len(nd->nd_md) - left);
    307  1.1.1.1.4.2  rmind 		nd->nd_md = mp2;
    308  1.1.1.1.4.2  rmind 		retp = p = NFSMTOD(mp2, caddr_t);
    309  1.1.1.1.4.2  rmind 		NFSBCOPY(nd->nd_dpos, p, left);	/* Copy what was left */
    310  1.1.1.1.4.2  rmind 		siz2 = siz - left;
    311  1.1.1.1.4.2  rmind 		p += left;
    312  1.1.1.1.4.2  rmind 		mp2 = mbuf_next(mp2);
    313  1.1.1.1.4.2  rmind 		/* Loop around copying up the siz2 bytes */
    314  1.1.1.1.4.2  rmind 		while (siz2 > 0) {
    315  1.1.1.1.4.2  rmind 			if (mp2 == NULL)
    316  1.1.1.1.4.2  rmind 				return (NULL);
    317  1.1.1.1.4.2  rmind 			xfer = (siz2 > mbuf_len(mp2)) ? mbuf_len(mp2) : siz2;
    318  1.1.1.1.4.2  rmind 			if (xfer > 0) {
    319  1.1.1.1.4.2  rmind 				NFSBCOPY(NFSMTOD(mp2, caddr_t), p, xfer);
    320  1.1.1.1.4.2  rmind 				NFSM_DATAP(mp2, xfer);
    321  1.1.1.1.4.2  rmind 				mbuf_setlen(mp2, mbuf_len(mp2) - xfer);
    322  1.1.1.1.4.2  rmind 				p += xfer;
    323  1.1.1.1.4.2  rmind 				siz2 -= xfer;
    324  1.1.1.1.4.2  rmind 			}
    325  1.1.1.1.4.2  rmind 			if (siz2 > 0)
    326  1.1.1.1.4.2  rmind 				mp2 = mbuf_next(mp2);
    327  1.1.1.1.4.2  rmind 		}
    328  1.1.1.1.4.2  rmind 		mbuf_setlen(nd->nd_md, siz);
    329  1.1.1.1.4.2  rmind 		nd->nd_md = mp2;
    330  1.1.1.1.4.2  rmind 		nd->nd_dpos = NFSMTOD(mp2, caddr_t);
    331  1.1.1.1.4.2  rmind 	}
    332  1.1.1.1.4.2  rmind 	return (retp);
    333  1.1.1.1.4.2  rmind }
    334  1.1.1.1.4.2  rmind 
    335  1.1.1.1.4.2  rmind /*
    336  1.1.1.1.4.2  rmind  * Advance the position in the mbuf chain.
    337  1.1.1.1.4.2  rmind  * If offs == 0, this is a no-op, but it is simpler to just return from
    338  1.1.1.1.4.2  rmind  * here than check for offs > 0 for all calls to nfsm_advance.
    339  1.1.1.1.4.2  rmind  * If left == -1, it should be calculated here.
    340  1.1.1.1.4.2  rmind  */
    341  1.1.1.1.4.2  rmind APPLESTATIC int
    342  1.1.1.1.4.2  rmind nfsm_advance(struct nfsrv_descript *nd, int offs, int left)
    343  1.1.1.1.4.2  rmind {
    344  1.1.1.1.4.2  rmind 	int error = 0;
    345  1.1.1.1.4.2  rmind 
    346  1.1.1.1.4.2  rmind 	if (offs == 0)
    347  1.1.1.1.4.2  rmind 		goto out;
    348  1.1.1.1.4.2  rmind 	/*
    349  1.1.1.1.4.2  rmind 	 * A negative offs should be considered a serious problem.
    350  1.1.1.1.4.2  rmind 	 */
    351  1.1.1.1.4.2  rmind 	if (offs < 0)
    352  1.1.1.1.4.2  rmind 		panic("nfsrv_advance");
    353  1.1.1.1.4.2  rmind 
    354  1.1.1.1.4.2  rmind 	/*
    355  1.1.1.1.4.2  rmind 	 * If left == -1, calculate it here.
    356  1.1.1.1.4.2  rmind 	 */
    357  1.1.1.1.4.2  rmind 	if (left == -1)
    358  1.1.1.1.4.2  rmind 		left = NFSMTOD(nd->nd_md, caddr_t) + mbuf_len(nd->nd_md) -
    359  1.1.1.1.4.2  rmind 		    nd->nd_dpos;
    360  1.1.1.1.4.2  rmind 
    361  1.1.1.1.4.2  rmind 	/*
    362  1.1.1.1.4.2  rmind 	 * Loop around, advancing over the mbuf data.
    363  1.1.1.1.4.2  rmind 	 */
    364  1.1.1.1.4.2  rmind 	while (offs > left) {
    365  1.1.1.1.4.2  rmind 		offs -= left;
    366  1.1.1.1.4.2  rmind 		nd->nd_md = mbuf_next(nd->nd_md);
    367  1.1.1.1.4.2  rmind 		if (nd->nd_md == NULL) {
    368  1.1.1.1.4.2  rmind 			error = EBADRPC;
    369  1.1.1.1.4.2  rmind 			goto out;
    370  1.1.1.1.4.2  rmind 		}
    371  1.1.1.1.4.2  rmind 		left = mbuf_len(nd->nd_md);
    372  1.1.1.1.4.2  rmind 		nd->nd_dpos = NFSMTOD(nd->nd_md, caddr_t);
    373  1.1.1.1.4.2  rmind 	}
    374  1.1.1.1.4.2  rmind 	nd->nd_dpos += offs;
    375  1.1.1.1.4.2  rmind 
    376  1.1.1.1.4.2  rmind out:
    377  1.1.1.1.4.2  rmind 	NFSEXITCODE(error);
    378  1.1.1.1.4.2  rmind 	return (error);
    379  1.1.1.1.4.2  rmind }
    380  1.1.1.1.4.2  rmind 
    381  1.1.1.1.4.2  rmind /*
    382  1.1.1.1.4.2  rmind  * Copy a string into mbuf(s).
    383  1.1.1.1.4.2  rmind  * Return the number of bytes output, including XDR overheads.
    384  1.1.1.1.4.2  rmind  */
    385  1.1.1.1.4.2  rmind APPLESTATIC int
    386  1.1.1.1.4.2  rmind nfsm_strtom(struct nfsrv_descript *nd, const char *cp, int siz)
    387  1.1.1.1.4.2  rmind {
    388  1.1.1.1.4.2  rmind 	mbuf_t m2;
    389  1.1.1.1.4.2  rmind 	int xfer, left;
    390  1.1.1.1.4.2  rmind 	mbuf_t m1;
    391  1.1.1.1.4.2  rmind 	int rem, bytesize;
    392  1.1.1.1.4.2  rmind 	u_int32_t *tl;
    393  1.1.1.1.4.2  rmind 	char *cp2;
    394  1.1.1.1.4.2  rmind 
    395  1.1.1.1.4.2  rmind 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
    396  1.1.1.1.4.2  rmind 	*tl = txdr_unsigned(siz);
    397  1.1.1.1.4.2  rmind 	rem = NFSM_RNDUP(siz) - siz;
    398  1.1.1.1.4.2  rmind 	bytesize = NFSX_UNSIGNED + siz + rem;
    399  1.1.1.1.4.2  rmind 	m2 = nd->nd_mb;
    400  1.1.1.1.4.2  rmind 	cp2 = nd->nd_bpos;
    401  1.1.1.1.4.2  rmind 	left = M_TRAILINGSPACE(m2);
    402  1.1.1.1.4.2  rmind 
    403  1.1.1.1.4.2  rmind 	/*
    404  1.1.1.1.4.2  rmind 	 * Loop around copying the string to mbuf(s).
    405  1.1.1.1.4.2  rmind 	 */
    406  1.1.1.1.4.2  rmind 	while (siz > 0) {
    407  1.1.1.1.4.2  rmind 		if (left == 0) {
    408  1.1.1.1.4.2  rmind 			if (siz > ncl_mbuf_mlen)
    409  1.1.1.1.4.2  rmind 				NFSMCLGET(m1, M_WAITOK);
    410  1.1.1.1.4.2  rmind 			else
    411  1.1.1.1.4.2  rmind 				NFSMGET(m1);
    412  1.1.1.1.4.2  rmind 			mbuf_setlen(m1, 0);
    413  1.1.1.1.4.2  rmind 			mbuf_setnext(m2, m1);
    414  1.1.1.1.4.2  rmind 			m2 = m1;
    415  1.1.1.1.4.2  rmind 			cp2 = NFSMTOD(m2, caddr_t);
    416  1.1.1.1.4.2  rmind 			left = M_TRAILINGSPACE(m2);
    417  1.1.1.1.4.2  rmind 		}
    418  1.1.1.1.4.2  rmind 		if (left >= siz)
    419  1.1.1.1.4.2  rmind 			xfer = siz;
    420  1.1.1.1.4.2  rmind 		else
    421  1.1.1.1.4.2  rmind 			xfer = left;
    422  1.1.1.1.4.2  rmind 		NFSBCOPY(cp, cp2, xfer);
    423  1.1.1.1.4.2  rmind 		cp += xfer;
    424  1.1.1.1.4.2  rmind 		mbuf_setlen(m2, mbuf_len(m2) + xfer);
    425  1.1.1.1.4.2  rmind 		siz -= xfer;
    426  1.1.1.1.4.2  rmind 		left -= xfer;
    427  1.1.1.1.4.2  rmind 		if (siz == 0 && rem) {
    428  1.1.1.1.4.2  rmind 			if (left < rem)
    429  1.1.1.1.4.2  rmind 				panic("nfsm_strtom");
    430  1.1.1.1.4.2  rmind 			NFSBZERO(cp2 + xfer, rem);
    431  1.1.1.1.4.2  rmind 			mbuf_setlen(m2, mbuf_len(m2) + rem);
    432  1.1.1.1.4.2  rmind 		}
    433  1.1.1.1.4.2  rmind 	}
    434  1.1.1.1.4.2  rmind 	nd->nd_mb = m2;
    435  1.1.1.1.4.2  rmind 	nd->nd_bpos = NFSMTOD(m2, caddr_t) + mbuf_len(m2);
    436  1.1.1.1.4.2  rmind 	return (bytesize);
    437  1.1.1.1.4.2  rmind }
    438  1.1.1.1.4.2  rmind 
    439  1.1.1.1.4.2  rmind /*
    440  1.1.1.1.4.2  rmind  * Called once to initialize data structures...
    441  1.1.1.1.4.2  rmind  */
    442  1.1.1.1.4.2  rmind APPLESTATIC void
    443  1.1.1.1.4.2  rmind newnfs_init(void)
    444  1.1.1.1.4.2  rmind {
    445  1.1.1.1.4.2  rmind 	static int nfs_inited = 0;
    446  1.1.1.1.4.2  rmind 
    447  1.1.1.1.4.2  rmind 	if (nfs_inited)
    448  1.1.1.1.4.2  rmind 		return;
    449  1.1.1.1.4.2  rmind 	nfs_inited = 1;
    450  1.1.1.1.4.2  rmind 
    451  1.1.1.1.4.2  rmind 	newnfs_true = txdr_unsigned(TRUE);
    452  1.1.1.1.4.2  rmind 	newnfs_false = txdr_unsigned(FALSE);
    453  1.1.1.1.4.2  rmind 	newnfs_xdrneg1 = txdr_unsigned(-1);
    454  1.1.1.1.4.2  rmind 	nfscl_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
    455  1.1.1.1.4.2  rmind 	if (nfscl_ticks < 1)
    456  1.1.1.1.4.2  rmind 		nfscl_ticks = 1;
    457  1.1.1.1.4.2  rmind 	NFSSETBOOTTIME(nfsboottime);
    458  1.1.1.1.4.2  rmind 
    459  1.1.1.1.4.2  rmind 	/*
    460  1.1.1.1.4.2  rmind 	 * Initialize reply list and start timer
    461  1.1.1.1.4.2  rmind 	 */
    462  1.1.1.1.4.2  rmind 	TAILQ_INIT(&nfsd_reqq);
    463  1.1.1.1.4.2  rmind 	NFS_TIMERINIT;
    464  1.1.1.1.4.2  rmind }
    465  1.1.1.1.4.2  rmind 
    466  1.1.1.1.4.2  rmind /*
    467  1.1.1.1.4.2  rmind  * Put a file handle in an mbuf list.
    468  1.1.1.1.4.2  rmind  * If the size argument == 0, just use the default size.
    469  1.1.1.1.4.2  rmind  * set_true == 1 if there should be an newnfs_true prepended on the file handle.
    470  1.1.1.1.4.2  rmind  * Return the number of bytes output, including XDR overhead.
    471  1.1.1.1.4.2  rmind  */
    472  1.1.1.1.4.2  rmind APPLESTATIC int
    473  1.1.1.1.4.2  rmind nfsm_fhtom(struct nfsrv_descript *nd, u_int8_t *fhp, int size, int set_true)
    474  1.1.1.1.4.2  rmind {
    475  1.1.1.1.4.2  rmind 	u_int32_t *tl;
    476  1.1.1.1.4.2  rmind 	u_int8_t *cp;
    477  1.1.1.1.4.2  rmind 	int fullsiz, rem, bytesize = 0;
    478  1.1.1.1.4.2  rmind 
    479  1.1.1.1.4.2  rmind 	if (size == 0)
    480  1.1.1.1.4.2  rmind 		size = NFSX_MYFH;
    481  1.1.1.1.4.2  rmind 	switch (nd->nd_flag & (ND_NFSV2 | ND_NFSV3 | ND_NFSV4)) {
    482  1.1.1.1.4.2  rmind 	case ND_NFSV2:
    483  1.1.1.1.4.2  rmind 		if (size > NFSX_V2FH)
    484  1.1.1.1.4.2  rmind 			panic("fh size > NFSX_V2FH for NFSv2");
    485  1.1.1.1.4.2  rmind 		NFSM_BUILD(cp, u_int8_t *, NFSX_V2FH);
    486  1.1.1.1.4.2  rmind 		NFSBCOPY(fhp, cp, size);
    487  1.1.1.1.4.2  rmind 		if (size < NFSX_V2FH)
    488  1.1.1.1.4.2  rmind 			NFSBZERO(cp + size, NFSX_V2FH - size);
    489  1.1.1.1.4.2  rmind 		bytesize = NFSX_V2FH;
    490  1.1.1.1.4.2  rmind 		break;
    491  1.1.1.1.4.2  rmind 	case ND_NFSV3:
    492  1.1.1.1.4.2  rmind 	case ND_NFSV4:
    493  1.1.1.1.4.2  rmind 		fullsiz = NFSM_RNDUP(size);
    494  1.1.1.1.4.2  rmind 		rem = fullsiz - size;
    495  1.1.1.1.4.2  rmind 		if (set_true) {
    496  1.1.1.1.4.2  rmind 		    bytesize = 2 * NFSX_UNSIGNED + fullsiz;
    497  1.1.1.1.4.2  rmind 		    NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
    498  1.1.1.1.4.2  rmind 		    *tl = newnfs_true;
    499  1.1.1.1.4.2  rmind 		} else {
    500  1.1.1.1.4.2  rmind 		    bytesize = NFSX_UNSIGNED + fullsiz;
    501  1.1.1.1.4.2  rmind 		}
    502  1.1.1.1.4.2  rmind 		(void) nfsm_strtom(nd, fhp, size);
    503  1.1.1.1.4.2  rmind 		break;
    504  1.1.1.1.4.2  rmind 	};
    505  1.1.1.1.4.2  rmind 	return (bytesize);
    506  1.1.1.1.4.2  rmind }
    507  1.1.1.1.4.2  rmind 
    508  1.1.1.1.4.2  rmind /*
    509  1.1.1.1.4.2  rmind  * This function compares two net addresses by family and returns TRUE
    510  1.1.1.1.4.2  rmind  * if they are the same host.
    511  1.1.1.1.4.2  rmind  * If there is any doubt, return FALSE.
    512  1.1.1.1.4.2  rmind  * The AF_INET family is handled as a special case so that address mbufs
    513  1.1.1.1.4.2  rmind  * don't need to be saved to store "struct in_addr", which is only 4 bytes.
    514  1.1.1.1.4.2  rmind  */
    515  1.1.1.1.4.2  rmind APPLESTATIC int
    516  1.1.1.1.4.2  rmind nfsaddr_match(int family, union nethostaddr *haddr, NFSSOCKADDR_T nam)
    517  1.1.1.1.4.2  rmind {
    518  1.1.1.1.4.2  rmind 	struct sockaddr_in *inetaddr;
    519  1.1.1.1.4.2  rmind 
    520  1.1.1.1.4.2  rmind 	switch (family) {
    521  1.1.1.1.4.2  rmind 	case AF_INET:
    522  1.1.1.1.4.2  rmind 		inetaddr = NFSSOCKADDR(nam, struct sockaddr_in *);
    523  1.1.1.1.4.2  rmind 		if (inetaddr->sin_family == AF_INET &&
    524  1.1.1.1.4.2  rmind 		    inetaddr->sin_addr.s_addr == haddr->had_inet.s_addr)
    525  1.1.1.1.4.2  rmind 			return (1);
    526  1.1.1.1.4.2  rmind 		break;
    527  1.1.1.1.4.2  rmind #ifdef INET6
    528  1.1.1.1.4.2  rmind 	case AF_INET6:
    529  1.1.1.1.4.2  rmind 		{
    530  1.1.1.1.4.2  rmind 		struct sockaddr_in6 *inetaddr6;
    531  1.1.1.1.4.2  rmind 
    532  1.1.1.1.4.2  rmind 		inetaddr6 = NFSSOCKADDR(nam, struct sockaddr_in6 *);
    533  1.1.1.1.4.2  rmind 		/* XXX - should test sin6_scope_id ? */
    534  1.1.1.1.4.2  rmind 		if (inetaddr6->sin6_family == AF_INET6 &&
    535  1.1.1.1.4.2  rmind 		    IN6_ARE_ADDR_EQUAL(&inetaddr6->sin6_addr,
    536  1.1.1.1.4.2  rmind 			  &haddr->had_inet6))
    537  1.1.1.1.4.2  rmind 			return (1);
    538  1.1.1.1.4.2  rmind 		}
    539  1.1.1.1.4.2  rmind 		break;
    540  1.1.1.1.4.2  rmind #endif
    541  1.1.1.1.4.2  rmind 	};
    542  1.1.1.1.4.2  rmind 	return (0);
    543  1.1.1.1.4.2  rmind }
    544  1.1.1.1.4.2  rmind 
    545  1.1.1.1.4.2  rmind /*
    546  1.1.1.1.4.2  rmind  * Similar to the above, but takes to NFSSOCKADDR_T args.
    547  1.1.1.1.4.2  rmind  */
    548  1.1.1.1.4.2  rmind APPLESTATIC int
    549  1.1.1.1.4.2  rmind nfsaddr2_match(NFSSOCKADDR_T nam1, NFSSOCKADDR_T nam2)
    550  1.1.1.1.4.2  rmind {
    551  1.1.1.1.4.2  rmind 	struct sockaddr_in *addr1, *addr2;
    552  1.1.1.1.4.2  rmind 	struct sockaddr *inaddr;
    553  1.1.1.1.4.2  rmind 
    554  1.1.1.1.4.2  rmind 	inaddr = NFSSOCKADDR(nam1, struct sockaddr *);
    555  1.1.1.1.4.2  rmind 	switch (inaddr->sa_family) {
    556  1.1.1.1.4.2  rmind 	case AF_INET:
    557  1.1.1.1.4.2  rmind 		addr1 = NFSSOCKADDR(nam1, struct sockaddr_in *);
    558  1.1.1.1.4.2  rmind 		addr2 = NFSSOCKADDR(nam2, struct sockaddr_in *);
    559  1.1.1.1.4.2  rmind 		if (addr2->sin_family == AF_INET &&
    560  1.1.1.1.4.2  rmind 		    addr1->sin_addr.s_addr == addr2->sin_addr.s_addr)
    561  1.1.1.1.4.2  rmind 			return (1);
    562  1.1.1.1.4.2  rmind 		break;
    563  1.1.1.1.4.2  rmind #ifdef INET6
    564  1.1.1.1.4.2  rmind 	case AF_INET6:
    565  1.1.1.1.4.2  rmind 		{
    566  1.1.1.1.4.2  rmind 		struct sockaddr_in6 *inet6addr1, *inet6addr2;
    567  1.1.1.1.4.2  rmind 
    568  1.1.1.1.4.2  rmind 		inet6addr1 = NFSSOCKADDR(nam1, struct sockaddr_in6 *);
    569  1.1.1.1.4.2  rmind 		inet6addr2 = NFSSOCKADDR(nam2, struct sockaddr_in6 *);
    570  1.1.1.1.4.2  rmind 		/* XXX - should test sin6_scope_id ? */
    571  1.1.1.1.4.2  rmind 		if (inet6addr2->sin6_family == AF_INET6 &&
    572  1.1.1.1.4.2  rmind 		    IN6_ARE_ADDR_EQUAL(&inet6addr1->sin6_addr,
    573  1.1.1.1.4.2  rmind 			  &inet6addr2->sin6_addr))
    574  1.1.1.1.4.2  rmind 			return (1);
    575  1.1.1.1.4.2  rmind 		}
    576  1.1.1.1.4.2  rmind 		break;
    577  1.1.1.1.4.2  rmind #endif
    578  1.1.1.1.4.2  rmind 	};
    579  1.1.1.1.4.2  rmind 	return (0);
    580  1.1.1.1.4.2  rmind }
    581  1.1.1.1.4.2  rmind 
    582  1.1.1.1.4.2  rmind 
    583  1.1.1.1.4.2  rmind /*
    584  1.1.1.1.4.2  rmind  * Trim the stuff already dissected off the mbuf list.
    585  1.1.1.1.4.2  rmind  */
    586  1.1.1.1.4.2  rmind APPLESTATIC void
    587  1.1.1.1.4.2  rmind newnfs_trimleading(nd)
    588  1.1.1.1.4.2  rmind 	struct nfsrv_descript *nd;
    589  1.1.1.1.4.2  rmind {
    590  1.1.1.1.4.2  rmind 	mbuf_t m, n;
    591  1.1.1.1.4.2  rmind 	int offs;
    592  1.1.1.1.4.2  rmind 
    593  1.1.1.1.4.2  rmind 	/*
    594  1.1.1.1.4.2  rmind 	 * First, free up leading mbufs.
    595  1.1.1.1.4.2  rmind 	 */
    596  1.1.1.1.4.2  rmind 	if (nd->nd_mrep != nd->nd_md) {
    597  1.1.1.1.4.2  rmind 		m = nd->nd_mrep;
    598  1.1.1.1.4.2  rmind 		while (mbuf_next(m) != nd->nd_md) {
    599  1.1.1.1.4.2  rmind 			if (mbuf_next(m) == NULL)
    600  1.1.1.1.4.2  rmind 				panic("nfsm trim leading");
    601  1.1.1.1.4.2  rmind 			m = mbuf_next(m);
    602  1.1.1.1.4.2  rmind 		}
    603  1.1.1.1.4.2  rmind 		mbuf_setnext(m, NULL);
    604  1.1.1.1.4.2  rmind 		mbuf_freem(nd->nd_mrep);
    605  1.1.1.1.4.2  rmind 	}
    606  1.1.1.1.4.2  rmind 	m = nd->nd_md;
    607  1.1.1.1.4.2  rmind 
    608  1.1.1.1.4.2  rmind 	/*
    609  1.1.1.1.4.2  rmind 	 * Now, adjust this mbuf, based on nd_dpos.
    610  1.1.1.1.4.2  rmind 	 */
    611  1.1.1.1.4.2  rmind 	offs = nd->nd_dpos - NFSMTOD(m, caddr_t);
    612  1.1.1.1.4.2  rmind 	if (offs == mbuf_len(m)) {
    613  1.1.1.1.4.2  rmind 		n = m;
    614  1.1.1.1.4.2  rmind 		m = mbuf_next(m);
    615  1.1.1.1.4.2  rmind 		if (m == NULL)
    616  1.1.1.1.4.2  rmind 			panic("nfsm trim leading2");
    617  1.1.1.1.4.2  rmind 		mbuf_setnext(n, NULL);
    618  1.1.1.1.4.2  rmind 		mbuf_freem(n);
    619  1.1.1.1.4.2  rmind 	} else if (offs > 0) {
    620  1.1.1.1.4.2  rmind 		mbuf_setlen(m, mbuf_len(m) - offs);
    621  1.1.1.1.4.2  rmind 		NFSM_DATAP(m, offs);
    622  1.1.1.1.4.2  rmind 	} else if (offs < 0)
    623  1.1.1.1.4.2  rmind 		panic("nfsm trimleading offs");
    624  1.1.1.1.4.2  rmind 	nd->nd_mrep = m;
    625  1.1.1.1.4.2  rmind 	nd->nd_md = m;
    626  1.1.1.1.4.2  rmind 	nd->nd_dpos = NFSMTOD(m, caddr_t);
    627  1.1.1.1.4.2  rmind }
    628  1.1.1.1.4.2  rmind 
    629  1.1.1.1.4.2  rmind /*
    630  1.1.1.1.4.2  rmind  * Trim trailing data off the mbuf list being built.
    631  1.1.1.1.4.2  rmind  */
    632  1.1.1.1.4.2  rmind APPLESTATIC void
    633  1.1.1.1.4.2  rmind newnfs_trimtrailing(nd, mb, bpos)
    634  1.1.1.1.4.2  rmind 	struct nfsrv_descript *nd;
    635  1.1.1.1.4.2  rmind 	mbuf_t mb;
    636  1.1.1.1.4.2  rmind 	caddr_t bpos;
    637  1.1.1.1.4.2  rmind {
    638  1.1.1.1.4.2  rmind 
    639  1.1.1.1.4.2  rmind 	if (mbuf_next(mb)) {
    640  1.1.1.1.4.2  rmind 		mbuf_freem(mbuf_next(mb));
    641  1.1.1.1.4.2  rmind 		mbuf_setnext(mb, NULL);
    642  1.1.1.1.4.2  rmind 	}
    643  1.1.1.1.4.2  rmind 	mbuf_setlen(mb, bpos - NFSMTOD(mb, caddr_t));
    644  1.1.1.1.4.2  rmind 	nd->nd_mb = mb;
    645  1.1.1.1.4.2  rmind 	nd->nd_bpos = bpos;
    646  1.1.1.1.4.2  rmind }
    647  1.1.1.1.4.2  rmind 
    648  1.1.1.1.4.2  rmind /*
    649  1.1.1.1.4.2  rmind  * Dissect a file handle on the client.
    650  1.1.1.1.4.2  rmind  */
    651  1.1.1.1.4.2  rmind APPLESTATIC int
    652  1.1.1.1.4.2  rmind nfsm_getfh(struct nfsrv_descript *nd, struct nfsfh **nfhpp)
    653  1.1.1.1.4.2  rmind {
    654  1.1.1.1.4.2  rmind 	u_int32_t *tl;
    655  1.1.1.1.4.2  rmind 	struct nfsfh *nfhp;
    656  1.1.1.1.4.2  rmind 	int error, len;
    657  1.1.1.1.4.2  rmind 
    658  1.1.1.1.4.2  rmind 	*nfhpp = NULL;
    659  1.1.1.1.4.2  rmind 	if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
    660  1.1.1.1.4.2  rmind 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    661  1.1.1.1.4.2  rmind 		if ((len = fxdr_unsigned(int, *tl)) <= 0 ||
    662  1.1.1.1.4.2  rmind 			len > NFSX_FHMAX) {
    663  1.1.1.1.4.2  rmind 			error = EBADRPC;
    664  1.1.1.1.4.2  rmind 			goto nfsmout;
    665  1.1.1.1.4.2  rmind 		}
    666  1.1.1.1.4.2  rmind 	} else
    667  1.1.1.1.4.2  rmind 		len = NFSX_V2FH;
    668  1.1.1.1.4.2  rmind 	MALLOC(nfhp, struct nfsfh *, sizeof (struct nfsfh) + len,
    669  1.1.1.1.4.2  rmind 	    M_NFSFH, M_WAITOK);
    670  1.1.1.1.4.2  rmind 	error = nfsrv_mtostr(nd, nfhp->nfh_fh, len);
    671  1.1.1.1.4.2  rmind 	if (error) {
    672  1.1.1.1.4.2  rmind 		FREE((caddr_t)nfhp, M_NFSFH);
    673  1.1.1.1.4.2  rmind 		goto nfsmout;
    674  1.1.1.1.4.2  rmind 	}
    675  1.1.1.1.4.2  rmind 	nfhp->nfh_len = len;
    676  1.1.1.1.4.2  rmind 	*nfhpp = nfhp;
    677  1.1.1.1.4.2  rmind nfsmout:
    678  1.1.1.1.4.2  rmind 	NFSEXITCODE2(error, nd);
    679  1.1.1.1.4.2  rmind 	return (error);
    680  1.1.1.1.4.2  rmind }
    681  1.1.1.1.4.2  rmind 
    682  1.1.1.1.4.2  rmind /*
    683  1.1.1.1.4.2  rmind  * Break down the nfsv4 acl.
    684  1.1.1.1.4.2  rmind  * If the aclp == NULL or won't fit in an acl, just discard the acl info.
    685  1.1.1.1.4.2  rmind  */
    686  1.1.1.1.4.2  rmind APPLESTATIC int
    687  1.1.1.1.4.2  rmind nfsrv_dissectacl(struct nfsrv_descript *nd, NFSACL_T *aclp, int *aclerrp,
    688  1.1.1.1.4.2  rmind     int *aclsizep, __unused NFSPROC_T *p)
    689  1.1.1.1.4.2  rmind {
    690  1.1.1.1.4.2  rmind 	u_int32_t *tl;
    691  1.1.1.1.4.2  rmind 	int i, aclsize;
    692  1.1.1.1.4.2  rmind 	int acecnt, error = 0, aceerr = 0, acesize;
    693  1.1.1.1.4.2  rmind 
    694  1.1.1.1.4.2  rmind 	*aclerrp = 0;
    695  1.1.1.1.4.2  rmind 	if (aclp)
    696  1.1.1.1.4.2  rmind 		aclp->acl_cnt = 0;
    697  1.1.1.1.4.2  rmind 	/*
    698  1.1.1.1.4.2  rmind 	 * Parse out the ace entries and expect them to conform to
    699  1.1.1.1.4.2  rmind 	 * what can be supported by R/W/X bits.
    700  1.1.1.1.4.2  rmind 	 */
    701  1.1.1.1.4.2  rmind 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    702  1.1.1.1.4.2  rmind 	aclsize = NFSX_UNSIGNED;
    703  1.1.1.1.4.2  rmind 	acecnt = fxdr_unsigned(int, *tl);
    704  1.1.1.1.4.2  rmind 	if (acecnt > ACL_MAX_ENTRIES)
    705  1.1.1.1.4.2  rmind 		aceerr = NFSERR_ATTRNOTSUPP;
    706  1.1.1.1.4.2  rmind 	if (nfsrv_useacl == 0)
    707  1.1.1.1.4.2  rmind 		aceerr = NFSERR_ATTRNOTSUPP;
    708  1.1.1.1.4.2  rmind 	for (i = 0; i < acecnt; i++) {
    709  1.1.1.1.4.2  rmind 		if (aclp && !aceerr)
    710  1.1.1.1.4.2  rmind 			error = nfsrv_dissectace(nd, &aclp->acl_entry[i],
    711  1.1.1.1.4.2  rmind 			    &aceerr, &acesize, p);
    712  1.1.1.1.4.2  rmind 		else
    713  1.1.1.1.4.2  rmind 			error = nfsrv_skipace(nd, &acesize);
    714  1.1.1.1.4.2  rmind 		if (error)
    715  1.1.1.1.4.2  rmind 			goto nfsmout;
    716  1.1.1.1.4.2  rmind 		aclsize += acesize;
    717  1.1.1.1.4.2  rmind 	}
    718  1.1.1.1.4.2  rmind 	if (aclp && !aceerr)
    719  1.1.1.1.4.2  rmind 		aclp->acl_cnt = acecnt;
    720  1.1.1.1.4.2  rmind 	if (aceerr)
    721  1.1.1.1.4.2  rmind 		*aclerrp = aceerr;
    722  1.1.1.1.4.2  rmind 	if (aclsizep)
    723  1.1.1.1.4.2  rmind 		*aclsizep = aclsize;
    724  1.1.1.1.4.2  rmind nfsmout:
    725  1.1.1.1.4.2  rmind 	NFSEXITCODE2(error, nd);
    726  1.1.1.1.4.2  rmind 	return (error);
    727  1.1.1.1.4.2  rmind }
    728  1.1.1.1.4.2  rmind 
    729  1.1.1.1.4.2  rmind /*
    730  1.1.1.1.4.2  rmind  * Skip over an NFSv4 ace entry. Just dissect the xdr and discard it.
    731  1.1.1.1.4.2  rmind  */
    732  1.1.1.1.4.2  rmind static int
    733  1.1.1.1.4.2  rmind nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep)
    734  1.1.1.1.4.2  rmind {
    735  1.1.1.1.4.2  rmind 	u_int32_t *tl;
    736  1.1.1.1.4.2  rmind 	int error, len = 0;
    737  1.1.1.1.4.2  rmind 
    738  1.1.1.1.4.2  rmind 	NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
    739  1.1.1.1.4.2  rmind 	len = fxdr_unsigned(int, *(tl + 3));
    740  1.1.1.1.4.2  rmind 	error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
    741  1.1.1.1.4.2  rmind nfsmout:
    742  1.1.1.1.4.2  rmind 	*acesizep = NFSM_RNDUP(len) + (4 * NFSX_UNSIGNED);
    743  1.1.1.1.4.2  rmind 	NFSEXITCODE2(error, nd);
    744  1.1.1.1.4.2  rmind 	return (error);
    745  1.1.1.1.4.2  rmind }
    746  1.1.1.1.4.2  rmind 
    747  1.1.1.1.4.2  rmind /*
    748  1.1.1.1.4.2  rmind  * Get attribute bits from an mbuf list.
    749  1.1.1.1.4.2  rmind  * Returns EBADRPC for a parsing error, 0 otherwise.
    750  1.1.1.1.4.2  rmind  * If the clearinvalid flag is set, clear the bits not supported.
    751  1.1.1.1.4.2  rmind  */
    752  1.1.1.1.4.2  rmind APPLESTATIC int
    753  1.1.1.1.4.2  rmind nfsrv_getattrbits(struct nfsrv_descript *nd, nfsattrbit_t *attrbitp, int *cntp,
    754  1.1.1.1.4.2  rmind     int *retnotsupp)
    755  1.1.1.1.4.2  rmind {
    756  1.1.1.1.4.2  rmind 	u_int32_t *tl;
    757  1.1.1.1.4.2  rmind 	int cnt, i, outcnt;
    758  1.1.1.1.4.2  rmind 	int error = 0;
    759  1.1.1.1.4.2  rmind 
    760  1.1.1.1.4.2  rmind 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    761  1.1.1.1.4.2  rmind 	cnt = fxdr_unsigned(int, *tl);
    762  1.1.1.1.4.2  rmind 	if (cnt < 0) {
    763  1.1.1.1.4.2  rmind 		error = NFSERR_BADXDR;
    764  1.1.1.1.4.2  rmind 		goto nfsmout;
    765  1.1.1.1.4.2  rmind 	}
    766  1.1.1.1.4.2  rmind 	if (cnt > NFSATTRBIT_MAXWORDS)
    767  1.1.1.1.4.2  rmind 		outcnt = NFSATTRBIT_MAXWORDS;
    768  1.1.1.1.4.2  rmind 	else
    769  1.1.1.1.4.2  rmind 		outcnt = cnt;
    770  1.1.1.1.4.2  rmind 	NFSZERO_ATTRBIT(attrbitp);
    771  1.1.1.1.4.2  rmind 	if (outcnt > 0) {
    772  1.1.1.1.4.2  rmind 		NFSM_DISSECT(tl, u_int32_t *, outcnt * NFSX_UNSIGNED);
    773  1.1.1.1.4.2  rmind 		for (i = 0; i < outcnt; i++)
    774  1.1.1.1.4.2  rmind 			attrbitp->bits[i] = fxdr_unsigned(u_int32_t, *tl++);
    775  1.1.1.1.4.2  rmind 	}
    776  1.1.1.1.4.2  rmind 	for (i = 0; i < (cnt - outcnt); i++) {
    777  1.1.1.1.4.2  rmind 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    778  1.1.1.1.4.2  rmind 		if (retnotsupp != NULL && *tl != 0)
    779  1.1.1.1.4.2  rmind 			*retnotsupp = NFSERR_ATTRNOTSUPP;
    780  1.1.1.1.4.2  rmind 	}
    781  1.1.1.1.4.2  rmind 	if (cntp)
    782  1.1.1.1.4.2  rmind 		*cntp = NFSX_UNSIGNED + (cnt * NFSX_UNSIGNED);
    783  1.1.1.1.4.2  rmind nfsmout:
    784  1.1.1.1.4.2  rmind 	NFSEXITCODE2(error, nd);
    785  1.1.1.1.4.2  rmind 	return (error);
    786  1.1.1.1.4.2  rmind }
    787  1.1.1.1.4.2  rmind 
    788  1.1.1.1.4.2  rmind /*
    789  1.1.1.1.4.2  rmind  * Get the attributes for V4.
    790  1.1.1.1.4.2  rmind  * If the compare flag is true, test for any attribute changes,
    791  1.1.1.1.4.2  rmind  * otherwise return the attribute values.
    792  1.1.1.1.4.2  rmind  * These attributes cover fields in "struct vattr", "struct statfs",
    793  1.1.1.1.4.2  rmind  * "struct nfsfsinfo", the file handle and the lease duration.
    794  1.1.1.1.4.2  rmind  * The value of retcmpp is set to 1 if all attributes are the same,
    795  1.1.1.1.4.2  rmind  * and 0 otherwise.
    796  1.1.1.1.4.2  rmind  * Returns EBADRPC if it can't be parsed, 0 otherwise.
    797  1.1.1.1.4.2  rmind  */
    798  1.1.1.1.4.2  rmind APPLESTATIC int
    799  1.1.1.1.4.2  rmind nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
    800  1.1.1.1.4.2  rmind     struct nfsvattr *nap, struct nfsfh **nfhpp, fhandle_t *fhp, int fhsize,
    801  1.1.1.1.4.2  rmind     struct nfsv3_pathconf *pc, struct statfs *sbp, struct nfsstatfs *sfp,
    802  1.1.1.1.4.2  rmind     struct nfsfsinfo *fsp, NFSACL_T *aclp, int compare, int *retcmpp,
    803  1.1.1.1.4.2  rmind     u_int32_t *leasep, u_int32_t *rderrp, NFSPROC_T *p, struct ucred *cred)
    804  1.1.1.1.4.2  rmind {
    805  1.1.1.1.4.2  rmind 	u_int32_t *tl;
    806  1.1.1.1.4.2  rmind 	int i = 0, j, k, l = 0, m, bitpos, attrsum = 0;
    807  1.1.1.1.4.2  rmind 	int error, tfhsize, aceerr, attrsize, cnt, retnotsup;
    808  1.1.1.1.4.2  rmind 	u_char *cp, *cp2, namestr[NFSV4_SMALLSTR + 1];
    809  1.1.1.1.4.2  rmind 	nfsattrbit_t attrbits, retattrbits, checkattrbits;
    810  1.1.1.1.4.2  rmind 	struct nfsfh *tnfhp;
    811  1.1.1.1.4.2  rmind 	struct nfsreferral *refp;
    812  1.1.1.1.4.2  rmind 	u_quad_t tquad;
    813  1.1.1.1.4.2  rmind 	nfsquad_t tnfsquad;
    814  1.1.1.1.4.2  rmind 	struct timespec temptime;
    815  1.1.1.1.4.2  rmind 	uid_t uid;
    816  1.1.1.1.4.2  rmind 	gid_t gid;
    817  1.1.1.1.4.2  rmind 	long fid;
    818  1.1.1.1.4.2  rmind 	u_int32_t freenum = 0, tuint;
    819  1.1.1.1.4.2  rmind 	u_int64_t uquad = 0, thyp, thyp2;
    820  1.1.1.1.4.2  rmind #ifdef QUOTA
    821  1.1.1.1.4.2  rmind 	struct dqblk dqb;
    822  1.1.1.1.4.2  rmind 	uid_t savuid;
    823  1.1.1.1.4.2  rmind #endif
    824  1.1.1.1.4.2  rmind 
    825  1.1.1.1.4.2  rmind 	if (compare) {
    826  1.1.1.1.4.2  rmind 		retnotsup = 0;
    827  1.1.1.1.4.2  rmind 		error = nfsrv_getattrbits(nd, &attrbits, NULL, &retnotsup);
    828  1.1.1.1.4.2  rmind 	} else {
    829  1.1.1.1.4.2  rmind 		error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
    830  1.1.1.1.4.2  rmind 	}
    831  1.1.1.1.4.2  rmind 	if (error)
    832  1.1.1.1.4.2  rmind 		goto nfsmout;
    833  1.1.1.1.4.2  rmind 
    834  1.1.1.1.4.2  rmind 	if (compare) {
    835  1.1.1.1.4.2  rmind 		*retcmpp = retnotsup;
    836  1.1.1.1.4.2  rmind 	} else {
    837  1.1.1.1.4.2  rmind 		/*
    838  1.1.1.1.4.2  rmind 		 * Just set default values to some of the important ones.
    839  1.1.1.1.4.2  rmind 		 */
    840  1.1.1.1.4.2  rmind 		if (nap != NULL) {
    841  1.1.1.1.4.2  rmind 			nap->na_type = VREG;
    842  1.1.1.1.4.2  rmind 			nap->na_mode = 0;
    843  1.1.1.1.4.2  rmind 			nap->na_rdev = (NFSDEV_T)0;
    844  1.1.1.1.4.2  rmind 			nap->na_mtime.tv_sec = 0;
    845  1.1.1.1.4.2  rmind 			nap->na_mtime.tv_nsec = 0;
    846  1.1.1.1.4.2  rmind 			nap->na_gen = 0;
    847  1.1.1.1.4.2  rmind 			nap->na_flags = 0;
    848  1.1.1.1.4.2  rmind 			nap->na_blocksize = NFS_FABLKSIZE;
    849  1.1.1.1.4.2  rmind 		}
    850  1.1.1.1.4.2  rmind 		if (sbp != NULL) {
    851  1.1.1.1.4.2  rmind 			sbp->f_bsize = NFS_FABLKSIZE;
    852  1.1.1.1.4.2  rmind 			sbp->f_blocks = 0;
    853  1.1.1.1.4.2  rmind 			sbp->f_bfree = 0;
    854  1.1.1.1.4.2  rmind 			sbp->f_bavail = 0;
    855  1.1.1.1.4.2  rmind 			sbp->f_files = 0;
    856  1.1.1.1.4.2  rmind 			sbp->f_ffree = 0;
    857  1.1.1.1.4.2  rmind 		}
    858  1.1.1.1.4.2  rmind 		if (fsp != NULL) {
    859  1.1.1.1.4.2  rmind 			fsp->fs_rtmax = 8192;
    860  1.1.1.1.4.2  rmind 			fsp->fs_rtpref = 8192;
    861  1.1.1.1.4.2  rmind 			fsp->fs_maxname = NFS_MAXNAMLEN;
    862  1.1.1.1.4.2  rmind 			fsp->fs_wtmax = 8192;
    863  1.1.1.1.4.2  rmind 			fsp->fs_wtpref = 8192;
    864  1.1.1.1.4.2  rmind 			fsp->fs_wtmult = NFS_FABLKSIZE;
    865  1.1.1.1.4.2  rmind 			fsp->fs_dtpref = 8192;
    866  1.1.1.1.4.2  rmind 			fsp->fs_maxfilesize = 0xffffffffffffffffull;
    867  1.1.1.1.4.2  rmind 			fsp->fs_timedelta.tv_sec = 0;
    868  1.1.1.1.4.2  rmind 			fsp->fs_timedelta.tv_nsec = 1;
    869  1.1.1.1.4.2  rmind 			fsp->fs_properties = (NFSV3_FSFLINK | NFSV3_FSFSYMLINK |
    870  1.1.1.1.4.2  rmind 				NFSV3_FSFHOMOGENEOUS | NFSV3_FSFCANSETTIME);
    871  1.1.1.1.4.2  rmind 		}
    872  1.1.1.1.4.2  rmind 		if (pc != NULL) {
    873  1.1.1.1.4.2  rmind 			pc->pc_linkmax = LINK_MAX;
    874  1.1.1.1.4.2  rmind 			pc->pc_namemax = NAME_MAX;
    875  1.1.1.1.4.2  rmind 			pc->pc_notrunc = 0;
    876  1.1.1.1.4.2  rmind 			pc->pc_chownrestricted = 0;
    877  1.1.1.1.4.2  rmind 			pc->pc_caseinsensitive = 0;
    878  1.1.1.1.4.2  rmind 			pc->pc_casepreserving = 1;
    879  1.1.1.1.4.2  rmind 		}
    880  1.1.1.1.4.2  rmind 	}
    881  1.1.1.1.4.2  rmind 
    882  1.1.1.1.4.2  rmind 	/*
    883  1.1.1.1.4.2  rmind 	 * Loop around getting the attributes.
    884  1.1.1.1.4.2  rmind 	 */
    885  1.1.1.1.4.2  rmind 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    886  1.1.1.1.4.2  rmind 	attrsize = fxdr_unsigned(int, *tl);
    887  1.1.1.1.4.2  rmind 	for (bitpos = 0; bitpos < NFSATTRBIT_MAX; bitpos++) {
    888  1.1.1.1.4.2  rmind 	    if (attrsum > attrsize) {
    889  1.1.1.1.4.2  rmind 		error = NFSERR_BADXDR;
    890  1.1.1.1.4.2  rmind 		goto nfsmout;
    891  1.1.1.1.4.2  rmind 	    }
    892  1.1.1.1.4.2  rmind 	    if (NFSISSET_ATTRBIT(&attrbits, bitpos))
    893  1.1.1.1.4.2  rmind 		switch (bitpos) {
    894  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SUPPORTEDATTRS:
    895  1.1.1.1.4.2  rmind 			retnotsup = 0;
    896  1.1.1.1.4.2  rmind 			if (compare || nap == NULL)
    897  1.1.1.1.4.2  rmind 			    error = nfsrv_getattrbits(nd, &retattrbits,
    898  1.1.1.1.4.2  rmind 				&cnt, &retnotsup);
    899  1.1.1.1.4.2  rmind 			else
    900  1.1.1.1.4.2  rmind 			    error = nfsrv_getattrbits(nd, &nap->na_suppattr,
    901  1.1.1.1.4.2  rmind 				&cnt, &retnotsup);
    902  1.1.1.1.4.2  rmind 			if (error)
    903  1.1.1.1.4.2  rmind 			    goto nfsmout;
    904  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp)) {
    905  1.1.1.1.4.2  rmind 			   NFSSETSUPP_ATTRBIT(&checkattrbits);
    906  1.1.1.1.4.2  rmind 			   if (!NFSEQUAL_ATTRBIT(&retattrbits, &checkattrbits)
    907  1.1.1.1.4.2  rmind 			       || retnotsup)
    908  1.1.1.1.4.2  rmind 				*retcmpp = NFSERR_NOTSAME;
    909  1.1.1.1.4.2  rmind 			}
    910  1.1.1.1.4.2  rmind 			attrsum += cnt;
    911  1.1.1.1.4.2  rmind 			break;
    912  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TYPE:
    913  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    914  1.1.1.1.4.2  rmind 			if (compare) {
    915  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
    916  1.1.1.1.4.2  rmind 				    if (nap->na_type != nfsv34tov_type(*tl))
    917  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
    918  1.1.1.1.4.2  rmind 				}
    919  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
    920  1.1.1.1.4.2  rmind 				nap->na_type = nfsv34tov_type(*tl);
    921  1.1.1.1.4.2  rmind 			}
    922  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
    923  1.1.1.1.4.2  rmind 			break;
    924  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FHEXPIRETYPE:
    925  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    926  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp)) {
    927  1.1.1.1.4.2  rmind 				if (fxdr_unsigned(int, *tl) !=
    928  1.1.1.1.4.2  rmind 					NFSV4FHTYPE_PERSISTENT)
    929  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
    930  1.1.1.1.4.2  rmind 			}
    931  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
    932  1.1.1.1.4.2  rmind 			break;
    933  1.1.1.1.4.2  rmind 		case NFSATTRBIT_CHANGE:
    934  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
    935  1.1.1.1.4.2  rmind 			if (compare) {
    936  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
    937  1.1.1.1.4.2  rmind 				    if (nap->na_filerev != fxdr_hyper(tl))
    938  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
    939  1.1.1.1.4.2  rmind 				}
    940  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
    941  1.1.1.1.4.2  rmind 				nap->na_filerev = fxdr_hyper(tl);
    942  1.1.1.1.4.2  rmind 			}
    943  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
    944  1.1.1.1.4.2  rmind 			break;
    945  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SIZE:
    946  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
    947  1.1.1.1.4.2  rmind 			if (compare) {
    948  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
    949  1.1.1.1.4.2  rmind 				    if (nap->na_size != fxdr_hyper(tl))
    950  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
    951  1.1.1.1.4.2  rmind 				}
    952  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
    953  1.1.1.1.4.2  rmind 				nap->na_size = fxdr_hyper(tl);
    954  1.1.1.1.4.2  rmind 			}
    955  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
    956  1.1.1.1.4.2  rmind 			break;
    957  1.1.1.1.4.2  rmind 		case NFSATTRBIT_LINKSUPPORT:
    958  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    959  1.1.1.1.4.2  rmind 			if (compare) {
    960  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
    961  1.1.1.1.4.2  rmind 				    if (fsp->fs_properties & NFSV3_FSFLINK) {
    962  1.1.1.1.4.2  rmind 					if (*tl == newnfs_false)
    963  1.1.1.1.4.2  rmind 						*retcmpp = NFSERR_NOTSAME;
    964  1.1.1.1.4.2  rmind 				    } else {
    965  1.1.1.1.4.2  rmind 					if (*tl == newnfs_true)
    966  1.1.1.1.4.2  rmind 						*retcmpp = NFSERR_NOTSAME;
    967  1.1.1.1.4.2  rmind 				    }
    968  1.1.1.1.4.2  rmind 				}
    969  1.1.1.1.4.2  rmind 			} else if (fsp != NULL) {
    970  1.1.1.1.4.2  rmind 				if (*tl == newnfs_true)
    971  1.1.1.1.4.2  rmind 					fsp->fs_properties |= NFSV3_FSFLINK;
    972  1.1.1.1.4.2  rmind 				else
    973  1.1.1.1.4.2  rmind 					fsp->fs_properties &= ~NFSV3_FSFLINK;
    974  1.1.1.1.4.2  rmind 			}
    975  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
    976  1.1.1.1.4.2  rmind 			break;
    977  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SYMLINKSUPPORT:
    978  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    979  1.1.1.1.4.2  rmind 			if (compare) {
    980  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
    981  1.1.1.1.4.2  rmind 				    if (fsp->fs_properties & NFSV3_FSFSYMLINK) {
    982  1.1.1.1.4.2  rmind 					if (*tl == newnfs_false)
    983  1.1.1.1.4.2  rmind 						*retcmpp = NFSERR_NOTSAME;
    984  1.1.1.1.4.2  rmind 				    } else {
    985  1.1.1.1.4.2  rmind 					if (*tl == newnfs_true)
    986  1.1.1.1.4.2  rmind 						*retcmpp = NFSERR_NOTSAME;
    987  1.1.1.1.4.2  rmind 				    }
    988  1.1.1.1.4.2  rmind 				}
    989  1.1.1.1.4.2  rmind 			} else if (fsp != NULL) {
    990  1.1.1.1.4.2  rmind 				if (*tl == newnfs_true)
    991  1.1.1.1.4.2  rmind 					fsp->fs_properties |= NFSV3_FSFSYMLINK;
    992  1.1.1.1.4.2  rmind 				else
    993  1.1.1.1.4.2  rmind 					fsp->fs_properties &= ~NFSV3_FSFSYMLINK;
    994  1.1.1.1.4.2  rmind 			}
    995  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
    996  1.1.1.1.4.2  rmind 			break;
    997  1.1.1.1.4.2  rmind 		case NFSATTRBIT_NAMEDATTR:
    998  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    999  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp)) {
   1000  1.1.1.1.4.2  rmind 				if (*tl != newnfs_false)
   1001  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1002  1.1.1.1.4.2  rmind 			}
   1003  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1004  1.1.1.1.4.2  rmind 			break;
   1005  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FSID:
   1006  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
   1007  1.1.1.1.4.2  rmind 			thyp = fxdr_hyper(tl);
   1008  1.1.1.1.4.2  rmind 			tl += 2;
   1009  1.1.1.1.4.2  rmind 			thyp2 = fxdr_hyper(tl);
   1010  1.1.1.1.4.2  rmind 			if (compare) {
   1011  1.1.1.1.4.2  rmind 			    if (*retcmpp == 0) {
   1012  1.1.1.1.4.2  rmind 				if (thyp != (u_int64_t)
   1013  1.1.1.1.4.2  rmind 				    vfs_statfs(vnode_mount(vp))->f_fsid.val[0] ||
   1014  1.1.1.1.4.2  rmind 				    thyp2 != (u_int64_t)
   1015  1.1.1.1.4.2  rmind 				    vfs_statfs(vnode_mount(vp))->f_fsid.val[1])
   1016  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1017  1.1.1.1.4.2  rmind 			    }
   1018  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
   1019  1.1.1.1.4.2  rmind 				nap->na_filesid[0] = thyp;
   1020  1.1.1.1.4.2  rmind 				nap->na_filesid[1] = thyp2;
   1021  1.1.1.1.4.2  rmind 			}
   1022  1.1.1.1.4.2  rmind 			attrsum += (4 * NFSX_UNSIGNED);
   1023  1.1.1.1.4.2  rmind 			break;
   1024  1.1.1.1.4.2  rmind 		case NFSATTRBIT_UNIQUEHANDLES:
   1025  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1026  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp)) {
   1027  1.1.1.1.4.2  rmind 				if (*tl != newnfs_true)
   1028  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1029  1.1.1.1.4.2  rmind 			}
   1030  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1031  1.1.1.1.4.2  rmind 			break;
   1032  1.1.1.1.4.2  rmind 		case NFSATTRBIT_LEASETIME:
   1033  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1034  1.1.1.1.4.2  rmind 			if (compare) {
   1035  1.1.1.1.4.2  rmind 				if (fxdr_unsigned(int, *tl) != nfsrv_lease &&
   1036  1.1.1.1.4.2  rmind 				    !(*retcmpp))
   1037  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1038  1.1.1.1.4.2  rmind 			} else if (leasep != NULL) {
   1039  1.1.1.1.4.2  rmind 				*leasep = fxdr_unsigned(u_int32_t, *tl);
   1040  1.1.1.1.4.2  rmind 			}
   1041  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1042  1.1.1.1.4.2  rmind 			break;
   1043  1.1.1.1.4.2  rmind 		case NFSATTRBIT_RDATTRERROR:
   1044  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1045  1.1.1.1.4.2  rmind 			if (compare) {
   1046  1.1.1.1.4.2  rmind 				 if (!(*retcmpp))
   1047  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_INVAL;
   1048  1.1.1.1.4.2  rmind 			} else if (rderrp != NULL) {
   1049  1.1.1.1.4.2  rmind 				*rderrp = fxdr_unsigned(u_int32_t, *tl);
   1050  1.1.1.1.4.2  rmind 			}
   1051  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1052  1.1.1.1.4.2  rmind 			break;
   1053  1.1.1.1.4.2  rmind 		case NFSATTRBIT_ACL:
   1054  1.1.1.1.4.2  rmind 			if (compare) {
   1055  1.1.1.1.4.2  rmind 			  if (!(*retcmpp)) {
   1056  1.1.1.1.4.2  rmind 			    if (nfsrv_useacl) {
   1057  1.1.1.1.4.2  rmind 				NFSACL_T *naclp;
   1058  1.1.1.1.4.2  rmind 
   1059  1.1.1.1.4.2  rmind 				naclp = acl_alloc(M_WAITOK);
   1060  1.1.1.1.4.2  rmind 				error = nfsrv_dissectacl(nd, naclp, &aceerr,
   1061  1.1.1.1.4.2  rmind 				    &cnt, p);
   1062  1.1.1.1.4.2  rmind 				if (error) {
   1063  1.1.1.1.4.2  rmind 				    acl_free(naclp);
   1064  1.1.1.1.4.2  rmind 				    goto nfsmout;
   1065  1.1.1.1.4.2  rmind 				}
   1066  1.1.1.1.4.2  rmind 				if (aceerr || aclp == NULL ||
   1067  1.1.1.1.4.2  rmind 				    nfsrv_compareacl(aclp, naclp))
   1068  1.1.1.1.4.2  rmind 				    *retcmpp = NFSERR_NOTSAME;
   1069  1.1.1.1.4.2  rmind 				acl_free(naclp);
   1070  1.1.1.1.4.2  rmind 			    } else {
   1071  1.1.1.1.4.2  rmind 				error = nfsrv_dissectacl(nd, NULL, &aceerr,
   1072  1.1.1.1.4.2  rmind 				    &cnt, p);
   1073  1.1.1.1.4.2  rmind 				*retcmpp = NFSERR_ATTRNOTSUPP;
   1074  1.1.1.1.4.2  rmind 			    }
   1075  1.1.1.1.4.2  rmind 			  }
   1076  1.1.1.1.4.2  rmind 			} else {
   1077  1.1.1.1.4.2  rmind 			    if (vp != NULL && aclp != NULL)
   1078  1.1.1.1.4.2  rmind 				error = nfsrv_dissectacl(nd, aclp, &aceerr,
   1079  1.1.1.1.4.2  rmind 				    &cnt, p);
   1080  1.1.1.1.4.2  rmind 			    else
   1081  1.1.1.1.4.2  rmind 				error = nfsrv_dissectacl(nd, NULL, &aceerr,
   1082  1.1.1.1.4.2  rmind 				    &cnt, p);
   1083  1.1.1.1.4.2  rmind 			    if (error)
   1084  1.1.1.1.4.2  rmind 				goto nfsmout;
   1085  1.1.1.1.4.2  rmind 			}
   1086  1.1.1.1.4.2  rmind 			attrsum += cnt;
   1087  1.1.1.1.4.2  rmind 			break;
   1088  1.1.1.1.4.2  rmind 		case NFSATTRBIT_ACLSUPPORT:
   1089  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1090  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp)) {
   1091  1.1.1.1.4.2  rmind 				if (nfsrv_useacl) {
   1092  1.1.1.1.4.2  rmind 					if (fxdr_unsigned(u_int32_t, *tl) !=
   1093  1.1.1.1.4.2  rmind 					    NFSV4ACE_SUPTYPES)
   1094  1.1.1.1.4.2  rmind 						*retcmpp = NFSERR_NOTSAME;
   1095  1.1.1.1.4.2  rmind 				} else {
   1096  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_ATTRNOTSUPP;
   1097  1.1.1.1.4.2  rmind 				}
   1098  1.1.1.1.4.2  rmind 			}
   1099  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1100  1.1.1.1.4.2  rmind 			break;
   1101  1.1.1.1.4.2  rmind 		case NFSATTRBIT_ARCHIVE:
   1102  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1103  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp))
   1104  1.1.1.1.4.2  rmind 				*retcmpp = NFSERR_ATTRNOTSUPP;
   1105  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1106  1.1.1.1.4.2  rmind 			break;
   1107  1.1.1.1.4.2  rmind 		case NFSATTRBIT_CANSETTIME:
   1108  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1109  1.1.1.1.4.2  rmind 			if (compare) {
   1110  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
   1111  1.1.1.1.4.2  rmind 				    if (fsp->fs_properties & NFSV3_FSFCANSETTIME) {
   1112  1.1.1.1.4.2  rmind 					if (*tl == newnfs_false)
   1113  1.1.1.1.4.2  rmind 						*retcmpp = NFSERR_NOTSAME;
   1114  1.1.1.1.4.2  rmind 				    } else {
   1115  1.1.1.1.4.2  rmind 					if (*tl == newnfs_true)
   1116  1.1.1.1.4.2  rmind 						*retcmpp = NFSERR_NOTSAME;
   1117  1.1.1.1.4.2  rmind 				    }
   1118  1.1.1.1.4.2  rmind 				}
   1119  1.1.1.1.4.2  rmind 			} else if (fsp != NULL) {
   1120  1.1.1.1.4.2  rmind 				if (*tl == newnfs_true)
   1121  1.1.1.1.4.2  rmind 					fsp->fs_properties |= NFSV3_FSFCANSETTIME;
   1122  1.1.1.1.4.2  rmind 				else
   1123  1.1.1.1.4.2  rmind 					fsp->fs_properties &= ~NFSV3_FSFCANSETTIME;
   1124  1.1.1.1.4.2  rmind 			}
   1125  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1126  1.1.1.1.4.2  rmind 			break;
   1127  1.1.1.1.4.2  rmind 		case NFSATTRBIT_CASEINSENSITIVE:
   1128  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1129  1.1.1.1.4.2  rmind 			if (compare) {
   1130  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
   1131  1.1.1.1.4.2  rmind 				    if (*tl != newnfs_false)
   1132  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1133  1.1.1.1.4.2  rmind 				}
   1134  1.1.1.1.4.2  rmind 			} else if (pc != NULL) {
   1135  1.1.1.1.4.2  rmind 				pc->pc_caseinsensitive =
   1136  1.1.1.1.4.2  rmind 				    fxdr_unsigned(u_int32_t, *tl);
   1137  1.1.1.1.4.2  rmind 			}
   1138  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1139  1.1.1.1.4.2  rmind 			break;
   1140  1.1.1.1.4.2  rmind 		case NFSATTRBIT_CASEPRESERVING:
   1141  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1142  1.1.1.1.4.2  rmind 			if (compare) {
   1143  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
   1144  1.1.1.1.4.2  rmind 				    if (*tl != newnfs_true)
   1145  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1146  1.1.1.1.4.2  rmind 				}
   1147  1.1.1.1.4.2  rmind 			} else if (pc != NULL) {
   1148  1.1.1.1.4.2  rmind 				pc->pc_casepreserving =
   1149  1.1.1.1.4.2  rmind 				    fxdr_unsigned(u_int32_t, *tl);
   1150  1.1.1.1.4.2  rmind 			}
   1151  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1152  1.1.1.1.4.2  rmind 			break;
   1153  1.1.1.1.4.2  rmind 		case NFSATTRBIT_CHOWNRESTRICTED:
   1154  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1155  1.1.1.1.4.2  rmind 			if (compare) {
   1156  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
   1157  1.1.1.1.4.2  rmind 				    if (*tl != newnfs_true)
   1158  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1159  1.1.1.1.4.2  rmind 				}
   1160  1.1.1.1.4.2  rmind 			} else if (pc != NULL) {
   1161  1.1.1.1.4.2  rmind 				pc->pc_chownrestricted =
   1162  1.1.1.1.4.2  rmind 				    fxdr_unsigned(u_int32_t, *tl);
   1163  1.1.1.1.4.2  rmind 			}
   1164  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1165  1.1.1.1.4.2  rmind 			break;
   1166  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FILEHANDLE:
   1167  1.1.1.1.4.2  rmind 			error = nfsm_getfh(nd, &tnfhp);
   1168  1.1.1.1.4.2  rmind 			if (error)
   1169  1.1.1.1.4.2  rmind 				goto nfsmout;
   1170  1.1.1.1.4.2  rmind 			tfhsize = tnfhp->nfh_len;
   1171  1.1.1.1.4.2  rmind 			if (compare) {
   1172  1.1.1.1.4.2  rmind 				if (!(*retcmpp) &&
   1173  1.1.1.1.4.2  rmind 				    !NFSRV_CMPFH(tnfhp->nfh_fh, tfhsize,
   1174  1.1.1.1.4.2  rmind 				     fhp, fhsize))
   1175  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1176  1.1.1.1.4.2  rmind 				FREE((caddr_t)tnfhp, M_NFSFH);
   1177  1.1.1.1.4.2  rmind 			} else if (nfhpp != NULL) {
   1178  1.1.1.1.4.2  rmind 				*nfhpp = tnfhp;
   1179  1.1.1.1.4.2  rmind 			} else {
   1180  1.1.1.1.4.2  rmind 				FREE((caddr_t)tnfhp, M_NFSFH);
   1181  1.1.1.1.4.2  rmind 			}
   1182  1.1.1.1.4.2  rmind 			attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(tfhsize));
   1183  1.1.1.1.4.2  rmind 			break;
   1184  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FILEID:
   1185  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1186  1.1.1.1.4.2  rmind 			thyp = fxdr_hyper(tl);
   1187  1.1.1.1.4.2  rmind 			if (compare) {
   1188  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
   1189  1.1.1.1.4.2  rmind 				    if ((u_int64_t)nap->na_fileid != thyp)
   1190  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1191  1.1.1.1.4.2  rmind 				}
   1192  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
   1193  1.1.1.1.4.2  rmind 				if (*tl++)
   1194  1.1.1.1.4.2  rmind 					printf("NFSv4 fileid > 32bits\n");
   1195  1.1.1.1.4.2  rmind 				nap->na_fileid = thyp;
   1196  1.1.1.1.4.2  rmind 			}
   1197  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1198  1.1.1.1.4.2  rmind 			break;
   1199  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FILESAVAIL:
   1200  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1201  1.1.1.1.4.2  rmind 			if (compare) {
   1202  1.1.1.1.4.2  rmind 				if (!(*retcmpp) &&
   1203  1.1.1.1.4.2  rmind 				    sfp->sf_afiles != fxdr_hyper(tl))
   1204  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1205  1.1.1.1.4.2  rmind 			} else if (sfp != NULL) {
   1206  1.1.1.1.4.2  rmind 				sfp->sf_afiles = fxdr_hyper(tl);
   1207  1.1.1.1.4.2  rmind 			}
   1208  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1209  1.1.1.1.4.2  rmind 			break;
   1210  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FILESFREE:
   1211  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1212  1.1.1.1.4.2  rmind 			if (compare) {
   1213  1.1.1.1.4.2  rmind 				if (!(*retcmpp) &&
   1214  1.1.1.1.4.2  rmind 				    sfp->sf_ffiles != fxdr_hyper(tl))
   1215  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1216  1.1.1.1.4.2  rmind 			} else if (sfp != NULL) {
   1217  1.1.1.1.4.2  rmind 				sfp->sf_ffiles = fxdr_hyper(tl);
   1218  1.1.1.1.4.2  rmind 			}
   1219  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1220  1.1.1.1.4.2  rmind 			break;
   1221  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FILESTOTAL:
   1222  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1223  1.1.1.1.4.2  rmind 			if (compare) {
   1224  1.1.1.1.4.2  rmind 				if (!(*retcmpp) &&
   1225  1.1.1.1.4.2  rmind 				    sfp->sf_tfiles != fxdr_hyper(tl))
   1226  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1227  1.1.1.1.4.2  rmind 			} else if (sfp != NULL) {
   1228  1.1.1.1.4.2  rmind 				sfp->sf_tfiles = fxdr_hyper(tl);
   1229  1.1.1.1.4.2  rmind 			}
   1230  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1231  1.1.1.1.4.2  rmind 			break;
   1232  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FSLOCATIONS:
   1233  1.1.1.1.4.2  rmind 			error = nfsrv_getrefstr(nd, &cp, &cp2, &l, &m);
   1234  1.1.1.1.4.2  rmind 			if (error)
   1235  1.1.1.1.4.2  rmind 				goto nfsmout;
   1236  1.1.1.1.4.2  rmind 			attrsum += l;
   1237  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp)) {
   1238  1.1.1.1.4.2  rmind 				refp = nfsv4root_getreferral(vp, NULL, 0);
   1239  1.1.1.1.4.2  rmind 				if (refp != NULL) {
   1240  1.1.1.1.4.2  rmind 					if (cp == NULL || cp2 == NULL ||
   1241  1.1.1.1.4.2  rmind 					    strcmp(cp, "/") ||
   1242  1.1.1.1.4.2  rmind 					    strcmp(cp2, refp->nfr_srvlist))
   1243  1.1.1.1.4.2  rmind 						*retcmpp = NFSERR_NOTSAME;
   1244  1.1.1.1.4.2  rmind 				} else if (m == 0) {
   1245  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1246  1.1.1.1.4.2  rmind 				}
   1247  1.1.1.1.4.2  rmind 			}
   1248  1.1.1.1.4.2  rmind 			if (cp != NULL)
   1249  1.1.1.1.4.2  rmind 				free(cp, M_NFSSTRING);
   1250  1.1.1.1.4.2  rmind 			if (cp2 != NULL)
   1251  1.1.1.1.4.2  rmind 				free(cp2, M_NFSSTRING);
   1252  1.1.1.1.4.2  rmind 			break;
   1253  1.1.1.1.4.2  rmind 		case NFSATTRBIT_HIDDEN:
   1254  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1255  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp))
   1256  1.1.1.1.4.2  rmind 				*retcmpp = NFSERR_ATTRNOTSUPP;
   1257  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1258  1.1.1.1.4.2  rmind 			break;
   1259  1.1.1.1.4.2  rmind 		case NFSATTRBIT_HOMOGENEOUS:
   1260  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1261  1.1.1.1.4.2  rmind 			if (compare) {
   1262  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
   1263  1.1.1.1.4.2  rmind 				    if (fsp->fs_properties &
   1264  1.1.1.1.4.2  rmind 					NFSV3_FSFHOMOGENEOUS) {
   1265  1.1.1.1.4.2  rmind 					if (*tl == newnfs_false)
   1266  1.1.1.1.4.2  rmind 						*retcmpp = NFSERR_NOTSAME;
   1267  1.1.1.1.4.2  rmind 				    } else {
   1268  1.1.1.1.4.2  rmind 					if (*tl == newnfs_true)
   1269  1.1.1.1.4.2  rmind 						*retcmpp = NFSERR_NOTSAME;
   1270  1.1.1.1.4.2  rmind 				    }
   1271  1.1.1.1.4.2  rmind 				}
   1272  1.1.1.1.4.2  rmind 			} else if (fsp != NULL) {
   1273  1.1.1.1.4.2  rmind 				if (*tl == newnfs_true)
   1274  1.1.1.1.4.2  rmind 				    fsp->fs_properties |= NFSV3_FSFHOMOGENEOUS;
   1275  1.1.1.1.4.2  rmind 				else
   1276  1.1.1.1.4.2  rmind 				    fsp->fs_properties &= ~NFSV3_FSFHOMOGENEOUS;
   1277  1.1.1.1.4.2  rmind 			}
   1278  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1279  1.1.1.1.4.2  rmind 			break;
   1280  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MAXFILESIZE:
   1281  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1282  1.1.1.1.4.2  rmind 			tnfsquad.qval = fxdr_hyper(tl);
   1283  1.1.1.1.4.2  rmind 			if (compare) {
   1284  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
   1285  1.1.1.1.4.2  rmind 					tquad = NFSRV_MAXFILESIZE;
   1286  1.1.1.1.4.2  rmind 					if (tquad != tnfsquad.qval)
   1287  1.1.1.1.4.2  rmind 						*retcmpp = NFSERR_NOTSAME;
   1288  1.1.1.1.4.2  rmind 				}
   1289  1.1.1.1.4.2  rmind 			} else if (fsp != NULL) {
   1290  1.1.1.1.4.2  rmind 				fsp->fs_maxfilesize = tnfsquad.qval;
   1291  1.1.1.1.4.2  rmind 			}
   1292  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1293  1.1.1.1.4.2  rmind 			break;
   1294  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MAXLINK:
   1295  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1296  1.1.1.1.4.2  rmind 			if (compare) {
   1297  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
   1298  1.1.1.1.4.2  rmind 				    if (fxdr_unsigned(int, *tl) != LINK_MAX)
   1299  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1300  1.1.1.1.4.2  rmind 				}
   1301  1.1.1.1.4.2  rmind 			} else if (pc != NULL) {
   1302  1.1.1.1.4.2  rmind 				pc->pc_linkmax = fxdr_unsigned(u_int32_t, *tl);
   1303  1.1.1.1.4.2  rmind 			}
   1304  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1305  1.1.1.1.4.2  rmind 			break;
   1306  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MAXNAME:
   1307  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1308  1.1.1.1.4.2  rmind 			if (compare) {
   1309  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
   1310  1.1.1.1.4.2  rmind 				    if (fsp->fs_maxname !=
   1311  1.1.1.1.4.2  rmind 					fxdr_unsigned(u_int32_t, *tl))
   1312  1.1.1.1.4.2  rmind 						*retcmpp = NFSERR_NOTSAME;
   1313  1.1.1.1.4.2  rmind 				}
   1314  1.1.1.1.4.2  rmind 			} else {
   1315  1.1.1.1.4.2  rmind 				tuint = fxdr_unsigned(u_int32_t, *tl);
   1316  1.1.1.1.4.2  rmind 				/*
   1317  1.1.1.1.4.2  rmind 				 * Some Linux NFSv4 servers report this
   1318  1.1.1.1.4.2  rmind 				 * as 0 or 4billion, so I'll set it to
   1319  1.1.1.1.4.2  rmind 				 * NFS_MAXNAMLEN. If a server actually creates
   1320  1.1.1.1.4.2  rmind 				 * a name longer than NFS_MAXNAMLEN, it will
   1321  1.1.1.1.4.2  rmind 				 * get an error back.
   1322  1.1.1.1.4.2  rmind 				 */
   1323  1.1.1.1.4.2  rmind 				if (tuint == 0 || tuint > NFS_MAXNAMLEN)
   1324  1.1.1.1.4.2  rmind 					tuint = NFS_MAXNAMLEN;
   1325  1.1.1.1.4.2  rmind 				if (fsp != NULL)
   1326  1.1.1.1.4.2  rmind 					fsp->fs_maxname = tuint;
   1327  1.1.1.1.4.2  rmind 				if (pc != NULL)
   1328  1.1.1.1.4.2  rmind 					pc->pc_namemax = tuint;
   1329  1.1.1.1.4.2  rmind 			}
   1330  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1331  1.1.1.1.4.2  rmind 			break;
   1332  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MAXREAD:
   1333  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1334  1.1.1.1.4.2  rmind 			if (compare) {
   1335  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
   1336  1.1.1.1.4.2  rmind 				    if (fsp->fs_rtmax != fxdr_unsigned(u_int32_t,
   1337  1.1.1.1.4.2  rmind 					*(tl + 1)) || *tl != 0)
   1338  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1339  1.1.1.1.4.2  rmind 				}
   1340  1.1.1.1.4.2  rmind 			} else if (fsp != NULL) {
   1341  1.1.1.1.4.2  rmind 				fsp->fs_rtmax = fxdr_unsigned(u_int32_t, *++tl);
   1342  1.1.1.1.4.2  rmind 				fsp->fs_rtpref = fsp->fs_rtmax;
   1343  1.1.1.1.4.2  rmind 				fsp->fs_dtpref = fsp->fs_rtpref;
   1344  1.1.1.1.4.2  rmind 			}
   1345  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1346  1.1.1.1.4.2  rmind 			break;
   1347  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MAXWRITE:
   1348  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1349  1.1.1.1.4.2  rmind 			if (compare) {
   1350  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
   1351  1.1.1.1.4.2  rmind 				    if (fsp->fs_wtmax != fxdr_unsigned(u_int32_t,
   1352  1.1.1.1.4.2  rmind 					*(tl + 1)) || *tl != 0)
   1353  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1354  1.1.1.1.4.2  rmind 				}
   1355  1.1.1.1.4.2  rmind 			} else if (fsp != NULL) {
   1356  1.1.1.1.4.2  rmind 				fsp->fs_wtmax = fxdr_unsigned(int, *++tl);
   1357  1.1.1.1.4.2  rmind 				fsp->fs_wtpref = fsp->fs_wtmax;
   1358  1.1.1.1.4.2  rmind 			}
   1359  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1360  1.1.1.1.4.2  rmind 			break;
   1361  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MIMETYPE:
   1362  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1363  1.1.1.1.4.2  rmind 			i = fxdr_unsigned(int, *tl);
   1364  1.1.1.1.4.2  rmind 			attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(i));
   1365  1.1.1.1.4.2  rmind 			error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
   1366  1.1.1.1.4.2  rmind 			if (error)
   1367  1.1.1.1.4.2  rmind 				goto nfsmout;
   1368  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp))
   1369  1.1.1.1.4.2  rmind 				*retcmpp = NFSERR_ATTRNOTSUPP;
   1370  1.1.1.1.4.2  rmind 			break;
   1371  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MODE:
   1372  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1373  1.1.1.1.4.2  rmind 			if (compare) {
   1374  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
   1375  1.1.1.1.4.2  rmind 				    if (nap->na_mode != nfstov_mode(*tl))
   1376  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1377  1.1.1.1.4.2  rmind 				}
   1378  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
   1379  1.1.1.1.4.2  rmind 				nap->na_mode = nfstov_mode(*tl);
   1380  1.1.1.1.4.2  rmind 			}
   1381  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1382  1.1.1.1.4.2  rmind 			break;
   1383  1.1.1.1.4.2  rmind 		case NFSATTRBIT_NOTRUNC:
   1384  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1385  1.1.1.1.4.2  rmind 			if (compare) {
   1386  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
   1387  1.1.1.1.4.2  rmind 				    if (*tl != newnfs_true)
   1388  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1389  1.1.1.1.4.2  rmind 				}
   1390  1.1.1.1.4.2  rmind 			} else if (pc != NULL) {
   1391  1.1.1.1.4.2  rmind 				pc->pc_notrunc = fxdr_unsigned(u_int32_t, *tl);
   1392  1.1.1.1.4.2  rmind 			}
   1393  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1394  1.1.1.1.4.2  rmind 			break;
   1395  1.1.1.1.4.2  rmind 		case NFSATTRBIT_NUMLINKS:
   1396  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1397  1.1.1.1.4.2  rmind 			tuint = fxdr_unsigned(u_int32_t, *tl);
   1398  1.1.1.1.4.2  rmind 			if (compare) {
   1399  1.1.1.1.4.2  rmind 			    if (!(*retcmpp)) {
   1400  1.1.1.1.4.2  rmind 				if ((u_int32_t)nap->na_nlink != tuint)
   1401  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1402  1.1.1.1.4.2  rmind 			    }
   1403  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
   1404  1.1.1.1.4.2  rmind 				nap->na_nlink = tuint;
   1405  1.1.1.1.4.2  rmind 			}
   1406  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1407  1.1.1.1.4.2  rmind 			break;
   1408  1.1.1.1.4.2  rmind 		case NFSATTRBIT_OWNER:
   1409  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1410  1.1.1.1.4.2  rmind 			j = fxdr_unsigned(int, *tl);
   1411  1.1.1.1.4.2  rmind 			if (j < 0) {
   1412  1.1.1.1.4.2  rmind 				error = NFSERR_BADXDR;
   1413  1.1.1.1.4.2  rmind 				goto nfsmout;
   1414  1.1.1.1.4.2  rmind 			}
   1415  1.1.1.1.4.2  rmind 			attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j));
   1416  1.1.1.1.4.2  rmind 			if (j > NFSV4_SMALLSTR)
   1417  1.1.1.1.4.2  rmind 				cp = malloc(j + 1, M_NFSSTRING, M_WAITOK);
   1418  1.1.1.1.4.2  rmind 			else
   1419  1.1.1.1.4.2  rmind 				cp = namestr;
   1420  1.1.1.1.4.2  rmind 			error = nfsrv_mtostr(nd, cp, j);
   1421  1.1.1.1.4.2  rmind 			if (error) {
   1422  1.1.1.1.4.2  rmind 				if (j > NFSV4_SMALLSTR)
   1423  1.1.1.1.4.2  rmind 					free(cp, M_NFSSTRING);
   1424  1.1.1.1.4.2  rmind 				goto nfsmout;
   1425  1.1.1.1.4.2  rmind 			}
   1426  1.1.1.1.4.2  rmind 			if (compare) {
   1427  1.1.1.1.4.2  rmind 			    if (!(*retcmpp)) {
   1428  1.1.1.1.4.2  rmind 				if (nfsv4_strtouid(nd, cp, j, &uid, p) ||
   1429  1.1.1.1.4.2  rmind 				    nap->na_uid != uid)
   1430  1.1.1.1.4.2  rmind 				    *retcmpp = NFSERR_NOTSAME;
   1431  1.1.1.1.4.2  rmind 			    }
   1432  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
   1433  1.1.1.1.4.2  rmind 				if (nfsv4_strtouid(nd, cp, j, &uid, p))
   1434  1.1.1.1.4.2  rmind 					nap->na_uid = nfsrv_defaultuid;
   1435  1.1.1.1.4.2  rmind 				else
   1436  1.1.1.1.4.2  rmind 					nap->na_uid = uid;
   1437  1.1.1.1.4.2  rmind 			}
   1438  1.1.1.1.4.2  rmind 			if (j > NFSV4_SMALLSTR)
   1439  1.1.1.1.4.2  rmind 				free(cp, M_NFSSTRING);
   1440  1.1.1.1.4.2  rmind 			break;
   1441  1.1.1.1.4.2  rmind 		case NFSATTRBIT_OWNERGROUP:
   1442  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1443  1.1.1.1.4.2  rmind 			j = fxdr_unsigned(int, *tl);
   1444  1.1.1.1.4.2  rmind 			if (j < 0) {
   1445  1.1.1.1.4.2  rmind 				error =  NFSERR_BADXDR;
   1446  1.1.1.1.4.2  rmind 				goto nfsmout;
   1447  1.1.1.1.4.2  rmind 			}
   1448  1.1.1.1.4.2  rmind 			attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j));
   1449  1.1.1.1.4.2  rmind 			if (j > NFSV4_SMALLSTR)
   1450  1.1.1.1.4.2  rmind 				cp = malloc(j + 1, M_NFSSTRING, M_WAITOK);
   1451  1.1.1.1.4.2  rmind 			else
   1452  1.1.1.1.4.2  rmind 				cp = namestr;
   1453  1.1.1.1.4.2  rmind 			error = nfsrv_mtostr(nd, cp, j);
   1454  1.1.1.1.4.2  rmind 			if (error) {
   1455  1.1.1.1.4.2  rmind 				if (j > NFSV4_SMALLSTR)
   1456  1.1.1.1.4.2  rmind 					free(cp, M_NFSSTRING);
   1457  1.1.1.1.4.2  rmind 				goto nfsmout;
   1458  1.1.1.1.4.2  rmind 			}
   1459  1.1.1.1.4.2  rmind 			if (compare) {
   1460  1.1.1.1.4.2  rmind 			    if (!(*retcmpp)) {
   1461  1.1.1.1.4.2  rmind 				if (nfsv4_strtogid(nd, cp, j, &gid, p) ||
   1462  1.1.1.1.4.2  rmind 				    nap->na_gid != gid)
   1463  1.1.1.1.4.2  rmind 				    *retcmpp = NFSERR_NOTSAME;
   1464  1.1.1.1.4.2  rmind 			    }
   1465  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
   1466  1.1.1.1.4.2  rmind 				if (nfsv4_strtogid(nd, cp, j, &gid, p))
   1467  1.1.1.1.4.2  rmind 					nap->na_gid = nfsrv_defaultgid;
   1468  1.1.1.1.4.2  rmind 				else
   1469  1.1.1.1.4.2  rmind 					nap->na_gid = gid;
   1470  1.1.1.1.4.2  rmind 			}
   1471  1.1.1.1.4.2  rmind 			if (j > NFSV4_SMALLSTR)
   1472  1.1.1.1.4.2  rmind 				free(cp, M_NFSSTRING);
   1473  1.1.1.1.4.2  rmind 			break;
   1474  1.1.1.1.4.2  rmind 		case NFSATTRBIT_QUOTAHARD:
   1475  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1476  1.1.1.1.4.2  rmind 			if (sbp != NULL) {
   1477  1.1.1.1.4.2  rmind 			    if (priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA, 0))
   1478  1.1.1.1.4.2  rmind 				freenum = sbp->f_bfree;
   1479  1.1.1.1.4.2  rmind 			    else
   1480  1.1.1.1.4.2  rmind 				freenum = sbp->f_bavail;
   1481  1.1.1.1.4.2  rmind #ifdef QUOTA
   1482  1.1.1.1.4.2  rmind 			    /*
   1483  1.1.1.1.4.2  rmind 			     * ufs_quotactl() insists that the uid argument
   1484  1.1.1.1.4.2  rmind 			     * equal p_ruid for non-root quota access, so
   1485  1.1.1.1.4.2  rmind 			     * we'll just make sure that's the case.
   1486  1.1.1.1.4.2  rmind 			     */
   1487  1.1.1.1.4.2  rmind 			    savuid = p->p_cred->p_ruid;
   1488  1.1.1.1.4.2  rmind 			    p->p_cred->p_ruid = cred->cr_uid;
   1489  1.1.1.1.4.2  rmind 			    if (!VFS_QUOTACTL(vnode_mount(vp),QCMD(Q_GETQUOTA,
   1490  1.1.1.1.4.2  rmind 				USRQUOTA), cred->cr_uid, (caddr_t)&dqb))
   1491  1.1.1.1.4.2  rmind 				freenum = min(dqb.dqb_bhardlimit, freenum);
   1492  1.1.1.1.4.2  rmind 			    p->p_cred->p_ruid = savuid;
   1493  1.1.1.1.4.2  rmind #endif	/* QUOTA */
   1494  1.1.1.1.4.2  rmind 			    uquad = (u_int64_t)freenum;
   1495  1.1.1.1.4.2  rmind 			    NFSQUOTABLKTOBYTE(uquad, sbp->f_bsize);
   1496  1.1.1.1.4.2  rmind 			}
   1497  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp)) {
   1498  1.1.1.1.4.2  rmind 				if (uquad != fxdr_hyper(tl))
   1499  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1500  1.1.1.1.4.2  rmind 			}
   1501  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1502  1.1.1.1.4.2  rmind 			break;
   1503  1.1.1.1.4.2  rmind 		case NFSATTRBIT_QUOTASOFT:
   1504  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1505  1.1.1.1.4.2  rmind 			if (sbp != NULL) {
   1506  1.1.1.1.4.2  rmind 			    if (priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA, 0))
   1507  1.1.1.1.4.2  rmind 				freenum = sbp->f_bfree;
   1508  1.1.1.1.4.2  rmind 			    else
   1509  1.1.1.1.4.2  rmind 				freenum = sbp->f_bavail;
   1510  1.1.1.1.4.2  rmind #ifdef QUOTA
   1511  1.1.1.1.4.2  rmind 			    /*
   1512  1.1.1.1.4.2  rmind 			     * ufs_quotactl() insists that the uid argument
   1513  1.1.1.1.4.2  rmind 			     * equal p_ruid for non-root quota access, so
   1514  1.1.1.1.4.2  rmind 			     * we'll just make sure that's the case.
   1515  1.1.1.1.4.2  rmind 			     */
   1516  1.1.1.1.4.2  rmind 			    savuid = p->p_cred->p_ruid;
   1517  1.1.1.1.4.2  rmind 			    p->p_cred->p_ruid = cred->cr_uid;
   1518  1.1.1.1.4.2  rmind 			    if (!VFS_QUOTACTL(vnode_mount(vp),QCMD(Q_GETQUOTA,
   1519  1.1.1.1.4.2  rmind 				USRQUOTA), cred->cr_uid, (caddr_t)&dqb))
   1520  1.1.1.1.4.2  rmind 				freenum = min(dqb.dqb_bsoftlimit, freenum);
   1521  1.1.1.1.4.2  rmind 			    p->p_cred->p_ruid = savuid;
   1522  1.1.1.1.4.2  rmind #endif	/* QUOTA */
   1523  1.1.1.1.4.2  rmind 			    uquad = (u_int64_t)freenum;
   1524  1.1.1.1.4.2  rmind 			    NFSQUOTABLKTOBYTE(uquad, sbp->f_bsize);
   1525  1.1.1.1.4.2  rmind 			}
   1526  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp)) {
   1527  1.1.1.1.4.2  rmind 				if (uquad != fxdr_hyper(tl))
   1528  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1529  1.1.1.1.4.2  rmind 			}
   1530  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1531  1.1.1.1.4.2  rmind 			break;
   1532  1.1.1.1.4.2  rmind 		case NFSATTRBIT_QUOTAUSED:
   1533  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1534  1.1.1.1.4.2  rmind 			if (sbp != NULL) {
   1535  1.1.1.1.4.2  rmind 			    freenum = 0;
   1536  1.1.1.1.4.2  rmind #ifdef QUOTA
   1537  1.1.1.1.4.2  rmind 			    /*
   1538  1.1.1.1.4.2  rmind 			     * ufs_quotactl() insists that the uid argument
   1539  1.1.1.1.4.2  rmind 			     * equal p_ruid for non-root quota access, so
   1540  1.1.1.1.4.2  rmind 			     * we'll just make sure that's the case.
   1541  1.1.1.1.4.2  rmind 			     */
   1542  1.1.1.1.4.2  rmind 			    savuid = p->p_cred->p_ruid;
   1543  1.1.1.1.4.2  rmind 			    p->p_cred->p_ruid = cred->cr_uid;
   1544  1.1.1.1.4.2  rmind 			    if (!VFS_QUOTACTL(vnode_mount(vp),QCMD(Q_GETQUOTA,
   1545  1.1.1.1.4.2  rmind 				USRQUOTA), cred->cr_uid, (caddr_t)&dqb))
   1546  1.1.1.1.4.2  rmind 				freenum = dqb.dqb_curblocks;
   1547  1.1.1.1.4.2  rmind 			    p->p_cred->p_ruid = savuid;
   1548  1.1.1.1.4.2  rmind #endif	/* QUOTA */
   1549  1.1.1.1.4.2  rmind 			    uquad = (u_int64_t)freenum;
   1550  1.1.1.1.4.2  rmind 			    NFSQUOTABLKTOBYTE(uquad, sbp->f_bsize);
   1551  1.1.1.1.4.2  rmind 			}
   1552  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp)) {
   1553  1.1.1.1.4.2  rmind 				if (uquad != fxdr_hyper(tl))
   1554  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1555  1.1.1.1.4.2  rmind 			}
   1556  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1557  1.1.1.1.4.2  rmind 			break;
   1558  1.1.1.1.4.2  rmind 		case NFSATTRBIT_RAWDEV:
   1559  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4SPECDATA);
   1560  1.1.1.1.4.2  rmind 			j = fxdr_unsigned(int, *tl++);
   1561  1.1.1.1.4.2  rmind 			k = fxdr_unsigned(int, *tl);
   1562  1.1.1.1.4.2  rmind 			if (compare) {
   1563  1.1.1.1.4.2  rmind 			    if (!(*retcmpp)) {
   1564  1.1.1.1.4.2  rmind 				if (nap->na_rdev != NFSMAKEDEV(j, k))
   1565  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1566  1.1.1.1.4.2  rmind 			    }
   1567  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
   1568  1.1.1.1.4.2  rmind 				nap->na_rdev = NFSMAKEDEV(j, k);
   1569  1.1.1.1.4.2  rmind 			}
   1570  1.1.1.1.4.2  rmind 			attrsum += NFSX_V4SPECDATA;
   1571  1.1.1.1.4.2  rmind 			break;
   1572  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SPACEAVAIL:
   1573  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1574  1.1.1.1.4.2  rmind 			if (compare) {
   1575  1.1.1.1.4.2  rmind 				if (!(*retcmpp) &&
   1576  1.1.1.1.4.2  rmind 				    sfp->sf_abytes != fxdr_hyper(tl))
   1577  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1578  1.1.1.1.4.2  rmind 			} else if (sfp != NULL) {
   1579  1.1.1.1.4.2  rmind 				sfp->sf_abytes = fxdr_hyper(tl);
   1580  1.1.1.1.4.2  rmind 			}
   1581  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1582  1.1.1.1.4.2  rmind 			break;
   1583  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SPACEFREE:
   1584  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1585  1.1.1.1.4.2  rmind 			if (compare) {
   1586  1.1.1.1.4.2  rmind 				if (!(*retcmpp) &&
   1587  1.1.1.1.4.2  rmind 				    sfp->sf_fbytes != fxdr_hyper(tl))
   1588  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1589  1.1.1.1.4.2  rmind 			} else if (sfp != NULL) {
   1590  1.1.1.1.4.2  rmind 				sfp->sf_fbytes = fxdr_hyper(tl);
   1591  1.1.1.1.4.2  rmind 			}
   1592  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1593  1.1.1.1.4.2  rmind 			break;
   1594  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SPACETOTAL:
   1595  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1596  1.1.1.1.4.2  rmind 			if (compare) {
   1597  1.1.1.1.4.2  rmind 				if (!(*retcmpp) &&
   1598  1.1.1.1.4.2  rmind 				    sfp->sf_tbytes != fxdr_hyper(tl))
   1599  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1600  1.1.1.1.4.2  rmind 			} else if (sfp != NULL) {
   1601  1.1.1.1.4.2  rmind 				sfp->sf_tbytes = fxdr_hyper(tl);
   1602  1.1.1.1.4.2  rmind 			}
   1603  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1604  1.1.1.1.4.2  rmind 			break;
   1605  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SPACEUSED:
   1606  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1607  1.1.1.1.4.2  rmind 			thyp = fxdr_hyper(tl);
   1608  1.1.1.1.4.2  rmind 			if (compare) {
   1609  1.1.1.1.4.2  rmind 			    if (!(*retcmpp)) {
   1610  1.1.1.1.4.2  rmind 				if ((u_int64_t)nap->na_bytes != thyp)
   1611  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1612  1.1.1.1.4.2  rmind 			    }
   1613  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
   1614  1.1.1.1.4.2  rmind 				nap->na_bytes = thyp;
   1615  1.1.1.1.4.2  rmind 			}
   1616  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1617  1.1.1.1.4.2  rmind 			break;
   1618  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SYSTEM:
   1619  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1620  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp))
   1621  1.1.1.1.4.2  rmind 				*retcmpp = NFSERR_ATTRNOTSUPP;
   1622  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1623  1.1.1.1.4.2  rmind 			break;
   1624  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TIMEACCESS:
   1625  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
   1626  1.1.1.1.4.2  rmind 			fxdr_nfsv4time(tl, &temptime);
   1627  1.1.1.1.4.2  rmind 			if (compare) {
   1628  1.1.1.1.4.2  rmind 			    if (!(*retcmpp)) {
   1629  1.1.1.1.4.2  rmind 				if (!NFS_CMPTIME(temptime, nap->na_atime))
   1630  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1631  1.1.1.1.4.2  rmind 			    }
   1632  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
   1633  1.1.1.1.4.2  rmind 				nap->na_atime = temptime;
   1634  1.1.1.1.4.2  rmind 			}
   1635  1.1.1.1.4.2  rmind 			attrsum += NFSX_V4TIME;
   1636  1.1.1.1.4.2  rmind 			break;
   1637  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TIMEACCESSSET:
   1638  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1639  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1640  1.1.1.1.4.2  rmind 			i = fxdr_unsigned(int, *tl);
   1641  1.1.1.1.4.2  rmind 			if (i == NFSV4SATTRTIME_TOCLIENT) {
   1642  1.1.1.1.4.2  rmind 				NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
   1643  1.1.1.1.4.2  rmind 				attrsum += NFSX_V4TIME;
   1644  1.1.1.1.4.2  rmind 			}
   1645  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp))
   1646  1.1.1.1.4.2  rmind 				*retcmpp = NFSERR_INVAL;
   1647  1.1.1.1.4.2  rmind 			break;
   1648  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TIMEBACKUP:
   1649  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
   1650  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp))
   1651  1.1.1.1.4.2  rmind 				*retcmpp = NFSERR_ATTRNOTSUPP;
   1652  1.1.1.1.4.2  rmind 			attrsum += NFSX_V4TIME;
   1653  1.1.1.1.4.2  rmind 			break;
   1654  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TIMECREATE:
   1655  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
   1656  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp))
   1657  1.1.1.1.4.2  rmind 				*retcmpp = NFSERR_ATTRNOTSUPP;
   1658  1.1.1.1.4.2  rmind 			attrsum += NFSX_V4TIME;
   1659  1.1.1.1.4.2  rmind 			break;
   1660  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TIMEDELTA:
   1661  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
   1662  1.1.1.1.4.2  rmind 			if (fsp != NULL) {
   1663  1.1.1.1.4.2  rmind 			    if (compare) {
   1664  1.1.1.1.4.2  rmind 				if (!(*retcmpp)) {
   1665  1.1.1.1.4.2  rmind 				    if ((u_int32_t)fsp->fs_timedelta.tv_sec !=
   1666  1.1.1.1.4.2  rmind 					fxdr_unsigned(u_int32_t, *(tl + 1)) ||
   1667  1.1.1.1.4.2  rmind 				        (u_int32_t)fsp->fs_timedelta.tv_nsec !=
   1668  1.1.1.1.4.2  rmind 					(fxdr_unsigned(u_int32_t, *(tl + 2)) %
   1669  1.1.1.1.4.2  rmind 					 1000000000) ||
   1670  1.1.1.1.4.2  rmind 					*tl != 0)
   1671  1.1.1.1.4.2  rmind 					    *retcmpp = NFSERR_NOTSAME;
   1672  1.1.1.1.4.2  rmind 				}
   1673  1.1.1.1.4.2  rmind 			    } else {
   1674  1.1.1.1.4.2  rmind 				fxdr_nfsv4time(tl, &fsp->fs_timedelta);
   1675  1.1.1.1.4.2  rmind 			    }
   1676  1.1.1.1.4.2  rmind 			}
   1677  1.1.1.1.4.2  rmind 			attrsum += NFSX_V4TIME;
   1678  1.1.1.1.4.2  rmind 			break;
   1679  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TIMEMETADATA:
   1680  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
   1681  1.1.1.1.4.2  rmind 			fxdr_nfsv4time(tl, &temptime);
   1682  1.1.1.1.4.2  rmind 			if (compare) {
   1683  1.1.1.1.4.2  rmind 			    if (!(*retcmpp)) {
   1684  1.1.1.1.4.2  rmind 				if (!NFS_CMPTIME(temptime, nap->na_ctime))
   1685  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1686  1.1.1.1.4.2  rmind 			    }
   1687  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
   1688  1.1.1.1.4.2  rmind 				nap->na_ctime = temptime;
   1689  1.1.1.1.4.2  rmind 			}
   1690  1.1.1.1.4.2  rmind 			attrsum += NFSX_V4TIME;
   1691  1.1.1.1.4.2  rmind 			break;
   1692  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TIMEMODIFY:
   1693  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
   1694  1.1.1.1.4.2  rmind 			fxdr_nfsv4time(tl, &temptime);
   1695  1.1.1.1.4.2  rmind 			if (compare) {
   1696  1.1.1.1.4.2  rmind 			    if (!(*retcmpp)) {
   1697  1.1.1.1.4.2  rmind 				if (!NFS_CMPTIME(temptime, nap->na_mtime))
   1698  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1699  1.1.1.1.4.2  rmind 			    }
   1700  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
   1701  1.1.1.1.4.2  rmind 				nap->na_mtime = temptime;
   1702  1.1.1.1.4.2  rmind 			}
   1703  1.1.1.1.4.2  rmind 			attrsum += NFSX_V4TIME;
   1704  1.1.1.1.4.2  rmind 			break;
   1705  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TIMEMODIFYSET:
   1706  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   1707  1.1.1.1.4.2  rmind 			attrsum += NFSX_UNSIGNED;
   1708  1.1.1.1.4.2  rmind 			i = fxdr_unsigned(int, *tl);
   1709  1.1.1.1.4.2  rmind 			if (i == NFSV4SATTRTIME_TOCLIENT) {
   1710  1.1.1.1.4.2  rmind 				NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
   1711  1.1.1.1.4.2  rmind 				attrsum += NFSX_V4TIME;
   1712  1.1.1.1.4.2  rmind 			}
   1713  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp))
   1714  1.1.1.1.4.2  rmind 				*retcmpp = NFSERR_INVAL;
   1715  1.1.1.1.4.2  rmind 			break;
   1716  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MOUNTEDONFILEID:
   1717  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
   1718  1.1.1.1.4.2  rmind 			thyp = fxdr_hyper(tl);
   1719  1.1.1.1.4.2  rmind 			if (compare) {
   1720  1.1.1.1.4.2  rmind 			    if (!(*retcmpp)) {
   1721  1.1.1.1.4.2  rmind 				if (*tl++) {
   1722  1.1.1.1.4.2  rmind 					*retcmpp = NFSERR_NOTSAME;
   1723  1.1.1.1.4.2  rmind 				} else {
   1724  1.1.1.1.4.2  rmind 					if (!vp || !nfsrv_atroot(vp, &fid))
   1725  1.1.1.1.4.2  rmind 						fid = nap->na_fileid;
   1726  1.1.1.1.4.2  rmind 					if ((u_int64_t)fid != thyp)
   1727  1.1.1.1.4.2  rmind 						*retcmpp = NFSERR_NOTSAME;
   1728  1.1.1.1.4.2  rmind 				}
   1729  1.1.1.1.4.2  rmind 			    }
   1730  1.1.1.1.4.2  rmind 			} else if (nap != NULL) {
   1731  1.1.1.1.4.2  rmind 			    if (*tl++)
   1732  1.1.1.1.4.2  rmind 				printf("NFSv4 mounted on fileid > 32bits\n");
   1733  1.1.1.1.4.2  rmind 			    nap->na_mntonfileno = thyp;
   1734  1.1.1.1.4.2  rmind 			}
   1735  1.1.1.1.4.2  rmind 			attrsum += NFSX_HYPER;
   1736  1.1.1.1.4.2  rmind 			break;
   1737  1.1.1.1.4.2  rmind 		default:
   1738  1.1.1.1.4.2  rmind 			printf("EEK! nfsv4_loadattr unknown attr=%d\n",
   1739  1.1.1.1.4.2  rmind 				bitpos);
   1740  1.1.1.1.4.2  rmind 			if (compare && !(*retcmpp))
   1741  1.1.1.1.4.2  rmind 				*retcmpp = NFSERR_ATTRNOTSUPP;
   1742  1.1.1.1.4.2  rmind 			/*
   1743  1.1.1.1.4.2  rmind 			 * and get out of the loop, since we can't parse
   1744  1.1.1.1.4.2  rmind 			 * the unknown attrbute data.
   1745  1.1.1.1.4.2  rmind 			 */
   1746  1.1.1.1.4.2  rmind 			bitpos = NFSATTRBIT_MAX;
   1747  1.1.1.1.4.2  rmind 			break;
   1748  1.1.1.1.4.2  rmind 		};
   1749  1.1.1.1.4.2  rmind 	}
   1750  1.1.1.1.4.2  rmind 
   1751  1.1.1.1.4.2  rmind 	/*
   1752  1.1.1.1.4.2  rmind 	 * some clients pad the attrlist, so we need to skip over the
   1753  1.1.1.1.4.2  rmind 	 * padding.
   1754  1.1.1.1.4.2  rmind 	 */
   1755  1.1.1.1.4.2  rmind 	if (attrsum > attrsize) {
   1756  1.1.1.1.4.2  rmind 		error = NFSERR_BADXDR;
   1757  1.1.1.1.4.2  rmind 	} else {
   1758  1.1.1.1.4.2  rmind 		attrsize = NFSM_RNDUP(attrsize);
   1759  1.1.1.1.4.2  rmind 		if (attrsum < attrsize)
   1760  1.1.1.1.4.2  rmind 			error = nfsm_advance(nd, attrsize - attrsum, -1);
   1761  1.1.1.1.4.2  rmind 	}
   1762  1.1.1.1.4.2  rmind nfsmout:
   1763  1.1.1.1.4.2  rmind 	NFSEXITCODE2(error, nd);
   1764  1.1.1.1.4.2  rmind 	return (error);
   1765  1.1.1.1.4.2  rmind }
   1766  1.1.1.1.4.2  rmind 
   1767  1.1.1.1.4.2  rmind /*
   1768  1.1.1.1.4.2  rmind  * Implement sleep locks for newnfs. The nfslock_usecnt allows for a
   1769  1.1.1.1.4.2  rmind  * shared lock and the NFSXXX_LOCK flag permits an exclusive lock.
   1770  1.1.1.1.4.2  rmind  * The first argument is a pointer to an nfsv4lock structure.
   1771  1.1.1.1.4.2  rmind  * The second argument is 1 iff a blocking lock is wanted.
   1772  1.1.1.1.4.2  rmind  * If this argument is 0, the call waits until no thread either wants nor
   1773  1.1.1.1.4.2  rmind  * holds an exclusive lock.
   1774  1.1.1.1.4.2  rmind  * It returns 1 if the lock was acquired, 0 otherwise.
   1775  1.1.1.1.4.2  rmind  * If several processes call this function concurrently wanting the exclusive
   1776  1.1.1.1.4.2  rmind  * lock, one will get the lock and the rest will return without getting the
   1777  1.1.1.1.4.2  rmind  * lock. (If the caller must have the lock, it simply calls this function in a
   1778  1.1.1.1.4.2  rmind  *  loop until the function returns 1 to indicate the lock was acquired.)
   1779  1.1.1.1.4.2  rmind  * Any usecnt must be decremented by calling nfsv4_relref() before
   1780  1.1.1.1.4.2  rmind  * calling nfsv4_lock(). It was done this way, so nfsv4_lock() could
   1781  1.1.1.1.4.2  rmind  * be called in a loop.
   1782  1.1.1.1.4.2  rmind  * The isleptp argument is set to indicate if the call slept, iff not NULL
   1783  1.1.1.1.4.2  rmind  * and the mp argument indicates to check for a forced dismount, iff not
   1784  1.1.1.1.4.2  rmind  * NULL.
   1785  1.1.1.1.4.2  rmind  */
   1786  1.1.1.1.4.2  rmind APPLESTATIC int
   1787  1.1.1.1.4.2  rmind nfsv4_lock(struct nfsv4lock *lp, int iwantlock, int *isleptp,
   1788  1.1.1.1.4.2  rmind     void *mutex, struct mount *mp)
   1789  1.1.1.1.4.2  rmind {
   1790  1.1.1.1.4.2  rmind 
   1791  1.1.1.1.4.2  rmind 	if (isleptp)
   1792  1.1.1.1.4.2  rmind 		*isleptp = 0;
   1793  1.1.1.1.4.2  rmind 	/*
   1794  1.1.1.1.4.2  rmind 	 * If a lock is wanted, loop around until the lock is acquired by
   1795  1.1.1.1.4.2  rmind 	 * someone and then released. If I want the lock, try to acquire it.
   1796  1.1.1.1.4.2  rmind 	 * For a lock to be issued, no lock must be in force and the usecnt
   1797  1.1.1.1.4.2  rmind 	 * must be zero.
   1798  1.1.1.1.4.2  rmind 	 */
   1799  1.1.1.1.4.2  rmind 	if (iwantlock) {
   1800  1.1.1.1.4.2  rmind 	    if (!(lp->nfslock_lock & NFSV4LOCK_LOCK) &&
   1801  1.1.1.1.4.2  rmind 		lp->nfslock_usecnt == 0) {
   1802  1.1.1.1.4.2  rmind 		lp->nfslock_lock &= ~NFSV4LOCK_LOCKWANTED;
   1803  1.1.1.1.4.2  rmind 		lp->nfslock_lock |= NFSV4LOCK_LOCK;
   1804  1.1.1.1.4.2  rmind 		return (1);
   1805  1.1.1.1.4.2  rmind 	    }
   1806  1.1.1.1.4.2  rmind 	    lp->nfslock_lock |= NFSV4LOCK_LOCKWANTED;
   1807  1.1.1.1.4.2  rmind 	}
   1808  1.1.1.1.4.2  rmind 	while (lp->nfslock_lock & (NFSV4LOCK_LOCK | NFSV4LOCK_LOCKWANTED)) {
   1809  1.1.1.1.4.2  rmind 		if (mp != NULL && (mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
   1810  1.1.1.1.4.2  rmind 			lp->nfslock_lock &= ~NFSV4LOCK_LOCKWANTED;
   1811  1.1.1.1.4.2  rmind 			return (0);
   1812  1.1.1.1.4.2  rmind 		}
   1813  1.1.1.1.4.2  rmind 		lp->nfslock_lock |= NFSV4LOCK_WANTED;
   1814  1.1.1.1.4.2  rmind 		if (isleptp)
   1815  1.1.1.1.4.2  rmind 			*isleptp = 1;
   1816  1.1.1.1.4.2  rmind 		(void) nfsmsleep(&lp->nfslock_lock, mutex,
   1817  1.1.1.1.4.2  rmind 		    PZERO - 1, "nfsv4lck", NULL);
   1818  1.1.1.1.4.2  rmind 		if (iwantlock && !(lp->nfslock_lock & NFSV4LOCK_LOCK) &&
   1819  1.1.1.1.4.2  rmind 		    lp->nfslock_usecnt == 0) {
   1820  1.1.1.1.4.2  rmind 			lp->nfslock_lock &= ~NFSV4LOCK_LOCKWANTED;
   1821  1.1.1.1.4.2  rmind 			lp->nfslock_lock |= NFSV4LOCK_LOCK;
   1822  1.1.1.1.4.2  rmind 			return (1);
   1823  1.1.1.1.4.2  rmind 		}
   1824  1.1.1.1.4.2  rmind 	}
   1825  1.1.1.1.4.2  rmind 	return (0);
   1826  1.1.1.1.4.2  rmind }
   1827  1.1.1.1.4.2  rmind 
   1828  1.1.1.1.4.2  rmind /*
   1829  1.1.1.1.4.2  rmind  * Release the lock acquired by nfsv4_lock().
   1830  1.1.1.1.4.2  rmind  * The second argument is set to 1 to indicate the nfslock_usecnt should be
   1831  1.1.1.1.4.2  rmind  * incremented, as well.
   1832  1.1.1.1.4.2  rmind  */
   1833  1.1.1.1.4.2  rmind APPLESTATIC void
   1834  1.1.1.1.4.2  rmind nfsv4_unlock(struct nfsv4lock *lp, int incref)
   1835  1.1.1.1.4.2  rmind {
   1836  1.1.1.1.4.2  rmind 
   1837  1.1.1.1.4.2  rmind 	lp->nfslock_lock &= ~NFSV4LOCK_LOCK;
   1838  1.1.1.1.4.2  rmind 	if (incref)
   1839  1.1.1.1.4.2  rmind 		lp->nfslock_usecnt++;
   1840  1.1.1.1.4.2  rmind 	nfsv4_wanted(lp);
   1841  1.1.1.1.4.2  rmind }
   1842  1.1.1.1.4.2  rmind 
   1843  1.1.1.1.4.2  rmind /*
   1844  1.1.1.1.4.2  rmind  * Release a reference cnt.
   1845  1.1.1.1.4.2  rmind  */
   1846  1.1.1.1.4.2  rmind APPLESTATIC void
   1847  1.1.1.1.4.2  rmind nfsv4_relref(struct nfsv4lock *lp)
   1848  1.1.1.1.4.2  rmind {
   1849  1.1.1.1.4.2  rmind 
   1850  1.1.1.1.4.2  rmind 	if (lp->nfslock_usecnt <= 0)
   1851  1.1.1.1.4.2  rmind 		panic("nfsv4root ref cnt");
   1852  1.1.1.1.4.2  rmind 	lp->nfslock_usecnt--;
   1853  1.1.1.1.4.2  rmind 	if (lp->nfslock_usecnt == 0)
   1854  1.1.1.1.4.2  rmind 		nfsv4_wanted(lp);
   1855  1.1.1.1.4.2  rmind }
   1856  1.1.1.1.4.2  rmind 
   1857  1.1.1.1.4.2  rmind /*
   1858  1.1.1.1.4.2  rmind  * Get a reference cnt.
   1859  1.1.1.1.4.2  rmind  * This function will wait for any exclusive lock to be released, but will
   1860  1.1.1.1.4.2  rmind  * not wait for threads that want the exclusive lock. If priority needs
   1861  1.1.1.1.4.2  rmind  * to be given to threads that need the exclusive lock, a call to nfsv4_lock()
   1862  1.1.1.1.4.2  rmind  * with the 2nd argument == 0 should be done before calling nfsv4_getref().
   1863  1.1.1.1.4.2  rmind  * If the mp argument is not NULL, check for MNTK_UNMOUNTF being set and
   1864  1.1.1.1.4.2  rmind  * return without getting a refcnt for that case.
   1865  1.1.1.1.4.2  rmind  */
   1866  1.1.1.1.4.2  rmind APPLESTATIC void
   1867  1.1.1.1.4.2  rmind nfsv4_getref(struct nfsv4lock *lp, int *isleptp, void *mutex,
   1868  1.1.1.1.4.2  rmind     struct mount *mp)
   1869  1.1.1.1.4.2  rmind {
   1870  1.1.1.1.4.2  rmind 
   1871  1.1.1.1.4.2  rmind 	if (isleptp)
   1872  1.1.1.1.4.2  rmind 		*isleptp = 0;
   1873  1.1.1.1.4.2  rmind 
   1874  1.1.1.1.4.2  rmind 	/*
   1875  1.1.1.1.4.2  rmind 	 * Wait for a lock held.
   1876  1.1.1.1.4.2  rmind 	 */
   1877  1.1.1.1.4.2  rmind 	while (lp->nfslock_lock & NFSV4LOCK_LOCK) {
   1878  1.1.1.1.4.2  rmind 		if (mp != NULL && (mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0)
   1879  1.1.1.1.4.2  rmind 			return;
   1880  1.1.1.1.4.2  rmind 		lp->nfslock_lock |= NFSV4LOCK_WANTED;
   1881  1.1.1.1.4.2  rmind 		if (isleptp)
   1882  1.1.1.1.4.2  rmind 			*isleptp = 1;
   1883  1.1.1.1.4.2  rmind 		(void) nfsmsleep(&lp->nfslock_lock, mutex,
   1884  1.1.1.1.4.2  rmind 		    PZERO - 1, "nfsv4gr", NULL);
   1885  1.1.1.1.4.2  rmind 	}
   1886  1.1.1.1.4.2  rmind 	if (mp != NULL && (mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0)
   1887  1.1.1.1.4.2  rmind 		return;
   1888  1.1.1.1.4.2  rmind 
   1889  1.1.1.1.4.2  rmind 	lp->nfslock_usecnt++;
   1890  1.1.1.1.4.2  rmind }
   1891  1.1.1.1.4.2  rmind 
   1892  1.1.1.1.4.2  rmind /*
   1893  1.1.1.1.4.2  rmind  * Get a reference as above, but return failure instead of sleeping if
   1894  1.1.1.1.4.2  rmind  * an exclusive lock is held.
   1895  1.1.1.1.4.2  rmind  */
   1896  1.1.1.1.4.2  rmind APPLESTATIC int
   1897  1.1.1.1.4.2  rmind nfsv4_getref_nonblock(struct nfsv4lock *lp)
   1898  1.1.1.1.4.2  rmind {
   1899  1.1.1.1.4.2  rmind 
   1900  1.1.1.1.4.2  rmind 	if ((lp->nfslock_lock & NFSV4LOCK_LOCK) != 0)
   1901  1.1.1.1.4.2  rmind 		return (0);
   1902  1.1.1.1.4.2  rmind 
   1903  1.1.1.1.4.2  rmind 	lp->nfslock_usecnt++;
   1904  1.1.1.1.4.2  rmind 	return (1);
   1905  1.1.1.1.4.2  rmind }
   1906  1.1.1.1.4.2  rmind 
   1907  1.1.1.1.4.2  rmind /*
   1908  1.1.1.1.4.2  rmind  * Test for a lock. Return 1 if locked, 0 otherwise.
   1909  1.1.1.1.4.2  rmind  */
   1910  1.1.1.1.4.2  rmind APPLESTATIC int
   1911  1.1.1.1.4.2  rmind nfsv4_testlock(struct nfsv4lock *lp)
   1912  1.1.1.1.4.2  rmind {
   1913  1.1.1.1.4.2  rmind 
   1914  1.1.1.1.4.2  rmind 	if ((lp->nfslock_lock & NFSV4LOCK_LOCK) == 0 &&
   1915  1.1.1.1.4.2  rmind 	    lp->nfslock_usecnt == 0)
   1916  1.1.1.1.4.2  rmind 		return (0);
   1917  1.1.1.1.4.2  rmind 	return (1);
   1918  1.1.1.1.4.2  rmind }
   1919  1.1.1.1.4.2  rmind 
   1920  1.1.1.1.4.2  rmind /*
   1921  1.1.1.1.4.2  rmind  * Wake up anyone sleeping, waiting for this lock.
   1922  1.1.1.1.4.2  rmind  */
   1923  1.1.1.1.4.2  rmind static void
   1924  1.1.1.1.4.2  rmind nfsv4_wanted(struct nfsv4lock *lp)
   1925  1.1.1.1.4.2  rmind {
   1926  1.1.1.1.4.2  rmind 
   1927  1.1.1.1.4.2  rmind 	if (lp->nfslock_lock & NFSV4LOCK_WANTED) {
   1928  1.1.1.1.4.2  rmind 		lp->nfslock_lock &= ~NFSV4LOCK_WANTED;
   1929  1.1.1.1.4.2  rmind 		wakeup((caddr_t)&lp->nfslock_lock);
   1930  1.1.1.1.4.2  rmind 	}
   1931  1.1.1.1.4.2  rmind }
   1932  1.1.1.1.4.2  rmind 
   1933  1.1.1.1.4.2  rmind /*
   1934  1.1.1.1.4.2  rmind  * Copy a string from an mbuf list into a character array.
   1935  1.1.1.1.4.2  rmind  * Return EBADRPC if there is an mbuf error,
   1936  1.1.1.1.4.2  rmind  * 0 otherwise.
   1937  1.1.1.1.4.2  rmind  */
   1938  1.1.1.1.4.2  rmind APPLESTATIC int
   1939  1.1.1.1.4.2  rmind nfsrv_mtostr(struct nfsrv_descript *nd, char *str, int siz)
   1940  1.1.1.1.4.2  rmind {
   1941  1.1.1.1.4.2  rmind 	char *cp;
   1942  1.1.1.1.4.2  rmind 	int xfer, len;
   1943  1.1.1.1.4.2  rmind 	mbuf_t mp;
   1944  1.1.1.1.4.2  rmind 	int rem, error = 0;
   1945  1.1.1.1.4.2  rmind 
   1946  1.1.1.1.4.2  rmind 	mp = nd->nd_md;
   1947  1.1.1.1.4.2  rmind 	cp = nd->nd_dpos;
   1948  1.1.1.1.4.2  rmind 	len = NFSMTOD(mp, caddr_t) + mbuf_len(mp) - cp;
   1949  1.1.1.1.4.2  rmind 	rem = NFSM_RNDUP(siz) - siz;
   1950  1.1.1.1.4.2  rmind 	while (siz > 0) {
   1951  1.1.1.1.4.2  rmind 		if (len > siz)
   1952  1.1.1.1.4.2  rmind 			xfer = siz;
   1953  1.1.1.1.4.2  rmind 		else
   1954  1.1.1.1.4.2  rmind 			xfer = len;
   1955  1.1.1.1.4.2  rmind 		NFSBCOPY(cp, str, xfer);
   1956  1.1.1.1.4.2  rmind 		str += xfer;
   1957  1.1.1.1.4.2  rmind 		siz -= xfer;
   1958  1.1.1.1.4.2  rmind 		if (siz > 0) {
   1959  1.1.1.1.4.2  rmind 			mp = mbuf_next(mp);
   1960  1.1.1.1.4.2  rmind 			if (mp == NULL) {
   1961  1.1.1.1.4.2  rmind 				error = EBADRPC;
   1962  1.1.1.1.4.2  rmind 				goto out;
   1963  1.1.1.1.4.2  rmind 			}
   1964  1.1.1.1.4.2  rmind 			cp = NFSMTOD(mp, caddr_t);
   1965  1.1.1.1.4.2  rmind 			len = mbuf_len(mp);
   1966  1.1.1.1.4.2  rmind 		} else {
   1967  1.1.1.1.4.2  rmind 			cp += xfer;
   1968  1.1.1.1.4.2  rmind 			len -= xfer;
   1969  1.1.1.1.4.2  rmind 		}
   1970  1.1.1.1.4.2  rmind 	}
   1971  1.1.1.1.4.2  rmind 	*str = '\0';
   1972  1.1.1.1.4.2  rmind 	nd->nd_dpos = cp;
   1973  1.1.1.1.4.2  rmind 	nd->nd_md = mp;
   1974  1.1.1.1.4.2  rmind 	if (rem > 0) {
   1975  1.1.1.1.4.2  rmind 		if (len < rem)
   1976  1.1.1.1.4.2  rmind 			error = nfsm_advance(nd, rem, len);
   1977  1.1.1.1.4.2  rmind 		else
   1978  1.1.1.1.4.2  rmind 			nd->nd_dpos += rem;
   1979  1.1.1.1.4.2  rmind 	}
   1980  1.1.1.1.4.2  rmind 
   1981  1.1.1.1.4.2  rmind out:
   1982  1.1.1.1.4.2  rmind 	NFSEXITCODE2(error, nd);
   1983  1.1.1.1.4.2  rmind 	return (error);
   1984  1.1.1.1.4.2  rmind }
   1985  1.1.1.1.4.2  rmind 
   1986  1.1.1.1.4.2  rmind /*
   1987  1.1.1.1.4.2  rmind  * Fill in the attributes as marked by the bitmap (V4).
   1988  1.1.1.1.4.2  rmind  */
   1989  1.1.1.1.4.2  rmind APPLESTATIC int
   1990  1.1.1.1.4.2  rmind nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
   1991  1.1.1.1.4.2  rmind     NFSACL_T *saclp, struct vattr *vap, fhandle_t *fhp, int rderror,
   1992  1.1.1.1.4.2  rmind     nfsattrbit_t *attrbitp, struct ucred *cred, NFSPROC_T *p, int isdgram,
   1993  1.1.1.1.4.2  rmind     int reterr, int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno)
   1994  1.1.1.1.4.2  rmind {
   1995  1.1.1.1.4.2  rmind 	int bitpos, retnum = 0;
   1996  1.1.1.1.4.2  rmind 	u_int32_t *tl;
   1997  1.1.1.1.4.2  rmind 	int siz, prefixnum, error;
   1998  1.1.1.1.4.2  rmind 	u_char *cp, namestr[NFSV4_SMALLSTR];
   1999  1.1.1.1.4.2  rmind 	nfsattrbit_t attrbits, retbits;
   2000  1.1.1.1.4.2  rmind 	nfsattrbit_t *retbitp = &retbits;
   2001  1.1.1.1.4.2  rmind 	u_int32_t freenum, *retnump;
   2002  1.1.1.1.4.2  rmind 	u_int64_t uquad;
   2003  1.1.1.1.4.2  rmind 	struct statfs fs;
   2004  1.1.1.1.4.2  rmind 	struct nfsfsinfo fsinf;
   2005  1.1.1.1.4.2  rmind 	struct timespec temptime;
   2006  1.1.1.1.4.2  rmind 	NFSACL_T *aclp, *naclp = NULL;
   2007  1.1.1.1.4.2  rmind #ifdef QUOTA
   2008  1.1.1.1.4.2  rmind 	struct dqblk dqb;
   2009  1.1.1.1.4.2  rmind 	uid_t savuid;
   2010  1.1.1.1.4.2  rmind #endif
   2011  1.1.1.1.4.2  rmind 
   2012  1.1.1.1.4.2  rmind 	/*
   2013  1.1.1.1.4.2  rmind 	 * First, set the bits that can be filled and get fsinfo.
   2014  1.1.1.1.4.2  rmind 	 */
   2015  1.1.1.1.4.2  rmind 	NFSSET_ATTRBIT(retbitp, attrbitp);
   2016  1.1.1.1.4.2  rmind 	/* If p and cred are NULL, it is a client side call */
   2017  1.1.1.1.4.2  rmind 	if (p == NULL && cred == NULL) {
   2018  1.1.1.1.4.2  rmind 		NFSCLRNOTSETABLE_ATTRBIT(retbitp);
   2019  1.1.1.1.4.2  rmind 		aclp = saclp;
   2020  1.1.1.1.4.2  rmind 	} else {
   2021  1.1.1.1.4.2  rmind 		NFSCLRNOTFILLABLE_ATTRBIT(retbitp);
   2022  1.1.1.1.4.2  rmind 		naclp = acl_alloc(M_WAITOK);
   2023  1.1.1.1.4.2  rmind 		aclp = naclp;
   2024  1.1.1.1.4.2  rmind 	}
   2025  1.1.1.1.4.2  rmind 	nfsvno_getfs(&fsinf, isdgram);
   2026  1.1.1.1.4.2  rmind #ifndef APPLE
   2027  1.1.1.1.4.2  rmind 	/*
   2028  1.1.1.1.4.2  rmind 	 * Get the VFS_STATFS(), since some attributes need them.
   2029  1.1.1.1.4.2  rmind 	 */
   2030  1.1.1.1.4.2  rmind 	if (NFSISSETSTATFS_ATTRBIT(retbitp)) {
   2031  1.1.1.1.4.2  rmind 		error = VFS_STATFS(mp, &fs);
   2032  1.1.1.1.4.2  rmind 		if (error != 0) {
   2033  1.1.1.1.4.2  rmind 			if (reterr) {
   2034  1.1.1.1.4.2  rmind 				nd->nd_repstat = NFSERR_ACCES;
   2035  1.1.1.1.4.2  rmind 				return (0);
   2036  1.1.1.1.4.2  rmind 			}
   2037  1.1.1.1.4.2  rmind 			NFSCLRSTATFS_ATTRBIT(retbitp);
   2038  1.1.1.1.4.2  rmind 		}
   2039  1.1.1.1.4.2  rmind 	}
   2040  1.1.1.1.4.2  rmind #endif
   2041  1.1.1.1.4.2  rmind 
   2042  1.1.1.1.4.2  rmind 	/*
   2043  1.1.1.1.4.2  rmind 	 * And the NFSv4 ACL...
   2044  1.1.1.1.4.2  rmind 	 */
   2045  1.1.1.1.4.2  rmind 	if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_ACLSUPPORT) &&
   2046  1.1.1.1.4.2  rmind 	    (nfsrv_useacl == 0 || ((cred != NULL || p != NULL) &&
   2047  1.1.1.1.4.2  rmind 		supports_nfsv4acls == 0))) {
   2048  1.1.1.1.4.2  rmind 		NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACLSUPPORT);
   2049  1.1.1.1.4.2  rmind 	}
   2050  1.1.1.1.4.2  rmind 	if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_ACL)) {
   2051  1.1.1.1.4.2  rmind 		if (nfsrv_useacl == 0 || ((cred != NULL || p != NULL) &&
   2052  1.1.1.1.4.2  rmind 		    supports_nfsv4acls == 0)) {
   2053  1.1.1.1.4.2  rmind 			NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACL);
   2054  1.1.1.1.4.2  rmind 		} else if (naclp != NULL) {
   2055  1.1.1.1.4.2  rmind 			if (NFSVOPLOCK(vp, LK_SHARED) == 0) {
   2056  1.1.1.1.4.2  rmind 				error = VOP_ACCESSX(vp, VREAD_ACL, cred, p);
   2057  1.1.1.1.4.2  rmind 				if (error == 0)
   2058  1.1.1.1.4.2  rmind 					error = VOP_GETACL(vp, ACL_TYPE_NFS4,
   2059  1.1.1.1.4.2  rmind 					    naclp, cred, p);
   2060  1.1.1.1.4.2  rmind 				NFSVOPUNLOCK(vp, 0);
   2061  1.1.1.1.4.2  rmind 			} else
   2062  1.1.1.1.4.2  rmind 				error = NFSERR_PERM;
   2063  1.1.1.1.4.2  rmind 			if (error != 0) {
   2064  1.1.1.1.4.2  rmind 				if (reterr) {
   2065  1.1.1.1.4.2  rmind 					nd->nd_repstat = NFSERR_ACCES;
   2066  1.1.1.1.4.2  rmind 					return (0);
   2067  1.1.1.1.4.2  rmind 				}
   2068  1.1.1.1.4.2  rmind 				NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACL);
   2069  1.1.1.1.4.2  rmind 			}
   2070  1.1.1.1.4.2  rmind 		}
   2071  1.1.1.1.4.2  rmind 	}
   2072  1.1.1.1.4.2  rmind 	/*
   2073  1.1.1.1.4.2  rmind 	 * Put out the attribute bitmap for the ones being filled in
   2074  1.1.1.1.4.2  rmind 	 * and get the field for the number of attributes returned.
   2075  1.1.1.1.4.2  rmind 	 */
   2076  1.1.1.1.4.2  rmind 	prefixnum = nfsrv_putattrbit(nd, retbitp);
   2077  1.1.1.1.4.2  rmind 	NFSM_BUILD(retnump, u_int32_t *, NFSX_UNSIGNED);
   2078  1.1.1.1.4.2  rmind 	prefixnum += NFSX_UNSIGNED;
   2079  1.1.1.1.4.2  rmind 
   2080  1.1.1.1.4.2  rmind 	/*
   2081  1.1.1.1.4.2  rmind 	 * Now, loop around filling in the attributes for each bit set.
   2082  1.1.1.1.4.2  rmind 	 */
   2083  1.1.1.1.4.2  rmind 	for (bitpos = 0; bitpos < NFSATTRBIT_MAX; bitpos++) {
   2084  1.1.1.1.4.2  rmind 	    if (NFSISSET_ATTRBIT(retbitp, bitpos)) {
   2085  1.1.1.1.4.2  rmind 		switch (bitpos) {
   2086  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SUPPORTEDATTRS:
   2087  1.1.1.1.4.2  rmind 			NFSSETSUPP_ATTRBIT(&attrbits);
   2088  1.1.1.1.4.2  rmind 			if (nfsrv_useacl == 0 || ((cred != NULL || p != NULL)
   2089  1.1.1.1.4.2  rmind 			    && supports_nfsv4acls == 0)) {
   2090  1.1.1.1.4.2  rmind 			    NFSCLRBIT_ATTRBIT(&attrbits,NFSATTRBIT_ACLSUPPORT);
   2091  1.1.1.1.4.2  rmind 			    NFSCLRBIT_ATTRBIT(&attrbits,NFSATTRBIT_ACL);
   2092  1.1.1.1.4.2  rmind 			}
   2093  1.1.1.1.4.2  rmind 			retnum += nfsrv_putattrbit(nd, &attrbits);
   2094  1.1.1.1.4.2  rmind 			break;
   2095  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TYPE:
   2096  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2097  1.1.1.1.4.2  rmind 			*tl = vtonfsv34_type(vap->va_type);
   2098  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2099  1.1.1.1.4.2  rmind 			break;
   2100  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FHEXPIRETYPE:
   2101  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2102  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(NFSV4FHTYPE_PERSISTENT);
   2103  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2104  1.1.1.1.4.2  rmind 			break;
   2105  1.1.1.1.4.2  rmind 		case NFSATTRBIT_CHANGE:
   2106  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2107  1.1.1.1.4.2  rmind 			txdr_hyper(vap->va_filerev, tl);
   2108  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2109  1.1.1.1.4.2  rmind 			break;
   2110  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SIZE:
   2111  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2112  1.1.1.1.4.2  rmind 			txdr_hyper(vap->va_size, tl);
   2113  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2114  1.1.1.1.4.2  rmind 			break;
   2115  1.1.1.1.4.2  rmind 		case NFSATTRBIT_LINKSUPPORT:
   2116  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2117  1.1.1.1.4.2  rmind 			if (fsinf.fs_properties & NFSV3FSINFO_LINK)
   2118  1.1.1.1.4.2  rmind 				*tl = newnfs_true;
   2119  1.1.1.1.4.2  rmind 			else
   2120  1.1.1.1.4.2  rmind 				*tl = newnfs_false;
   2121  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2122  1.1.1.1.4.2  rmind 			break;
   2123  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SYMLINKSUPPORT:
   2124  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2125  1.1.1.1.4.2  rmind 			if (fsinf.fs_properties & NFSV3FSINFO_SYMLINK)
   2126  1.1.1.1.4.2  rmind 				*tl = newnfs_true;
   2127  1.1.1.1.4.2  rmind 			else
   2128  1.1.1.1.4.2  rmind 				*tl = newnfs_false;
   2129  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2130  1.1.1.1.4.2  rmind 			break;
   2131  1.1.1.1.4.2  rmind 		case NFSATTRBIT_NAMEDATTR:
   2132  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2133  1.1.1.1.4.2  rmind 			*tl = newnfs_false;
   2134  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2135  1.1.1.1.4.2  rmind 			break;
   2136  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FSID:
   2137  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_V4FSID);
   2138  1.1.1.1.4.2  rmind 			*tl++ = 0;
   2139  1.1.1.1.4.2  rmind 			*tl++ = txdr_unsigned(mp->mnt_stat.f_fsid.val[0]);
   2140  1.1.1.1.4.2  rmind 			*tl++ = 0;
   2141  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(mp->mnt_stat.f_fsid.val[1]);
   2142  1.1.1.1.4.2  rmind 			retnum += NFSX_V4FSID;
   2143  1.1.1.1.4.2  rmind 			break;
   2144  1.1.1.1.4.2  rmind 		case NFSATTRBIT_UNIQUEHANDLES:
   2145  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2146  1.1.1.1.4.2  rmind 			*tl = newnfs_true;
   2147  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2148  1.1.1.1.4.2  rmind 			break;
   2149  1.1.1.1.4.2  rmind 		case NFSATTRBIT_LEASETIME:
   2150  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2151  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(nfsrv_lease);
   2152  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2153  1.1.1.1.4.2  rmind 			break;
   2154  1.1.1.1.4.2  rmind 		case NFSATTRBIT_RDATTRERROR:
   2155  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2156  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(rderror);
   2157  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2158  1.1.1.1.4.2  rmind 			break;
   2159  1.1.1.1.4.2  rmind 		/*
   2160  1.1.1.1.4.2  rmind 		 * Recommended Attributes. (Only the supported ones.)
   2161  1.1.1.1.4.2  rmind 		 */
   2162  1.1.1.1.4.2  rmind 		case NFSATTRBIT_ACL:
   2163  1.1.1.1.4.2  rmind 			retnum += nfsrv_buildacl(nd, aclp, vnode_vtype(vp), p);
   2164  1.1.1.1.4.2  rmind 			break;
   2165  1.1.1.1.4.2  rmind 		case NFSATTRBIT_ACLSUPPORT:
   2166  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2167  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(NFSV4ACE_SUPTYPES);
   2168  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2169  1.1.1.1.4.2  rmind 			break;
   2170  1.1.1.1.4.2  rmind 		case NFSATTRBIT_CANSETTIME:
   2171  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2172  1.1.1.1.4.2  rmind 			if (fsinf.fs_properties & NFSV3FSINFO_CANSETTIME)
   2173  1.1.1.1.4.2  rmind 				*tl = newnfs_true;
   2174  1.1.1.1.4.2  rmind 			else
   2175  1.1.1.1.4.2  rmind 				*tl = newnfs_false;
   2176  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2177  1.1.1.1.4.2  rmind 			break;
   2178  1.1.1.1.4.2  rmind 		case NFSATTRBIT_CASEINSENSITIVE:
   2179  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2180  1.1.1.1.4.2  rmind 			*tl = newnfs_false;
   2181  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2182  1.1.1.1.4.2  rmind 			break;
   2183  1.1.1.1.4.2  rmind 		case NFSATTRBIT_CASEPRESERVING:
   2184  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2185  1.1.1.1.4.2  rmind 			*tl = newnfs_true;
   2186  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2187  1.1.1.1.4.2  rmind 			break;
   2188  1.1.1.1.4.2  rmind 		case NFSATTRBIT_CHOWNRESTRICTED:
   2189  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2190  1.1.1.1.4.2  rmind 			*tl = newnfs_true;
   2191  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2192  1.1.1.1.4.2  rmind 			break;
   2193  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FILEHANDLE:
   2194  1.1.1.1.4.2  rmind 			retnum += nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
   2195  1.1.1.1.4.2  rmind 			break;
   2196  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FILEID:
   2197  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2198  1.1.1.1.4.2  rmind 			*tl++ = 0;
   2199  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(vap->va_fileid);
   2200  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2201  1.1.1.1.4.2  rmind 			break;
   2202  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FILESAVAIL:
   2203  1.1.1.1.4.2  rmind 			/*
   2204  1.1.1.1.4.2  rmind 			 * Check quota and use min(quota, f_ffree).
   2205  1.1.1.1.4.2  rmind 			 */
   2206  1.1.1.1.4.2  rmind 			freenum = fs.f_ffree;
   2207  1.1.1.1.4.2  rmind #ifdef QUOTA
   2208  1.1.1.1.4.2  rmind 			/*
   2209  1.1.1.1.4.2  rmind 			 * ufs_quotactl() insists that the uid argument
   2210  1.1.1.1.4.2  rmind 			 * equal p_ruid for non-root quota access, so
   2211  1.1.1.1.4.2  rmind 			 * we'll just make sure that's the case.
   2212  1.1.1.1.4.2  rmind 			 */
   2213  1.1.1.1.4.2  rmind 			savuid = p->p_cred->p_ruid;
   2214  1.1.1.1.4.2  rmind 			p->p_cred->p_ruid = cred->cr_uid;
   2215  1.1.1.1.4.2  rmind 			if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA),
   2216  1.1.1.1.4.2  rmind 			    cred->cr_uid, (caddr_t)&dqb))
   2217  1.1.1.1.4.2  rmind 			    freenum = min(dqb.dqb_isoftlimit-dqb.dqb_curinodes,
   2218  1.1.1.1.4.2  rmind 				freenum);
   2219  1.1.1.1.4.2  rmind 			p->p_cred->p_ruid = savuid;
   2220  1.1.1.1.4.2  rmind #endif	/* QUOTA */
   2221  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2222  1.1.1.1.4.2  rmind 			*tl++ = 0;
   2223  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(freenum);
   2224  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2225  1.1.1.1.4.2  rmind 			break;
   2226  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FILESFREE:
   2227  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2228  1.1.1.1.4.2  rmind 			*tl++ = 0;
   2229  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(fs.f_ffree);
   2230  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2231  1.1.1.1.4.2  rmind 			break;
   2232  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FILESTOTAL:
   2233  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2234  1.1.1.1.4.2  rmind 			*tl++ = 0;
   2235  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(fs.f_files);
   2236  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2237  1.1.1.1.4.2  rmind 			break;
   2238  1.1.1.1.4.2  rmind 		case NFSATTRBIT_FSLOCATIONS:
   2239  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
   2240  1.1.1.1.4.2  rmind 			*tl++ = 0;
   2241  1.1.1.1.4.2  rmind 			*tl = 0;
   2242  1.1.1.1.4.2  rmind 			retnum += 2 * NFSX_UNSIGNED;
   2243  1.1.1.1.4.2  rmind 			break;
   2244  1.1.1.1.4.2  rmind 		case NFSATTRBIT_HOMOGENEOUS:
   2245  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2246  1.1.1.1.4.2  rmind 			if (fsinf.fs_properties & NFSV3FSINFO_HOMOGENEOUS)
   2247  1.1.1.1.4.2  rmind 				*tl = newnfs_true;
   2248  1.1.1.1.4.2  rmind 			else
   2249  1.1.1.1.4.2  rmind 				*tl = newnfs_false;
   2250  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2251  1.1.1.1.4.2  rmind 			break;
   2252  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MAXFILESIZE:
   2253  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2254  1.1.1.1.4.2  rmind 			uquad = NFSRV_MAXFILESIZE;
   2255  1.1.1.1.4.2  rmind 			txdr_hyper(uquad, tl);
   2256  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2257  1.1.1.1.4.2  rmind 			break;
   2258  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MAXLINK:
   2259  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2260  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(LINK_MAX);
   2261  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2262  1.1.1.1.4.2  rmind 			break;
   2263  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MAXNAME:
   2264  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2265  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(NFS_MAXNAMLEN);
   2266  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2267  1.1.1.1.4.2  rmind 			break;
   2268  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MAXREAD:
   2269  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2270  1.1.1.1.4.2  rmind 			*tl++ = 0;
   2271  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(fsinf.fs_rtmax);
   2272  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2273  1.1.1.1.4.2  rmind 			break;
   2274  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MAXWRITE:
   2275  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2276  1.1.1.1.4.2  rmind 			*tl++ = 0;
   2277  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(fsinf.fs_wtmax);
   2278  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2279  1.1.1.1.4.2  rmind 			break;
   2280  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MODE:
   2281  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2282  1.1.1.1.4.2  rmind 			*tl = vtonfsv34_mode(vap->va_mode);
   2283  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2284  1.1.1.1.4.2  rmind 			break;
   2285  1.1.1.1.4.2  rmind 		case NFSATTRBIT_NOTRUNC:
   2286  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2287  1.1.1.1.4.2  rmind 			*tl = newnfs_true;
   2288  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2289  1.1.1.1.4.2  rmind 			break;
   2290  1.1.1.1.4.2  rmind 		case NFSATTRBIT_NUMLINKS:
   2291  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2292  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(vap->va_nlink);
   2293  1.1.1.1.4.2  rmind 			retnum += NFSX_UNSIGNED;
   2294  1.1.1.1.4.2  rmind 			break;
   2295  1.1.1.1.4.2  rmind 		case NFSATTRBIT_OWNER:
   2296  1.1.1.1.4.2  rmind 			cp = namestr;
   2297  1.1.1.1.4.2  rmind 			nfsv4_uidtostr(vap->va_uid, &cp, &siz, p);
   2298  1.1.1.1.4.2  rmind 			retnum += nfsm_strtom(nd, cp, siz);
   2299  1.1.1.1.4.2  rmind 			if (cp != namestr)
   2300  1.1.1.1.4.2  rmind 				free(cp, M_NFSSTRING);
   2301  1.1.1.1.4.2  rmind 			break;
   2302  1.1.1.1.4.2  rmind 		case NFSATTRBIT_OWNERGROUP:
   2303  1.1.1.1.4.2  rmind 			cp = namestr;
   2304  1.1.1.1.4.2  rmind 			nfsv4_gidtostr(vap->va_gid, &cp, &siz, p);
   2305  1.1.1.1.4.2  rmind 			retnum += nfsm_strtom(nd, cp, siz);
   2306  1.1.1.1.4.2  rmind 			if (cp != namestr)
   2307  1.1.1.1.4.2  rmind 				free(cp, M_NFSSTRING);
   2308  1.1.1.1.4.2  rmind 			break;
   2309  1.1.1.1.4.2  rmind 		case NFSATTRBIT_QUOTAHARD:
   2310  1.1.1.1.4.2  rmind 			if (priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA, 0))
   2311  1.1.1.1.4.2  rmind 				freenum = fs.f_bfree;
   2312  1.1.1.1.4.2  rmind 			else
   2313  1.1.1.1.4.2  rmind 				freenum = fs.f_bavail;
   2314  1.1.1.1.4.2  rmind #ifdef QUOTA
   2315  1.1.1.1.4.2  rmind 			/*
   2316  1.1.1.1.4.2  rmind 			 * ufs_quotactl() insists that the uid argument
   2317  1.1.1.1.4.2  rmind 			 * equal p_ruid for non-root quota access, so
   2318  1.1.1.1.4.2  rmind 			 * we'll just make sure that's the case.
   2319  1.1.1.1.4.2  rmind 			 */
   2320  1.1.1.1.4.2  rmind 			savuid = p->p_cred->p_ruid;
   2321  1.1.1.1.4.2  rmind 			p->p_cred->p_ruid = cred->cr_uid;
   2322  1.1.1.1.4.2  rmind 			if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA),
   2323  1.1.1.1.4.2  rmind 			    cred->cr_uid, (caddr_t)&dqb))
   2324  1.1.1.1.4.2  rmind 			    freenum = min(dqb.dqb_bhardlimit, freenum);
   2325  1.1.1.1.4.2  rmind 			p->p_cred->p_ruid = savuid;
   2326  1.1.1.1.4.2  rmind #endif	/* QUOTA */
   2327  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2328  1.1.1.1.4.2  rmind 			uquad = (u_int64_t)freenum;
   2329  1.1.1.1.4.2  rmind 			NFSQUOTABLKTOBYTE(uquad, fs.f_bsize);
   2330  1.1.1.1.4.2  rmind 			txdr_hyper(uquad, tl);
   2331  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2332  1.1.1.1.4.2  rmind 			break;
   2333  1.1.1.1.4.2  rmind 		case NFSATTRBIT_QUOTASOFT:
   2334  1.1.1.1.4.2  rmind 			if (priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA, 0))
   2335  1.1.1.1.4.2  rmind 				freenum = fs.f_bfree;
   2336  1.1.1.1.4.2  rmind 			else
   2337  1.1.1.1.4.2  rmind 				freenum = fs.f_bavail;
   2338  1.1.1.1.4.2  rmind #ifdef QUOTA
   2339  1.1.1.1.4.2  rmind 			/*
   2340  1.1.1.1.4.2  rmind 			 * ufs_quotactl() insists that the uid argument
   2341  1.1.1.1.4.2  rmind 			 * equal p_ruid for non-root quota access, so
   2342  1.1.1.1.4.2  rmind 			 * we'll just make sure that's the case.
   2343  1.1.1.1.4.2  rmind 			 */
   2344  1.1.1.1.4.2  rmind 			savuid = p->p_cred->p_ruid;
   2345  1.1.1.1.4.2  rmind 			p->p_cred->p_ruid = cred->cr_uid;
   2346  1.1.1.1.4.2  rmind 			if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA),
   2347  1.1.1.1.4.2  rmind 			    cred->cr_uid, (caddr_t)&dqb))
   2348  1.1.1.1.4.2  rmind 			    freenum = min(dqb.dqb_bsoftlimit, freenum);
   2349  1.1.1.1.4.2  rmind 			p->p_cred->p_ruid = savuid;
   2350  1.1.1.1.4.2  rmind #endif	/* QUOTA */
   2351  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2352  1.1.1.1.4.2  rmind 			uquad = (u_int64_t)freenum;
   2353  1.1.1.1.4.2  rmind 			NFSQUOTABLKTOBYTE(uquad, fs.f_bsize);
   2354  1.1.1.1.4.2  rmind 			txdr_hyper(uquad, tl);
   2355  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2356  1.1.1.1.4.2  rmind 			break;
   2357  1.1.1.1.4.2  rmind 		case NFSATTRBIT_QUOTAUSED:
   2358  1.1.1.1.4.2  rmind 			freenum = 0;
   2359  1.1.1.1.4.2  rmind #ifdef QUOTA
   2360  1.1.1.1.4.2  rmind 			/*
   2361  1.1.1.1.4.2  rmind 			 * ufs_quotactl() insists that the uid argument
   2362  1.1.1.1.4.2  rmind 			 * equal p_ruid for non-root quota access, so
   2363  1.1.1.1.4.2  rmind 			 * we'll just make sure that's the case.
   2364  1.1.1.1.4.2  rmind 			 */
   2365  1.1.1.1.4.2  rmind 			savuid = p->p_cred->p_ruid;
   2366  1.1.1.1.4.2  rmind 			p->p_cred->p_ruid = cred->cr_uid;
   2367  1.1.1.1.4.2  rmind 			if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA),
   2368  1.1.1.1.4.2  rmind 			    cred->cr_uid, (caddr_t)&dqb))
   2369  1.1.1.1.4.2  rmind 			    freenum = dqb.dqb_curblocks;
   2370  1.1.1.1.4.2  rmind 			p->p_cred->p_ruid = savuid;
   2371  1.1.1.1.4.2  rmind #endif	/* QUOTA */
   2372  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2373  1.1.1.1.4.2  rmind 			uquad = (u_int64_t)freenum;
   2374  1.1.1.1.4.2  rmind 			NFSQUOTABLKTOBYTE(uquad, fs.f_bsize);
   2375  1.1.1.1.4.2  rmind 			txdr_hyper(uquad, tl);
   2376  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2377  1.1.1.1.4.2  rmind 			break;
   2378  1.1.1.1.4.2  rmind 		case NFSATTRBIT_RAWDEV:
   2379  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_V4SPECDATA);
   2380  1.1.1.1.4.2  rmind 			*tl++ = txdr_unsigned(NFSMAJOR(vap->va_rdev));
   2381  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(NFSMINOR(vap->va_rdev));
   2382  1.1.1.1.4.2  rmind 			retnum += NFSX_V4SPECDATA;
   2383  1.1.1.1.4.2  rmind 			break;
   2384  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SPACEAVAIL:
   2385  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2386  1.1.1.1.4.2  rmind 			if (priv_check_cred(cred, PRIV_VFS_BLOCKRESERVE, 0))
   2387  1.1.1.1.4.2  rmind 				uquad = (u_int64_t)fs.f_bfree;
   2388  1.1.1.1.4.2  rmind 			else
   2389  1.1.1.1.4.2  rmind 				uquad = (u_int64_t)fs.f_bavail;
   2390  1.1.1.1.4.2  rmind 			uquad *= fs.f_bsize;
   2391  1.1.1.1.4.2  rmind 			txdr_hyper(uquad, tl);
   2392  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2393  1.1.1.1.4.2  rmind 			break;
   2394  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SPACEFREE:
   2395  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2396  1.1.1.1.4.2  rmind 			uquad = (u_int64_t)fs.f_bfree;
   2397  1.1.1.1.4.2  rmind 			uquad *= fs.f_bsize;
   2398  1.1.1.1.4.2  rmind 			txdr_hyper(uquad, tl);
   2399  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2400  1.1.1.1.4.2  rmind 			break;
   2401  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SPACETOTAL:
   2402  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2403  1.1.1.1.4.2  rmind 			uquad = (u_int64_t)fs.f_blocks;
   2404  1.1.1.1.4.2  rmind 			uquad *= fs.f_bsize;
   2405  1.1.1.1.4.2  rmind 			txdr_hyper(uquad, tl);
   2406  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2407  1.1.1.1.4.2  rmind 			break;
   2408  1.1.1.1.4.2  rmind 		case NFSATTRBIT_SPACEUSED:
   2409  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2410  1.1.1.1.4.2  rmind 			txdr_hyper(vap->va_bytes, tl);
   2411  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2412  1.1.1.1.4.2  rmind 			break;
   2413  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TIMEACCESS:
   2414  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
   2415  1.1.1.1.4.2  rmind 			txdr_nfsv4time(&vap->va_atime, tl);
   2416  1.1.1.1.4.2  rmind 			retnum += NFSX_V4TIME;
   2417  1.1.1.1.4.2  rmind 			break;
   2418  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TIMEACCESSSET:
   2419  1.1.1.1.4.2  rmind 			if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
   2420  1.1.1.1.4.2  rmind 				NFSM_BUILD(tl, u_int32_t *, NFSX_V4SETTIME);
   2421  1.1.1.1.4.2  rmind 				*tl++ = txdr_unsigned(NFSV4SATTRTIME_TOCLIENT);
   2422  1.1.1.1.4.2  rmind 				txdr_nfsv4time(&vap->va_atime, tl);
   2423  1.1.1.1.4.2  rmind 				retnum += NFSX_V4SETTIME;
   2424  1.1.1.1.4.2  rmind 			} else {
   2425  1.1.1.1.4.2  rmind 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2426  1.1.1.1.4.2  rmind 				*tl = txdr_unsigned(NFSV4SATTRTIME_TOSERVER);
   2427  1.1.1.1.4.2  rmind 				retnum += NFSX_UNSIGNED;
   2428  1.1.1.1.4.2  rmind 			}
   2429  1.1.1.1.4.2  rmind 			break;
   2430  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TIMEDELTA:
   2431  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
   2432  1.1.1.1.4.2  rmind 			temptime.tv_sec = 0;
   2433  1.1.1.1.4.2  rmind 			temptime.tv_nsec = 1000000000 / hz;
   2434  1.1.1.1.4.2  rmind 			txdr_nfsv4time(&temptime, tl);
   2435  1.1.1.1.4.2  rmind 			retnum += NFSX_V4TIME;
   2436  1.1.1.1.4.2  rmind 			break;
   2437  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TIMEMETADATA:
   2438  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
   2439  1.1.1.1.4.2  rmind 			txdr_nfsv4time(&vap->va_ctime, tl);
   2440  1.1.1.1.4.2  rmind 			retnum += NFSX_V4TIME;
   2441  1.1.1.1.4.2  rmind 			break;
   2442  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TIMEMODIFY:
   2443  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
   2444  1.1.1.1.4.2  rmind 			txdr_nfsv4time(&vap->va_mtime, tl);
   2445  1.1.1.1.4.2  rmind 			retnum += NFSX_V4TIME;
   2446  1.1.1.1.4.2  rmind 			break;
   2447  1.1.1.1.4.2  rmind 		case NFSATTRBIT_TIMEMODIFYSET:
   2448  1.1.1.1.4.2  rmind 			if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
   2449  1.1.1.1.4.2  rmind 				NFSM_BUILD(tl, u_int32_t *, NFSX_V4SETTIME);
   2450  1.1.1.1.4.2  rmind 				*tl++ = txdr_unsigned(NFSV4SATTRTIME_TOCLIENT);
   2451  1.1.1.1.4.2  rmind 				txdr_nfsv4time(&vap->va_mtime, tl);
   2452  1.1.1.1.4.2  rmind 				retnum += NFSX_V4SETTIME;
   2453  1.1.1.1.4.2  rmind 			} else {
   2454  1.1.1.1.4.2  rmind 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   2455  1.1.1.1.4.2  rmind 				*tl = txdr_unsigned(NFSV4SATTRTIME_TOSERVER);
   2456  1.1.1.1.4.2  rmind 				retnum += NFSX_UNSIGNED;
   2457  1.1.1.1.4.2  rmind 			}
   2458  1.1.1.1.4.2  rmind 			break;
   2459  1.1.1.1.4.2  rmind 		case NFSATTRBIT_MOUNTEDONFILEID:
   2460  1.1.1.1.4.2  rmind 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
   2461  1.1.1.1.4.2  rmind 			if (at_root != 0)
   2462  1.1.1.1.4.2  rmind 				uquad = mounted_on_fileno;
   2463  1.1.1.1.4.2  rmind 			else
   2464  1.1.1.1.4.2  rmind 				uquad = (u_int64_t)vap->va_fileid;
   2465  1.1.1.1.4.2  rmind 			txdr_hyper(uquad, tl);
   2466  1.1.1.1.4.2  rmind 			retnum += NFSX_HYPER;
   2467  1.1.1.1.4.2  rmind 			break;
   2468  1.1.1.1.4.2  rmind 		default:
   2469  1.1.1.1.4.2  rmind 			printf("EEK! Bad V4 attribute bitpos=%d\n", bitpos);
   2470  1.1.1.1.4.2  rmind 		};
   2471  1.1.1.1.4.2  rmind 	    }
   2472  1.1.1.1.4.2  rmind 	}
   2473  1.1.1.1.4.2  rmind 	if (naclp != NULL)
   2474  1.1.1.1.4.2  rmind 		acl_free(naclp);
   2475  1.1.1.1.4.2  rmind 	*retnump = txdr_unsigned(retnum);
   2476  1.1.1.1.4.2  rmind 	return (retnum + prefixnum);
   2477  1.1.1.1.4.2  rmind }
   2478  1.1.1.1.4.2  rmind 
   2479  1.1.1.1.4.2  rmind /*
   2480  1.1.1.1.4.2  rmind  * Put the attribute bits onto an mbuf list.
   2481  1.1.1.1.4.2  rmind  * Return the number of bytes of output generated.
   2482  1.1.1.1.4.2  rmind  */
   2483  1.1.1.1.4.2  rmind APPLESTATIC int
   2484  1.1.1.1.4.2  rmind nfsrv_putattrbit(struct nfsrv_descript *nd, nfsattrbit_t *attrbitp)
   2485  1.1.1.1.4.2  rmind {
   2486  1.1.1.1.4.2  rmind 	u_int32_t *tl;
   2487  1.1.1.1.4.2  rmind 	int cnt, i, bytesize;
   2488  1.1.1.1.4.2  rmind 
   2489  1.1.1.1.4.2  rmind 	for (cnt = NFSATTRBIT_MAXWORDS; cnt > 0; cnt--)
   2490  1.1.1.1.4.2  rmind 		if (attrbitp->bits[cnt - 1])
   2491  1.1.1.1.4.2  rmind 			break;
   2492  1.1.1.1.4.2  rmind 	bytesize = (cnt + 1) * NFSX_UNSIGNED;
   2493  1.1.1.1.4.2  rmind 	NFSM_BUILD(tl, u_int32_t *, bytesize);
   2494  1.1.1.1.4.2  rmind 	*tl++ = txdr_unsigned(cnt);
   2495  1.1.1.1.4.2  rmind 	for (i = 0; i < cnt; i++)
   2496  1.1.1.1.4.2  rmind 		*tl++ = txdr_unsigned(attrbitp->bits[i]);
   2497  1.1.1.1.4.2  rmind 	return (bytesize);
   2498  1.1.1.1.4.2  rmind }
   2499  1.1.1.1.4.2  rmind 
   2500  1.1.1.1.4.2  rmind /*
   2501  1.1.1.1.4.2  rmind  * Convert a uid to a string.
   2502  1.1.1.1.4.2  rmind  * If the lookup fails, just output the digits.
   2503  1.1.1.1.4.2  rmind  * uid - the user id
   2504  1.1.1.1.4.2  rmind  * cpp - points to a buffer of size NFSV4_SMALLSTR
   2505  1.1.1.1.4.2  rmind  *       (malloc a larger one, as required)
   2506  1.1.1.1.4.2  rmind  * retlenp - pointer to length to be returned
   2507  1.1.1.1.4.2  rmind  */
   2508  1.1.1.1.4.2  rmind APPLESTATIC void
   2509  1.1.1.1.4.2  rmind nfsv4_uidtostr(uid_t uid, u_char **cpp, int *retlenp, NFSPROC_T *p)
   2510  1.1.1.1.4.2  rmind {
   2511  1.1.1.1.4.2  rmind 	int i;
   2512  1.1.1.1.4.2  rmind 	struct nfsusrgrp *usrp;
   2513  1.1.1.1.4.2  rmind 	u_char *cp = *cpp;
   2514  1.1.1.1.4.2  rmind 	uid_t tmp;
   2515  1.1.1.1.4.2  rmind 	int cnt, hasampersand, len = NFSV4_SMALLSTR, ret;
   2516  1.1.1.1.4.2  rmind 
   2517  1.1.1.1.4.2  rmind 	cnt = 0;
   2518  1.1.1.1.4.2  rmind tryagain:
   2519  1.1.1.1.4.2  rmind 	NFSLOCKNAMEID();
   2520  1.1.1.1.4.2  rmind 	if (nfsrv_dnsname) {
   2521  1.1.1.1.4.2  rmind 		/*
   2522  1.1.1.1.4.2  rmind 		 * Always map nfsrv_defaultuid to "nobody".
   2523  1.1.1.1.4.2  rmind 		 */
   2524  1.1.1.1.4.2  rmind 		if (uid == nfsrv_defaultuid) {
   2525  1.1.1.1.4.2  rmind 			i = nfsrv_dnsnamelen + 7;
   2526  1.1.1.1.4.2  rmind 			if (i > len) {
   2527  1.1.1.1.4.2  rmind 				NFSUNLOCKNAMEID();
   2528  1.1.1.1.4.2  rmind 				if (len > NFSV4_SMALLSTR)
   2529  1.1.1.1.4.2  rmind 					free(cp, M_NFSSTRING);
   2530  1.1.1.1.4.2  rmind 				cp = malloc(i, M_NFSSTRING, M_WAITOK);
   2531  1.1.1.1.4.2  rmind 				*cpp = cp;
   2532  1.1.1.1.4.2  rmind 				len = i;
   2533  1.1.1.1.4.2  rmind 				goto tryagain;
   2534  1.1.1.1.4.2  rmind 			}
   2535  1.1.1.1.4.2  rmind 			*retlenp = i;
   2536  1.1.1.1.4.2  rmind 			NFSBCOPY("nobody@", cp, 7);
   2537  1.1.1.1.4.2  rmind 			cp += 7;
   2538  1.1.1.1.4.2  rmind 			NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
   2539  1.1.1.1.4.2  rmind 			NFSUNLOCKNAMEID();
   2540  1.1.1.1.4.2  rmind 			return;
   2541  1.1.1.1.4.2  rmind 		}
   2542  1.1.1.1.4.2  rmind 		hasampersand = 0;
   2543  1.1.1.1.4.2  rmind 		LIST_FOREACH(usrp, NFSUSERHASH(uid), lug_numhash) {
   2544  1.1.1.1.4.2  rmind 			if (usrp->lug_uid == uid) {
   2545  1.1.1.1.4.2  rmind 				if (usrp->lug_expiry < NFSD_MONOSEC)
   2546  1.1.1.1.4.2  rmind 					break;
   2547  1.1.1.1.4.2  rmind 				/*
   2548  1.1.1.1.4.2  rmind 				 * If the name doesn't already have an '@'
   2549  1.1.1.1.4.2  rmind 				 * in it, append @domainname to it.
   2550  1.1.1.1.4.2  rmind 				 */
   2551  1.1.1.1.4.2  rmind 				for (i = 0; i < usrp->lug_namelen; i++) {
   2552  1.1.1.1.4.2  rmind 					if (usrp->lug_name[i] == '@') {
   2553  1.1.1.1.4.2  rmind 						hasampersand = 1;
   2554  1.1.1.1.4.2  rmind 						break;
   2555  1.1.1.1.4.2  rmind 					}
   2556  1.1.1.1.4.2  rmind 				}
   2557  1.1.1.1.4.2  rmind 				if (hasampersand)
   2558  1.1.1.1.4.2  rmind 					i = usrp->lug_namelen;
   2559  1.1.1.1.4.2  rmind 				else
   2560  1.1.1.1.4.2  rmind 					i = usrp->lug_namelen +
   2561  1.1.1.1.4.2  rmind 					    nfsrv_dnsnamelen + 1;
   2562  1.1.1.1.4.2  rmind 				if (i > len) {
   2563  1.1.1.1.4.2  rmind 					NFSUNLOCKNAMEID();
   2564  1.1.1.1.4.2  rmind 					if (len > NFSV4_SMALLSTR)
   2565  1.1.1.1.4.2  rmind 						free(cp, M_NFSSTRING);
   2566  1.1.1.1.4.2  rmind 					cp = malloc(i, M_NFSSTRING, M_WAITOK);
   2567  1.1.1.1.4.2  rmind 					*cpp = cp;
   2568  1.1.1.1.4.2  rmind 					len = i;
   2569  1.1.1.1.4.2  rmind 					goto tryagain;
   2570  1.1.1.1.4.2  rmind 				}
   2571  1.1.1.1.4.2  rmind 				*retlenp = i;
   2572  1.1.1.1.4.2  rmind 				NFSBCOPY(usrp->lug_name, cp, usrp->lug_namelen);
   2573  1.1.1.1.4.2  rmind 				if (!hasampersand) {
   2574  1.1.1.1.4.2  rmind 					cp += usrp->lug_namelen;
   2575  1.1.1.1.4.2  rmind 					*cp++ = '@';
   2576  1.1.1.1.4.2  rmind 					NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
   2577  1.1.1.1.4.2  rmind 				}
   2578  1.1.1.1.4.2  rmind 				TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
   2579  1.1.1.1.4.2  rmind 				TAILQ_INSERT_TAIL(&nfsuserlruhead, usrp, lug_lru);
   2580  1.1.1.1.4.2  rmind 				NFSUNLOCKNAMEID();
   2581  1.1.1.1.4.2  rmind 				return;
   2582  1.1.1.1.4.2  rmind 			}
   2583  1.1.1.1.4.2  rmind 		}
   2584  1.1.1.1.4.2  rmind 		NFSUNLOCKNAMEID();
   2585  1.1.1.1.4.2  rmind 		cnt++;
   2586  1.1.1.1.4.2  rmind 		ret = nfsrv_getuser(RPCNFSUSERD_GETUID, uid, (gid_t)0,
   2587  1.1.1.1.4.2  rmind 		    NULL, p);
   2588  1.1.1.1.4.2  rmind 		if (ret == 0 && cnt < 2)
   2589  1.1.1.1.4.2  rmind 			goto tryagain;
   2590  1.1.1.1.4.2  rmind 	} else {
   2591  1.1.1.1.4.2  rmind 		NFSUNLOCKNAMEID();
   2592  1.1.1.1.4.2  rmind 	}
   2593  1.1.1.1.4.2  rmind 
   2594  1.1.1.1.4.2  rmind 	/*
   2595  1.1.1.1.4.2  rmind 	 * No match, just return a string of digits.
   2596  1.1.1.1.4.2  rmind 	 */
   2597  1.1.1.1.4.2  rmind 	tmp = uid;
   2598  1.1.1.1.4.2  rmind 	i = 0;
   2599  1.1.1.1.4.2  rmind 	while (tmp || i == 0) {
   2600  1.1.1.1.4.2  rmind 		tmp /= 10;
   2601  1.1.1.1.4.2  rmind 		i++;
   2602  1.1.1.1.4.2  rmind 	}
   2603  1.1.1.1.4.2  rmind 	len = (i > len) ? len : i;
   2604  1.1.1.1.4.2  rmind 	*retlenp = len;
   2605  1.1.1.1.4.2  rmind 	cp += (len - 1);
   2606  1.1.1.1.4.2  rmind 	tmp = uid;
   2607  1.1.1.1.4.2  rmind 	for (i = 0; i < len; i++) {
   2608  1.1.1.1.4.2  rmind 		*cp-- = '0' + (tmp % 10);
   2609  1.1.1.1.4.2  rmind 		tmp /= 10;
   2610  1.1.1.1.4.2  rmind 	}
   2611  1.1.1.1.4.2  rmind 	return;
   2612  1.1.1.1.4.2  rmind }
   2613  1.1.1.1.4.2  rmind 
   2614  1.1.1.1.4.2  rmind /*
   2615  1.1.1.1.4.2  rmind  * Convert a string to a uid.
   2616  1.1.1.1.4.2  rmind  * If no conversion is possible return NFSERR_BADOWNER, otherwise
   2617  1.1.1.1.4.2  rmind  * return 0.
   2618  1.1.1.1.4.2  rmind  * If this is called from a client side mount using AUTH_SYS and the
   2619  1.1.1.1.4.2  rmind  * string is made up entirely of digits, just convert the string to
   2620  1.1.1.1.4.2  rmind  * a number.
   2621  1.1.1.1.4.2  rmind  */
   2622  1.1.1.1.4.2  rmind APPLESTATIC int
   2623  1.1.1.1.4.2  rmind nfsv4_strtouid(struct nfsrv_descript *nd, u_char *str, int len, uid_t *uidp,
   2624  1.1.1.1.4.2  rmind     NFSPROC_T *p)
   2625  1.1.1.1.4.2  rmind {
   2626  1.1.1.1.4.2  rmind 	int i;
   2627  1.1.1.1.4.2  rmind 	char *cp, *endstr, *str0;
   2628  1.1.1.1.4.2  rmind 	struct nfsusrgrp *usrp;
   2629  1.1.1.1.4.2  rmind 	int cnt, ret;
   2630  1.1.1.1.4.2  rmind 	int error = 0;
   2631  1.1.1.1.4.2  rmind 	uid_t tuid;
   2632  1.1.1.1.4.2  rmind 
   2633  1.1.1.1.4.2  rmind 	if (len == 0) {
   2634  1.1.1.1.4.2  rmind 		error = NFSERR_BADOWNER;
   2635  1.1.1.1.4.2  rmind 		goto out;
   2636  1.1.1.1.4.2  rmind 	}
   2637  1.1.1.1.4.2  rmind 	/* If a string of digits and an AUTH_SYS mount, just convert it. */
   2638  1.1.1.1.4.2  rmind 	str0 = str;
   2639  1.1.1.1.4.2  rmind 	tuid = (uid_t)strtoul(str0, &endstr, 10);
   2640  1.1.1.1.4.2  rmind 	if ((endstr - str0) == len &&
   2641  1.1.1.1.4.2  rmind 	    (nd->nd_flag & (ND_KERBV | ND_NFSCL)) == ND_NFSCL) {
   2642  1.1.1.1.4.2  rmind 		*uidp = tuid;
   2643  1.1.1.1.4.2  rmind 		goto out;
   2644  1.1.1.1.4.2  rmind 	}
   2645  1.1.1.1.4.2  rmind 	/*
   2646  1.1.1.1.4.2  rmind 	 * Look for an '@'.
   2647  1.1.1.1.4.2  rmind 	 */
   2648  1.1.1.1.4.2  rmind 	cp = strchr(str0, '@');
   2649  1.1.1.1.4.2  rmind 	if (cp != NULL)
   2650  1.1.1.1.4.2  rmind 		i = (int)(cp++ - str0);
   2651  1.1.1.1.4.2  rmind 	else
   2652  1.1.1.1.4.2  rmind 		i = len;
   2653  1.1.1.1.4.2  rmind 
   2654  1.1.1.1.4.2  rmind 	cnt = 0;
   2655  1.1.1.1.4.2  rmind tryagain:
   2656  1.1.1.1.4.2  rmind 	NFSLOCKNAMEID();
   2657  1.1.1.1.4.2  rmind 	/*
   2658  1.1.1.1.4.2  rmind 	 * If an '@' is found and the domain name matches, search for the name
   2659  1.1.1.1.4.2  rmind 	 * with dns stripped off.
   2660  1.1.1.1.4.2  rmind 	 * Mixed case alpahbetics will match for the domain name, but all
   2661  1.1.1.1.4.2  rmind 	 * upper case will not.
   2662  1.1.1.1.4.2  rmind 	 */
   2663  1.1.1.1.4.2  rmind 	if (cnt == 0 && i < len && i > 0 && nfsrv_dnsname &&
   2664  1.1.1.1.4.2  rmind 	    (len - 1 - i) == nfsrv_dnsnamelen &&
   2665  1.1.1.1.4.2  rmind 	    !nfsrv_cmpmixedcase(cp, nfsrv_dnsname, nfsrv_dnsnamelen)) {
   2666  1.1.1.1.4.2  rmind 		len -= (nfsrv_dnsnamelen + 1);
   2667  1.1.1.1.4.2  rmind 		*(cp - 1) = '\0';
   2668  1.1.1.1.4.2  rmind 	}
   2669  1.1.1.1.4.2  rmind 
   2670  1.1.1.1.4.2  rmind 	/*
   2671  1.1.1.1.4.2  rmind 	 * Check for the special case of "nobody".
   2672  1.1.1.1.4.2  rmind 	 */
   2673  1.1.1.1.4.2  rmind 	if (len == 6 && !NFSBCMP(str, "nobody", 6)) {
   2674  1.1.1.1.4.2  rmind 		*uidp = nfsrv_defaultuid;
   2675  1.1.1.1.4.2  rmind 		NFSUNLOCKNAMEID();
   2676  1.1.1.1.4.2  rmind 		error = 0;
   2677  1.1.1.1.4.2  rmind 		goto out;
   2678  1.1.1.1.4.2  rmind 	}
   2679  1.1.1.1.4.2  rmind 
   2680  1.1.1.1.4.2  rmind 	LIST_FOREACH(usrp, NFSUSERNAMEHASH(str, len), lug_namehash) {
   2681  1.1.1.1.4.2  rmind 		if (usrp->lug_namelen == len &&
   2682  1.1.1.1.4.2  rmind 		    !NFSBCMP(usrp->lug_name, str, len)) {
   2683  1.1.1.1.4.2  rmind 			if (usrp->lug_expiry < NFSD_MONOSEC)
   2684  1.1.1.1.4.2  rmind 				break;
   2685  1.1.1.1.4.2  rmind 			*uidp = usrp->lug_uid;
   2686  1.1.1.1.4.2  rmind 			TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
   2687  1.1.1.1.4.2  rmind 			TAILQ_INSERT_TAIL(&nfsuserlruhead, usrp, lug_lru);
   2688  1.1.1.1.4.2  rmind 			NFSUNLOCKNAMEID();
   2689  1.1.1.1.4.2  rmind 			error = 0;
   2690  1.1.1.1.4.2  rmind 			goto out;
   2691  1.1.1.1.4.2  rmind 		}
   2692  1.1.1.1.4.2  rmind 	}
   2693  1.1.1.1.4.2  rmind 	NFSUNLOCKNAMEID();
   2694  1.1.1.1.4.2  rmind 	cnt++;
   2695  1.1.1.1.4.2  rmind 	ret = nfsrv_getuser(RPCNFSUSERD_GETUSER, (uid_t)0, (gid_t)0,
   2696  1.1.1.1.4.2  rmind 	    str, p);
   2697  1.1.1.1.4.2  rmind 	if (ret == 0 && cnt < 2)
   2698  1.1.1.1.4.2  rmind 		goto tryagain;
   2699  1.1.1.1.4.2  rmind 	error = NFSERR_BADOWNER;
   2700  1.1.1.1.4.2  rmind 
   2701  1.1.1.1.4.2  rmind out:
   2702  1.1.1.1.4.2  rmind 	NFSEXITCODE(error);
   2703  1.1.1.1.4.2  rmind 	return (error);
   2704  1.1.1.1.4.2  rmind }
   2705  1.1.1.1.4.2  rmind 
   2706  1.1.1.1.4.2  rmind /*
   2707  1.1.1.1.4.2  rmind  * Convert a gid to a string.
   2708  1.1.1.1.4.2  rmind  * gid - the group id
   2709  1.1.1.1.4.2  rmind  * cpp - points to a buffer of size NFSV4_SMALLSTR
   2710  1.1.1.1.4.2  rmind  *       (malloc a larger one, as required)
   2711  1.1.1.1.4.2  rmind  * retlenp - pointer to length to be returned
   2712  1.1.1.1.4.2  rmind  */
   2713  1.1.1.1.4.2  rmind APPLESTATIC void
   2714  1.1.1.1.4.2  rmind nfsv4_gidtostr(gid_t gid, u_char **cpp, int *retlenp, NFSPROC_T *p)
   2715  1.1.1.1.4.2  rmind {
   2716  1.1.1.1.4.2  rmind 	int i;
   2717  1.1.1.1.4.2  rmind 	struct nfsusrgrp *usrp;
   2718  1.1.1.1.4.2  rmind 	u_char *cp = *cpp;
   2719  1.1.1.1.4.2  rmind 	gid_t tmp;
   2720  1.1.1.1.4.2  rmind 	int cnt, hasampersand, len = NFSV4_SMALLSTR, ret;
   2721  1.1.1.1.4.2  rmind 
   2722  1.1.1.1.4.2  rmind 	cnt = 0;
   2723  1.1.1.1.4.2  rmind tryagain:
   2724  1.1.1.1.4.2  rmind 	NFSLOCKNAMEID();
   2725  1.1.1.1.4.2  rmind 	if (nfsrv_dnsname) {
   2726  1.1.1.1.4.2  rmind 		/*
   2727  1.1.1.1.4.2  rmind 		 * Always map nfsrv_defaultgid to "nogroup".
   2728  1.1.1.1.4.2  rmind 		 */
   2729  1.1.1.1.4.2  rmind 		if (gid == nfsrv_defaultgid) {
   2730  1.1.1.1.4.2  rmind 			i = nfsrv_dnsnamelen + 8;
   2731  1.1.1.1.4.2  rmind 			if (i > len) {
   2732  1.1.1.1.4.2  rmind 				NFSUNLOCKNAMEID();
   2733  1.1.1.1.4.2  rmind 				if (len > NFSV4_SMALLSTR)
   2734  1.1.1.1.4.2  rmind 					free(cp, M_NFSSTRING);
   2735  1.1.1.1.4.2  rmind 				cp = malloc(i, M_NFSSTRING, M_WAITOK);
   2736  1.1.1.1.4.2  rmind 				*cpp = cp;
   2737  1.1.1.1.4.2  rmind 				len = i;
   2738  1.1.1.1.4.2  rmind 				goto tryagain;
   2739  1.1.1.1.4.2  rmind 			}
   2740  1.1.1.1.4.2  rmind 			*retlenp = i;
   2741  1.1.1.1.4.2  rmind 			NFSBCOPY("nogroup@", cp, 8);
   2742  1.1.1.1.4.2  rmind 			cp += 8;
   2743  1.1.1.1.4.2  rmind 			NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
   2744  1.1.1.1.4.2  rmind 			NFSUNLOCKNAMEID();
   2745  1.1.1.1.4.2  rmind 			return;
   2746  1.1.1.1.4.2  rmind 		}
   2747  1.1.1.1.4.2  rmind 		hasampersand = 0;
   2748  1.1.1.1.4.2  rmind 		LIST_FOREACH(usrp, NFSGROUPHASH(gid), lug_numhash) {
   2749  1.1.1.1.4.2  rmind 			if (usrp->lug_gid == gid) {
   2750  1.1.1.1.4.2  rmind 				if (usrp->lug_expiry < NFSD_MONOSEC)
   2751  1.1.1.1.4.2  rmind 					break;
   2752  1.1.1.1.4.2  rmind 				/*
   2753  1.1.1.1.4.2  rmind 				 * If the name doesn't already have an '@'
   2754  1.1.1.1.4.2  rmind 				 * in it, append @domainname to it.
   2755  1.1.1.1.4.2  rmind 				 */
   2756  1.1.1.1.4.2  rmind 				for (i = 0; i < usrp->lug_namelen; i++) {
   2757  1.1.1.1.4.2  rmind 					if (usrp->lug_name[i] == '@') {
   2758  1.1.1.1.4.2  rmind 						hasampersand = 1;
   2759  1.1.1.1.4.2  rmind 						break;
   2760  1.1.1.1.4.2  rmind 					}
   2761  1.1.1.1.4.2  rmind 				}
   2762  1.1.1.1.4.2  rmind 				if (hasampersand)
   2763  1.1.1.1.4.2  rmind 					i = usrp->lug_namelen;
   2764  1.1.1.1.4.2  rmind 				else
   2765  1.1.1.1.4.2  rmind 					i = usrp->lug_namelen +
   2766  1.1.1.1.4.2  rmind 					    nfsrv_dnsnamelen + 1;
   2767  1.1.1.1.4.2  rmind 				if (i > len) {
   2768  1.1.1.1.4.2  rmind 					NFSUNLOCKNAMEID();
   2769  1.1.1.1.4.2  rmind 					if (len > NFSV4_SMALLSTR)
   2770  1.1.1.1.4.2  rmind 						free(cp, M_NFSSTRING);
   2771  1.1.1.1.4.2  rmind 					cp = malloc(i, M_NFSSTRING, M_WAITOK);
   2772  1.1.1.1.4.2  rmind 					*cpp = cp;
   2773  1.1.1.1.4.2  rmind 					len = i;
   2774  1.1.1.1.4.2  rmind 					goto tryagain;
   2775  1.1.1.1.4.2  rmind 				}
   2776  1.1.1.1.4.2  rmind 				*retlenp = i;
   2777  1.1.1.1.4.2  rmind 				NFSBCOPY(usrp->lug_name, cp, usrp->lug_namelen);
   2778  1.1.1.1.4.2  rmind 				if (!hasampersand) {
   2779  1.1.1.1.4.2  rmind 					cp += usrp->lug_namelen;
   2780  1.1.1.1.4.2  rmind 					*cp++ = '@';
   2781  1.1.1.1.4.2  rmind 					NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
   2782  1.1.1.1.4.2  rmind 				}
   2783  1.1.1.1.4.2  rmind 				TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
   2784  1.1.1.1.4.2  rmind 				TAILQ_INSERT_TAIL(&nfsuserlruhead, usrp, lug_lru);
   2785  1.1.1.1.4.2  rmind 				NFSUNLOCKNAMEID();
   2786  1.1.1.1.4.2  rmind 				return;
   2787  1.1.1.1.4.2  rmind 			}
   2788  1.1.1.1.4.2  rmind 		}
   2789  1.1.1.1.4.2  rmind 		NFSUNLOCKNAMEID();
   2790  1.1.1.1.4.2  rmind 		cnt++;
   2791  1.1.1.1.4.2  rmind 		ret = nfsrv_getuser(RPCNFSUSERD_GETGID, (uid_t)0, gid,
   2792  1.1.1.1.4.2  rmind 		    NULL, p);
   2793  1.1.1.1.4.2  rmind 		if (ret == 0 && cnt < 2)
   2794  1.1.1.1.4.2  rmind 			goto tryagain;
   2795  1.1.1.1.4.2  rmind 	} else {
   2796  1.1.1.1.4.2  rmind 		NFSUNLOCKNAMEID();
   2797  1.1.1.1.4.2  rmind 	}
   2798  1.1.1.1.4.2  rmind 
   2799  1.1.1.1.4.2  rmind 	/*
   2800  1.1.1.1.4.2  rmind 	 * No match, just return a string of digits.
   2801  1.1.1.1.4.2  rmind 	 */
   2802  1.1.1.1.4.2  rmind 	tmp = gid;
   2803  1.1.1.1.4.2  rmind 	i = 0;
   2804  1.1.1.1.4.2  rmind 	while (tmp || i == 0) {
   2805  1.1.1.1.4.2  rmind 		tmp /= 10;
   2806  1.1.1.1.4.2  rmind 		i++;
   2807  1.1.1.1.4.2  rmind 	}
   2808  1.1.1.1.4.2  rmind 	len = (i > len) ? len : i;
   2809  1.1.1.1.4.2  rmind 	*retlenp = len;
   2810  1.1.1.1.4.2  rmind 	cp += (len - 1);
   2811  1.1.1.1.4.2  rmind 	tmp = gid;
   2812  1.1.1.1.4.2  rmind 	for (i = 0; i < len; i++) {
   2813  1.1.1.1.4.2  rmind 		*cp-- = '0' + (tmp % 10);
   2814  1.1.1.1.4.2  rmind 		tmp /= 10;
   2815  1.1.1.1.4.2  rmind 	}
   2816  1.1.1.1.4.2  rmind 	return;
   2817  1.1.1.1.4.2  rmind }
   2818  1.1.1.1.4.2  rmind 
   2819  1.1.1.1.4.2  rmind /*
   2820  1.1.1.1.4.2  rmind  * Convert a string to a gid.
   2821  1.1.1.1.4.2  rmind  * If no conversion is possible return NFSERR_BADOWNER, otherwise
   2822  1.1.1.1.4.2  rmind  * return 0.
   2823  1.1.1.1.4.2  rmind  * If this is called from a client side mount using AUTH_SYS and the
   2824  1.1.1.1.4.2  rmind  * string is made up entirely of digits, just convert the string to
   2825  1.1.1.1.4.2  rmind  * a number.
   2826  1.1.1.1.4.2  rmind  */
   2827  1.1.1.1.4.2  rmind APPLESTATIC int
   2828  1.1.1.1.4.2  rmind nfsv4_strtogid(struct nfsrv_descript *nd, u_char *str, int len, gid_t *gidp,
   2829  1.1.1.1.4.2  rmind     NFSPROC_T *p)
   2830  1.1.1.1.4.2  rmind {
   2831  1.1.1.1.4.2  rmind 	int i;
   2832  1.1.1.1.4.2  rmind 	char *cp, *endstr, *str0;
   2833  1.1.1.1.4.2  rmind 	struct nfsusrgrp *usrp;
   2834  1.1.1.1.4.2  rmind 	int cnt, ret;
   2835  1.1.1.1.4.2  rmind 	int error = 0;
   2836  1.1.1.1.4.2  rmind 	gid_t tgid;
   2837  1.1.1.1.4.2  rmind 
   2838  1.1.1.1.4.2  rmind 	if (len == 0) {
   2839  1.1.1.1.4.2  rmind 		error =  NFSERR_BADOWNER;
   2840  1.1.1.1.4.2  rmind 		goto out;
   2841  1.1.1.1.4.2  rmind 	}
   2842  1.1.1.1.4.2  rmind 	/* If a string of digits and an AUTH_SYS mount, just convert it. */
   2843  1.1.1.1.4.2  rmind 	str0 = str;
   2844  1.1.1.1.4.2  rmind 	tgid = (gid_t)strtoul(str0, &endstr, 10);
   2845  1.1.1.1.4.2  rmind 	if ((endstr - str0) == len &&
   2846  1.1.1.1.4.2  rmind 	    (nd->nd_flag & (ND_KERBV | ND_NFSCL)) == ND_NFSCL) {
   2847  1.1.1.1.4.2  rmind 		*gidp = tgid;
   2848  1.1.1.1.4.2  rmind 		goto out;
   2849  1.1.1.1.4.2  rmind 	}
   2850  1.1.1.1.4.2  rmind 	/*
   2851  1.1.1.1.4.2  rmind 	 * Look for an '@'.
   2852  1.1.1.1.4.2  rmind 	 */
   2853  1.1.1.1.4.2  rmind 	cp = strchr(str0, '@');
   2854  1.1.1.1.4.2  rmind 	if (cp != NULL)
   2855  1.1.1.1.4.2  rmind 		i = (int)(cp++ - str0);
   2856  1.1.1.1.4.2  rmind 	else
   2857  1.1.1.1.4.2  rmind 		i = len;
   2858  1.1.1.1.4.2  rmind 
   2859  1.1.1.1.4.2  rmind 	cnt = 0;
   2860  1.1.1.1.4.2  rmind tryagain:
   2861  1.1.1.1.4.2  rmind 	NFSLOCKNAMEID();
   2862  1.1.1.1.4.2  rmind 	/*
   2863  1.1.1.1.4.2  rmind 	 * If an '@' is found and the dns name matches, search for the name
   2864  1.1.1.1.4.2  rmind 	 * with the dns stripped off.
   2865  1.1.1.1.4.2  rmind 	 */
   2866  1.1.1.1.4.2  rmind 	if (cnt == 0 && i < len && i > 0 && nfsrv_dnsname &&
   2867  1.1.1.1.4.2  rmind 	    (len - 1 - i) == nfsrv_dnsnamelen &&
   2868  1.1.1.1.4.2  rmind 	    !nfsrv_cmpmixedcase(cp, nfsrv_dnsname, nfsrv_dnsnamelen)) {
   2869  1.1.1.1.4.2  rmind 		len -= (nfsrv_dnsnamelen + 1);
   2870  1.1.1.1.4.2  rmind 		*(cp - 1) = '\0';
   2871  1.1.1.1.4.2  rmind 	}
   2872  1.1.1.1.4.2  rmind 
   2873  1.1.1.1.4.2  rmind 	/*
   2874  1.1.1.1.4.2  rmind 	 * Check for the special case of "nogroup".
   2875  1.1.1.1.4.2  rmind 	 */
   2876  1.1.1.1.4.2  rmind 	if (len == 7 && !NFSBCMP(str, "nogroup", 7)) {
   2877  1.1.1.1.4.2  rmind 		*gidp = nfsrv_defaultgid;
   2878  1.1.1.1.4.2  rmind 		NFSUNLOCKNAMEID();
   2879  1.1.1.1.4.2  rmind 		error = 0;
   2880  1.1.1.1.4.2  rmind 		goto out;
   2881  1.1.1.1.4.2  rmind 	}
   2882  1.1.1.1.4.2  rmind 
   2883  1.1.1.1.4.2  rmind 	LIST_FOREACH(usrp, NFSGROUPNAMEHASH(str, len), lug_namehash) {
   2884  1.1.1.1.4.2  rmind 		if (usrp->lug_namelen == len &&
   2885  1.1.1.1.4.2  rmind 		    !NFSBCMP(usrp->lug_name, str, len)) {
   2886  1.1.1.1.4.2  rmind 			if (usrp->lug_expiry < NFSD_MONOSEC)
   2887  1.1.1.1.4.2  rmind 				break;
   2888  1.1.1.1.4.2  rmind 			*gidp = usrp->lug_gid;
   2889  1.1.1.1.4.2  rmind 			TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
   2890  1.1.1.1.4.2  rmind 			TAILQ_INSERT_TAIL(&nfsuserlruhead, usrp, lug_lru);
   2891  1.1.1.1.4.2  rmind 			NFSUNLOCKNAMEID();
   2892  1.1.1.1.4.2  rmind 			error = 0;
   2893  1.1.1.1.4.2  rmind 			goto out;
   2894  1.1.1.1.4.2  rmind 		}
   2895  1.1.1.1.4.2  rmind 	}
   2896  1.1.1.1.4.2  rmind 	NFSUNLOCKNAMEID();
   2897  1.1.1.1.4.2  rmind 	cnt++;
   2898  1.1.1.1.4.2  rmind 	ret = nfsrv_getuser(RPCNFSUSERD_GETGROUP, (uid_t)0, (gid_t)0,
   2899  1.1.1.1.4.2  rmind 	    str, p);
   2900  1.1.1.1.4.2  rmind 	if (ret == 0 && cnt < 2)
   2901  1.1.1.1.4.2  rmind 		goto tryagain;
   2902  1.1.1.1.4.2  rmind 	error = NFSERR_BADOWNER;
   2903  1.1.1.1.4.2  rmind 
   2904  1.1.1.1.4.2  rmind out:
   2905  1.1.1.1.4.2  rmind 	NFSEXITCODE(error);
   2906  1.1.1.1.4.2  rmind 	return (error);
   2907  1.1.1.1.4.2  rmind }
   2908  1.1.1.1.4.2  rmind 
   2909  1.1.1.1.4.2  rmind /*
   2910  1.1.1.1.4.2  rmind  * Cmp len chars, allowing mixed case in the first argument to match lower
   2911  1.1.1.1.4.2  rmind  * case in the second, but not if the first argument is all upper case.
   2912  1.1.1.1.4.2  rmind  * Return 0 for a match, 1 otherwise.
   2913  1.1.1.1.4.2  rmind  */
   2914  1.1.1.1.4.2  rmind static int
   2915  1.1.1.1.4.2  rmind nfsrv_cmpmixedcase(u_char *cp, u_char *cp2, int len)
   2916  1.1.1.1.4.2  rmind {
   2917  1.1.1.1.4.2  rmind 	int i;
   2918  1.1.1.1.4.2  rmind 	u_char tmp;
   2919  1.1.1.1.4.2  rmind 	int fndlower = 0;
   2920  1.1.1.1.4.2  rmind 
   2921  1.1.1.1.4.2  rmind 	for (i = 0; i < len; i++) {
   2922  1.1.1.1.4.2  rmind 		if (*cp >= 'A' && *cp <= 'Z') {
   2923  1.1.1.1.4.2  rmind 			tmp = *cp++ + ('a' - 'A');
   2924  1.1.1.1.4.2  rmind 		} else {
   2925  1.1.1.1.4.2  rmind 			tmp = *cp++;
   2926  1.1.1.1.4.2  rmind 			if (tmp >= 'a' && tmp <= 'z')
   2927  1.1.1.1.4.2  rmind 				fndlower = 1;
   2928  1.1.1.1.4.2  rmind 		}
   2929  1.1.1.1.4.2  rmind 		if (tmp != *cp2++)
   2930  1.1.1.1.4.2  rmind 			return (1);
   2931  1.1.1.1.4.2  rmind 	}
   2932  1.1.1.1.4.2  rmind 	if (fndlower)
   2933  1.1.1.1.4.2  rmind 		return (0);
   2934  1.1.1.1.4.2  rmind 	else
   2935  1.1.1.1.4.2  rmind 		return (1);
   2936  1.1.1.1.4.2  rmind }
   2937  1.1.1.1.4.2  rmind 
   2938  1.1.1.1.4.2  rmind /*
   2939  1.1.1.1.4.2  rmind  * Set the port for the nfsuserd.
   2940  1.1.1.1.4.2  rmind  */
   2941  1.1.1.1.4.2  rmind APPLESTATIC int
   2942  1.1.1.1.4.2  rmind nfsrv_nfsuserdport(u_short port, NFSPROC_T *p)
   2943  1.1.1.1.4.2  rmind {
   2944  1.1.1.1.4.2  rmind 	struct nfssockreq *rp;
   2945  1.1.1.1.4.2  rmind 	struct sockaddr_in *ad;
   2946  1.1.1.1.4.2  rmind 	int error;
   2947  1.1.1.1.4.2  rmind 
   2948  1.1.1.1.4.2  rmind 	NFSLOCKNAMEID();
   2949  1.1.1.1.4.2  rmind 	if (nfsrv_nfsuserd) {
   2950  1.1.1.1.4.2  rmind 		NFSUNLOCKNAMEID();
   2951  1.1.1.1.4.2  rmind 		error = EPERM;
   2952  1.1.1.1.4.2  rmind 		goto out;
   2953  1.1.1.1.4.2  rmind 	}
   2954  1.1.1.1.4.2  rmind 	nfsrv_nfsuserd = 1;
   2955  1.1.1.1.4.2  rmind 	NFSUNLOCKNAMEID();
   2956  1.1.1.1.4.2  rmind 	/*
   2957  1.1.1.1.4.2  rmind 	 * Set up the socket record and connect.
   2958  1.1.1.1.4.2  rmind 	 */
   2959  1.1.1.1.4.2  rmind 	rp = &nfsrv_nfsuserdsock;
   2960  1.1.1.1.4.2  rmind 	rp->nr_client = NULL;
   2961  1.1.1.1.4.2  rmind 	rp->nr_sotype = SOCK_DGRAM;
   2962  1.1.1.1.4.2  rmind 	rp->nr_soproto = IPPROTO_UDP;
   2963  1.1.1.1.4.2  rmind 	rp->nr_lock = (NFSR_RESERVEDPORT | NFSR_LOCALHOST);
   2964  1.1.1.1.4.2  rmind 	rp->nr_cred = NULL;
   2965  1.1.1.1.4.2  rmind 	NFSSOCKADDRALLOC(rp->nr_nam);
   2966  1.1.1.1.4.2  rmind 	NFSSOCKADDRSIZE(rp->nr_nam, sizeof (struct sockaddr_in));
   2967  1.1.1.1.4.2  rmind 	ad = NFSSOCKADDR(rp->nr_nam, struct sockaddr_in *);
   2968  1.1.1.1.4.2  rmind 	ad->sin_family = AF_INET;
   2969  1.1.1.1.4.2  rmind 	ad->sin_addr.s_addr = htonl((u_int32_t)0x7f000001);	/* 127.0.0.1 */
   2970  1.1.1.1.4.2  rmind 	ad->sin_port = port;
   2971  1.1.1.1.4.2  rmind 	rp->nr_prog = RPCPROG_NFSUSERD;
   2972  1.1.1.1.4.2  rmind 	rp->nr_vers = RPCNFSUSERD_VERS;
   2973  1.1.1.1.4.2  rmind 	error = newnfs_connect(NULL, rp, NFSPROCCRED(p), p, 0);
   2974  1.1.1.1.4.2  rmind 	if (error) {
   2975  1.1.1.1.4.2  rmind 		NFSSOCKADDRFREE(rp->nr_nam);
   2976  1.1.1.1.4.2  rmind 		nfsrv_nfsuserd = 0;
   2977  1.1.1.1.4.2  rmind 	}
   2978  1.1.1.1.4.2  rmind out:
   2979  1.1.1.1.4.2  rmind 	NFSEXITCODE(error);
   2980  1.1.1.1.4.2  rmind 	return (error);
   2981  1.1.1.1.4.2  rmind }
   2982  1.1.1.1.4.2  rmind 
   2983  1.1.1.1.4.2  rmind /*
   2984  1.1.1.1.4.2  rmind  * Delete the nfsuserd port.
   2985  1.1.1.1.4.2  rmind  */
   2986  1.1.1.1.4.2  rmind APPLESTATIC void
   2987  1.1.1.1.4.2  rmind nfsrv_nfsuserddelport(void)
   2988  1.1.1.1.4.2  rmind {
   2989  1.1.1.1.4.2  rmind 
   2990  1.1.1.1.4.2  rmind 	NFSLOCKNAMEID();
   2991  1.1.1.1.4.2  rmind 	if (nfsrv_nfsuserd == 0) {
   2992  1.1.1.1.4.2  rmind 		NFSUNLOCKNAMEID();
   2993  1.1.1.1.4.2  rmind 		return;
   2994  1.1.1.1.4.2  rmind 	}
   2995  1.1.1.1.4.2  rmind 	nfsrv_nfsuserd = 0;
   2996  1.1.1.1.4.2  rmind 	NFSUNLOCKNAMEID();
   2997  1.1.1.1.4.2  rmind 	newnfs_disconnect(&nfsrv_nfsuserdsock);
   2998  1.1.1.1.4.2  rmind 	NFSSOCKADDRFREE(nfsrv_nfsuserdsock.nr_nam);
   2999  1.1.1.1.4.2  rmind }
   3000  1.1.1.1.4.2  rmind 
   3001  1.1.1.1.4.2  rmind /*
   3002  1.1.1.1.4.2  rmind  * Do upcalls to the nfsuserd, for cache misses of the owner/ownergroup
   3003  1.1.1.1.4.2  rmind  * name<-->id cache.
   3004  1.1.1.1.4.2  rmind  * Returns 0 upon success, non-zero otherwise.
   3005  1.1.1.1.4.2  rmind  */
   3006  1.1.1.1.4.2  rmind static int
   3007  1.1.1.1.4.2  rmind nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name, NFSPROC_T *p)
   3008  1.1.1.1.4.2  rmind {
   3009  1.1.1.1.4.2  rmind 	u_int32_t *tl;
   3010  1.1.1.1.4.2  rmind 	struct nfsrv_descript *nd;
   3011  1.1.1.1.4.2  rmind 	int len;
   3012  1.1.1.1.4.2  rmind 	struct nfsrv_descript nfsd;
   3013  1.1.1.1.4.2  rmind 	struct ucred *cred;
   3014  1.1.1.1.4.2  rmind 	int error;
   3015  1.1.1.1.4.2  rmind 
   3016  1.1.1.1.4.2  rmind 	NFSLOCKNAMEID();
   3017  1.1.1.1.4.2  rmind 	if (nfsrv_nfsuserd == 0) {
   3018  1.1.1.1.4.2  rmind 		NFSUNLOCKNAMEID();
   3019  1.1.1.1.4.2  rmind 		error = EPERM;
   3020  1.1.1.1.4.2  rmind 		goto out;
   3021  1.1.1.1.4.2  rmind 	}
   3022  1.1.1.1.4.2  rmind 	NFSUNLOCKNAMEID();
   3023  1.1.1.1.4.2  rmind 	nd = &nfsd;
   3024  1.1.1.1.4.2  rmind 	cred = newnfs_getcred();
   3025  1.1.1.1.4.2  rmind 	nd->nd_flag = ND_GSSINITREPLY;
   3026  1.1.1.1.4.2  rmind 	nfsrvd_rephead(nd);
   3027  1.1.1.1.4.2  rmind 
   3028  1.1.1.1.4.2  rmind 	nd->nd_procnum = procnum;
   3029  1.1.1.1.4.2  rmind 	if (procnum == RPCNFSUSERD_GETUID || procnum == RPCNFSUSERD_GETGID) {
   3030  1.1.1.1.4.2  rmind 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
   3031  1.1.1.1.4.2  rmind 		if (procnum == RPCNFSUSERD_GETUID)
   3032  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(uid);
   3033  1.1.1.1.4.2  rmind 		else
   3034  1.1.1.1.4.2  rmind 			*tl = txdr_unsigned(gid);
   3035  1.1.1.1.4.2  rmind 	} else {
   3036  1.1.1.1.4.2  rmind 		len = strlen(name);
   3037  1.1.1.1.4.2  rmind 		(void) nfsm_strtom(nd, name, len);
   3038  1.1.1.1.4.2  rmind 	}
   3039  1.1.1.1.4.2  rmind 	error = newnfs_request(nd, NULL, NULL, &nfsrv_nfsuserdsock, NULL, NULL,
   3040  1.1.1.1.4.2  rmind 		cred, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, NULL, 0, NULL, NULL);
   3041  1.1.1.1.4.2  rmind 	NFSFREECRED(cred);
   3042  1.1.1.1.4.2  rmind 	if (!error) {
   3043  1.1.1.1.4.2  rmind 		mbuf_freem(nd->nd_mrep);
   3044  1.1.1.1.4.2  rmind 		error = nd->nd_repstat;
   3045  1.1.1.1.4.2  rmind 	}
   3046  1.1.1.1.4.2  rmind out:
   3047  1.1.1.1.4.2  rmind 	NFSEXITCODE(error);
   3048  1.1.1.1.4.2  rmind 	return (error);
   3049  1.1.1.1.4.2  rmind }
   3050  1.1.1.1.4.2  rmind 
   3051  1.1.1.1.4.2  rmind /*
   3052  1.1.1.1.4.2  rmind  * This function is called from the nfssvc(2) system call, to update the
   3053  1.1.1.1.4.2  rmind  * kernel user/group name list(s) for the V4 owner and ownergroup attributes.
   3054  1.1.1.1.4.2  rmind  */
   3055  1.1.1.1.4.2  rmind APPLESTATIC int
   3056  1.1.1.1.4.2  rmind nfssvc_idname(struct nfsd_idargs *nidp)
   3057  1.1.1.1.4.2  rmind {
   3058  1.1.1.1.4.2  rmind 	struct nfsusrgrp *nusrp, *usrp, *newusrp;
   3059  1.1.1.1.4.2  rmind 	struct nfsuserhashhead *hp;
   3060  1.1.1.1.4.2  rmind 	int i;
   3061  1.1.1.1.4.2  rmind 	int error = 0;
   3062  1.1.1.1.4.2  rmind 	u_char *cp;
   3063  1.1.1.1.4.2  rmind 
   3064  1.1.1.1.4.2  rmind 	if (nidp->nid_flag & NFSID_INITIALIZE) {
   3065  1.1.1.1.4.2  rmind 	    cp = (u_char *)malloc(nidp->nid_namelen + 1,
   3066  1.1.1.1.4.2  rmind 		M_NFSSTRING, M_WAITOK);
   3067  1.1.1.1.4.2  rmind 	    error = copyin(CAST_USER_ADDR_T(nidp->nid_name), cp,
   3068  1.1.1.1.4.2  rmind 		nidp->nid_namelen);
   3069  1.1.1.1.4.2  rmind 	    NFSLOCKNAMEID();
   3070  1.1.1.1.4.2  rmind 	    if (nfsrv_dnsname) {
   3071  1.1.1.1.4.2  rmind 		/*
   3072  1.1.1.1.4.2  rmind 		 * Free up all the old stuff and reinitialize hash lists.
   3073  1.1.1.1.4.2  rmind 		 */
   3074  1.1.1.1.4.2  rmind 		TAILQ_FOREACH_SAFE(usrp, &nfsuserlruhead, lug_lru, nusrp) {
   3075  1.1.1.1.4.2  rmind 			nfsrv_removeuser(usrp);
   3076  1.1.1.1.4.2  rmind 		}
   3077  1.1.1.1.4.2  rmind 		free(nfsrv_dnsname, M_NFSSTRING);
   3078  1.1.1.1.4.2  rmind 		nfsrv_dnsname = NULL;
   3079  1.1.1.1.4.2  rmind 	    }
   3080  1.1.1.1.4.2  rmind 	    TAILQ_INIT(&nfsuserlruhead);
   3081  1.1.1.1.4.2  rmind 	    for (i = 0; i < NFSUSERHASHSIZE; i++)
   3082  1.1.1.1.4.2  rmind 		LIST_INIT(&nfsuserhash[i]);
   3083  1.1.1.1.4.2  rmind 	    for (i = 0; i < NFSGROUPHASHSIZE; i++)
   3084  1.1.1.1.4.2  rmind 		LIST_INIT(&nfsgrouphash[i]);
   3085  1.1.1.1.4.2  rmind 	    for (i = 0; i < NFSUSERHASHSIZE; i++)
   3086  1.1.1.1.4.2  rmind 		LIST_INIT(&nfsusernamehash[i]);
   3087  1.1.1.1.4.2  rmind 	    for (i = 0; i < NFSGROUPHASHSIZE; i++)
   3088  1.1.1.1.4.2  rmind 		LIST_INIT(&nfsgroupnamehash[i]);
   3089  1.1.1.1.4.2  rmind 
   3090  1.1.1.1.4.2  rmind 	    /*
   3091  1.1.1.1.4.2  rmind 	     * Put name in "DNS" string.
   3092  1.1.1.1.4.2  rmind 	     */
   3093  1.1.1.1.4.2  rmind 	    if (!error) {
   3094  1.1.1.1.4.2  rmind 		nfsrv_dnsname = cp;
   3095  1.1.1.1.4.2  rmind 		nfsrv_dnsnamelen = nidp->nid_namelen;
   3096  1.1.1.1.4.2  rmind 		nfsrv_defaultuid = nidp->nid_uid;
   3097  1.1.1.1.4.2  rmind 		nfsrv_defaultgid = nidp->nid_gid;
   3098  1.1.1.1.4.2  rmind 		nfsrv_usercnt = 0;
   3099  1.1.1.1.4.2  rmind 		nfsrv_usermax = nidp->nid_usermax;
   3100  1.1.1.1.4.2  rmind 	    }
   3101  1.1.1.1.4.2  rmind 	    NFSUNLOCKNAMEID();
   3102  1.1.1.1.4.2  rmind 	    if (error)
   3103  1.1.1.1.4.2  rmind 		free(cp, M_NFSSTRING);
   3104  1.1.1.1.4.2  rmind 	    goto out;
   3105  1.1.1.1.4.2  rmind 	}
   3106  1.1.1.1.4.2  rmind 
   3107  1.1.1.1.4.2  rmind 	/*
   3108  1.1.1.1.4.2  rmind 	 * malloc the new one now, so any potential sleep occurs before
   3109  1.1.1.1.4.2  rmind 	 * manipulation of the lists.
   3110  1.1.1.1.4.2  rmind 	 */
   3111  1.1.1.1.4.2  rmind 	MALLOC(newusrp, struct nfsusrgrp *, sizeof (struct nfsusrgrp) +
   3112  1.1.1.1.4.2  rmind 	    nidp->nid_namelen, M_NFSUSERGROUP, M_WAITOK);
   3113  1.1.1.1.4.2  rmind 	error = copyin(CAST_USER_ADDR_T(nidp->nid_name), newusrp->lug_name,
   3114  1.1.1.1.4.2  rmind 	    nidp->nid_namelen);
   3115  1.1.1.1.4.2  rmind 	if (error) {
   3116  1.1.1.1.4.2  rmind 		free((caddr_t)newusrp, M_NFSUSERGROUP);
   3117  1.1.1.1.4.2  rmind 		goto out;
   3118  1.1.1.1.4.2  rmind 	}
   3119  1.1.1.1.4.2  rmind 	newusrp->lug_namelen = nidp->nid_namelen;
   3120  1.1.1.1.4.2  rmind 
   3121  1.1.1.1.4.2  rmind 	NFSLOCKNAMEID();
   3122  1.1.1.1.4.2  rmind 	/*
   3123  1.1.1.1.4.2  rmind 	 * Delete old entries, as required.
   3124  1.1.1.1.4.2  rmind 	 */
   3125  1.1.1.1.4.2  rmind 	if (nidp->nid_flag & (NFSID_DELUID | NFSID_ADDUID)) {
   3126  1.1.1.1.4.2  rmind 		hp = NFSUSERHASH(nidp->nid_uid);
   3127  1.1.1.1.4.2  rmind 		LIST_FOREACH_SAFE(usrp, hp, lug_numhash, nusrp) {
   3128  1.1.1.1.4.2  rmind 			if (usrp->lug_uid == nidp->nid_uid)
   3129  1.1.1.1.4.2  rmind 				nfsrv_removeuser(usrp);
   3130  1.1.1.1.4.2  rmind 		}
   3131  1.1.1.1.4.2  rmind 	}
   3132  1.1.1.1.4.2  rmind 	if (nidp->nid_flag & (NFSID_DELUSERNAME | NFSID_ADDUSERNAME)) {
   3133  1.1.1.1.4.2  rmind 		hp = NFSUSERNAMEHASH(newusrp->lug_name, newusrp->lug_namelen);
   3134  1.1.1.1.4.2  rmind 		LIST_FOREACH_SAFE(usrp, hp, lug_namehash, nusrp) {
   3135  1.1.1.1.4.2  rmind 			if (usrp->lug_namelen == newusrp->lug_namelen &&
   3136  1.1.1.1.4.2  rmind 			    !NFSBCMP(usrp->lug_name, newusrp->lug_name,
   3137  1.1.1.1.4.2  rmind 			    usrp->lug_namelen))
   3138  1.1.1.1.4.2  rmind 				nfsrv_removeuser(usrp);
   3139  1.1.1.1.4.2  rmind 		}
   3140  1.1.1.1.4.2  rmind 	}
   3141  1.1.1.1.4.2  rmind 	if (nidp->nid_flag & (NFSID_DELGID | NFSID_ADDGID)) {
   3142  1.1.1.1.4.2  rmind 		hp = NFSGROUPHASH(nidp->nid_gid);
   3143  1.1.1.1.4.2  rmind 		LIST_FOREACH_SAFE(usrp, hp, lug_numhash, nusrp) {
   3144  1.1.1.1.4.2  rmind 			if (usrp->lug_gid == nidp->nid_gid)
   3145  1.1.1.1.4.2  rmind 				nfsrv_removeuser(usrp);
   3146  1.1.1.1.4.2  rmind 		}
   3147  1.1.1.1.4.2  rmind 	}
   3148  1.1.1.1.4.2  rmind 	if (nidp->nid_flag & (NFSID_DELGROUPNAME | NFSID_ADDGROUPNAME)) {
   3149  1.1.1.1.4.2  rmind 		hp = NFSGROUPNAMEHASH(newusrp->lug_name, newusrp->lug_namelen);
   3150  1.1.1.1.4.2  rmind 		LIST_FOREACH_SAFE(usrp, hp, lug_namehash, nusrp) {
   3151  1.1.1.1.4.2  rmind 			if (usrp->lug_namelen == newusrp->lug_namelen &&
   3152  1.1.1.1.4.2  rmind 			    !NFSBCMP(usrp->lug_name, newusrp->lug_name,
   3153  1.1.1.1.4.2  rmind 			    usrp->lug_namelen))
   3154  1.1.1.1.4.2  rmind 				nfsrv_removeuser(usrp);
   3155  1.1.1.1.4.2  rmind 		}
   3156  1.1.1.1.4.2  rmind 	}
   3157  1.1.1.1.4.2  rmind 	TAILQ_FOREACH_SAFE(usrp, &nfsuserlruhead, lug_lru, nusrp) {
   3158  1.1.1.1.4.2  rmind 		if (usrp->lug_expiry < NFSD_MONOSEC)
   3159  1.1.1.1.4.2  rmind 			nfsrv_removeuser(usrp);
   3160  1.1.1.1.4.2  rmind 	}
   3161  1.1.1.1.4.2  rmind 	while (nfsrv_usercnt >= nfsrv_usermax) {
   3162  1.1.1.1.4.2  rmind 		usrp = TAILQ_FIRST(&nfsuserlruhead);
   3163  1.1.1.1.4.2  rmind 		nfsrv_removeuser(usrp);
   3164  1.1.1.1.4.2  rmind 	}
   3165  1.1.1.1.4.2  rmind 
   3166  1.1.1.1.4.2  rmind 	/*
   3167  1.1.1.1.4.2  rmind 	 * Now, we can add the new one.
   3168  1.1.1.1.4.2  rmind 	 */
   3169  1.1.1.1.4.2  rmind 	if (nidp->nid_usertimeout)
   3170  1.1.1.1.4.2  rmind 		newusrp->lug_expiry = NFSD_MONOSEC + nidp->nid_usertimeout;
   3171  1.1.1.1.4.2  rmind 	else
   3172  1.1.1.1.4.2  rmind 		newusrp->lug_expiry = NFSD_MONOSEC + 5;
   3173  1.1.1.1.4.2  rmind 	if (nidp->nid_flag & (NFSID_ADDUID | NFSID_ADDUSERNAME)) {
   3174  1.1.1.1.4.2  rmind 		newusrp->lug_uid = nidp->nid_uid;
   3175  1.1.1.1.4.2  rmind 		LIST_INSERT_HEAD(NFSUSERHASH(newusrp->lug_uid), newusrp,
   3176  1.1.1.1.4.2  rmind 		    lug_numhash);
   3177  1.1.1.1.4.2  rmind 		LIST_INSERT_HEAD(NFSUSERNAMEHASH(newusrp->lug_name,
   3178  1.1.1.1.4.2  rmind 		    newusrp->lug_namelen), newusrp, lug_namehash);
   3179  1.1.1.1.4.2  rmind 		TAILQ_INSERT_TAIL(&nfsuserlruhead, newusrp, lug_lru);
   3180  1.1.1.1.4.2  rmind 		nfsrv_usercnt++;
   3181  1.1.1.1.4.2  rmind 	} else if (nidp->nid_flag & (NFSID_ADDGID | NFSID_ADDGROUPNAME)) {
   3182  1.1.1.1.4.2  rmind 		newusrp->lug_gid = nidp->nid_gid;
   3183  1.1.1.1.4.2  rmind 		LIST_INSERT_HEAD(NFSGROUPHASH(newusrp->lug_gid), newusrp,
   3184  1.1.1.1.4.2  rmind 		    lug_numhash);
   3185  1.1.1.1.4.2  rmind 		LIST_INSERT_HEAD(NFSGROUPNAMEHASH(newusrp->lug_name,
   3186  1.1.1.1.4.2  rmind 		    newusrp->lug_namelen), newusrp, lug_namehash);
   3187  1.1.1.1.4.2  rmind 		TAILQ_INSERT_TAIL(&nfsuserlruhead, newusrp, lug_lru);
   3188  1.1.1.1.4.2  rmind 		nfsrv_usercnt++;
   3189  1.1.1.1.4.2  rmind 	} else
   3190  1.1.1.1.4.2  rmind 		FREE((caddr_t)newusrp, M_NFSUSERGROUP);
   3191  1.1.1.1.4.2  rmind 	NFSUNLOCKNAMEID();
   3192  1.1.1.1.4.2  rmind out:
   3193  1.1.1.1.4.2  rmind 	NFSEXITCODE(error);
   3194  1.1.1.1.4.2  rmind 	return (error);
   3195  1.1.1.1.4.2  rmind }
   3196  1.1.1.1.4.2  rmind 
   3197  1.1.1.1.4.2  rmind /*
   3198  1.1.1.1.4.2  rmind  * Remove a user/group name element.
   3199  1.1.1.1.4.2  rmind  */
   3200  1.1.1.1.4.2  rmind static void
   3201  1.1.1.1.4.2  rmind nfsrv_removeuser(struct nfsusrgrp *usrp)
   3202  1.1.1.1.4.2  rmind {
   3203  1.1.1.1.4.2  rmind 
   3204  1.1.1.1.4.2  rmind 	NFSNAMEIDREQUIRED();
   3205  1.1.1.1.4.2  rmind 	LIST_REMOVE(usrp, lug_numhash);
   3206  1.1.1.1.4.2  rmind 	LIST_REMOVE(usrp, lug_namehash);
   3207  1.1.1.1.4.2  rmind 	TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
   3208  1.1.1.1.4.2  rmind 	nfsrv_usercnt--;
   3209  1.1.1.1.4.2  rmind 	FREE((caddr_t)usrp, M_NFSUSERGROUP);
   3210  1.1.1.1.4.2  rmind }
   3211  1.1.1.1.4.2  rmind 
   3212  1.1.1.1.4.2  rmind /*
   3213  1.1.1.1.4.2  rmind  * This function scans a byte string and checks for UTF-8 compliance.
   3214  1.1.1.1.4.2  rmind  * It returns 0 if it conforms and NFSERR_INVAL if not.
   3215  1.1.1.1.4.2  rmind  */
   3216  1.1.1.1.4.2  rmind APPLESTATIC int
   3217  1.1.1.1.4.2  rmind nfsrv_checkutf8(u_int8_t *cp, int len)
   3218  1.1.1.1.4.2  rmind {
   3219  1.1.1.1.4.2  rmind 	u_int32_t val = 0x0;
   3220  1.1.1.1.4.2  rmind 	int cnt = 0, gotd = 0, shift = 0;
   3221  1.1.1.1.4.2  rmind 	u_int8_t byte;
   3222  1.1.1.1.4.2  rmind 	static int utf8_shift[5] = { 7, 11, 16, 21, 26 };
   3223  1.1.1.1.4.2  rmind 	int error = 0;
   3224  1.1.1.1.4.2  rmind 
   3225  1.1.1.1.4.2  rmind 	/*
   3226  1.1.1.1.4.2  rmind 	 * Here are what the variables are used for:
   3227  1.1.1.1.4.2  rmind 	 * val - the calculated value of a multibyte char, used to check
   3228  1.1.1.1.4.2  rmind 	 *       that it was coded with the correct range
   3229  1.1.1.1.4.2  rmind 	 * cnt - the number of 10xxxxxx bytes to follow
   3230  1.1.1.1.4.2  rmind 	 * gotd - set for a char of Dxxx, so D800<->DFFF can be checked for
   3231  1.1.1.1.4.2  rmind 	 * shift - lower order bits of range (ie. "val >> shift" should
   3232  1.1.1.1.4.2  rmind 	 *       not be 0, in other words, dividing by the lower bound
   3233  1.1.1.1.4.2  rmind 	 *       of the range should get a non-zero value)
   3234  1.1.1.1.4.2  rmind 	 * byte - used to calculate cnt
   3235  1.1.1.1.4.2  rmind 	 */
   3236  1.1.1.1.4.2  rmind 	while (len > 0) {
   3237  1.1.1.1.4.2  rmind 		if (cnt > 0) {
   3238  1.1.1.1.4.2  rmind 			/* This handles the 10xxxxxx bytes */
   3239  1.1.1.1.4.2  rmind 			if ((*cp & 0xc0) != 0x80 ||
   3240  1.1.1.1.4.2  rmind 			    (gotd && (*cp & 0x20))) {
   3241  1.1.1.1.4.2  rmind 				error = NFSERR_INVAL;
   3242  1.1.1.1.4.2  rmind 				goto out;
   3243  1.1.1.1.4.2  rmind 			}
   3244  1.1.1.1.4.2  rmind 			gotd = 0;
   3245  1.1.1.1.4.2  rmind 			val <<= 6;
   3246  1.1.1.1.4.2  rmind 			val |= (*cp & 0x3f);
   3247  1.1.1.1.4.2  rmind 			cnt--;
   3248  1.1.1.1.4.2  rmind 			if (cnt == 0 && (val >> shift) == 0x0) {
   3249  1.1.1.1.4.2  rmind 				error = NFSERR_INVAL;
   3250  1.1.1.1.4.2  rmind 				goto out;
   3251  1.1.1.1.4.2  rmind 			}
   3252  1.1.1.1.4.2  rmind 		} else if (*cp & 0x80) {
   3253  1.1.1.1.4.2  rmind 			/* first byte of multi byte char */
   3254  1.1.1.1.4.2  rmind 			byte = *cp;
   3255  1.1.1.1.4.2  rmind 			while ((byte & 0x40) && cnt < 6) {
   3256  1.1.1.1.4.2  rmind 				cnt++;
   3257  1.1.1.1.4.2  rmind 				byte <<= 1;
   3258  1.1.1.1.4.2  rmind 			}
   3259  1.1.1.1.4.2  rmind 			if (cnt == 0 || cnt == 6) {
   3260  1.1.1.1.4.2  rmind 				error = NFSERR_INVAL;
   3261  1.1.1.1.4.2  rmind 				goto out;
   3262  1.1.1.1.4.2  rmind 			}
   3263  1.1.1.1.4.2  rmind 			val = (*cp & (0x3f >> cnt));
   3264  1.1.1.1.4.2  rmind 			shift = utf8_shift[cnt - 1];
   3265  1.1.1.1.4.2  rmind 			if (cnt == 2 && val == 0xd)
   3266  1.1.1.1.4.2  rmind 				/* Check for the 0xd800-0xdfff case */
   3267  1.1.1.1.4.2  rmind 				gotd = 1;
   3268  1.1.1.1.4.2  rmind 		}
   3269  1.1.1.1.4.2  rmind 		cp++;
   3270  1.1.1.1.4.2  rmind 		len--;
   3271  1.1.1.1.4.2  rmind 	}
   3272  1.1.1.1.4.2  rmind 	if (cnt > 0)
   3273  1.1.1.1.4.2  rmind 		error = NFSERR_INVAL;
   3274  1.1.1.1.4.2  rmind 
   3275  1.1.1.1.4.2  rmind out:
   3276  1.1.1.1.4.2  rmind 	NFSEXITCODE(error);
   3277  1.1.1.1.4.2  rmind 	return (error);
   3278  1.1.1.1.4.2  rmind }
   3279  1.1.1.1.4.2  rmind 
   3280  1.1.1.1.4.2  rmind /*
   3281  1.1.1.1.4.2  rmind  * Parse the xdr for an NFSv4 FsLocations attribute. Return two malloc'd
   3282  1.1.1.1.4.2  rmind  * strings, one with the root path in it and the other with the list of
   3283  1.1.1.1.4.2  rmind  * locations. The list is in the same format as is found in nfr_refs.
   3284  1.1.1.1.4.2  rmind  * It is a "," separated list of entries, where each of them is of the
   3285  1.1.1.1.4.2  rmind  * form <server>:<rootpath>. For example
   3286  1.1.1.1.4.2  rmind  * "nfsv4-test:/sub2,nfsv4-test2:/user/mnt,nfsv4-test2:/user/mnt2"
   3287  1.1.1.1.4.2  rmind  * The nilp argument is set to 1 for the special case of a null fs_root
   3288  1.1.1.1.4.2  rmind  * and an empty server list.
   3289  1.1.1.1.4.2  rmind  * It returns NFSERR_BADXDR, if the xdr can't be parsed and returns the
   3290  1.1.1.1.4.2  rmind  * number of xdr bytes parsed in sump.
   3291  1.1.1.1.4.2  rmind  */
   3292  1.1.1.1.4.2  rmind static int
   3293  1.1.1.1.4.2  rmind nfsrv_getrefstr(struct nfsrv_descript *nd, u_char **fsrootp, u_char **srvp,
   3294  1.1.1.1.4.2  rmind     int *sump, int *nilp)
   3295  1.1.1.1.4.2  rmind {
   3296  1.1.1.1.4.2  rmind 	u_int32_t *tl;
   3297  1.1.1.1.4.2  rmind 	u_char *cp = NULL, *cp2 = NULL, *cp3, *str;
   3298  1.1.1.1.4.2  rmind 	int i, j, len, stringlen, cnt, slen, siz, xdrsum, error = 0, nsrv;
   3299  1.1.1.1.4.2  rmind 	struct list {
   3300  1.1.1.1.4.2  rmind 		SLIST_ENTRY(list) next;
   3301  1.1.1.1.4.2  rmind 		int len;
   3302  1.1.1.1.4.2  rmind 		u_char host[1];
   3303  1.1.1.1.4.2  rmind 	} *lsp, *nlsp;
   3304  1.1.1.1.4.2  rmind 	SLIST_HEAD(, list) head;
   3305  1.1.1.1.4.2  rmind 
   3306  1.1.1.1.4.2  rmind 	*fsrootp = NULL;
   3307  1.1.1.1.4.2  rmind 	*srvp = NULL;
   3308  1.1.1.1.4.2  rmind 	*nilp = 0;
   3309  1.1.1.1.4.2  rmind 
   3310  1.1.1.1.4.2  rmind 	/*
   3311  1.1.1.1.4.2  rmind 	 * Get the fs_root path and check for the special case of null path
   3312  1.1.1.1.4.2  rmind 	 * and 0 length server list.
   3313  1.1.1.1.4.2  rmind 	 */
   3314  1.1.1.1.4.2  rmind 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   3315  1.1.1.1.4.2  rmind 	len = fxdr_unsigned(int, *tl);
   3316  1.1.1.1.4.2  rmind 	if (len < 0 || len > 10240) {
   3317  1.1.1.1.4.2  rmind 		error = NFSERR_BADXDR;
   3318  1.1.1.1.4.2  rmind 		goto nfsmout;
   3319  1.1.1.1.4.2  rmind 	}
   3320  1.1.1.1.4.2  rmind 	if (len == 0) {
   3321  1.1.1.1.4.2  rmind 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   3322  1.1.1.1.4.2  rmind 		if (*tl != 0) {
   3323  1.1.1.1.4.2  rmind 			error = NFSERR_BADXDR;
   3324  1.1.1.1.4.2  rmind 			goto nfsmout;
   3325  1.1.1.1.4.2  rmind 		}
   3326  1.1.1.1.4.2  rmind 		*nilp = 1;
   3327  1.1.1.1.4.2  rmind 		*sump = 2 * NFSX_UNSIGNED;
   3328  1.1.1.1.4.2  rmind 		error = 0;
   3329  1.1.1.1.4.2  rmind 		goto nfsmout;
   3330  1.1.1.1.4.2  rmind 	}
   3331  1.1.1.1.4.2  rmind 	cp = malloc(len + 1, M_NFSSTRING, M_WAITOK);
   3332  1.1.1.1.4.2  rmind 	error = nfsrv_mtostr(nd, cp, len);
   3333  1.1.1.1.4.2  rmind 	if (!error) {
   3334  1.1.1.1.4.2  rmind 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   3335  1.1.1.1.4.2  rmind 		cnt = fxdr_unsigned(int, *tl);
   3336  1.1.1.1.4.2  rmind 		if (cnt <= 0)
   3337  1.1.1.1.4.2  rmind 			error = NFSERR_BADXDR;
   3338  1.1.1.1.4.2  rmind 	}
   3339  1.1.1.1.4.2  rmind 	if (error)
   3340  1.1.1.1.4.2  rmind 		goto nfsmout;
   3341  1.1.1.1.4.2  rmind 
   3342  1.1.1.1.4.2  rmind 	/*
   3343  1.1.1.1.4.2  rmind 	 * Now, loop through the location list and make up the srvlist.
   3344  1.1.1.1.4.2  rmind 	 */
   3345  1.1.1.1.4.2  rmind 	xdrsum = (2 * NFSX_UNSIGNED) + NFSM_RNDUP(len);
   3346  1.1.1.1.4.2  rmind 	cp2 = cp3 = malloc(1024, M_NFSSTRING, M_WAITOK);
   3347  1.1.1.1.4.2  rmind 	slen = 1024;
   3348  1.1.1.1.4.2  rmind 	siz = 0;
   3349  1.1.1.1.4.2  rmind 	for (i = 0; i < cnt; i++) {
   3350  1.1.1.1.4.2  rmind 		SLIST_INIT(&head);
   3351  1.1.1.1.4.2  rmind 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   3352  1.1.1.1.4.2  rmind 		nsrv = fxdr_unsigned(int, *tl);
   3353  1.1.1.1.4.2  rmind 		if (nsrv <= 0) {
   3354  1.1.1.1.4.2  rmind 			error = NFSERR_BADXDR;
   3355  1.1.1.1.4.2  rmind 			goto nfsmout;
   3356  1.1.1.1.4.2  rmind 		}
   3357  1.1.1.1.4.2  rmind 
   3358  1.1.1.1.4.2  rmind 		/*
   3359  1.1.1.1.4.2  rmind 		 * Handle the first server by putting it in the srvstr.
   3360  1.1.1.1.4.2  rmind 		 */
   3361  1.1.1.1.4.2  rmind 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   3362  1.1.1.1.4.2  rmind 		len = fxdr_unsigned(int, *tl);
   3363  1.1.1.1.4.2  rmind 		if (len <= 0 || len > 1024) {
   3364  1.1.1.1.4.2  rmind 			error = NFSERR_BADXDR;
   3365  1.1.1.1.4.2  rmind 			goto nfsmout;
   3366  1.1.1.1.4.2  rmind 		}
   3367  1.1.1.1.4.2  rmind 		nfsrv_refstrbigenough(siz + len + 3, &cp2, &cp3, &slen);
   3368  1.1.1.1.4.2  rmind 		if (cp3 != cp2) {
   3369  1.1.1.1.4.2  rmind 			*cp3++ = ',';
   3370  1.1.1.1.4.2  rmind 			siz++;
   3371  1.1.1.1.4.2  rmind 		}
   3372  1.1.1.1.4.2  rmind 		error = nfsrv_mtostr(nd, cp3, len);
   3373  1.1.1.1.4.2  rmind 		if (error)
   3374  1.1.1.1.4.2  rmind 			goto nfsmout;
   3375  1.1.1.1.4.2  rmind 		cp3 += len;
   3376  1.1.1.1.4.2  rmind 		*cp3++ = ':';
   3377  1.1.1.1.4.2  rmind 		siz += (len + 1);
   3378  1.1.1.1.4.2  rmind 		xdrsum += (2 * NFSX_UNSIGNED) + NFSM_RNDUP(len);
   3379  1.1.1.1.4.2  rmind 		for (j = 1; j < nsrv; j++) {
   3380  1.1.1.1.4.2  rmind 			/*
   3381  1.1.1.1.4.2  rmind 			 * Yuck, put them in an slist and process them later.
   3382  1.1.1.1.4.2  rmind 			 */
   3383  1.1.1.1.4.2  rmind 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   3384  1.1.1.1.4.2  rmind 			len = fxdr_unsigned(int, *tl);
   3385  1.1.1.1.4.2  rmind 			if (len <= 0 || len > 1024) {
   3386  1.1.1.1.4.2  rmind 				error = NFSERR_BADXDR;
   3387  1.1.1.1.4.2  rmind 				goto nfsmout;
   3388  1.1.1.1.4.2  rmind 			}
   3389  1.1.1.1.4.2  rmind 			lsp = (struct list *)malloc(sizeof (struct list)
   3390  1.1.1.1.4.2  rmind 			    + len, M_TEMP, M_WAITOK);
   3391  1.1.1.1.4.2  rmind 			error = nfsrv_mtostr(nd, lsp->host, len);
   3392  1.1.1.1.4.2  rmind 			if (error)
   3393  1.1.1.1.4.2  rmind 				goto nfsmout;
   3394  1.1.1.1.4.2  rmind 			xdrsum += NFSX_UNSIGNED + NFSM_RNDUP(len);
   3395  1.1.1.1.4.2  rmind 			lsp->len = len;
   3396  1.1.1.1.4.2  rmind 			SLIST_INSERT_HEAD(&head, lsp, next);
   3397  1.1.1.1.4.2  rmind 		}
   3398  1.1.1.1.4.2  rmind 
   3399  1.1.1.1.4.2  rmind 		/*
   3400  1.1.1.1.4.2  rmind 		 * Finally, we can get the path.
   3401  1.1.1.1.4.2  rmind 		 */
   3402  1.1.1.1.4.2  rmind 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   3403  1.1.1.1.4.2  rmind 		len = fxdr_unsigned(int, *tl);
   3404  1.1.1.1.4.2  rmind 		if (len <= 0 || len > 1024) {
   3405  1.1.1.1.4.2  rmind 			error = NFSERR_BADXDR;
   3406  1.1.1.1.4.2  rmind 			goto nfsmout;
   3407  1.1.1.1.4.2  rmind 		}
   3408  1.1.1.1.4.2  rmind 		nfsrv_refstrbigenough(siz + len + 1, &cp2, &cp3, &slen);
   3409  1.1.1.1.4.2  rmind 		error = nfsrv_mtostr(nd, cp3, len);
   3410  1.1.1.1.4.2  rmind 		if (error)
   3411  1.1.1.1.4.2  rmind 			goto nfsmout;
   3412  1.1.1.1.4.2  rmind 		xdrsum += NFSX_UNSIGNED + NFSM_RNDUP(len);
   3413  1.1.1.1.4.2  rmind 		str = cp3;
   3414  1.1.1.1.4.2  rmind 		stringlen = len;
   3415  1.1.1.1.4.2  rmind 		cp3 += len;
   3416  1.1.1.1.4.2  rmind 		siz += len;
   3417  1.1.1.1.4.2  rmind 		SLIST_FOREACH_SAFE(lsp, &head, next, nlsp) {
   3418  1.1.1.1.4.2  rmind 			nfsrv_refstrbigenough(siz + lsp->len + stringlen + 3,
   3419  1.1.1.1.4.2  rmind 			    &cp2, &cp3, &slen);
   3420  1.1.1.1.4.2  rmind 			*cp3++ = ',';
   3421  1.1.1.1.4.2  rmind 			NFSBCOPY(lsp->host, cp3, lsp->len);
   3422  1.1.1.1.4.2  rmind 			cp3 += lsp->len;
   3423  1.1.1.1.4.2  rmind 			*cp3++ = ':';
   3424  1.1.1.1.4.2  rmind 			NFSBCOPY(str, cp3, stringlen);
   3425  1.1.1.1.4.2  rmind 			cp3 += stringlen;
   3426  1.1.1.1.4.2  rmind 			*cp3 = '\0';
   3427  1.1.1.1.4.2  rmind 			siz += (lsp->len + stringlen + 2);
   3428  1.1.1.1.4.2  rmind 			free((caddr_t)lsp, M_TEMP);
   3429  1.1.1.1.4.2  rmind 		}
   3430  1.1.1.1.4.2  rmind 	}
   3431  1.1.1.1.4.2  rmind 	*fsrootp = cp;
   3432  1.1.1.1.4.2  rmind 	*srvp = cp2;
   3433  1.1.1.1.4.2  rmind 	*sump = xdrsum;
   3434  1.1.1.1.4.2  rmind 	NFSEXITCODE2(0, nd);
   3435  1.1.1.1.4.2  rmind 	return (0);
   3436  1.1.1.1.4.2  rmind nfsmout:
   3437  1.1.1.1.4.2  rmind 	if (cp != NULL)
   3438  1.1.1.1.4.2  rmind 		free(cp, M_NFSSTRING);
   3439  1.1.1.1.4.2  rmind 	if (cp2 != NULL)
   3440  1.1.1.1.4.2  rmind 		free(cp2, M_NFSSTRING);
   3441  1.1.1.1.4.2  rmind 	NFSEXITCODE2(error, nd);
   3442  1.1.1.1.4.2  rmind 	return (error);
   3443  1.1.1.1.4.2  rmind }
   3444  1.1.1.1.4.2  rmind 
   3445  1.1.1.1.4.2  rmind /*
   3446  1.1.1.1.4.2  rmind  * Make the malloc'd space large enough. This is a pain, but the xdr
   3447  1.1.1.1.4.2  rmind  * doesn't set an upper bound on the side, so...
   3448  1.1.1.1.4.2  rmind  */
   3449  1.1.1.1.4.2  rmind static void
   3450  1.1.1.1.4.2  rmind nfsrv_refstrbigenough(int siz, u_char **cpp, u_char **cpp2, int *slenp)
   3451  1.1.1.1.4.2  rmind {
   3452  1.1.1.1.4.2  rmind 	u_char *cp;
   3453  1.1.1.1.4.2  rmind 	int i;
   3454  1.1.1.1.4.2  rmind 
   3455  1.1.1.1.4.2  rmind 	if (siz <= *slenp)
   3456  1.1.1.1.4.2  rmind 		return;
   3457  1.1.1.1.4.2  rmind 	cp = malloc(siz + 1024, M_NFSSTRING, M_WAITOK);
   3458  1.1.1.1.4.2  rmind 	NFSBCOPY(*cpp, cp, *slenp);
   3459  1.1.1.1.4.2  rmind 	free(*cpp, M_NFSSTRING);
   3460  1.1.1.1.4.2  rmind 	i = *cpp2 - *cpp;
   3461  1.1.1.1.4.2  rmind 	*cpp = cp;
   3462  1.1.1.1.4.2  rmind 	*cpp2 = cp + i;
   3463  1.1.1.1.4.2  rmind 	*slenp = siz + 1024;
   3464  1.1.1.1.4.2  rmind }
   3465  1.1.1.1.4.2  rmind 
   3466  1.1.1.1.4.2  rmind /*
   3467  1.1.1.1.4.2  rmind  * Initialize the reply header data structures.
   3468  1.1.1.1.4.2  rmind  */
   3469  1.1.1.1.4.2  rmind APPLESTATIC void
   3470  1.1.1.1.4.2  rmind nfsrvd_rephead(struct nfsrv_descript *nd)
   3471  1.1.1.1.4.2  rmind {
   3472  1.1.1.1.4.2  rmind 	mbuf_t mreq;
   3473  1.1.1.1.4.2  rmind 
   3474  1.1.1.1.4.2  rmind 	/*
   3475  1.1.1.1.4.2  rmind 	 * If this is a big reply, use a cluster.
   3476  1.1.1.1.4.2  rmind 	 */
   3477  1.1.1.1.4.2  rmind 	if ((nd->nd_flag & ND_GSSINITREPLY) == 0 &&
   3478  1.1.1.1.4.2  rmind 	    nfs_bigreply[nd->nd_procnum]) {
   3479  1.1.1.1.4.2  rmind 		NFSMCLGET(mreq, M_WAITOK);
   3480  1.1.1.1.4.2  rmind 		nd->nd_mreq = mreq;
   3481  1.1.1.1.4.2  rmind 		nd->nd_mb = mreq;
   3482  1.1.1.1.4.2  rmind 	} else {
   3483  1.1.1.1.4.2  rmind 		NFSMGET(mreq);
   3484  1.1.1.1.4.2  rmind 		nd->nd_mreq = mreq;
   3485  1.1.1.1.4.2  rmind 		nd->nd_mb = mreq;
   3486  1.1.1.1.4.2  rmind 	}
   3487  1.1.1.1.4.2  rmind 	nd->nd_bpos = NFSMTOD(mreq, caddr_t);
   3488  1.1.1.1.4.2  rmind 	mbuf_setlen(mreq, 0);
   3489  1.1.1.1.4.2  rmind 
   3490  1.1.1.1.4.2  rmind 	if ((nd->nd_flag & ND_GSSINITREPLY) == 0)
   3491  1.1.1.1.4.2  rmind 		NFSM_BUILD(nd->nd_errp, int *, NFSX_UNSIGNED);
   3492  1.1.1.1.4.2  rmind }
   3493  1.1.1.1.4.2  rmind 
   3494  1.1.1.1.4.2  rmind /*
   3495  1.1.1.1.4.2  rmind  * Lock a socket against others.
   3496  1.1.1.1.4.2  rmind  * Currently used to serialize connect/disconnect attempts.
   3497  1.1.1.1.4.2  rmind  */
   3498  1.1.1.1.4.2  rmind int
   3499  1.1.1.1.4.2  rmind newnfs_sndlock(int *flagp)
   3500  1.1.1.1.4.2  rmind {
   3501  1.1.1.1.4.2  rmind 	struct timespec ts;
   3502  1.1.1.1.4.2  rmind 
   3503  1.1.1.1.4.2  rmind 	NFSLOCKSOCK();
   3504  1.1.1.1.4.2  rmind 	while (*flagp & NFSR_SNDLOCK) {
   3505  1.1.1.1.4.2  rmind 		*flagp |= NFSR_WANTSND;
   3506  1.1.1.1.4.2  rmind 		ts.tv_sec = 0;
   3507  1.1.1.1.4.2  rmind 		ts.tv_nsec = 0;
   3508  1.1.1.1.4.2  rmind 		(void) nfsmsleep((caddr_t)flagp, NFSSOCKMUTEXPTR,
   3509  1.1.1.1.4.2  rmind 		    PZERO - 1, "nfsndlck", &ts);
   3510  1.1.1.1.4.2  rmind 	}
   3511  1.1.1.1.4.2  rmind 	*flagp |= NFSR_SNDLOCK;
   3512  1.1.1.1.4.2  rmind 	NFSUNLOCKSOCK();
   3513  1.1.1.1.4.2  rmind 	return (0);
   3514  1.1.1.1.4.2  rmind }
   3515  1.1.1.1.4.2  rmind 
   3516  1.1.1.1.4.2  rmind /*
   3517  1.1.1.1.4.2  rmind  * Unlock the stream socket for others.
   3518  1.1.1.1.4.2  rmind  */
   3519  1.1.1.1.4.2  rmind void
   3520  1.1.1.1.4.2  rmind newnfs_sndunlock(int *flagp)
   3521  1.1.1.1.4.2  rmind {
   3522  1.1.1.1.4.2  rmind 
   3523  1.1.1.1.4.2  rmind 	NFSLOCKSOCK();
   3524  1.1.1.1.4.2  rmind 	if ((*flagp & NFSR_SNDLOCK) == 0)
   3525  1.1.1.1.4.2  rmind 		panic("nfs sndunlock");
   3526  1.1.1.1.4.2  rmind 	*flagp &= ~NFSR_SNDLOCK;
   3527  1.1.1.1.4.2  rmind 	if (*flagp & NFSR_WANTSND) {
   3528  1.1.1.1.4.2  rmind 		*flagp &= ~NFSR_WANTSND;
   3529  1.1.1.1.4.2  rmind 		wakeup((caddr_t)flagp);
   3530  1.1.1.1.4.2  rmind 	}
   3531  1.1.1.1.4.2  rmind 	NFSUNLOCKSOCK();
   3532  1.1.1.1.4.2  rmind }
   3533  1.1.1.1.4.2  rmind 
   3534  1.1.1.1.4.2  rmind APPLESTATIC int
   3535  1.1.1.1.4.2  rmind nfsv4_getipaddr(struct nfsrv_descript *nd, struct sockaddr_storage *sa,
   3536  1.1.1.1.4.2  rmind     int *isudp)
   3537  1.1.1.1.4.2  rmind {
   3538  1.1.1.1.4.2  rmind 	struct sockaddr_in *sad;
   3539  1.1.1.1.4.2  rmind 	struct sockaddr_in6 *sad6;
   3540  1.1.1.1.4.2  rmind 	struct in_addr saddr;
   3541  1.1.1.1.4.2  rmind 	uint32_t portnum, *tl;
   3542  1.1.1.1.4.2  rmind 	int af = 0, i, j, k;
   3543  1.1.1.1.4.2  rmind 	char addr[64], protocol[5], *cp;
   3544  1.1.1.1.4.2  rmind 	int cantparse = 0, error = 0;
   3545  1.1.1.1.4.2  rmind 	uint16_t portv;
   3546  1.1.1.1.4.2  rmind 
   3547  1.1.1.1.4.2  rmind 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   3548  1.1.1.1.4.2  rmind 	i = fxdr_unsigned(int, *tl);
   3549  1.1.1.1.4.2  rmind 	if (i >= 3 && i <= 4) {
   3550  1.1.1.1.4.2  rmind 		error = nfsrv_mtostr(nd, protocol, i);
   3551  1.1.1.1.4.2  rmind 		if (error)
   3552  1.1.1.1.4.2  rmind 			goto nfsmout;
   3553  1.1.1.1.4.2  rmind 		if (strcmp(protocol, "tcp") == 0) {
   3554  1.1.1.1.4.2  rmind 			af = AF_INET;
   3555  1.1.1.1.4.2  rmind 			*isudp = 0;
   3556  1.1.1.1.4.2  rmind 		} else if (strcmp(protocol, "udp") == 0) {
   3557  1.1.1.1.4.2  rmind 			af = AF_INET;
   3558  1.1.1.1.4.2  rmind 			*isudp = 1;
   3559  1.1.1.1.4.2  rmind 		} else if (strcmp(protocol, "tcp6") == 0) {
   3560  1.1.1.1.4.2  rmind 			af = AF_INET6;
   3561  1.1.1.1.4.2  rmind 			*isudp = 0;
   3562  1.1.1.1.4.2  rmind 		} else if (strcmp(protocol, "udp6") == 0) {
   3563  1.1.1.1.4.2  rmind 			af = AF_INET6;
   3564  1.1.1.1.4.2  rmind 			*isudp = 1;
   3565  1.1.1.1.4.2  rmind 		} else
   3566  1.1.1.1.4.2  rmind 			cantparse = 1;
   3567  1.1.1.1.4.2  rmind 	} else {
   3568  1.1.1.1.4.2  rmind 		cantparse = 1;
   3569  1.1.1.1.4.2  rmind 		if (i > 0) {
   3570  1.1.1.1.4.2  rmind 			error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
   3571  1.1.1.1.4.2  rmind 			if (error)
   3572  1.1.1.1.4.2  rmind 				goto nfsmout;
   3573  1.1.1.1.4.2  rmind 		}
   3574  1.1.1.1.4.2  rmind 	}
   3575  1.1.1.1.4.2  rmind 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
   3576  1.1.1.1.4.2  rmind 	i = fxdr_unsigned(int, *tl);
   3577  1.1.1.1.4.2  rmind 	if (i < 0) {
   3578  1.1.1.1.4.2  rmind 		error = NFSERR_BADXDR;
   3579  1.1.1.1.4.2  rmind 		goto nfsmout;
   3580  1.1.1.1.4.2  rmind 	} else if (cantparse == 0 && i >= 11 && i < 64) {
   3581  1.1.1.1.4.2  rmind 		/*
   3582  1.1.1.1.4.2  rmind 		 * The shortest address is 11chars and the longest is < 64.
   3583  1.1.1.1.4.2  rmind 		 */
   3584  1.1.1.1.4.2  rmind 		error = nfsrv_mtostr(nd, addr, i);
   3585  1.1.1.1.4.2  rmind 		if (error)
   3586  1.1.1.1.4.2  rmind 			goto nfsmout;
   3587  1.1.1.1.4.2  rmind 
   3588  1.1.1.1.4.2  rmind 		/* Find the port# at the end and extract that. */
   3589  1.1.1.1.4.2  rmind 		i = strlen(addr);
   3590  1.1.1.1.4.2  rmind 		k = 0;
   3591  1.1.1.1.4.2  rmind 		cp = &addr[i - 1];
   3592  1.1.1.1.4.2  rmind 		/* Count back two '.'s from end to get port# field. */
   3593  1.1.1.1.4.2  rmind 		for (j = 0; j < i; j++) {
   3594  1.1.1.1.4.2  rmind 			if (*cp == '.') {
   3595  1.1.1.1.4.2  rmind 				k++;
   3596  1.1.1.1.4.2  rmind 				if (k == 2)
   3597  1.1.1.1.4.2  rmind 					break;
   3598  1.1.1.1.4.2  rmind 			}
   3599  1.1.1.1.4.2  rmind 			cp--;
   3600  1.1.1.1.4.2  rmind 		}
   3601  1.1.1.1.4.2  rmind 		if (k == 2) {
   3602  1.1.1.1.4.2  rmind 			/*
   3603  1.1.1.1.4.2  rmind 			 * The NFSv4 port# is appended as .N.N, where N is
   3604  1.1.1.1.4.2  rmind 			 * a decimal # in the range 0-255, just like an inet4
   3605  1.1.1.1.4.2  rmind 			 * address. Cheat and use inet_aton(), which will
   3606  1.1.1.1.4.2  rmind 			 * return a Class A address and then shift the high
   3607  1.1.1.1.4.2  rmind 			 * order 8bits over to convert it to the port#.
   3608  1.1.1.1.4.2  rmind 			 */
   3609  1.1.1.1.4.2  rmind 			*cp++ = '\0';
   3610  1.1.1.1.4.2  rmind 			if (inet_aton(cp, &saddr) == 1) {
   3611  1.1.1.1.4.2  rmind 				portnum = ntohl(saddr.s_addr);
   3612  1.1.1.1.4.2  rmind 				portv = (uint16_t)((portnum >> 16) |
   3613  1.1.1.1.4.2  rmind 				    (portnum & 0xff));
   3614  1.1.1.1.4.2  rmind 			} else
   3615  1.1.1.1.4.2  rmind 				cantparse = 1;
   3616  1.1.1.1.4.2  rmind 		} else
   3617  1.1.1.1.4.2  rmind 			cantparse = 1;
   3618  1.1.1.1.4.2  rmind 		if (cantparse == 0) {
   3619  1.1.1.1.4.2  rmind 			if (af == AF_INET) {
   3620  1.1.1.1.4.2  rmind 				sad = (struct sockaddr_in *)sa;
   3621  1.1.1.1.4.2  rmind 				if (inet_pton(af, addr, &sad->sin_addr) == 1) {
   3622  1.1.1.1.4.2  rmind 					sad->sin_len = sizeof(*sad);
   3623  1.1.1.1.4.2  rmind 					sad->sin_family = AF_INET;
   3624  1.1.1.1.4.2  rmind 					sad->sin_port = htons(portv);
   3625  1.1.1.1.4.2  rmind 					return (0);
   3626  1.1.1.1.4.2  rmind 				}
   3627  1.1.1.1.4.2  rmind 			} else {
   3628  1.1.1.1.4.2  rmind 				sad6 = (struct sockaddr_in6 *)sa;
   3629  1.1.1.1.4.2  rmind 				if (inet_pton(af, addr, &sad6->sin6_addr)
   3630  1.1.1.1.4.2  rmind 				    == 1) {
   3631  1.1.1.1.4.2  rmind 					sad6->sin6_len = sizeof(*sad6);
   3632  1.1.1.1.4.2  rmind 					sad6->sin6_family = AF_INET6;
   3633  1.1.1.1.4.2  rmind 					sad6->sin6_port = htons(portv);
   3634  1.1.1.1.4.2  rmind 					return (0);
   3635  1.1.1.1.4.2  rmind 				}
   3636  1.1.1.1.4.2  rmind 			}
   3637  1.1.1.1.4.2  rmind 		}
   3638  1.1.1.1.4.2  rmind 	} else {
   3639  1.1.1.1.4.2  rmind 		if (i > 0) {
   3640  1.1.1.1.4.2  rmind 			error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
   3641  1.1.1.1.4.2  rmind 			if (error)
   3642  1.1.1.1.4.2  rmind 				goto nfsmout;
   3643  1.1.1.1.4.2  rmind 		}
   3644  1.1.1.1.4.2  rmind 	}
   3645  1.1.1.1.4.2  rmind 	error = EPERM;
   3646  1.1.1.1.4.2  rmind nfsmout:
   3647  1.1.1.1.4.2  rmind 	return (error);
   3648  1.1.1.1.4.2  rmind }
   3649  1.1.1.1.4.2  rmind 
   3650  1.1.1.1.4.2  rmind /*
   3651  1.1.1.1.4.2  rmind  * Handle an NFSv4.1 Sequence request for the session.
   3652  1.1.1.1.4.2  rmind  */
   3653  1.1.1.1.4.2  rmind int
   3654  1.1.1.1.4.2  rmind nfsv4_seqsession(uint32_t seqid, uint32_t slotid, uint32_t highslot,
   3655  1.1.1.1.4.2  rmind     struct nfsslot *slots, struct mbuf **reply, uint16_t maxslot)
   3656  1.1.1.1.4.2  rmind {
   3657  1.1.1.1.4.2  rmind 	int error;
   3658  1.1.1.1.4.2  rmind 
   3659  1.1.1.1.4.2  rmind 	error = 0;
   3660  1.1.1.1.4.2  rmind 	*reply = NULL;
   3661  1.1.1.1.4.2  rmind 	if (slotid > maxslot)
   3662  1.1.1.1.4.2  rmind 		return (NFSERR_BADSLOT);
   3663  1.1.1.1.4.2  rmind 	if (seqid == slots[slotid].nfssl_seq) {
   3664  1.1.1.1.4.2  rmind 		/* A retry. */
   3665  1.1.1.1.4.2  rmind 		if (slots[slotid].nfssl_inprog != 0)
   3666  1.1.1.1.4.2  rmind 			error = NFSERR_DELAY;
   3667  1.1.1.1.4.2  rmind 		else if (slots[slotid].nfssl_reply != NULL) {
   3668  1.1.1.1.4.2  rmind 			*reply = slots[slotid].nfssl_reply;
   3669  1.1.1.1.4.2  rmind 			slots[slotid].nfssl_reply = NULL;
   3670  1.1.1.1.4.2  rmind 			slots[slotid].nfssl_inprog = 1;
   3671  1.1.1.1.4.2  rmind 		} else
   3672  1.1.1.1.4.2  rmind 			error = NFSERR_SEQMISORDERED;
   3673  1.1.1.1.4.2  rmind 	} else if ((slots[slotid].nfssl_seq + 1) == seqid) {
   3674  1.1.1.1.4.2  rmind 		m_freem(slots[slotid].nfssl_reply);
   3675  1.1.1.1.4.2  rmind 		slots[slotid].nfssl_reply = NULL;
   3676  1.1.1.1.4.2  rmind 		slots[slotid].nfssl_inprog = 1;
   3677  1.1.1.1.4.2  rmind 		slots[slotid].nfssl_seq++;
   3678  1.1.1.1.4.2  rmind 	} else
   3679  1.1.1.1.4.2  rmind 		error = NFSERR_SEQMISORDERED;
   3680  1.1.1.1.4.2  rmind 	return (error);
   3681  1.1.1.1.4.2  rmind }
   3682  1.1.1.1.4.2  rmind 
   3683  1.1.1.1.4.2  rmind /*
   3684  1.1.1.1.4.2  rmind  * Cache this reply for the slot.
   3685  1.1.1.1.4.2  rmind  */
   3686  1.1.1.1.4.2  rmind void
   3687  1.1.1.1.4.2  rmind nfsv4_seqsess_cacherep(uint32_t slotid, struct nfsslot *slots, struct mbuf *rep)
   3688  1.1.1.1.4.2  rmind {
   3689  1.1.1.1.4.2  rmind 
   3690  1.1.1.1.4.2  rmind 	slots[slotid].nfssl_reply = rep;
   3691  1.1.1.1.4.2  rmind 	slots[slotid].nfssl_inprog = 0;
   3692  1.1.1.1.4.2  rmind }
   3693  1.1.1.1.4.2  rmind 
   3694  1.1.1.1.4.2  rmind /*
   3695  1.1.1.1.4.2  rmind  * Generate the xdr for an NFSv4.1 Sequence Operation.
   3696  1.1.1.1.4.2  rmind  */
   3697  1.1.1.1.4.2  rmind APPLESTATIC void
   3698  1.1.1.1.4.2  rmind nfsv4_setsequence(struct nfsrv_descript *nd, struct nfsclsession *sep,
   3699  1.1.1.1.4.2  rmind     int dont_replycache)
   3700  1.1.1.1.4.2  rmind {
   3701  1.1.1.1.4.2  rmind 	uint32_t *tl, slotseq = 0;
   3702  1.1.1.1.4.2  rmind 	int i, maxslot, slotpos;
   3703  1.1.1.1.4.2  rmind 	uint64_t bitval;
   3704  1.1.1.1.4.2  rmind 	uint8_t sessionid[NFSX_V4SESSIONID];
   3705  1.1.1.1.4.2  rmind 
   3706  1.1.1.1.4.2  rmind 	/* Find an unused slot. */
   3707  1.1.1.1.4.2  rmind 	slotpos = -1;
   3708  1.1.1.1.4.2  rmind 	maxslot = -1;
   3709  1.1.1.1.4.2  rmind 	mtx_lock(&sep->nfsess_mtx);
   3710  1.1.1.1.4.2  rmind 	do {
   3711  1.1.1.1.4.2  rmind 		bitval = 1;
   3712  1.1.1.1.4.2  rmind 		for (i = 0; i < sep->nfsess_foreslots; i++) {
   3713  1.1.1.1.4.2  rmind 			if ((bitval & sep->nfsess_slots) == 0) {
   3714  1.1.1.1.4.2  rmind 				slotpos = i;
   3715  1.1.1.1.4.2  rmind 				sep->nfsess_slots |= bitval;
   3716  1.1.1.1.4.2  rmind 				sep->nfsess_slotseq[i]++;
   3717  1.1.1.1.4.2  rmind 				slotseq = sep->nfsess_slotseq[i];
   3718  1.1.1.1.4.2  rmind 				break;
   3719  1.1.1.1.4.2  rmind 			}
   3720  1.1.1.1.4.2  rmind 			bitval <<= 1;
   3721  1.1.1.1.4.2  rmind 		}
   3722  1.1.1.1.4.2  rmind 		if (slotpos == -1)
   3723  1.1.1.1.4.2  rmind 			(void)mtx_sleep(&sep->nfsess_slots, &sep->nfsess_mtx,
   3724  1.1.1.1.4.2  rmind 			    PZERO, "nfsclseq", 0);
   3725  1.1.1.1.4.2  rmind 	} while (slotpos == -1);
   3726  1.1.1.1.4.2  rmind 	/* Now, find the highest slot in use. (nfsc_slots is 64bits) */
   3727  1.1.1.1.4.2  rmind 	bitval = 1;
   3728  1.1.1.1.4.2  rmind 	for (i = 0; i < 64; i++) {
   3729  1.1.1.1.4.2  rmind 		if ((bitval & sep->nfsess_slots) != 0)
   3730  1.1.1.1.4.2  rmind 			maxslot = i;
   3731  1.1.1.1.4.2  rmind 		bitval <<= 1;
   3732  1.1.1.1.4.2  rmind 	}
   3733  1.1.1.1.4.2  rmind 	bcopy(sep->nfsess_sessionid, sessionid, NFSX_V4SESSIONID);
   3734  1.1.1.1.4.2  rmind 	mtx_unlock(&sep->nfsess_mtx);
   3735  1.1.1.1.4.2  rmind 	KASSERT(maxslot >= 0, ("nfscl_setsequence neg maxslot"));
   3736  1.1.1.1.4.2  rmind 
   3737  1.1.1.1.4.2  rmind 	/* Build the Sequence arguments. */
   3738  1.1.1.1.4.2  rmind 	NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 4 * NFSX_UNSIGNED);
   3739  1.1.1.1.4.2  rmind 	bcopy(sessionid, tl, NFSX_V4SESSIONID);
   3740  1.1.1.1.4.2  rmind 	tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
   3741  1.1.1.1.4.2  rmind 	nd->nd_slotseq = tl;
   3742  1.1.1.1.4.2  rmind 	*tl++ = txdr_unsigned(slotseq);
   3743  1.1.1.1.4.2  rmind 	*tl++ = txdr_unsigned(slotpos);
   3744  1.1.1.1.4.2  rmind 	*tl++ = txdr_unsigned(maxslot);
   3745  1.1.1.1.4.2  rmind 	if (dont_replycache == 0)
   3746  1.1.1.1.4.2  rmind 		*tl = newnfs_true;
   3747  1.1.1.1.4.2  rmind 	else
   3748  1.1.1.1.4.2  rmind 		*tl = newnfs_false;
   3749  1.1.1.1.4.2  rmind 	nd->nd_flag |= ND_HASSEQUENCE;
   3750  1.1.1.1.4.2  rmind }
   3751  1.1.1.1.4.2  rmind 
   3752  1.1.1.1.4.2  rmind /*
   3753  1.1.1.1.4.2  rmind  * Free a session slot.
   3754  1.1.1.1.4.2  rmind  */
   3755  1.1.1.1.4.2  rmind APPLESTATIC void
   3756  1.1.1.1.4.2  rmind nfsv4_freeslot(struct nfsclsession *sep, int slot)
   3757  1.1.1.1.4.2  rmind {
   3758  1.1.1.1.4.2  rmind 	uint64_t bitval;
   3759  1.1.1.1.4.2  rmind 
   3760  1.1.1.1.4.2  rmind 	bitval = 1;
   3761  1.1.1.1.4.2  rmind 	if (slot > 0)
   3762  1.1.1.1.4.2  rmind 		bitval <<= slot;
   3763  1.1.1.1.4.2  rmind 	mtx_lock(&sep->nfsess_mtx);
   3764  1.1.1.1.4.2  rmind 	if ((bitval & sep->nfsess_slots) == 0)
   3765  1.1.1.1.4.2  rmind 		printf("freeing free slot!!\n");
   3766  1.1.1.1.4.2  rmind 	sep->nfsess_slots &= ~bitval;
   3767  1.1.1.1.4.2  rmind 	wakeup(&sep->nfsess_slots);
   3768  1.1.1.1.4.2  rmind 	mtx_unlock(&sep->nfsess_mtx);
   3769  1.1.1.1.4.2  rmind }
   3770  1.1.1.1.4.2  rmind 
   3771