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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/time.h>
27 #include <sys/systm.h>
28
29 #include <nfs/nfs.h>
30 #include <nfs/nfs4.h>
31 #include <nfs/rnode4.h>
32 #include <nfs/nfs4_clnt.h>
33 #include <sys/cmn_err.h>
34
35 static int
timestruc_to_settime4(timestruc_t * tt,settime4 * tt4,int flags)36 timestruc_to_settime4(timestruc_t *tt, settime4 *tt4, int flags)
37 {
38 int error = 0;
39
40 if (flags & ATTR_UTIME) {
41 tt4->set_it = SET_TO_CLIENT_TIME4;
42 error = nfs4_time_vton(tt, &tt4->time);
43 } else {
44 tt4->set_it = SET_TO_SERVER_TIME4;
45 }
46 return (error);
47 }
48
49
50 /*
51 * nfs4_ver_fattr4_attr translates a vattr attribute into a fattr4 attribute
52 * for use by nfsv4 verify. For setting atime or mtime use the entry for
53 * time_XX (XX == access or modify).
54 * Return TRUE if arg was set (even if there was an error) and FALSE
55 * otherwise. Also set error code. The caller should not continue
56 * if error was set, whether or not the return is TRUE or FALSE. Returning
57 * FALSE does not mean there was an error, only that the attr was not set.
58 *
59 * Note: For now we only have the options used by setattr. In the future
60 * the switch statement below should cover all vattr attrs and possibly
61 * sys attrs as well.
62 */
63 /* ARGSUSED */
64 static bool_t
nfs4_ver_fattr4_attr(vattr_t * vap,struct nfs4_ntov_map * ntovp,union nfs4_attr_u * nap,int flags,int * errorp)65 nfs4_ver_fattr4_attr(vattr_t *vap, struct nfs4_ntov_map *ntovp,
66 union nfs4_attr_u *nap, int flags, int *errorp)
67 {
68 bool_t retval = TRUE;
69
70 /*
71 * Special case for time set: if setting the
72 * time, ignore entry for time access/modify set (setattr)
73 * and instead use that of time access/modify.
74 */
75 *errorp = 0;
76 /*
77 * Bit matches the mask
78 */
79 switch (ntovp->vbit & vap->va_mask) {
80 case AT_SIZE:
81 nap->size = vap->va_size;
82 break;
83 case AT_MODE:
84 nap->mode = vap->va_mode;
85 break;
86 case AT_UID:
87 /*
88 * if no mapping, uid could be mapped to a numeric string,
89 * e.g. 12345->"12345"
90 */
91 if (*errorp = nfs_idmap_uid_str(vap->va_uid, &nap->owner,
92 FALSE))
93 retval = FALSE;
94 break;
95 case AT_GID:
96 /*
97 * if no mapping, gid will be mapped to a number string,
98 * e.g. "12345"
99 */
100 if (*errorp = nfs_idmap_gid_str(vap->va_gid, &nap->owner_group,
101 FALSE))
102 retval = FALSE;
103 break;
104 case AT_ATIME:
105 if ((ntovp->nval != FATTR4_TIME_ACCESS) ||
106 (*errorp = nfs4_time_vton(&vap->va_ctime,
107 &nap->time_access))) {
108 /*
109 * either asked for FATTR4_TIME_ACCESS_SET -
110 * not used for setattr
111 * or system time invalid for otw transfers
112 */
113 retval = FALSE;
114 }
115 break;
116 case AT_MTIME:
117 if ((ntovp->nval != FATTR4_TIME_MODIFY) ||
118 (*errorp = nfs4_time_vton(&vap->va_mtime,
119 &nap->time_modify))) {
120 /*
121 * either asked for FATTR4_TIME_MODIFY_SET -
122 * not used for setattr
123 * or system time invalid for otw transfers
124 */
125 retval = FALSE;
126 }
127 break;
128 case AT_CTIME:
129 if (*errorp = nfs4_time_vton(&vap->va_ctime,
130 &nap->time_metadata)) {
131 /*
132 * system time invalid for otw transfers
133 */
134 retval = FALSE;
135 }
136 break;
137 default:
138 retval = FALSE;
139 }
140 return (retval);
141 }
142
143 /*
144 * nfs4_set_fattr4_attr translates a vattr attribute into a fattr4 attribute
145 * for use by nfs4_setattr. For setting atime or mtime use the entry for
146 * time_XX_set rather than time_XX (XX == access or modify).
147 * Return TRUE if arg was set (even if there was an error) and FALSE
148 * otherwise. Also set error code. The caller should not continue
149 * if error was set, whether or not the return is TRUE or FALSE. Returning
150 * FALSE does not mean there was an error, only that the attr was not set.
151 */
152 static bool_t
nfs4_set_fattr4_attr(vattr_t * vap,vsecattr_t * vsap,struct nfs4_ntov_map * ntovp,union nfs4_attr_u * nap,int flags,int * errorp)153 nfs4_set_fattr4_attr(vattr_t *vap, vsecattr_t *vsap,
154 struct nfs4_ntov_map *ntovp, union nfs4_attr_u *nap, int flags,
155 int *errorp)
156 {
157 bool_t retval = TRUE;
158
159 /*
160 * Special case for time set: if setting the
161 * time, ignore entry for time access/modify
162 * and instead use that of time access/modify set.
163 */
164 *errorp = 0;
165 /*
166 * Bit matches the mask
167 */
168 switch (ntovp->vbit & vap->va_mask) {
169 case AT_SIZE:
170 nap->size = vap->va_size;
171 break;
172 case AT_MODE:
173 nap->mode = vap->va_mode;
174 break;
175 case AT_UID:
176 /*
177 * if no mapping, uid will be mapped to a number string,
178 * e.g. "12345"
179 */
180 if (*errorp = nfs_idmap_uid_str(vap->va_uid, &nap->owner,
181 FALSE))
182 retval = FALSE;
183 break;
184 case AT_GID:
185 /*
186 * if no mapping, gid will be mapped to a number string,
187 * e.g. "12345"
188 */
189 if (*errorp = nfs_idmap_gid_str(vap->va_gid, &nap->owner_group,
190 FALSE))
191 retval = FALSE;
192 break;
193 case AT_ATIME:
194 if ((ntovp->nval != FATTR4_TIME_ACCESS_SET) ||
195 (*errorp = timestruc_to_settime4(&vap->va_atime,
196 &nap->time_access_set, flags))) {
197 /* FATTR4_TIME_ACCESS - not used for verify */
198 retval = FALSE;
199 }
200 break;
201 case AT_MTIME:
202 if ((ntovp->nval != FATTR4_TIME_MODIFY_SET) ||
203 (*errorp = timestruc_to_settime4(&vap->va_mtime,
204 &nap->time_modify_set, flags))) {
205 /* FATTR4_TIME_MODIFY - not used for verify */
206 retval = FALSE;
207 }
208 break;
209 default:
210 /*
211 * If the ntovp->vbit == 0 this is most likely the ACL.
212 */
213 if (ntovp->vbit == 0 && ntovp->fbit == FATTR4_ACL_MASK) {
214 ASSERT(vsap->vsa_mask == (VSA_ACE | VSA_ACECNT));
215 nap->acl.fattr4_acl_len = vsap->vsa_aclcnt;
216 nap->acl.fattr4_acl_val = vsap->vsa_aclentp;
217 } else
218 retval = FALSE;
219 }
220
221 return (retval);
222 }
223
224 /*
225 * XXX - This is a shorter version of vattr_to_fattr4 which only takes care
226 * of setattr args - size, mode, uid/gid, times. Eventually we should generalize
227 * by using nfs4_ntov_map and the same functions used by the server.
228 * Here we just hardcoded the setattr attributes. Note that the order is
229 * important - it should follow the order of the bits in the mask.
230 */
231 int
vattr_to_fattr4(vattr_t * vap,vsecattr_t * vsap,fattr4 * fattrp,int flags,enum nfs_opnum4 op,bitmap4 supp)232 vattr_to_fattr4(vattr_t *vap, vsecattr_t *vsap, fattr4 *fattrp, int flags,
233 enum nfs_opnum4 op, bitmap4 supp)
234 {
235 int i, j;
236 union nfs4_attr_u *na = NULL;
237 int attrcnt;
238 int uid_attr = -1;
239 int gid_attr = -1;
240 int acl_attr = -1;
241 XDR xdr;
242 ulong_t xdr_size;
243 char *xdr_attrs;
244 int error = 0;
245 uint8_t amap[NFS4_MAXNUM_ATTRS];
246 uint_t va_mask = vap->va_mask;
247 bool_t (*attrfunc)();
248
249 #ifndef lint
250 /*
251 * Make sure that maximum attribute number can be expressed as an
252 * 8 bit quantity.
253 */
254 ASSERT(NFS4_MAXNUM_ATTRS <= (UINT8_MAX + 1));
255 #endif
256 fattrp->attrmask = 0;
257 fattrp->attrlist4_len = 0;
258 fattrp->attrlist4 = NULL;
259 na = kmem_zalloc(sizeof (union nfs4_attr_u) * nfs4_ntov_map_size,
260 KM_SLEEP);
261
262 if (op == OP_SETATTR || op == OP_CREATE || op == OP_OPEN) {
263 /*
264 * Note we need to set the attrmask for set operations.
265 * In particular mtime and atime will be set to the
266 * servers time.
267 */
268 nfs4_vmask_to_nmask_set(va_mask, &fattrp->attrmask);
269 if (vsap != NULL)
270 fattrp->attrmask |= FATTR4_ACL_MASK;
271 attrfunc = nfs4_set_fattr4_attr;
272 } else { /* verify/nverify */
273 /*
274 * Verfy/nverify use the "normal vmask_to_nmask
275 * this routine knows how to handle all vmask bits
276 */
277 nfs4_vmask_to_nmask(va_mask, &fattrp->attrmask);
278 /*
279 * XXX verify/nverify only works for a subset of attrs that
280 * directly map to vattr_t attrs. So, verify/nverify is
281 * broken for servers that only support mandatory attrs.
282 * Mask out change attr for now and fix verify op to
283 * work with mandonly servers later. nfs4_vmask_to_nmask
284 * sets change whenever it sees request for ctime/mtime,
285 * so we must turn off change because nfs4_ver_fattr4_attr
286 * will not generate args for change. This is a bug
287 * that will be fixed later.
288 * XXX
289 */
290 fattrp->attrmask &= ~FATTR4_CHANGE_MASK;
291 attrfunc = nfs4_ver_fattr4_attr;
292 }
293
294 /* Mask out any rec attrs unsupported by server */
295 fattrp->attrmask &= supp;
296
297 attrcnt = 0;
298 xdr_size = 0;
299 for (i = 0; i < nfs4_ntov_map_size; i++) {
300 /*
301 * In the case of FATTR4_ACL_MASK, the vbit will be 0 (zero)
302 * so we must also check if the fbit is FATTR4_ACL_MASK before
303 * skipping over this attribute.
304 */
305 if (!(nfs4_ntov_map[i].vbit & vap->va_mask)) {
306 if (nfs4_ntov_map[i].fbit != FATTR4_ACL_MASK)
307 continue;
308 if (vsap == NULL)
309 continue;
310 }
311
312 if (attrfunc == nfs4_set_fattr4_attr) {
313 if (!(*attrfunc)(vap, vsap, &nfs4_ntov_map[i],
314 &na[attrcnt], flags, &error))
315 continue;
316 } else if (attrfunc == nfs4_ver_fattr4_attr) {
317 if (!(*attrfunc)(vap, &nfs4_ntov_map[i], &na[attrcnt],
318 flags, &error))
319 continue;
320 }
321
322 if (error)
323 goto done; /* Exit! */
324
325 /*
326 * Calculate XDR size
327 */
328 if (nfs4_ntov_map[i].xdr_size != 0) {
329 /*
330 * If we are setting attributes (attrfunc is
331 * nfs4_set_fattr4_attr) and are setting the
332 * mtime or atime, adjust the xdr size down by
333 * 3 words, since we are using the server's
334 * time as the current time. Exception: if
335 * ATTR_UTIME is set, the client sends the
336 * time, so leave the xdr size alone.
337 */
338 xdr_size += nfs4_ntov_map[i].xdr_size;
339 if ((nfs4_ntov_map[i].nval == FATTR4_TIME_ACCESS_SET ||
340 nfs4_ntov_map[i].nval == FATTR4_TIME_MODIFY_SET) &&
341 attrfunc == nfs4_set_fattr4_attr &&
342 !(flags & ATTR_UTIME)) {
343 xdr_size -= 3 * BYTES_PER_XDR_UNIT;
344 }
345 } else {
346 /*
347 * The only zero xdr_sizes we should see
348 * are AT_UID, AT_GID and FATTR4_ACL_MASK
349 */
350 ASSERT(nfs4_ntov_map[i].vbit == AT_UID ||
351 nfs4_ntov_map[i].vbit == AT_GID ||
352 nfs4_ntov_map[i].fbit == FATTR4_ACL_MASK);
353 if (nfs4_ntov_map[i].vbit == AT_UID) {
354 uid_attr = attrcnt;
355 xdr_size += BYTES_PER_XDR_UNIT; /* length */
356 xdr_size +=
357 RNDUP(na[attrcnt].owner.utf8string_len);
358 } else if (nfs4_ntov_map[i].vbit == AT_GID) {
359 gid_attr = attrcnt;
360 xdr_size += BYTES_PER_XDR_UNIT; /* length */
361 xdr_size +=
362 RNDUP(
363 na[attrcnt].owner_group.utf8string_len);
364 } else if (nfs4_ntov_map[i].fbit == FATTR4_ACL_MASK) {
365 nfsace4 *tmpacl = (nfsace4 *)vsap->vsa_aclentp;
366
367 acl_attr = attrcnt;
368 /* fattr4_acl_len */
369 xdr_size += BYTES_PER_XDR_UNIT;
370 /* fattr4_acl_val */
371 xdr_size += RNDUP((vsap->vsa_aclcnt *
372 (sizeof (acetype4) + sizeof (aceflag4)
373 + sizeof (acemask4))));
374
375 for (j = 0; j < vsap->vsa_aclcnt; j++) {
376 /* who - utf8string_len */
377 xdr_size += BYTES_PER_XDR_UNIT;
378 /* who - utf8string_val */
379 xdr_size +=
380 RNDUP(tmpacl[j].who.utf8string_len);
381 }
382 }
383 }
384
385 /*
386 * This attr is going otw
387 */
388 amap[attrcnt] = (uint8_t)nfs4_ntov_map[i].nval;
389 attrcnt++;
390
391 /*
392 * Clear this bit from test mask so we stop
393 * as soon as all requested attrs are done.
394 */
395 va_mask &= ~nfs4_ntov_map[i].vbit;
396 if (va_mask == 0 &&
397 (vsap == NULL || (vsap != NULL && acl_attr != -1)))
398 break;
399 }
400
401 if (attrcnt == 0) {
402 goto done;
403 }
404
405 fattrp->attrlist4 = xdr_attrs = kmem_alloc(xdr_size, KM_SLEEP);
406 fattrp->attrlist4_len = xdr_size;
407 xdrmem_create(&xdr, xdr_attrs, xdr_size, XDR_ENCODE);
408 for (i = 0; i < attrcnt; i++) {
409 if ((*nfs4_ntov_map[amap[i]].xfunc)(&xdr, &na[i]) == FALSE) {
410 cmn_err(CE_WARN, "vattr_to_fattr4: xdr encode of "
411 "attribute failed\n");
412 error = EINVAL;
413 break;
414 }
415 }
416 done:
417 /*
418 * Free any malloc'd attrs, can only be uid or gid
419 */
420 if (uid_attr != -1 && na[uid_attr].owner.utf8string_val != NULL) {
421 kmem_free(na[uid_attr].owner.utf8string_val,
422 na[uid_attr].owner.utf8string_len);
423 }
424 if (gid_attr != -1 && na[gid_attr].owner_group.utf8string_val != NULL) {
425 kmem_free(na[gid_attr].owner_group.utf8string_val,
426 na[gid_attr].owner_group.utf8string_len);
427 }
428
429 /* xdrmem_destroy(&xdrs); */ /* NO-OP */
430 kmem_free(na, sizeof (union nfs4_attr_u) * nfs4_ntov_map_size);
431 if (error)
432 nfs4_fattr4_free(fattrp);
433 return (error);
434 }
435
436 void
nfs4_fattr4_free(fattr4 * attrp)437 nfs4_fattr4_free(fattr4 *attrp)
438 {
439 /*
440 * set attrlist4val/len to 0 because...
441 *
442 * op_readdir resfree function could call us again
443 * for last entry4 if it was able to encode the name
444 * and cookie but couldn't encode the attrs because
445 * of maxcount violation (from rddir args). In that
446 * case, the last/partial entry4's fattr4 has already
447 * been free'd, but the entry4 remains on the end of
448 * the list.
449 */
450 attrp->attrmask = 0;
451
452 if (attrp->attrlist4) {
453 kmem_free(attrp->attrlist4, attrp->attrlist4_len);
454 attrp->attrlist4 = NULL;
455 attrp->attrlist4_len = 0;
456 }
457 }
458
459 /*
460 * Translate a vattr_t mask to a fattr4 type bitmap, caller is
461 * responsible for zeroing bitsval if needed.
462 */
463 void
nfs4_vmask_to_nmask(uint_t vmask,bitmap4 * bitsval)464 nfs4_vmask_to_nmask(uint_t vmask, bitmap4 *bitsval)
465 {
466 if (vmask == AT_ALL || vmask == NFS4_VTON_ATTR_MASK) {
467 *bitsval |= NFS4_NTOV_ATTR_MASK;
468 return;
469 }
470
471 vmask &= NFS4_VTON_ATTR_MASK;
472 if (vmask == 0) {
473 return;
474 }
475
476 if (vmask & AT_TYPE)
477 *bitsval |= FATTR4_TYPE_MASK;
478 if (vmask & AT_MODE)
479 *bitsval |= FATTR4_MODE_MASK;
480 if (vmask & AT_UID)
481 *bitsval |= FATTR4_OWNER_MASK;
482 if (vmask & AT_GID)
483 *bitsval |= FATTR4_OWNER_GROUP_MASK;
484 if (vmask & AT_FSID)
485 *bitsval |= FATTR4_FSID_MASK;
486 /* set mounted_on_fileid when AT_NODEID requested */
487 if (vmask & AT_NODEID)
488 *bitsval |= FATTR4_FILEID_MASK | FATTR4_MOUNTED_ON_FILEID_MASK;
489 if (vmask & AT_NLINK)
490 *bitsval |= FATTR4_NUMLINKS_MASK;
491 if (vmask & AT_SIZE)
492 *bitsval |= FATTR4_SIZE_MASK;
493 if (vmask & AT_ATIME)
494 *bitsval |= FATTR4_TIME_ACCESS_MASK;
495 if (vmask & AT_MTIME)
496 *bitsval |= FATTR4_TIME_MODIFY_MASK;
497 /* also set CHANGE whenever AT_CTIME requested */
498 if (vmask & AT_CTIME)
499 *bitsval |= FATTR4_TIME_METADATA_MASK | FATTR4_CHANGE_MASK;
500 if (vmask & AT_NBLOCKS)
501 *bitsval |= FATTR4_SPACE_USED_MASK;
502 if (vmask & AT_RDEV)
503 *bitsval |= FATTR4_RAWDEV_MASK;
504 }
505
506 /*
507 * nfs4_vmask_to_nmask_set is used for setattr. A separate function needed
508 * because of special treatment to timeset.
509 */
510 void
nfs4_vmask_to_nmask_set(uint_t vmask,bitmap4 * bitsval)511 nfs4_vmask_to_nmask_set(uint_t vmask, bitmap4 *bitsval)
512 {
513 vmask &= NFS4_VTON_ATTR_MASK_SET;
514
515 if (vmask == 0) {
516 return;
517 }
518
519 if (vmask & AT_MODE)
520 *bitsval |= FATTR4_MODE_MASK;
521 if (vmask & AT_UID)
522 *bitsval |= FATTR4_OWNER_MASK;
523 if (vmask & AT_GID)
524 *bitsval |= FATTR4_OWNER_GROUP_MASK;
525 if (vmask & AT_SIZE)
526 *bitsval |= FATTR4_SIZE_MASK;
527 if (vmask & AT_ATIME)
528 *bitsval |= FATTR4_TIME_ACCESS_SET_MASK;
529 if (vmask & AT_MTIME)
530 *bitsval |= FATTR4_TIME_MODIFY_SET_MASK;
531 }
532
533 /*
534 * Convert NFS Version 4 over the network attributes to the local
535 * virtual attributes.
536 */
537 vtype_t nf4_to_vt[] = {
538 VBAD, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VDIR, VREG
539 };
540
541
542 /*
543 * { fbit, vbit, vfsstat, mandatory,
544 * nval, xdr_size, xfunc,
545 * sv_getit, prtstr },
546 */
547 struct nfs4_ntov_map nfs4_ntov_map[] = {
548 { FATTR4_SUPPORTED_ATTRS_MASK, 0, FALSE, TRUE,
549 FATTR4_SUPPORTED_ATTRS, 2 * BYTES_PER_XDR_UNIT, xdr_bitmap4,
550 NULL, "fattr4_supported_attrs" },
551
552 { FATTR4_TYPE_MASK, AT_TYPE, FALSE, TRUE,
553 FATTR4_TYPE, BYTES_PER_XDR_UNIT, xdr_int,
554 NULL, "fattr4_type" },
555
556 { FATTR4_FH_EXPIRE_TYPE_MASK, 0, FALSE, TRUE,
557 FATTR4_FH_EXPIRE_TYPE, BYTES_PER_XDR_UNIT, xdr_u_int,
558 NULL, "fattr4_fh_expire_type" },
559
560 { FATTR4_CHANGE_MASK, 0, FALSE, TRUE,
561 FATTR4_CHANGE, 2 * BYTES_PER_XDR_UNIT, xdr_u_longlong_t,
562 NULL, "fattr4_change" },
563
564 { FATTR4_SIZE_MASK, AT_SIZE, FALSE, TRUE,
565 FATTR4_SIZE, 2 * BYTES_PER_XDR_UNIT, xdr_u_longlong_t,
566 NULL, "fattr4_size" },
567
568 { FATTR4_LINK_SUPPORT_MASK, 0, FALSE, TRUE,
569 FATTR4_LINK_SUPPORT, BYTES_PER_XDR_UNIT, xdr_bool,
570 NULL, "fattr4_link_support" },
571
572 { FATTR4_SYMLINK_SUPPORT_MASK, 0, FALSE, TRUE,
573 FATTR4_SYMLINK_SUPPORT, BYTES_PER_XDR_UNIT, xdr_bool,
574 NULL, "fattr4_symlink_support" },
575
576 { FATTR4_NAMED_ATTR_MASK, 0, FALSE, TRUE,
577 FATTR4_NAMED_ATTR, BYTES_PER_XDR_UNIT, xdr_bool,
578 NULL, "fattr4_named_attr" },
579
580 { FATTR4_FSID_MASK, AT_FSID, FALSE, TRUE,
581 FATTR4_FSID, 4 * BYTES_PER_XDR_UNIT, xdr_fattr4_fsid,
582 NULL, "fattr4_fsid" },
583
584 { FATTR4_UNIQUE_HANDLES_MASK, 0, FALSE, TRUE,
585 FATTR4_UNIQUE_HANDLES, BYTES_PER_XDR_UNIT, xdr_bool,
586 NULL, "fattr4_unique_handles" },
587
588 { FATTR4_LEASE_TIME_MASK, 0, FALSE, TRUE,
589 FATTR4_LEASE_TIME, BYTES_PER_XDR_UNIT, xdr_u_int,
590 NULL, "fattr4_lease_time" },
591
592 { FATTR4_RDATTR_ERROR_MASK, 0, FALSE, TRUE,
593 FATTR4_RDATTR_ERROR, BYTES_PER_XDR_UNIT, xdr_int,
594 NULL, "fattr4_rdattr_error" },
595
596 { FATTR4_ACL_MASK, 0, FALSE, FALSE,
597 FATTR4_ACL, 0, xdr_fattr4_acl,
598 NULL, "fattr4_acl" },
599
600 { FATTR4_ACLSUPPORT_MASK, 0, FALSE, FALSE,
601 FATTR4_ACLSUPPORT, BYTES_PER_XDR_UNIT, xdr_u_int,
602 NULL, "fattr4_aclsupport" },
603
604 { FATTR4_ARCHIVE_MASK, 0, FALSE, FALSE,
605 FATTR4_ARCHIVE, BYTES_PER_XDR_UNIT, xdr_bool,
606 NULL, "fattr4_archive" },
607
608 { FATTR4_CANSETTIME_MASK, 0, FALSE, FALSE,
609 FATTR4_CANSETTIME, BYTES_PER_XDR_UNIT, xdr_bool,
610 NULL, "fattr4_cansettime" },
611
612 { FATTR4_CASE_INSENSITIVE_MASK, 0, FALSE, FALSE,
613 FATTR4_CASE_INSENSITIVE, BYTES_PER_XDR_UNIT, xdr_bool,
614 NULL, "fattr4_case_insensitive" },
615
616 { FATTR4_CASE_PRESERVING_MASK, 0, FALSE, FALSE,
617 FATTR4_CASE_PRESERVING, BYTES_PER_XDR_UNIT, xdr_bool,
618 NULL, "fattr4_case_preserving" },
619
620 { FATTR4_CHOWN_RESTRICTED_MASK, 0, FALSE, FALSE,
621 FATTR4_CHOWN_RESTRICTED, BYTES_PER_XDR_UNIT, xdr_bool,
622 NULL, "fattr4_chown_restricted" },
623
624 { FATTR4_FILEHANDLE_MASK, 0, FALSE, TRUE,
625 FATTR4_FILEHANDLE, 0, xdr_nfs_fh4,
626 NULL, "fattr4_filehandle" },
627
628 { FATTR4_FILEID_MASK, AT_NODEID, FALSE, FALSE,
629 FATTR4_FILEID, 2 * BYTES_PER_XDR_UNIT, xdr_u_longlong_t,
630 NULL, "fattr4_fileid" },
631
632 { FATTR4_FILES_AVAIL_MASK, 0, TRUE, FALSE,
633 FATTR4_FILES_AVAIL, 2 * BYTES_PER_XDR_UNIT, xdr_u_longlong_t,
634 NULL, "fattr4_files_avail" },
635
636 { FATTR4_FILES_FREE_MASK, 0, TRUE, FALSE,
637 FATTR4_FILES_FREE, 2 * BYTES_PER_XDR_UNIT, xdr_u_longlong_t,
638 NULL, "fattr4_files_free" },
639
640 { FATTR4_FILES_TOTAL_MASK, 0, TRUE, FALSE,
641 FATTR4_FILES_TOTAL, 2 * BYTES_PER_XDR_UNIT, xdr_u_longlong_t,
642 NULL, "fattr4_files_total" },
643
644 { FATTR4_FS_LOCATIONS_MASK, 0, FALSE, FALSE,
645 FATTR4_FS_LOCATIONS, 0, xdr_fattr4_fs_locations,
646 NULL, "fattr4_fs_locations" },
647
648 { FATTR4_HIDDEN_MASK, 0, FALSE, FALSE,
649 FATTR4_HIDDEN, BYTES_PER_XDR_UNIT, xdr_bool,
650 NULL, "fattr4_hidden" },
651
652 { FATTR4_HOMOGENEOUS_MASK, 0, FALSE, FALSE,
653 FATTR4_HOMOGENEOUS, BYTES_PER_XDR_UNIT, xdr_bool,
654 NULL, "fattr4_homogeneous" },
655
656 { FATTR4_MAXFILESIZE_MASK, 0, FALSE, FALSE,
657 FATTR4_MAXFILESIZE, 2 * BYTES_PER_XDR_UNIT, xdr_u_longlong_t,
658 NULL, "fattr4_maxfilesize" },
659
660 { FATTR4_MAXLINK_MASK, 0, FALSE, FALSE,
661 FATTR4_MAXLINK, BYTES_PER_XDR_UNIT, xdr_u_int,
662 NULL, "fattr4_maxlink" },
663
664 { FATTR4_MAXNAME_MASK, 0, FALSE, FALSE,
665 FATTR4_MAXNAME, BYTES_PER_XDR_UNIT, xdr_u_int,
666 NULL, "fattr4_maxname" },
667
668 { FATTR4_MAXREAD_MASK, 0, FALSE, FALSE,
669 FATTR4_MAXREAD, 2 * BYTES_PER_XDR_UNIT, xdr_u_longlong_t,
670 NULL, "fattr4_maxread" },
671
672 { FATTR4_MAXWRITE_MASK, 0, FALSE, FALSE,
673 FATTR4_MAXWRITE, 2 * BYTES_PER_XDR_UNIT, xdr_u_longlong_t,
674 NULL, "fattr4_maxwrite" },
675
676 { FATTR4_MIMETYPE_MASK, 0, FALSE, FALSE,
677 FATTR4_MIMETYPE, 0, xdr_utf8string,
678 NULL, "fattr4_mimetype" },
679
680 { FATTR4_MODE_MASK, AT_MODE, FALSE, FALSE,
681 FATTR4_MODE, BYTES_PER_XDR_UNIT, xdr_u_int,
682 NULL, "fattr4_mode" },
683
684 { FATTR4_NO_TRUNC_MASK, 0, FALSE, FALSE,
685 FATTR4_NO_TRUNC, BYTES_PER_XDR_UNIT, xdr_bool,
686 NULL, "fattr4_no_trunc" },
687
688 { FATTR4_NUMLINKS_MASK, AT_NLINK, FALSE, FALSE,
689 FATTR4_NUMLINKS, BYTES_PER_XDR_UNIT, xdr_u_int,
690 NULL, "fattr4_numlinks" },
691
692 { FATTR4_OWNER_MASK, AT_UID, FALSE, FALSE,
693 FATTR4_OWNER, 0, xdr_utf8string,
694 NULL, "fattr4_owner" },
695
696 { FATTR4_OWNER_GROUP_MASK, AT_GID, FALSE, FALSE,
697 FATTR4_OWNER_GROUP, 0, xdr_utf8string,
698 NULL, "fattr4_owner_group" },
699
700 { FATTR4_QUOTA_AVAIL_HARD_MASK, 0, FALSE, FALSE,
701 FATTR4_QUOTA_AVAIL_HARD, 2 * BYTES_PER_XDR_UNIT,
702 xdr_u_longlong_t,
703 NULL, "fattr4_quota_avail_hard" },
704
705 { FATTR4_QUOTA_AVAIL_SOFT_MASK, 0, FALSE, FALSE,
706 FATTR4_QUOTA_AVAIL_SOFT, 2 * BYTES_PER_XDR_UNIT,
707 xdr_u_longlong_t,
708 NULL, "fattr4_quota_avail_soft" },
709
710 { FATTR4_QUOTA_USED_MASK, 0, FALSE, FALSE,
711 FATTR4_QUOTA_USED, 2 * BYTES_PER_XDR_UNIT, xdr_u_longlong_t,
712 NULL, "fattr4_quota_used" },
713
714 { FATTR4_RAWDEV_MASK, AT_RDEV, FALSE, FALSE,
715 FATTR4_RAWDEV, 2 * BYTES_PER_XDR_UNIT, xdr_fattr4_rawdev,
716 NULL, "fattr4_rawdev" },
717
718 { FATTR4_SPACE_AVAIL_MASK, 0, TRUE, FALSE,
719 FATTR4_SPACE_AVAIL, 2 * BYTES_PER_XDR_UNIT, xdr_u_longlong_t,
720 NULL, "fattr4_space_avail" },
721
722 { FATTR4_SPACE_FREE_MASK, 0, TRUE, FALSE,
723 FATTR4_SPACE_FREE, 2 * BYTES_PER_XDR_UNIT, xdr_u_longlong_t,
724 NULL, "fattr4_space_free" },
725
726 { FATTR4_SPACE_TOTAL_MASK, 0, TRUE, FALSE,
727 FATTR4_SPACE_TOTAL, 2 * BYTES_PER_XDR_UNIT, xdr_u_longlong_t,
728 NULL, "fattr4_space_total" },
729
730 { FATTR4_SPACE_USED_MASK, AT_NBLOCKS, FALSE, FALSE,
731 FATTR4_SPACE_USED, 2 * BYTES_PER_XDR_UNIT, xdr_u_longlong_t,
732 NULL, "fattr4_space_used" },
733
734 { FATTR4_SYSTEM_MASK, 0, FALSE, FALSE,
735 FATTR4_SYSTEM, BYTES_PER_XDR_UNIT, xdr_bool,
736 NULL, "fattr4_system" },
737
738 { FATTR4_TIME_ACCESS_MASK, AT_ATIME, FALSE, FALSE,
739 FATTR4_TIME_ACCESS, 3 * BYTES_PER_XDR_UNIT, xdr_nfstime4,
740 NULL, "fattr4_time_access" },
741
742 { FATTR4_TIME_ACCESS_SET_MASK, AT_ATIME, FALSE, FALSE,
743 FATTR4_TIME_ACCESS_SET, 4 * BYTES_PER_XDR_UNIT, xdr_settime4,
744 NULL, "fattr4_time_access_set" },
745
746 { FATTR4_TIME_BACKUP_MASK, 0, FALSE, FALSE,
747 FATTR4_TIME_BACKUP, 3 * BYTES_PER_XDR_UNIT, xdr_nfstime4,
748 NULL, "fattr4_time_backup" },
749
750 { FATTR4_TIME_CREATE_MASK, 0, FALSE, FALSE,
751 FATTR4_TIME_CREATE, 3 * BYTES_PER_XDR_UNIT, xdr_nfstime4,
752 NULL, "fattr4_time_create" },
753
754 { FATTR4_TIME_DELTA_MASK, 0, FALSE, FALSE,
755 FATTR4_TIME_DELTA, 3 * BYTES_PER_XDR_UNIT, xdr_nfstime4,
756 NULL, "fattr4_time_delta" },
757
758 { FATTR4_TIME_METADATA_MASK, AT_CTIME, FALSE, FALSE,
759 FATTR4_TIME_METADATA, 3 * BYTES_PER_XDR_UNIT, xdr_nfstime4,
760 NULL, "fattr4_time_metadata" },
761
762 { FATTR4_TIME_MODIFY_MASK, AT_MTIME, FALSE, FALSE,
763 FATTR4_TIME_MODIFY, 3 * BYTES_PER_XDR_UNIT, xdr_nfstime4,
764 NULL, "fattr4_time_modify" },
765
766 { FATTR4_TIME_MODIFY_SET_MASK, AT_MTIME, FALSE, FALSE,
767 FATTR4_TIME_MODIFY_SET, 4 * BYTES_PER_XDR_UNIT, xdr_settime4,
768 NULL, "fattr4_time_modify_set" },
769
770 { FATTR4_MOUNTED_ON_FILEID_MASK, AT_NODEID, FALSE, FALSE,
771 FATTR4_MOUNTED_ON_FILEID, 2 * BYTES_PER_XDR_UNIT,
772 xdr_u_longlong_t,
773 NULL, "fattr4_mounted_on_fileid" },
774
775 { FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL, 0, FALSE, FALSE,
776 FATTR4_MOUNTED_ON_FILEID + 1, 0, xdr_bitmap4,
777 NULL, "fattr4_suppattr_exclcreat" },
778 };
779
780 uint_t nfs4_ntov_map_size = sizeof (nfs4_ntov_map) /
781 sizeof (struct nfs4_ntov_map);
782