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