2 * Copyright (c) 2006-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * miscellaneous support functions for NFSv4
32 #include <sys/param.h>
34 #include <sys/kauth.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/mount_internal.h>
38 #include <sys/vnode_internal.h>
39 #include <sys/kpi_mbuf.h>
40 #include <sys/socket.h>
42 #include <sys/malloc.h>
43 #include <sys/syscall.h>
44 #include <sys/ubc_internal.h>
45 #include <sys/fcntl.h>
46 #include <sys/quota.h>
47 #include <sys/uio_internal.h>
48 #include <sys/domain.h>
49 #include <libkern/OSAtomic.h>
50 #include <kern/thread_call.h>
53 #include <sys/vmparam.h>
56 #include <kern/clock.h>
58 #include <nfs/rpcv2.h>
59 #include <nfs/nfsproto.h>
61 #include <nfs/nfsnode.h>
62 #include <nfs/xdr_subs.h>
63 #include <nfs/nfsm_subs.h>
64 #include <nfs/nfs_gss.h>
65 #include <nfs/nfsmount.h>
66 #include <nfs/nfs_lock.h>
68 #include <miscfs/specfs/specdev.h>
70 #include <netinet/in.h>
71 #include <net/kpi_interface.h>
78 nfs4_setclientid(struct nfsmount
*nmp
)
80 struct sockaddr
*saddr
;
83 int idlen
, len
, error
= 0, status
, numops
;
88 struct nfsm_chain nmreq
, nmrep
;
90 static uint8_t en0addr
[6];
91 static uint8_t en0addr_set
= 0;
93 lck_mtx_lock(nfs_request_mutex
);
95 ifnet_t interface
= NULL
;
96 error
= ifnet_find_by_name("en0", &interface
);
98 error
= ifnet_lladdr_copy_bytes(interface
, en0addr
, sizeof(en0addr
));
100 printf("nfs4_setclientid: error getting en0 address, %d\n", error
);
105 ifnet_release(interface
);
107 lck_mtx_unlock(nfs_request_mutex
);
109 ctx
= vfs_context_kernel(); /* XXX */
110 thd
= vfs_context_thread(ctx
);
111 cred
= vfs_context_ucred(ctx
);
113 nfsm_chain_null(&nmreq
);
114 nfsm_chain_null(&nmrep
);
116 /* ID: en0_address + server_address */
117 idlen
= len
= sizeof(en0addr
);
118 bcopy(en0addr
, &id
[0], len
);
119 saddr
= mbuf_data(nmp
->nm_nam
);
120 len
= min(saddr
->sa_len
, sizeof(id
)-idlen
);
121 bcopy(saddr
, &id
[idlen
], len
);
126 nfsm_chain_build_alloc_init(error
, &nmreq
, 14 * NFSX_UNSIGNED
+ idlen
);
127 nfsm_chain_add_compound_header(error
, &nmreq
, "setclientid", numops
);
129 nfsm_chain_add_32(error
, &nmreq
, NFS_OP_SETCLIENTID
);
130 /* nfs_client_id4 client; */
131 nfsm_chain_add_64(error
, &nmreq
, nmp
->nm_mounttime
);
132 nfsm_chain_add_32(error
, &nmreq
, idlen
);
133 nfsm_chain_add_opaque(error
, &nmreq
, id
, idlen
);
134 /* cb_client4 callback; */
135 /* We don't provide callback info yet */
136 nfsm_chain_add_32(error
, &nmreq
, 0); /* callback program */
137 nfsm_chain_add_string(error
, &nmreq
, "", 0); /* callback r_netid */
138 nfsm_chain_add_string(error
, &nmreq
, "", 0); /* callback r_addr */
139 nfsm_chain_add_32(error
, &nmreq
, 0); /* callback_ident */
140 nfsm_chain_build_done(error
, &nmreq
);
141 nfsm_assert(error
, (numops
== 0), EPROTO
);
143 error
= nfs_request2(NULL
, nmp
->nm_mountp
, &nmreq
, NFSPROC4_COMPOUND
, thd
, cred
, R_SETUP
, &nmrep
, &xid
, &status
);
144 nfsm_chain_skip_tag(error
, &nmrep
);
145 nfsm_chain_get_32(error
, &nmrep
, numops
);
146 nfsm_chain_op_check(error
, &nmrep
, NFS_OP_SETCLIENTID
);
147 if (error
== NFSERR_CLID_INUSE
)
148 printf("nfs4_setclientid: client ID in use?\n");
150 nfsm_chain_get_64(error
, &nmrep
, nmp
->nm_clientid
);
151 nfsm_chain_get_64(error
, &nmrep
, verifier
);
152 nfsm_chain_cleanup(&nmreq
);
153 nfsm_chain_cleanup(&nmrep
);
155 // SETCLIENTID_CONFIRM
157 nfsm_chain_build_alloc_init(error
, &nmreq
, 13 * NFSX_UNSIGNED
);
158 nfsm_chain_add_compound_header(error
, &nmreq
, "setclientid_confirm", numops
);
160 nfsm_chain_add_32(error
, &nmreq
, NFS_OP_SETCLIENTID_CONFIRM
);
161 nfsm_chain_add_64(error
, &nmreq
, nmp
->nm_clientid
);
162 nfsm_chain_add_64(error
, &nmreq
, verifier
);
163 nfsm_chain_build_done(error
, &nmreq
);
164 nfsm_assert(error
, (numops
== 0), EPROTO
);
166 error
= nfs_request2(NULL
, nmp
->nm_mountp
, &nmreq
, NFSPROC4_COMPOUND
, thd
, cred
, R_SETUP
, &nmrep
, &xid
, &status
);
167 nfsm_chain_skip_tag(error
, &nmrep
);
168 nfsm_chain_get_32(error
, &nmrep
, numops
);
169 nfsm_chain_op_check(error
, &nmrep
, NFS_OP_SETCLIENTID_CONFIRM
);
171 printf("nfs4_setclientid: confirm error %d\n", error
);
173 nfsm_chain_cleanup(&nmreq
);
174 nfsm_chain_cleanup(&nmrep
);
176 printf("nfs4_setclientid failed, %d\n", error
);
181 * periodic timer to renew lease state on server
184 nfs4_renew_timer(void *param0
, __unused
void *param1
)
186 struct nfsmount
*nmp
= param0
;
187 int error
= 0, status
, numops
, interval
;
190 struct nfsm_chain nmreq
, nmrep
;
192 ctx
= vfs_context_kernel(); /* XXX */
194 nfsm_chain_null(&nmreq
);
195 nfsm_chain_null(&nmrep
);
199 nfsm_chain_build_alloc_init(error
, &nmreq
, 8 * NFSX_UNSIGNED
);
200 nfsm_chain_add_compound_header(error
, &nmreq
, "renew", numops
);
202 nfsm_chain_add_32(error
, &nmreq
, NFS_OP_RENEW
);
203 nfsm_chain_add_64(error
, &nmreq
, nmp
->nm_clientid
);
204 nfsm_chain_build_done(error
, &nmreq
);
205 nfsm_assert(error
, (numops
== 0), EPROTO
);
207 error
= nfs_request(NULL
, nmp
->nm_mountp
, &nmreq
, NFSPROC4_COMPOUND
, ctx
, &nmrep
, &xid
, &status
);
208 nfsm_chain_skip_tag(error
, &nmrep
);
209 nfsm_chain_get_32(error
, &nmrep
, numops
);
210 nfsm_chain_op_check(error
, &nmrep
, NFS_OP_RENEW
);
213 printf("nfs4_renew_timer: error %d\n", error
);
214 nfsm_chain_cleanup(&nmreq
);
215 nfsm_chain_cleanup(&nmrep
);
217 interval
= nmp
->nm_fsattr
.nfsa_lease
/ (error
? 4 : 2);
220 nfs_interval_timer_start(nmp
->nm_renew_timer
, interval
* 1000);
224 * Set a vnode attr's supported bits according to the given bitmap
227 nfs_vattr_set_supported(uint32_t *bitmap
, struct vnode_attr
*vap
)
229 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TYPE
))
230 VATTR_SET_SUPPORTED(vap
, va_type
);
231 // if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CHANGE))
232 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_SIZE
))
233 VATTR_SET_SUPPORTED(vap
, va_data_size
);
234 // if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_NAMED_ATTR))
235 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_FSID
))
236 VATTR_SET_SUPPORTED(vap
, va_fsid
);
237 // if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ACL))
238 // VATTR_SET_SUPPORTED(vap, va_acl);
239 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_ARCHIVE
))
240 VATTR_SET_SUPPORTED(vap
, va_flags
);
241 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_FILEID
))
242 VATTR_SET_SUPPORTED(vap
, va_fileid
);
243 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_HIDDEN
))
244 VATTR_SET_SUPPORTED(vap
, va_flags
);
245 // if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MIMETYPE))
246 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_MODE
))
247 VATTR_SET_SUPPORTED(vap
, va_mode
);
248 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_NUMLINKS
))
249 VATTR_SET_SUPPORTED(vap
, va_nlink
);
250 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_OWNER
))
251 VATTR_SET_SUPPORTED(vap
, va_uid
);
252 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_OWNER_GROUP
))
253 VATTR_SET_SUPPORTED(vap
, va_gid
);
254 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_RAWDEV
))
255 VATTR_SET_SUPPORTED(vap
, va_rdev
);
256 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_SPACE_USED
))
257 VATTR_SET_SUPPORTED(vap
, va_total_alloc
);
258 // if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SYSTEM))
259 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_ACCESS
))
260 VATTR_SET_SUPPORTED(vap
, va_access_time
);
261 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_BACKUP
))
262 VATTR_SET_SUPPORTED(vap
, va_backup_time
);
263 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_CREATE
))
264 VATTR_SET_SUPPORTED(vap
, va_create_time
);
265 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_METADATA
))
266 VATTR_SET_SUPPORTED(vap
, va_change_time
);
267 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_MODIFY
))
268 VATTR_SET_SUPPORTED(vap
, va_modify_time
);
272 * Parse the attributes that are in the mbuf list and store them in
273 * the given structures.
277 struct nfsm_chain
*nmc
,
278 struct nfs_fsattr
*nfsap
,
279 struct nfs_vattr
*nvap
,
283 int error
= 0, attrbytes
;
284 uint32_t val
, val2
, val3
, i
, j
;
285 uint32_t bitmap
[NFS_ATTR_BITMAP_LEN
], len
;
287 struct nfs_fsattr nfsa_dummy
;
288 struct nfs_vattr nva_dummy
;
289 struct dqblk dqb_dummy
;
291 /* if not interested in some values... throw 'em into a local dummy variable */
299 attrbytes
= val
= val2
= val3
= 0;
301 len
= NFS_ATTR_BITMAP_LEN
;
302 nfsm_chain_get_bitmap(error
, nmc
, bitmap
, len
);
303 /* add bits to object/fs attr bitmaps */
304 for (i
=0; i
< NFS_ATTR_BITMAP_LEN
; i
++) {
305 nvap
->nva_bitmap
[i
] |= bitmap
[i
] & nfs_object_attr_bitmap
[i
];
306 nfsap
->nfsa_bitmap
[i
] |= bitmap
[i
] & nfs_fs_attr_bitmap
[i
];
309 nfsm_chain_get_32(error
, nmc
, attrbytes
);
312 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_SUPPORTED_ATTRS
)) {
313 len
= NFS_ATTR_BITMAP_LEN
;
314 nfsm_chain_get_bitmap(error
, nmc
, nfsap
->nfsa_supp_attr
, len
);
315 attrbytes
-= (len
+ 1) * NFSX_UNSIGNED
;
317 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TYPE
)) {
318 nfsm_chain_get_32(error
, nmc
, val
);
319 nvap
->nva_type
= nfstov_type(val
, NFS_VER4
);
320 attrbytes
-= NFSX_UNSIGNED
;
322 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_FH_EXPIRE_TYPE
)) {
323 nfsm_chain_get_32(error
, nmc
, val
);
325 if (val
!= NFS_FH_PERSISTENT
)
326 printf("nfs: warning: non-persistent file handles!\n");
328 printf("nfs: warning unknown fh type: 0x%x\n", val
);
329 nfsap
->nfsa_flags
&= ~NFS_FSFLAG_FHTYPE_MASK
;
330 nfsap
->nfsa_flags
|= val
<< 24;
331 attrbytes
-= NFSX_UNSIGNED
;
333 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_CHANGE
)) {
334 nfsm_chain_get_64(error
, nmc
, nvap
->nva_change
);
335 attrbytes
-= 2 * NFSX_UNSIGNED
;
337 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_SIZE
)) {
338 nfsm_chain_get_64(error
, nmc
, nvap
->nva_size
);
339 attrbytes
-= 2 * NFSX_UNSIGNED
;
341 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_LINK_SUPPORT
)) {
342 nfsm_chain_get_32(error
, nmc
, val
);
344 nfsap
->nfsa_flags
|= NFS_FSFLAG_LINK
;
346 nfsap
->nfsa_flags
&= ~NFS_FSFLAG_LINK
;
347 attrbytes
-= NFSX_UNSIGNED
;
349 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_SYMLINK_SUPPORT
)) {
350 nfsm_chain_get_32(error
, nmc
, val
);
352 nfsap
->nfsa_flags
|= NFS_FSFLAG_SYMLINK
;
354 nfsap
->nfsa_flags
&= ~NFS_FSFLAG_SYMLINK
;
355 attrbytes
-= NFSX_UNSIGNED
;
357 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_NAMED_ATTR
)) {
358 nfsm_chain_get_32(error
, nmc
, val
);
360 nvap
->nva_flags
|= NFS_FFLAG_NAMED_ATTR
;
362 nvap
->nva_flags
&= ~NFS_FFLAG_NAMED_ATTR
;
363 attrbytes
-= NFSX_UNSIGNED
;
365 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_FSID
)) {
366 nfsm_chain_get_64(error
, nmc
, nvap
->nva_fsid
.major
);
367 nfsm_chain_get_64(error
, nmc
, nvap
->nva_fsid
.minor
);
368 attrbytes
-= 4 * NFSX_UNSIGNED
;
370 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_UNIQUE_HANDLES
)) {
371 nfsm_chain_get_32(error
, nmc
, val
);
373 nfsap
->nfsa_flags
|= NFS_FSFLAG_UNIQUE_FH
;
375 nfsap
->nfsa_flags
&= ~NFS_FSFLAG_UNIQUE_FH
;
376 attrbytes
-= NFSX_UNSIGNED
;
378 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_LEASE_TIME
)) {
379 nfsm_chain_get_32(error
, nmc
, nfsap
->nfsa_lease
);
380 attrbytes
-= NFSX_UNSIGNED
;
382 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_RDATTR_ERROR
)) {
383 nfsm_chain_get_32(error
, nmc
, error
);
384 attrbytes
-= NFSX_UNSIGNED
;
387 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_ACL
)) { /* skip for now */
388 nfsm_chain_get_32(error
, nmc
, val
); /* ACE count */
389 for (i
=0; !error
&& (i
< val
); i
++) {
390 nfsm_chain_adv(error
, nmc
, 3 * NFSX_UNSIGNED
);
391 nfsm_chain_get_32(error
, nmc
, val2
); /* string length */
392 nfsm_chain_adv(error
, nmc
, nfsm_rndup(val2
));
393 attrbytes
-= 4*NFSX_UNSIGNED
+ nfsm_rndup(val2
);
394 nfsm_assert(error
, (attrbytes
>= 0), EBADRPC
);
397 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_ACLSUPPORT
)) {
398 nfsm_chain_get_32(error
, nmc
, val
);
400 nfsap
->nfsa_flags
|= NFS_FSFLAG_ACL
;
402 nfsap
->nfsa_flags
&= ~NFS_FSFLAG_ACL
;
403 attrbytes
-= NFSX_UNSIGNED
;
405 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_ARCHIVE
)) { /* SF_ARCHIVED */
406 nfsm_chain_get_32(error
, nmc
, val
);
408 nvap
->nva_flags
|= NFS_FFLAG_ARCHIVED
;
410 nvap
->nva_flags
&= ~NFS_FFLAG_ARCHIVED
;
411 attrbytes
-= NFSX_UNSIGNED
;
413 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_CANSETTIME
)) {
414 nfsm_chain_get_32(error
, nmc
, val
);
416 nfsap
->nfsa_flags
|= NFS_FSFLAG_SET_TIME
;
418 nfsap
->nfsa_flags
&= ~NFS_FSFLAG_SET_TIME
;
419 attrbytes
-= NFSX_UNSIGNED
;
421 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_CASE_INSENSITIVE
)) {
422 nfsm_chain_get_32(error
, nmc
, val
);
424 nfsap
->nfsa_flags
|= NFS_FSFLAG_CASE_INSENSITIVE
;
426 nfsap
->nfsa_flags
&= ~NFS_FSFLAG_CASE_INSENSITIVE
;
427 attrbytes
-= NFSX_UNSIGNED
;
429 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_CASE_PRESERVING
)) {
430 nfsm_chain_get_32(error
, nmc
, val
);
432 nfsap
->nfsa_flags
|= NFS_FSFLAG_CASE_PRESERVING
;
434 nfsap
->nfsa_flags
&= ~NFS_FSFLAG_CASE_PRESERVING
;
435 attrbytes
-= NFSX_UNSIGNED
;
437 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_CHOWN_RESTRICTED
)) {
438 nfsm_chain_get_32(error
, nmc
, val
);
440 nfsap
->nfsa_flags
|= NFS_FSFLAG_CHOWN_RESTRICTED
;
442 nfsap
->nfsa_flags
&= ~NFS_FSFLAG_CHOWN_RESTRICTED
;
443 attrbytes
-= NFSX_UNSIGNED
;
445 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_FILEHANDLE
)) {
446 nfsm_chain_get_32(error
, nmc
, val
);
449 nfsm_chain_get_opaque(error
, nmc
, nfsm_rndup(val
), fhp
->fh_data
);
451 nfsm_chain_adv(error
, nmc
, nfsm_rndup(val
));
453 attrbytes
-= NFSX_UNSIGNED
+ nfsm_rndup(val
);
455 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_FILEID
)) {
456 nfsm_chain_get_64(error
, nmc
, nvap
->nva_fileid
);
457 attrbytes
-= 2 * NFSX_UNSIGNED
;
459 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_FILES_AVAIL
)) {
460 nfsm_chain_get_64(error
, nmc
, nfsap
->nfsa_files_avail
);
461 attrbytes
-= 2 * NFSX_UNSIGNED
;
463 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_FILES_FREE
)) {
464 nfsm_chain_get_64(error
, nmc
, nfsap
->nfsa_files_free
);
465 attrbytes
-= 2 * NFSX_UNSIGNED
;
467 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_FILES_TOTAL
)) {
468 nfsm_chain_get_64(error
, nmc
, nfsap
->nfsa_files_total
);
469 attrbytes
-= 2 * NFSX_UNSIGNED
;
471 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_FS_LOCATIONS
)) { /* skip for now */
472 nfsm_chain_get_32(error
, nmc
, val
); /* root path length */
473 nfsm_chain_adv(error
, nmc
, nfsm_rndup(val
)); /* root path */
474 attrbytes
-= (2 * NFSX_UNSIGNED
) + nfsm_rndup(val
);
475 nfsm_chain_get_32(error
, nmc
, val
); /* location count */
476 for (i
=0; !error
&& (i
< val
); i
++) {
477 nfsm_chain_get_32(error
, nmc
, val2
); /* server string length */
478 nfsm_chain_adv(error
, nmc
, nfsm_rndup(val2
)); /* server string */
479 attrbytes
-= (2 * NFSX_UNSIGNED
) + nfsm_rndup(val2
);
480 nfsm_chain_get_32(error
, nmc
, val2
); /* pathname component count */
481 for (j
=0; !error
&& (j
< val2
); j
++) {
482 nfsm_chain_get_32(error
, nmc
, val3
); /* component length */
483 nfsm_chain_adv(error
, nmc
, nfsm_rndup(val3
)); /* component */
484 attrbytes
-= NFSX_UNSIGNED
+ nfsm_rndup(val3
);
485 nfsm_assert(error
, (attrbytes
>= 0), EBADRPC
);
487 nfsm_assert(error
, (attrbytes
>= 0), EBADRPC
);
489 nfsm_assert(error
, (attrbytes
>= 0), EBADRPC
);
491 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_HIDDEN
)) { /* UF_HIDDEN */
492 nfsm_chain_get_32(error
, nmc
, val
);
494 nvap
->nva_flags
|= NFS_FFLAG_HIDDEN
;
496 nvap
->nva_flags
&= ~NFS_FFLAG_HIDDEN
;
497 attrbytes
-= NFSX_UNSIGNED
;
499 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_HOMOGENEOUS
)) {
500 /* XXX If NOT homogeneous, we may need to clear flags on the mount */
501 nfsm_chain_get_32(error
, nmc
, val
);
503 nfsap
->nfsa_flags
|= NFS_FSFLAG_HOMOGENEOUS
;
505 nfsap
->nfsa_flags
&= ~NFS_FSFLAG_HOMOGENEOUS
;
506 attrbytes
-= NFSX_UNSIGNED
;
508 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_MAXFILESIZE
)) {
509 nfsm_chain_get_64(error
, nmc
, nfsap
->nfsa_maxfilesize
);
510 attrbytes
-= 2 * NFSX_UNSIGNED
;
512 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_MAXLINK
)) {
513 nfsm_chain_get_32(error
, nmc
, nvap
->nva_maxlink
);
514 if (!error
&& (nfsap
->nfsa_maxlink
> INT32_MAX
))
515 nfsap
->nfsa_maxlink
= INT32_MAX
;
516 attrbytes
-= NFSX_UNSIGNED
;
518 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_MAXNAME
)) {
519 nfsm_chain_get_32(error
, nmc
, nfsap
->nfsa_maxname
);
520 if (!error
&& (nfsap
->nfsa_maxname
> INT32_MAX
))
521 nfsap
->nfsa_maxname
= INT32_MAX
;
522 attrbytes
-= NFSX_UNSIGNED
;
524 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_MAXREAD
)) {
525 nfsm_chain_get_64(error
, nmc
, nfsap
->nfsa_maxread
);
526 attrbytes
-= 2 * NFSX_UNSIGNED
;
528 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_MAXWRITE
)) {
529 nfsm_chain_get_64(error
, nmc
, nfsap
->nfsa_maxwrite
);
530 attrbytes
-= 2 * NFSX_UNSIGNED
;
532 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_MIMETYPE
)) {
533 nfsm_chain_get_32(error
, nmc
, val
);
534 nfsm_chain_adv(error
, nmc
, nfsm_rndup(val
));
535 attrbytes
-= NFSX_UNSIGNED
+ nfsm_rndup(val
);
537 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_MODE
)) {
538 nfsm_chain_get_32(error
, nmc
, nvap
->nva_mode
);
539 attrbytes
-= NFSX_UNSIGNED
;
541 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_NO_TRUNC
)) {
542 nfsm_chain_get_32(error
, nmc
, val
);
544 nfsap
->nfsa_flags
|= NFS_FSFLAG_NO_TRUNC
;
546 nfsap
->nfsa_flags
&= ~NFS_FSFLAG_NO_TRUNC
;
547 attrbytes
-= NFSX_UNSIGNED
;
549 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_NUMLINKS
)) {
550 nfsm_chain_get_32(error
, nmc
, val
);
551 nvap
->nva_nlink
= val
;
552 attrbytes
-= NFSX_UNSIGNED
;
554 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_OWNER
)) { /* XXX ugly hack for now */
555 nfsm_chain_get_32(error
, nmc
, len
);
556 nfsm_chain_get_opaque_pointer(error
, nmc
, len
, s
);
557 attrbytes
-= NFSX_UNSIGNED
+ nfsm_rndup(len
);
559 if ((*s
>= '0') && (*s
<= '9'))
560 nvap
->nva_uid
= strtol(s
, NULL
, 10);
561 else if (!strncmp(s
, "nobody@", 7))
563 else if (!strncmp(s
, "root@", 5))
566 nvap
->nva_uid
= 99; /* unknown */
568 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_OWNER_GROUP
)) { /* XXX ugly hack for now */
569 nfsm_chain_get_32(error
, nmc
, len
);
570 nfsm_chain_get_opaque_pointer(error
, nmc
, len
, s
);
571 attrbytes
-= NFSX_UNSIGNED
+ nfsm_rndup(len
);
573 if ((*s
>= '0') && (*s
<= '9'))
574 nvap
->nva_gid
= strtol(s
, NULL
, 10);
575 else if (!strncmp(s
, "nobody@", 7))
577 else if (!strncmp(s
, "root@", 5))
580 nvap
->nva_gid
= 99; /* unknown */
582 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_QUOTA_AVAIL_HARD
)) {
583 nfsm_chain_get_64(error
, nmc
, dqbp
->dqb_bhardlimit
);
584 attrbytes
-= 2 * NFSX_UNSIGNED
;
586 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_QUOTA_AVAIL_SOFT
)) {
587 nfsm_chain_get_64(error
, nmc
, dqbp
->dqb_bsoftlimit
);
588 attrbytes
-= 2 * NFSX_UNSIGNED
;
590 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_QUOTA_USED
)) {
591 nfsm_chain_get_64(error
, nmc
, dqbp
->dqb_curbytes
);
592 attrbytes
-= 2 * NFSX_UNSIGNED
;
594 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_RAWDEV
)) {
595 nfsm_chain_get_32(error
, nmc
, nvap
->nva_rawdev
.specdata1
);
596 nfsm_chain_get_32(error
, nmc
, nvap
->nva_rawdev
.specdata2
);
597 attrbytes
-= 2 * NFSX_UNSIGNED
;
599 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_SPACE_AVAIL
)) {
600 nfsm_chain_get_64(error
, nmc
, nfsap
->nfsa_space_avail
);
601 attrbytes
-= 2 * NFSX_UNSIGNED
;
603 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_SPACE_FREE
)) {
604 nfsm_chain_get_64(error
, nmc
, nfsap
->nfsa_space_free
);
605 attrbytes
-= 2 * NFSX_UNSIGNED
;
607 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_SPACE_TOTAL
)) {
608 nfsm_chain_get_64(error
, nmc
, nfsap
->nfsa_space_total
);
609 attrbytes
-= 2 * NFSX_UNSIGNED
;
611 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_SPACE_USED
)) {
612 nfsm_chain_get_64(error
, nmc
, nvap
->nva_bytes
);
613 attrbytes
-= 2 * NFSX_UNSIGNED
;
615 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_SYSTEM
)) {
616 /* we'd support this if we had a flag to map it to... */
617 nfsm_chain_adv(error
, nmc
, NFSX_UNSIGNED
);
618 attrbytes
-= NFSX_UNSIGNED
;
620 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_ACCESS
)) {
621 nfsm_chain_get_64(error
, nmc
, nvap
->nva_timesec
[NFSTIME_ACCESS
]);
622 nfsm_chain_get_32(error
, nmc
, nvap
->nva_timensec
[NFSTIME_ACCESS
]);
623 attrbytes
-= 3 * NFSX_UNSIGNED
;
625 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_ACCESS_SET
)) {
626 nfsm_chain_adv(error
, nmc
, 4*NFSX_UNSIGNED
); /* just skip it */
627 attrbytes
-= 4 * NFSX_UNSIGNED
;
629 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_BACKUP
)) {
630 nfsm_chain_get_64(error
, nmc
, nvap
->nva_timesec
[NFSTIME_BACKUP
]);
631 nfsm_chain_get_32(error
, nmc
, nvap
->nva_timensec
[NFSTIME_BACKUP
]);
632 attrbytes
-= 3 * NFSX_UNSIGNED
;
634 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_CREATE
)) {
635 nfsm_chain_get_64(error
, nmc
, nvap
->nva_timesec
[NFSTIME_CREATE
]);
636 nfsm_chain_get_32(error
, nmc
, nvap
->nva_timensec
[NFSTIME_CREATE
]);
637 attrbytes
-= 3 * NFSX_UNSIGNED
;
639 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_DELTA
)) { /* skip for now */
640 nfsm_chain_adv(error
, nmc
, 3*NFSX_UNSIGNED
);
641 attrbytes
-= 3 * NFSX_UNSIGNED
;
643 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_METADATA
)) {
644 nfsm_chain_get_64(error
, nmc
, nvap
->nva_timesec
[NFSTIME_CHANGE
]);
645 nfsm_chain_get_32(error
, nmc
, nvap
->nva_timensec
[NFSTIME_CHANGE
]);
646 attrbytes
-= 3 * NFSX_UNSIGNED
;
648 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_MODIFY
)) {
649 nfsm_chain_get_64(error
, nmc
, nvap
->nva_timesec
[NFSTIME_MODIFY
]);
650 nfsm_chain_get_32(error
, nmc
, nvap
->nva_timensec
[NFSTIME_MODIFY
]);
651 attrbytes
-= 3 * NFSX_UNSIGNED
;
653 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_MODIFY_SET
)) {
654 nfsm_chain_adv(error
, nmc
, 4*NFSX_UNSIGNED
); /* just skip it */
655 attrbytes
-= 4 * NFSX_UNSIGNED
;
657 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_MOUNTED_ON_FILEID
)) { /* skip for now */
658 nfsm_chain_adv(error
, nmc
, 2*NFSX_UNSIGNED
);
659 attrbytes
-= 2 * NFSX_UNSIGNED
;
661 /* advance over any leftover attrbytes */
662 nfsm_assert(error
, (attrbytes
>= 0), EBADRPC
);
663 nfsm_chain_adv(error
, nmc
, nfsm_rndup(attrbytes
));
669 * Add an NFSv4 "sattr" structure to an mbuf chain
672 nfsm_chain_add_fattr4_f(struct nfsm_chain
*nmc
, struct vnode_attr
*vap
, struct nfsmount
*nmp
)
674 int error
= 0, attrbytes
, slen
, i
;
675 uint32_t *pattrbytes
;
676 uint32_t bitmap
[NFS_ATTR_BITMAP_LEN
];
680 * Do this in two passes.
681 * First calculate the bitmap, then pack
682 * everything together and set the size.
685 NFS_CLEAR_ATTRIBUTES(bitmap
);
686 if (VATTR_IS_ACTIVE(vap
, va_data_size
))
687 NFS_BITMAP_SET(bitmap
, NFS_FATTR_SIZE
);
688 if (VATTR_IS_ACTIVE(vap
, va_acl
)) {
689 // NFS_BITMAP_SET(bitmap, NFS_FATTR_ACL)
691 if (VATTR_IS_ACTIVE(vap
, va_flags
)) {
692 NFS_BITMAP_SET(bitmap
, NFS_FATTR_ARCHIVE
);
693 NFS_BITMAP_SET(bitmap
, NFS_FATTR_HIDDEN
);
695 // NFS_BITMAP_SET(bitmap, NFS_FATTR_MIMETYPE)
696 if (VATTR_IS_ACTIVE(vap
, va_mode
))
697 NFS_BITMAP_SET(bitmap
, NFS_FATTR_MODE
);
698 if (VATTR_IS_ACTIVE(vap
, va_uid
))
699 NFS_BITMAP_SET(bitmap
, NFS_FATTR_OWNER
);
700 if (VATTR_IS_ACTIVE(vap
, va_gid
))
701 NFS_BITMAP_SET(bitmap
, NFS_FATTR_OWNER_GROUP
);
702 // NFS_BITMAP_SET(bitmap, NFS_FATTR_SYSTEM)
703 if (vap
->va_vaflags
& VA_UTIMES_NULL
) {
704 NFS_BITMAP_SET(bitmap
, NFS_FATTR_TIME_ACCESS_SET
);
705 NFS_BITMAP_SET(bitmap
, NFS_FATTR_TIME_MODIFY_SET
);
707 if (VATTR_IS_ACTIVE(vap
, va_access_time
))
708 NFS_BITMAP_SET(bitmap
, NFS_FATTR_TIME_ACCESS_SET
);
709 if (VATTR_IS_ACTIVE(vap
, va_modify_time
))
710 NFS_BITMAP_SET(bitmap
, NFS_FATTR_TIME_MODIFY_SET
);
712 if (VATTR_IS_ACTIVE(vap
, va_backup_time
))
713 NFS_BITMAP_SET(bitmap
, NFS_FATTR_TIME_BACKUP
);
714 if (VATTR_IS_ACTIVE(vap
, va_create_time
))
715 NFS_BITMAP_SET(bitmap
, NFS_FATTR_TIME_CREATE
);
716 /* and limit to what is supported by server */
717 for (i
=0; i
< NFS_ATTR_BITMAP_LEN
; i
++)
718 bitmap
[i
] &= nmp
->nm_fsattr
.nfsa_supp_attr
[i
];
721 * Now pack it all together:
722 * BITMAP, #BYTES, ATTRS
723 * Keep a pointer to the length so we can set it later.
725 nfsm_chain_add_bitmap(error
, nmc
, bitmap
, NFS_ATTR_BITMAP_LEN
);
727 nfsm_chain_add_32(error
, nmc
, attrbytes
);
728 pattrbytes
= (uint32_t*)(nmc
->nmc_ptr
- NFSX_UNSIGNED
);
730 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_SIZE
)) {
731 nfsm_chain_add_64(error
, nmc
, vap
->va_data_size
);
732 attrbytes
+= 2*NFSX_UNSIGNED
;
734 // NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ACL)
735 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_ARCHIVE
)) {
736 nfsm_chain_add_32(error
, nmc
, (vap
->va_flags
& SF_ARCHIVED
) ? 1 : 0);
737 attrbytes
+= NFSX_UNSIGNED
;
739 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_HIDDEN
)) {
740 nfsm_chain_add_32(error
, nmc
, (vap
->va_flags
& UF_HIDDEN
) ? 1 : 0);
741 attrbytes
+= NFSX_UNSIGNED
;
743 // NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MIMETYPE)
744 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_MODE
)) {
745 nfsm_chain_add_32(error
, nmc
, vap
->va_mode
);
746 attrbytes
+= NFSX_UNSIGNED
;
748 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_OWNER
)) {
749 slen
= snprintf(s
, sizeof(s
), "%d", vap
->va_uid
);
750 nfsm_chain_add_string(error
, nmc
, s
, slen
);
751 attrbytes
+= NFSX_UNSIGNED
+ nfsm_rndup(slen
);
753 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_OWNER_GROUP
)) {
754 slen
= snprintf(s
, sizeof(s
), "%d", vap
->va_gid
);
755 nfsm_chain_add_string(error
, nmc
, s
, slen
);
756 attrbytes
+= NFSX_UNSIGNED
+ nfsm_rndup(slen
);
758 // NFS_BITMAP_SET(bitmap, NFS_FATTR_SYSTEM)
759 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_ACCESS_SET
)) {
760 if (vap
->va_vaflags
& VA_UTIMES_NULL
) {
761 nfsm_chain_add_32(error
, nmc
, NFS_TIME_SET_TO_SERVER
);
762 attrbytes
+= NFSX_UNSIGNED
;
764 nfsm_chain_add_32(error
, nmc
, NFS_TIME_SET_TO_CLIENT
);
765 nfsm_chain_add_64(error
, nmc
, vap
->va_access_time
.tv_sec
);
766 nfsm_chain_add_32(error
, nmc
, vap
->va_access_time
.tv_nsec
);
767 attrbytes
+= 4*NFSX_UNSIGNED
;
770 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_BACKUP
)) {
771 nfsm_chain_add_64(error
, nmc
, vap
->va_backup_time
.tv_sec
);
772 nfsm_chain_add_32(error
, nmc
, vap
->va_backup_time
.tv_nsec
);
773 attrbytes
+= 3*NFSX_UNSIGNED
;
775 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_CREATE
)) {
776 nfsm_chain_add_64(error
, nmc
, vap
->va_create_time
.tv_sec
);
777 nfsm_chain_add_32(error
, nmc
, vap
->va_create_time
.tv_nsec
);
778 attrbytes
+= 3*NFSX_UNSIGNED
;
780 if (NFS_BITMAP_ISSET(bitmap
, NFS_FATTR_TIME_MODIFY_SET
)) {
781 if (vap
->va_vaflags
& VA_UTIMES_NULL
) {
782 nfsm_chain_add_32(error
, nmc
, NFS_TIME_SET_TO_SERVER
);
783 attrbytes
+= NFSX_UNSIGNED
;
785 nfsm_chain_add_32(error
, nmc
, NFS_TIME_SET_TO_CLIENT
);
786 nfsm_chain_add_64(error
, nmc
, vap
->va_modify_time
.tv_sec
);
787 nfsm_chain_add_32(error
, nmc
, vap
->va_modify_time
.tv_nsec
);
788 attrbytes
+= 4*NFSX_UNSIGNED
;
792 /* Now, set the attribute data length */
793 *pattrbytes
= txdr_unsigned(attrbytes
);