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