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