]> git.saurik.com Git - apple/xnu.git/blob - bsd/nfs/nfs4_subs.c
xnu-1228.15.4.tar.gz
[apple/xnu.git] / bsd / nfs / nfs4_subs.c
1 /*
2 * Copyright (c) 2006-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 /*
30 * miscellaneous support functions for NFSv4
31 */
32 #include <sys/param.h>
33 #include <sys/proc.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>
41 #include <sys/stat.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>
51
52 #include <sys/vm.h>
53 #include <sys/vmparam.h>
54
55 #include <sys/time.h>
56 #include <kern/clock.h>
57
58 #include <nfs/rpcv2.h>
59 #include <nfs/nfsproto.h>
60 #include <nfs/nfs.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>
67
68 #include <miscfs/specfs/specdev.h>
69
70 #include <netinet/in.h>
71 #include <net/kpi_interface.h>
72
73
74 /*
75 * NFSv4 SETCLIENTID
76 */
77 int
78 nfs4_setclientid(struct nfsmount *nmp)
79 {
80 struct sockaddr *saddr;
81 uint64_t verifier;
82 char id[128];
83 int idlen, len, error = 0, status, numops;
84 u_int64_t xid;
85 vfs_context_t ctx;
86 thread_t thd;
87 kauth_cred_t cred;
88 struct nfsm_chain nmreq, nmrep;
89
90 static uint8_t en0addr[6];
91 static uint8_t en0addr_set = 0;
92
93 lck_mtx_lock(nfs_request_mutex);
94 if (!en0addr_set) {
95 ifnet_t interface = NULL;
96 error = ifnet_find_by_name("en0", &interface);
97 if (!error)
98 error = ifnet_lladdr_copy_bytes(interface, en0addr, sizeof(en0addr));
99 if (error)
100 printf("nfs4_setclientid: error getting en0 address, %d\n", error);
101 if (!error)
102 en0addr_set = 1;
103 error = 0;
104 if (interface)
105 ifnet_release(interface);
106 }
107 lck_mtx_unlock(nfs_request_mutex);
108
109 ctx = vfs_context_kernel(); /* XXX */
110 thd = vfs_context_thread(ctx);
111 cred = vfs_context_ucred(ctx);
112
113 nfsm_chain_null(&nmreq);
114 nfsm_chain_null(&nmrep);
115
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);
122 idlen += len;
123
124 // SETCLIENTID
125 numops = 1;
126 nfsm_chain_build_alloc_init(error, &nmreq, 14 * NFSX_UNSIGNED + idlen);
127 nfsm_chain_add_compound_header(error, &nmreq, "setclientid", numops);
128 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);
142 nfsmout_if(error);
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");
149 nfsmout_if(error);
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);
154
155 // SETCLIENTID_CONFIRM
156 numops = 1;
157 nfsm_chain_build_alloc_init(error, &nmreq, 13 * NFSX_UNSIGNED);
158 nfsm_chain_add_compound_header(error, &nmreq, "setclientid_confirm", numops);
159 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);
165 nfsmout_if(error);
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);
170 if (error)
171 printf("nfs4_setclientid: confirm error %d\n", error);
172 nfsmout:
173 nfsm_chain_cleanup(&nmreq);
174 nfsm_chain_cleanup(&nmrep);
175 if (error)
176 printf("nfs4_setclientid failed, %d\n", error);
177 return (error);
178 }
179
180 /*
181 * periodic timer to renew lease state on server
182 */
183 void
184 nfs4_renew_timer(void *param0, __unused void *param1)
185 {
186 struct nfsmount *nmp = param0;
187 int error = 0, status, numops, interval;
188 u_int64_t xid;
189 vfs_context_t ctx;
190 struct nfsm_chain nmreq, nmrep;
191
192 ctx = vfs_context_kernel(); /* XXX */
193
194 nfsm_chain_null(&nmreq);
195 nfsm_chain_null(&nmrep);
196
197 // RENEW
198 numops = 1;
199 nfsm_chain_build_alloc_init(error, &nmreq, 8 * NFSX_UNSIGNED);
200 nfsm_chain_add_compound_header(error, &nmreq, "renew", numops);
201 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);
206 nfsmout_if(error);
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);
211 nfsmout:
212 if (error)
213 printf("nfs4_renew_timer: error %d\n", error);
214 nfsm_chain_cleanup(&nmreq);
215 nfsm_chain_cleanup(&nmrep);
216
217 interval = nmp->nm_fsattr.nfsa_lease / (error ? 4 : 2);
218 if (interval < 1)
219 interval = 1;
220 nfs_interval_timer_start(nmp->nm_renew_timer, interval * 1000);
221 }
222
223 /*
224 * Set a vnode attr's supported bits according to the given bitmap
225 */
226 void
227 nfs_vattr_set_supported(uint32_t *bitmap, struct vnode_attr *vap)
228 {
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);
269 }
270
271 /*
272 * Parse the attributes that are in the mbuf list and store them in
273 * the given structures.
274 */
275 int
276 nfs4_parsefattr(
277 struct nfsm_chain *nmc,
278 struct nfs_fsattr *nfsap,
279 struct nfs_vattr *nvap,
280 fhandle_t *fhp,
281 struct dqblk *dqbp)
282 {
283 int error = 0, attrbytes;
284 uint32_t val, val2, val3, i, j;
285 uint32_t bitmap[NFS_ATTR_BITMAP_LEN], len;
286 char *s;
287 struct nfs_fsattr nfsa_dummy;
288 struct nfs_vattr nva_dummy;
289 struct dqblk dqb_dummy;
290
291 /* if not interested in some values... throw 'em into a local dummy variable */
292 if (!nfsap)
293 nfsap = &nfsa_dummy;
294 if (!nvap)
295 nvap = &nva_dummy;
296 if (!dqbp)
297 dqbp = &dqb_dummy;
298
299 attrbytes = val = val2 = val3 = 0;
300
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];
307 }
308
309 nfsm_chain_get_32(error, nmc, attrbytes);
310 nfsmout_if(error);
311
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;
316 }
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;
321 }
322 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FH_EXPIRE_TYPE)) {
323 nfsm_chain_get_32(error, nmc, val);
324 nfsmout_if(error);
325 if (val != NFS_FH_PERSISTENT)
326 printf("nfs: warning: non-persistent file handles!\n");
327 if (val & ~0xff)
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;
332 }
333 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CHANGE)) {
334 nfsm_chain_get_64(error, nmc, nvap->nva_change);
335 attrbytes -= 2 * NFSX_UNSIGNED;
336 }
337 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SIZE)) {
338 nfsm_chain_get_64(error, nmc, nvap->nva_size);
339 attrbytes -= 2 * NFSX_UNSIGNED;
340 }
341 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_LINK_SUPPORT)) {
342 nfsm_chain_get_32(error, nmc, val);
343 if (val)
344 nfsap->nfsa_flags |= NFS_FSFLAG_LINK;
345 else
346 nfsap->nfsa_flags &= ~NFS_FSFLAG_LINK;
347 attrbytes -= NFSX_UNSIGNED;
348 }
349 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SYMLINK_SUPPORT)) {
350 nfsm_chain_get_32(error, nmc, val);
351 if (val)
352 nfsap->nfsa_flags |= NFS_FSFLAG_SYMLINK;
353 else
354 nfsap->nfsa_flags &= ~NFS_FSFLAG_SYMLINK;
355 attrbytes -= NFSX_UNSIGNED;
356 }
357 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_NAMED_ATTR)) {
358 nfsm_chain_get_32(error, nmc, val);
359 if (val)
360 nvap->nva_flags |= NFS_FFLAG_NAMED_ATTR;
361 else
362 nvap->nva_flags &= ~NFS_FFLAG_NAMED_ATTR;
363 attrbytes -= NFSX_UNSIGNED;
364 }
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;
369 }
370 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_UNIQUE_HANDLES)) {
371 nfsm_chain_get_32(error, nmc, val);
372 if (val)
373 nfsap->nfsa_flags |= NFS_FSFLAG_UNIQUE_FH;
374 else
375 nfsap->nfsa_flags &= ~NFS_FSFLAG_UNIQUE_FH;
376 attrbytes -= NFSX_UNSIGNED;
377 }
378 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_LEASE_TIME)) {
379 nfsm_chain_get_32(error, nmc, nfsap->nfsa_lease);
380 attrbytes -= NFSX_UNSIGNED;
381 }
382 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_RDATTR_ERROR)) {
383 nfsm_chain_get_32(error, nmc, error);
384 attrbytes -= NFSX_UNSIGNED;
385 nfsmout_if(error);
386 }
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);
395 }
396 }
397 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ACLSUPPORT)) {
398 nfsm_chain_get_32(error, nmc, val);
399 if (val)
400 nfsap->nfsa_flags |= NFS_FSFLAG_ACL;
401 else
402 nfsap->nfsa_flags &= ~NFS_FSFLAG_ACL;
403 attrbytes -= NFSX_UNSIGNED;
404 }
405 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ARCHIVE)) { /* SF_ARCHIVED */
406 nfsm_chain_get_32(error, nmc, val);
407 if (val)
408 nvap->nva_flags |= NFS_FFLAG_ARCHIVED;
409 else
410 nvap->nva_flags &= ~NFS_FFLAG_ARCHIVED;
411 attrbytes -= NFSX_UNSIGNED;
412 }
413 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CANSETTIME)) {
414 nfsm_chain_get_32(error, nmc, val);
415 if (val)
416 nfsap->nfsa_flags |= NFS_FSFLAG_SET_TIME;
417 else
418 nfsap->nfsa_flags &= ~NFS_FSFLAG_SET_TIME;
419 attrbytes -= NFSX_UNSIGNED;
420 }
421 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CASE_INSENSITIVE)) {
422 nfsm_chain_get_32(error, nmc, val);
423 if (val)
424 nfsap->nfsa_flags |= NFS_FSFLAG_CASE_INSENSITIVE;
425 else
426 nfsap->nfsa_flags &= ~NFS_FSFLAG_CASE_INSENSITIVE;
427 attrbytes -= NFSX_UNSIGNED;
428 }
429 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CASE_PRESERVING)) {
430 nfsm_chain_get_32(error, nmc, val);
431 if (val)
432 nfsap->nfsa_flags |= NFS_FSFLAG_CASE_PRESERVING;
433 else
434 nfsap->nfsa_flags &= ~NFS_FSFLAG_CASE_PRESERVING;
435 attrbytes -= NFSX_UNSIGNED;
436 }
437 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CHOWN_RESTRICTED)) {
438 nfsm_chain_get_32(error, nmc, val);
439 if (val)
440 nfsap->nfsa_flags |= NFS_FSFLAG_CHOWN_RESTRICTED;
441 else
442 nfsap->nfsa_flags &= ~NFS_FSFLAG_CHOWN_RESTRICTED;
443 attrbytes -= NFSX_UNSIGNED;
444 }
445 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FILEHANDLE)) {
446 nfsm_chain_get_32(error, nmc, val);
447 if (fhp) {
448 fhp->fh_len = val;
449 nfsm_chain_get_opaque(error, nmc, nfsm_rndup(val), fhp->fh_data);
450 } else {
451 nfsm_chain_adv(error, nmc, nfsm_rndup(val));
452 }
453 attrbytes -= NFSX_UNSIGNED + nfsm_rndup(val);
454 }
455 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FILEID)) {
456 nfsm_chain_get_64(error, nmc, nvap->nva_fileid);
457 attrbytes -= 2 * NFSX_UNSIGNED;
458 }
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;
462 }
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;
466 }
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;
470 }
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);
486 }
487 nfsm_assert(error, (attrbytes >= 0), EBADRPC);
488 }
489 nfsm_assert(error, (attrbytes >= 0), EBADRPC);
490 }
491 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_HIDDEN)) { /* UF_HIDDEN */
492 nfsm_chain_get_32(error, nmc, val);
493 if (val)
494 nvap->nva_flags |= NFS_FFLAG_HIDDEN;
495 else
496 nvap->nva_flags &= ~NFS_FFLAG_HIDDEN;
497 attrbytes -= NFSX_UNSIGNED;
498 }
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);
502 if (val)
503 nfsap->nfsa_flags |= NFS_FSFLAG_HOMOGENEOUS;
504 else
505 nfsap->nfsa_flags &= ~NFS_FSFLAG_HOMOGENEOUS;
506 attrbytes -= NFSX_UNSIGNED;
507 }
508 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MAXFILESIZE)) {
509 nfsm_chain_get_64(error, nmc, nfsap->nfsa_maxfilesize);
510 attrbytes -= 2 * NFSX_UNSIGNED;
511 }
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;
517 }
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;
523 }
524 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MAXREAD)) {
525 nfsm_chain_get_64(error, nmc, nfsap->nfsa_maxread);
526 attrbytes -= 2 * NFSX_UNSIGNED;
527 }
528 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MAXWRITE)) {
529 nfsm_chain_get_64(error, nmc, nfsap->nfsa_maxwrite);
530 attrbytes -= 2 * NFSX_UNSIGNED;
531 }
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);
536 }
537 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MODE)) {
538 nfsm_chain_get_32(error, nmc, nvap->nva_mode);
539 attrbytes -= NFSX_UNSIGNED;
540 }
541 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_NO_TRUNC)) {
542 nfsm_chain_get_32(error, nmc, val);
543 if (val)
544 nfsap->nfsa_flags |= NFS_FSFLAG_NO_TRUNC;
545 else
546 nfsap->nfsa_flags &= ~NFS_FSFLAG_NO_TRUNC;
547 attrbytes -= NFSX_UNSIGNED;
548 }
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;
553 }
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);
558 nfsmout_if(error);
559 if ((*s >= '0') && (*s <= '9'))
560 nvap->nva_uid = strtol(s, NULL, 10);
561 else if (!strncmp(s, "nobody@", 7))
562 nvap->nva_uid = -2;
563 else if (!strncmp(s, "root@", 5))
564 nvap->nva_uid = 0;
565 else
566 nvap->nva_uid = 99; /* unknown */
567 }
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);
572 nfsmout_if(error);
573 if ((*s >= '0') && (*s <= '9'))
574 nvap->nva_gid = strtol(s, NULL, 10);
575 else if (!strncmp(s, "nobody@", 7))
576 nvap->nva_gid = -2;
577 else if (!strncmp(s, "root@", 5))
578 nvap->nva_uid = 0;
579 else
580 nvap->nva_gid = 99; /* unknown */
581 }
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;
585 }
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;
589 }
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;
593 }
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;
598 }
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;
602 }
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;
606 }
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;
610 }
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;
614 }
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;
619 }
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;
624 }
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;
628 }
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;
633 }
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;
638 }
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;
642 }
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;
647 }
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;
652 }
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;
656 }
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;
660 }
661 /* advance over any leftover attrbytes */
662 nfsm_assert(error, (attrbytes >= 0), EBADRPC);
663 nfsm_chain_adv(error, nmc, nfsm_rndup(attrbytes));
664 nfsmout:
665 return (error);
666 }
667
668 /*
669 * Add an NFSv4 "sattr" structure to an mbuf chain
670 */
671 int
672 nfsm_chain_add_fattr4_f(struct nfsm_chain *nmc, struct vnode_attr *vap, struct nfsmount *nmp)
673 {
674 int error = 0, attrbytes, slen, i;
675 uint32_t *pattrbytes;
676 uint32_t bitmap[NFS_ATTR_BITMAP_LEN];
677 char s[32];
678
679 /*
680 * Do this in two passes.
681 * First calculate the bitmap, then pack
682 * everything together and set the size.
683 */
684
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)
690 }
691 if (VATTR_IS_ACTIVE(vap, va_flags)) {
692 NFS_BITMAP_SET(bitmap, NFS_FATTR_ARCHIVE);
693 NFS_BITMAP_SET(bitmap, NFS_FATTR_HIDDEN);
694 }
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);
706 } else {
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);
711 }
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];
719
720 /*
721 * Now pack it all together:
722 * BITMAP, #BYTES, ATTRS
723 * Keep a pointer to the length so we can set it later.
724 */
725 nfsm_chain_add_bitmap(error, nmc, bitmap, NFS_ATTR_BITMAP_LEN);
726 attrbytes = 0;
727 nfsm_chain_add_32(error, nmc, attrbytes);
728 pattrbytes = (uint32_t*)(nmc->nmc_ptr - NFSX_UNSIGNED);
729
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;
733 }
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;
738 }
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;
742 }
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;
747 }
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);
752 }
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);
757 }
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;
763 } else {
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;
768 }
769 }
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;
774 }
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;
779 }
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;
784 } else {
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;
789 }
790 }
791 nfsmout_if(error);
792 /* Now, set the attribute data length */
793 *pattrbytes = txdr_unsigned(attrbytes);
794 nfsmout:
795 return (error);
796 }
797