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 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright 2018 Nexenta Systems, Inc.
29 * Copyright 2020 RackTop Systems, Inc.
30 */
31
32 #include <sys/systm.h>
33 #include <sys/cmn_err.h>
34 #include <nfs/nfs.h>
35 #include <nfs/export.h>
36 #include <nfs/nfs4.h>
37 #include <sys/ddi.h>
38 #include <sys/door.h>
39 #include <sys/sdt.h>
40 #include <nfs/nfssys.h>
41
42 void rfs4_init_compound_state(struct compound_state *);
43
44 bitmap4 rfs4_supported_attrs;
45 int MSG_PRT_DEBUG = FALSE;
46
47 /* If building with DEBUG enabled, enable mandattr tunable by default */
48 #ifdef DEBUG
49 #ifndef RFS4_SUPPORT_MANDATTR_ONLY
50 #define RFS4_SUPPORT_MANDATTR_ONLY
51 #endif
52 #endif
53
54 /*
55 * If building with mandattr only code, disable it by default.
56 * To enable, set rfs4_mandattr_only in /etc/system and reboot.
57 * When building without mandattr ifdef, the compiler should
58 * optimize away the the comparisons because RFS4_MANDATTR_ONLY
59 * is defined to be 0.
60 */
61 #ifdef RFS4_SUPPORT_MANDATTR_ONLY
62 #define NFS4_LAST_MANDATTR FATTR4_RDATTR_ERROR
63 #define RFS4_MANDATTR_ONLY rfs4_mandattr_only
64 int rfs4_mandattr_only = 0;
65 #else
66 #define RFS4_MANDATTR_ONLY 0
67 #endif
68
69
70 static void rfs4_ntov_init(void);
71 static int rfs4_fattr4_supported_attrs();
72 static int rfs4_fattr4_type();
73 static int rfs4_fattr4_fh_expire_type();
74 static int rfs4_fattr4_change();
75 static int rfs4_fattr4_size();
76 static int rfs4_fattr4_link_support();
77 static int rfs4_fattr4_symlink_support();
78 static int rfs4_fattr4_named_attr();
79 static int rfs4_fattr4_fsid();
80 static int rfs4_fattr4_unique_handles();
81 static int rfs4_fattr4_lease_time();
82 static int rfs4_fattr4_rdattr_error();
83 static int rfs4_fattr4_acl();
84 static int rfs4_fattr4_aclsupport();
85 static int rfs4_fattr4_archive();
86 static int rfs4_fattr4_cansettime();
87 static int rfs4_fattr4_case_insensitive();
88 static int rfs4_fattr4_case_preserving();
89 static int rfs4_fattr4_chown_restricted();
90 static int rfs4_fattr4_filehandle();
91 static int rfs4_fattr4_fileid();
92 static int rfs4_fattr4_files_avail();
93 static int rfs4_fattr4_files_free();
94 static int rfs4_fattr4_files_total();
95 static int rfs4_fattr4_fs_locations();
96 static int rfs4_fattr4_hidden();
97 static int rfs4_fattr4_homogeneous();
98 static int rfs4_fattr4_maxfilesize();
99 static int rfs4_fattr4_maxlink();
100 static int rfs4_fattr4_maxname();
101 static int rfs4_fattr4_maxread();
102 static int rfs4_fattr4_maxwrite();
103 static int rfs4_fattr4_mimetype();
104 static int rfs4_fattr4_mode();
105 static int rfs4_fattr4_no_trunc();
106 static int rfs4_fattr4_numlinks();
107 static int rfs4_fattr4_owner();
108 static int rfs4_fattr4_owner_group();
109 static int rfs4_fattr4_quota_avail_hard();
110 static int rfs4_fattr4_quota_avail_soft();
111 static int rfs4_fattr4_quota_used();
112 static int rfs4_fattr4_rawdev();
113 static int rfs4_fattr4_space_avail();
114 static int rfs4_fattr4_space_free();
115 static int rfs4_fattr4_space_total();
116 static int rfs4_fattr4_space_used();
117 static int rfs4_fattr4_system();
118 static int rfs4_fattr4_time_access();
119 static int rfs4_fattr4_time_access_set();
120 static int rfs4_fattr4_time_backup();
121 static int rfs4_fattr4_time_create();
122 static int rfs4_fattr4_time_delta();
123 static int rfs4_fattr4_time_metadata();
124 static int rfs4_fattr4_time_modify();
125 static int rfs4_fattr4_time_modify_set();
126
127 /*
128 * Initialize the supported attributes
129 */
130 bitmap4 supported_attrs[3];
131
132 static void
init_supported_attrs(void)133 init_supported_attrs(void)
134 {
135 supported_attrs[0] = supported_attrs[1] = supported_attrs[2] =
136 rfs4_supported_attrs;
137
138 /* restrict to nfsv4.0 */
139 supported_attrs[0] &= ~(FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL |
140 FATTR4_SEC_LABEL_MASK_LOCAL);
141
142 /* restrict to nfsv4.1 */
143 supported_attrs[1] &= ~FATTR4_SEC_LABEL_MASK_LOCAL;
144 }
145
146 void
rfs4_attr_init(void)147 rfs4_attr_init(void)
148 {
149 int i;
150 struct nfs4_svgetit_arg sarg;
151 struct compound_state cs;
152 struct statvfs64 sb;
153
154 rfs4_init_compound_state(&cs);
155 /*
156 * This is global state checking, called once. We might be in
157 * non-global-zone context here (say a modload happens from a zone
158 * process) so in this case, we want the global-zone root vnode.
159 */
160 cs.vp = rootvp;
161 cs.fh.nfs_fh4_val = NULL;
162 cs.cr = kcred;
163 cs.minorversion = NFS_PROT_V4_MINORVERSION(NFS_VERS_4_2);
164
165 /*
166 * Get all the supported attributes
167 */
168 sarg.op = NFS4ATTR_SUPPORTED;
169 sarg.cs = &cs;
170 sarg.vap->va_mask = AT_ALL;
171 sarg.sbp = &sb;
172 sarg.flag = 0;
173 sarg.rdattr_error = NFS4_OK;
174 sarg.rdattr_error_req = FALSE;
175 sarg.is_referral = B_FALSE;
176
177 rfs4_ntov_init();
178
179 rfs4_supported_attrs = 0;
180 for (i = 0; i < NFS4_MAXNUM_ATTRS; i++) {
181 #ifdef RFS4_SUPPORT_MANDATTR_ONLY
182 if (rfs4_mandattr_only == TRUE && i > NFS4_LAST_MANDATTR)
183 continue;
184 #endif
185 if ((*nfs4_ntov_map[i].sv_getit)(NFS4ATTR_SUPPORTED,
186 &sarg, NULL) == 0) {
187 rfs4_supported_attrs |= nfs4_ntov_map[i].fbit;
188 }
189 }
190
191 init_supported_attrs();
192 }
193
194 /*
195 * The following rfs4_fattr4_* functions convert between the fattr4
196 * arguments/attributes and the system (e.g. vattr) values. The following
197 * commands are currently in use:
198 *
199 * NFS4ATTR_SUPPORTED: checks if the attribute in question is supported:
200 * sarg.op = SUPPORTED - all supported attrs
201 * sarg.op = GETIT - only supported readable attrs
202 * sarg.op = SETIT - only supported writable attrs
203 *
204 * NFS4ATTR_GETIT: getattr type conversion - convert system values
205 * (e.g. vattr struct) to fattr4 type values to be returned to the
206 * user - usually in response to nfsv4 getattr request.
207 *
208 * NFS4ATTR_SETIT: convert fattr4 type values to system values to use by
209 * setattr. Allows only read/write and write attributes,
210 * even if not supported by the filesystem. Note that ufs only allows setattr
211 * of owner/group, mode, size, atime/mtime.
212 *
213 * NFS4ATTR_VERIT: convert fattr4 type values to system values to use by
214 * verify/nverify. Implemented to allow
215 * almost everything that can be returned by getattr into known structs
216 * (like vfsstat64 or vattr_t), that is, both read only and read/write attrs.
217 * The function will return -1 if it found that the arguments don't match.
218 * This applies to system-wide values that don't require a VOP_GETATTR
219 * or other further checks to verify. It will return no error if they
220 * either match or were retrieved successfully for later checking.
221 *
222 * NFS4ATTR_FREEIT: free up any space allocated by either of the above.
223 * The sargp->op should be either NFS4ATTR_GETIT or NFS4ATTR_SETIT
224 * to indicate which op was used to allocate the space.
225 *
226 * XXX Note: these functions are currently used by the server only. A
227 * XXX different method of conversion is used on the client side.
228 * XXX Eventually combining the two (possibly by adding NFS4ATTR_CLNT_GETIT
229 * XXX and SETIT) may be a cleaner approach.
230 */
231
232 /*
233 * Mandatory attributes
234 */
235
236 /* ARGSUSED */
237 static int
rfs4_fattr4_supported_attrs(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)238 rfs4_fattr4_supported_attrs(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
239 union nfs4_attr_u *na)
240 {
241 int error = 0;
242 bitmap4 supported = supported_attrs[sarg->cs->minorversion];
243
244 switch (cmd) {
245 case NFS4ATTR_SUPPORTED:
246 if (sarg->op == NFS4ATTR_SETIT)
247 error = EINVAL;
248 break; /* this attr is supported */
249 case NFS4ATTR_GETIT:
250 na->supported_attrs = supported;
251 break;
252 case NFS4ATTR_SETIT:
253 /*
254 * read-only attr
255 */
256 error = EINVAL;
257 break;
258 case NFS4ATTR_VERIT:
259 /*
260 * Compare the input bitmap to the server's bitmap
261 */
262 if (na->supported_attrs != supported) {
263 error = -1; /* no match */
264 }
265 break;
266 case NFS4ATTR_FREEIT:
267 break;
268 }
269 return (error);
270 }
271
272 /*
273 * Translate vnode vtype to nfsv4_ftype.
274 */
275 static nfs_ftype4 vt_to_nf4[] = {
276 0, NF4REG, NF4DIR, NF4BLK, NF4CHR, NF4LNK, NF4FIFO, 0, 0, NF4SOCK, 0
277 };
278
279 /* ARGSUSED */
280 static int
rfs4_fattr4_type(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)281 rfs4_fattr4_type(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
282 union nfs4_attr_u *na)
283 {
284 int error = 0;
285
286 switch (cmd) {
287 case NFS4ATTR_SUPPORTED:
288 if (sarg->op == NFS4ATTR_SETIT)
289 error = EINVAL;
290 break; /* this attr is supported */
291 case NFS4ATTR_GETIT:
292 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_TYPE)) {
293 error = -1; /* may be okay if rdattr_error */
294 break;
295 }
296 ASSERT(sarg->vap->va_mask & AT_TYPE);
297
298 /*
299 * if xattr flag not set, use v4_to_nf4 mapping;
300 * otherwise verify xattr flag is in sync with va_type
301 * and set xattr types.
302 */
303 if (! (sarg->xattr & (FH4_NAMEDATTR | FH4_ATTRDIR)))
304 na->type = vt_to_nf4[sarg->vap->va_type];
305 else {
306 /*
307 * FH4 flag was set. Dir type maps to attrdir,
308 * and all other types map to namedattr.
309 */
310 if (sarg->vap->va_type == VDIR)
311 na->type = NF4ATTRDIR;
312 else
313 na->type = NF4NAMEDATTR;
314 }
315 break;
316 case NFS4ATTR_SETIT:
317 /*
318 * read-only attr
319 */
320 error = EINVAL;
321 break;
322 case NFS4ATTR_VERIT:
323 /*
324 * Compare the input type to the object type on server
325 */
326 ASSERT(sarg->vap->va_mask & AT_TYPE);
327 if (sarg->vap->va_type != nf4_to_vt[na->type])
328 error = -1; /* no match */
329 break;
330 case NFS4ATTR_FREEIT:
331 break;
332 }
333 return (error);
334 }
335
336 /* ARGSUSED */
337 static int
fattr4_get_fh_expire_type(struct exportinfo * exi,uint32_t * fh_expire_typep)338 fattr4_get_fh_expire_type(struct exportinfo *exi, uint32_t *fh_expire_typep)
339 {
340 #ifdef VOLATILE_FH_TEST
341 int ex_flags;
342
343 if (exi == NULL)
344 return (ESTALE);
345 ex_flags = exi->exi_export.ex_flags;
346 if ((ex_flags & (EX_VOLFH | EX_VOLRNM | EX_VOLMIG | EX_NOEXPOPEN))
347 == 0) {
348 *fh_expire_typep = FH4_PERSISTENT;
349 return (0);
350 }
351 *fh_expire_typep = 0;
352
353 if (ex_flags & EX_NOEXPOPEN) {
354 /* file handles should not expire with open - not used */
355 *fh_expire_typep = FH4_NOEXPIRE_WITH_OPEN;
356 }
357 if (ex_flags & EX_VOLFH) {
358 /*
359 * file handles may expire any time - on share here.
360 * If volatile any, no need to check other flags.
361 */
362 *fh_expire_typep |= FH4_VOLATILE_ANY;
363 return (0);
364 }
365 if (ex_flags & EX_VOLRNM) {
366 /* file handles may expire on rename */
367 *fh_expire_typep |= FH4_VOL_RENAME;
368 }
369 if (ex_flags & EX_VOLMIG) {
370 /* file handles may expire on migration - not used */
371 *fh_expire_typep |= FH4_VOL_MIGRATION;
372 }
373 #else /* not VOLATILE_FH_TEST */
374 *fh_expire_typep = FH4_PERSISTENT;
375 #endif /* VOLATILE_FH_TEST */
376
377 return (0);
378 }
379
380 /*
381 * At this point the only volatile filehandles we allow (for test purposes
382 * only) are either fh's that expire when the filesystem is shared (reshared),
383 * fh's that expire on a rename and persistent ones.
384 */
385 /* ARGSUSED */
386 static int
rfs4_fattr4_fh_expire_type(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)387 rfs4_fattr4_fh_expire_type(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
388 union nfs4_attr_u *na)
389 {
390 uint32_t fh_expire_type;
391 int error = 0;
392
393 switch (cmd) {
394 case NFS4ATTR_SUPPORTED:
395 if (sarg->op == NFS4ATTR_SETIT)
396 error = EINVAL;
397 break; /* this attr is supported */
398 case NFS4ATTR_GETIT:
399 error = fattr4_get_fh_expire_type(sarg->cs->exi,
400 &na->fh_expire_type);
401 break;
402 case NFS4ATTR_SETIT:
403 /*
404 * read-only attr
405 */
406 error = EINVAL;
407 break;
408 case NFS4ATTR_VERIT:
409 error = fattr4_get_fh_expire_type(sarg->cs->exi,
410 &fh_expire_type);
411 if (!error && (na->fh_expire_type != fh_expire_type))
412 error = -1; /* no match */
413 break;
414 case NFS4ATTR_FREEIT:
415 break;
416 }
417 return (error);
418 }
419
420 static int
fattr4_get_change(struct nfs4_svgetit_arg * sarg,fattr4_change * changep)421 fattr4_get_change(struct nfs4_svgetit_arg *sarg, fattr4_change *changep)
422 {
423 vattr_t vap2[1], *vap = sarg->vap;
424 struct compound_state *cs = sarg->cs;
425 vnode_t *vp = cs->vp;
426 nfsstat4 status;
427 timespec_t vis_change;
428
429 if ((vap->va_mask & AT_CTIME) == 0) {
430 if (sarg->rdattr_error && (vp == NULL)) {
431 return (-1); /* may be okay if rdattr_error */
432 }
433 ASSERT(vp != NULL);
434 vap = vap2;
435 vap->va_mask = AT_CTIME;
436 status = rfs4_vop_getattr(vp, vap, 0, cs->cr);
437 if (status != NFS4_OK)
438 return (geterrno4(status));
439 }
440 NFS4_SET_FATTR4_CHANGE(*changep, vap->va_ctime);
441
442 if (nfs_visible_change(cs->exi, vp, &vis_change)) {
443 fattr4_change visch;
444 NFS4_SET_FATTR4_CHANGE(visch, vis_change);
445 if (visch > *changep)
446 *changep = visch;
447 }
448
449 return (0);
450 }
451
452 /* ARGSUSED */
453 static int
rfs4_fattr4_change(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)454 rfs4_fattr4_change(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
455 union nfs4_attr_u *na)
456 {
457 int error = 0;
458 fattr4_change change;
459 uint_t mask;
460 vattr_t *vap = sarg->vap;
461
462 switch (cmd) {
463 case NFS4ATTR_SUPPORTED:
464 if (sarg->op == NFS4ATTR_SETIT)
465 error = EINVAL;
466 break; /* this attr is supported */
467 case NFS4ATTR_GETIT:
468 error = fattr4_get_change(sarg, &na->change);
469 break;
470 case NFS4ATTR_SETIT:
471 /*
472 * read-only attr
473 */
474 error = EINVAL;
475 break;
476 case NFS4ATTR_VERIT:
477 mask = vap->va_mask;
478 vap->va_mask &= ~AT_CTIME; /* force a VOP_GETATTR */
479 error = fattr4_get_change(sarg, &change);
480 vap->va_mask = mask;
481 if (!error && (na->change != change))
482 error = -1;
483 break;
484 case NFS4ATTR_FREEIT:
485 break;
486 }
487 return (error);
488 }
489
490 /* ARGSUSED */
491 static int
rfs4_fattr4_size(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)492 rfs4_fattr4_size(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
493 union nfs4_attr_u *na)
494 {
495 int error = 0;
496
497 switch (cmd) {
498 case NFS4ATTR_SUPPORTED:
499 break; /* this attr is supported */
500 case NFS4ATTR_GETIT:
501 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_SIZE)) {
502 error = -1; /* may be okay if rdattr_error */
503 break;
504 }
505 ASSERT(sarg->vap->va_mask & AT_SIZE);
506 na->size = sarg->vap->va_size;
507 break;
508 case NFS4ATTR_SETIT:
509 ASSERT(sarg->vap->va_mask & AT_SIZE);
510 sarg->vap->va_size = na->size;
511 break;
512 case NFS4ATTR_VERIT:
513 ASSERT(sarg->vap->va_mask & AT_SIZE);
514 if (sarg->vap->va_size != na->size)
515 error = -1; /* no match */
516 break;
517 case NFS4ATTR_FREEIT:
518 break;
519 }
520 return (error);
521 }
522
523 /*
524 * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports
525 * hard links.
526 */
527 /* ARGSUSED */
528 static int
rfs4_fattr4_link_support(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)529 rfs4_fattr4_link_support(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
530 union nfs4_attr_u *na)
531 {
532 int error = 0;
533
534 switch (cmd) {
535 case NFS4ATTR_SUPPORTED:
536 if (sarg->op == NFS4ATTR_SETIT)
537 error = EINVAL;
538 break; /* this attr is supported */
539 case NFS4ATTR_GETIT:
540 na->link_support = TRUE;
541 break;
542 case NFS4ATTR_SETIT:
543 /*
544 * read-only attr
545 */
546 error = EINVAL;
547 break;
548 case NFS4ATTR_VERIT:
549 if (!na->link_support)
550 error = -1; /* no match */
551 break;
552 case NFS4ATTR_FREEIT:
553 break;
554 }
555 return (error);
556 }
557
558 /*
559 * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports
560 * sym links.
561 */
562 /* ARGSUSED */
563 static int
rfs4_fattr4_symlink_support(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)564 rfs4_fattr4_symlink_support(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
565 union nfs4_attr_u *na)
566 {
567 int error = 0;
568
569 switch (cmd) {
570 case NFS4ATTR_SUPPORTED:
571 if (sarg->op == NFS4ATTR_SETIT)
572 error = EINVAL;
573 break; /* this attr is supported */
574 case NFS4ATTR_GETIT:
575 na->symlink_support = TRUE;
576 break;
577 case NFS4ATTR_SETIT:
578 /*
579 * read-only attr
580 */
581 error = EINVAL;
582 break;
583 case NFS4ATTR_VERIT:
584 if (!na->symlink_support)
585 error = -1; /* no match */
586 break;
587 case NFS4ATTR_FREEIT:
588 break;
589 }
590 return (error);
591 }
592
593 /* ARGSUSED */
594 static int
rfs4_fattr4_named_attr(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)595 rfs4_fattr4_named_attr(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
596 union nfs4_attr_u *na)
597 {
598 int error = 0;
599 ulong_t val;
600
601 switch (cmd) {
602 case NFS4ATTR_SUPPORTED:
603 if (sarg->op == NFS4ATTR_SETIT)
604 error = EINVAL;
605 break; /* this attr is supported */
606 case NFS4ATTR_GETIT:
607 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
608 error = -1; /* may be okay if rdattr_error */
609 break;
610 }
611 ASSERT(sarg->cs->vp != NULL);
612
613 /*
614 * Solaris xattr model requires that VFS_XATTR is set
615 * in file systems enabled for generic xattr. If VFS_XATTR
616 * not set, no need to call pathconf for _PC_XATTR_EXISTS..
617 *
618 * However the VFS_XATTR flag doesn't indicate sysattr support
619 * so always check for sysattrs and then only do the
620 * _PC_XATTR_EXISTS pathconf if needed.
621 */
622
623 val = 0;
624 error = VOP_PATHCONF(sarg->cs->vp, _PC_SATTR_EXISTS,
625 &val, sarg->cs->cr, NULL);
626 if ((error || val == 0) &&
627 sarg->cs->vp->v_vfsp->vfs_flag & VFS_XATTR) {
628 error = VOP_PATHCONF(sarg->cs->vp,
629 _PC_XATTR_EXISTS, &val, sarg->cs->cr, NULL);
630 if (error)
631 break;
632 }
633 na->named_attr = (val ? TRUE : FALSE);
634 break;
635 case NFS4ATTR_SETIT:
636 /*
637 * read-only attr
638 */
639 error = EINVAL;
640 break;
641 case NFS4ATTR_VERIT:
642 ASSERT(sarg->cs->vp != NULL);
643 if (sarg->cs->vp->v_vfsp->vfs_flag & VFS_XATTR) {
644 error = VOP_PATHCONF(sarg->cs->vp, _PC_SATTR_EXISTS,
645 &val, sarg->cs->cr, NULL);
646 if (error || val == 0)
647 error = VOP_PATHCONF(sarg->cs->vp,
648 _PC_XATTR_EXISTS, &val,
649 sarg->cs->cr, NULL);
650 if (error)
651 break;
652 } else
653 val = 0;
654 if (na->named_attr != (val ? TRUE : FALSE))
655 error = -1; /* no match */
656 break;
657 case NFS4ATTR_FREEIT:
658 break;
659 }
660 return (error);
661 }
662
663 /* ARGSUSED */
664 static int
rfs4_fattr4_fsid(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)665 rfs4_fattr4_fsid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
666 union nfs4_attr_u *na)
667 {
668 int error = 0;
669 int *pmaj = (int *)&na->fsid.major;
670
671 /*
672 * fsid_t is 64bits so it fits completely in fattr4_fsid.major.
673 * fattr4_fsid.minor is always set to 0 since it isn't needed (yet).
674 */
675 switch (cmd) {
676 case NFS4ATTR_SUPPORTED:
677 if (sarg->op == NFS4ATTR_SETIT)
678 error = EINVAL;
679 break; /* this attr is supported */
680 case NFS4ATTR_GETIT:
681 if (sarg->is_referral) {
682 na->fsid.major = 1;
683 na->fsid.minor = 0;
684 } else if (sarg->cs->exi->exi_volatile_dev) {
685 pmaj[0] = sarg->cs->exi->exi_fsid.val[0];
686 pmaj[1] = sarg->cs->exi->exi_fsid.val[1];
687 na->fsid.minor = 0;
688 } else {
689 na->fsid.major = getmajor(sarg->vap->va_fsid);
690 na->fsid.minor = getminor(sarg->vap->va_fsid);
691 }
692 break;
693 case NFS4ATTR_SETIT:
694 error = EINVAL;
695 break;
696 case NFS4ATTR_VERIT:
697 if (sarg->is_referral) {
698 if (na->fsid.major != 1 ||
699 na->fsid.minor != 0)
700 error = -1;
701 } else if (sarg->cs->exi->exi_volatile_dev) {
702 if (pmaj[0] != sarg->cs->exi->exi_fsid.val[0] ||
703 pmaj[1] != sarg->cs->exi->exi_fsid.val[1] ||
704 na->fsid.minor != 0)
705 error = -1;
706 } else {
707 if (na->fsid.major != getmajor(sarg->vap->va_fsid) ||
708 na->fsid.minor != getminor(sarg->vap->va_fsid))
709 error = -1;
710 }
711 break;
712 case NFS4ATTR_FREEIT:
713 break;
714 }
715 return (error);
716 }
717
718 /* ARGSUSED */
719 static int
rfs4_fattr4_unique_handles(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)720 rfs4_fattr4_unique_handles(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
721 union nfs4_attr_u *na)
722 {
723 /*
724 * XXX
725 * For now, we can't support this. Problem of /export, beinging
726 * a file system, /export/a and /export/b shared separately,
727 * and /export/a/l and /export/b/l are ahrd links of each other.
728 */
729 int error = 0;
730
731 switch (cmd) {
732 case NFS4ATTR_SUPPORTED:
733 if (sarg->op == NFS4ATTR_SETIT)
734 error = EINVAL;
735 break; /* this attr is supported */
736 case NFS4ATTR_GETIT:
737 na->unique_handles = FALSE;
738 break;
739 case NFS4ATTR_SETIT:
740 /*
741 * read-only attr
742 */
743 error = EINVAL;
744 break;
745 case NFS4ATTR_VERIT:
746 if (na->unique_handles)
747 error = -1; /* no match */
748 break;
749 case NFS4ATTR_FREEIT:
750 break;
751 }
752 return (error);
753 }
754
755 /* ARGSUSED */
756 static int
rfs4_fattr4_lease_time(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)757 rfs4_fattr4_lease_time(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
758 union nfs4_attr_u *na)
759 {
760 int error = 0;
761
762 switch (cmd) {
763 case NFS4ATTR_SUPPORTED:
764 if (sarg->op == NFS4ATTR_SETIT)
765 error = EINVAL;
766 break; /* this attr is supported */
767 case NFS4ATTR_GETIT:
768 na->lease_time = rfs4_lease_time;
769 break;
770 case NFS4ATTR_SETIT:
771 /*
772 * read-only attr
773 */
774 error = EINVAL;
775 break;
776 case NFS4ATTR_VERIT:
777 if (na->lease_time != rfs4_lease_time)
778 error = -1; /* no match */
779 break;
780 case NFS4ATTR_FREEIT:
781 break;
782 }
783 return (error);
784 }
785
786 /* ARGSUSED */
787 static int
rfs4_fattr4_rdattr_error(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)788 rfs4_fattr4_rdattr_error(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
789 union nfs4_attr_u *na)
790 {
791 int error = 0;
792
793 switch (cmd) {
794 case NFS4ATTR_SUPPORTED:
795 if ((sarg->op == NFS4ATTR_SETIT) ||
796 (sarg->op == NFS4ATTR_VERIT))
797 error = EINVAL;
798 break; /* this attr is supported */
799 case NFS4ATTR_GETIT:
800 ASSERT(sarg->rdattr_error_req);
801 na->rdattr_error = sarg->rdattr_error;
802 break;
803 case NFS4ATTR_SETIT:
804 case NFS4ATTR_VERIT:
805 /*
806 * read-only attr
807 */
808 error = EINVAL;
809 break;
810 case NFS4ATTR_FREEIT:
811 break;
812 }
813 return (error);
814 }
815
816 /*
817 * Server side compare of a filehandle from the wire to a native
818 * server filehandle.
819 */
820 static int
rfs4fhcmp(nfs_fh4 * wirefh,nfs_fh4 * srvfh)821 rfs4fhcmp(nfs_fh4 *wirefh, nfs_fh4 *srvfh)
822 {
823 nfs_fh4_fmt_t fh;
824
825 ASSERT(IS_P2ALIGNED(wirefh->nfs_fh4_val, sizeof (uint32_t)));
826
827 bzero(&fh, sizeof (nfs_fh4_fmt_t));
828 if (!xdr_inline_decode_nfs_fh4((uint32_t *)wirefh->nfs_fh4_val, &fh,
829 wirefh->nfs_fh4_len))
830 return (1);
831
832 return (bcmp(srvfh->nfs_fh4_val, &fh, srvfh->nfs_fh4_len));
833 }
834
835 /* ARGSUSED */
836 static int
rfs4_fattr4_filehandle(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)837 rfs4_fattr4_filehandle(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
838 union nfs4_attr_u *na)
839 {
840 nfs_fh4 *fh;
841
842 switch (cmd) {
843 case NFS4ATTR_SUPPORTED:
844 if (sarg->op == NFS4ATTR_SETIT)
845 return (EINVAL);
846 return (0); /* this attr is supported */
847 case NFS4ATTR_GETIT:
848 /*
849 * If sarg->cs->fh is all zeros then should makefh a new
850 * one, otherwise, copy that one over.
851 */
852 fh = &sarg->cs->fh;
853 if (sarg->cs->fh.nfs_fh4_len == 0) {
854 if (sarg->rdattr_error && (sarg->cs->vp == NULL))
855 return (-1); /* okay if rdattr_error */
856 ASSERT(sarg->cs->vp != NULL);
857 na->filehandle.nfs_fh4_val =
858 kmem_alloc(NFS_FH4_LEN, KM_SLEEP);
859 return (makefh4(&na->filehandle, sarg->cs->vp,
860 sarg->cs->exi));
861 }
862 na->filehandle.nfs_fh4_val =
863 kmem_alloc(fh->nfs_fh4_len, KM_SLEEP);
864 nfs_fh4_copy(fh, &na->filehandle);
865 return (0);
866 case NFS4ATTR_SETIT:
867 /*
868 * read-only attr
869 */
870 return (EINVAL);
871 case NFS4ATTR_VERIT:
872 /*
873 * A verify of a filehandle will have the client sending
874 * the raw format which needs to be compared to the
875 * native format.
876 */
877 if (rfs4fhcmp(&na->filehandle, &sarg->cs->fh) == 1)
878 return (-1); /* no match */
879 return (0);
880 case NFS4ATTR_FREEIT:
881 if (sarg->op != NFS4ATTR_GETIT)
882 return (0);
883 if (na->filehandle.nfs_fh4_val == NULL)
884 return (0);
885 kmem_free(na->filehandle.nfs_fh4_val,
886 na->filehandle.nfs_fh4_len);
887 na->filehandle.nfs_fh4_val = NULL;
888 na->filehandle.nfs_fh4_len = 0;
889 return (0);
890 }
891 return (0);
892 }
893
894 /*
895 * Recommended attributes
896 */
897
898 /* ARGSUSED */
899 static int
rfs4_fattr4_acl(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)900 rfs4_fattr4_acl(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
901 union nfs4_attr_u *na)
902 {
903 int error = 0;
904 vsecattr_t vs_native, vs_ace4;
905 ulong_t whichacl;
906 nfsstat4 status;
907 vattr_t va, *vap = sarg->vap;
908 vnode_t *vp = sarg->cs->vp;
909
910 if (RFS4_MANDATTR_ONLY)
911 return (ENOTSUP);
912
913 switch (cmd) {
914 case NFS4ATTR_SUPPORTED:
915 break;
916
917 case NFS4ATTR_VERIT:
918 case NFS4ATTR_GETIT:
919 if (sarg->rdattr_error && (vp == NULL)) {
920 return (-1);
921 }
922 ASSERT(vp != NULL);
923 bzero(&vs_native, sizeof (vs_native));
924
925 /* see which ACLs fs supports */
926 error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &whichacl,
927 sarg->cs->cr, NULL);
928 if (error != 0) {
929 /*
930 * If we got an error, then the filesystem
931 * likely does not understand the _PC_ACL_ENABLED
932 * pathconf. In this case, we fall back to trying
933 * POSIX-draft (aka UFS-style) ACLs, since that's
934 * the behavior used by earlier version of NFS.
935 */
936 error = 0;
937 whichacl = _ACL_ACLENT_ENABLED;
938 }
939
940 if (!(whichacl & (_ACL_ACE_ENABLED | _ACL_ACLENT_ENABLED))) {
941 /*
942 * If the file system supports neither ACE nor
943 * ACLENT ACLs we will fall back to UFS-style ACLs
944 * like we did above if there was an error upon
945 * calling VOP_PATHCONF.
946 *
947 * ACE and ACLENT type ACLs are the only interfaces
948 * supported thus far. If any other bits are set on
949 * 'whichacl' upon return from VOP_PATHCONF, we will
950 * ignore them.
951 */
952 whichacl = _ACL_ACLENT_ENABLED;
953 }
954
955 if (whichacl & _ACL_ACE_ENABLED)
956 vs_native.vsa_mask = VSA_ACE | VSA_ACECNT;
957 else if (whichacl & _ACL_ACLENT_ENABLED)
958 vs_native.vsa_mask = VSA_ACL | VSA_ACLCNT |
959 VSA_DFACL | VSA_DFACLCNT;
960
961 if (error != 0)
962 break;
963
964 /* get the ACL, and translate it into nfsace4 style */
965 error = VOP_GETSECATTR(vp, &vs_native,
966 0, sarg->cs->cr, NULL);
967 if (error != 0)
968 break;
969 if (whichacl & _ACL_ACE_ENABLED) {
970 error = vs_acet_to_ace4(&vs_native, &vs_ace4, TRUE);
971 vs_acet_destroy(&vs_native);
972 } else {
973 error = vs_aent_to_ace4(&vs_native, &vs_ace4,
974 vp->v_type == VDIR, TRUE);
975 vs_aent_destroy(&vs_native);
976 }
977 if (error != 0)
978 break;
979
980 if (cmd == NFS4ATTR_GETIT) {
981 na->acl.fattr4_acl_len = vs_ace4.vsa_aclcnt;
982 /* see case NFS4ATTR_FREEIT for this being freed */
983 na->acl.fattr4_acl_val = vs_ace4.vsa_aclentp;
984 } else {
985 if (na->acl.fattr4_acl_len != vs_ace4.vsa_aclcnt)
986 error = -1; /* no match */
987 else if (ln_ace4_cmp(na->acl.fattr4_acl_val,
988 vs_ace4.vsa_aclentp,
989 vs_ace4.vsa_aclcnt) != 0)
990 error = -1; /* no match */
991 }
992
993 break;
994
995 case NFS4ATTR_SETIT:
996 if (sarg->rdattr_error && (vp == NULL)) {
997 return (-1);
998 }
999 ASSERT(vp != NULL);
1000
1001 /* prepare vs_ace4 from fattr4 data */
1002 bzero(&vs_ace4, sizeof (vs_ace4));
1003 vs_ace4.vsa_mask = VSA_ACE | VSA_ACECNT;
1004 vs_ace4.vsa_aclcnt = na->acl.fattr4_acl_len;
1005 vs_ace4.vsa_aclentp = na->acl.fattr4_acl_val;
1006 vs_ace4.vsa_aclentsz = vs_ace4.vsa_aclcnt * sizeof (ace_t);
1007 /* make sure we have correct owner/group */
1008 if ((vap->va_mask & (AT_UID | AT_GID)) !=
1009 (AT_UID | AT_GID)) {
1010 vap = &va;
1011 vap->va_mask = AT_UID | AT_GID;
1012 status = rfs4_vop_getattr(vp,
1013 vap, 0, sarg->cs->cr);
1014 if (status != NFS4_OK)
1015 return (geterrno4(status));
1016 }
1017
1018 /* see which ACLs the fs supports */
1019 error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &whichacl,
1020 sarg->cs->cr, NULL);
1021 if (error != 0) {
1022 /*
1023 * If we got an error, then the filesystem
1024 * likely does not understand the _PC_ACL_ENABLED
1025 * pathconf. In this case, we fall back to trying
1026 * POSIX-draft (aka UFS-style) ACLs, since that's
1027 * the behavior used by earlier version of NFS.
1028 */
1029 error = 0;
1030 whichacl = _ACL_ACLENT_ENABLED;
1031 }
1032
1033 if (!(whichacl & (_ACL_ACLENT_ENABLED | _ACL_ACE_ENABLED))) {
1034 /*
1035 * If the file system supports neither ACE nor
1036 * ACLENT ACLs we will fall back to UFS-style ACLs
1037 * like we did above if there was an error upon
1038 * calling VOP_PATHCONF.
1039 *
1040 * ACE and ACLENT type ACLs are the only interfaces
1041 * supported thus far. If any other bits are set on
1042 * 'whichacl' upon return from VOP_PATHCONF, we will
1043 * ignore them.
1044 */
1045 whichacl = _ACL_ACLENT_ENABLED;
1046 }
1047
1048 if (whichacl & _ACL_ACE_ENABLED) {
1049 error = vs_ace4_to_acet(&vs_ace4, &vs_native,
1050 vap->va_uid, vap->va_gid, TRUE);
1051 if (error != 0)
1052 break;
1053 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
1054 error = VOP_SETSECATTR(vp, &vs_native,
1055 0, sarg->cs->cr, NULL);
1056 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
1057 vs_acet_destroy(&vs_native);
1058 } else if (whichacl & _ACL_ACLENT_ENABLED) {
1059 error = vs_ace4_to_aent(&vs_ace4, &vs_native,
1060 vap->va_uid, vap->va_gid, vp->v_type == VDIR, TRUE);
1061 if (error != 0)
1062 break;
1063 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
1064 error = VOP_SETSECATTR(vp, &vs_native,
1065 0, sarg->cs->cr, NULL);
1066 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
1067 vs_aent_destroy(&vs_native);
1068 }
1069 break;
1070
1071 case NFS4ATTR_FREEIT:
1072 if (sarg->op == NFS4ATTR_GETIT) {
1073 vs_ace4.vsa_mask = VSA_ACE | VSA_ACECNT;
1074 vs_ace4.vsa_aclcnt = na->acl.fattr4_acl_len;
1075 vs_ace4.vsa_aclentp = na->acl.fattr4_acl_val;
1076 vs_ace4_destroy(&vs_ace4);
1077 }
1078 break;
1079 }
1080
1081 return (error);
1082 }
1083
1084 /* ARGSUSED */
1085 static int
rfs4_fattr4_aclsupport(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1086 rfs4_fattr4_aclsupport(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1087 union nfs4_attr_u *na)
1088 {
1089 int error = 0;
1090
1091 if (RFS4_MANDATTR_ONLY)
1092 return (ENOTSUP);
1093
1094 switch (cmd) {
1095 case NFS4ATTR_SUPPORTED:
1096 if (sarg->op == NFS4ATTR_SETIT)
1097 error = EINVAL;
1098 break; /* supported */
1099 case NFS4ATTR_GETIT:
1100 na->aclsupport = ACL4_SUPPORT_ALLOW_ACL |
1101 ACL4_SUPPORT_DENY_ACL;
1102 break;
1103 case NFS4ATTR_SETIT:
1104 error = EINVAL;
1105 break;
1106 case NFS4ATTR_VERIT:
1107 if (na->aclsupport != (ACL4_SUPPORT_ALLOW_ACL |
1108 ACL4_SUPPORT_DENY_ACL))
1109 error = -1; /* no match */
1110 break;
1111 }
1112
1113 return (error);
1114 }
1115
1116 /* ARGSUSED */
1117 static int
rfs4_fattr4_archive(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1118 rfs4_fattr4_archive(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1119 union nfs4_attr_u *na)
1120 {
1121 return (ENOTSUP);
1122 }
1123
1124 /* ARGSUSED */
1125 static int
rfs4_fattr4_cansettime(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1126 rfs4_fattr4_cansettime(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1127 union nfs4_attr_u *na)
1128 {
1129 int error = 0;
1130
1131 if (RFS4_MANDATTR_ONLY)
1132 return (ENOTSUP);
1133
1134 switch (cmd) {
1135 case NFS4ATTR_SUPPORTED:
1136 if (sarg->op == NFS4ATTR_SETIT)
1137 error = EINVAL;
1138 break; /* this attr is supported */
1139 case NFS4ATTR_GETIT:
1140 na->cansettime = TRUE;
1141 break;
1142 case NFS4ATTR_SETIT:
1143 /*
1144 * read-only attr
1145 */
1146 error = EINVAL;
1147 break;
1148 case NFS4ATTR_VERIT:
1149 if (!na->cansettime)
1150 error = -1; /* no match */
1151 break;
1152 case NFS4ATTR_FREEIT:
1153 break;
1154 }
1155 return (error);
1156 }
1157
1158 /*
1159 * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports
1160 * case insensitive.
1161 */
1162 /* ARGSUSED */
1163 static int
rfs4_fattr4_case_insensitive(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1164 rfs4_fattr4_case_insensitive(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1165 union nfs4_attr_u *na)
1166 {
1167 int error = 0;
1168
1169 if (RFS4_MANDATTR_ONLY)
1170 return (ENOTSUP);
1171
1172 switch (cmd) {
1173 case NFS4ATTR_SUPPORTED:
1174 if (sarg->op == NFS4ATTR_SETIT)
1175 error = EINVAL;
1176 break; /* this attr is supported */
1177 case NFS4ATTR_GETIT:
1178 na->case_insensitive = FALSE;
1179 break;
1180 case NFS4ATTR_SETIT:
1181 /*
1182 * read-only attr
1183 */
1184 error = EINVAL;
1185 break;
1186 case NFS4ATTR_VERIT:
1187 if (!na->case_insensitive)
1188 error = -1; /* no match */
1189 break;
1190 case NFS4ATTR_FREEIT:
1191 break;
1192 }
1193 return (error);
1194 }
1195
1196 /* ARGSUSED */
1197 static int
rfs4_fattr4_case_preserving(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1198 rfs4_fattr4_case_preserving(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1199 union nfs4_attr_u *na)
1200 {
1201 int error = 0;
1202
1203 if (RFS4_MANDATTR_ONLY)
1204 return (ENOTSUP);
1205
1206 switch (cmd) {
1207 case NFS4ATTR_SUPPORTED:
1208 if (sarg->op == NFS4ATTR_SETIT)
1209 error = EINVAL;
1210 break; /* this attr is supported */
1211 case NFS4ATTR_GETIT:
1212 na->case_preserving = TRUE;
1213 break;
1214 case NFS4ATTR_SETIT:
1215 /*
1216 * read-only attr
1217 */
1218 error = EINVAL;
1219 break;
1220 case NFS4ATTR_VERIT:
1221 if (!na->case_preserving)
1222 error = -1; /* no match */
1223 break;
1224 case NFS4ATTR_FREEIT:
1225 break;
1226 }
1227 return (error);
1228 }
1229
1230 /* fattr4_chown_restricted should reall be fattr4_chown_allowed */
1231 /* ARGSUSED */
1232 static int
rfs4_fattr4_chown_restricted(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1233 rfs4_fattr4_chown_restricted(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1234 union nfs4_attr_u *na)
1235 {
1236 int error = 0;
1237 ulong_t val;
1238
1239 if (RFS4_MANDATTR_ONLY)
1240 return (ENOTSUP);
1241
1242 switch (cmd) {
1243 case NFS4ATTR_SUPPORTED:
1244 if (sarg->op == NFS4ATTR_SETIT)
1245 error = EINVAL;
1246 break; /* this attr is supported */
1247 case NFS4ATTR_GETIT:
1248 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
1249 error = -1; /* may be okay if rdattr_error */
1250 break;
1251 }
1252 ASSERT(sarg->cs->vp != NULL);
1253 error = VOP_PATHCONF(sarg->cs->vp,
1254 _PC_CHOWN_RESTRICTED, &val, sarg->cs->cr, NULL);
1255 if (error)
1256 break;
1257
1258 na->chown_restricted = (val == 1);
1259 break;
1260 case NFS4ATTR_SETIT:
1261 /*
1262 * read-only attr
1263 */
1264 error = EINVAL;
1265 break;
1266 case NFS4ATTR_VERIT:
1267 ASSERT(sarg->cs->vp != NULL);
1268 error = VOP_PATHCONF(sarg->cs->vp,
1269 _PC_CHOWN_RESTRICTED, &val, sarg->cs->cr, NULL);
1270 if (error)
1271 break;
1272 if (na->chown_restricted != (val == 1))
1273 error = -1; /* no match */
1274 break;
1275 case NFS4ATTR_FREEIT:
1276 break;
1277 }
1278 return (error);
1279 }
1280
1281 /* ARGSUSED */
1282 static int
rfs4_fattr4_fileid(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1283 rfs4_fattr4_fileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1284 union nfs4_attr_u *na)
1285 {
1286 int error = 0;
1287
1288 if (RFS4_MANDATTR_ONLY)
1289 return (ENOTSUP);
1290
1291 switch (cmd) {
1292 case NFS4ATTR_SUPPORTED:
1293 if (sarg->op == NFS4ATTR_SETIT)
1294 error = EINVAL;
1295 break; /* this attr is supported */
1296 case NFS4ATTR_GETIT:
1297 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NODEID)) {
1298 error = -1; /* may be okay if rdattr_error */
1299 break;
1300 }
1301 ASSERT(sarg->vap->va_mask & AT_NODEID);
1302 na->fileid = sarg->vap->va_nodeid;
1303 break;
1304 case NFS4ATTR_SETIT:
1305 /*
1306 * read-only attr
1307 */
1308 error = EINVAL;
1309 break;
1310 case NFS4ATTR_VERIT:
1311 ASSERT(sarg->vap->va_mask & AT_NODEID);
1312 if (sarg->vap->va_nodeid != na->fileid)
1313 error = -1; /* no match */
1314 break;
1315 case NFS4ATTR_FREEIT:
1316 break;
1317 }
1318 return (error);
1319 }
1320
1321 /* ARGSUSED */
1322 static int
rfs4_get_mntdfileid(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg)1323 rfs4_get_mntdfileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg)
1324 {
1325 int error = 0;
1326 vattr_t *vap, va;
1327 vnode_t *stubvp = NULL, *vp;
1328
1329 vp = sarg->cs->vp;
1330 sarg->mntdfid_set = FALSE;
1331
1332 /*
1333 * VROOT object or zone's root, must untraverse.
1334 *
1335 * NOTE: Not doing reality checks on curzone vs. compound
1336 * state vnode because it will mismatch once at initialization
1337 * if a non-global-zone triggers the module load, BUT in that case
1338 * the vp is literally "/" which has VROOT set.
1339 */
1340 if ((vp->v_flag & VROOT) || VN_IS_CURZONEROOT(vp)) {
1341
1342 /* extra hold for vp since untraverse might rele */
1343 VN_HOLD(vp);
1344 stubvp = untraverse(vp, ZONE_ROOTVP());
1345
1346 /*
1347 * If vp/stubvp are same, we must be at system-or-zone
1348 * root because untraverse returned same vp
1349 * for a VROOT object. sarg->vap was setup
1350 * before we got here, so there's no need to do
1351 * another getattr -- just use the one in sarg.
1352 */
1353 if (VN_CMP(vp, stubvp)) {
1354 ASSERT(VN_IS_CURZONEROOT(vp));
1355 vap = sarg->vap;
1356 } else {
1357 va.va_mask = AT_NODEID;
1358 vap = &va;
1359 error = rfs4_vop_getattr(stubvp, vap, 0, sarg->cs->cr);
1360 }
1361
1362 /*
1363 * Done with stub, time to rele. If vp and stubvp
1364 * were the same, then we need to rele either vp or
1365 * stubvp. If they weren't the same, then untraverse()
1366 * already took case of the extra hold on vp, and only
1367 * the stub needs to be rele'd. Both cases are handled
1368 * by unconditionally rele'ing the stub.
1369 */
1370 VN_RELE(stubvp);
1371 } else
1372 vap = sarg->vap;
1373
1374 /*
1375 * At this point, vap should contain "correct" AT_NODEID --
1376 * (for V_ROOT case, nodeid of stub, for non-VROOT case,
1377 * nodeid of vp). If error or AT_NODEID not available, then
1378 * make the obligatory (yet mysterious) rdattr_error
1379 * check that is so common in the attr code.
1380 */
1381 if (!error && (vap->va_mask & AT_NODEID)) {
1382 sarg->mounted_on_fileid = vap->va_nodeid;
1383 sarg->mntdfid_set = TRUE;
1384 } else if (sarg->rdattr_error)
1385 error = -1;
1386
1387 /*
1388 * error describes these cases:
1389 * 0 : success
1390 * -1: failure due to previous attr processing error (rddir only).
1391 * * : new attr failure (if rddir, caller will set rdattr_error)
1392 */
1393 return (error);
1394 }
1395
1396 /* ARGSUSED */
1397 static int
rfs4_fattr4_mounted_on_fileid(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1398 rfs4_fattr4_mounted_on_fileid(nfs4_attr_cmd_t cmd,
1399 struct nfs4_svgetit_arg *sarg, union nfs4_attr_u *na)
1400 {
1401 int error = 0;
1402
1403 if (RFS4_MANDATTR_ONLY)
1404 return (ENOTSUP);
1405
1406 switch (cmd) {
1407 case NFS4ATTR_SUPPORTED:
1408 if (sarg->op == NFS4ATTR_SETIT)
1409 error = EINVAL;
1410 break; /* this attr is supported */
1411 case NFS4ATTR_GETIT:
1412 case NFS4ATTR_VERIT:
1413 if (!sarg->mntdfid_set)
1414 error = rfs4_get_mntdfileid(cmd, sarg);
1415
1416 if (!error && sarg->mntdfid_set) {
1417 if (cmd == NFS4ATTR_GETIT)
1418 na->mounted_on_fileid = sarg->mounted_on_fileid;
1419 else
1420 if (na->mounted_on_fileid !=
1421 sarg->mounted_on_fileid)
1422 error = -1;
1423 }
1424 break;
1425 case NFS4ATTR_SETIT:
1426 /* read-only attr */
1427 error = EINVAL;
1428 break;
1429 case NFS4ATTR_FREEIT:
1430 break;
1431 }
1432 return (error);
1433 }
1434
1435 /* ARGSUSED */
1436 static int
rfs4_fattr4_files_avail(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1437 rfs4_fattr4_files_avail(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1438 union nfs4_attr_u *na)
1439 {
1440 int error = 0;
1441
1442 if (RFS4_MANDATTR_ONLY)
1443 return (ENOTSUP);
1444
1445 switch (cmd) {
1446 case NFS4ATTR_SUPPORTED:
1447 if (sarg->op == NFS4ATTR_SETIT)
1448 error = EINVAL;
1449 break; /* this attr is supported */
1450 case NFS4ATTR_GETIT:
1451 if (sarg->rdattr_error && (sarg->sbp == NULL)) {
1452 error = -1; /* may be okay if rdattr_error */
1453 break;
1454 }
1455 ASSERT(sarg->sbp != NULL);
1456 na->files_avail = sarg->sbp->f_favail;
1457 break;
1458 case NFS4ATTR_SETIT:
1459 /*
1460 * read-only attr
1461 */
1462 error = EINVAL;
1463 break;
1464 case NFS4ATTR_VERIT:
1465 ASSERT(sarg->sbp != NULL);
1466 if (sarg->sbp->f_favail != na->files_avail)
1467 error = -1; /* no match */
1468 break;
1469 case NFS4ATTR_FREEIT:
1470 break;
1471 }
1472 return (error);
1473 }
1474
1475 /* ARGSUSED */
1476 static int
rfs4_fattr4_files_free(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1477 rfs4_fattr4_files_free(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1478 union nfs4_attr_u *na)
1479 {
1480 int error = 0;
1481
1482 if (RFS4_MANDATTR_ONLY)
1483 return (ENOTSUP);
1484
1485 switch (cmd) {
1486 case NFS4ATTR_SUPPORTED:
1487 if (sarg->op == NFS4ATTR_SETIT)
1488 error = EINVAL;
1489 break; /* this attr is supported */
1490 case NFS4ATTR_GETIT:
1491 if (sarg->rdattr_error && (sarg->sbp == NULL)) {
1492 error = -1; /* may be okay if rdattr_error */
1493 break;
1494 }
1495 ASSERT(sarg->sbp != NULL);
1496 na->files_free = sarg->sbp->f_ffree;
1497 break;
1498 case NFS4ATTR_SETIT:
1499 /*
1500 * read-only attr
1501 */
1502 error = EINVAL;
1503 break;
1504 case NFS4ATTR_VERIT:
1505 ASSERT(sarg->sbp != NULL);
1506 if (sarg->sbp->f_ffree != na->files_free)
1507 error = -1; /* no match */
1508 break;
1509 case NFS4ATTR_FREEIT:
1510 break;
1511 }
1512 return (error);
1513 }
1514
1515 /* ARGSUSED */
1516 static int
rfs4_fattr4_files_total(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1517 rfs4_fattr4_files_total(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1518 union nfs4_attr_u *na)
1519 {
1520 int error = 0;
1521
1522 if (RFS4_MANDATTR_ONLY)
1523 return (ENOTSUP);
1524
1525 switch (cmd) {
1526 case NFS4ATTR_SUPPORTED:
1527 if (sarg->op == NFS4ATTR_SETIT)
1528 error = EINVAL;
1529 break; /* this attr is supported */
1530 case NFS4ATTR_GETIT:
1531 if (sarg->rdattr_error && (sarg->sbp == NULL)) {
1532 error = -1; /* may be okay if rdattr_error */
1533 break;
1534 }
1535 ASSERT(sarg->sbp != NULL);
1536 na->files_total = sarg->sbp->f_files;
1537 break;
1538 case NFS4ATTR_SETIT:
1539 /*
1540 * read-only attr
1541 */
1542 error = EINVAL;
1543 break;
1544 case NFS4ATTR_VERIT:
1545 ASSERT(sarg->sbp != NULL);
1546 if (sarg->sbp->f_files != na->files_total)
1547 error = -1; /* no match */
1548 break;
1549 case NFS4ATTR_FREEIT:
1550 break;
1551 }
1552 return (error);
1553 }
1554
1555 static void
rfs4_free_pathname4(pathname4 * pn4)1556 rfs4_free_pathname4(pathname4 *pn4)
1557 {
1558 int i, len;
1559 utf8string *utf8s;
1560
1561 if (pn4 == NULL || (len = pn4->pathname4_len) == 0 ||
1562 (utf8s = pn4->pathname4_val) == NULL)
1563 return;
1564
1565 for (i = 0; i < len; i++, utf8s++) {
1566 if (utf8s->utf8string_val == NULL ||
1567 utf8s->utf8string_len == 0)
1568 continue;
1569
1570 kmem_free(utf8s->utf8string_val, utf8s->utf8string_len);
1571 utf8s->utf8string_val = NULL;
1572 }
1573
1574 kmem_free(pn4->pathname4_val,
1575 sizeof (utf8string) * pn4->pathname4_len);
1576 pn4->pathname4_val = 0;
1577 }
1578
1579 static void
rfs4_free_fs_location4(fs_location4 * fsl4)1580 rfs4_free_fs_location4(fs_location4 *fsl4)
1581 {
1582 if (fsl4 == NULL)
1583 return;
1584
1585 rfs4_free_pathname4((pathname4 *)&fsl4->server_len);
1586 rfs4_free_pathname4(&fsl4->rootpath);
1587 }
1588
1589 void
rfs4_free_fs_locations4(fs_locations4 * fsls4)1590 rfs4_free_fs_locations4(fs_locations4 *fsls4)
1591 {
1592 int i, len;
1593 fs_location4 *fsl4;
1594
1595 if (fsls4 == NULL)
1596 return;
1597
1598 /* free fs_root */
1599 rfs4_free_pathname4(&fsls4->fs_root);
1600
1601 if ((len = fsls4->locations_len) == 0 ||
1602 (fsl4 = fsls4->locations_val) == NULL)
1603 return;
1604
1605 /* free fs_location4 */
1606 for (i = 0; i < len; i++) {
1607 rfs4_free_fs_location4(fsl4);
1608 fsl4++;
1609 }
1610
1611 kmem_free(fsls4->locations_val, sizeof (fs_location4) * len);
1612 fsls4->locations_val = NULL;
1613 }
1614
1615 /* ARGSUSED */
1616 static int
rfs4_fattr4_fs_locations(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1617 rfs4_fattr4_fs_locations(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1618 union nfs4_attr_u *na)
1619 {
1620 int error = 0;
1621 fs_locations4 *fsl;
1622
1623 if (RFS4_MANDATTR_ONLY)
1624 return (ENOTSUP);
1625
1626 switch (cmd) {
1627 case NFS4ATTR_SUPPORTED:
1628 if (sarg->op == NFS4ATTR_SETIT || sarg->op == NFS4ATTR_VERIT)
1629 error = EINVAL;
1630 break; /* this attr is supported */
1631
1632 case NFS4ATTR_GETIT:
1633 {
1634 kstat_named_t *stat =
1635 sarg->cs->exi->exi_ne->ne_globals->svstat[NFS_V4];
1636
1637 fsl = fetch_referral(sarg->cs->vp, sarg->cs->cr);
1638 if (fsl == NULL)
1639 (void) memset(&(na->fs_locations), 0,
1640 sizeof (fs_locations4));
1641 else {
1642 na->fs_locations = *fsl;
1643 kmem_free(fsl, sizeof (fs_locations4));
1644 }
1645 stat[NFS_REFERRALS].value.ui64++;
1646 break;
1647 }
1648 case NFS4ATTR_FREEIT:
1649 if (sarg->op == NFS4ATTR_SETIT || sarg->op == NFS4ATTR_VERIT)
1650 error = EINVAL;
1651 rfs4_free_fs_locations4(&na->fs_locations);
1652 break;
1653
1654 case NFS4ATTR_SETIT:
1655 case NFS4ATTR_VERIT:
1656 /*
1657 * read-only attr
1658 */
1659 error = EINVAL;
1660 break;
1661 }
1662 return (error);
1663 }
1664
1665 /* ARGSUSED */
1666 static int
rfs4_fattr4_hidden(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1667 rfs4_fattr4_hidden(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1668 union nfs4_attr_u *na)
1669 {
1670 return (ENOTSUP);
1671 }
1672
1673 /* ARGSUSED */
1674 static int
rfs4_fattr4_homogeneous(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1675 rfs4_fattr4_homogeneous(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1676 union nfs4_attr_u *na)
1677 {
1678 int error = 0;
1679
1680 if (RFS4_MANDATTR_ONLY)
1681 return (ENOTSUP);
1682
1683 switch (cmd) {
1684 case NFS4ATTR_SUPPORTED:
1685 if (sarg->op == NFS4ATTR_SETIT)
1686 error = EINVAL;
1687 break; /* this attr is supported */
1688 case NFS4ATTR_GETIT:
1689 na->homogeneous = TRUE; /* XXX - need a VOP extension */
1690 break;
1691 case NFS4ATTR_SETIT:
1692 /*
1693 * read-only attr
1694 */
1695 error = EINVAL;
1696 break;
1697 case NFS4ATTR_VERIT:
1698 if (!na->homogeneous)
1699 error = -1; /* no match */
1700 break;
1701 case NFS4ATTR_FREEIT:
1702 break;
1703 }
1704 return (error);
1705 }
1706
1707 /* ARGSUSED */
1708 static int
rfs4_fattr4_maxfilesize(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1709 rfs4_fattr4_maxfilesize(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1710 union nfs4_attr_u *na)
1711 {
1712 int error = 0;
1713 ulong_t val;
1714 fattr4_maxfilesize maxfilesize;
1715
1716 if (RFS4_MANDATTR_ONLY)
1717 return (ENOTSUP);
1718
1719 switch (cmd) {
1720 case NFS4ATTR_SUPPORTED:
1721 if (sarg->op == NFS4ATTR_SETIT)
1722 error = EINVAL;
1723 break; /* this attr is supported */
1724 case NFS4ATTR_GETIT:
1725 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
1726 error = -1; /* may be okay if rdattr_error */
1727 break;
1728 }
1729 ASSERT(sarg->cs->vp != NULL);
1730 error = VOP_PATHCONF(sarg->cs->vp, _PC_FILESIZEBITS, &val,
1731 sarg->cs->cr, NULL);
1732 if (error)
1733 break;
1734
1735 /*
1736 * If the underlying file system does not support
1737 * _PC_FILESIZEBITS, return a reasonable default. Note that
1738 * error code on VOP_PATHCONF will be 0, even if the underlying
1739 * file system does not support _PC_FILESIZEBITS.
1740 */
1741 if (val == (ulong_t)-1) {
1742 na->maxfilesize = MAXOFF32_T;
1743 } else {
1744 if (val >= (sizeof (uint64_t) * 8))
1745 na->maxfilesize = INT64_MAX;
1746 else
1747 na->maxfilesize = ((1LL << (val - 1)) - 1);
1748 }
1749 break;
1750 case NFS4ATTR_SETIT:
1751 /*
1752 * read-only attr
1753 */
1754 error = EINVAL;
1755 break;
1756 case NFS4ATTR_VERIT:
1757 ASSERT(sarg->cs->vp != NULL);
1758 error = VOP_PATHCONF(sarg->cs->vp, _PC_FILESIZEBITS, &val,
1759 sarg->cs->cr, NULL);
1760 if (error)
1761 break;
1762 /*
1763 * If the underlying file system does not support
1764 * _PC_FILESIZEBITS, return a reasonable default. Note that
1765 * error code on VOP_PATHCONF will be 0, even if the underlying
1766 * file system does not support _PC_FILESIZEBITS.
1767 */
1768 if (val == (ulong_t)-1) {
1769 maxfilesize = MAXOFF32_T;
1770 } else {
1771 if (val >= (sizeof (uint64_t) * 8))
1772 maxfilesize = INT64_MAX;
1773 else
1774 maxfilesize = ((1LL << (val - 1)) - 1);
1775 }
1776 if (na->maxfilesize != maxfilesize)
1777 error = -1; /* no match */
1778 break;
1779 case NFS4ATTR_FREEIT:
1780 break;
1781 }
1782 return (error);
1783 }
1784
1785 /* ARGSUSED */
1786 static int
rfs4_fattr4_maxlink(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1787 rfs4_fattr4_maxlink(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1788 union nfs4_attr_u *na)
1789 {
1790 int error = 0;
1791 ulong_t val;
1792
1793 if (RFS4_MANDATTR_ONLY)
1794 return (ENOTSUP);
1795
1796 switch (cmd) {
1797 case NFS4ATTR_SUPPORTED:
1798 if (sarg->op == NFS4ATTR_SETIT)
1799 error = EINVAL;
1800 break; /* this attr is supported */
1801 case NFS4ATTR_GETIT:
1802 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
1803 error = -1; /* may be okay if rdattr_error */
1804 break;
1805 }
1806 ASSERT(sarg->cs->vp != NULL);
1807 error = VOP_PATHCONF(sarg->cs->vp, _PC_LINK_MAX, &val,
1808 sarg->cs->cr, NULL);
1809 if (error == 0) {
1810 na->maxlink = val;
1811 }
1812 break;
1813 case NFS4ATTR_SETIT:
1814 /*
1815 * read-only attr
1816 */
1817 error = EINVAL;
1818 break;
1819 case NFS4ATTR_VERIT:
1820 ASSERT(sarg->cs->vp != NULL);
1821 error = VOP_PATHCONF(sarg->cs->vp, _PC_LINK_MAX, &val,
1822 sarg->cs->cr, NULL);
1823 if (!error && (na->maxlink != (uint32_t)val))
1824 error = -1; /* no match */
1825 break;
1826 case NFS4ATTR_FREEIT:
1827 break;
1828 }
1829 return (error);
1830 }
1831
1832 /* ARGSUSED */
1833 static int
rfs4_fattr4_maxname(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1834 rfs4_fattr4_maxname(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1835 union nfs4_attr_u *na)
1836 {
1837 int error = 0;
1838 ulong_t val;
1839
1840 if (RFS4_MANDATTR_ONLY)
1841 return (ENOTSUP);
1842
1843 switch (cmd) {
1844 case NFS4ATTR_SUPPORTED:
1845 if (sarg->op == NFS4ATTR_SETIT)
1846 error = EINVAL;
1847 break; /* this attr is supported */
1848 case NFS4ATTR_GETIT:
1849 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
1850 error = -1; /* may be okay if rdattr_error */
1851 break;
1852 }
1853 ASSERT(sarg->cs->vp != NULL);
1854 error = VOP_PATHCONF(sarg->cs->vp, _PC_NAME_MAX, &val,
1855 sarg->cs->cr, NULL);
1856 if (error == 0) {
1857 na->maxname = val;
1858 }
1859 break;
1860 case NFS4ATTR_SETIT:
1861 /*
1862 * read-only attr
1863 */
1864 error = EINVAL;
1865 break;
1866 case NFS4ATTR_VERIT:
1867 ASSERT(sarg->cs->vp != NULL);
1868 error = VOP_PATHCONF(sarg->cs->vp, _PC_NAME_MAX, &val,
1869 sarg->cs->cr, NULL);
1870 if (!error && (na->maxname != val))
1871 error = -1; /* no match */
1872 break;
1873 case NFS4ATTR_FREEIT:
1874 break;
1875 }
1876 return (error);
1877 }
1878
1879 /* ARGSUSED */
1880 static int
rfs4_fattr4_maxread(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1881 rfs4_fattr4_maxread(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1882 union nfs4_attr_u *na)
1883 {
1884 int error = 0;
1885
1886 if (RFS4_MANDATTR_ONLY)
1887 return (ENOTSUP);
1888
1889 switch (cmd) {
1890 case NFS4ATTR_SUPPORTED:
1891 if (sarg->op == NFS4ATTR_SETIT)
1892 error = EINVAL;
1893 break; /* this attr is supported */
1894 case NFS4ATTR_GETIT:
1895 na->maxread = rfs4_tsize(sarg->cs->req);
1896 break;
1897 case NFS4ATTR_SETIT:
1898 /*
1899 * read-only attr
1900 */
1901 error = EINVAL;
1902 break;
1903 case NFS4ATTR_VERIT:
1904 if (na->maxread != rfs4_tsize(sarg->cs->req))
1905 error = -1; /* no match */
1906 break;
1907 case NFS4ATTR_FREEIT:
1908 break;
1909 }
1910 return (error);
1911 }
1912
1913 /* ARGSUSED */
1914 static int
rfs4_fattr4_maxwrite(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1915 rfs4_fattr4_maxwrite(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1916 union nfs4_attr_u *na)
1917 {
1918 int error = 0;
1919
1920 if (RFS4_MANDATTR_ONLY)
1921 return (ENOTSUP);
1922
1923 switch (cmd) {
1924 case NFS4ATTR_SUPPORTED:
1925 if (sarg->op == NFS4ATTR_SETIT)
1926 error = EINVAL;
1927 break; /* this attr is supported */
1928 case NFS4ATTR_GETIT:
1929 na->maxwrite = rfs4_tsize(sarg->cs->req);
1930 break;
1931 case NFS4ATTR_SETIT:
1932 /*
1933 * read-only attr
1934 */
1935 error = EINVAL;
1936 break;
1937 case NFS4ATTR_VERIT:
1938 if (na->maxwrite != rfs4_tsize(sarg->cs->req))
1939 error = -1; /* no match */
1940 break;
1941 case NFS4ATTR_FREEIT:
1942 break;
1943 }
1944 return (error);
1945 }
1946
1947 /* ARGSUSED */
1948 static int
rfs4_fattr4_mimetype(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1949 rfs4_fattr4_mimetype(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1950 union nfs4_attr_u *na)
1951 {
1952 return (ENOTSUP);
1953 }
1954
1955 /* ARGSUSED */
1956 static int
rfs4_fattr4_mode(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)1957 rfs4_fattr4_mode(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1958 union nfs4_attr_u *na)
1959 {
1960 int error = 0;
1961
1962 if (RFS4_MANDATTR_ONLY)
1963 return (ENOTSUP);
1964
1965 switch (cmd) {
1966 case NFS4ATTR_SUPPORTED:
1967 break; /* this attr is supported */
1968 case NFS4ATTR_GETIT:
1969 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_MODE)) {
1970 error = -1; /* may be okay if rdattr_error */
1971 break;
1972 }
1973 ASSERT(sarg->vap->va_mask & AT_MODE);
1974 na->mode = sarg->vap->va_mode;
1975 break;
1976 case NFS4ATTR_SETIT:
1977 ASSERT(sarg->vap->va_mask & AT_MODE);
1978 sarg->vap->va_mode = na->mode;
1979 /*
1980 * If the filesystem is exported with nosuid, then mask off
1981 * the setuid and setgid bits.
1982 */
1983 if (sarg->cs->vp->v_type == VREG &&
1984 (sarg->cs->exi->exi_export.ex_flags & EX_NOSUID))
1985 sarg->vap->va_mode &= ~(VSUID | VSGID);
1986 break;
1987 case NFS4ATTR_VERIT:
1988 ASSERT(sarg->vap->va_mask & AT_MODE);
1989 if (sarg->vap->va_mode != na->mode)
1990 error = -1; /* no match */
1991 break;
1992 case NFS4ATTR_FREEIT:
1993 break;
1994 }
1995 return (error);
1996 }
1997
1998 /* ARGSUSED */
1999 static int
rfs4_fattr4_no_trunc(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2000 rfs4_fattr4_no_trunc(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2001 union nfs4_attr_u *na)
2002 {
2003 int error = 0;
2004
2005 if (RFS4_MANDATTR_ONLY)
2006 return (ENOTSUP);
2007
2008 switch (cmd) {
2009 case NFS4ATTR_SUPPORTED:
2010 if (sarg->op == NFS4ATTR_SETIT)
2011 error = EINVAL;
2012 break; /* this attr is supported */
2013 case NFS4ATTR_GETIT:
2014 na->no_trunc = TRUE;
2015 break;
2016 case NFS4ATTR_SETIT:
2017 /*
2018 * read-only attr
2019 */
2020 error = EINVAL;
2021 break;
2022 case NFS4ATTR_VERIT:
2023 if (!na->no_trunc)
2024 error = -1; /* no match */
2025 break;
2026 case NFS4ATTR_FREEIT:
2027 break;
2028 }
2029 return (error);
2030 }
2031
2032 /* ARGSUSED */
2033 static int
rfs4_fattr4_numlinks(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2034 rfs4_fattr4_numlinks(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2035 union nfs4_attr_u *na)
2036 {
2037 int error = 0;
2038
2039 if (RFS4_MANDATTR_ONLY)
2040 return (ENOTSUP);
2041
2042 switch (cmd) {
2043 case NFS4ATTR_SUPPORTED:
2044 if (sarg->op == NFS4ATTR_SETIT)
2045 error = EINVAL;
2046 break; /* this attr is supported */
2047 case NFS4ATTR_GETIT:
2048 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NLINK)) {
2049 error = -1; /* may be okay if rdattr_error */
2050 break;
2051 }
2052 ASSERT(sarg->vap->va_mask & AT_NLINK);
2053 na->numlinks = sarg->vap->va_nlink;
2054 break;
2055 case NFS4ATTR_SETIT:
2056 /*
2057 * read-only attr
2058 */
2059 error = EINVAL;
2060 break;
2061 case NFS4ATTR_VERIT:
2062 ASSERT(sarg->vap->va_mask & AT_NLINK);
2063 if (sarg->vap->va_nlink != na->numlinks)
2064 error = -1; /* no match */
2065 break;
2066 case NFS4ATTR_FREEIT:
2067 break;
2068 }
2069 return (error);
2070 }
2071
2072 /* ARGSUSED */
2073 static int
rfs4_fattr4_owner(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2074 rfs4_fattr4_owner(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2075 union nfs4_attr_u *na)
2076 {
2077 int error = 0;
2078 uid_t uid;
2079
2080 if (RFS4_MANDATTR_ONLY)
2081 return (ENOTSUP);
2082
2083 switch (cmd) {
2084 case NFS4ATTR_SUPPORTED:
2085 break; /* this attr is supported */
2086 case NFS4ATTR_GETIT:
2087 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_UID)) {
2088 error = -1; /* may be okay if rdattr_error */
2089 break;
2090 }
2091 ASSERT(sarg->vap->va_mask & AT_UID);
2092
2093 /*
2094 * There are well defined polices for what happens on server-
2095 * side GETATTR when uid to attribute string conversion cannot
2096 * occur. Please refer to nfs4_idmap.c for details.
2097 */
2098 error = nfs_idmap_uid_str(sarg->vap->va_uid, &na->owner, TRUE);
2099 switch (error) {
2100 case ECONNREFUSED:
2101 error = NFS4ERR_DELAY;
2102 break;
2103 default:
2104 break;
2105 }
2106 break;
2107
2108 case NFS4ATTR_SETIT:
2109 ASSERT(sarg->vap->va_mask & AT_UID);
2110
2111 /*
2112 * There are well defined policies for what happens on server-
2113 * side SETATTR of 'owner' when a "user@domain" mapping cannot
2114 * occur. Please refer to nfs4_idmap.c for details.
2115 *
2116 * Any other errors, such as the mapping not being found by
2117 * nfsmapid(8), and interrupted clnt_call, etc, will result
2118 * in NFS4ERR_BADOWNER.
2119 *
2120 * XXX need to return consistent errors, perhaps all
2121 * server side attribute routines should return NFS4ERR*.
2122 */
2123 error = nfs_idmap_str_uid(&na->owner, &sarg->vap->va_uid, TRUE);
2124 switch (error) {
2125 case NFS4_OK:
2126 case ENOTSUP:
2127 /*
2128 * Ignore warning that we are the
2129 * nfsmapid (can't happen on srv)
2130 */
2131 error = 0;
2132 MSG_PRT_DEBUG = FALSE;
2133 break;
2134
2135 case ECOMM:
2136 case ECONNREFUSED:
2137 if (!MSG_PRT_DEBUG) {
2138 /*
2139 * printed just once per daemon death,
2140 * inform the user and then stay silent
2141 */
2142 cmn_err(CE_WARN, "!Unable to contact "
2143 "nfsmapid");
2144 MSG_PRT_DEBUG = TRUE;
2145 }
2146 error = NFS4ERR_DELAY;
2147 break;
2148
2149 case EINVAL:
2150 error = NFS4ERR_INVAL;
2151 break;
2152
2153 default:
2154 error = NFS4ERR_BADOWNER;
2155 break;
2156 }
2157 break;
2158
2159 case NFS4ATTR_VERIT:
2160 ASSERT(sarg->vap->va_mask & AT_UID);
2161 error = nfs_idmap_str_uid(&na->owner, &uid, TRUE);
2162 /*
2163 * Ignore warning that we are the nfsmapid (can't happen on srv)
2164 */
2165 if (error == ENOTSUP)
2166 error = 0;
2167 if (error)
2168 error = -1; /* no match */
2169 else if (sarg->vap->va_uid != uid)
2170 error = -1; /* no match */
2171 break;
2172 case NFS4ATTR_FREEIT:
2173 if (sarg->op == NFS4ATTR_GETIT) {
2174 if (na->owner.utf8string_val) {
2175 UTF8STRING_FREE(na->owner)
2176 bzero(&na->owner, sizeof (na->owner));
2177 }
2178 }
2179 break;
2180 }
2181 return (error);
2182 }
2183
2184 /* ARGSUSED */
2185 static int
rfs4_fattr4_owner_group(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2186 rfs4_fattr4_owner_group(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2187 union nfs4_attr_u *na)
2188 {
2189 int error = 0;
2190 gid_t gid;
2191
2192 if (RFS4_MANDATTR_ONLY)
2193 return (ENOTSUP);
2194
2195 switch (cmd) {
2196 case NFS4ATTR_SUPPORTED:
2197 break; /* this attr is supported */
2198 case NFS4ATTR_GETIT:
2199 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_GID)) {
2200 error = -1; /* may be okay if rdattr_error */
2201 break;
2202 }
2203 ASSERT(sarg->vap->va_mask & AT_GID);
2204
2205 /*
2206 * There are well defined polices for what happens on server-
2207 * side GETATTR when gid to attribute string conversion cannot
2208 * occur. Please refer to nfs4_idmap.c for details.
2209 */
2210 error = nfs_idmap_gid_str(sarg->vap->va_gid, &na->owner_group,
2211 TRUE);
2212 switch (error) {
2213 case ECONNREFUSED:
2214 error = NFS4ERR_DELAY;
2215 break;
2216 default:
2217 break;
2218 }
2219 break;
2220
2221 case NFS4ATTR_SETIT:
2222 ASSERT(sarg->vap->va_mask & AT_GID);
2223
2224 /*
2225 * There are well defined policies for what happens on server-
2226 * side SETATTR of 'owner_group' when a "group@domain" mapping
2227 * cannot occur. Please refer to nfs4_idmap.c for details.
2228 *
2229 * Any other errors, such as the mapping not being found by
2230 * nfsmapid(8), and interrupted clnt_call, etc, will result
2231 * in NFS4ERR_BADOWNER.
2232 *
2233 * XXX need to return consistent errors, perhaps all
2234 * server side attribute routines should return NFS4ERR*.
2235 */
2236 error = nfs_idmap_str_gid(&na->owner_group, &sarg->vap->va_gid,
2237 TRUE);
2238 switch (error) {
2239 case NFS4_OK:
2240 case ENOTSUP:
2241 /*
2242 * Ignore warning that we are the
2243 * nfsmapid (can't happen on srv)
2244 */
2245 error = 0;
2246 MSG_PRT_DEBUG = FALSE;
2247 break;
2248
2249 case ECOMM:
2250 case ECONNREFUSED:
2251 if (!MSG_PRT_DEBUG) {
2252 /*
2253 * printed just once per daemon death,
2254 * inform the user and then stay silent
2255 */
2256 cmn_err(CE_WARN, "!Unable to contact "
2257 "nfsmapid");
2258 MSG_PRT_DEBUG = TRUE;
2259 }
2260 error = NFS4ERR_DELAY;
2261 break;
2262
2263 case EINVAL:
2264 error = NFS4ERR_INVAL;
2265 break;
2266
2267 default:
2268 error = NFS4ERR_BADOWNER;
2269 break;
2270 }
2271 break;
2272
2273 case NFS4ATTR_VERIT:
2274 ASSERT(sarg->vap->va_mask & AT_GID);
2275 error = nfs_idmap_str_gid(&na->owner_group, &gid, TRUE);
2276 /*
2277 * Ignore warning that we are the nfsmapid (can't happen on srv)
2278 */
2279 if (error == ENOTSUP)
2280 error = 0;
2281 if (error)
2282 error = -1; /* no match */
2283 else if (sarg->vap->va_gid != gid)
2284 error = -1; /* no match */
2285 break;
2286 case NFS4ATTR_FREEIT:
2287 if (sarg->op == NFS4ATTR_GETIT) {
2288 if (na->owner_group.utf8string_val) {
2289 UTF8STRING_FREE(na->owner_group)
2290 bzero(&na->owner_group,
2291 sizeof (na->owner_group));
2292 }
2293 }
2294 break;
2295 }
2296 return (error);
2297 }
2298
2299 /* XXX - quota attributes should be supportable on Solaris 2 */
2300 /* ARGSUSED */
2301 static int
rfs4_fattr4_quota_avail_hard(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2302 rfs4_fattr4_quota_avail_hard(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2303 union nfs4_attr_u *na)
2304 {
2305 return (ENOTSUP);
2306 }
2307
2308 /* ARGSUSED */
2309 static int
rfs4_fattr4_quota_avail_soft(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2310 rfs4_fattr4_quota_avail_soft(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2311 union nfs4_attr_u *na)
2312 {
2313 return (ENOTSUP);
2314 }
2315
2316 /* ARGSUSED */
2317 static int
rfs4_fattr4_quota_used(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2318 rfs4_fattr4_quota_used(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2319 union nfs4_attr_u *na)
2320 {
2321 return (ENOTSUP);
2322 }
2323
2324 /* ARGSUSED */
2325 static int
rfs4_fattr4_rawdev(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2326 rfs4_fattr4_rawdev(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2327 union nfs4_attr_u *na)
2328 {
2329 int error = 0;
2330
2331 if (RFS4_MANDATTR_ONLY)
2332 return (ENOTSUP);
2333
2334 switch (cmd) {
2335 case NFS4ATTR_SUPPORTED:
2336 if (sarg->op == NFS4ATTR_SETIT)
2337 error = EINVAL;
2338 break; /* this attr is supported */
2339 case NFS4ATTR_GETIT:
2340 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_RDEV)) {
2341 error = -1; /* may be okay if rdattr_error */
2342 break;
2343 }
2344 ASSERT(sarg->vap->va_mask & AT_RDEV);
2345 na->rawdev.specdata1 = (uint32)getmajor(sarg->vap->va_rdev);
2346 na->rawdev.specdata2 = (uint32)getminor(sarg->vap->va_rdev);
2347 break;
2348 case NFS4ATTR_SETIT:
2349 /*
2350 * read-only attr
2351 */
2352 error = EINVAL;
2353 break;
2354 case NFS4ATTR_VERIT:
2355 ASSERT(sarg->vap->va_mask & AT_RDEV);
2356 if ((na->rawdev.specdata1 !=
2357 (uint32)getmajor(sarg->vap->va_rdev)) ||
2358 (na->rawdev.specdata2 !=
2359 (uint32)getminor(sarg->vap->va_rdev)))
2360 error = -1; /* no match */
2361 break;
2362 case NFS4ATTR_FREEIT:
2363 break;
2364 }
2365 return (error);
2366 }
2367
2368 /* ARGSUSED */
2369 static int
rfs4_fattr4_space_avail(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2370 rfs4_fattr4_space_avail(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2371 union nfs4_attr_u *na)
2372 {
2373 int error = 0;
2374
2375 if (RFS4_MANDATTR_ONLY)
2376 return (ENOTSUP);
2377
2378 switch (cmd) {
2379 case NFS4ATTR_SUPPORTED:
2380 if (sarg->op == NFS4ATTR_SETIT)
2381 error = EINVAL;
2382 break; /* this attr is supported */
2383 case NFS4ATTR_GETIT:
2384 if (sarg->rdattr_error && (sarg->sbp == NULL)) {
2385 error = -1; /* may be okay if rdattr_error */
2386 break;
2387 }
2388 ASSERT(sarg->sbp != NULL);
2389 if (sarg->sbp->f_bavail != (fsblkcnt64_t)-1) {
2390 na->space_avail =
2391 (fattr4_space_avail) sarg->sbp->f_frsize *
2392 (fattr4_space_avail) sarg->sbp->f_bavail;
2393 } else {
2394 na->space_avail =
2395 (fattr4_space_avail) sarg->sbp->f_bavail;
2396 }
2397 break;
2398 case NFS4ATTR_SETIT:
2399 /*
2400 * read-only attr
2401 */
2402 error = EINVAL;
2403 break;
2404 case NFS4ATTR_VERIT:
2405 ASSERT(sarg->sbp != NULL);
2406 if (sarg->sbp->f_bavail != na->space_avail)
2407 error = -1; /* no match */
2408 break;
2409 case NFS4ATTR_FREEIT:
2410 break;
2411 }
2412 return (error);
2413 }
2414
2415 /* ARGSUSED */
2416 static int
rfs4_fattr4_space_free(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2417 rfs4_fattr4_space_free(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2418 union nfs4_attr_u *na)
2419 {
2420 int error = 0;
2421
2422 if (RFS4_MANDATTR_ONLY)
2423 return (ENOTSUP);
2424
2425 switch (cmd) {
2426 case NFS4ATTR_SUPPORTED:
2427 if (sarg->op == NFS4ATTR_SETIT)
2428 error = EINVAL;
2429 break; /* this attr is supported */
2430 case NFS4ATTR_GETIT:
2431 if (sarg->rdattr_error && (sarg->sbp == NULL)) {
2432 error = -1; /* may be okay if rdattr_error */
2433 break;
2434 }
2435 ASSERT(sarg->sbp != NULL);
2436 if (sarg->sbp->f_bfree != (fsblkcnt64_t)-1) {
2437 na->space_free =
2438 (fattr4_space_free) sarg->sbp->f_frsize *
2439 (fattr4_space_free) sarg->sbp->f_bfree;
2440 } else {
2441 na->space_free =
2442 (fattr4_space_free) sarg->sbp->f_bfree;
2443 }
2444 break;
2445 case NFS4ATTR_SETIT:
2446 /*
2447 * read-only attr
2448 */
2449 error = EINVAL;
2450 break;
2451 case NFS4ATTR_VERIT:
2452 ASSERT(sarg->sbp != NULL);
2453 if (sarg->sbp->f_bfree != na->space_free)
2454 error = -1; /* no match */
2455 break;
2456 case NFS4ATTR_FREEIT:
2457 break;
2458 }
2459 return (error);
2460 }
2461
2462 /* ARGSUSED */
2463 static int
rfs4_fattr4_space_total(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2464 rfs4_fattr4_space_total(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2465 union nfs4_attr_u *na)
2466 {
2467 int error = 0;
2468
2469 if (RFS4_MANDATTR_ONLY)
2470 return (ENOTSUP);
2471
2472 switch (cmd) {
2473 case NFS4ATTR_SUPPORTED:
2474 if (sarg->op == NFS4ATTR_SETIT)
2475 error = EINVAL;
2476 break; /* this attr is supported */
2477 case NFS4ATTR_GETIT:
2478 if (sarg->rdattr_error_req && (sarg->sbp == NULL)) {
2479 error = -1; /* may be okay if rdattr_error */
2480 break;
2481 }
2482 ASSERT(sarg->sbp != NULL);
2483 if (sarg->sbp->f_blocks != (fsblkcnt64_t)-1) {
2484 na->space_total =
2485 (fattr4_space_total) sarg->sbp->f_frsize *
2486 (fattr4_space_total) sarg->sbp->f_blocks;
2487 } else {
2488 na->space_total =
2489 (fattr4_space_total) sarg->sbp->f_blocks;
2490 }
2491 break;
2492 case NFS4ATTR_SETIT:
2493 /*
2494 * read-only attr
2495 */
2496 error = EINVAL;
2497 break;
2498 case NFS4ATTR_VERIT:
2499 ASSERT(sarg->sbp != NULL);
2500 if (sarg->sbp->f_blocks != na->space_total)
2501 error = -1; /* no match */
2502 break;
2503 case NFS4ATTR_FREEIT:
2504 break;
2505 }
2506 return (error);
2507 }
2508
2509 /* ARGSUSED */
2510 static int
rfs4_fattr4_space_used(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2511 rfs4_fattr4_space_used(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2512 union nfs4_attr_u *na)
2513 {
2514 int error = 0;
2515
2516 if (RFS4_MANDATTR_ONLY)
2517 return (ENOTSUP);
2518
2519 switch (cmd) {
2520 case NFS4ATTR_SUPPORTED:
2521 if (sarg->op == NFS4ATTR_SETIT)
2522 error = EINVAL;
2523 break; /* this attr is supported */
2524 case NFS4ATTR_GETIT:
2525 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NBLOCKS)) {
2526 error = -1; /* may be okay if rdattr_error */
2527 break;
2528 }
2529 ASSERT(sarg->vap->va_mask & AT_NBLOCKS);
2530 na->space_used = (fattr4_space_used) DEV_BSIZE *
2531 (fattr4_space_used) sarg->vap->va_nblocks;
2532 break;
2533 case NFS4ATTR_SETIT:
2534 /*
2535 * read-only attr
2536 */
2537 error = EINVAL;
2538 break;
2539 case NFS4ATTR_VERIT:
2540 ASSERT(sarg->vap->va_mask & AT_NBLOCKS);
2541 if (sarg->vap->va_nblocks != na->space_used)
2542 error = -1; /* no match */
2543 break;
2544 case NFS4ATTR_FREEIT:
2545 break;
2546 }
2547 return (error);
2548 }
2549
2550 /* ARGSUSED */
2551 static int
rfs4_fattr4_system(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2552 rfs4_fattr4_system(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2553 union nfs4_attr_u *na)
2554 {
2555 return (ENOTSUP);
2556 }
2557
2558 /* ARGSUSED */
2559 static int
rfs4_fattr4_time_access(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2560 rfs4_fattr4_time_access(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2561 union nfs4_attr_u *na)
2562 {
2563 int error = 0;
2564 timestruc_t atime;
2565
2566 if (RFS4_MANDATTR_ONLY)
2567 return (ENOTSUP);
2568
2569 switch (cmd) {
2570 case NFS4ATTR_SUPPORTED:
2571 if (sarg->op == NFS4ATTR_SETIT)
2572 error = EINVAL;
2573 break; /* this attr is supported */
2574 case NFS4ATTR_GETIT:
2575 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_ATIME)) {
2576 error = -1; /* may be okay if rdattr_error */
2577 break;
2578 }
2579 ASSERT(sarg->vap->va_mask & AT_ATIME);
2580 error = nfs4_time_vton(&sarg->vap->va_atime, &na->time_access);
2581 break;
2582 case NFS4ATTR_SETIT:
2583 /*
2584 * read-only attr
2585 */
2586 error = EINVAL;
2587 break;
2588 case NFS4ATTR_VERIT:
2589 ASSERT(sarg->vap->va_mask & AT_ATIME);
2590 error = nfs4_time_ntov(&na->time_access, &atime);
2591 if (error)
2592 break;
2593 if (bcmp(&atime, &sarg->vap->va_atime, sizeof (atime)))
2594 error = -1; /* no match */
2595 break;
2596 case NFS4ATTR_FREEIT:
2597 break;
2598 }
2599 return (error);
2600 }
2601
2602 /*
2603 * XXX - need to support the setting of access time
2604 */
2605 /* ARGSUSED */
2606 static int
rfs4_fattr4_time_access_set(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2607 rfs4_fattr4_time_access_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2608 union nfs4_attr_u *na)
2609 {
2610 int error = 0;
2611 settime4 *ta;
2612
2613 if (RFS4_MANDATTR_ONLY)
2614 return (ENOTSUP);
2615
2616 switch (cmd) {
2617 case NFS4ATTR_SUPPORTED:
2618 if ((sarg->op == NFS4ATTR_GETIT) ||
2619 (sarg->op == NFS4ATTR_VERIT))
2620 error = EINVAL;
2621 break; /* this attr is supported */
2622 case NFS4ATTR_GETIT:
2623 case NFS4ATTR_VERIT:
2624 /*
2625 * write only attr
2626 */
2627 error = EINVAL;
2628 break;
2629 case NFS4ATTR_SETIT:
2630 ASSERT(sarg->vap->va_mask & AT_ATIME);
2631 /*
2632 * Set access time (by server or by client)
2633 */
2634 ta = &na->time_access_set;
2635 if (ta->set_it == SET_TO_CLIENT_TIME4) {
2636 error = nfs4_time_ntov(&ta->time, &sarg->vap->va_atime);
2637 } else if (ta->set_it == SET_TO_SERVER_TIME4) {
2638 gethrestime(&sarg->vap->va_atime);
2639 } else {
2640 error = EINVAL;
2641 }
2642 break;
2643 case NFS4ATTR_FREEIT:
2644 break;
2645 }
2646 return (error);
2647 }
2648
2649 /* ARGSUSED */
2650 static int
rfs4_fattr4_time_backup(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2651 rfs4_fattr4_time_backup(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2652 union nfs4_attr_u *na)
2653 {
2654 return (ENOTSUP);
2655 }
2656
2657 /* ARGSUSED */
2658 static int
rfs4_fattr4_time_create(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2659 rfs4_fattr4_time_create(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2660 union nfs4_attr_u *na)
2661 {
2662 return (ENOTSUP);
2663 }
2664
2665 /* ARGSUSED */
2666 static int
rfs4_fattr4_time_delta(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2667 rfs4_fattr4_time_delta(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2668 union nfs4_attr_u *na)
2669 {
2670 int error = 0;
2671
2672 if (RFS4_MANDATTR_ONLY)
2673 return (ENOTSUP);
2674
2675 switch (cmd) {
2676 case NFS4ATTR_SUPPORTED:
2677 if (sarg->op == NFS4ATTR_SETIT)
2678 error = EINVAL;
2679 break; /* this attr is supported */
2680 case NFS4ATTR_GETIT:
2681 na->time_delta.seconds = 0;
2682 na->time_delta.nseconds = 1000;
2683 break;
2684 case NFS4ATTR_SETIT:
2685 /*
2686 * write only attr
2687 */
2688 error = EINVAL;
2689 break;
2690 case NFS4ATTR_VERIT:
2691 if ((na->time_delta.seconds != 0) ||
2692 (na->time_delta.nseconds != 1000))
2693 error = -1; /* no match */
2694 break;
2695 case NFS4ATTR_FREEIT:
2696 break;
2697 }
2698 return (error);
2699 }
2700
2701 /* ARGSUSED */
2702 static int
rfs4_fattr4_time_metadata(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2703 rfs4_fattr4_time_metadata(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2704 union nfs4_attr_u *na)
2705 {
2706 int error = 0;
2707 timestruc_t ctime;
2708
2709 if (RFS4_MANDATTR_ONLY)
2710 return (ENOTSUP);
2711
2712 switch (cmd) {
2713 case NFS4ATTR_SUPPORTED:
2714 if (sarg->op == NFS4ATTR_SETIT)
2715 error = EINVAL;
2716 break; /* this attr is supported */
2717 case NFS4ATTR_GETIT:
2718 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_CTIME)) {
2719 error = -1; /* may be okay if rdattr_error */
2720 break;
2721 }
2722 ASSERT(sarg->vap->va_mask & AT_CTIME);
2723 error = nfs4_time_vton(&sarg->vap->va_ctime,
2724 &na->time_metadata);
2725 break;
2726 case NFS4ATTR_SETIT:
2727 /*
2728 * read-only attr
2729 */
2730 error = EINVAL;
2731 break;
2732 case NFS4ATTR_VERIT:
2733 ASSERT(sarg->vap->va_mask & AT_CTIME);
2734 error = nfs4_time_ntov(&na->time_metadata, &ctime);
2735 if (error)
2736 break;
2737 if (bcmp(&ctime, &sarg->vap->va_ctime, sizeof (ctime)))
2738 error = -1; /* no match */
2739 break;
2740 case NFS4ATTR_FREEIT:
2741 break;
2742 }
2743 return (error);
2744 }
2745
2746 /* ARGSUSED */
2747 static int
rfs4_fattr4_time_modify(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2748 rfs4_fattr4_time_modify(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2749 union nfs4_attr_u *na)
2750 {
2751 int error = 0;
2752 timestruc_t mtime;
2753
2754 if (RFS4_MANDATTR_ONLY)
2755 return (ENOTSUP);
2756
2757 switch (cmd) {
2758 case NFS4ATTR_SUPPORTED:
2759 if (sarg->op == NFS4ATTR_SETIT)
2760 error = EINVAL;
2761 break; /* this attr is supported */
2762 case NFS4ATTR_GETIT:
2763 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_MTIME)) {
2764 error = -1; /* may be okay if rdattr_error */
2765 break;
2766 }
2767 ASSERT(sarg->vap->va_mask & AT_MTIME);
2768 error = nfs4_time_vton(&sarg->vap->va_mtime, &na->time_modify);
2769 break;
2770 case NFS4ATTR_SETIT:
2771 /*
2772 * read-only attr
2773 */
2774 error = EINVAL;
2775 break;
2776 case NFS4ATTR_VERIT:
2777 ASSERT(sarg->vap->va_mask & AT_MTIME);
2778 error = nfs4_time_ntov(&na->time_modify, &mtime);
2779 if (error)
2780 break;
2781 if (bcmp(&mtime, &sarg->vap->va_mtime, sizeof (mtime)))
2782 error = -1; /* no match */
2783 break;
2784 case NFS4ATTR_FREEIT:
2785 break;
2786 }
2787 return (error);
2788 }
2789
2790 /*
2791 * XXX - need to add support for setting modify time
2792 */
2793 /* ARGSUSED */
2794 static int
rfs4_fattr4_time_modify_set(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2795 rfs4_fattr4_time_modify_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2796 union nfs4_attr_u *na)
2797 {
2798 int error = 0;
2799 settime4 *tm;
2800
2801 if (RFS4_MANDATTR_ONLY)
2802 return (ENOTSUP);
2803
2804 switch (cmd) {
2805 case NFS4ATTR_SUPPORTED:
2806 if ((sarg->op == NFS4ATTR_GETIT) ||
2807 (sarg->op == NFS4ATTR_VERIT))
2808 error = EINVAL;
2809 break; /* this attr is supported */
2810 case NFS4ATTR_GETIT:
2811 case NFS4ATTR_VERIT:
2812 /*
2813 * write only attr
2814 */
2815 error = EINVAL;
2816 break;
2817 case NFS4ATTR_SETIT:
2818 ASSERT(sarg->vap->va_mask & AT_MTIME);
2819 /*
2820 * Set modify time (by server or by client)
2821 */
2822 tm = &na->time_modify_set;
2823 if (tm->set_it == SET_TO_CLIENT_TIME4) {
2824 error = nfs4_time_ntov(&tm->time, &sarg->vap->va_mtime);
2825 sarg->flag = ATTR_UTIME;
2826 } else if (tm->set_it == SET_TO_SERVER_TIME4) {
2827 gethrestime(&sarg->vap->va_mtime);
2828 } else {
2829 error = EINVAL;
2830 }
2831 break;
2832 case NFS4ATTR_FREEIT:
2833 break;
2834 }
2835 return (error);
2836 }
2837
2838 /* ARGSUSED */
2839 static int
rfs4_fattr4_suppattr_exclcreat(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2840 rfs4_fattr4_suppattr_exclcreat(nfs4_attr_cmd_t cmd,
2841 struct nfs4_svgetit_arg *sarg, union nfs4_attr_u *na)
2842 {
2843 int error = 0;
2844
2845 /* Not supported for nfs4.0 */
2846 if (sarg->cs->minorversion == 0)
2847 return (ENOTSUP);
2848
2849 switch (cmd) {
2850 case NFS4ATTR_SUPPORTED:
2851 if (sarg->op == NFS4ATTR_SETIT)
2852 error = EINVAL;
2853 break; /* this attr is supported */
2854 case NFS4ATTR_GETIT:
2855 na->supp_exclcreat = RFS4_SUPPATTR_EXCLCREAT;
2856 break;
2857 case NFS4ATTR_SETIT:
2858 /*
2859 * read-only attr
2860 */
2861 error = EINVAL;
2862 break;
2863 case NFS4ATTR_VERIT:
2864 if (na->supp_exclcreat != RFS4_SUPPATTR_EXCLCREAT)
2865 error = -1; /* no match */
2866 break;
2867 case NFS4ATTR_FREEIT:
2868 break;
2869 }
2870 return (error);
2871 }
2872
2873 static void
rfs4_ntov_init(void)2874 rfs4_ntov_init(void)
2875 {
2876 /* index must be same as corresponding FATTR4_* define */
2877 nfs4_ntov_map[0].sv_getit = rfs4_fattr4_supported_attrs;
2878 nfs4_ntov_map[1].sv_getit = rfs4_fattr4_type;
2879 nfs4_ntov_map[2].sv_getit = rfs4_fattr4_fh_expire_type;
2880 nfs4_ntov_map[3].sv_getit = rfs4_fattr4_change;
2881 nfs4_ntov_map[4].sv_getit = rfs4_fattr4_size;
2882 nfs4_ntov_map[5].sv_getit = rfs4_fattr4_link_support;
2883 nfs4_ntov_map[6].sv_getit = rfs4_fattr4_symlink_support;
2884 nfs4_ntov_map[7].sv_getit = rfs4_fattr4_named_attr;
2885 nfs4_ntov_map[8].sv_getit = rfs4_fattr4_fsid;
2886 nfs4_ntov_map[9].sv_getit = rfs4_fattr4_unique_handles;
2887 nfs4_ntov_map[10].sv_getit = rfs4_fattr4_lease_time;
2888 nfs4_ntov_map[11].sv_getit = rfs4_fattr4_rdattr_error;
2889 nfs4_ntov_map[12].sv_getit = rfs4_fattr4_acl;
2890 nfs4_ntov_map[13].sv_getit = rfs4_fattr4_aclsupport;
2891 nfs4_ntov_map[14].sv_getit = rfs4_fattr4_archive;
2892 nfs4_ntov_map[15].sv_getit = rfs4_fattr4_cansettime;
2893 nfs4_ntov_map[16].sv_getit = rfs4_fattr4_case_insensitive;
2894 nfs4_ntov_map[17].sv_getit = rfs4_fattr4_case_preserving;
2895 nfs4_ntov_map[18].sv_getit = rfs4_fattr4_chown_restricted;
2896 nfs4_ntov_map[19].sv_getit = rfs4_fattr4_filehandle;
2897 nfs4_ntov_map[20].sv_getit = rfs4_fattr4_fileid;
2898 nfs4_ntov_map[21].sv_getit = rfs4_fattr4_files_avail;
2899 nfs4_ntov_map[22].sv_getit = rfs4_fattr4_files_free;
2900 nfs4_ntov_map[23].sv_getit = rfs4_fattr4_files_total;
2901 nfs4_ntov_map[24].sv_getit = rfs4_fattr4_fs_locations;
2902 nfs4_ntov_map[25].sv_getit = rfs4_fattr4_hidden;
2903 nfs4_ntov_map[26].sv_getit = rfs4_fattr4_homogeneous;
2904 nfs4_ntov_map[27].sv_getit = rfs4_fattr4_maxfilesize;
2905 nfs4_ntov_map[28].sv_getit = rfs4_fattr4_maxlink;
2906 nfs4_ntov_map[29].sv_getit = rfs4_fattr4_maxname;
2907 nfs4_ntov_map[30].sv_getit = rfs4_fattr4_maxread;
2908 nfs4_ntov_map[31].sv_getit = rfs4_fattr4_maxwrite;
2909 nfs4_ntov_map[32].sv_getit = rfs4_fattr4_mimetype;
2910 nfs4_ntov_map[33].sv_getit = rfs4_fattr4_mode;
2911 nfs4_ntov_map[34].sv_getit = rfs4_fattr4_no_trunc;
2912 nfs4_ntov_map[35].sv_getit = rfs4_fattr4_numlinks;
2913 nfs4_ntov_map[36].sv_getit = rfs4_fattr4_owner;
2914 nfs4_ntov_map[37].sv_getit = rfs4_fattr4_owner_group;
2915 nfs4_ntov_map[38].sv_getit = rfs4_fattr4_quota_avail_hard;
2916 nfs4_ntov_map[39].sv_getit = rfs4_fattr4_quota_avail_soft;
2917 nfs4_ntov_map[40].sv_getit = rfs4_fattr4_quota_used;
2918 nfs4_ntov_map[41].sv_getit = rfs4_fattr4_rawdev;
2919 nfs4_ntov_map[42].sv_getit = rfs4_fattr4_space_avail;
2920 nfs4_ntov_map[43].sv_getit = rfs4_fattr4_space_free;
2921 nfs4_ntov_map[44].sv_getit = rfs4_fattr4_space_total;
2922 nfs4_ntov_map[45].sv_getit = rfs4_fattr4_space_used;
2923 nfs4_ntov_map[46].sv_getit = rfs4_fattr4_system;
2924 nfs4_ntov_map[47].sv_getit = rfs4_fattr4_time_access;
2925 nfs4_ntov_map[48].sv_getit = rfs4_fattr4_time_access_set;
2926 nfs4_ntov_map[49].sv_getit = rfs4_fattr4_time_backup;
2927 nfs4_ntov_map[50].sv_getit = rfs4_fattr4_time_create;
2928 nfs4_ntov_map[51].sv_getit = rfs4_fattr4_time_delta;
2929 nfs4_ntov_map[52].sv_getit = rfs4_fattr4_time_metadata;
2930 nfs4_ntov_map[53].sv_getit = rfs4_fattr4_time_modify;
2931 nfs4_ntov_map[54].sv_getit = rfs4_fattr4_time_modify_set;
2932 nfs4_ntov_map[55].sv_getit = rfs4_fattr4_mounted_on_fileid;
2933 nfs4_ntov_map[56].sv_getit = rfs4_fattr4_suppattr_exclcreat;
2934 }
2935