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 */ 77int 78nfs4_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); 172nfsmout: 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 */ 183void 184nfs4_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); 211nfsmout: 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 */ 226void 227nfs_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 */ 275int 276nfs4_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)); 664nfsmout: 665 return (error); 666} 667 668/* 669 * Add an NFSv4 "sattr" structure to an mbuf chain 670 */ 671int 672nfsm_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); 794nfsmout: 795 return (error); 796} 797 798