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