|
1 /* |
|
2 * CDDL HEADER START |
|
3 * |
|
4 * The contents of this file are subject to the terms of the |
|
5 * Common Development and Distribution License, Version 1.0 only |
|
6 * (the "License"). You may not use this file except in compliance |
|
7 * with the License. |
|
8 * |
|
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
10 * or http://www.opensolaris.org/os/licensing. |
|
11 * See the License for the specific language governing permissions |
|
12 * and limitations under the License. |
|
13 * |
|
14 * When distributing Covered Code, include this CDDL HEADER in each |
|
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
16 * If applicable, add the following below this CDDL HEADER, with the |
|
17 * fields enclosed by brackets "[]" replaced with your own identifying |
|
18 * information: Portions Copyright [yyyy] [name of copyright owner] |
|
19 * |
|
20 * CDDL HEADER END |
|
21 */ |
|
22 /* |
|
23 * Copyright 2005 Sun Microsystems, Inc. |
|
24 * All rights reserved. Use is subject to license terms. |
|
25 */ |
|
26 |
|
27 #pragma ident "%Z%%M% %I% %E% SMI" |
|
28 |
|
29 /* |
|
30 * A handcoded version based on the original rpcgen code. |
|
31 * |
|
32 * Note: All future NFS4 protocol changes should be added by hand |
|
33 * to this file. |
|
34 * |
|
35 * CAUTION: All protocol changes must also be propagated to: |
|
36 * usr/src/cmd/cmd-inet/usr.sbin/snoop/nfs4_xdr.c |
|
37 */ |
|
38 |
|
39 #include <sys/types.h> |
|
40 #include <sys/sunddi.h> |
|
41 #include <sys/dnlc.h> |
|
42 #include <nfs/nfs.h> |
|
43 #include <nfs/nfs4_kprot.h> |
|
44 #include <nfs/rnode4.h> |
|
45 #include <nfs/nfs4.h> |
|
46 #include <nfs/nfs4_clnt.h> |
|
47 #include <sys/sdt.h> |
|
48 #include <rpc/rpc_rdma.h> |
|
49 |
|
50 bool_t |
|
51 xdr_bitmap4(XDR *xdrs, bitmap4 *objp) |
|
52 { |
|
53 int32_t len, size; |
|
54 |
|
55 if (xdrs->x_op == XDR_FREE) |
|
56 return (TRUE); |
|
57 |
|
58 /* |
|
59 * Simplified bitmap4 processing, always encode from uint64_t |
|
60 * to 2 uint32_t's, always decode first 2 uint32_t's into a |
|
61 * uint64_t and ignore all of the rest. |
|
62 */ |
|
63 if (xdrs->x_op == XDR_ENCODE) { |
|
64 len = 2; |
|
65 |
|
66 if (!XDR_PUTINT32(xdrs, &len)) |
|
67 return (FALSE); |
|
68 |
|
69 #if defined(_LITTLE_ENDIAN) |
|
70 if (XDR_PUTINT32(xdrs, (int32_t *)((char *)objp + |
|
71 BYTES_PER_XDR_UNIT)) == TRUE) { |
|
72 return (XDR_PUTINT32(xdrs, (int32_t *)objp)); |
|
73 } |
|
74 #elif defined(_BIG_ENDIAN) |
|
75 if (XDR_PUTINT32(xdrs, (int32_t *)objp) == TRUE) { |
|
76 return (XDR_PUTINT32(xdrs, (int32_t *)((char *)objp + |
|
77 BYTES_PER_XDR_UNIT))); |
|
78 } |
|
79 #endif |
|
80 return (FALSE); |
|
81 } |
|
82 |
|
83 if (!XDR_GETINT32(xdrs, &len)) |
|
84 return (FALSE); |
|
85 |
|
86 /* |
|
87 * Common fast DECODE cases |
|
88 */ |
|
89 if (len == 2) { |
|
90 #if defined(_LITTLE_ENDIAN) |
|
91 if (XDR_GETINT32(xdrs, (int32_t *)((char *)objp + |
|
92 BYTES_PER_XDR_UNIT)) == TRUE) { |
|
93 return (XDR_GETINT32(xdrs, (int32_t *)objp)); |
|
94 } |
|
95 #elif defined(_BIG_ENDIAN) |
|
96 if (XDR_GETINT32(xdrs, (int32_t *)objp) == TRUE) { |
|
97 return (XDR_GETINT32(xdrs, (int32_t *)((char *)objp + |
|
98 BYTES_PER_XDR_UNIT))); |
|
99 } |
|
100 #endif |
|
101 return (FALSE); |
|
102 } |
|
103 |
|
104 *objp = 0; |
|
105 if (len == 0) |
|
106 return (TRUE); |
|
107 |
|
108 /* |
|
109 * The not so common DECODE cases, len == 1 || len > 2 |
|
110 */ |
|
111 #if defined(_LITTLE_ENDIAN) |
|
112 if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT))) |
|
113 return (FALSE); |
|
114 if (--len == 0) |
|
115 return (TRUE); |
|
116 if (!XDR_GETINT32(xdrs, (int32_t *)objp)) |
|
117 return (FALSE); |
|
118 #elif defined(_BIG_ENDIAN) |
|
119 if (!XDR_GETINT32(xdrs, (int32_t *)objp)) |
|
120 return (FALSE); |
|
121 if (--len == 0) |
|
122 return (TRUE); |
|
123 if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT))) |
|
124 return (FALSE); |
|
125 #else |
|
126 return (FALSE); |
|
127 #endif |
|
128 |
|
129 if (--len == 0) |
|
130 return (TRUE); |
|
131 |
|
132 size = len * BYTES_PER_XDR_UNIT; |
|
133 return (XDR_CONTROL(xdrs, XDR_SKIPBYTES, &size)); |
|
134 } |
|
135 |
|
136 /* Called by xdr_array, nfsid_map_xdr */ |
|
137 bool_t |
|
138 xdr_utf8string(XDR *xdrs, utf8string *objp) |
|
139 { |
|
140 if (xdrs->x_op != XDR_FREE) |
|
141 return (xdr_bytes(xdrs, (char **)&objp->utf8string_val, |
|
142 (uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING)); |
|
143 |
|
144 if (objp->utf8string_val != NULL) { |
|
145 kmem_free(objp->utf8string_val, objp->utf8string_len); |
|
146 objp->utf8string_val = NULL; |
|
147 } |
|
148 return (TRUE); |
|
149 } |
|
150 |
|
151 /* |
|
152 * Called in nfs_acl_xdr.c |
|
153 */ |
|
154 bool_t |
|
155 xdr_nfs_fh4(XDR *xdrs, nfs_fh4 *objp) |
|
156 { |
|
157 if (xdrs->x_op != XDR_FREE) |
|
158 return (xdr_bytes(xdrs, (char **)&objp->nfs_fh4_val, |
|
159 (uint_t *)&objp->nfs_fh4_len, NFS4_FHSIZE)); |
|
160 |
|
161 if (objp->nfs_fh4_val != NULL) { |
|
162 kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len); |
|
163 objp->nfs_fh4_val = NULL; |
|
164 } |
|
165 return (TRUE); |
|
166 } |
|
167 |
|
168 /* Called by xdr_array */ |
|
169 static bool_t |
|
170 xdr_fs_location4(XDR *xdrs, fs_location4 *objp) |
|
171 { |
|
172 if (!xdr_array(xdrs, (char **)&objp->server_val, |
|
173 (uint_t *)&objp->server_len, NFS4_FS_LOCATIONS_LIMIT, |
|
174 sizeof (utf8string), (xdrproc_t)xdr_utf8string)) |
|
175 return (FALSE); |
|
176 return (xdr_array(xdrs, (char **)&objp->rootpath.pathname4_val, |
|
177 (uint_t *)&objp->rootpath.pathname4_len, |
|
178 NFS4_MAX_PATHNAME4, |
|
179 sizeof (utf8string), (xdrproc_t)xdr_utf8string)); |
|
180 } |
|
181 |
|
182 /* Called by xdr_array */ |
|
183 static bool_t |
|
184 xdr_nfsace4(XDR *xdrs, nfsace4 *objp) |
|
185 { |
|
186 if (xdrs->x_op != XDR_FREE) { |
|
187 if (!xdr_u_int(xdrs, &objp->type)) |
|
188 return (FALSE); |
|
189 if (!xdr_u_int(xdrs, &objp->flag)) |
|
190 return (FALSE); |
|
191 if (!xdr_u_int(xdrs, &objp->access_mask)) |
|
192 return (FALSE); |
|
193 |
|
194 if (xdrs->x_op == XDR_DECODE) { |
|
195 objp->who.utf8string_val = NULL; |
|
196 objp->who.utf8string_len = 0; |
|
197 } |
|
198 |
|
199 return (xdr_bytes(xdrs, (char **)&objp->who.utf8string_val, |
|
200 (uint_t *)&objp->who.utf8string_len, |
|
201 NFS4_MAX_UTF8STRING)); |
|
202 } |
|
203 |
|
204 /* |
|
205 * Optimized free case |
|
206 */ |
|
207 if (objp->who.utf8string_val != NULL) { |
|
208 kmem_free(objp->who.utf8string_val, objp->who.utf8string_len); |
|
209 objp->who.utf8string_val = NULL; |
|
210 } |
|
211 return (TRUE); |
|
212 } |
|
213 |
|
214 /* |
|
215 * These functions are called out of nfs4_attr.c |
|
216 */ |
|
217 bool_t |
|
218 xdr_fattr4_fsid(XDR *xdrs, fattr4_fsid *objp) |
|
219 { |
|
220 if (xdrs->x_op == XDR_FREE) |
|
221 return (TRUE); |
|
222 |
|
223 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->major)) |
|
224 return (FALSE); |
|
225 return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->minor)); |
|
226 } |
|
227 |
|
228 |
|
229 bool_t |
|
230 xdr_fattr4_acl(XDR *xdrs, fattr4_acl *objp) |
|
231 { |
|
232 return (xdr_array(xdrs, (char **)&objp->fattr4_acl_val, |
|
233 (uint_t *)&objp->fattr4_acl_len, NFS4_ACL_LIMIT, |
|
234 sizeof (nfsace4), (xdrproc_t)xdr_nfsace4)); |
|
235 } |
|
236 |
|
237 bool_t |
|
238 xdr_fattr4_fs_locations(XDR *xdrs, fattr4_fs_locations *objp) |
|
239 { |
|
240 if (!xdr_array(xdrs, (char **)&objp->fs_root.pathname4_val, |
|
241 (uint_t *)&objp->fs_root.pathname4_len, |
|
242 NFS4_MAX_PATHNAME4, |
|
243 sizeof (utf8string), (xdrproc_t)xdr_utf8string)) |
|
244 return (FALSE); |
|
245 return (xdr_array(xdrs, (char **)&objp->locations_val, |
|
246 (uint_t *)&objp->locations_len, NFS4_FS_LOCATIONS_LIMIT, |
|
247 sizeof (fs_location4), (xdrproc_t)xdr_fs_location4)); |
|
248 } |
|
249 |
|
250 bool_t |
|
251 xdr_fattr4_rawdev(XDR *xdrs, fattr4_rawdev *objp) |
|
252 { |
|
253 if (xdrs->x_op == XDR_FREE) |
|
254 return (TRUE); |
|
255 |
|
256 if (!xdr_u_int(xdrs, &objp->specdata1)) |
|
257 return (FALSE); |
|
258 return (xdr_u_int(xdrs, &objp->specdata2)); |
|
259 } |
|
260 |
|
261 bool_t |
|
262 xdr_nfstime4(XDR *xdrs, nfstime4 *objp) |
|
263 { |
|
264 if (xdrs->x_op == XDR_FREE) |
|
265 return (TRUE); |
|
266 |
|
267 if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->seconds)) |
|
268 return (FALSE); |
|
269 return (xdr_u_int(xdrs, &objp->nseconds)); |
|
270 } |
|
271 |
|
272 |
|
273 /* |
|
274 * structured used for calls into xdr_ga_fattr_res() as a means |
|
275 * to do an immediate/short-term cache of owner/group strings |
|
276 * for callers like the readdir processing. In the case of readdir, |
|
277 * it is likely that the directory objects will be owned by the same |
|
278 * owner/group and if so there is no need to call into the uid/gid |
|
279 * mapping code. While the uid/gid interfaces have their own cache |
|
280 * having one here will reduct pathlength further. |
|
281 */ |
|
282 #define MAX_OG_NAME 100 |
|
283 typedef struct ug_cache |
|
284 { |
|
285 uid_t uid; |
|
286 gid_t gid; |
|
287 utf8string u_curr, u_last; |
|
288 utf8string g_curr, g_last; |
|
289 char u_buf1[MAX_OG_NAME]; |
|
290 char u_buf2[MAX_OG_NAME]; |
|
291 char g_buf1[MAX_OG_NAME]; |
|
292 char g_buf2[MAX_OG_NAME]; |
|
293 } ug_cache_t; |
|
294 |
|
295 #define U_SWAP_CURR_LAST(ug) \ |
|
296 (ug)->u_last.utf8string_len = (ug)->u_curr.utf8string_len; \ |
|
297 if ((ug)->u_last.utf8string_val == (ug)->u_buf1) { \ |
|
298 (ug)->u_last.utf8string_val = (ug)->u_buf2; \ |
|
299 (ug)->u_curr.utf8string_val = (ug)->u_buf1; \ |
|
300 } else { \ |
|
301 (ug)->u_last.utf8string_val = (ug)->u_buf1; \ |
|
302 (ug)->u_curr.utf8string_val = (ug)->u_buf2; \ |
|
303 } |
|
304 |
|
305 #define G_SWAP_CURR_LAST(ug) \ |
|
306 (ug)->g_last.utf8string_len = (ug)->g_curr.utf8string_len; \ |
|
307 if ((ug)->g_last.utf8string_val == (ug)->g_buf1) { \ |
|
308 (ug)->g_last.utf8string_val = (ug)->g_buf2; \ |
|
309 (ug)->g_curr.utf8string_val = (ug)->g_buf1; \ |
|
310 } else { \ |
|
311 (ug)->g_last.utf8string_val = (ug)->g_buf1; \ |
|
312 (ug)->g_curr.utf8string_val = (ug)->g_buf2; \ |
|
313 } |
|
314 |
|
315 static ug_cache_t * |
|
316 alloc_ugcache() |
|
317 { |
|
318 ug_cache_t *pug = kmem_alloc(sizeof (ug_cache_t), KM_SLEEP); |
|
319 |
|
320 pug->uid = pug->gid = 0; |
|
321 pug->u_curr.utf8string_len = 0; |
|
322 pug->u_last.utf8string_len = 0; |
|
323 pug->g_curr.utf8string_len = 0; |
|
324 pug->g_last.utf8string_len = 0; |
|
325 pug->u_curr.utf8string_val = pug->u_buf1; |
|
326 pug->u_last.utf8string_val = pug->u_buf2; |
|
327 pug->g_curr.utf8string_val = pug->g_buf1; |
|
328 pug->g_last.utf8string_val = pug->g_buf2; |
|
329 |
|
330 return (pug); |
|
331 } |
|
332 |
|
333 static void |
|
334 xdr_ga_prefill_vattr(struct nfs4_ga_res *garp, struct mntinfo4 *mi) |
|
335 { |
|
336 static vattr_t s_vattr = { |
|
337 AT_ALL, /* va_mask */ |
|
338 VNON, /* va_type */ |
|
339 0777, /* va_mode */ |
|
340 UID_NOBODY, /* va_uid */ |
|
341 GID_NOBODY, /* va_gid */ |
|
342 0, /* va_fsid */ |
|
343 0, /* va_nodeid */ |
|
344 1, /* va_nlink */ |
|
345 0, /* va_size */ |
|
346 {0, 0}, /* va_atime */ |
|
347 {0, 0}, /* va_mtime */ |
|
348 {0, 0}, /* va_ctime */ |
|
349 0, /* va_rdev */ |
|
350 MAXBSIZE, /* va_blksize */ |
|
351 0, /* va_nblocks */ |
|
352 0 /* va_seq */ |
|
353 }; |
|
354 |
|
355 |
|
356 garp->n4g_va = s_vattr; |
|
357 garp->n4g_va.va_fsid = mi->mi_vfsp->vfs_dev; |
|
358 hrt2ts(gethrtime(), &garp->n4g_va.va_atime); |
|
359 garp->n4g_va.va_mtime = garp->n4g_va.va_ctime = garp->n4g_va.va_atime; |
|
360 } |
|
361 |
|
362 static void |
|
363 xdr_ga_prefill_statvfs(struct nfs4_ga_ext_res *gesp, struct mntinfo4 *mi) |
|
364 { |
|
365 static statvfs64_t s_sb = { |
|
366 MAXBSIZE, /* f_bsize */ |
|
367 DEV_BSIZE, /* f_frsize */ |
|
368 (fsfilcnt64_t)-1, /* f_blocks */ |
|
369 (fsfilcnt64_t)-1, /* f_bfree */ |
|
370 (fsfilcnt64_t)-1, /* f_bavail */ |
|
371 (fsfilcnt64_t)-1, /* f_files */ |
|
372 (fsfilcnt64_t)-1, /* f_ffree */ |
|
373 (fsfilcnt64_t)-1, /* f_favail */ |
|
374 0, /* f_fsid */ |
|
375 "\0", /* f_basetype */ |
|
376 0, /* f_flag */ |
|
377 MAXNAMELEN, /* f_namemax */ |
|
378 "\0", /* f_fstr */ |
|
379 }; |
|
380 |
|
381 gesp->n4g_sb = s_sb; |
|
382 gesp->n4g_sb.f_fsid = mi->mi_vfsp->vfs_fsid.val[0]; |
|
383 } |
|
384 |
|
385 static bool_t |
|
386 xdr_ga_fattr_res(XDR *xdrs, struct nfs4_ga_res *garp, bitmap4 resbmap, |
|
387 bitmap4 argbmap, struct mntinfo4 *mi, ug_cache_t *pug) |
|
388 { |
|
389 int truefalse; |
|
390 struct nfs4_ga_ext_res ges, *gesp; |
|
391 vattr_t *vap = &garp->n4g_va; |
|
392 vsecattr_t *vsap = &garp->n4g_vsa; |
|
393 |
|
394 ASSERT(xdrs->x_op == XDR_DECODE); |
|
395 |
|
396 if (garp->n4g_ext_res) |
|
397 gesp = garp->n4g_ext_res; |
|
398 else |
|
399 gesp = ⩾ |
|
400 |
|
401 vap->va_mask = 0; |
|
402 |
|
403 /* Check to see if the vattr should be pre-filled */ |
|
404 if (argbmap & NFS4_VATTR_MASK) |
|
405 xdr_ga_prefill_vattr(garp, mi); |
|
406 |
|
407 if (argbmap & NFS4_STATFS_ATTR_MASK) |
|
408 xdr_ga_prefill_statvfs(gesp, mi); |
|
409 |
|
410 if (resbmap & |
|
411 (FATTR4_SUPPORTED_ATTRS_MASK | |
|
412 FATTR4_TYPE_MASK | |
|
413 FATTR4_FH_EXPIRE_TYPE_MASK | |
|
414 FATTR4_CHANGE_MASK | |
|
415 FATTR4_SIZE_MASK | |
|
416 FATTR4_LINK_SUPPORT_MASK | |
|
417 FATTR4_SYMLINK_SUPPORT_MASK | |
|
418 FATTR4_NAMED_ATTR_MASK)) { |
|
419 |
|
420 if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) { |
|
421 if (!xdr_bitmap4(xdrs, &gesp->n4g_suppattrs)) |
|
422 return (FALSE); |
|
423 } |
|
424 if (resbmap & FATTR4_TYPE_MASK) { |
|
425 if (!XDR_GETINT32(xdrs, (int *)&vap->va_type)) |
|
426 return (FALSE); |
|
427 |
|
428 if (vap->va_type < NF4REG || |
|
429 vap->va_type > NF4NAMEDATTR) |
|
430 vap->va_type = VBAD; |
|
431 else |
|
432 vap->va_type = nf4_to_vt[vap->va_type]; |
|
433 if (vap->va_type == VBLK) |
|
434 vap->va_blksize = DEV_BSIZE; |
|
435 |
|
436 vap->va_mask |= AT_TYPE; |
|
437 } |
|
438 if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) { |
|
439 if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_fet)) |
|
440 return (FALSE); |
|
441 } |
|
442 if (resbmap & FATTR4_CHANGE_MASK) { |
|
443 if (!xdr_u_longlong_t(xdrs, |
|
444 (u_longlong_t *)&garp->n4g_change)) |
|
445 return (FALSE); |
|
446 garp->n4g_change_valid = 1; |
|
447 } |
|
448 if (resbmap & FATTR4_SIZE_MASK) { |
|
449 if (!xdr_u_longlong_t(xdrs, |
|
450 (u_longlong_t *)&vap->va_size)) |
|
451 return (FALSE); |
|
452 if (!NFS4_SIZE_OK(vap->va_size)) { |
|
453 garp->n4g_attrerr = EFBIG; |
|
454 garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR; |
|
455 } else { |
|
456 vap->va_mask |= AT_SIZE; |
|
457 } |
|
458 } |
|
459 if (resbmap & FATTR4_LINK_SUPPORT_MASK) { |
|
460 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) |
|
461 return (FALSE); |
|
462 gesp->n4g_pc4.pc4_link_support = |
|
463 (truefalse ? TRUE : FALSE); |
|
464 } |
|
465 if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) { |
|
466 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) |
|
467 return (FALSE); |
|
468 gesp->n4g_pc4.pc4_symlink_support = |
|
469 (truefalse ? TRUE : FALSE); |
|
470 } |
|
471 if (resbmap & FATTR4_NAMED_ATTR_MASK) { |
|
472 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) |
|
473 return (FALSE); |
|
474 gesp->n4g_pc4.pc4_xattr_exists = TRUE; |
|
475 gesp->n4g_pc4.pc4_xattr_exists = |
|
476 (truefalse ? TRUE : FALSE); |
|
477 } |
|
478 } |
|
479 if (resbmap & |
|
480 (FATTR4_FSID_MASK | |
|
481 FATTR4_UNIQUE_HANDLES_MASK | |
|
482 FATTR4_LEASE_TIME_MASK | |
|
483 FATTR4_RDATTR_ERROR_MASK)) { |
|
484 |
|
485 if (resbmap & FATTR4_FSID_MASK) { |
|
486 if ((!xdr_u_longlong_t(xdrs, |
|
487 (u_longlong_t *)&garp->n4g_fsid.major)) || |
|
488 (!xdr_u_longlong_t(xdrs, |
|
489 (u_longlong_t *)&garp->n4g_fsid.minor))) |
|
490 return (FALSE); |
|
491 garp->n4g_fsid_valid = 1; |
|
492 } |
|
493 if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) { |
|
494 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) |
|
495 return (FALSE); |
|
496 gesp->n4g_pc4.pc4_unique_handles = |
|
497 (truefalse ? TRUE : FALSE); |
|
498 } |
|
499 if (resbmap & FATTR4_LEASE_TIME_MASK) { |
|
500 if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_leasetime)) |
|
501 return (FALSE); |
|
502 } |
|
503 if (resbmap & FATTR4_RDATTR_ERROR_MASK) { |
|
504 if (!XDR_GETINT32(xdrs, |
|
505 (int *)&gesp->n4g_rdattr_error)) |
|
506 return (FALSE); |
|
507 } |
|
508 } |
|
509 if (resbmap & |
|
510 (FATTR4_ACL_MASK | |
|
511 FATTR4_ACLSUPPORT_MASK | |
|
512 FATTR4_ARCHIVE_MASK | |
|
513 FATTR4_CANSETTIME_MASK)) { |
|
514 |
|
515 if (resbmap & FATTR4_ACL_MASK) { |
|
516 fattr4_acl acl; |
|
517 |
|
518 acl.fattr4_acl_val = NULL; |
|
519 acl.fattr4_acl_len = 0; |
|
520 |
|
521 if (!xdr_fattr4_acl(xdrs, &acl)) |
|
522 return (FALSE); |
|
523 |
|
524 vsap->vsa_aclcnt = acl.fattr4_acl_len; |
|
525 vsap->vsa_aclentp = acl.fattr4_acl_val; |
|
526 vsap->vsa_mask = VSA_ACE | VSA_ACECNT; |
|
527 |
|
528 } |
|
529 if (resbmap & FATTR4_ACLSUPPORT_MASK) { |
|
530 if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_aclsupport)) |
|
531 return (FALSE); |
|
532 } |
|
533 if (resbmap & FATTR4_ARCHIVE_MASK) { |
|
534 ASSERT(0); |
|
535 } |
|
536 if (resbmap & FATTR4_CANSETTIME_MASK) { |
|
537 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) |
|
538 return (FALSE); |
|
539 gesp->n4g_pc4.pc4_cansettime = |
|
540 (truefalse ? TRUE : FALSE); |
|
541 } |
|
542 } |
|
543 if (resbmap & |
|
544 (FATTR4_CASE_INSENSITIVE_MASK | |
|
545 FATTR4_CASE_PRESERVING_MASK | |
|
546 FATTR4_CHOWN_RESTRICTED_MASK | |
|
547 FATTR4_FILEHANDLE_MASK | |
|
548 FATTR4_FILEID_MASK | |
|
549 FATTR4_FILES_AVAIL_MASK | |
|
550 FATTR4_FILES_FREE_MASK | |
|
551 FATTR4_FILES_TOTAL_MASK)) { |
|
552 |
|
553 if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) { |
|
554 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) |
|
555 return (FALSE); |
|
556 gesp->n4g_pc4.pc4_case_insensitive = |
|
557 (truefalse ? TRUE : FALSE); |
|
558 } |
|
559 if (resbmap & FATTR4_CASE_PRESERVING_MASK) { |
|
560 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) |
|
561 return (FALSE); |
|
562 gesp->n4g_pc4.pc4_case_preserving = |
|
563 (truefalse ? TRUE : FALSE); |
|
564 } |
|
565 if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) { |
|
566 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) |
|
567 return (FALSE); |
|
568 gesp->n4g_pc4.pc4_chown_restricted = |
|
569 (truefalse ? TRUE : FALSE); |
|
570 } |
|
571 if (resbmap & FATTR4_FILEHANDLE_MASK) { |
|
572 gesp->n4g_fh_u.nfs_fh4_alt.len = 0; |
|
573 gesp->n4g_fh_u.nfs_fh4_alt.val = |
|
574 gesp->n4g_fh_u.nfs_fh4_alt.data; |
|
575 if (!xdr_bytes(xdrs, |
|
576 (char **)&gesp->n4g_fh_u.n4g_fh.nfs_fh4_val, |
|
577 (uint_t *)&gesp->n4g_fh_u.n4g_fh.nfs_fh4_len, |
|
578 NFS4_FHSIZE)) |
|
579 return (FALSE); |
|
580 } |
|
581 if (resbmap & FATTR4_FILEID_MASK) { |
|
582 if (!xdr_u_longlong_t(xdrs, |
|
583 (u_longlong_t *)&vap->va_nodeid)) |
|
584 return (FALSE); |
|
585 vap->va_mask |= AT_NODEID; |
|
586 } |
|
587 if (resbmap & FATTR4_FILES_AVAIL_MASK) { |
|
588 if (!xdr_u_longlong_t(xdrs, |
|
589 (u_longlong_t *)&gesp->n4g_sb.f_favail)) |
|
590 return (FALSE); |
|
591 } |
|
592 if (resbmap & FATTR4_FILES_FREE_MASK) { |
|
593 if (!xdr_u_longlong_t(xdrs, |
|
594 (u_longlong_t *)&gesp->n4g_sb.f_ffree)) |
|
595 return (FALSE); |
|
596 } |
|
597 if (resbmap & FATTR4_FILES_TOTAL_MASK) { |
|
598 if (!xdr_u_longlong_t(xdrs, |
|
599 (u_longlong_t *)&gesp->n4g_sb.f_files)) |
|
600 return (FALSE); |
|
601 } |
|
602 } |
|
603 if (resbmap & |
|
604 (FATTR4_FS_LOCATIONS_MASK | |
|
605 FATTR4_HIDDEN_MASK | |
|
606 FATTR4_HOMOGENEOUS_MASK)) { |
|
607 |
|
608 if (resbmap & FATTR4_FS_LOCATIONS_MASK) { |
|
609 ASSERT(0); |
|
610 } |
|
611 if (resbmap & FATTR4_HIDDEN_MASK) { |
|
612 ASSERT(0); |
|
613 } |
|
614 if (resbmap & FATTR4_HOMOGENEOUS_MASK) { |
|
615 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) |
|
616 return (FALSE); |
|
617 gesp->n4g_pc4.pc4_homogeneous = |
|
618 (truefalse ? TRUE : FALSE); |
|
619 } |
|
620 } |
|
621 if (resbmap & |
|
622 (FATTR4_MAXFILESIZE_MASK | |
|
623 FATTR4_MAXLINK_MASK | |
|
624 FATTR4_MAXNAME_MASK | |
|
625 FATTR4_MAXREAD_MASK | |
|
626 FATTR4_MAXWRITE_MASK)) { |
|
627 |
|
628 if (resbmap & FATTR4_MAXFILESIZE_MASK) { |
|
629 if (!xdr_u_longlong_t(xdrs, |
|
630 (u_longlong_t *)&gesp->n4g_maxfilesize)) |
|
631 return (FALSE); |
|
632 } |
|
633 if (resbmap & FATTR4_MAXLINK_MASK) { |
|
634 if (!XDR_GETINT32(xdrs, |
|
635 (int *)&gesp->n4g_pc4.pc4_link_max)) |
|
636 return (FALSE); |
|
637 } |
|
638 if (resbmap & FATTR4_MAXNAME_MASK) { |
|
639 if (!XDR_GETINT32(xdrs, |
|
640 (int *)&gesp->n4g_pc4.pc4_name_max)) |
|
641 return (FALSE); |
|
642 gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max; |
|
643 } |
|
644 if (resbmap & FATTR4_MAXREAD_MASK) { |
|
645 if (!xdr_u_longlong_t(xdrs, |
|
646 (u_longlong_t *)&gesp->n4g_maxread)) |
|
647 return (FALSE); |
|
648 } |
|
649 if (resbmap & FATTR4_MAXWRITE_MASK) { |
|
650 if (!xdr_u_longlong_t(xdrs, |
|
651 (u_longlong_t *)&gesp->n4g_maxwrite)) |
|
652 return (FALSE); |
|
653 } |
|
654 } |
|
655 if (resbmap & |
|
656 (FATTR4_MIMETYPE_MASK | |
|
657 FATTR4_MODE_MASK | |
|
658 FATTR4_NO_TRUNC_MASK | |
|
659 FATTR4_NUMLINKS_MASK)) { |
|
660 |
|
661 if (resbmap & FATTR4_MIMETYPE_MASK) { |
|
662 ASSERT(0); |
|
663 } |
|
664 if (resbmap & FATTR4_MODE_MASK) { |
|
665 if (!XDR_GETINT32(xdrs, (int *)&vap->va_mode)) |
|
666 return (FALSE); |
|
667 vap->va_mask |= AT_MODE; |
|
668 } |
|
669 if (resbmap & FATTR4_NO_TRUNC_MASK) { |
|
670 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) |
|
671 return (FALSE); |
|
672 gesp->n4g_pc4.pc4_no_trunc = |
|
673 (truefalse ? TRUE : FALSE); |
|
674 } |
|
675 if (resbmap & FATTR4_NUMLINKS_MASK) { |
|
676 if (!XDR_GETINT32(xdrs, (int *)&vap->va_nlink)) |
|
677 return (FALSE); |
|
678 vap->va_mask |= AT_NLINK; |
|
679 } |
|
680 } |
|
681 if (resbmap & |
|
682 (FATTR4_OWNER_MASK | |
|
683 FATTR4_OWNER_GROUP_MASK | |
|
684 FATTR4_QUOTA_AVAIL_HARD_MASK | |
|
685 FATTR4_QUOTA_AVAIL_SOFT_MASK)) { |
|
686 |
|
687 if (resbmap & FATTR4_OWNER_MASK) { |
|
688 uint_t *owner_length, ol; |
|
689 char *owner_val = NULL; |
|
690 char *owner_alloc = NULL; |
|
691 utf8string ov; |
|
692 int error; |
|
693 |
|
694 /* get the OWNER_LENGTH */ |
|
695 if (!xdr_u_int(xdrs, &ol)) |
|
696 return (FALSE); |
|
697 |
|
698 /* Manage the owner length location */ |
|
699 if (pug && ol <= MAX_OG_NAME) { |
|
700 owner_length = &pug->u_curr.utf8string_len; |
|
701 *owner_length = ol; |
|
702 } else { |
|
703 owner_length = &ol; |
|
704 } |
|
705 |
|
706 /* find memory to store the decode */ |
|
707 if (*owner_length > MAX_OG_NAME || pug == NULL) |
|
708 owner_val = owner_alloc = |
|
709 kmem_alloc(*owner_length, KM_SLEEP); |
|
710 else |
|
711 owner_val = pug->u_curr.utf8string_val; |
|
712 |
|
713 /* get the OWNER string */ |
|
714 if (!xdr_opaque(xdrs, owner_val, *owner_length)) { |
|
715 if (owner_alloc) |
|
716 kmem_free(owner_alloc, *owner_length); |
|
717 return (FALSE); |
|
718 } |
|
719 |
|
720 /* Optimize for matching if called for */ |
|
721 if (pug && |
|
722 *owner_length == pug->u_last.utf8string_len && |
|
723 bcmp(owner_val, pug->u_last.utf8string_val, |
|
724 *owner_length) == 0) { |
|
725 vap->va_uid = pug->uid; |
|
726 vap->va_mask |= AT_UID; |
|
727 } else { |
|
728 uid_t uid; |
|
729 |
|
730 ov.utf8string_len = *owner_length; |
|
731 ov.utf8string_val = owner_val; |
|
732 error = nfs_idmap_str_uid(&ov, &uid, FALSE); |
|
733 /* |
|
734 * String was mapped, but to nobody because |
|
735 * we are nfsmapid, indicate it should not |
|
736 * be cached. |
|
737 */ |
|
738 if (error == ENOTSUP) { |
|
739 error = 0; |
|
740 garp->n4g_attrwhy = |
|
741 NFS4_GETATTR_NOCACHE_OK; |
|
742 } |
|
743 |
|
744 if (error) { |
|
745 garp->n4g_attrerr = error; |
|
746 garp->n4g_attrwhy = |
|
747 NFS4_GETATTR_ATUID_ERR; |
|
748 } else { |
|
749 vap->va_uid = uid; |
|
750 vap->va_mask |= AT_UID; |
|
751 if (pug && ol <= MAX_OG_NAME) { |
|
752 pug->uid = uid; |
|
753 U_SWAP_CURR_LAST(pug); |
|
754 } |
|
755 } |
|
756 if (owner_alloc) |
|
757 kmem_free(owner_alloc, *owner_length); |
|
758 } |
|
759 } |
|
760 if (resbmap & FATTR4_OWNER_GROUP_MASK) { |
|
761 uint_t *group_length, gl; |
|
762 char *group_val = NULL; |
|
763 char *group_alloc = NULL; |
|
764 utf8string gv; |
|
765 int error; |
|
766 |
|
767 /* get the OWNER_GROUP_LENGTH */ |
|
768 if (!xdr_u_int(xdrs, &gl)) |
|
769 return (FALSE); |
|
770 |
|
771 /* Manage the group length location */ |
|
772 if (pug && gl <= MAX_OG_NAME) { |
|
773 group_length = &pug->g_curr.utf8string_len; |
|
774 *group_length = gl; |
|
775 } else { |
|
776 group_length = ≷ |
|
777 } |
|
778 |
|
779 /* find memory to store the decode */ |
|
780 if (*group_length > MAX_OG_NAME || pug == NULL) |
|
781 group_val = group_alloc = |
|
782 kmem_alloc(*group_length, KM_SLEEP); |
|
783 else |
|
784 group_val = pug->g_curr.utf8string_val; |
|
785 |
|
786 /* get the OWNER_GROUP string */ |
|
787 if (!xdr_opaque(xdrs, group_val, *group_length)) { |
|
788 if (group_alloc) |
|
789 kmem_free(group_alloc, *group_length); |
|
790 return (FALSE); |
|
791 } |
|
792 |
|
793 /* Optimize for matching if called for */ |
|
794 if (pug && |
|
795 *group_length == pug->g_last.utf8string_len && |
|
796 bcmp(group_val, pug->g_last.utf8string_val, |
|
797 *group_length) == 0) { |
|
798 vap->va_gid = pug->gid; |
|
799 vap->va_mask |= AT_GID; |
|
800 } else { |
|
801 uid_t gid; |
|
802 |
|
803 gv.utf8string_len = *group_length; |
|
804 gv.utf8string_val = group_val; |
|
805 error = nfs_idmap_str_gid(&gv, &gid, FALSE); |
|
806 /* |
|
807 * String was mapped, but to nobody because |
|
808 * we are nfsmapid, indicate it should not |
|
809 * be cached. |
|
810 */ |
|
811 if (error == ENOTSUP) { |
|
812 error = 0; |
|
813 garp->n4g_attrwhy = |
|
814 NFS4_GETATTR_NOCACHE_OK; |
|
815 } |
|
816 |
|
817 if (error) { |
|
818 garp->n4g_attrerr = error; |
|
819 garp->n4g_attrwhy = |
|
820 NFS4_GETATTR_ATGID_ERR; |
|
821 } else { |
|
822 vap->va_gid = gid; |
|
823 vap->va_mask |= AT_GID; |
|
824 if (pug && gl <= MAX_OG_NAME) { |
|
825 pug->gid = gid; |
|
826 G_SWAP_CURR_LAST(pug); |
|
827 } |
|
828 } |
|
829 if (group_alloc) { |
|
830 kmem_free(group_alloc, *group_length); |
|
831 } |
|
832 } |
|
833 } |
|
834 if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) { |
|
835 ASSERT(0); |
|
836 } |
|
837 if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) { |
|
838 ASSERT(0); |
|
839 } |
|
840 } |
|
841 if (resbmap & |
|
842 (FATTR4_QUOTA_USED_MASK | |
|
843 FATTR4_SPACE_AVAIL_MASK | |
|
844 FATTR4_SPACE_FREE_MASK | |
|
845 FATTR4_SPACE_TOTAL_MASK | |
|
846 FATTR4_SPACE_USED_MASK | |
|
847 FATTR4_SYSTEM_MASK)) { |
|
848 |
|
849 if (resbmap & FATTR4_QUOTA_USED_MASK) { |
|
850 ASSERT(0); |
|
851 } |
|
852 if (resbmap & FATTR4_RAWDEV_MASK) { |
|
853 fattr4_rawdev rawdev; |
|
854 if (!xdr_fattr4_rawdev(xdrs, &rawdev)) |
|
855 return (FALSE); |
|
856 |
|
857 if (vap->va_type == VCHR || vap->va_type == VBLK) { |
|
858 vap->va_rdev = makedevice(rawdev.specdata1, |
|
859 rawdev.specdata2); |
|
860 } else { |
|
861 vap->va_rdev = 0; |
|
862 } |
|
863 vap->va_mask |= AT_RDEV; |
|
864 } |
|
865 if (resbmap & FATTR4_SPACE_AVAIL_MASK) { |
|
866 if (!xdr_u_longlong_t(xdrs, |
|
867 (u_longlong_t *)&gesp->n4g_sb.f_bavail)) |
|
868 return (FALSE); |
|
869 gesp->n4g_sb.f_bavail /= DEV_BSIZE; |
|
870 } |
|
871 if (resbmap & FATTR4_SPACE_FREE_MASK) { |
|
872 if (!xdr_u_longlong_t(xdrs, |
|
873 (u_longlong_t *)&gesp->n4g_sb.f_bfree)) |
|
874 return (FALSE); |
|
875 gesp->n4g_sb.f_bfree /= DEV_BSIZE; |
|
876 } |
|
877 if (resbmap & FATTR4_SPACE_TOTAL_MASK) { |
|
878 if (!xdr_u_longlong_t(xdrs, |
|
879 (u_longlong_t *)&gesp->n4g_sb.f_blocks)) |
|
880 return (FALSE); |
|
881 gesp->n4g_sb.f_blocks /= DEV_BSIZE; |
|
882 } |
|
883 if (resbmap & FATTR4_SPACE_USED_MASK) { |
|
884 uint64_t space_used; |
|
885 if (!xdr_u_longlong_t(xdrs, |
|
886 (u_longlong_t *)&space_used)) |
|
887 return (FALSE); |
|
888 |
|
889 /* Compute space depending on device type */ |
|
890 ASSERT((vap->va_mask & AT_TYPE)); |
|
891 if (vap->va_type == VREG || vap->va_type == VDIR || |
|
892 vap->va_type == VLNK) { |
|
893 vap->va_nblocks = (u_longlong_t) |
|
894 ((space_used + (offset4)DEV_BSIZE - |
|
895 (offset4)1) / (offset4)DEV_BSIZE); |
|
896 } else { |
|
897 vap->va_nblocks = 0; |
|
898 } |
|
899 vap->va_mask |= AT_NBLOCKS; |
|
900 } |
|
901 if (resbmap & FATTR4_SYSTEM_MASK) { |
|
902 ASSERT(0); |
|
903 } |
|
904 } |
|
905 if (resbmap & |
|
906 (FATTR4_TIME_ACCESS_MASK | |
|
907 FATTR4_TIME_ACCESS_SET_MASK | |
|
908 FATTR4_TIME_BACKUP_MASK | |
|
909 FATTR4_TIME_CREATE_MASK | |
|
910 FATTR4_TIME_DELTA_MASK | |
|
911 FATTR4_TIME_METADATA_MASK | |
|
912 FATTR4_TIME_MODIFY_MASK | |
|
913 FATTR4_TIME_MODIFY_SET_MASK | |
|
914 FATTR4_MOUNTED_ON_FILEID_MASK)) { |
|
915 |
|
916 if (resbmap & FATTR4_TIME_ACCESS_MASK) { |
|
917 nfstime4 atime; |
|
918 int error; |
|
919 |
|
920 if (!xdr_longlong_t(xdrs, |
|
921 (longlong_t *)&atime.seconds)) |
|
922 return (FALSE); |
|
923 if (!XDR_GETINT32(xdrs, (int *)&atime.nseconds)) |
|
924 return (FALSE); |
|
925 error = nfs4_time_ntov(&atime, &vap->va_atime); |
|
926 if (error) { |
|
927 garp->n4g_attrerr = error; |
|
928 garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR; |
|
929 } |
|
930 vap->va_mask |= AT_ATIME; |
|
931 } |
|
932 if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) { |
|
933 ASSERT(0); |
|
934 } |
|
935 if (resbmap & FATTR4_TIME_BACKUP_MASK) { |
|
936 ASSERT(0); |
|
937 } |
|
938 if (resbmap & FATTR4_TIME_CREATE_MASK) { |
|
939 ASSERT(0); |
|
940 } |
|
941 if (resbmap & FATTR4_TIME_DELTA_MASK) { |
|
942 if ((!xdr_u_longlong_t(xdrs, |
|
943 (u_longlong_t *)&gesp->n4g_delta.seconds)) || |
|
944 (!xdr_u_int(xdrs, &gesp->n4g_delta.nseconds))) |
|
945 return (FALSE); |
|
946 } |
|
947 if (resbmap & FATTR4_TIME_METADATA_MASK) { |
|
948 nfstime4 mdt; |
|
949 int error; |
|
950 |
|
951 if (!xdr_longlong_t(xdrs, (longlong_t *)&mdt.seconds)) |
|
952 return (FALSE); |
|
953 if (!XDR_GETINT32(xdrs, (int32_t *)&mdt.nseconds)) |
|
954 return (FALSE); |
|
955 error = nfs4_time_ntov(&mdt, &vap->va_ctime); |
|
956 if (error) { |
|
957 garp->n4g_attrerr = error; |
|
958 garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR; |
|
959 } |
|
960 vap->va_mask |= AT_CTIME; |
|
961 } |
|
962 if (resbmap & FATTR4_TIME_MODIFY_MASK) { |
|
963 nfstime4 mtime; |
|
964 int error; |
|
965 |
|
966 if (!xdr_longlong_t(xdrs, |
|
967 (longlong_t *)&mtime.seconds)) |
|
968 return (FALSE); |
|
969 if (!XDR_GETINT32(xdrs, (int32_t *)&mtime.nseconds)) |
|
970 return (FALSE); |
|
971 error = nfs4_time_ntov(&mtime, &vap->va_mtime); |
|
972 if (error) { |
|
973 garp->n4g_attrerr = error; |
|
974 garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR; |
|
975 } |
|
976 vap->va_mask |= AT_MTIME; |
|
977 } |
|
978 if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) { |
|
979 ASSERT(0); |
|
980 } |
|
981 if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) { |
|
982 if (!xdr_u_longlong_t(xdrs, |
|
983 (u_longlong_t *)&garp->n4g_mon_fid)) |
|
984 return (FALSE); |
|
985 garp->n4g_mon_fid_valid = 1; |
|
986 } |
|
987 } |
|
988 |
|
989 if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) { |
|
990 /* copy only if not provided */ |
|
991 if (garp->n4g_ext_res == NULL) { |
|
992 garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP); |
|
993 bcopy(&ges, garp->n4g_ext_res, sizeof (ges)); |
|
994 } |
|
995 } |
|
996 |
|
997 return (TRUE); |
|
998 } |
|
999 |
|
1000 /* |
|
1001 * Inlined version of get_bitmap4 processing |
|
1002 */ |
|
1003 bitmap4 |
|
1004 xdr_get_bitmap4_inline(uint32_t **iptr) |
|
1005 { |
|
1006 uint32_t resbmaplen; |
|
1007 bitmap4 bm; |
|
1008 uint32_t *ptr = *iptr; |
|
1009 |
|
1010 /* bitmap LENGTH */ |
|
1011 resbmaplen = IXDR_GET_U_INT32(ptr); |
|
1012 |
|
1013 /* Inline the bitmap and attrlen for common case of two word map */ |
|
1014 if (resbmaplen == 2) { |
|
1015 IXDR_GET_HYPER(ptr, bm); |
|
1016 *iptr = ptr; |
|
1017 return (bm); |
|
1018 } |
|
1019 |
|
1020 #if defined(_LITTLE_ENDIAN) |
|
1021 bm = IXDR_GET_U_INT32(ptr); |
|
1022 if (--resbmaplen == 0) { |
|
1023 *iptr = ptr; |
|
1024 return (bm); |
|
1025 } |
|
1026 *((uint32_t *)&bm) |= IXDR_GET_U_INT32(ptr); |
|
1027 if (--resbmaplen == 0) { |
|
1028 *iptr = ptr; |
|
1029 return (bm); |
|
1030 } |
|
1031 ptr += resbmaplen; |
|
1032 *iptr = ptr; |
|
1033 return (bm); |
|
1034 #elif defined(_BIG_ENDIAN) |
|
1035 *((uint32_t *)&bm) = IXDR_GET_U_INT32(ptr); |
|
1036 if (--resbmaplen == 0) { |
|
1037 *iptr = ptr; |
|
1038 return (bm); |
|
1039 } |
|
1040 bm |= IXDR_GET_U_INT32(ptr); |
|
1041 if (--resbmaplen == 0) { |
|
1042 *iptr = ptr; |
|
1043 return (bm); |
|
1044 } |
|
1045 ptr += resbmaplen; |
|
1046 *iptr = ptr; |
|
1047 return (bm); |
|
1048 #else |
|
1049 ASSERT(0); |
|
1050 ptr += resbmaplen; |
|
1051 *iptr = ptr; |
|
1052 return (0); |
|
1053 #endif |
|
1054 } |
|
1055 |
|
1056 static bool_t |
|
1057 xdr_ga_fattr_res_inline(uint32_t *ptr, struct nfs4_ga_res *garp, |
|
1058 bitmap4 resbmap, bitmap4 argbmap, struct mntinfo4 *mi, |
|
1059 ug_cache_t *pug) |
|
1060 { |
|
1061 int truefalse; |
|
1062 struct nfs4_ga_ext_res ges, *gesp; |
|
1063 vattr_t *vap = &garp->n4g_va; |
|
1064 |
|
1065 if (garp->n4g_ext_res) |
|
1066 gesp = garp->n4g_ext_res; |
|
1067 else |
|
1068 gesp = ⩾ |
|
1069 |
|
1070 vap->va_mask = 0; |
|
1071 |
|
1072 /* Check to see if the vattr should be pre-filled */ |
|
1073 if (argbmap & NFS4_VATTR_MASK) |
|
1074 xdr_ga_prefill_vattr(garp, mi); |
|
1075 |
|
1076 if (argbmap & NFS4_STATFS_ATTR_MASK) |
|
1077 xdr_ga_prefill_statvfs(gesp, mi); |
|
1078 |
|
1079 if (resbmap & |
|
1080 (FATTR4_SUPPORTED_ATTRS_MASK | |
|
1081 FATTR4_TYPE_MASK | |
|
1082 FATTR4_FH_EXPIRE_TYPE_MASK | |
|
1083 FATTR4_CHANGE_MASK | |
|
1084 FATTR4_SIZE_MASK | |
|
1085 FATTR4_LINK_SUPPORT_MASK | |
|
1086 FATTR4_SYMLINK_SUPPORT_MASK | |
|
1087 FATTR4_NAMED_ATTR_MASK)) { |
|
1088 |
|
1089 if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) { |
|
1090 gesp->n4g_suppattrs = xdr_get_bitmap4_inline(&ptr); |
|
1091 } |
|
1092 if (resbmap & FATTR4_TYPE_MASK) { |
|
1093 vap->va_type = IXDR_GET_U_INT32(ptr); |
|
1094 |
|
1095 if (vap->va_type < NF4REG || |
|
1096 vap->va_type > NF4NAMEDATTR) |
|
1097 vap->va_type = VBAD; |
|
1098 else |
|
1099 vap->va_type = nf4_to_vt[vap->va_type]; |
|
1100 if (vap->va_type == VBLK) |
|
1101 vap->va_blksize = DEV_BSIZE; |
|
1102 |
|
1103 vap->va_mask |= AT_TYPE; |
|
1104 } |
|
1105 if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) { |
|
1106 gesp->n4g_fet = IXDR_GET_U_INT32(ptr); |
|
1107 } |
|
1108 if (resbmap & FATTR4_CHANGE_MASK) { |
|
1109 IXDR_GET_U_HYPER(ptr, garp->n4g_change); |
|
1110 garp->n4g_change_valid = 1; |
|
1111 } |
|
1112 if (resbmap & FATTR4_SIZE_MASK) { |
|
1113 IXDR_GET_U_HYPER(ptr, vap->va_size); |
|
1114 |
|
1115 if (!NFS4_SIZE_OK(vap->va_size)) { |
|
1116 garp->n4g_attrerr = EFBIG; |
|
1117 garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR; |
|
1118 } else { |
|
1119 vap->va_mask |= AT_SIZE; |
|
1120 } |
|
1121 } |
|
1122 if (resbmap & FATTR4_LINK_SUPPORT_MASK) { |
|
1123 truefalse = IXDR_GET_U_INT32(ptr); |
|
1124 gesp->n4g_pc4.pc4_link_support = |
|
1125 (truefalse ? TRUE : FALSE); |
|
1126 } |
|
1127 if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) { |
|
1128 truefalse = IXDR_GET_U_INT32(ptr); |
|
1129 gesp->n4g_pc4.pc4_symlink_support = |
|
1130 (truefalse ? TRUE : FALSE); |
|
1131 } |
|
1132 if (resbmap & FATTR4_NAMED_ATTR_MASK) { |
|
1133 truefalse = IXDR_GET_U_INT32(ptr); |
|
1134 gesp->n4g_pc4.pc4_xattr_exists = TRUE; |
|
1135 gesp->n4g_pc4.pc4_xattr_exists = |
|
1136 (truefalse ? TRUE : FALSE); |
|
1137 } |
|
1138 } |
|
1139 if (resbmap & |
|
1140 (FATTR4_FSID_MASK | |
|
1141 FATTR4_UNIQUE_HANDLES_MASK | |
|
1142 FATTR4_LEASE_TIME_MASK | |
|
1143 FATTR4_RDATTR_ERROR_MASK)) { |
|
1144 |
|
1145 if (resbmap & FATTR4_FSID_MASK) { |
|
1146 IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.major); |
|
1147 IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.minor); |
|
1148 garp->n4g_fsid_valid = 1; |
|
1149 } |
|
1150 if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) { |
|
1151 truefalse = IXDR_GET_U_INT32(ptr); |
|
1152 gesp->n4g_pc4.pc4_unique_handles = |
|
1153 (truefalse ? TRUE : FALSE); |
|
1154 } |
|
1155 if (resbmap & FATTR4_LEASE_TIME_MASK) { |
|
1156 gesp->n4g_leasetime = IXDR_GET_U_INT32(ptr); |
|
1157 } |
|
1158 if (resbmap & FATTR4_RDATTR_ERROR_MASK) { |
|
1159 gesp->n4g_rdattr_error = IXDR_GET_U_INT32(ptr); |
|
1160 } |
|
1161 } |
|
1162 if (resbmap & |
|
1163 (FATTR4_ACL_MASK | |
|
1164 FATTR4_ACLSUPPORT_MASK | |
|
1165 FATTR4_ARCHIVE_MASK | |
|
1166 FATTR4_CANSETTIME_MASK)) { |
|
1167 |
|
1168 if (resbmap & FATTR4_ACL_MASK) { |
|
1169 ASSERT(0); |
|
1170 } |
|
1171 if (resbmap & FATTR4_ACLSUPPORT_MASK) { |
|
1172 gesp->n4g_aclsupport = IXDR_GET_U_INT32(ptr); |
|
1173 } |
|
1174 if (resbmap & FATTR4_ARCHIVE_MASK) { |
|
1175 ASSERT(0); |
|
1176 } |
|
1177 if (resbmap & FATTR4_CANSETTIME_MASK) { |
|
1178 truefalse = IXDR_GET_U_INT32(ptr); |
|
1179 gesp->n4g_pc4.pc4_cansettime = |
|
1180 (truefalse ? TRUE : FALSE); |
|
1181 } |
|
1182 } |
|
1183 if (resbmap & |
|
1184 (FATTR4_CASE_INSENSITIVE_MASK | |
|
1185 FATTR4_CASE_PRESERVING_MASK | |
|
1186 FATTR4_CHOWN_RESTRICTED_MASK | |
|
1187 FATTR4_FILEHANDLE_MASK | |
|
1188 FATTR4_FILEID_MASK | |
|
1189 FATTR4_FILES_AVAIL_MASK | |
|
1190 FATTR4_FILES_FREE_MASK | |
|
1191 FATTR4_FILES_TOTAL_MASK)) { |
|
1192 |
|
1193 if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) { |
|
1194 truefalse = IXDR_GET_U_INT32(ptr); |
|
1195 gesp->n4g_pc4.pc4_case_insensitive = |
|
1196 (truefalse ? TRUE : FALSE); |
|
1197 } |
|
1198 if (resbmap & FATTR4_CASE_PRESERVING_MASK) { |
|
1199 truefalse = IXDR_GET_U_INT32(ptr); |
|
1200 gesp->n4g_pc4.pc4_case_preserving = |
|
1201 (truefalse ? TRUE : FALSE); |
|
1202 } |
|
1203 if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) { |
|
1204 truefalse = IXDR_GET_U_INT32(ptr); |
|
1205 gesp->n4g_pc4.pc4_chown_restricted = |
|
1206 (truefalse ? TRUE : FALSE); |
|
1207 } |
|
1208 if (resbmap & FATTR4_FILEHANDLE_MASK) { |
|
1209 int len = IXDR_GET_U_INT32(ptr); |
|
1210 |
|
1211 gesp->n4g_fh_u.nfs_fh4_alt.len = 0; |
|
1212 gesp->n4g_fh_u.nfs_fh4_alt.val = |
|
1213 gesp->n4g_fh_u.nfs_fh4_alt.data; |
|
1214 gesp->n4g_fh_u.n4g_fh.nfs_fh4_len = len; |
|
1215 |
|
1216 bcopy(ptr, gesp->n4g_fh_u.n4g_fh.nfs_fh4_val, len); |
|
1217 |
|
1218 ptr += RNDUP(len) / BYTES_PER_XDR_UNIT; |
|
1219 } |
|
1220 if (resbmap & FATTR4_FILEID_MASK) { |
|
1221 IXDR_GET_U_HYPER(ptr, vap->va_nodeid); |
|
1222 vap->va_mask |= AT_NODEID; |
|
1223 } |
|
1224 if (resbmap & FATTR4_FILES_AVAIL_MASK) { |
|
1225 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_favail); |
|
1226 } |
|
1227 if (resbmap & FATTR4_FILES_FREE_MASK) { |
|
1228 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_ffree); |
|
1229 } |
|
1230 if (resbmap & FATTR4_FILES_TOTAL_MASK) { |
|
1231 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_files); |
|
1232 } |
|
1233 } |
|
1234 if (resbmap & |
|
1235 (FATTR4_FS_LOCATIONS_MASK | |
|
1236 FATTR4_HIDDEN_MASK | |
|
1237 FATTR4_HOMOGENEOUS_MASK)) { |
|
1238 |
|
1239 if (resbmap & FATTR4_FS_LOCATIONS_MASK) { |
|
1240 ASSERT(0); |
|
1241 } |
|
1242 if (resbmap & FATTR4_HIDDEN_MASK) { |
|
1243 ASSERT(0); |
|
1244 } |
|
1245 if (resbmap & FATTR4_HOMOGENEOUS_MASK) { |
|
1246 truefalse = IXDR_GET_U_INT32(ptr); |
|
1247 gesp->n4g_pc4.pc4_homogeneous = |
|
1248 (truefalse ? TRUE : FALSE); |
|
1249 } |
|
1250 } |
|
1251 if (resbmap & |
|
1252 (FATTR4_MAXFILESIZE_MASK | |
|
1253 FATTR4_MAXLINK_MASK | |
|
1254 FATTR4_MAXNAME_MASK | |
|
1255 FATTR4_MAXREAD_MASK | |
|
1256 FATTR4_MAXWRITE_MASK)) { |
|
1257 |
|
1258 if (resbmap & FATTR4_MAXFILESIZE_MASK) { |
|
1259 IXDR_GET_U_HYPER(ptr, gesp->n4g_maxfilesize); |
|
1260 } |
|
1261 if (resbmap & FATTR4_MAXLINK_MASK) { |
|
1262 gesp->n4g_pc4.pc4_link_max = IXDR_GET_U_INT32(ptr); |
|
1263 } |
|
1264 if (resbmap & FATTR4_MAXNAME_MASK) { |
|
1265 gesp->n4g_pc4.pc4_name_max = IXDR_GET_U_INT32(ptr); |
|
1266 gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max; |
|
1267 } |
|
1268 if (resbmap & FATTR4_MAXREAD_MASK) { |
|
1269 IXDR_GET_U_HYPER(ptr, gesp->n4g_maxread); |
|
1270 } |
|
1271 if (resbmap & FATTR4_MAXWRITE_MASK) { |
|
1272 IXDR_GET_U_HYPER(ptr, gesp->n4g_maxwrite); |
|
1273 } |
|
1274 } |
|
1275 if (resbmap & |
|
1276 (FATTR4_MIMETYPE_MASK | |
|
1277 FATTR4_MODE_MASK | |
|
1278 FATTR4_NO_TRUNC_MASK | |
|
1279 FATTR4_NUMLINKS_MASK)) { |
|
1280 |
|
1281 if (resbmap & FATTR4_MIMETYPE_MASK) { |
|
1282 ASSERT(0); |
|
1283 } |
|
1284 if (resbmap & FATTR4_MODE_MASK) { |
|
1285 vap->va_mode = IXDR_GET_U_INT32(ptr); |
|
1286 vap->va_mask |= AT_MODE; |
|
1287 } |
|
1288 if (resbmap & FATTR4_NO_TRUNC_MASK) { |
|
1289 truefalse = IXDR_GET_U_INT32(ptr); |
|
1290 gesp->n4g_pc4.pc4_no_trunc = |
|
1291 (truefalse ? TRUE : FALSE); |
|
1292 } |
|
1293 if (resbmap & FATTR4_NUMLINKS_MASK) { |
|
1294 vap->va_nlink = IXDR_GET_U_INT32(ptr); |
|
1295 vap->va_mask |= AT_NLINK; |
|
1296 } |
|
1297 } |
|
1298 if (resbmap & |
|
1299 (FATTR4_OWNER_MASK | |
|
1300 FATTR4_OWNER_GROUP_MASK | |
|
1301 FATTR4_QUOTA_AVAIL_HARD_MASK | |
|
1302 FATTR4_QUOTA_AVAIL_SOFT_MASK)) { |
|
1303 |
|
1304 if (resbmap & FATTR4_OWNER_MASK) { |
|
1305 uint_t *owner_length, ol; |
|
1306 char *owner_val = NULL; |
|
1307 utf8string ov; |
|
1308 int error; |
|
1309 |
|
1310 /* get the OWNER_LENGTH */ |
|
1311 ol = IXDR_GET_U_INT32(ptr); |
|
1312 |
|
1313 /* Manage the owner length location */ |
|
1314 if (pug && ol <= MAX_OG_NAME) { |
|
1315 owner_length = &pug->u_curr.utf8string_len; |
|
1316 *owner_length = ol; |
|
1317 } else { |
|
1318 owner_length = &ol; |
|
1319 } |
|
1320 |
|
1321 /* find memory to store the decode */ |
|
1322 if (*owner_length > MAX_OG_NAME || pug == NULL) |
|
1323 owner_val = (char *)ptr; |
|
1324 else |
|
1325 owner_val = (char *)ptr; |
|
1326 |
|
1327 /* Optimize for matching if called for */ |
|
1328 if (pug && |
|
1329 *owner_length == pug->u_last.utf8string_len && |
|
1330 bcmp(owner_val, pug->u_last.utf8string_val, |
|
1331 *owner_length) == 0) { |
|
1332 vap->va_uid = pug->uid; |
|
1333 vap->va_mask |= AT_UID; |
|
1334 } else { |
|
1335 uid_t uid; |
|
1336 |
|
1337 ov.utf8string_len = *owner_length; |
|
1338 ov.utf8string_val = owner_val; |
|
1339 error = nfs_idmap_str_uid(&ov, &uid, FALSE); |
|
1340 /* |
|
1341 * String was mapped, but to nobody because |
|
1342 * we are nfsmapid, indicate it should not |
|
1343 * be cached. |
|
1344 */ |
|
1345 if (error == ENOTSUP) { |
|
1346 error = 0; |
|
1347 garp->n4g_attrwhy = |
|
1348 NFS4_GETATTR_NOCACHE_OK; |
|
1349 } |
|
1350 |
|
1351 if (error) { |
|
1352 garp->n4g_attrerr = error; |
|
1353 garp->n4g_attrwhy = |
|
1354 NFS4_GETATTR_ATUID_ERR; |
|
1355 } else { |
|
1356 vap->va_uid = uid; |
|
1357 vap->va_mask |= AT_UID; |
|
1358 /* save the results for next time */ |
|
1359 if (pug && ol <= MAX_OG_NAME) { |
|
1360 pug->uid = uid; |
|
1361 pug->u_curr.utf8string_len = |
|
1362 ov.utf8string_len; |
|
1363 bcopy(owner_val, |
|
1364 pug->u_curr.utf8string_val, ol); |
|
1365 U_SWAP_CURR_LAST(pug); |
|
1366 } |
|
1367 } |
|
1368 } |
|
1369 ptr += RNDUP(ol) / BYTES_PER_XDR_UNIT; |
|
1370 } |
|
1371 if (resbmap & FATTR4_OWNER_GROUP_MASK) { |
|
1372 uint_t *group_length, gl; |
|
1373 char *group_val = NULL; |
|
1374 utf8string gv; |
|
1375 int error; |
|
1376 |
|
1377 /* get the OWNER_GROUP_LENGTH */ |
|
1378 gl = IXDR_GET_U_INT32(ptr); |
|
1379 |
|
1380 /* Manage the group length location */ |
|
1381 if (pug && gl <= MAX_OG_NAME) { |
|
1382 group_length = &pug->g_curr.utf8string_len; |
|
1383 *group_length = gl; |
|
1384 } else { |
|
1385 group_length = ≷ |
|
1386 } |
|
1387 |
|
1388 /* find memory to store the decode */ |
|
1389 if (*group_length > MAX_OG_NAME || pug == NULL) |
|
1390 group_val = (char *)ptr; |
|
1391 else |
|
1392 group_val = (char *)ptr; |
|
1393 |
|
1394 /* Optimize for matching if called for */ |
|
1395 if (pug && |
|
1396 *group_length == pug->g_last.utf8string_len && |
|
1397 bcmp(group_val, pug->g_last.utf8string_val, |
|
1398 *group_length) == 0) { |
|
1399 vap->va_gid = pug->gid; |
|
1400 vap->va_mask |= AT_GID; |
|
1401 } else { |
|
1402 uid_t gid; |
|
1403 |
|
1404 gv.utf8string_len = *group_length; |
|
1405 gv.utf8string_val = group_val; |
|
1406 error = nfs_idmap_str_gid(&gv, &gid, FALSE); |
|
1407 /* |
|
1408 * String was mapped, but to nobody because |
|
1409 * we are nfsmapid, indicate it should not |
|
1410 * be cached. |
|
1411 */ |
|
1412 if (error == ENOTSUP) { |
|
1413 error = 0; |
|
1414 garp->n4g_attrwhy = |
|
1415 NFS4_GETATTR_NOCACHE_OK; |
|
1416 } |
|
1417 |
|
1418 if (error) { |
|
1419 garp->n4g_attrerr = error; |
|
1420 garp->n4g_attrwhy = |
|
1421 NFS4_GETATTR_ATGID_ERR; |
|
1422 } else { |
|
1423 vap->va_gid = gid; |
|
1424 vap->va_mask |= AT_GID; |
|
1425 if (pug && gl <= MAX_OG_NAME) { |
|
1426 pug->gid = gid; |
|
1427 pug->g_curr.utf8string_len = |
|
1428 gv.utf8string_len; |
|
1429 bcopy(group_val, |
|
1430 pug->g_curr.utf8string_val, |
|
1431 gl); |
|
1432 G_SWAP_CURR_LAST(pug); |
|
1433 } |
|
1434 } |
|
1435 } |
|
1436 ptr += RNDUP(gl) / BYTES_PER_XDR_UNIT; |
|
1437 } |
|
1438 if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) { |
|
1439 ASSERT(0); |
|
1440 } |
|
1441 if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) { |
|
1442 ASSERT(0); |
|
1443 } |
|
1444 } |
|
1445 if (resbmap & |
|
1446 (FATTR4_QUOTA_USED_MASK | |
|
1447 FATTR4_SPACE_AVAIL_MASK | |
|
1448 FATTR4_SPACE_FREE_MASK | |
|
1449 FATTR4_SPACE_TOTAL_MASK | |
|
1450 FATTR4_SPACE_USED_MASK | |
|
1451 FATTR4_SYSTEM_MASK)) { |
|
1452 |
|
1453 if (resbmap & FATTR4_QUOTA_USED_MASK) { |
|
1454 ASSERT(0); |
|
1455 } |
|
1456 if (resbmap & FATTR4_RAWDEV_MASK) { |
|
1457 fattr4_rawdev rawdev; |
|
1458 |
|
1459 rawdev.specdata1 = IXDR_GET_U_INT32(ptr); |
|
1460 rawdev.specdata2 = IXDR_GET_U_INT32(ptr); |
|
1461 |
|
1462 if (vap->va_type == VCHR || vap->va_type == VBLK) { |
|
1463 vap->va_rdev = makedevice(rawdev.specdata1, |
|
1464 rawdev.specdata2); |
|
1465 } else { |
|
1466 vap->va_rdev = 0; |
|
1467 } |
|
1468 vap->va_mask |= AT_RDEV; |
|
1469 } |
|
1470 if (resbmap & FATTR4_SPACE_AVAIL_MASK) { |
|
1471 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bavail); |
|
1472 gesp->n4g_sb.f_bavail /= DEV_BSIZE; |
|
1473 } |
|
1474 if (resbmap & FATTR4_SPACE_FREE_MASK) { |
|
1475 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bfree); |
|
1476 gesp->n4g_sb.f_bfree /= DEV_BSIZE; |
|
1477 } |
|
1478 if (resbmap & FATTR4_SPACE_TOTAL_MASK) { |
|
1479 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_blocks); |
|
1480 gesp->n4g_sb.f_blocks /= DEV_BSIZE; |
|
1481 } |
|
1482 if (resbmap & FATTR4_SPACE_USED_MASK) { |
|
1483 uint64_t space_used; |
|
1484 IXDR_GET_U_HYPER(ptr, space_used); |
|
1485 |
|
1486 /* Compute space depending on device type */ |
|
1487 ASSERT((vap->va_mask & AT_TYPE)); |
|
1488 if (vap->va_type == VREG || vap->va_type == VDIR || |
|
1489 vap->va_type == VLNK) { |
|
1490 vap->va_nblocks = (u_longlong_t) |
|
1491 ((space_used + (offset4)DEV_BSIZE - |
|
1492 (offset4)1) / (offset4)DEV_BSIZE); |
|
1493 } else { |
|
1494 vap->va_nblocks = 0; |
|
1495 } |
|
1496 vap->va_mask |= AT_NBLOCKS; |
|
1497 } |
|
1498 if (resbmap & FATTR4_SYSTEM_MASK) { |
|
1499 ASSERT(0); |
|
1500 } |
|
1501 } |
|
1502 if (resbmap & |
|
1503 (FATTR4_TIME_ACCESS_MASK | |
|
1504 FATTR4_TIME_ACCESS_SET_MASK | |
|
1505 FATTR4_TIME_BACKUP_MASK | |
|
1506 FATTR4_TIME_CREATE_MASK | |
|
1507 FATTR4_TIME_DELTA_MASK | |
|
1508 FATTR4_TIME_METADATA_MASK | |
|
1509 FATTR4_TIME_MODIFY_MASK | |
|
1510 FATTR4_TIME_MODIFY_SET_MASK | |
|
1511 FATTR4_MOUNTED_ON_FILEID_MASK)) { |
|
1512 |
|
1513 if (resbmap & FATTR4_TIME_ACCESS_MASK) { |
|
1514 nfstime4 atime; |
|
1515 int error; |
|
1516 |
|
1517 IXDR_GET_U_HYPER(ptr, atime.seconds); |
|
1518 atime.nseconds = IXDR_GET_U_INT32(ptr); |
|
1519 |
|
1520 error = nfs4_time_ntov(&atime, &vap->va_atime); |
|
1521 if (error) { |
|
1522 garp->n4g_attrerr = error; |
|
1523 garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR; |
|
1524 } |
|
1525 vap->va_mask |= AT_ATIME; |
|
1526 } |
|
1527 if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) { |
|
1528 ASSERT(0); |
|
1529 } |
|
1530 if (resbmap & FATTR4_TIME_BACKUP_MASK) { |
|
1531 ASSERT(0); |
|
1532 } |
|
1533 if (resbmap & FATTR4_TIME_CREATE_MASK) { |
|
1534 ASSERT(0); |
|
1535 } |
|
1536 if (resbmap & FATTR4_TIME_DELTA_MASK) { |
|
1537 IXDR_GET_U_HYPER(ptr, gesp->n4g_delta.seconds); |
|
1538 gesp->n4g_delta.nseconds = IXDR_GET_U_INT32(ptr); |
|
1539 } |
|
1540 if (resbmap & FATTR4_TIME_METADATA_MASK) { |
|
1541 nfstime4 mdt; |
|
1542 int error; |
|
1543 |
|
1544 IXDR_GET_U_HYPER(ptr, mdt.seconds); |
|
1545 mdt.nseconds = IXDR_GET_U_INT32(ptr); |
|
1546 |
|
1547 error = nfs4_time_ntov(&mdt, &vap->va_ctime); |
|
1548 if (error) { |
|
1549 garp->n4g_attrerr = error; |
|
1550 garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR; |
|
1551 } |
|
1552 vap->va_mask |= AT_CTIME; |
|
1553 } |
|
1554 if (resbmap & FATTR4_TIME_MODIFY_MASK) { |
|
1555 nfstime4 mtime; |
|
1556 int error; |
|
1557 |
|
1558 IXDR_GET_U_HYPER(ptr, mtime.seconds); |
|
1559 mtime.nseconds = IXDR_GET_U_INT32(ptr); |
|
1560 |
|
1561 error = nfs4_time_ntov(&mtime, &vap->va_mtime); |
|
1562 if (error) { |
|
1563 garp->n4g_attrerr = error; |
|
1564 garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR; |
|
1565 } |
|
1566 vap->va_mask |= AT_MTIME; |
|
1567 } |
|
1568 if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) { |
|
1569 ASSERT(0); |
|
1570 } |
|
1571 if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) { |
|
1572 IXDR_GET_U_HYPER(ptr, garp->n4g_mon_fid); |
|
1573 garp->n4g_mon_fid_valid = 1; |
|
1574 } |
|
1575 } |
|
1576 |
|
1577 /* |
|
1578 * FATTR4_ACL_MASK is not yet supported by this function, but |
|
1579 * we check against it anyway, in case it ever is. |
|
1580 */ |
|
1581 if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) { |
|
1582 /* copy only if not provided */ |
|
1583 if (garp->n4g_ext_res == NULL) { |
|
1584 garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP); |
|
1585 bcopy(&ges, garp->n4g_ext_res, sizeof (ges)); |
|
1586 } |
|
1587 } |
|
1588 |
|
1589 return (TRUE); |
|
1590 } |
|
1591 |
|
1592 |
|
1593 /* |
|
1594 * "." and ".." buffers for filling in on read and readdir |
|
1595 * calls. Intialize the first time and fill in on every |
|
1596 * call to to readdir. |
|
1597 */ |
|
1598 char *nfs4_dot_entries; |
|
1599 char *nfs4_dot_dot_entry; |
|
1600 |
|
1601 /* |
|
1602 * Create the "." or ".." and pad the buffer once so they are |
|
1603 * copied out as required into the user supplied buffer everytime. |
|
1604 * DIRENT64_RECLEN(sizeof (".") - 1) = DIRENT64_RECLEN(1) |
|
1605 * DIRENT64_RECLEN(sizeof ("..") - 1) = DIRENT64_RECLEN(2) |
|
1606 */ |
|
1607 void |
|
1608 nfs4_init_dot_entries() |
|
1609 { |
|
1610 struct dirent64 *odp; |
|
1611 |
|
1612 /* |
|
1613 * zalloc it so it zeros the buffer out. Need |
|
1614 * to just do it once. |
|
1615 */ |
|
1616 nfs4_dot_entries = kmem_zalloc(DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2), |
|
1617 KM_SLEEP); |
|
1618 |
|
1619 odp = (struct dirent64 *)nfs4_dot_entries; |
|
1620 odp->d_off = 1; /* magic cookie for "." entry */ |
|
1621 odp->d_reclen = DIRENT64_RECLEN(1); |
|
1622 odp->d_name[0] = '.'; |
|
1623 odp->d_name[1] = '\0'; |
|
1624 |
|
1625 nfs4_dot_dot_entry = nfs4_dot_entries + DIRENT64_RECLEN(1); |
|
1626 odp = (struct dirent64 *)nfs4_dot_dot_entry; |
|
1627 |
|
1628 odp->d_off = 2; |
|
1629 odp->d_reclen = DIRENT64_RECLEN(2); |
|
1630 odp->d_name[0] = '.'; |
|
1631 odp->d_name[1] = '.'; |
|
1632 odp->d_name[2] = '\0'; |
|
1633 } |
|
1634 |
|
1635 void |
|
1636 nfs4_destroy_dot_entries() |
|
1637 { |
|
1638 if (nfs4_dot_entries) |
|
1639 kmem_free(nfs4_dot_entries, DIRENT64_RECLEN(1) + |
|
1640 DIRENT64_RECLEN(2)); |
|
1641 |
|
1642 nfs4_dot_entries = nfs4_dot_dot_entry = NULL; |
|
1643 } |
|
1644 |
|
1645 bool_t |
|
1646 xdr_READDIR4res_clnt(XDR *xdrs, READDIR4res_clnt *objp, READDIR4args *aobjp) |
|
1647 { |
|
1648 bool_t more_data; |
|
1649 rddir4_cache *rdc = aobjp->rdc; |
|
1650 dirent64_t *dp = NULL; |
|
1651 int entry_length = 0; |
|
1652 int space_left = 0; |
|
1653 bitmap4 resbmap; |
|
1654 uint32_t attrlen; |
|
1655 nfs4_ga_res_t gar; |
|
1656 struct nfs4_ga_ext_res ges; |
|
1657 uint64_t last_cookie = 0; |
|
1658 int skip_to_end; |
|
1659 ug_cache_t *pug = NULL; |
|
1660 |
|
1661 ASSERT(xdrs->x_op == XDR_DECODE); |
|
1662 ASSERT(rdc->entries == NULL); |
|
1663 ASSERT(aobjp->dircount > 0); |
|
1664 |
|
1665 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
1666 return (FALSE); |
|
1667 if (objp->status != NFS4_OK) |
|
1668 return (TRUE); |
|
1669 |
|
1670 gar.n4g_va.va_mask = 0; |
|
1671 gar.n4g_change_valid = 0; |
|
1672 gar.n4g_mon_fid_valid = 0; |
|
1673 gar.n4g_fsid_valid = 0; |
|
1674 gar.n4g_vsa.vsa_mask = 0; |
|
1675 gar.n4g_attrwhy = NFS4_GETATTR_OP_OK; |
|
1676 ges.n4g_pc4.pc4_cache_valid = 0; |
|
1677 ges.n4g_pc4.pc4_xattr_valid = 0; |
|
1678 gar.n4g_ext_res = ⩾ |
|
1679 |
|
1680 /* READDIR4res_clnt_free needs to kmem_free this buffer */ |
|
1681 rdc->entries = kmem_alloc(aobjp->dircount, KM_SLEEP); |
|
1682 |
|
1683 dp = (dirent64_t *)rdc->entries; |
|
1684 rdc->entlen = rdc->buflen = space_left = aobjp->dircount; |
|
1685 |
|
1686 /* Fill in dot and dot-dot if needed */ |
|
1687 if (rdc->nfs4_cookie == (nfs_cookie4) 0 || |
|
1688 rdc->nfs4_cookie == (nfs_cookie4) 1) { |
|
1689 |
|
1690 if (rdc->nfs4_cookie == (nfs_cookie4)0) { |
|
1691 bcopy(nfs4_dot_entries, rdc->entries, |
|
1692 DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2)); |
|
1693 objp->dotp = dp; |
|
1694 dp = (struct dirent64 *)(((char *)dp) + |
|
1695 DIRENT64_RECLEN(1)); |
|
1696 objp->dotdotp = dp; |
|
1697 dp = (struct dirent64 *)(((char *)dp) + |
|
1698 DIRENT64_RECLEN(2)); |
|
1699 space_left -= DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2); |
|
1700 |
|
1701 } else { /* for ".." entry */ |
|
1702 bcopy(nfs4_dot_dot_entry, rdc->entries, |
|
1703 DIRENT64_RECLEN(2)); |
|
1704 objp->dotp = NULL; |
|
1705 objp->dotdotp = dp; |
|
1706 dp = (struct dirent64 *)(((char *)dp) + |
|
1707 DIRENT64_RECLEN(2)); |
|
1708 space_left -= DIRENT64_RECLEN(2); |
|
1709 } |
|
1710 /* Magic NFSv4 number for entry after start */ |
|
1711 last_cookie = 2; |
|
1712 } |
|
1713 |
|
1714 /* Get the cookie VERIFIER */ |
|
1715 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf)) |
|
1716 goto noentries; |
|
1717 |
|
1718 /* Get the do-we-have-a-next-entry BOOL */ |
|
1719 if (!xdr_bool(xdrs, &more_data)) |
|
1720 goto noentries; |
|
1721 |
|
1722 if (aobjp->attr_request & (FATTR4_OWNER_MASK | FATTR4_OWNER_GROUP_MASK)) |
|
1723 pug = alloc_ugcache(); |
|
1724 |
|
1725 skip_to_end = 0; |
|
1726 while (more_data) { |
|
1727 uint_t namelen; |
|
1728 uint64_t cookie; |
|
1729 |
|
1730 /* Get the COOKIE */ |
|
1731 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&cookie)) |
|
1732 goto noentries; |
|
1733 |
|
1734 /* Get the LENGTH of the entry name */ |
|
1735 if (!xdr_u_int(xdrs, &namelen)) |
|
1736 goto noentries; |
|
1737 |
|
1738 if (!skip_to_end) { |
|
1739 /* |
|
1740 * With the length of the directory entry name |
|
1741 * in hand, figure out if there is room left |
|
1742 * to encode it for the requestor. If not, |
|
1743 * that is okay, but the rest of the readdir |
|
1744 * operation result must be decoded in the |
|
1745 * case there are following operations |
|
1746 * in the compound request. Therefore, mark |
|
1747 * the rest of the response as "skip" and |
|
1748 * decode or skip the remaining data |
|
1749 */ |
|
1750 entry_length = DIRENT64_RECLEN(namelen); |
|
1751 if (space_left < entry_length) |
|
1752 skip_to_end = 1; |
|
1753 } |
|
1754 |
|
1755 /* Get the NAME of the entry */ |
|
1756 if (!skip_to_end) { |
|
1757 if (!xdr_opaque(xdrs, dp->d_name, namelen)) |
|
1758 goto noentries; |
|
1759 bzero(&dp->d_name[namelen], |
|
1760 DIRENT64_NAMELEN(entry_length) - namelen); |
|
1761 dp->d_off = last_cookie = cookie; |
|
1762 dp->d_reclen = entry_length; |
|
1763 } else { |
|
1764 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &namelen)) |
|
1765 goto noentries; |
|
1766 } |
|
1767 |
|
1768 /* Get the attribute BITMAP */ |
|
1769 if (!xdr_bitmap4(xdrs, &resbmap)) |
|
1770 goto noentries; |
|
1771 /* Get the LENGTH of the attributes */ |
|
1772 if (!xdr_u_int(xdrs, (uint_t *)&attrlen)) |
|
1773 goto noentries; |
|
1774 |
|
1775 /* Get the ATTRIBUTES */ |
|
1776 if (!skip_to_end) { |
|
1777 uint32_t *ptr; |
|
1778 |
|
1779 if (!(resbmap & FATTR4_ACL_MASK) && |
|
1780 (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen)) |
|
1781 != NULL) { |
|
1782 if (!xdr_ga_fattr_res_inline(ptr, &gar, resbmap, |
|
1783 aobjp->attr_request, |
|
1784 aobjp->mi, pug)) |
|
1785 goto noentries; |
|
1786 } else { |
|
1787 if (!xdr_ga_fattr_res(xdrs, &gar, resbmap, |
|
1788 aobjp->attr_request, |
|
1789 aobjp->mi, pug)) |
|
1790 goto noentries; |
|
1791 } |
|
1792 |
|
1793 /* Fill in the d_ino per the server's fid values */ |
|
1794 /* |
|
1795 * Important to note that the mounted on fileid |
|
1796 * is returned in d_ino if supported. This is |
|
1797 * expected, readdir returns the mounted on fileid |
|
1798 * while stat() returns the fileid of the object |
|
1799 * on "top" of the mount. |
|
1800 */ |
|
1801 if (gar.n4g_mon_fid_valid) |
|
1802 dp->d_ino = gar.n4g_mon_fid; |
|
1803 else if (gar.n4g_va.va_mask & AT_NODEID) |
|
1804 dp->d_ino = gar.n4g_va.va_nodeid; |
|
1805 else |
|
1806 dp->d_ino = 0; |
|
1807 |
|
1808 /* See about creating an rnode for this entry */ |
|
1809 if ((resbmap & |
|
1810 (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) == |
|
1811 (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) { |
|
1812 nfs4_sharedfh_t *sfhp; |
|
1813 vnode_t *vp; |
|
1814 |
|
1815 sfhp = sfh4_put(&ges.n4g_fh_u.n4g_fh, |
|
1816 aobjp->mi, NULL); |
|
1817 vp = makenfs4node(sfhp, &gar, |
|
1818 aobjp->dvp->v_vfsp, |
|
1819 aobjp->t, |
|
1820 aobjp->cr, |
|
1821 aobjp->dvp, |
|
1822 fn_get(VTOSV(aobjp->dvp)->sv_name, |
|
1823 dp->d_name)); |
|
1824 sfh4_rele(&sfhp); |
|
1825 dnlc_update(aobjp->dvp, dp->d_name, vp); |
|
1826 VN_RELE(vp); |
|
1827 } |
|
1828 |
|
1829 dp = (struct dirent64 *)(((caddr_t)dp) + dp->d_reclen); |
|
1830 |
|
1831 space_left -= entry_length; |
|
1832 |
|
1833 } else { |
|
1834 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &attrlen)) |
|
1835 goto noentries; |
|
1836 } |
|
1837 |
|
1838 /* Get the do-we-have-a-next-entry BOOL */ |
|
1839 if (!xdr_bool(xdrs, &more_data)) |
|
1840 goto noentries; |
|
1841 } |
|
1842 |
|
1843 if (pug) { |
|
1844 kmem_free(pug, sizeof (ug_cache_t)); |
|
1845 pug = NULL; |
|
1846 } |
|
1847 |
|
1848 /* |
|
1849 * Finish up the rddir cache |
|
1850 * If no entries were returned, free up buffer & |
|
1851 * set ncookie to the starting cookie for this |
|
1852 * readdir request so that the direof caching |
|
1853 * will work properly. |
|
1854 */ |
|
1855 ASSERT(rdc->entries); |
|
1856 if (last_cookie == 0) { |
|
1857 kmem_free(rdc->entries, rdc->entlen); |
|
1858 rdc->entries = NULL; |
|
1859 last_cookie = rdc->nfs4_cookie; |
|
1860 } |
|
1861 |
|
1862 rdc->actlen = rdc->entlen - space_left; |
|
1863 rdc->nfs4_ncookie = last_cookie; |
|
1864 |
|
1865 /* Get the EOF marker */ |
|
1866 if (!xdr_bool(xdrs, &objp->eof)) |
|
1867 goto noentries; |
|
1868 |
|
1869 /* |
|
1870 * If the server returns eof and there were no |
|
1871 * skipped entries, set eof |
|
1872 */ |
|
1873 rdc->eof = (objp->eof && !skip_to_end) ? TRUE : FALSE; |
|
1874 |
|
1875 /* |
|
1876 * If we encoded entries we are done |
|
1877 */ |
|
1878 if (rdc->entries) { |
|
1879 rdc->error = 0; |
|
1880 return (TRUE); |
|
1881 } |
|
1882 |
|
1883 /* |
|
1884 * If there were no entries and we skipped because |
|
1885 * there was not enough space, return EINVAL |
|
1886 */ |
|
1887 if (skip_to_end) { |
|
1888 rdc->error = EINVAL; |
|
1889 return (TRUE); |
|
1890 } |
|
1891 |
|
1892 /* |
|
1893 * No entries, nothing skipped, and EOF, return OK. |
|
1894 */ |
|
1895 if (objp->eof == TRUE) { |
|
1896 rdc->error = 0; |
|
1897 return (TRUE); |
|
1898 } |
|
1899 |
|
1900 /* |
|
1901 * No entries, nothing skipped, and not EOF |
|
1902 * probably a bad cookie, return ENOENT. |
|
1903 */ |
|
1904 rdc->error = ENOENT; |
|
1905 return (TRUE); |
|
1906 |
|
1907 noentries: |
|
1908 if (rdc->entries) { |
|
1909 kmem_free(rdc->entries, rdc->entlen); |
|
1910 rdc->entries = NULL; |
|
1911 } |
|
1912 if (pug) |
|
1913 kmem_free(pug, sizeof (ug_cache_t)); |
|
1914 rdc->error = EIO; |
|
1915 return (FALSE); |
|
1916 } |
|
1917 |
|
1918 /* |
|
1919 * xdr_ga_res |
|
1920 * |
|
1921 * Returns: FALSE on raw data processing errors, TRUE otherwise. |
|
1922 * |
|
1923 * This function pre-processes the OP_GETATTR response, and then |
|
1924 * calls common routines to process the GETATTR fattr4 results into |
|
1925 * vnode attributes and other components that the client is interested |
|
1926 * in. If an error other than an RPC error is encountered, the details |
|
1927 * of the error are filled into objp, although the result of the |
|
1928 * processing is set to TRUE. |
|
1929 */ |
|
1930 static bool_t |
|
1931 xdr_ga_res(XDR *xdrs, GETATTR4res *objp, GETATTR4args *aobjp) |
|
1932 { |
|
1933 uint32_t *ptr; |
|
1934 bitmap4 resbmap; |
|
1935 uint32_t attrlen; |
|
1936 |
|
1937 ASSERT(xdrs->x_op == XDR_DECODE); |
|
1938 |
|
1939 /* Initialize objp attribute error values */ |
|
1940 objp->ga_res.n4g_attrerr = |
|
1941 objp->ga_res.n4g_attrwhy = NFS4_GETATTR_OP_OK; |
|
1942 |
|
1943 if (!xdr_bitmap4(xdrs, &resbmap)) |
|
1944 return (FALSE); |
|
1945 |
|
1946 /* save the response bitmap for the caller */ |
|
1947 objp->ga_res.n4g_resbmap = resbmap; |
|
1948 |
|
1949 /* attrlen */ |
|
1950 if (!XDR_GETINT32(xdrs, (int32_t *)&attrlen)) |
|
1951 return (FALSE); |
|
1952 |
|
1953 /* |
|
1954 * Handle case where request and response bitmaps don't match. |
|
1955 */ |
|
1956 if (aobjp->attr_request && aobjp->attr_request != resbmap) { |
|
1957 bitmap4 deltabmap; |
|
1958 |
|
1959 /* |
|
1960 * Return error for case where server sent extra attributes |
|
1961 * because the "unknown" attributes may be anywhere in the |
|
1962 * xdr stream and can't be properly processed. |
|
1963 */ |
|
1964 deltabmap = ((aobjp->attr_request ^ resbmap) & resbmap); |
|
1965 if (deltabmap) { |
|
1966 objp->ga_res.n4g_attrerr = EINVAL; |
|
1967 objp->ga_res.n4g_attrwhy = NFS4_GETATTR_BITMAP_ERR; |
|
1968 return (TRUE); |
|
1969 } |
|
1970 |
|
1971 /* |
|
1972 * Return error for case where there is a mandatory |
|
1973 * attribute missing in the server response. Note that |
|
1974 * missing recommended attributes are evaluated in the |
|
1975 * specific routines that decode the server response. |
|
1976 */ |
|
1977 deltabmap = ((aobjp->attr_request ^ resbmap) |
|
1978 & aobjp->attr_request); |
|
1979 if ((deltabmap & FATTR4_MANDATTR_MASK)) { |
|
1980 objp->ga_res.n4g_attrerr = EINVAL; |
|
1981 objp->ga_res.n4g_attrwhy = NFS4_GETATTR_MANDATTR_ERR; |
|
1982 return (TRUE); |
|
1983 } |
|
1984 } |
|
1985 |
|
1986 /* Check to see if the attrs can be inlined and go for it if so */ |
|
1987 if (!(resbmap & FATTR4_ACL_MASK) && |
|
1988 (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen)) != NULL) |
|
1989 return (xdr_ga_fattr_res_inline(ptr, &objp->ga_res, |
|
1990 resbmap, aobjp->attr_request, |
|
1991 aobjp->mi, NULL)); |
|
1992 else |
|
1993 return (xdr_ga_fattr_res(xdrs, &objp->ga_res, |
|
1994 resbmap, aobjp->attr_request, |
|
1995 aobjp->mi, NULL)); |
|
1996 } |
|
1997 |
|
1998 #if defined(DEBUG) && !defined(lint) |
|
1999 /* |
|
2000 * We assume that an enum is a 32-bit value, check it once |
|
2001 */ |
|
2002 static enum szchk { SZVAL } szchkvar; |
|
2003 #endif |
|
2004 |
|
2005 bool_t |
|
2006 xdr_settime4(XDR *xdrs, settime4 *objp) |
|
2007 { |
|
2008 #if defined(DEBUG) && !defined(lint) |
|
2009 ASSERT(sizeof (szchkvar) == sizeof (int32_t)); |
|
2010 #endif |
|
2011 if (xdrs->x_op == XDR_FREE) |
|
2012 return (TRUE); |
|
2013 |
|
2014 if (!xdr_int(xdrs, (int *)&objp->set_it)) |
|
2015 return (FALSE); |
|
2016 if (objp->set_it != SET_TO_CLIENT_TIME4) |
|
2017 return (TRUE); |
|
2018 /* xdr_nfstime4 */ |
|
2019 if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->time.seconds)) |
|
2020 return (FALSE); |
|
2021 return (xdr_u_int(xdrs, &objp->time.nseconds)); |
|
2022 } |
|
2023 |
|
2024 static bool_t |
|
2025 xdr_fattr4(XDR *xdrs, fattr4 *objp) |
|
2026 { |
|
2027 if (xdrs->x_op != XDR_FREE) { |
|
2028 if (!xdr_bitmap4(xdrs, &objp->attrmask)) |
|
2029 return (FALSE); |
|
2030 return (xdr_bytes(xdrs, (char **)&objp->attrlist4, |
|
2031 (uint_t *)&objp->attrlist4_len, NFS4_FATTR4_LIMIT)); |
|
2032 } |
|
2033 |
|
2034 /* |
|
2035 * Optimized free case |
|
2036 */ |
|
2037 if (objp->attrlist4 != NULL) |
|
2038 kmem_free(objp->attrlist4, objp->attrlist4_len); |
|
2039 return (TRUE); |
|
2040 } |
|
2041 |
|
2042 static bool_t |
|
2043 xdr_ACCESS4res(XDR *xdrs, ACCESS4res *objp) |
|
2044 { |
|
2045 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
2046 return (FALSE); |
|
2047 if (objp->status != NFS4_OK) |
|
2048 return (TRUE); |
|
2049 if (!xdr_u_int(xdrs, &objp->supported)) |
|
2050 return (FALSE); |
|
2051 return (xdr_u_int(xdrs, &objp->access)); |
|
2052 } |
|
2053 |
|
2054 static bool_t |
|
2055 xdr_CLOSE4args(XDR *xdrs, CLOSE4args *objp) |
|
2056 { |
|
2057 if (!xdr_u_int(xdrs, &objp->seqid)) |
|
2058 return (FALSE); |
|
2059 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid)) |
|
2060 return (FALSE); |
|
2061 return (xdr_opaque(xdrs, objp->open_stateid.other, 12)); |
|
2062 } |
|
2063 |
|
2064 static bool_t |
|
2065 xdr_CLOSE4res(XDR *xdrs, CLOSE4res *objp) |
|
2066 { |
|
2067 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
2068 return (FALSE); |
|
2069 if (objp->status != NFS4_OK) |
|
2070 return (TRUE); |
|
2071 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid)) |
|
2072 return (FALSE); |
|
2073 return (xdr_opaque(xdrs, objp->open_stateid.other, 12)); |
|
2074 } |
|
2075 |
|
2076 static bool_t |
|
2077 xdr_CREATE4args(XDR *xdrs, CREATE4args *objp) |
|
2078 { |
|
2079 if (xdrs->x_op != XDR_FREE) { |
|
2080 if (!xdr_int(xdrs, (int32_t *)&objp->type)) |
|
2081 return (FALSE); |
|
2082 switch (objp->type) { |
|
2083 case NF4LNK: |
|
2084 if (!xdr_bytes(xdrs, |
|
2085 (char **)&objp->ftype4_u.linkdata.utf8string_val, |
|
2086 (uint_t *)&objp->ftype4_u.linkdata.utf8string_len, |
|
2087 NFS4_MAX_UTF8STRING)) |
|
2088 return (FALSE); |
|
2089 break; |
|
2090 case NF4BLK: |
|
2091 case NF4CHR: |
|
2092 if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata1)) |
|
2093 return (FALSE); |
|
2094 if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata2)) |
|
2095 return (FALSE); |
|
2096 break; |
|
2097 case NF4SOCK: |
|
2098 case NF4FIFO: |
|
2099 case NF4DIR: |
|
2100 default: |
|
2101 break; /* server should return NFS4ERR_BADTYPE */ |
|
2102 } |
|
2103 if (!xdr_bytes(xdrs, (char **)&objp->objname.utf8string_val, |
|
2104 (uint_t *)&objp->objname.utf8string_len, |
|
2105 NFS4_MAX_UTF8STRING)) |
|
2106 return (FALSE); |
|
2107 return (xdr_fattr4(xdrs, &objp->createattrs)); |
|
2108 } |
|
2109 |
|
2110 /* |
|
2111 * Optimized free case |
|
2112 */ |
|
2113 if (objp->type == NF4LNK) { |
|
2114 if (objp->ftype4_u.linkdata.utf8string_val != NULL) |
|
2115 kmem_free(objp->ftype4_u.linkdata.utf8string_val, |
|
2116 objp->ftype4_u.linkdata.utf8string_len); |
|
2117 } |
|
2118 if (objp->objname.utf8string_val != NULL) |
|
2119 kmem_free(objp->objname.utf8string_val, |
|
2120 objp->objname.utf8string_len); |
|
2121 return (xdr_fattr4(xdrs, &objp->createattrs)); |
|
2122 } |
|
2123 |
|
2124 static bool_t |
|
2125 xdr_CREATE4cargs(XDR *xdrs, CREATE4cargs *objp) |
|
2126 { |
|
2127 int len; |
|
2128 |
|
2129 ASSERT(xdrs->x_op == XDR_ENCODE); |
|
2130 |
|
2131 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->type)) |
|
2132 return (FALSE); |
|
2133 switch (objp->type) { |
|
2134 case NF4LNK: |
|
2135 len = strlen(objp->ftype4_u.clinkdata); |
|
2136 if (len > NFS4_MAX_UTF8STRING) |
|
2137 return (FALSE); |
|
2138 if (!XDR_PUTINT32(xdrs, &len)) |
|
2139 return (FALSE); |
|
2140 if (!xdr_opaque(xdrs, objp->ftype4_u.clinkdata, len)) |
|
2141 return (FALSE); |
|
2142 break; |
|
2143 case NF4BLK: |
|
2144 case NF4CHR: |
|
2145 if (!XDR_PUTINT32(xdrs, |
|
2146 (int32_t *)&objp->ftype4_u.devdata.specdata1)) |
|
2147 return (FALSE); |
|
2148 if (!XDR_PUTINT32(xdrs, |
|
2149 (int32_t *)&objp->ftype4_u.devdata.specdata2)) |
|
2150 return (FALSE); |
|
2151 break; |
|
2152 case NF4SOCK: |
|
2153 case NF4FIFO: |
|
2154 case NF4DIR: |
|
2155 default: |
|
2156 break; /* server should return NFS4ERR_BADTYPE */ |
|
2157 } |
|
2158 |
|
2159 len = strlen(objp->cname); |
|
2160 if (len > NFS4_MAX_UTF8STRING) |
|
2161 return (FALSE); |
|
2162 if (!XDR_PUTINT32(xdrs, &len)) |
|
2163 return (FALSE); |
|
2164 if (!xdr_opaque(xdrs, objp->cname, len)) |
|
2165 return (FALSE); |
|
2166 |
|
2167 return (xdr_fattr4(xdrs, &objp->createattrs)); |
|
2168 } |
|
2169 |
|
2170 static bool_t |
|
2171 xdr_CREATE4res(XDR *xdrs, CREATE4res *objp) |
|
2172 { |
|
2173 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
2174 return (FALSE); |
|
2175 if (objp->status != NFS4_OK) |
|
2176 return (TRUE); |
|
2177 if (!xdr_bool(xdrs, &objp->cinfo.atomic)) |
|
2178 return (FALSE); |
|
2179 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before)) |
|
2180 return (FALSE); |
|
2181 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after)) |
|
2182 return (FALSE); |
|
2183 return (xdr_bitmap4(xdrs, &objp->attrset)); |
|
2184 } |
|
2185 |
|
2186 static bool_t |
|
2187 xdr_LINK4res(XDR *xdrs, LINK4res *objp) |
|
2188 { |
|
2189 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
2190 return (FALSE); |
|
2191 if (objp->status != NFS4_OK) |
|
2192 return (TRUE); |
|
2193 if (!xdr_bool(xdrs, &objp->cinfo.atomic)) |
|
2194 return (FALSE); |
|
2195 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before)) |
|
2196 return (FALSE); |
|
2197 return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after)); |
|
2198 } |
|
2199 |
|
2200 static bool_t |
|
2201 xdr_LOCK4args(XDR *xdrs, LOCK4args *objp) |
|
2202 { |
|
2203 if (xdrs->x_op != XDR_FREE) { |
|
2204 if (!xdr_int(xdrs, (int *)&objp->locktype)) |
|
2205 return (FALSE); |
|
2206 if (!xdr_bool(xdrs, &objp->reclaim)) |
|
2207 return (FALSE); |
|
2208 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset)) |
|
2209 return (FALSE); |
|
2210 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length)) |
|
2211 return (FALSE); |
|
2212 if (!xdr_bool(xdrs, &objp->locker.new_lock_owner)) |
|
2213 return (FALSE); |
|
2214 if (objp->locker.new_lock_owner == TRUE) { |
|
2215 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner. |
|
2216 open_seqid)) |
|
2217 return (FALSE); |
|
2218 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner. |
|
2219 open_stateid.seqid)) |
|
2220 return (FALSE); |
|
2221 if (!xdr_opaque(xdrs, objp->locker.locker4_u.open_owner. |
|
2222 open_stateid.other, |
|
2223 12)) |
|
2224 return (FALSE); |
|
2225 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner. |
|
2226 lock_seqid)) |
|
2227 return (FALSE); |
|
2228 if (!xdr_u_longlong_t(xdrs, |
|
2229 (u_longlong_t *)&objp->locker.locker4_u. |
|
2230 open_owner.lock_owner.clientid)) |
|
2231 return (FALSE); |
|
2232 return (xdr_bytes(xdrs, |
|
2233 (char **)&objp->locker.locker4_u.open_owner. |
|
2234 lock_owner.owner_val, |
|
2235 (uint_t *)&objp->locker.locker4_u.open_owner. |
|
2236 lock_owner.owner_len, |
|
2237 NFS4_OPAQUE_LIMIT)); |
|
2238 } |
|
2239 |
|
2240 if (objp->locker.new_lock_owner != FALSE) |
|
2241 return (FALSE); |
|
2242 |
|
2243 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner. |
|
2244 lock_stateid.seqid)) |
|
2245 return (FALSE); |
|
2246 if (!xdr_opaque(xdrs, objp->locker.locker4_u.lock_owner. |
|
2247 lock_stateid.other, |
|
2248 12)) |
|
2249 return (FALSE); |
|
2250 return (xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner. |
|
2251 lock_seqid)); |
|
2252 } |
|
2253 |
|
2254 /* |
|
2255 * Optimized free case |
|
2256 */ |
|
2257 if (objp->locker.new_lock_owner == TRUE) { |
|
2258 if (objp->locker.locker4_u.open_owner.lock_owner.owner_val != |
|
2259 NULL) { |
|
2260 kmem_free(objp->locker.locker4_u.open_owner.lock_owner. |
|
2261 owner_val, |
|
2262 objp->locker.locker4_u.open_owner.lock_owner. |
|
2263 owner_len); |
|
2264 } |
|
2265 } |
|
2266 |
|
2267 return (TRUE); |
|
2268 } |
|
2269 |
|
2270 static bool_t |
|
2271 xdr_LOCK4res(XDR *xdrs, LOCK4res *objp) |
|
2272 { |
|
2273 if (xdrs->x_op != XDR_FREE) { |
|
2274 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
2275 return (FALSE); |
|
2276 if (objp->status == NFS4_OK) { |
|
2277 if (!xdr_u_int(xdrs, |
|
2278 &objp->LOCK4res_u.lock_stateid.seqid)) |
|
2279 return (FALSE); |
|
2280 return (xdr_opaque(xdrs, |
|
2281 objp->LOCK4res_u.lock_stateid.other, 12)); |
|
2282 } |
|
2283 if (objp->status != NFS4ERR_DENIED) |
|
2284 return (TRUE); |
|
2285 |
|
2286 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u. |
|
2287 denied.offset)) |
|
2288 return (FALSE); |
|
2289 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u. |
|
2290 denied.length)) |
|
2291 return (FALSE); |
|
2292 if (!xdr_int(xdrs, (int *)&objp->LOCK4res_u.denied.locktype)) |
|
2293 return (FALSE); |
|
2294 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u. |
|
2295 denied.owner.clientid)) |
|
2296 return (FALSE); |
|
2297 return (xdr_bytes(xdrs, |
|
2298 (char **)&objp->LOCK4res_u.denied.owner.owner_val, |
|
2299 (uint_t *)&objp->LOCK4res_u.denied.owner.owner_len, |
|
2300 NFS4_OPAQUE_LIMIT)); |
|
2301 } |
|
2302 |
|
2303 /* |
|
2304 * Optimized free case |
|
2305 */ |
|
2306 if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED) |
|
2307 return (TRUE); |
|
2308 |
|
2309 if (objp->LOCK4res_u.denied.owner.owner_val != NULL) |
|
2310 kmem_free(objp->LOCK4res_u.denied.owner.owner_val, |
|
2311 objp->LOCK4res_u.denied.owner.owner_len); |
|
2312 return (TRUE); |
|
2313 } |
|
2314 |
|
2315 static bool_t |
|
2316 xdr_LOCKT4args(XDR *xdrs, LOCKT4args *objp) |
|
2317 { |
|
2318 if (xdrs->x_op != XDR_FREE) { |
|
2319 if (!xdr_int(xdrs, (int *)&objp->locktype)) |
|
2320 return (FALSE); |
|
2321 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset)) |
|
2322 return (FALSE); |
|
2323 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length)) |
|
2324 return (FALSE); |
|
2325 if (!xdr_u_longlong_t(xdrs, |
|
2326 (u_longlong_t *)&objp->owner.clientid)) |
|
2327 return (FALSE); |
|
2328 return (xdr_bytes(xdrs, (char **)&objp->owner.owner_val, |
|
2329 (uint_t *)&objp->owner.owner_len, |
|
2330 NFS4_OPAQUE_LIMIT)); |
|
2331 } |
|
2332 |
|
2333 /* |
|
2334 * Optimized free case |
|
2335 */ |
|
2336 if (objp->owner.owner_val != NULL) |
|
2337 kmem_free(objp->owner.owner_val, objp->owner.owner_len); |
|
2338 return (TRUE); |
|
2339 } |
|
2340 |
|
2341 static bool_t |
|
2342 xdr_LOCKT4res(XDR *xdrs, LOCKT4res *objp) |
|
2343 { |
|
2344 if (xdrs->x_op != XDR_FREE) { |
|
2345 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
2346 return (FALSE); |
|
2347 if (objp->status == NFS4_OK) |
|
2348 return (TRUE); |
|
2349 if (objp->status != NFS4ERR_DENIED) |
|
2350 return (TRUE); |
|
2351 /* xdr_LOCK4denied */ |
|
2352 if (!xdr_u_longlong_t(xdrs, |
|
2353 (u_longlong_t *)&objp->denied.offset)) |
|
2354 return (FALSE); |
|
2355 if (!xdr_u_longlong_t(xdrs, |
|
2356 (u_longlong_t *)&objp->denied.length)) |
|
2357 return (FALSE); |
|
2358 if (!xdr_int(xdrs, (int *)&objp->denied.locktype)) |
|
2359 return (FALSE); |
|
2360 if (!xdr_u_longlong_t(xdrs, |
|
2361 (u_longlong_t *)&objp->denied.owner.clientid)) |
|
2362 return (FALSE); |
|
2363 return (xdr_bytes(xdrs, |
|
2364 (char **)&objp->denied.owner.owner_val, |
|
2365 (uint_t *)&objp->denied.owner.owner_len, |
|
2366 NFS4_OPAQUE_LIMIT)); |
|
2367 } |
|
2368 |
|
2369 /* |
|
2370 * Optimized free case |
|
2371 */ |
|
2372 if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED) |
|
2373 return (TRUE); |
|
2374 if (objp->denied.owner.owner_val != NULL) |
|
2375 kmem_free(objp->denied.owner.owner_val, |
|
2376 objp->denied.owner.owner_len); |
|
2377 return (TRUE); |
|
2378 } |
|
2379 |
|
2380 static bool_t |
|
2381 xdr_LOCKU4args(XDR *xdrs, LOCKU4args *objp) |
|
2382 { |
|
2383 if (!xdr_int(xdrs, (int *)&objp->locktype)) |
|
2384 return (FALSE); |
|
2385 if (!xdr_u_int(xdrs, &objp->seqid)) |
|
2386 return (FALSE); |
|
2387 if (!xdr_u_int(xdrs, &objp->lock_stateid.seqid)) |
|
2388 return (FALSE); |
|
2389 if (!xdr_opaque(xdrs, objp->lock_stateid.other, 12)) |
|
2390 return (FALSE); |
|
2391 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset)) |
|
2392 return (FALSE); |
|
2393 return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length)); |
|
2394 } |
|
2395 |
|
2396 static bool_t |
|
2397 xdr_OPEN4args(XDR *xdrs, OPEN4args *objp) |
|
2398 { |
|
2399 if (xdrs->x_op != XDR_FREE) { |
|
2400 if (!xdr_u_int(xdrs, &objp->seqid)) |
|
2401 return (FALSE); |
|
2402 if (!xdr_u_int(xdrs, &objp->share_access)) |
|
2403 return (FALSE); |
|
2404 if (!xdr_u_int(xdrs, &objp->share_deny)) |
|
2405 return (FALSE); |
|
2406 |
|
2407 /* xdr_open_owner4 */ |
|
2408 if (!xdr_u_longlong_t(xdrs, |
|
2409 (u_longlong_t *)&objp->owner.clientid)) |
|
2410 return (FALSE); |
|
2411 if (!xdr_bytes(xdrs, (char **)&objp->owner.owner_val, |
|
2412 (uint_t *)&objp->owner.owner_len, |
|
2413 NFS4_OPAQUE_LIMIT)) |
|
2414 return (FALSE); |
|
2415 |
|
2416 /* xdr_openflag4 */ |
|
2417 if (!xdr_int(xdrs, (int *)&objp->opentype)) |
|
2418 return (FALSE); |
|
2419 if (objp->opentype == OPEN4_CREATE) { |
|
2420 |
|
2421 /* xdr_createhow4 */ |
|
2422 if (!xdr_int(xdrs, (int *)&objp->mode)) |
|
2423 return (FALSE); |
|
2424 switch (objp->mode) { |
|
2425 case UNCHECKED4: |
|
2426 case GUARDED4: |
|
2427 if (!xdr_fattr4(xdrs, |
|
2428 &objp->createhow4_u.createattrs)) |
|
2429 return (FALSE); |
|
2430 break; |
|
2431 case EXCLUSIVE4: |
|
2432 if (!xdr_u_longlong_t(xdrs, |
|
2433 (u_longlong_t *)&objp->createhow4_u. |
|
2434 createverf)) |
|
2435 return (FALSE); |
|
2436 break; |
|
2437 default: |
|
2438 return (FALSE); |
|
2439 } |
|
2440 } |
|
2441 |
|
2442 /* xdr_open_claim4 */ |
|
2443 if (!xdr_int(xdrs, (int *)&objp->claim)) |
|
2444 return (FALSE); |
|
2445 |
|
2446 switch (objp->claim) { |
|
2447 case CLAIM_NULL: |
|
2448 return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u. |
|
2449 file.utf8string_val, |
|
2450 (uint_t *)&objp->open_claim4_u.file. |
|
2451 utf8string_len, |
|
2452 NFS4_MAX_UTF8STRING)); |
|
2453 case CLAIM_PREVIOUS: |
|
2454 return (xdr_int(xdrs, |
|
2455 (int *)&objp->open_claim4_u.delegate_type)); |
|
2456 case CLAIM_DELEGATE_CUR: |
|
2457 if (!xdr_u_int(xdrs, (uint_t *)&objp->open_claim4_u. |
|
2458 delegate_cur_info.delegate_stateid.seqid)) |
|
2459 return (FALSE); |
|
2460 if (!xdr_opaque(xdrs, objp->open_claim4_u. |
|
2461 delegate_cur_info.delegate_stateid.other, |
|
2462 12)) |
|
2463 return (FALSE); |
|
2464 return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u. |
|
2465 delegate_cur_info.file.utf8string_val, |
|
2466 (uint_t *)&objp->open_claim4_u. |
|
2467 delegate_cur_info.file.utf8string_len, |
|
2468 NFS4_MAX_UTF8STRING)); |
|
2469 case CLAIM_DELEGATE_PREV: |
|
2470 return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u. |
|
2471 file_delegate_prev.utf8string_val, |
|
2472 (uint_t *)&objp->open_claim4_u. |
|
2473 file_delegate_prev.utf8string_len, |
|
2474 NFS4_MAX_UTF8STRING)); |
|
2475 default: |
|
2476 return (FALSE); |
|
2477 } |
|
2478 } |
|
2479 |
|
2480 /* |
|
2481 * Optimized free case |
|
2482 */ |
|
2483 if (objp->owner.owner_val != NULL) |
|
2484 kmem_free(objp->owner.owner_val, objp->owner.owner_len); |
|
2485 |
|
2486 if (objp->opentype == OPEN4_CREATE) { |
|
2487 switch (objp->mode) { |
|
2488 case UNCHECKED4: |
|
2489 case GUARDED4: |
|
2490 (void) xdr_fattr4(xdrs, |
|
2491 &objp->createhow4_u.createattrs); |
|
2492 break; |
|
2493 case EXCLUSIVE4: |
|
2494 default: |
|
2495 break; |
|
2496 } |
|
2497 } |
|
2498 |
|
2499 switch (objp->claim) { |
|
2500 case CLAIM_NULL: |
|
2501 if (objp->open_claim4_u.file.utf8string_val != NULL) |
|
2502 kmem_free(objp->open_claim4_u.file.utf8string_val, |
|
2503 objp->open_claim4_u.file.utf8string_len); |
|
2504 return (TRUE); |
|
2505 case CLAIM_PREVIOUS: |
|
2506 return (TRUE); |
|
2507 case CLAIM_DELEGATE_CUR: |
|
2508 if (objp->open_claim4_u.delegate_cur_info.file.utf8string_val != |
|
2509 NULL) { |
|
2510 kmem_free(objp->open_claim4_u.delegate_cur_info.file. |
|
2511 utf8string_val, |
|
2512 objp->open_claim4_u.delegate_cur_info.file. |
|
2513 utf8string_len); |
|
2514 } |
|
2515 return (TRUE); |
|
2516 case CLAIM_DELEGATE_PREV: |
|
2517 if (objp->open_claim4_u.file_delegate_prev.utf8string_val != |
|
2518 NULL) { |
|
2519 kmem_free(objp->open_claim4_u.file_delegate_prev. |
|
2520 utf8string_val, |
|
2521 objp->open_claim4_u.file_delegate_prev. |
|
2522 utf8string_len); |
|
2523 } |
|
2524 return (TRUE); |
|
2525 default: |
|
2526 return (TRUE); |
|
2527 } |
|
2528 /* NOTREACHED */ |
|
2529 } |
|
2530 |
|
2531 static bool_t |
|
2532 xdr_OPEN4cargs(XDR *xdrs, OPEN4cargs *objp) |
|
2533 { |
|
2534 int op; |
|
2535 int len; |
|
2536 rpc_inline_t *ptr; |
|
2537 |
|
2538 ASSERT(xdrs->x_op == XDR_ENCODE); |
|
2539 |
|
2540 /* |
|
2541 * We must always define the client's open_owner to be |
|
2542 * 4 byte aligned and sized. |
|
2543 */ |
|
2544 ASSERT(objp->owner.owner_len <= NFS4_OPAQUE_LIMIT); |
|
2545 ASSERT(!(objp->owner.owner_len % BYTES_PER_XDR_UNIT)); |
|
2546 |
|
2547 len = objp->owner.owner_len; |
|
2548 if ((ptr = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + len)) != NULL) { |
|
2549 int i; |
|
2550 int32_t *ip; |
|
2551 |
|
2552 IXDR_PUT_U_INT32(ptr, OP_OPEN); |
|
2553 IXDR_PUT_U_INT32(ptr, objp->seqid); |
|
2554 IXDR_PUT_U_INT32(ptr, objp->share_access); |
|
2555 IXDR_PUT_U_INT32(ptr, objp->share_deny); |
|
2556 |
|
2557 /* xdr_open_owner4 */ |
|
2558 IXDR_PUT_HYPER(ptr, objp->owner.clientid); |
|
2559 IXDR_PUT_U_INT32(ptr, objp->owner.owner_len); |
|
2560 /* We know this is very short so don't bcopy */ |
|
2561 ip = (int32_t *)objp->owner.owner_val; |
|
2562 len /= BYTES_PER_XDR_UNIT; |
|
2563 for (i = 0; i < len; i++) |
|
2564 *ptr++ = *ip++; |
|
2565 |
|
2566 /* xdr_openflag4 */ |
|
2567 IXDR_PUT_U_INT32(ptr, objp->opentype); |
|
2568 } else { |
|
2569 op = OP_OPEN; |
|
2570 if (!XDR_PUTINT32(xdrs, (int32_t *)&op)) |
|
2571 return (FALSE); |
|
2572 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->seqid)) |
|
2573 return (FALSE); |
|
2574 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_access)) |
|
2575 return (FALSE); |
|
2576 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_deny)) |
|
2577 return (FALSE); |
|
2578 |
|
2579 /* xdr_open_owner4 */ |
|
2580 if (!xdr_u_longlong_t(xdrs, |
|
2581 (u_longlong_t *)&objp->owner.clientid)) |
|
2582 return (FALSE); |
|
2583 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->owner.owner_len)) |
|
2584 return (FALSE); |
|
2585 if (!xdr_opaque(xdrs, objp->owner.owner_val, |
|
2586 objp->owner.owner_len)) |
|
2587 return (FALSE); |
|
2588 |
|
2589 /* xdr_openflag4 */ |
|
2590 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->opentype)) |
|
2591 return (FALSE); |
|
2592 } |
|
2593 |
|
2594 if (objp->opentype == OPEN4_CREATE) { |
|
2595 /* xdr_createhow4 */ |
|
2596 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->mode)) |
|
2597 return (FALSE); |
|
2598 switch (objp->mode) { |
|
2599 case UNCHECKED4: |
|
2600 case GUARDED4: |
|
2601 if (!xdr_fattr4(xdrs, |
|
2602 &objp->createhow4_u.createattrs)) |
|
2603 return (FALSE); |
|
2604 break; |
|
2605 case EXCLUSIVE4: |
|
2606 if (!xdr_u_longlong_t(xdrs, |
|
2607 (u_longlong_t *)&objp->createhow4_u. |
|
2608 createverf)) |
|
2609 return (FALSE); |
|
2610 break; |
|
2611 default: |
|
2612 return (FALSE); |
|
2613 } |
|
2614 } |
|
2615 |
|
2616 /* xdr_open_claim4 */ |
|
2617 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->claim)) |
|
2618 return (FALSE); |
|
2619 |
|
2620 switch (objp->claim) { |
|
2621 case CLAIM_NULL: |
|
2622 len = strlen(objp->open_claim4_u.cfile); |
|
2623 if (len > NFS4_MAX_UTF8STRING) |
|
2624 return (FALSE); |
|
2625 if (XDR_PUTINT32(xdrs, &len)) { |
|
2626 return (xdr_opaque(xdrs, |
|
2627 objp->open_claim4_u.cfile, len)); |
|
2628 } |
|
2629 return (FALSE); |
|
2630 case CLAIM_PREVIOUS: |
|
2631 return (XDR_PUTINT32(xdrs, |
|
2632 (int32_t *)&objp->open_claim4_u.delegate_type)); |
|
2633 case CLAIM_DELEGATE_CUR: |
|
2634 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->open_claim4_u. |
|
2635 delegate_cur_info.delegate_stateid.seqid)) |
|
2636 return (FALSE); |
|
2637 if (!xdr_opaque(xdrs, objp->open_claim4_u. |
|
2638 delegate_cur_info.delegate_stateid.other, |
|
2639 12)) |
|
2640 return (FALSE); |
|
2641 len = strlen(objp->open_claim4_u.delegate_cur_info.cfile); |
|
2642 if (len > NFS4_MAX_UTF8STRING) |
|
2643 return (FALSE); |
|
2644 if (XDR_PUTINT32(xdrs, &len)) { |
|
2645 return (xdr_opaque(xdrs, |
|
2646 objp->open_claim4_u.delegate_cur_info.cfile, |
|
2647 len)); |
|
2648 } |
|
2649 return (FALSE); |
|
2650 case CLAIM_DELEGATE_PREV: |
|
2651 len = strlen(objp->open_claim4_u.cfile_delegate_prev); |
|
2652 if (len > NFS4_MAX_UTF8STRING) |
|
2653 return (FALSE); |
|
2654 if (XDR_PUTINT32(xdrs, &len)) { |
|
2655 return (xdr_opaque(xdrs, |
|
2656 objp->open_claim4_u.cfile_delegate_prev, len)); |
|
2657 } |
|
2658 return (FALSE); |
|
2659 default: |
|
2660 return (FALSE); |
|
2661 } |
|
2662 /* NOTREACHED */ |
|
2663 return (FALSE); |
|
2664 } |
|
2665 |
|
2666 static bool_t |
|
2667 xdr_OPEN4res(XDR *xdrs, OPEN4res *objp) |
|
2668 { |
|
2669 if (xdrs->x_op != XDR_FREE) { |
|
2670 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
2671 return (FALSE); |
|
2672 if (objp->status != NFS4_OK) |
|
2673 return (TRUE); |
|
2674 if (!xdr_u_int(xdrs, &objp->stateid.seqid)) |
|
2675 return (FALSE); |
|
2676 if (!xdr_opaque(xdrs, objp->stateid.other, 12)) |
|
2677 return (FALSE); |
|
2678 if (!xdr_bool(xdrs, &objp->cinfo.atomic)) |
|
2679 return (FALSE); |
|
2680 if (!xdr_u_longlong_t(xdrs, |
|
2681 (u_longlong_t *)&objp->cinfo.before)) |
|
2682 return (FALSE); |
|
2683 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after)) |
|
2684 return (FALSE); |
|
2685 if (!xdr_u_int(xdrs, &objp->rflags)) |
|
2686 return (FALSE); |
|
2687 if (!xdr_bitmap4(xdrs, &objp->attrset)) |
|
2688 return (FALSE); |
|
2689 if (!xdr_int(xdrs, |
|
2690 (int *)&objp->delegation.delegation_type)) |
|
2691 return (FALSE); |
|
2692 switch (objp->delegation.delegation_type) { |
|
2693 case OPEN_DELEGATE_NONE: |
|
2694 return (TRUE); |
|
2695 case OPEN_DELEGATE_READ: |
|
2696 if (!xdr_u_int(xdrs, &objp->delegation. |
|
2697 open_delegation4_u.read.stateid.seqid)) |
|
2698 return (FALSE); |
|
2699 if (!xdr_opaque(xdrs, objp->delegation. |
|
2700 open_delegation4_u.read.stateid.other, |
|
2701 12)) |
|
2702 return (FALSE); |
|
2703 if (!xdr_bool(xdrs, &objp->delegation. |
|
2704 open_delegation4_u.read.recall)) |
|
2705 return (FALSE); |
|
2706 return (xdr_nfsace4(xdrs, &objp->delegation. |
|
2707 open_delegation4_u.read.permissions)); |
|
2708 case OPEN_DELEGATE_WRITE: |
|
2709 if (!xdr_u_int(xdrs, &objp->delegation. |
|
2710 open_delegation4_u.write.stateid.seqid)) |
|
2711 return (FALSE); |
|
2712 if (!xdr_opaque(xdrs, objp->delegation. |
|
2713 open_delegation4_u.write.stateid.other, |
|
2714 12)) |
|
2715 return (FALSE); |
|
2716 if (!xdr_bool(xdrs, &objp->delegation. |
|
2717 open_delegation4_u.write.recall)) |
|
2718 return (FALSE); |
|
2719 if (!xdr_int(xdrs, (int *)&objp->delegation. |
|
2720 open_delegation4_u.write.space_limit. |
|
2721 limitby)) |
|
2722 return (FALSE); |
|
2723 switch (objp->delegation. |
|
2724 open_delegation4_u.write.space_limit. |
|
2725 limitby) { |
|
2726 case NFS_LIMIT_SIZE: |
|
2727 if (!xdr_u_longlong_t(xdrs, |
|
2728 (u_longlong_t *)&objp->delegation. |
|
2729 open_delegation4_u.write.space_limit. |
|
2730 nfs_space_limit4_u.filesize)) |
|
2731 return (FALSE); |
|
2732 break; |
|
2733 case NFS_LIMIT_BLOCKS: |
|
2734 if (!xdr_u_int(xdrs, |
|
2735 &objp->delegation.open_delegation4_u.write. |
|
2736 space_limit.nfs_space_limit4_u. |
|
2737 mod_blocks.num_blocks)) |
|
2738 return (FALSE); |
|
2739 if (!xdr_u_int(xdrs, &objp->delegation. |
|
2740 open_delegation4_u.write.space_limit. |
|
2741 nfs_space_limit4_u.mod_blocks. |
|
2742 bytes_per_block)) |
|
2743 return (FALSE); |
|
2744 break; |
|
2745 default: |
|
2746 return (FALSE); |
|
2747 } |
|
2748 return (xdr_nfsace4(xdrs, &objp->delegation. |
|
2749 open_delegation4_u.write.permissions)); |
|
2750 } |
|
2751 return (FALSE); |
|
2752 } |
|
2753 |
|
2754 /* |
|
2755 * Optimized free case |
|
2756 */ |
|
2757 if (objp->status != NFS4_OK) |
|
2758 return (TRUE); |
|
2759 |
|
2760 switch (objp->delegation.delegation_type) { |
|
2761 case OPEN_DELEGATE_NONE: |
|
2762 return (TRUE); |
|
2763 case OPEN_DELEGATE_READ: |
|
2764 return (xdr_nfsace4(xdrs, &objp->delegation. |
|
2765 open_delegation4_u.read.permissions)); |
|
2766 case OPEN_DELEGATE_WRITE: |
|
2767 switch (objp->delegation. |
|
2768 open_delegation4_u.write.space_limit.limitby) { |
|
2769 case NFS_LIMIT_SIZE: |
|
2770 case NFS_LIMIT_BLOCKS: |
|
2771 break; |
|
2772 default: |
|
2773 return (FALSE); |
|
2774 } |
|
2775 return (xdr_nfsace4(xdrs, &objp->delegation. |
|
2776 open_delegation4_u.write.permissions)); |
|
2777 } |
|
2778 return (FALSE); |
|
2779 } |
|
2780 |
|
2781 static bool_t |
|
2782 xdr_OPEN_CONFIRM4res(XDR *xdrs, OPEN_CONFIRM4res *objp) |
|
2783 { |
|
2784 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
2785 return (FALSE); |
|
2786 if (objp->status != NFS4_OK) |
|
2787 return (TRUE); |
|
2788 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid)) |
|
2789 return (FALSE); |
|
2790 return (xdr_opaque(xdrs, objp->open_stateid.other, 12)); |
|
2791 } |
|
2792 |
|
2793 static bool_t |
|
2794 xdr_OPEN_DOWNGRADE4args(XDR *xdrs, OPEN_DOWNGRADE4args *objp) |
|
2795 { |
|
2796 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid)) |
|
2797 return (FALSE); |
|
2798 if (!xdr_opaque(xdrs, objp->open_stateid.other, 12)) |
|
2799 return (FALSE); |
|
2800 if (!xdr_u_int(xdrs, &objp->seqid)) |
|
2801 return (FALSE); |
|
2802 if (!xdr_u_int(xdrs, &objp->share_access)) |
|
2803 return (FALSE); |
|
2804 return (xdr_u_int(xdrs, &objp->share_deny)); |
|
2805 } |
|
2806 |
|
2807 static bool_t |
|
2808 xdr_OPEN_DOWNGRADE4res(XDR *xdrs, OPEN_DOWNGRADE4res *objp) |
|
2809 { |
|
2810 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
2811 return (FALSE); |
|
2812 if (objp->status != NFS4_OK) |
|
2813 return (TRUE); |
|
2814 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid)) |
|
2815 return (FALSE); |
|
2816 return (xdr_opaque(xdrs, objp->open_stateid.other, 12)); |
|
2817 } |
|
2818 |
|
2819 static bool_t |
|
2820 xdr_READ4args(XDR *xdrs, READ4args *objp) |
|
2821 { |
|
2822 if (!xdr_u_int(xdrs, &objp->stateid.seqid)) |
|
2823 return (FALSE); |
|
2824 if (!xdr_opaque(xdrs, objp->stateid.other, 12)) |
|
2825 return (FALSE); |
|
2826 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset)) |
|
2827 return (FALSE); |
|
2828 return (xdr_u_int(xdrs, &objp->count)); |
|
2829 } |
|
2830 |
|
2831 static bool_t |
|
2832 xdr_READ4res(XDR *xdrs, READ4res *objp) |
|
2833 { |
|
2834 int i, rndup; |
|
2835 mblk_t *mp; |
|
2836 |
|
2837 if (xdrs->x_op == XDR_DECODE) |
|
2838 return (FALSE); |
|
2839 |
|
2840 if (xdrs->x_op == XDR_FREE) { |
|
2841 /* |
|
2842 * Optimized free case |
|
2843 */ |
|
2844 if (objp->status != NFS4_OK) |
|
2845 return (TRUE); |
|
2846 if (objp->data_val != NULL) |
|
2847 kmem_free(objp->data_val, objp->data_len); |
|
2848 return (TRUE); |
|
2849 } |
|
2850 |
|
2851 /* on with ENCODE paths */ |
|
2852 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->status)) |
|
2853 return (FALSE); |
|
2854 if (objp->status != NFS4_OK) |
|
2855 return (TRUE); |
|
2856 |
|
2857 if (!XDR_PUTINT32(xdrs, &objp->eof)) |
|
2858 return (FALSE); |
|
2859 |
|
2860 mp = objp->mblk; |
|
2861 if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) { |
|
2862 mp->b_wptr += objp->data_len; |
|
2863 rndup = BYTES_PER_XDR_UNIT - |
|
2864 (objp->data_len % BYTES_PER_XDR_UNIT); |
|
2865 if (rndup != BYTES_PER_XDR_UNIT) |
|
2866 for (i = 0; i < rndup; i++) |
|
2867 *mp->b_wptr++ = '\0'; |
|
2868 if (xdrmblk_putmblk(xdrs, mp, objp->data_len) == TRUE) { |
|
2869 objp->mblk = NULL; |
|
2870 return (TRUE); |
|
2871 } |
|
2872 } |
|
2873 return (xdr_bytes(xdrs, (char **)&objp->data_val, |
|
2874 (uint_t *)&objp->data_len, |
|
2875 objp->data_len)); |
|
2876 } |
|
2877 |
|
2878 static bool_t |
|
2879 xdr_READ4res_clnt(XDR *xdrs, READ4res *objp, READ4args *aobjp) |
|
2880 { |
|
2881 mblk_t *mp; |
|
2882 size_t n; |
|
2883 int error; |
|
2884 uint_t size = aobjp->res_maxsize; |
|
2885 |
|
2886 if (xdrs->x_op == XDR_ENCODE) |
|
2887 return (FALSE); |
|
2888 |
|
2889 if (xdrs->x_op == XDR_FREE) { |
|
2890 /* |
|
2891 * Optimized free case |
|
2892 */ |
|
2893 if (objp->status != NFS4_OK) |
|
2894 return (TRUE); |
|
2895 if (objp->data_val != NULL) |
|
2896 kmem_free(objp->data_val, objp->data_len); |
|
2897 return (TRUE); |
|
2898 } |
|
2899 |
|
2900 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status)) |
|
2901 return (FALSE); |
|
2902 if (objp->status != NFS4_OK) |
|
2903 return (TRUE); |
|
2904 |
|
2905 if (!XDR_GETINT32(xdrs, &objp->eof)) |
|
2906 return (FALSE); |
|
2907 |
|
2908 |
|
2909 /* |
|
2910 * This is a special case such that the caller is providing a |
|
2911 * uio as a guide to eventual data location; this is used for |
|
2912 * handling DIRECTIO reads. |
|
2913 */ |
|
2914 if (aobjp->res_uiop != NULL) { |
|
2915 struct uio *uiop = aobjp->res_uiop; |
|
2916 int32_t *ptr; |
|
2917 |
|
2918 if (xdrs->x_ops == &xdrmblk_ops) { |
|
2919 if (!xdrmblk_getmblk(xdrs, &mp, &objp->data_len)) |
|
2920 return (FALSE); |
|
2921 |
|
2922 if (objp->data_len == 0) |
|
2923 return (TRUE); |
|
2924 |
|
2925 if (objp->data_len > size) |
|
2926 return (FALSE); |
|
2927 |
|
2928 size = objp->data_len; |
|
2929 do { |
|
2930 n = MIN(size, mp->b_wptr - mp->b_rptr); |
|
2931 if ((n = MIN(uiop->uio_resid, n)) != 0) { |
|
2932 |
|
2933 error = uiomove((char *)mp->b_rptr, n, |
|
2934 UIO_READ, uiop); |
|
2935 if (error) |
|
2936 return (FALSE); |
|
2937 mp->b_rptr += n; |
|
2938 size -= n; |
|
2939 } |
|
2940 |
|
2941 while (mp && (mp->b_rptr >= mp->b_wptr)) |
|
2942 mp = mp->b_cont; |
|
2943 } while (mp && size > 0 && uiop->uio_resid > 0); |
|
2944 |
|
2945 return (TRUE); |
|
2946 } |
|
2947 |
|
2948 /* |
|
2949 * This isn't an xdrmblk stream. Handle the likely |
|
2950 * case that it can be inlined (ex. xdrmem). |
|
2951 */ |
|
2952 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->data_len)) |
|
2953 return (FALSE); |
|
2954 |
|
2955 if (objp->data_len == 0) |
|
2956 return (TRUE); |
|
2957 |
|
2958 if (objp->data_len > size) |
|
2959 return (FALSE); |
|
2960 |
|
2961 size = (int)objp->data_len; |
|
2962 if ((ptr = XDR_INLINE(xdrs, size)) != NULL) |
|
2963 return (uiomove(ptr, size, UIO_READ, uiop) ? |
|
2964 FALSE : TRUE); |
|
2965 |
|
2966 /* |
|
2967 * Handle some other (unlikely) stream type that will |
|
2968 * need a copy. |
|
2969 */ |
|
2970 if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL) |
|
2971 return (FALSE); |
|
2972 |
|
2973 if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) { |
|
2974 kmem_free(ptr, size); |
|
2975 return (FALSE); |
|
2976 } |
|
2977 error = uiomove(ptr, size, UIO_READ, uiop); |
|
2978 kmem_free(ptr, size); |
|
2979 |
|
2980 return (error ? FALSE : TRUE); |
|
2981 } |
|
2982 |
|
2983 /* |
|
2984 * Check for the other special case of the caller providing |
|
2985 * the target area for the data. |
|
2986 */ |
|
2987 if (aobjp->res_data_val_alt) |
|
2988 return (xdr_bytes(xdrs, (char **)&aobjp->res_data_val_alt, |
|
2989 (uint_t *)&objp->data_len, |
|
2990 aobjp->res_maxsize)); |
|
2991 |
|
2992 /* caller didn't set things up right if we got this far */ |
|
2993 return (FALSE); |
|
2994 } |
|
2995 |
|
2996 static bool_t |
|
2997 xdr_READDIR4args(XDR *xdrs, READDIR4args *objp) |
|
2998 { |
|
2999 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookie)) |
|
3000 return (FALSE); |
|
3001 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf)) |
|
3002 return (FALSE); |
|
3003 if (!xdr_u_int(xdrs, &objp->dircount)) |
|
3004 return (FALSE); |
|
3005 if (!xdr_u_int(xdrs, &objp->maxcount)) |
|
3006 return (FALSE); |
|
3007 return (xdr_bitmap4(xdrs, &objp->attr_request)); |
|
3008 } |
|
3009 |
|
3010 /* ARGSUSED */ |
|
3011 static bool_t |
|
3012 xdrmblk_putmblk_rd(XDR *xdrs, mblk_t *m) |
|
3013 { |
|
3014 if (((m->b_wptr - m->b_rptr) % BYTES_PER_XDR_UNIT) != 0) |
|
3015 return (FALSE); |
|
3016 |
|
3017 /* LINTED pointer alignment */ |
|
3018 ((mblk_t *)xdrs->x_base)->b_cont = m; |
|
3019 xdrs->x_base = (caddr_t)m; |
|
3020 xdrs->x_handy = 0; |
|
3021 return (TRUE); |
|
3022 } |
|
3023 |
|
3024 bool_t |
|
3025 xdr_READDIR4res(XDR *xdrs, READDIR4res *objp) |
|
3026 { |
|
3027 mblk_t *mp = objp->mblk; |
|
3028 bool_t ret_val; |
|
3029 uint_t flags = 0; |
|
3030 |
|
3031 ASSERT(xdrs->x_op == XDR_ENCODE); |
|
3032 |
|
3033 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
3034 return (FALSE); |
|
3035 if (objp->status != NFS4_OK) |
|
3036 return (TRUE); |
|
3037 if (mp == NULL) |
|
3038 return (FALSE); |
|
3039 |
|
3040 if (xdrs->x_ops == &xdrmblk_ops) { |
|
3041 if (xdrmblk_putmblk_rd(xdrs, mp) |
|
3042 == TRUE) { |
|
3043 /* mblk successfully inserted into outgoing chain */ |
|
3044 objp->mblk = NULL; |
|
3045 return (TRUE); |
|
3046 } |
|
3047 } |
|
3048 |
|
3049 ASSERT(mp->b_cont == NULL); |
|
3050 |
|
3051 /* |
|
3052 * If running over RDMA, the pre-encoded m_blk needs to be moved |
|
3053 * without being chunked. |
|
3054 * Check if chunking is disabled for this xdr stream. If not disable |
|
3055 * it for this op and then enable it back on. |
|
3056 */ |
|
3057 XDR_CONTROL(xdrs, XDR_RDMAGET, &flags); |
|
3058 if (flags & RDMA_NOCHUNK) |
|
3059 return (xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len)); |
|
3060 |
|
3061 flags |= RDMA_NOCHUNK; |
|
3062 (void) XDR_CONTROL(xdrs, XDR_RDMASET, &flags); |
|
3063 ret_val = xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len); |
|
3064 flags &= ~RDMA_NOCHUNK; |
|
3065 (void) XDR_CONTROL(xdrs, XDR_RDMASET, &flags); |
|
3066 return (ret_val); |
|
3067 } |
|
3068 |
|
3069 static bool_t |
|
3070 xdr_READLINK4res(XDR *xdrs, READLINK4res *objp) |
|
3071 { |
|
3072 if (xdrs->x_op != XDR_FREE) { |
|
3073 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
3074 return (FALSE); |
|
3075 if (objp->status != NFS4_OK) |
|
3076 return (TRUE); |
|
3077 return (xdr_bytes(xdrs, (char **)&objp->link.utf8string_val, |
|
3078 (uint_t *)&objp->link.utf8string_len, |
|
3079 NFS4_MAX_UTF8STRING)); |
|
3080 } |
|
3081 |
|
3082 /* |
|
3083 * Optimized free case |
|
3084 */ |
|
3085 if (objp->status != NFS4_OK) |
|
3086 return (TRUE); |
|
3087 if (objp->link.utf8string_val != NULL) |
|
3088 kmem_free(objp->link.utf8string_val, objp->link.utf8string_len); |
|
3089 return (TRUE); |
|
3090 } |
|
3091 |
|
3092 static bool_t |
|
3093 xdr_REMOVE4res(XDR *xdrs, REMOVE4res *objp) |
|
3094 { |
|
3095 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
3096 return (FALSE); |
|
3097 if (objp->status != NFS4_OK) |
|
3098 return (TRUE); |
|
3099 if (!xdr_bool(xdrs, &objp->cinfo.atomic)) |
|
3100 return (FALSE); |
|
3101 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before)) |
|
3102 return (FALSE); |
|
3103 return (xdr_u_longlong_t(xdrs, |
|
3104 (u_longlong_t *)&objp->cinfo.after)); |
|
3105 } |
|
3106 |
|
3107 static bool_t |
|
3108 xdr_RENAME4res(XDR *xdrs, RENAME4res *objp) |
|
3109 { |
|
3110 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
3111 return (FALSE); |
|
3112 if (objp->status != NFS4_OK) |
|
3113 return (TRUE); |
|
3114 if (!xdr_bool(xdrs, &objp->source_cinfo.atomic)) |
|
3115 return (FALSE); |
|
3116 if (!xdr_u_longlong_t(xdrs, |
|
3117 (u_longlong_t *)&objp->source_cinfo.before)) |
|
3118 return (FALSE); |
|
3119 if (!xdr_u_longlong_t(xdrs, |
|
3120 (u_longlong_t *)&objp->source_cinfo.after)) |
|
3121 return (FALSE); |
|
3122 if (!xdr_bool(xdrs, &objp->target_cinfo.atomic)) |
|
3123 return (FALSE); |
|
3124 if (!xdr_u_longlong_t(xdrs, |
|
3125 (u_longlong_t *)&objp->target_cinfo.before)) |
|
3126 return (FALSE); |
|
3127 return (xdr_u_longlong_t(xdrs, |
|
3128 (u_longlong_t *)&objp->target_cinfo.after)); |
|
3129 } |
|
3130 |
|
3131 static bool_t |
|
3132 xdr_secinfo4(XDR *xdrs, secinfo4 *objp) |
|
3133 { |
|
3134 if (xdrs->x_op != XDR_FREE) { |
|
3135 if (!xdr_u_int(xdrs, &objp->flavor)) |
|
3136 return (FALSE); |
|
3137 if (objp->flavor != RPCSEC_GSS) |
|
3138 return (TRUE); |
|
3139 if (!xdr_bytes(xdrs, |
|
3140 (char **)&objp->flavor_info.oid.sec_oid4_val, |
|
3141 (uint_t *)&objp->flavor_info.oid.sec_oid4_len, |
|
3142 NFS4_MAX_SECOID4)) |
|
3143 return (FALSE); |
|
3144 if (!xdr_u_int(xdrs, &objp->flavor_info.qop)) |
|
3145 return (FALSE); |
|
3146 return (xdr_int(xdrs, (int *)&objp->flavor_info.service)); |
|
3147 } |
|
3148 |
|
3149 /* |
|
3150 * Optimized free path |
|
3151 */ |
|
3152 if (objp->flavor != RPCSEC_GSS) |
|
3153 return (TRUE); |
|
3154 |
|
3155 if (objp->flavor_info.oid.sec_oid4_val != NULL) |
|
3156 kmem_free(objp->flavor_info.oid.sec_oid4_val, |
|
3157 objp->flavor_info.oid.sec_oid4_len); |
|
3158 return (TRUE); |
|
3159 } |
|
3160 |
|
3161 static bool_t |
|
3162 xdr_SETCLIENTID4args(XDR *xdrs, SETCLIENTID4args *objp) |
|
3163 { |
|
3164 if (xdrs->x_op != XDR_FREE) { |
|
3165 if (!xdr_u_longlong_t(xdrs, |
|
3166 (u_longlong_t *)&objp->client.verifier)) |
|
3167 return (FALSE); |
|
3168 if (!xdr_bytes(xdrs, (char **)&objp->client.id_val, |
|
3169 (uint_t *)&objp->client.id_len, NFS4_OPAQUE_LIMIT)) |
|
3170 return (FALSE); |
|
3171 if (!xdr_u_int(xdrs, &objp->callback.cb_program)) |
|
3172 return (FALSE); |
|
3173 if (!xdr_string(xdrs, &objp->callback.cb_location.r_netid, |
|
3174 NFS4_OPAQUE_LIMIT)) |
|
3175 return (FALSE); |
|
3176 if (!xdr_string(xdrs, &objp->callback.cb_location.r_addr, |
|
3177 NFS4_OPAQUE_LIMIT)) |
|
3178 return (FALSE); |
|
3179 return (xdr_u_int(xdrs, &objp->callback_ident)); |
|
3180 } |
|
3181 |
|
3182 /* |
|
3183 * Optimized free case |
|
3184 */ |
|
3185 if (objp->client.id_val != NULL) |
|
3186 kmem_free(objp->client.id_val, objp->client.id_len); |
|
3187 (void) xdr_string(xdrs, &objp->callback.cb_location.r_netid, |
|
3188 NFS4_OPAQUE_LIMIT); |
|
3189 return (xdr_string(xdrs, &objp->callback.cb_location.r_addr, |
|
3190 NFS4_OPAQUE_LIMIT)); |
|
3191 } |
|
3192 |
|
3193 static bool_t |
|
3194 xdr_SETCLIENTID4res(XDR *xdrs, SETCLIENTID4res *objp) |
|
3195 { |
|
3196 if (xdrs->x_op != XDR_FREE) { |
|
3197 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
3198 return (FALSE); |
|
3199 switch (objp->status) { |
|
3200 case NFS4_OK: |
|
3201 if (!xdr_u_longlong_t(xdrs, |
|
3202 (u_longlong_t *)&objp->SETCLIENTID4res_u.resok4. |
|
3203 clientid)) |
|
3204 return (FALSE); |
|
3205 return (xdr_u_longlong_t(xdrs, |
|
3206 (u_longlong_t *)&objp->SETCLIENTID4res_u. |
|
3207 resok4.setclientid_confirm)); |
|
3208 case NFS4ERR_CLID_INUSE: |
|
3209 if (!xdr_string(xdrs, |
|
3210 &objp->SETCLIENTID4res_u.client_using. |
|
3211 r_netid, NFS4_OPAQUE_LIMIT)) |
|
3212 return (FALSE); |
|
3213 return (xdr_string(xdrs, |
|
3214 &objp->SETCLIENTID4res_u.client_using. |
|
3215 r_addr, NFS4_OPAQUE_LIMIT)); |
|
3216 } |
|
3217 return (TRUE); |
|
3218 } |
|
3219 |
|
3220 /* |
|
3221 * Optimized free case |
|
3222 */ |
|
3223 if (objp->status != NFS4ERR_CLID_INUSE) |
|
3224 return (TRUE); |
|
3225 |
|
3226 if (!xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_netid, |
|
3227 NFS4_OPAQUE_LIMIT)) |
|
3228 return (FALSE); |
|
3229 return (xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_addr, |
|
3230 NFS4_OPAQUE_LIMIT)); |
|
3231 } |
|
3232 |
|
3233 static bool_t |
|
3234 xdr_WRITE4args(XDR *xdrs, WRITE4args *objp) |
|
3235 { |
|
3236 if (xdrs->x_op != XDR_FREE) { |
|
3237 if (!xdr_u_int(xdrs, &objp->stateid.seqid)) |
|
3238 return (FALSE); |
|
3239 if (!xdr_opaque(xdrs, objp->stateid.other, 12)) |
|
3240 return (FALSE); |
|
3241 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset)) |
|
3242 return (FALSE); |
|
3243 if (!xdr_int(xdrs, (int *)&objp->stable)) |
|
3244 return (FALSE); |
|
3245 if (xdrs->x_op == XDR_DECODE) { |
|
3246 if (xdrs->x_ops == &xdrmblk_ops) { |
|
3247 objp->data_val = NULL; |
|
3248 return (xdrmblk_getmblk(xdrs, &objp->mblk, |
|
3249 &objp->data_len)); |
|
3250 } |
|
3251 /* Else fall thru for the xdr_bytes(). */ |
|
3252 objp->mblk = NULL; |
|
3253 } |
|
3254 return (xdr_bytes(xdrs, (char **)&objp->data_val, |
|
3255 (uint_t *)&objp->data_len, NFS4_DATA_LIMIT)); |
|
3256 } |
|
3257 |
|
3258 /* |
|
3259 * Optimized free case |
|
3260 */ |
|
3261 if (objp->data_val != NULL) |
|
3262 kmem_free(objp->data_val, objp->data_len); |
|
3263 return (TRUE); |
|
3264 } |
|
3265 |
|
3266 static bool_t |
|
3267 xdr_WRITE4res(XDR *xdrs, WRITE4res *objp) |
|
3268 { |
|
3269 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
3270 return (FALSE); |
|
3271 if (objp->status != NFS4_OK) |
|
3272 return (TRUE); |
|
3273 if (!xdr_u_int(xdrs, &objp->count)) |
|
3274 return (FALSE); |
|
3275 if (!xdr_int(xdrs, (int *)&objp->committed)) |
|
3276 return (FALSE); |
|
3277 return (xdr_u_longlong_t(xdrs, |
|
3278 (u_longlong_t *)&objp->writeverf)); |
|
3279 } |
|
3280 |
|
3281 static bool_t |
|
3282 xdr_nfs_argop4_free(XDR *xdrs, nfs_argop4 **arrayp, int len) |
|
3283 { |
|
3284 int i; |
|
3285 nfs_argop4 *array = *arrayp; |
|
3286 |
|
3287 /* |
|
3288 * Optimized XDR_FREE only args array |
|
3289 */ |
|
3290 ASSERT(xdrs->x_op == XDR_FREE); |
|
3291 |
|
3292 /* |
|
3293 * Nothing to do? |
|
3294 */ |
|
3295 if (array == NULL) |
|
3296 return (TRUE); |
|
3297 |
|
3298 for (i = 0; i < len; i++) { |
|
3299 /* |
|
3300 * These should be ordered by frequency of use |
|
3301 */ |
|
3302 switch (array[i].argop) { |
|
3303 case OP_PUTFH: |
|
3304 if (array[i].nfs_argop4_u.opputfh.object.nfs_fh4_val != |
|
3305 NULL) { |
|
3306 kmem_free(array[i].nfs_argop4_u.opputfh.object. |
|
3307 nfs_fh4_val, |
|
3308 array[i].nfs_argop4_u.opputfh.object. |
|
3309 nfs_fh4_len); |
|
3310 } |
|
3311 continue; |
|
3312 case OP_GETATTR: |
|
3313 case OP_GETFH: |
|
3314 continue; |
|
3315 case OP_LOOKUP: |
|
3316 if (array[i].nfs_argop4_u.oplookup.objname. |
|
3317 utf8string_val != NULL) { |
|
3318 kmem_free(array[i].nfs_argop4_u.oplookup. |
|
3319 objname.utf8string_val, |
|
3320 array[i].nfs_argop4_u.oplookup. |
|
3321 objname.utf8string_len); |
|
3322 } |
|
3323 continue; |
|
3324 case OP_OPEN: |
|
3325 (void) xdr_OPEN4args(xdrs, |
|
3326 &array[i].nfs_argop4_u.opopen); |
|
3327 continue; |
|
3328 case OP_CLOSE: |
|
3329 case OP_ACCESS: |
|
3330 case OP_READ: |
|
3331 continue; |
|
3332 case OP_WRITE: |
|
3333 (void) xdr_WRITE4args(xdrs, |
|
3334 &array[i].nfs_argop4_u.opwrite); |
|
3335 continue; |
|
3336 case OP_DELEGRETURN: |
|
3337 case OP_LOOKUPP: |
|
3338 case OP_READDIR: |
|
3339 continue; |
|
3340 case OP_REMOVE: |
|
3341 if (array[i].nfs_argop4_u.opremove.target. |
|
3342 utf8string_val != NULL) { |
|
3343 kmem_free(array[i].nfs_argop4_u.opremove.target. |
|
3344 utf8string_val, |
|
3345 array[i].nfs_argop4_u.opremove.target. |
|
3346 utf8string_len); |
|
3347 } |
|
3348 continue; |
|
3349 case OP_COMMIT: |
|
3350 continue; |
|
3351 case OP_CREATE: |
|
3352 (void) xdr_CREATE4args(xdrs, |
|
3353 &array[i].nfs_argop4_u.opcreate); |
|
3354 continue; |
|
3355 case OP_DELEGPURGE: |
|
3356 continue; |
|
3357 case OP_LINK: |
|
3358 if (array[i].nfs_argop4_u.oplink.newname. |
|
3359 utf8string_val != NULL) { |
|
3360 kmem_free(array[i].nfs_argop4_u.oplink.newname. |
|
3361 utf8string_val, |
|
3362 array[i].nfs_argop4_u.oplink.newname. |
|
3363 utf8string_len); |
|
3364 } |
|
3365 continue; |
|
3366 case OP_LOCK: |
|
3367 (void) xdr_LOCK4args(xdrs, |
|
3368 &array[i].nfs_argop4_u.oplock); |
|
3369 continue; |
|
3370 case OP_LOCKT: |
|
3371 (void) xdr_LOCKT4args(xdrs, |
|
3372 &array[i].nfs_argop4_u.oplockt); |
|
3373 continue; |
|
3374 case OP_LOCKU: |
|
3375 continue; |
|
3376 case OP_NVERIFY: |
|
3377 (void) xdr_fattr4(xdrs, |
|
3378 &array[i].nfs_argop4_u.opnverify.obj_attributes); |
|
3379 continue; |
|
3380 case OP_OPENATTR: |
|
3381 case OP_OPEN_CONFIRM: |
|
3382 case OP_OPEN_DOWNGRADE: |
|
3383 case OP_PUTPUBFH: |
|
3384 case OP_PUTROOTFH: |
|
3385 case OP_READLINK: |
|
3386 continue; |
|
3387 case OP_RENAME: |
|
3388 if (array[i].nfs_argop4_u.oprename.oldname. |
|
3389 utf8string_val != NULL) { |
|
3390 kmem_free(array[i].nfs_argop4_u.oprename. |
|
3391 oldname.utf8string_val, |
|
3392 array[i].nfs_argop4_u.oprename. |
|
3393 oldname.utf8string_len); |
|
3394 } |
|
3395 if (array[i].nfs_argop4_u.oprename.newname. |
|
3396 utf8string_val != NULL) { |
|
3397 kmem_free(array[i].nfs_argop4_u.oprename. |
|
3398 newname.utf8string_val, |
|
3399 array[i].nfs_argop4_u.oprename. |
|
3400 newname.utf8string_len); |
|
3401 } |
|
3402 continue; |
|
3403 case OP_RENEW: |
|
3404 case OP_RESTOREFH: |
|
3405 case OP_SAVEFH: |
|
3406 continue; |
|
3407 case OP_SECINFO: |
|
3408 if (array[i].nfs_argop4_u.opsecinfo.name. |
|
3409 utf8string_val != NULL) { |
|
3410 kmem_free(array[i].nfs_argop4_u.opsecinfo.name. |
|
3411 utf8string_val, |
|
3412 array[i].nfs_argop4_u.opsecinfo.name. |
|
3413 utf8string_len); |
|
3414 } |
|
3415 continue; |
|
3416 case OP_SETATTR: |
|
3417 (void) xdr_fattr4(xdrs, |
|
3418 &array[i].nfs_argop4_u.opsetattr.obj_attributes); |
|
3419 continue; |
|
3420 case OP_SETCLIENTID: |
|
3421 (void) xdr_SETCLIENTID4args(xdrs, |
|
3422 &array[i].nfs_argop4_u.opsetclientid); |
|
3423 continue; |
|
3424 case OP_SETCLIENTID_CONFIRM: |
|
3425 continue; |
|
3426 case OP_VERIFY: |
|
3427 (void) xdr_fattr4(xdrs, |
|
3428 &array[i].nfs_argop4_u.opverify.obj_attributes); |
|
3429 continue; |
|
3430 case OP_RELEASE_LOCKOWNER: |
|
3431 if (array[i].nfs_argop4_u.oprelease_lockowner. |
|
3432 lock_owner.owner_val != NULL) { |
|
3433 kmem_free(array[i].nfs_argop4_u. |
|
3434 oprelease_lockowner.lock_owner.owner_val, |
|
3435 array[i].nfs_argop4_u. |
|
3436 oprelease_lockowner.lock_owner.owner_len); |
|
3437 } |
|
3438 continue; |
|
3439 case OP_ILLEGAL: |
|
3440 continue; |
|
3441 default: |
|
3442 /* |
|
3443 * An invalid op is a coding error, it should never |
|
3444 * have been decoded. |
|
3445 * Don't error because the caller cannot finish |
|
3446 * freeing the residual memory of the array. |
|
3447 */ |
|
3448 continue; |
|
3449 } |
|
3450 } |
|
3451 |
|
3452 kmem_free(*arrayp, len * sizeof (nfs_argop4)); |
|
3453 *arrayp = NULL; |
|
3454 return (TRUE); |
|
3455 } |
|
3456 |
|
3457 static bool_t |
|
3458 xdr_nfs_argop4(XDR *xdrs, nfs_argop4 *objp) |
|
3459 { |
|
3460 if (!xdr_int(xdrs, (int *)&objp->argop)) |
|
3461 return (FALSE); |
|
3462 |
|
3463 /* |
|
3464 * These should be ordered by frequency of use |
|
3465 */ |
|
3466 switch (objp->argop) { |
|
3467 case OP_PUTFH: |
|
3468 return (xdr_bytes(xdrs, |
|
3469 (char **)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_val, |
|
3470 (uint_t *)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_len, |
|
3471 NFS4_FHSIZE)); |
|
3472 case OP_GETATTR: |
|
3473 return (xdr_bitmap4(xdrs, |
|
3474 &objp->nfs_argop4_u.opgetattr.attr_request)); |
|
3475 case OP_GETFH: |
|
3476 return (TRUE); |
|
3477 case OP_LOOKUP: |
|
3478 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oplookup. |
|
3479 objname.utf8string_val, |
|
3480 (uint_t *)&objp->nfs_argop4_u.oplookup. |
|
3481 objname.utf8string_len, |
|
3482 NFS4_MAX_UTF8STRING)); |
|
3483 case OP_OPEN: |
|
3484 return (xdr_OPEN4args(xdrs, &objp->nfs_argop4_u.opopen)); |
|
3485 case OP_CLOSE: |
|
3486 return (xdr_CLOSE4args(xdrs, &objp->nfs_argop4_u.opclose)); |
|
3487 case OP_ACCESS: |
|
3488 return (xdr_u_int(xdrs, |
|
3489 &objp->nfs_argop4_u.opaccess.access)); |
|
3490 case OP_READ: |
|
3491 return (xdr_READ4args(xdrs, &objp->nfs_argop4_u.opread)); |
|
3492 case OP_WRITE: |
|
3493 return (xdr_WRITE4args(xdrs, &objp->nfs_argop4_u.opwrite)); |
|
3494 case OP_DELEGRETURN: |
|
3495 if (!xdr_u_int(xdrs, |
|
3496 &objp->nfs_argop4_u.opdelegreturn.deleg_stateid.seqid)) |
|
3497 return (FALSE); |
|
3498 return (xdr_opaque(xdrs, |
|
3499 objp->nfs_argop4_u.opdelegreturn.deleg_stateid.other, 12)); |
|
3500 case OP_LOOKUPP: |
|
3501 return (TRUE); |
|
3502 case OP_READDIR: |
|
3503 return (xdr_READDIR4args(xdrs, &objp->nfs_argop4_u.opreaddir)); |
|
3504 case OP_REMOVE: |
|
3505 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.opremove. |
|
3506 target.utf8string_val, |
|
3507 (uint_t *)&objp->nfs_argop4_u.opremove. |
|
3508 target.utf8string_len, |
|
3509 NFS4_MAX_UTF8STRING)); |
|
3510 case OP_COMMIT: |
|
3511 if (!xdr_u_longlong_t(xdrs, |
|
3512 (u_longlong_t *)&objp->nfs_argop4_u.opcommit.offset)) |
|
3513 return (FALSE); |
|
3514 return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opcommit.count)); |
|
3515 case OP_CREATE: |
|
3516 return (xdr_CREATE4args(xdrs, &objp->nfs_argop4_u.opcreate)); |
|
3517 case OP_DELEGPURGE: |
|
3518 return (xdr_u_longlong_t(xdrs, |
|
3519 (u_longlong_t *)&objp->nfs_argop4_u.opdelegpurge.clientid)); |
|
3520 case OP_LINK: |
|
3521 return (xdr_bytes(xdrs, |
|
3522 (char **)&objp->nfs_argop4_u.oplink.newname.utf8string_val, |
|
3523 (uint_t *)&objp->nfs_argop4_u.oplink.newname.utf8string_len, |
|
3524 NFS4_MAX_UTF8STRING)); |
|
3525 case OP_LOCK: |
|
3526 return (xdr_LOCK4args(xdrs, &objp->nfs_argop4_u.oplock)); |
|
3527 case OP_LOCKT: |
|
3528 return (xdr_LOCKT4args(xdrs, &objp->nfs_argop4_u.oplockt)); |
|
3529 case OP_LOCKU: |
|
3530 return (xdr_LOCKU4args(xdrs, &objp->nfs_argop4_u.oplocku)); |
|
3531 case OP_NVERIFY: |
|
3532 return (xdr_fattr4(xdrs, |
|
3533 &objp->nfs_argop4_u.opnverify.obj_attributes)); |
|
3534 case OP_OPENATTR: |
|
3535 return (xdr_bool(xdrs, |
|
3536 &objp->nfs_argop4_u.opopenattr.createdir)); |
|
3537 case OP_OPEN_CONFIRM: |
|
3538 if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm. |
|
3539 open_stateid.seqid)) |
|
3540 return (FALSE); |
|
3541 if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opopen_confirm. |
|
3542 open_stateid.other, 12)) |
|
3543 return (FALSE); |
|
3544 return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm. |
|
3545 seqid)); |
|
3546 case OP_OPEN_DOWNGRADE: |
|
3547 return (xdr_OPEN_DOWNGRADE4args(xdrs, |
|
3548 &objp->nfs_argop4_u.opopen_downgrade)); |
|
3549 case OP_PUTPUBFH: |
|
3550 return (TRUE); |
|
3551 case OP_PUTROOTFH: |
|
3552 return (TRUE); |
|
3553 case OP_READLINK: |
|
3554 return (TRUE); |
|
3555 case OP_RENAME: |
|
3556 if (!xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename. |
|
3557 oldname.utf8string_val, |
|
3558 (uint_t *)&objp->nfs_argop4_u.oprename. |
|
3559 oldname.utf8string_len, |
|
3560 NFS4_MAX_UTF8STRING)) |
|
3561 return (FALSE); |
|
3562 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename. |
|
3563 newname.utf8string_val, |
|
3564 (uint_t *)&objp->nfs_argop4_u.oprename. |
|
3565 newname.utf8string_len, |
|
3566 NFS4_MAX_UTF8STRING)); |
|
3567 case OP_RENEW: |
|
3568 return (xdr_u_longlong_t(xdrs, |
|
3569 (u_longlong_t *)&objp->nfs_argop4_u.oprenew.clientid)); |
|
3570 case OP_RESTOREFH: |
|
3571 return (TRUE); |
|
3572 case OP_SAVEFH: |
|
3573 return (TRUE); |
|
3574 case OP_SECINFO: |
|
3575 return (xdr_bytes(xdrs, |
|
3576 (char **)&objp->nfs_argop4_u.opsecinfo.name.utf8string_val, |
|
3577 (uint_t *)&objp->nfs_argop4_u.opsecinfo.name.utf8string_len, |
|
3578 NFS4_MAX_UTF8STRING)); |
|
3579 case OP_SETATTR: |
|
3580 if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opsetattr. |
|
3581 stateid.seqid)) |
|
3582 return (FALSE); |
|
3583 if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opsetattr. |
|
3584 stateid.other, 12)) |
|
3585 return (FALSE); |
|
3586 return (xdr_fattr4(xdrs, &objp->nfs_argop4_u.opsetattr. |
|
3587 obj_attributes)); |
|
3588 case OP_SETCLIENTID: |
|
3589 return (xdr_SETCLIENTID4args(xdrs, |
|
3590 &objp->nfs_argop4_u.opsetclientid)); |
|
3591 case OP_SETCLIENTID_CONFIRM: |
|
3592 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->nfs_argop4_u. |
|
3593 opsetclientid_confirm.clientid)) |
|
3594 return (FALSE); |
|
3595 return (xdr_u_longlong_t(xdrs, |
|
3596 (u_longlong_t *)&objp->nfs_argop4_u. |
|
3597 opsetclientid_confirm.setclientid_confirm)); |
|
3598 case OP_VERIFY: |
|
3599 return (xdr_fattr4(xdrs, |
|
3600 &objp->nfs_argop4_u.opverify.obj_attributes)); |
|
3601 case OP_RELEASE_LOCKOWNER: |
|
3602 if (!xdr_u_longlong_t(xdrs, |
|
3603 (u_longlong_t *)&objp->nfs_argop4_u. |
|
3604 oprelease_lockowner.lock_owner.clientid)) |
|
3605 return (FALSE); |
|
3606 return (xdr_bytes(xdrs, |
|
3607 (char **)&objp->nfs_argop4_u.oprelease_lockowner. |
|
3608 lock_owner.owner_val, |
|
3609 (uint_t *)&objp->nfs_argop4_u.oprelease_lockowner. |
|
3610 lock_owner.owner_len, NFS4_OPAQUE_LIMIT)); |
|
3611 case OP_ILLEGAL: |
|
3612 return (TRUE); |
|
3613 } |
|
3614 return (FALSE); |
|
3615 } |
|
3616 |
|
3617 /* |
|
3618 * Client side encode only arg op processing |
|
3619 */ |
|
3620 static bool_t |
|
3621 xdr_cnfs_argop4(XDR *xdrs, nfs_argop4 *objp) |
|
3622 { |
|
3623 int len; |
|
3624 int op; |
|
3625 nfs4_sharedfh_t *sfh; |
|
3626 mntinfo4_t *mi; |
|
3627 rpc_inline_t *ptr; |
|
3628 |
|
3629 ASSERT(xdrs->x_op == XDR_ENCODE); |
|
3630 |
|
3631 /* |
|
3632 * Special case the private pseudo ops |
|
3633 */ |
|
3634 if (!(objp->argop & SUNW_PRIVATE_OP)) |
|
3635 return (xdr_nfs_argop4(xdrs, objp)); |
|
3636 |
|
3637 /* |
|
3638 * These should be ordered by frequency of use |
|
3639 */ |
|
3640 switch (objp->argop) { |
|
3641 case OP_CPUTFH: |
|
3642 /* |
|
3643 * We are passed in the file handle as a nfs4_sharedfh_t * |
|
3644 * We need to acquire the correct locks so we can copy it out. |
|
3645 */ |
|
3646 sfh = (nfs4_sharedfh_t *)objp->nfs_argop4_u.opcputfh.sfh; |
|
3647 mi = sfh->sfh_mi; |
|
3648 (void) nfs_rw_enter_sig(&mi->mi_fh_lock, RW_READER, 0); |
|
3649 |
|
3650 len = sfh->sfh_fh.nfs_fh4_len; |
|
3651 ASSERT(len <= NFS4_FHSIZE); |
|
3652 |
|
3653 /* |
|
3654 * First try and inline the copy |
|
3655 * Must first be a multiple of BYTES_PER_XDR_UNIT |
|
3656 */ |
|
3657 if (!(len % BYTES_PER_XDR_UNIT) && |
|
3658 (ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + len)) != |
|
3659 NULL) { |
|
3660 IXDR_PUT_U_INT32(ptr, OP_PUTFH); |
|
3661 IXDR_PUT_U_INT32(ptr, len); |
|
3662 bcopy(sfh->sfh_fh.nfs_fh4_val, ptr, len); |
|
3663 nfs_rw_exit(&mi->mi_fh_lock); |
|
3664 return (TRUE); |
|
3665 } |
|
3666 |
|
3667 op = OP_PUTFH; |
|
3668 if (!XDR_PUTINT32(xdrs, &op)) { |
|
3669 nfs_rw_exit(&mi->mi_fh_lock); |
|
3670 return (FALSE); |
|
3671 } |
|
3672 if (!XDR_PUTINT32(xdrs, &len)) { |
|
3673 nfs_rw_exit(&mi->mi_fh_lock); |
|
3674 return (FALSE); |
|
3675 } |
|
3676 if (!(len % BYTES_PER_XDR_UNIT)) { |
|
3677 if (XDR_PUTBYTES(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) { |
|
3678 nfs_rw_exit(&mi->mi_fh_lock); |
|
3679 return (TRUE); |
|
3680 } |
|
3681 } else if (xdr_opaque(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) { |
|
3682 nfs_rw_exit(&mi->mi_fh_lock); |
|
3683 return (TRUE); |
|
3684 } |
|
3685 nfs_rw_exit(&mi->mi_fh_lock); |
|
3686 return (FALSE); |
|
3687 case OP_CLOOKUP: |
|
3688 len = strlen(objp->nfs_argop4_u.opclookup.cname); |
|
3689 if (len > NFS4_MAX_UTF8STRING) |
|
3690 return (FALSE); |
|
3691 op = OP_LOOKUP; |
|
3692 if (XDR_PUTINT32(xdrs, &op)) { |
|
3693 if (XDR_PUTINT32(xdrs, &len)) { |
|
3694 return (xdr_opaque(xdrs, |
|
3695 objp->nfs_argop4_u.opclookup.cname, |
|
3696 len)); |
|
3697 } |
|
3698 } |
|
3699 return (FALSE); |
|
3700 case OP_COPEN: |
|
3701 /* op processing inlined in xdr_OPEN4cargs */ |
|
3702 return (xdr_OPEN4cargs(xdrs, &objp->nfs_argop4_u.opcopen)); |
|
3703 case OP_CREMOVE: |
|
3704 len = strlen(objp->nfs_argop4_u.opcremove.ctarget); |
|
3705 if (len > NFS4_MAX_UTF8STRING) |
|
3706 return (FALSE); |
|
3707 op = OP_REMOVE; |
|
3708 if (XDR_PUTINT32(xdrs, &op)) { |
|
3709 if (XDR_PUTINT32(xdrs, &len)) { |
|
3710 return (xdr_opaque(xdrs, |
|
3711 objp->nfs_argop4_u.opcremove.ctarget, |
|
3712 len)); |
|
3713 } |
|
3714 } |
|
3715 return (FALSE); |
|
3716 case OP_CCREATE: |
|
3717 op = OP_CREATE; |
|
3718 if (!XDR_PUTINT32(xdrs, &op)) |
|
3719 return (FALSE); |
|
3720 return (xdr_CREATE4cargs(xdrs, &objp->nfs_argop4_u.opccreate)); |
|
3721 case OP_CLINK: |
|
3722 len = strlen(objp->nfs_argop4_u.opclink.cnewname); |
|
3723 if (len > NFS4_MAX_UTF8STRING) |
|
3724 return (FALSE); |
|
3725 op = OP_LINK; |
|
3726 if (XDR_PUTINT32(xdrs, &op)) { |
|
3727 if (XDR_PUTINT32(xdrs, &len)) { |
|
3728 return (xdr_opaque(xdrs, |
|
3729 objp->nfs_argop4_u.opclink.cnewname, |
|
3730 len)); |
|
3731 } |
|
3732 } |
|
3733 return (FALSE); |
|
3734 case OP_CRENAME: |
|
3735 len = strlen(objp->nfs_argop4_u.opcrename.coldname); |
|
3736 if (len > NFS4_MAX_UTF8STRING) |
|
3737 return (FALSE); |
|
3738 op = OP_RENAME; |
|
3739 if (!XDR_PUTINT32(xdrs, &op)) |
|
3740 return (FALSE); |
|
3741 if (!XDR_PUTINT32(xdrs, &len)) |
|
3742 return (FALSE); |
|
3743 if (!xdr_opaque(xdrs, |
|
3744 objp->nfs_argop4_u.opcrename.coldname, len)) |
|
3745 return (FALSE); |
|
3746 len = strlen(objp->nfs_argop4_u.opcrename.cnewname); |
|
3747 if (len > NFS4_MAX_UTF8STRING) |
|
3748 return (FALSE); |
|
3749 if (XDR_PUTINT32(xdrs, &len)) { |
|
3750 return (xdr_opaque(xdrs, |
|
3751 objp->nfs_argop4_u.opcrename.cnewname, len)); |
|
3752 } |
|
3753 return (FALSE); |
|
3754 case OP_CSECINFO: |
|
3755 len = strlen(objp->nfs_argop4_u.opcsecinfo.cname); |
|
3756 if (len > NFS4_MAX_UTF8STRING) |
|
3757 return (FALSE); |
|
3758 op = OP_SECINFO; |
|
3759 if (XDR_PUTINT32(xdrs, &op)) { |
|
3760 if (XDR_PUTINT32(xdrs, &len)) { |
|
3761 return (xdr_opaque(xdrs, |
|
3762 objp->nfs_argop4_u.opcsecinfo.cname, |
|
3763 len)); |
|
3764 } |
|
3765 } |
|
3766 return (FALSE); |
|
3767 } |
|
3768 return (FALSE); |
|
3769 } |
|
3770 |
|
3771 /* |
|
3772 * Note that the len and decode_len will only be different in the case |
|
3773 * of the client's use of this free function. If the server is |
|
3774 * freeing results, then the len/decode_len will always match. |
|
3775 */ |
|
3776 static bool_t |
|
3777 xdr_nfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len) |
|
3778 { |
|
3779 int i; |
|
3780 nfs_resop4 *array = *arrayp; |
|
3781 |
|
3782 /* |
|
3783 * Optimized XDR_FREE only results array |
|
3784 */ |
|
3785 ASSERT(xdrs->x_op == XDR_FREE); |
|
3786 |
|
3787 if (array == NULL) |
|
3788 return (TRUE); |
|
3789 |
|
3790 for (i = 0; i < decode_len; i++) { |
|
3791 /* |
|
3792 * These should be ordered by frequency of use |
|
3793 */ |
|
3794 switch (array[i].resop) { |
|
3795 case OP_PUTFH: |
|
3796 continue; |
|
3797 case OP_GETATTR: |
|
3798 if (array[i].nfs_resop4_u.opgetattr.status != NFS4_OK) |
|
3799 continue; |
|
3800 if (array[i].nfs_resop4_u.opgetattr.ga_res.n4g_ext_res) |
|
3801 kmem_free(array[i].nfs_resop4_u.opgetattr. |
|
3802 ga_res.n4g_ext_res, |
|
3803 sizeof (struct nfs4_ga_ext_res)); |
|
3804 continue; |
|
3805 case OP_GETFH: |
|
3806 if (array[i].nfs_resop4_u.opgetfh.status != NFS4_OK) |
|
3807 continue; |
|
3808 if (array[i].nfs_resop4_u.opgetfh.object.nfs_fh4_val != |
|
3809 NULL) { |
|
3810 kmem_free(array[i].nfs_resop4_u.opgetfh.object. |
|
3811 nfs_fh4_val, |
|
3812 array[i].nfs_resop4_u.opgetfh.object. |
|
3813 nfs_fh4_len); |
|
3814 } |
|
3815 continue; |
|
3816 case OP_LOOKUP: |
|
3817 continue; |
|
3818 case OP_OPEN: |
|
3819 (void) xdr_OPEN4res(xdrs, &array[i].nfs_resop4_u. |
|
3820 opopen); |
|
3821 continue; |
|
3822 case OP_CLOSE: |
|
3823 case OP_ACCESS: |
|
3824 continue; |
|
3825 case OP_READ: |
|
3826 (void) xdr_READ4res(xdrs, |
|
3827 &array[i].nfs_resop4_u. |
|
3828 opread); |
|
3829 continue; |
|
3830 case OP_WRITE: |
|
3831 case OP_DELEGRETURN: |
|
3832 case OP_LOOKUPP: |
|
3833 case OP_READDIR: |
|
3834 case OP_REMOVE: |
|
3835 case OP_COMMIT: |
|
3836 case OP_CREATE: |
|
3837 case OP_DELEGPURGE: |
|
3838 case OP_LINK: |
|
3839 continue; |
|
3840 case OP_LOCK: |
|
3841 (void) xdr_LOCK4res(xdrs, &array[i].nfs_resop4_u. |
|
3842 oplock); |
|
3843 continue; |
|
3844 case OP_LOCKT: |
|
3845 (void) xdr_LOCKT4res(xdrs, &array[i].nfs_resop4_u. |
|
3846 oplockt); |
|
3847 continue; |
|
3848 case OP_LOCKU: |
|
3849 case OP_NVERIFY: |
|
3850 case OP_OPENATTR: |
|
3851 case OP_OPEN_CONFIRM: |
|
3852 case OP_OPEN_DOWNGRADE: |
|
3853 case OP_PUTPUBFH: |
|
3854 case OP_PUTROOTFH: |
|
3855 case OP_RENAME: |
|
3856 case OP_RENEW: |
|
3857 case OP_RESTOREFH: |
|
3858 case OP_SAVEFH: |
|
3859 continue; |
|
3860 case OP_READLINK: |
|
3861 (void) xdr_READLINK4res(xdrs, &array[i].nfs_resop4_u. |
|
3862 opreadlink); |
|
3863 continue; |
|
3864 case OP_SECINFO: |
|
3865 (void) xdr_array(xdrs, |
|
3866 (char **)&array[i].nfs_resop4_u.opsecinfo. |
|
3867 SECINFO4resok_val, |
|
3868 (uint_t *)&array[i].nfs_resop4_u.opsecinfo. |
|
3869 SECINFO4resok_len, |
|
3870 NFS4_SECINFO_LIMIT, sizeof (secinfo4), |
|
3871 (xdrproc_t)xdr_secinfo4); |
|
3872 continue; |
|
3873 case OP_SETCLIENTID: |
|
3874 (void) xdr_SETCLIENTID4res(xdrs, |
|
3875 &array[i].nfs_resop4_u.opsetclientid); |
|
3876 continue; |
|
3877 case OP_SETATTR: |
|
3878 case OP_SETCLIENTID_CONFIRM: |
|
3879 case OP_VERIFY: |
|
3880 case OP_RELEASE_LOCKOWNER: |
|
3881 case OP_ILLEGAL: |
|
3882 continue; |
|
3883 default: |
|
3884 /* |
|
3885 * An invalid op is a coding error, it should never |
|
3886 * have been decoded. |
|
3887 * Don't error because the caller cannot finish |
|
3888 * freeing the residual memory of the array. |
|
3889 */ |
|
3890 continue; |
|
3891 } |
|
3892 } |
|
3893 |
|
3894 kmem_free(*arrayp, len * sizeof (nfs_resop4)); |
|
3895 *arrayp = NULL; |
|
3896 return (TRUE); |
|
3897 } |
|
3898 |
|
3899 static bool_t |
|
3900 xdr_nfs_resop4(XDR *xdrs, nfs_resop4 *objp) |
|
3901 { |
|
3902 if (!xdr_int(xdrs, (int *)&objp->resop)) |
|
3903 return (FALSE); |
|
3904 /* |
|
3905 * These should be ordered by frequency of use |
|
3906 */ |
|
3907 switch (objp->resop) { |
|
3908 case OP_PUTFH: |
|
3909 return (xdr_int(xdrs, |
|
3910 (int32_t *)&objp->nfs_resop4_u.opputfh.status)); |
|
3911 case OP_GETATTR: |
|
3912 if (!xdr_int(xdrs, |
|
3913 (int32_t *)&objp->nfs_resop4_u.opgetattr.status)) |
|
3914 return (FALSE); |
|
3915 if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK) |
|
3916 return (TRUE); |
|
3917 return (xdr_fattr4(xdrs, |
|
3918 &objp->nfs_resop4_u.opgetattr.obj_attributes)); |
|
3919 case OP_GETFH: |
|
3920 if (!xdr_int(xdrs, |
|
3921 (int32_t *)&objp->nfs_resop4_u.opgetfh.status)) |
|
3922 return (FALSE); |
|
3923 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK) |
|
3924 return (TRUE); |
|
3925 return (xdr_bytes(xdrs, |
|
3926 (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val, |
|
3927 (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len, |
|
3928 NFS4_FHSIZE)); |
|
3929 case OP_LOOKUP: |
|
3930 return (xdr_int(xdrs, |
|
3931 (int32_t *)&objp->nfs_resop4_u.oplookup.status)); |
|
3932 case OP_OPEN: |
|
3933 return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen)); |
|
3934 case OP_CLOSE: |
|
3935 return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose)); |
|
3936 case OP_ACCESS: |
|
3937 return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess)); |
|
3938 case OP_READ: |
|
3939 return (xdr_READ4res(xdrs, &objp->nfs_resop4_u.opread)); |
|
3940 case OP_WRITE: |
|
3941 return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite)); |
|
3942 case OP_DELEGRETURN: |
|
3943 return (xdr_int(xdrs, |
|
3944 (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status)); |
|
3945 case OP_LOOKUPP: |
|
3946 return (xdr_int(xdrs, |
|
3947 (int32_t *)&objp->nfs_resop4_u.oplookupp.status)); |
|
3948 case OP_READDIR: |
|
3949 return (xdr_READDIR4res(xdrs, &objp->nfs_resop4_u.opreaddir)); |
|
3950 case OP_REMOVE: |
|
3951 return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove)); |
|
3952 |
|
3953 case OP_COMMIT: |
|
3954 if (!xdr_int(xdrs, |
|
3955 (int32_t *)&objp->nfs_resop4_u.opcommit.status)) |
|
3956 return (FALSE); |
|
3957 if (objp->nfs_resop4_u.opcommit.status != NFS4_OK) |
|
3958 return (TRUE); |
|
3959 return (xdr_u_longlong_t(xdrs, |
|
3960 (u_longlong_t *)&objp->nfs_resop4_u.opcommit. |
|
3961 writeverf)); |
|
3962 case OP_CREATE: |
|
3963 return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate)); |
|
3964 case OP_DELEGPURGE: |
|
3965 return (xdr_int(xdrs, |
|
3966 (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status)); |
|
3967 case OP_LINK: |
|
3968 return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink)); |
|
3969 case OP_LOCK: |
|
3970 return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock)); |
|
3971 case OP_LOCKT: |
|
3972 return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt)); |
|
3973 case OP_LOCKU: |
|
3974 if (!xdr_int(xdrs, |
|
3975 (int32_t *)&objp->nfs_resop4_u.oplocku.status)) |
|
3976 return (FALSE); |
|
3977 if (objp->nfs_resop4_u.oplocku.status != NFS4_OK) |
|
3978 return (TRUE); |
|
3979 if (!xdr_u_int(xdrs, |
|
3980 &objp->nfs_resop4_u.oplocku.lock_stateid.seqid)) |
|
3981 return (FALSE); |
|
3982 return (xdr_opaque(xdrs, |
|
3983 objp->nfs_resop4_u.oplocku.lock_stateid.other, |
|
3984 12)); |
|
3985 case OP_NVERIFY: |
|
3986 return (xdr_int(xdrs, |
|
3987 (int32_t *)&objp->nfs_resop4_u.opnverify.status)); |
|
3988 case OP_OPENATTR: |
|
3989 return (xdr_int(xdrs, |
|
3990 (int32_t *)&objp->nfs_resop4_u.opopenattr.status)); |
|
3991 case OP_OPEN_CONFIRM: |
|
3992 return (xdr_OPEN_CONFIRM4res(xdrs, |
|
3993 &objp->nfs_resop4_u.opopen_confirm)); |
|
3994 case OP_OPEN_DOWNGRADE: |
|
3995 return (xdr_OPEN_DOWNGRADE4res(xdrs, |
|
3996 &objp->nfs_resop4_u.opopen_downgrade)); |
|
3997 case OP_PUTPUBFH: |
|
3998 return (xdr_int(xdrs, |
|
3999 (int32_t *)&objp->nfs_resop4_u.opputpubfh.status)); |
|
4000 case OP_PUTROOTFH: |
|
4001 return (xdr_int(xdrs, |
|
4002 (int32_t *)&objp->nfs_resop4_u.opputrootfh.status)); |
|
4003 case OP_READLINK: |
|
4004 return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink)); |
|
4005 case OP_RENAME: |
|
4006 return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename)); |
|
4007 case OP_RENEW: |
|
4008 return (xdr_int(xdrs, |
|
4009 (int32_t *)&objp->nfs_resop4_u.oprenew.status)); |
|
4010 case OP_RESTOREFH: |
|
4011 return (xdr_int(xdrs, |
|
4012 (int32_t *)&objp->nfs_resop4_u.oprestorefh.status)); |
|
4013 case OP_SAVEFH: |
|
4014 return (xdr_int(xdrs, |
|
4015 (int32_t *)&objp->nfs_resop4_u.opsavefh.status)); |
|
4016 case OP_SECINFO: |
|
4017 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo. |
|
4018 status)) |
|
4019 return (FALSE); |
|
4020 if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK) |
|
4021 return (TRUE); |
|
4022 return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo. |
|
4023 SECINFO4resok_val, |
|
4024 (uint_t *)&objp->nfs_resop4_u.opsecinfo. |
|
4025 SECINFO4resok_len, |
|
4026 NFS4_SECINFO_LIMIT, sizeof (secinfo4), |
|
4027 (xdrproc_t)xdr_secinfo4)); |
|
4028 case OP_SETATTR: |
|
4029 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr. |
|
4030 status)) |
|
4031 return (FALSE); |
|
4032 return (xdr_bitmap4(xdrs, |
|
4033 &objp->nfs_resop4_u.opsetattr.attrsset)); |
|
4034 case OP_SETCLIENTID: |
|
4035 return (xdr_SETCLIENTID4res(xdrs, |
|
4036 &objp->nfs_resop4_u.opsetclientid)); |
|
4037 case OP_SETCLIENTID_CONFIRM: |
|
4038 return (xdr_int(xdrs, |
|
4039 (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm. |
|
4040 status)); |
|
4041 case OP_VERIFY: |
|
4042 return (xdr_int(xdrs, |
|
4043 (int32_t *)&objp->nfs_resop4_u.opverify.status)); |
|
4044 case OP_RELEASE_LOCKOWNER: |
|
4045 return (xdr_int(xdrs, |
|
4046 (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status)); |
|
4047 case OP_ILLEGAL: |
|
4048 return (xdr_int(xdrs, |
|
4049 (int32_t *)&objp->nfs_resop4_u.opillegal.status)); |
|
4050 } |
|
4051 return (FALSE); |
|
4052 } |
|
4053 |
|
4054 static bool_t |
|
4055 xdr_nfs_resop4_clnt(XDR *xdrs, nfs_resop4 *objp, nfs_argop4 *aobjp) |
|
4056 { |
|
4057 if (!xdr_int(xdrs, (int *)&objp->resop)) |
|
4058 return (FALSE); |
|
4059 /* |
|
4060 * These should be ordered by frequency of use |
|
4061 */ |
|
4062 switch (objp->resop) { |
|
4063 case OP_PUTFH: |
|
4064 return (xdr_int(xdrs, |
|
4065 (int32_t *)&objp->nfs_resop4_u.opputfh.status)); |
|
4066 case OP_GETATTR: |
|
4067 if (!xdr_int(xdrs, |
|
4068 (int32_t *)&objp->nfs_resop4_u.opgetattr.status)) |
|
4069 return (FALSE); |
|
4070 if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK) |
|
4071 return (TRUE); |
|
4072 return (xdr_ga_res(xdrs, |
|
4073 (GETATTR4res *)&objp->nfs_resop4_u.opgetattr, |
|
4074 &aobjp->nfs_argop4_u.opgetattr)); |
|
4075 case OP_GETFH: |
|
4076 if (!xdr_int(xdrs, |
|
4077 (int32_t *)&objp->nfs_resop4_u.opgetfh.status)) |
|
4078 return (FALSE); |
|
4079 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK) |
|
4080 return (TRUE); |
|
4081 return (xdr_bytes(xdrs, |
|
4082 (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val, |
|
4083 (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len, |
|
4084 NFS4_FHSIZE)); |
|
4085 case OP_LOOKUP: |
|
4086 return (xdr_int(xdrs, |
|
4087 (int32_t *)&objp->nfs_resop4_u.oplookup.status)); |
|
4088 case OP_NVERIFY: |
|
4089 return (xdr_int(xdrs, |
|
4090 (int32_t *)&objp->nfs_resop4_u.opnverify.status)); |
|
4091 case OP_OPEN: |
|
4092 return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen)); |
|
4093 case OP_CLOSE: |
|
4094 return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose)); |
|
4095 case OP_ACCESS: |
|
4096 return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess)); |
|
4097 case OP_READ: |
|
4098 return (xdr_READ4res_clnt(xdrs, &objp->nfs_resop4_u.opread, |
|
4099 &aobjp->nfs_argop4_u.opread)); |
|
4100 case OP_WRITE: |
|
4101 return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite)); |
|
4102 case OP_DELEGRETURN: |
|
4103 return (xdr_int(xdrs, |
|
4104 (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status)); |
|
4105 case OP_LOOKUPP: |
|
4106 return (xdr_int(xdrs, |
|
4107 (int32_t *)&objp->nfs_resop4_u.oplookupp.status)); |
|
4108 case OP_READDIR: |
|
4109 return (xdr_READDIR4res_clnt(xdrs, |
|
4110 &objp->nfs_resop4_u.opreaddirclnt, |
|
4111 &aobjp->nfs_argop4_u.opreaddir)); |
|
4112 case OP_REMOVE: |
|
4113 return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove)); |
|
4114 |
|
4115 case OP_COMMIT: |
|
4116 if (!xdr_int(xdrs, |
|
4117 (int32_t *)&objp->nfs_resop4_u.opcommit.status)) |
|
4118 return (FALSE); |
|
4119 if (objp->nfs_resop4_u.opcommit.status != NFS4_OK) |
|
4120 return (TRUE); |
|
4121 return (xdr_u_longlong_t(xdrs, |
|
4122 (u_longlong_t *)&objp->nfs_resop4_u.opcommit. |
|
4123 writeverf)); |
|
4124 case OP_CREATE: |
|
4125 return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate)); |
|
4126 case OP_DELEGPURGE: |
|
4127 return (xdr_int(xdrs, |
|
4128 (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status)); |
|
4129 case OP_LINK: |
|
4130 return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink)); |
|
4131 case OP_LOCK: |
|
4132 return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock)); |
|
4133 case OP_LOCKT: |
|
4134 return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt)); |
|
4135 case OP_LOCKU: |
|
4136 if (!xdr_int(xdrs, |
|
4137 (int32_t *)&objp->nfs_resop4_u.oplocku.status)) |
|
4138 return (FALSE); |
|
4139 if (objp->nfs_resop4_u.oplocku.status != NFS4_OK) |
|
4140 return (TRUE); |
|
4141 if (!xdr_u_int(xdrs, |
|
4142 &objp->nfs_resop4_u.oplocku.lock_stateid.seqid)) |
|
4143 return (FALSE); |
|
4144 return (xdr_opaque(xdrs, |
|
4145 objp->nfs_resop4_u.oplocku.lock_stateid.other, |
|
4146 12)); |
|
4147 case OP_OPENATTR: |
|
4148 return (xdr_int(xdrs, |
|
4149 (int32_t *)&objp->nfs_resop4_u.opopenattr.status)); |
|
4150 case OP_OPEN_CONFIRM: |
|
4151 return (xdr_OPEN_CONFIRM4res(xdrs, |
|
4152 &objp->nfs_resop4_u.opopen_confirm)); |
|
4153 case OP_OPEN_DOWNGRADE: |
|
4154 return (xdr_OPEN_DOWNGRADE4res(xdrs, |
|
4155 &objp->nfs_resop4_u.opopen_downgrade)); |
|
4156 case OP_PUTPUBFH: |
|
4157 return (xdr_int(xdrs, |
|
4158 (int32_t *)&objp->nfs_resop4_u.opputpubfh.status)); |
|
4159 case OP_PUTROOTFH: |
|
4160 return (xdr_int(xdrs, |
|
4161 (int32_t *)&objp->nfs_resop4_u.opputrootfh.status)); |
|
4162 case OP_READLINK: |
|
4163 return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink)); |
|
4164 case OP_RENAME: |
|
4165 return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename)); |
|
4166 case OP_RENEW: |
|
4167 return (xdr_int(xdrs, |
|
4168 (int32_t *)&objp->nfs_resop4_u.oprenew.status)); |
|
4169 case OP_RESTOREFH: |
|
4170 return (xdr_int(xdrs, |
|
4171 (int32_t *)&objp->nfs_resop4_u.oprestorefh.status)); |
|
4172 case OP_SAVEFH: |
|
4173 return (xdr_int(xdrs, |
|
4174 (int32_t *)&objp->nfs_resop4_u.opsavefh.status)); |
|
4175 case OP_SECINFO: |
|
4176 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo. |
|
4177 status)) |
|
4178 return (FALSE); |
|
4179 if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK) |
|
4180 return (TRUE); |
|
4181 return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo. |
|
4182 SECINFO4resok_val, |
|
4183 (uint_t *)&objp->nfs_resop4_u.opsecinfo. |
|
4184 SECINFO4resok_len, |
|
4185 ~0, sizeof (secinfo4), (xdrproc_t)xdr_secinfo4)); |
|
4186 case OP_SETATTR: |
|
4187 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr. |
|
4188 status)) |
|
4189 return (FALSE); |
|
4190 return (xdr_bitmap4(xdrs, |
|
4191 &objp->nfs_resop4_u.opsetattr.attrsset)); |
|
4192 case OP_SETCLIENTID: |
|
4193 return (xdr_SETCLIENTID4res(xdrs, |
|
4194 &objp->nfs_resop4_u.opsetclientid)); |
|
4195 case OP_SETCLIENTID_CONFIRM: |
|
4196 return (xdr_int(xdrs, |
|
4197 (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm. |
|
4198 status)); |
|
4199 case OP_VERIFY: |
|
4200 return (xdr_int(xdrs, |
|
4201 (int32_t *)&objp->nfs_resop4_u.opverify.status)); |
|
4202 case OP_RELEASE_LOCKOWNER: |
|
4203 return (xdr_int(xdrs, |
|
4204 (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status)); |
|
4205 case OP_ILLEGAL: |
|
4206 return (xdr_int(xdrs, |
|
4207 (int32_t *)&objp->nfs_resop4_u.opillegal.status)); |
|
4208 } |
|
4209 return (FALSE); |
|
4210 } |
|
4211 |
|
4212 bool_t |
|
4213 xdr_COMPOUND4args_clnt(XDR *xdrs, COMPOUND4args_clnt *objp) |
|
4214 { |
|
4215 static int32_t twelve = 12; |
|
4216 static int32_t minorversion = NFS4_MINORVERSION; |
|
4217 uint32_t *ctagp; |
|
4218 rpc_inline_t *ptr; |
|
4219 |
|
4220 /* |
|
4221 * XDR_ENCODE only |
|
4222 */ |
|
4223 if (xdrs->x_op == XDR_FREE) |
|
4224 return (TRUE); |
|
4225 if (xdrs->x_op == XDR_DECODE) |
|
4226 return (FALSE); |
|
4227 |
|
4228 ctagp = (uint32_t *)&nfs4_ctags[objp->ctag].ct_tag; |
|
4229 |
|
4230 if ((ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT)) != NULL) { |
|
4231 /* |
|
4232 * Efficiently encode fixed length tags, could be longlongs |
|
4233 * but 8 byte XDR alignment not assured |
|
4234 */ |
|
4235 IXDR_PUT_U_INT32(ptr, 12); |
|
4236 IXDR_PUT_U_INT32(ptr, ctagp[0]); |
|
4237 IXDR_PUT_U_INT32(ptr, ctagp[1]); |
|
4238 IXDR_PUT_U_INT32(ptr, ctagp[2]); |
|
4239 |
|
4240 /* |
|
4241 * Fixed minor version for now |
|
4242 */ |
|
4243 IXDR_PUT_U_INT32(ptr, NFS4_MINORVERSION); |
|
4244 } else { |
|
4245 if (!XDR_PUTINT32(xdrs, &twelve)) |
|
4246 return (FALSE); |
|
4247 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[0])) |
|
4248 return (FALSE); |
|
4249 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[1])) |
|
4250 return (FALSE); |
|
4251 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[2])) |
|
4252 return (FALSE); |
|
4253 if (!XDR_PUTINT32(xdrs, (int32_t *)&minorversion)) |
|
4254 return (FALSE); |
|
4255 } |
|
4256 |
|
4257 return (xdr_array(xdrs, (char **)&objp->array, |
|
4258 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, |
|
4259 sizeof (nfs_argop4), (xdrproc_t)xdr_cnfs_argop4)); |
|
4260 } |
|
4261 |
|
4262 bool_t |
|
4263 xdr_COMPOUND4args(XDR *xdrs, COMPOUND4args *objp) |
|
4264 { |
|
4265 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, |
|
4266 (uint_t *)&objp->tag.utf8string_len, |
|
4267 NFS4_MAX_UTF8STRING)) |
|
4268 return (FALSE); |
|
4269 if (!xdr_u_int(xdrs, &objp->minorversion)) |
|
4270 return (FALSE); |
|
4271 if (xdrs->x_op != XDR_FREE) |
|
4272 return (xdr_array(xdrs, (char **)&objp->array, |
|
4273 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, |
|
4274 sizeof (nfs_argop4), (xdrproc_t)xdr_nfs_argop4)); |
|
4275 |
|
4276 return (xdr_nfs_argop4_free(xdrs, &objp->array, objp->array_len)); |
|
4277 } |
|
4278 |
|
4279 bool_t |
|
4280 xdr_COMPOUND4res_clnt(XDR *xdrs, COMPOUND4res_clnt *objp) |
|
4281 { |
|
4282 uint32_t len; |
|
4283 int32_t *ptr; |
|
4284 nfs_argop4 *argop; |
|
4285 nfs_resop4 *resop; |
|
4286 |
|
4287 /* |
|
4288 * No XDR_ENCODE |
|
4289 */ |
|
4290 if (xdrs->x_op == XDR_ENCODE) |
|
4291 return (FALSE); |
|
4292 |
|
4293 if (xdrs->x_op != XDR_FREE) { |
|
4294 if ((ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) { |
|
4295 objp->status = IXDR_GET_U_INT32(ptr); |
|
4296 len = IXDR_GET_U_INT32(ptr); |
|
4297 } else { |
|
4298 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
4299 return (FALSE); |
|
4300 if (!xdr_u_int(xdrs, (uint32_t *)&len)) |
|
4301 return (FALSE); |
|
4302 } |
|
4303 if (len > NFS4_MAX_UTF8STRING) |
|
4304 return (FALSE); |
|
4305 /* |
|
4306 * Ignore the tag |
|
4307 */ |
|
4308 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &len)) |
|
4309 return (FALSE); |
|
4310 |
|
4311 if (!xdr_int(xdrs, (int32_t *)&objp->array_len)) |
|
4312 return (FALSE); |
|
4313 |
|
4314 if (objp->array_len > objp->argsp->array_len) |
|
4315 return (FALSE); |
|
4316 |
|
4317 if (objp->status == NFS_OK && |
|
4318 objp->array_len != objp->argsp->array_len) |
|
4319 return (FALSE); |
|
4320 |
|
4321 /* Alloc the results array */ |
|
4322 argop = objp->argsp->array; |
|
4323 len = objp->array_len * sizeof (nfs_resop4); |
|
4324 objp->decode_len = 0; |
|
4325 objp->array = resop = kmem_zalloc(len, KM_SLEEP); |
|
4326 |
|
4327 for (len = 0; len < objp->array_len; |
|
4328 len++, resop++, argop++, objp->decode_len++) { |
|
4329 if (!xdr_nfs_resop4_clnt(xdrs, resop, argop)) { |
|
4330 /* |
|
4331 * Make sure to free anything that may |
|
4332 * have been allocated along the way. |
|
4333 */ |
|
4334 xdrs->x_op = XDR_FREE; |
|
4335 (void) xdr_nfs_resop4_free(xdrs, &objp->array, |
|
4336 objp->array_len, |
|
4337 objp->decode_len); |
|
4338 return (FALSE); |
|
4339 } |
|
4340 } |
|
4341 return (TRUE); |
|
4342 } |
|
4343 return (xdr_nfs_resop4_free(xdrs, &objp->array, |
|
4344 objp->array_len, objp->decode_len)); |
|
4345 } |
|
4346 |
|
4347 bool_t |
|
4348 xdr_COMPOUND4res(XDR *xdrs, COMPOUND4res *objp) |
|
4349 { |
|
4350 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
4351 return (FALSE); |
|
4352 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, |
|
4353 (uint_t *)&objp->tag.utf8string_len, |
|
4354 NFS4_MAX_UTF8STRING)) |
|
4355 return (FALSE); |
|
4356 |
|
4357 if (xdrs->x_op != XDR_FREE) |
|
4358 return (xdr_array(xdrs, (char **)&objp->array, |
|
4359 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, |
|
4360 sizeof (nfs_resop4), (xdrproc_t)xdr_nfs_resop4)); |
|
4361 |
|
4362 return (xdr_nfs_resop4_free(xdrs, &objp->array, |
|
4363 objp->array_len, objp->array_len)); |
|
4364 } |
|
4365 |
|
4366 static bool_t |
|
4367 xdr_nfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp) |
|
4368 { |
|
4369 if (!xdr_u_int(xdrs, &objp->argop)) |
|
4370 return (FALSE); |
|
4371 switch (objp->argop) { |
|
4372 case OP_CB_GETATTR: |
|
4373 if (!xdr_bytes(xdrs, |
|
4374 (char **)&objp->nfs_cb_argop4_u.opcbgetattr.fh.nfs_fh4_val, |
|
4375 (uint_t *)&objp->nfs_cb_argop4_u.opcbgetattr.fh.nfs_fh4_len, |
|
4376 NFS4_FHSIZE)) |
|
4377 return (FALSE); |
|
4378 return (xdr_bitmap4(xdrs, |
|
4379 &objp->nfs_cb_argop4_u.opcbgetattr.attr_request)); |
|
4380 case OP_CB_RECALL: |
|
4381 if (!xdr_u_int(xdrs, |
|
4382 &objp->nfs_cb_argop4_u.opcbrecall.stateid.seqid)) |
|
4383 return (FALSE); |
|
4384 if (!xdr_opaque(xdrs, |
|
4385 objp->nfs_cb_argop4_u.opcbrecall.stateid.other, |
|
4386 12)) |
|
4387 return (FALSE); |
|
4388 if (!xdr_bool(xdrs, |
|
4389 &objp->nfs_cb_argop4_u.opcbrecall.truncate)) |
|
4390 return (FALSE); |
|
4391 return (xdr_bytes(xdrs, |
|
4392 (char **)&objp->nfs_cb_argop4_u.opcbrecall.fh.nfs_fh4_val, |
|
4393 (uint_t *)&objp->nfs_cb_argop4_u.opcbrecall.fh.nfs_fh4_len, |
|
4394 NFS4_FHSIZE)); |
|
4395 case OP_CB_ILLEGAL: |
|
4396 return (TRUE); |
|
4397 } |
|
4398 return (FALSE); |
|
4399 } |
|
4400 |
|
4401 static bool_t |
|
4402 xdr_nfs_cb_resop4(XDR *xdrs, nfs_cb_resop4 *objp) |
|
4403 { |
|
4404 if (!xdr_u_int(xdrs, &objp->resop)) |
|
4405 return (FALSE); |
|
4406 switch (objp->resop) { |
|
4407 case OP_CB_GETATTR: |
|
4408 if (!xdr_int(xdrs, |
|
4409 (int32_t *)&objp->nfs_cb_resop4_u.opcbgetattr. |
|
4410 status)) |
|
4411 return (FALSE); |
|
4412 if (objp->nfs_cb_resop4_u.opcbgetattr.status != NFS4_OK) |
|
4413 return (TRUE); |
|
4414 return (xdr_fattr4(xdrs, |
|
4415 &objp->nfs_cb_resop4_u.opcbgetattr. |
|
4416 obj_attributes)); |
|
4417 case OP_CB_RECALL: |
|
4418 return (xdr_int(xdrs, |
|
4419 (int32_t *)&objp->nfs_cb_resop4_u.opcbrecall.status)); |
|
4420 case OP_CB_ILLEGAL: |
|
4421 return (xdr_int(xdrs, |
|
4422 (int32_t *)&objp->nfs_cb_resop4_u.opcbillegal.status)); |
|
4423 } |
|
4424 return (FALSE); |
|
4425 } |
|
4426 |
|
4427 bool_t |
|
4428 xdr_CB_COMPOUND4args(XDR *xdrs, CB_COMPOUND4args *objp) |
|
4429 { |
|
4430 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, |
|
4431 (uint_t *)&objp->tag.utf8string_len, |
|
4432 NFS4_MAX_UTF8STRING)) |
|
4433 return (FALSE); |
|
4434 if (!xdr_u_int(xdrs, &objp->minorversion)) |
|
4435 return (FALSE); |
|
4436 if (!xdr_u_int(xdrs, &objp->callback_ident)) |
|
4437 return (FALSE); |
|
4438 return (xdr_array(xdrs, (char **)&objp->array, |
|
4439 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, |
|
4440 sizeof (nfs_cb_argop4), (xdrproc_t)xdr_nfs_cb_argop4)); |
|
4441 } |
|
4442 |
|
4443 bool_t |
|
4444 xdr_CB_COMPOUND4res(XDR *xdrs, CB_COMPOUND4res *objp) |
|
4445 { |
|
4446 if (!xdr_int(xdrs, (int32_t *)&objp->status)) |
|
4447 return (FALSE); |
|
4448 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, |
|
4449 (uint_t *)&objp->tag.utf8string_len, |
|
4450 NFS4_MAX_UTF8STRING)) |
|
4451 return (FALSE); |
|
4452 return (xdr_array(xdrs, (char **)&objp->array, |
|
4453 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, |
|
4454 sizeof (nfs_cb_resop4), (xdrproc_t)xdr_nfs_cb_resop4)); |
|
4455 } |