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