1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Rick Macklem at The University of Guelph. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35 36 #include <sys/cdefs.h> 37 #include "opt_inet.h" 38 #include "opt_inet6.h" 39 /* 40 * nfs version 2, 3 and 4 server calls to vnode ops 41 * - these routines generally have 3 phases 42 * 1 - break down and validate rpc request in mbuf list 43 * 2 - do the vnode ops for the request, usually by calling a nfsvno_XXX() 44 * function in nfsd_port.c 45 * 3 - build the rpc reply in an mbuf list 46 * For nfsv4, these functions are called for each Op within the Compound RPC. 47 */ 48 49 #include <fs/nfs/nfsport.h> 50 #include <sys/extattr.h> 51 #include <sys/filio.h> 52 53 /* Global vars */ 54 extern u_int32_t newnfs_false, newnfs_true; 55 extern __enum_uint8(vtype) nv34tov_type[8]; 56 extern struct timeval nfsboottime; 57 extern int nfsrv_enable_crossmntpt; 58 extern int nfsrv_statehashsize; 59 extern int nfsrv_layouthashsize; 60 extern time_t nfsdev_time; 61 extern volatile int nfsrv_devidcnt; 62 extern int nfsd_debuglevel; 63 extern u_long sb_max_adj; 64 extern int nfsrv_pnfsatime; 65 extern int nfsrv_maxpnfsmirror; 66 extern uint32_t nfs_srvmaxio; 67 68 static int nfs_async = 0; 69 SYSCTL_DECL(_vfs_nfsd); 70 SYSCTL_INT(_vfs_nfsd, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0, 71 "Tell client that writes were synced even though they were not"); 72 extern int nfsrv_doflexfile; 73 SYSCTL_INT(_vfs_nfsd, OID_AUTO, default_flexfile, CTLFLAG_RW, 74 &nfsrv_doflexfile, 0, "Make Flex File Layout the default for pNFS"); 75 static int nfsrv_linux42server = 1; 76 SYSCTL_INT(_vfs_nfsd, OID_AUTO, linux42server, CTLFLAG_RW, 77 &nfsrv_linux42server, 0, 78 "Enable Linux style NFSv4.2 server (non-RFC compliant)"); 79 static bool nfsrv_openaccess = true; 80 SYSCTL_BOOL(_vfs_nfsd, OID_AUTO, v4openaccess, CTLFLAG_RW, 81 &nfsrv_openaccess, 0, 82 "Enable Linux style NFSv4 Open access check"); 83 static char nfsrv_scope[NFSV4_OPAQUELIMIT]; 84 SYSCTL_STRING(_vfs_nfsd, OID_AUTO, scope, CTLFLAG_RWTUN, 85 &nfsrv_scope, NFSV4_OPAQUELIMIT, "Server scope"); 86 static char nfsrv_owner_major[NFSV4_OPAQUELIMIT]; 87 SYSCTL_STRING(_vfs_nfsd, OID_AUTO, owner_major, CTLFLAG_RWTUN, 88 &nfsrv_owner_major, NFSV4_OPAQUELIMIT, "Server owner major"); 89 static uint64_t nfsrv_owner_minor; 90 SYSCTL_U64(_vfs_nfsd, OID_AUTO, owner_minor, CTLFLAG_RWTUN, 91 &nfsrv_owner_minor, 0, "Server owner minor"); 92 /* 93 * Only enable this if all your exported file systems 94 * (or pNFS DSs for the pNFS case) support VOP_ALLOCATE. 95 */ 96 static bool nfsrv_doallocate = false; 97 SYSCTL_BOOL(_vfs_nfsd, OID_AUTO, enable_v42allocate, CTLFLAG_RW, 98 &nfsrv_doallocate, 0, 99 "Enable NFSv4.2 Allocate operation"); 100 static uint64_t nfsrv_maxcopyrange = SSIZE_MAX; 101 SYSCTL_U64(_vfs_nfsd, OID_AUTO, maxcopyrange, CTLFLAG_RW, 102 &nfsrv_maxcopyrange, 0, "Max size of a Copy so RPC times reasonable"); 103 104 /* 105 * This list defines the GSS mechanisms supported. 106 * (Don't ask me how you get these strings from the RFC stuff like 107 * iso(1), org(3)... but someone did it, so I don't need to know.) 108 */ 109 static struct nfsgss_mechlist nfsgss_mechlist[] = { 110 { 9, "\052\206\110\206\367\022\001\002\002", 11 }, 111 { 0, "", 0 }, 112 }; 113 114 /* local functions */ 115 static void nfsrvd_symlinksub(struct nfsrv_descript *nd, struct nameidata *ndp, 116 struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp, 117 vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp, 118 int *diraft_retp, nfsattrbit_t *attrbitp, 119 NFSACL_T *aclp, NFSPROC_T *p, struct nfsexstuff *exp, char *pathcp, 120 int pathlen); 121 static void nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct nameidata *ndp, 122 struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp, 123 vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp, 124 int *diraft_retp, nfsattrbit_t *attrbitp, NFSACL_T *aclp, 125 NFSPROC_T *p, struct nfsexstuff *exp); 126 127 /* 128 * nfs access service (not a part of NFS V2) 129 */ 130 int 131 nfsrvd_access(struct nfsrv_descript *nd, __unused int isdgram, 132 vnode_t vp, struct nfsexstuff *exp) 133 { 134 u_int32_t *tl; 135 int getret, error = 0; 136 struct nfsvattr nva; 137 u_int32_t testmode, nfsmode, supported = 0; 138 accmode_t deletebit; 139 struct thread *p = curthread; 140 141 if (nd->nd_repstat) { 142 nfsrv_postopattr(nd, 1, &nva); 143 goto out; 144 } 145 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 146 nfsmode = fxdr_unsigned(u_int32_t, *tl); 147 if ((nd->nd_flag & ND_NFSV4) && 148 (nfsmode & ~(NFSACCESS_READ | NFSACCESS_LOOKUP | 149 NFSACCESS_MODIFY | NFSACCESS_EXTEND | NFSACCESS_DELETE | 150 NFSACCESS_EXECUTE | NFSACCESS_XAREAD | NFSACCESS_XAWRITE | 151 NFSACCESS_XALIST))) { 152 nd->nd_repstat = NFSERR_INVAL; 153 vput(vp); 154 goto out; 155 } 156 if (nfsmode & NFSACCESS_READ) { 157 supported |= NFSACCESS_READ; 158 if (nfsvno_accchk(vp, VREAD, nd->nd_cred, exp, p, 159 NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported)) 160 nfsmode &= ~NFSACCESS_READ; 161 } 162 if (nfsmode & NFSACCESS_MODIFY) { 163 supported |= NFSACCESS_MODIFY; 164 if (nfsvno_accchk(vp, VWRITE, nd->nd_cred, exp, p, 165 NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported)) 166 nfsmode &= ~NFSACCESS_MODIFY; 167 } 168 if (nfsmode & NFSACCESS_EXTEND) { 169 supported |= NFSACCESS_EXTEND; 170 if (nfsvno_accchk(vp, VWRITE | VAPPEND, nd->nd_cred, exp, p, 171 NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported)) 172 nfsmode &= ~NFSACCESS_EXTEND; 173 } 174 if (nfsmode & NFSACCESS_XAREAD) { 175 supported |= NFSACCESS_XAREAD; 176 if (nfsvno_accchk(vp, VREAD, nd->nd_cred, exp, p, 177 NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported)) 178 nfsmode &= ~NFSACCESS_XAREAD; 179 } 180 if (nfsmode & NFSACCESS_XAWRITE) { 181 supported |= NFSACCESS_XAWRITE; 182 if (nfsvno_accchk(vp, VWRITE, nd->nd_cred, exp, p, 183 NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported)) 184 nfsmode &= ~NFSACCESS_XAWRITE; 185 } 186 if (nfsmode & NFSACCESS_XALIST) { 187 supported |= NFSACCESS_XALIST; 188 if (nfsvno_accchk(vp, VREAD, nd->nd_cred, exp, p, 189 NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported)) 190 nfsmode &= ~NFSACCESS_XALIST; 191 } 192 if (nfsmode & NFSACCESS_DELETE) { 193 supported |= NFSACCESS_DELETE; 194 if (vp->v_type == VDIR) 195 deletebit = VDELETE_CHILD; 196 else 197 deletebit = VDELETE; 198 if (nfsvno_accchk(vp, deletebit, nd->nd_cred, exp, p, 199 NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported)) 200 nfsmode &= ~NFSACCESS_DELETE; 201 } 202 if (vp->v_type == VDIR) 203 testmode = NFSACCESS_LOOKUP; 204 else 205 testmode = NFSACCESS_EXECUTE; 206 if (nfsmode & testmode) { 207 supported |= (nfsmode & testmode); 208 if (nfsvno_accchk(vp, VEXEC, nd->nd_cred, exp, p, 209 NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported)) 210 nfsmode &= ~testmode; 211 } 212 nfsmode &= supported; 213 if (nd->nd_flag & ND_NFSV3) { 214 getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL); 215 nfsrv_postopattr(nd, getret, &nva); 216 } 217 vput(vp); 218 if (nd->nd_flag & ND_NFSV4) { 219 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 220 *tl++ = txdr_unsigned(supported); 221 } else 222 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 223 *tl = txdr_unsigned(nfsmode); 224 225 out: 226 NFSEXITCODE2(0, nd); 227 return (0); 228 nfsmout: 229 vput(vp); 230 NFSEXITCODE2(error, nd); 231 return (error); 232 } 233 234 /* 235 * nfs getattr service 236 */ 237 int 238 nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram, 239 vnode_t vp, __unused struct nfsexstuff *exp) 240 { 241 struct nfsvattr nva; 242 fhandle_t fh; 243 int at_root = 0, error = 0, supports_nfsv4acls; 244 struct nfsreferral *refp; 245 nfsattrbit_t attrbits, tmpbits; 246 struct mount *mp; 247 struct vnode *tvp = NULL; 248 struct vattr va; 249 uint64_t mounted_on_fileno = 0; 250 accmode_t accmode; 251 struct thread *p = curthread; 252 253 if (nd->nd_repstat) 254 goto out; 255 if (nd->nd_flag & ND_NFSV4) { 256 error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL); 257 if (error) { 258 vput(vp); 259 goto out; 260 } 261 262 /* 263 * Check for a referral. 264 */ 265 refp = nfsv4root_getreferral(vp, NULL, 0); 266 if (refp != NULL) { 267 (void) nfsrv_putreferralattr(nd, &attrbits, refp, 1, 268 &nd->nd_repstat); 269 vput(vp); 270 goto out; 271 } 272 if (nd->nd_repstat == 0) { 273 accmode = 0; 274 NFSSET_ATTRBIT(&tmpbits, &attrbits); 275 276 /* 277 * GETATTR with write-only attr time_access_set and time_modify_set 278 * should return NFS4ERR_INVAL. 279 */ 280 if (NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_TIMEACCESSSET) || 281 NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_TIMEMODIFYSET)){ 282 error = NFSERR_INVAL; 283 vput(vp); 284 goto out; 285 } 286 if (NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_ACL)) { 287 NFSCLRBIT_ATTRBIT(&tmpbits, NFSATTRBIT_ACL); 288 accmode |= VREAD_ACL; 289 } 290 if (NFSNONZERO_ATTRBIT(&tmpbits)) 291 accmode |= VREAD_ATTRIBUTES; 292 if (accmode != 0) 293 nd->nd_repstat = nfsvno_accchk(vp, accmode, 294 nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE, 295 NFSACCCHK_VPISLOCKED, NULL); 296 } 297 } 298 if (!nd->nd_repstat) 299 nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, &attrbits); 300 if (!nd->nd_repstat) { 301 if (nd->nd_flag & ND_NFSV4) { 302 if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_FILEHANDLE)) 303 nd->nd_repstat = nfsvno_getfh(vp, &fh, p); 304 if (!nd->nd_repstat) 305 nd->nd_repstat = nfsrv_checkgetattr(nd, vp, 306 &nva, &attrbits, p); 307 if (nd->nd_repstat == 0) { 308 supports_nfsv4acls = nfs_supportsnfsv4acls(vp); 309 mp = vp->v_mount; 310 if (nfsrv_enable_crossmntpt != 0 && 311 vp->v_type == VDIR && 312 (vp->v_vflag & VV_ROOT) != 0 && 313 vp != rootvnode) { 314 tvp = mp->mnt_vnodecovered; 315 VREF(tvp); 316 at_root = 1; 317 } else 318 at_root = 0; 319 vfs_ref(mp); 320 NFSVOPUNLOCK(vp); 321 if (at_root != 0) { 322 if ((nd->nd_repstat = 323 NFSVOPLOCK(tvp, LK_SHARED)) == 0) { 324 nd->nd_repstat = VOP_GETATTR( 325 tvp, &va, nd->nd_cred); 326 vput(tvp); 327 } else 328 vrele(tvp); 329 if (nd->nd_repstat == 0) 330 mounted_on_fileno = (uint64_t) 331 va.va_fileid; 332 else 333 at_root = 0; 334 } 335 if (nd->nd_repstat == 0) 336 nd->nd_repstat = vfs_busy(mp, 0); 337 vfs_rel(mp); 338 if (nd->nd_repstat == 0) { 339 (void)nfsvno_fillattr(nd, mp, vp, &nva, 340 &fh, 0, &attrbits, nd->nd_cred, p, 341 isdgram, 1, supports_nfsv4acls, 342 at_root, mounted_on_fileno); 343 vfs_unbusy(mp); 344 } 345 vrele(vp); 346 } else 347 vput(vp); 348 } else { 349 nfsrv_fillattr(nd, &nva); 350 vput(vp); 351 } 352 } else { 353 vput(vp); 354 } 355 356 out: 357 NFSEXITCODE2(error, nd); 358 return (error); 359 } 360 361 /* 362 * nfs setattr service 363 */ 364 int 365 nfsrvd_setattr(struct nfsrv_descript *nd, __unused int isdgram, 366 vnode_t vp, struct nfsexstuff *exp) 367 { 368 struct nfsvattr nva, nva2; 369 u_int32_t *tl; 370 int preat_ret = 1, postat_ret = 1, gcheck = 0, error = 0; 371 int gotproxystateid; 372 struct timespec guard = { 0, 0 }; 373 nfsattrbit_t attrbits, retbits; 374 nfsv4stateid_t stateid; 375 NFSACL_T *aclp = NULL; 376 struct thread *p = curthread; 377 378 if (nd->nd_repstat) { 379 nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva); 380 goto out; 381 } 382 #ifdef NFS4_ACL_EXTATTR_NAME 383 aclp = acl_alloc(M_WAITOK); 384 aclp->acl_cnt = 0; 385 #endif 386 gotproxystateid = 0; 387 NFSVNO_ATTRINIT(&nva); 388 if (nd->nd_flag & ND_NFSV4) { 389 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID); 390 stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 391 stateid.other[0] = *tl++; 392 stateid.other[1] = *tl++; 393 stateid.other[2] = *tl; 394 if (stateid.other[0] == 0x55555555 && 395 stateid.other[1] == 0x55555555 && 396 stateid.other[2] == 0x55555555 && 397 stateid.seqid == 0xffffffff) 398 gotproxystateid = 1; 399 } 400 error = nfsrv_sattr(nd, vp, &nva, &attrbits, aclp, p); 401 if (error) 402 goto nfsmout; 403 404 /* For NFSv4, only va_uid is used from nva2. */ 405 NFSZERO_ATTRBIT(&retbits); 406 NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNER); 407 preat_ret = nfsvno_getattr(vp, &nva2, nd, p, 1, &retbits); 408 if (!nd->nd_repstat) 409 nd->nd_repstat = preat_ret; 410 411 NFSZERO_ATTRBIT(&retbits); 412 if (nd->nd_flag & ND_NFSV3) { 413 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 414 gcheck = fxdr_unsigned(int, *tl); 415 if (gcheck) { 416 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 417 fxdr_nfsv3time(tl, &guard); 418 } 419 if (!nd->nd_repstat && gcheck && 420 (nva2.na_ctime.tv_sec != guard.tv_sec || 421 nva2.na_ctime.tv_nsec != guard.tv_nsec)) 422 nd->nd_repstat = NFSERR_NOT_SYNC; 423 if (nd->nd_repstat) { 424 vput(vp); 425 #ifdef NFS4_ACL_EXTATTR_NAME 426 acl_free(aclp); 427 #endif 428 nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva); 429 goto out; 430 } 431 } else if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) 432 nd->nd_repstat = nfsrv_checkuidgid(nd, &nva); 433 434 /* 435 * Now that we have all the fields, lets do it. 436 * If the size is being changed write access is required, otherwise 437 * just check for a read only file system. 438 */ 439 if (!nd->nd_repstat) { 440 if (NFSVNO_NOTSETSIZE(&nva)) { 441 if (NFSVNO_EXRDONLY(exp) || 442 (vp->v_mount->mnt_flag & MNT_RDONLY)) 443 nd->nd_repstat = EROFS; 444 } else { 445 if (vp->v_type != VREG) 446 nd->nd_repstat = EINVAL; 447 else if (nva2.na_uid != nd->nd_cred->cr_uid || 448 NFSVNO_EXSTRICTACCESS(exp)) 449 nd->nd_repstat = nfsvno_accchk(vp, 450 VWRITE, nd->nd_cred, exp, p, 451 NFSACCCHK_NOOVERRIDE, 452 NFSACCCHK_VPISLOCKED, NULL); 453 } 454 } 455 /* 456 * Proxy operations from the MDS are allowed via the all 0s special 457 * stateid. 458 */ 459 if (nd->nd_repstat == 0 && (nd->nd_flag & ND_NFSV4) != 0 && 460 gotproxystateid == 0) 461 nd->nd_repstat = nfsrv_checksetattr(vp, nd, &stateid, 462 &nva, &attrbits, exp, p); 463 464 if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) { 465 /* 466 * For V4, try setting the attributes in sets, so that the 467 * reply bitmap will be correct for an error case. 468 */ 469 if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNER) || 470 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNERGROUP)) { 471 NFSVNO_ATTRINIT(&nva2); 472 NFSVNO_SETATTRVAL(&nva2, uid, nva.na_uid); 473 NFSVNO_SETATTRVAL(&nva2, gid, nva.na_gid); 474 nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p, 475 exp); 476 if (!nd->nd_repstat) { 477 if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNER)) 478 NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNER); 479 if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNERGROUP)) 480 NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNERGROUP); 481 } 482 } 483 if (!nd->nd_repstat && 484 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_SIZE)) { 485 NFSVNO_ATTRINIT(&nva2); 486 NFSVNO_SETATTRVAL(&nva2, size, nva.na_size); 487 nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p, 488 exp); 489 if (!nd->nd_repstat) 490 NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_SIZE); 491 } 492 if (!nd->nd_repstat && 493 (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET) || 494 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFYSET))) { 495 NFSVNO_ATTRINIT(&nva2); 496 NFSVNO_SETATTRVAL(&nva2, atime, nva.na_atime); 497 NFSVNO_SETATTRVAL(&nva2, mtime, nva.na_mtime); 498 if (nva.na_vaflags & VA_UTIMES_NULL) { 499 nva2.na_vaflags |= VA_UTIMES_NULL; 500 NFSVNO_SETACTIVE(&nva2, vaflags); 501 } 502 nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p, 503 exp); 504 if (!nd->nd_repstat) { 505 if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET)) 506 NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_TIMEACCESSSET); 507 if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFYSET)) 508 NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_TIMEMODIFYSET); 509 } 510 } 511 if (!nd->nd_repstat && 512 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMECREATE)) { 513 NFSVNO_ATTRINIT(&nva2); 514 NFSVNO_SETATTRVAL(&nva2, btime, nva.na_btime); 515 nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p, 516 exp); 517 if (!nd->nd_repstat) 518 NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_TIMECREATE); 519 } 520 if (!nd->nd_repstat && 521 (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODE) || 522 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODESETMASKED))) { 523 NFSVNO_ATTRINIT(&nva2); 524 NFSVNO_SETATTRVAL(&nva2, mode, nva.na_mode); 525 nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p, 526 exp); 527 if (!nd->nd_repstat) { 528 if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODE)) 529 NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_MODE); 530 if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODESETMASKED)) 531 NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_MODESETMASKED); 532 } 533 } 534 535 #ifdef NFS4_ACL_EXTATTR_NAME 536 if (!nd->nd_repstat && aclp->acl_cnt > 0 && 537 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_ACL)) { 538 nd->nd_repstat = nfsrv_setacl(vp, aclp, nd->nd_cred, p); 539 if (!nd->nd_repstat) 540 NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_ACL); 541 } 542 #endif 543 } else if (!nd->nd_repstat) { 544 nd->nd_repstat = nfsvno_setattr(vp, &nva, nd->nd_cred, p, 545 exp); 546 } 547 if (nd->nd_flag & (ND_NFSV2 | ND_NFSV3)) { 548 postat_ret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL); 549 if (!nd->nd_repstat) 550 nd->nd_repstat = postat_ret; 551 } 552 vput(vp); 553 #ifdef NFS4_ACL_EXTATTR_NAME 554 acl_free(aclp); 555 #endif 556 if (nd->nd_flag & ND_NFSV3) 557 nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva); 558 else if (nd->nd_flag & ND_NFSV4) 559 (void) nfsrv_putattrbit(nd, &retbits); 560 else if (!nd->nd_repstat) 561 nfsrv_fillattr(nd, &nva); 562 563 out: 564 NFSEXITCODE2(0, nd); 565 return (0); 566 nfsmout: 567 vput(vp); 568 #ifdef NFS4_ACL_EXTATTR_NAME 569 acl_free(aclp); 570 #endif 571 if (nd->nd_flag & ND_NFSV4) { 572 /* 573 * For all nd_repstat, the V4 reply includes a bitmap, 574 * even NFSERR_BADXDR, which is what this will end up 575 * returning. 576 */ 577 (void) nfsrv_putattrbit(nd, &retbits); 578 } 579 NFSEXITCODE2(error, nd); 580 return (error); 581 } 582 583 /* 584 * nfs lookup rpc 585 * (Also performs lookup parent for v4) 586 */ 587 int 588 nfsrvd_lookup(struct nfsrv_descript *nd, __unused int isdgram, 589 vnode_t dp, vnode_t *vpp, fhandle_t *fhp, struct nfsexstuff *exp) 590 { 591 struct nameidata named; 592 vnode_t vp, dirp = NULL; 593 int error = 0, dattr_ret = 1; 594 struct nfsvattr nva, dattr; 595 char *bufp; 596 u_long *hashp; 597 struct thread *p = curthread; 598 599 if (nd->nd_repstat) { 600 nfsrv_postopattr(nd, dattr_ret, &dattr); 601 goto out; 602 } 603 604 /* 605 * For some reason, if dp is a symlink, the error 606 * returned is supposed to be NFSERR_SYMLINK and not NFSERR_NOTDIR. 607 */ 608 if (dp->v_type == VLNK && (nd->nd_flag & ND_NFSV4)) { 609 nd->nd_repstat = NFSERR_SYMLINK; 610 vrele(dp); 611 goto out; 612 } 613 614 NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP, 615 LOCKLEAF); 616 nfsvno_setpathbuf(&named, &bufp, &hashp); 617 error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 618 if (error) { 619 vrele(dp); 620 nfsvno_relpathbuf(&named); 621 goto out; 622 } 623 if (!nd->nd_repstat) { 624 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, &dirp); 625 } else { 626 vrele(dp); 627 nfsvno_relpathbuf(&named); 628 } 629 if (nd->nd_repstat) { 630 if (dirp) { 631 if (nd->nd_flag & ND_NFSV3) 632 dattr_ret = nfsvno_getattr(dirp, &dattr, nd, p, 633 0, NULL); 634 vrele(dirp); 635 } 636 if (nd->nd_flag & ND_NFSV3) 637 nfsrv_postopattr(nd, dattr_ret, &dattr); 638 goto out; 639 } 640 nfsvno_relpathbuf(&named); 641 vp = named.ni_vp; 642 if ((nd->nd_flag & ND_NFSV4) != 0 && !NFSVNO_EXPORTED(exp) && 643 vp->v_type != VDIR && vp->v_type != VLNK) 644 /* 645 * Only allow lookup of VDIR and VLNK for traversal of 646 * non-exported volumes during NFSv4 mounting. 647 */ 648 nd->nd_repstat = ENOENT; 649 if (nd->nd_repstat == 0) { 650 nd->nd_repstat = nfsvno_getfh(vp, fhp, p); 651 /* 652 * EOPNOTSUPP indicates the file system cannot be exported, 653 * so just pretend the entry does not exist. 654 */ 655 if (nd->nd_repstat == EOPNOTSUPP) 656 nd->nd_repstat = ENOENT; 657 } 658 if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) 659 nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, NULL); 660 if (vpp != NULL && nd->nd_repstat == 0) 661 *vpp = vp; 662 else 663 vput(vp); 664 if (dirp) { 665 if (nd->nd_flag & ND_NFSV3) 666 dattr_ret = nfsvno_getattr(dirp, &dattr, nd, p, 0, 667 NULL); 668 vrele(dirp); 669 } 670 if (nd->nd_repstat) { 671 if (nd->nd_flag & ND_NFSV3) 672 nfsrv_postopattr(nd, dattr_ret, &dattr); 673 goto out; 674 } 675 if (nd->nd_flag & ND_NFSV2) { 676 (void)nfsm_fhtom(NULL, nd, (u_int8_t *)fhp, 0, 0); 677 nfsrv_fillattr(nd, &nva); 678 } else if (nd->nd_flag & ND_NFSV3) { 679 (void)nfsm_fhtom(NULL, nd, (u_int8_t *)fhp, 0, 0); 680 nfsrv_postopattr(nd, 0, &nva); 681 nfsrv_postopattr(nd, dattr_ret, &dattr); 682 } 683 684 out: 685 NFSEXITCODE2(error, nd); 686 return (error); 687 } 688 689 /* 690 * nfs readlink service 691 */ 692 int 693 nfsrvd_readlink(struct nfsrv_descript *nd, __unused int isdgram, 694 vnode_t vp, __unused struct nfsexstuff *exp) 695 { 696 u_int32_t *tl; 697 struct mbuf *mp = NULL, *mpend = NULL; 698 int getret = 1, len; 699 struct nfsvattr nva; 700 struct thread *p = curthread; 701 uint16_t off; 702 703 if (nd->nd_repstat) { 704 nfsrv_postopattr(nd, getret, &nva); 705 goto out; 706 } 707 if (vp->v_type != VLNK) { 708 if (nd->nd_flag & ND_NFSV2) 709 nd->nd_repstat = ENXIO; 710 else 711 nd->nd_repstat = EINVAL; 712 } 713 if (nd->nd_repstat == 0) { 714 if ((nd->nd_flag & ND_EXTPG) != 0) 715 nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred, 716 nd->nd_maxextsiz, p, &mp, &mpend, &len); 717 else 718 nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred, 719 0, p, &mp, &mpend, &len); 720 } 721 if (nd->nd_flag & ND_NFSV3) 722 getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL); 723 vput(vp); 724 if (nd->nd_flag & ND_NFSV3) 725 nfsrv_postopattr(nd, getret, &nva); 726 if (nd->nd_repstat) 727 goto out; 728 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 729 *tl = txdr_unsigned(len); 730 if (mp != NULL) { 731 nd->nd_mb->m_next = mp; 732 nd->nd_mb = mpend; 733 if ((mpend->m_flags & M_EXTPG) != 0) { 734 nd->nd_bextpg = mpend->m_epg_npgs - 1; 735 nd->nd_bpos = (char *)(void *) 736 PHYS_TO_DMAP(mpend->m_epg_pa[nd->nd_bextpg]); 737 off = (nd->nd_bextpg == 0) ? mpend->m_epg_1st_off : 0; 738 nd->nd_bpos += off + mpend->m_epg_last_len; 739 nd->nd_bextpgsiz = PAGE_SIZE - mpend->m_epg_last_len - 740 off; 741 } else 742 nd->nd_bpos = mtod(mpend, char *) + mpend->m_len; 743 } 744 745 out: 746 NFSEXITCODE2(0, nd); 747 return (0); 748 } 749 750 /* 751 * nfs read service 752 */ 753 int 754 nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram, 755 vnode_t vp, struct nfsexstuff *exp) 756 { 757 u_int32_t *tl; 758 int error = 0, cnt, getret = 1, gotproxystateid, reqlen, eof = 0; 759 struct mbuf *m2, *m3; 760 struct nfsvattr nva; 761 off_t off = 0x0; 762 struct nfsstate st, *stp = &st; 763 struct nfslock lo, *lop = &lo; 764 nfsv4stateid_t stateid; 765 nfsquad_t clientid; 766 struct thread *p = curthread; 767 uint16_t poff; 768 769 if (nd->nd_repstat) { 770 nfsrv_postopattr(nd, getret, &nva); 771 goto out; 772 } 773 if (nd->nd_flag & ND_NFSV2) { 774 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 775 off = (off_t)fxdr_unsigned(u_int32_t, *tl++); 776 reqlen = fxdr_unsigned(int, *tl); 777 } else if (nd->nd_flag & ND_NFSV3) { 778 NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 779 off = fxdr_hyper(tl); 780 tl += 2; 781 reqlen = fxdr_unsigned(int, *tl); 782 } else { 783 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 3*NFSX_UNSIGNED); 784 reqlen = fxdr_unsigned(int, *(tl + 6)); 785 } 786 if (reqlen > NFS_SRVMAXDATA(nd)) { 787 reqlen = NFS_SRVMAXDATA(nd); 788 } else if (reqlen < 0) { 789 error = EBADRPC; 790 goto nfsmout; 791 } 792 gotproxystateid = 0; 793 if (nd->nd_flag & ND_NFSV4) { 794 stp->ls_flags = (NFSLCK_CHECK | NFSLCK_READACCESS); 795 lop->lo_flags = NFSLCK_READ; 796 stp->ls_ownerlen = 0; 797 stp->ls_op = NULL; 798 stp->ls_uid = nd->nd_cred->cr_uid; 799 stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 800 clientid.lval[0] = stp->ls_stateid.other[0] = *tl++; 801 clientid.lval[1] = stp->ls_stateid.other[1] = *tl++; 802 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 803 if ((nd->nd_flag & ND_NFSV41) != 0) 804 clientid.qval = nd->nd_clientid.qval; 805 else if (nd->nd_clientid.qval != clientid.qval) 806 printf("EEK1 multiple clids\n"); 807 } else { 808 if ((nd->nd_flag & ND_NFSV41) != 0) 809 printf("EEK! no clientid from session\n"); 810 nd->nd_flag |= ND_IMPLIEDCLID; 811 nd->nd_clientid.qval = clientid.qval; 812 } 813 stp->ls_stateid.other[2] = *tl++; 814 /* 815 * Don't allow the client to use a special stateid for a DS op. 816 */ 817 if ((nd->nd_flag & ND_DSSERVER) != 0 && 818 ((stp->ls_stateid.other[0] == 0x0 && 819 stp->ls_stateid.other[1] == 0x0 && 820 stp->ls_stateid.other[2] == 0x0) || 821 (stp->ls_stateid.other[0] == 0xffffffff && 822 stp->ls_stateid.other[1] == 0xffffffff && 823 stp->ls_stateid.other[2] == 0xffffffff) || 824 stp->ls_stateid.seqid != 0)) 825 nd->nd_repstat = NFSERR_BADSTATEID; 826 /* However, allow the proxy stateid. */ 827 if (stp->ls_stateid.seqid == 0xffffffff && 828 stp->ls_stateid.other[0] == 0x55555555 && 829 stp->ls_stateid.other[1] == 0x55555555 && 830 stp->ls_stateid.other[2] == 0x55555555) 831 gotproxystateid = 1; 832 off = fxdr_hyper(tl); 833 lop->lo_first = off; 834 tl += 2; 835 lop->lo_end = off + reqlen; 836 /* 837 * Paranoia, just in case it wraps around. 838 */ 839 if (lop->lo_end < off) 840 lop->lo_end = NFS64BITSSET; 841 } 842 if (vp->v_type != VREG) { 843 if (nd->nd_flag & ND_NFSV3) 844 nd->nd_repstat = EINVAL; 845 else 846 nd->nd_repstat = (vp->v_type == VDIR) ? EISDIR : 847 EINVAL; 848 } 849 getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL); 850 if (!nd->nd_repstat) 851 nd->nd_repstat = getret; 852 if (!nd->nd_repstat && 853 (nva.na_uid != nd->nd_cred->cr_uid || 854 NFSVNO_EXSTRICTACCESS(exp))) { 855 nd->nd_repstat = nfsvno_accchk(vp, VREAD, 856 nd->nd_cred, exp, p, 857 NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL); 858 if (nd->nd_repstat) 859 nd->nd_repstat = nfsvno_accchk(vp, VEXEC, 860 nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER, 861 NFSACCCHK_VPISLOCKED, NULL); 862 } 863 /* 864 * DS reads are marked by ND_DSSERVER or use the proxy special 865 * stateid. 866 */ 867 if (nd->nd_repstat == 0 && (nd->nd_flag & (ND_NFSV4 | ND_DSSERVER)) == 868 ND_NFSV4 && gotproxystateid == 0) 869 nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, 870 &stateid, exp, nd, p); 871 if (nd->nd_repstat) { 872 vput(vp); 873 if (nd->nd_flag & ND_NFSV3) 874 nfsrv_postopattr(nd, getret, &nva); 875 goto out; 876 } 877 if (off >= nva.na_size) { 878 cnt = 0; 879 eof = 1; 880 } else if (reqlen == 0) 881 cnt = 0; 882 else if ((off + reqlen) >= nva.na_size) { 883 cnt = nva.na_size - off; 884 eof = 1; 885 } else 886 cnt = reqlen; 887 m3 = NULL; 888 if (cnt > 0) { 889 /* 890 * If cnt > MCLBYTES and the reply will not be saved, use 891 * ext_pgs mbufs for TLS. 892 * For NFSv4.0, we do not know for sure if the reply will 893 * be saved, so do not use ext_pgs mbufs for NFSv4.0. 894 * Always use ext_pgs mbufs if ND_EXTPG is set. 895 */ 896 if ((nd->nd_flag & ND_EXTPG) != 0 || (cnt > MCLBYTES && 897 (nd->nd_flag & (ND_TLS | ND_SAVEREPLY)) == ND_TLS && 898 (nd->nd_flag & (ND_NFSV4 | ND_NFSV41)) != ND_NFSV4)) 899 nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred, 900 nd->nd_maxextsiz, p, &m3, &m2); 901 else 902 nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred, 903 0, p, &m3, &m2); 904 if (!(nd->nd_flag & ND_NFSV4)) { 905 getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL); 906 if (!nd->nd_repstat) 907 nd->nd_repstat = getret; 908 } 909 if (nd->nd_repstat) { 910 vput(vp); 911 if (m3) 912 m_freem(m3); 913 if (nd->nd_flag & ND_NFSV3) 914 nfsrv_postopattr(nd, getret, &nva); 915 goto out; 916 } 917 } 918 vput(vp); 919 if (nd->nd_flag & ND_NFSV2) { 920 nfsrv_fillattr(nd, &nva); 921 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 922 } else { 923 if (nd->nd_flag & ND_NFSV3) { 924 nfsrv_postopattr(nd, getret, &nva); 925 NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 926 *tl++ = txdr_unsigned(cnt); 927 } else 928 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 929 if (eof) 930 *tl++ = newnfs_true; 931 else 932 *tl++ = newnfs_false; 933 } 934 *tl = txdr_unsigned(cnt); 935 if (m3) { 936 nd->nd_mb->m_next = m3; 937 nd->nd_mb = m2; 938 if ((m2->m_flags & M_EXTPG) != 0) { 939 nd->nd_flag |= ND_EXTPG; 940 nd->nd_bextpg = m2->m_epg_npgs - 1; 941 nd->nd_bpos = (char *)(void *) 942 PHYS_TO_DMAP(m2->m_epg_pa[nd->nd_bextpg]); 943 poff = (nd->nd_bextpg == 0) ? m2->m_epg_1st_off : 0; 944 nd->nd_bpos += poff + m2->m_epg_last_len; 945 nd->nd_bextpgsiz = PAGE_SIZE - m2->m_epg_last_len - 946 poff; 947 } else 948 nd->nd_bpos = mtod(m2, char *) + m2->m_len; 949 } 950 951 out: 952 NFSEXITCODE2(0, nd); 953 return (0); 954 nfsmout: 955 vput(vp); 956 NFSEXITCODE2(error, nd); 957 return (error); 958 } 959 960 /* 961 * nfs write service 962 */ 963 int 964 nfsrvd_write(struct nfsrv_descript *nd, __unused int isdgram, 965 vnode_t vp, struct nfsexstuff *exp) 966 { 967 u_int32_t *tl; 968 struct nfsvattr nva, forat; 969 int aftat_ret = 1, retlen, len, error = 0, forat_ret = 1; 970 int gotproxystateid, stable = NFSWRITE_FILESYNC; 971 off_t off; 972 struct nfsstate st, *stp = &st; 973 struct nfslock lo, *lop = &lo; 974 nfsv4stateid_t stateid; 975 nfsquad_t clientid; 976 nfsattrbit_t attrbits; 977 struct thread *p = curthread; 978 979 if (nd->nd_repstat) { 980 nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva); 981 goto out; 982 } 983 gotproxystateid = 0; 984 if (nd->nd_flag & ND_NFSV2) { 985 NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 986 off = (off_t)fxdr_unsigned(u_int32_t, *++tl); 987 tl += 2; 988 retlen = len = fxdr_unsigned(int32_t, *tl); 989 } else if (nd->nd_flag & ND_NFSV3) { 990 NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 991 off = fxdr_hyper(tl); 992 tl += 3; 993 stable = fxdr_unsigned(int, *tl++); 994 retlen = len = fxdr_unsigned(int32_t, *tl); 995 } else { 996 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 4 * NFSX_UNSIGNED); 997 stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS); 998 lop->lo_flags = NFSLCK_WRITE; 999 stp->ls_ownerlen = 0; 1000 stp->ls_op = NULL; 1001 stp->ls_uid = nd->nd_cred->cr_uid; 1002 stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 1003 clientid.lval[0] = stp->ls_stateid.other[0] = *tl++; 1004 clientid.lval[1] = stp->ls_stateid.other[1] = *tl++; 1005 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 1006 if ((nd->nd_flag & ND_NFSV41) != 0) 1007 clientid.qval = nd->nd_clientid.qval; 1008 else if (nd->nd_clientid.qval != clientid.qval) 1009 printf("EEK2 multiple clids\n"); 1010 } else { 1011 if ((nd->nd_flag & ND_NFSV41) != 0) 1012 printf("EEK! no clientid from session\n"); 1013 nd->nd_flag |= ND_IMPLIEDCLID; 1014 nd->nd_clientid.qval = clientid.qval; 1015 } 1016 stp->ls_stateid.other[2] = *tl++; 1017 /* 1018 * Don't allow the client to use a special stateid for a DS op. 1019 */ 1020 if ((nd->nd_flag & ND_DSSERVER) != 0 && 1021 ((stp->ls_stateid.other[0] == 0x0 && 1022 stp->ls_stateid.other[1] == 0x0 && 1023 stp->ls_stateid.other[2] == 0x0) || 1024 (stp->ls_stateid.other[0] == 0xffffffff && 1025 stp->ls_stateid.other[1] == 0xffffffff && 1026 stp->ls_stateid.other[2] == 0xffffffff) || 1027 stp->ls_stateid.seqid != 0)) 1028 nd->nd_repstat = NFSERR_BADSTATEID; 1029 /* However, allow the proxy stateid. */ 1030 if (stp->ls_stateid.seqid == 0xffffffff && 1031 stp->ls_stateid.other[0] == 0x55555555 && 1032 stp->ls_stateid.other[1] == 0x55555555 && 1033 stp->ls_stateid.other[2] == 0x55555555) 1034 gotproxystateid = 1; 1035 off = fxdr_hyper(tl); 1036 lop->lo_first = off; 1037 tl += 2; 1038 stable = fxdr_unsigned(int, *tl++); 1039 retlen = len = fxdr_unsigned(int32_t, *tl); 1040 lop->lo_end = off + len; 1041 /* 1042 * Paranoia, just in case it wraps around, which shouldn't 1043 * ever happen anyhow. 1044 */ 1045 if (lop->lo_end < lop->lo_first) 1046 lop->lo_end = NFS64BITSSET; 1047 } 1048 1049 if (retlen > nfs_srvmaxio || retlen < 0) 1050 nd->nd_repstat = EIO; 1051 if (vp->v_type != VREG && !nd->nd_repstat) { 1052 if (nd->nd_flag & ND_NFSV3) 1053 nd->nd_repstat = EINVAL; 1054 else 1055 nd->nd_repstat = (vp->v_type == VDIR) ? EISDIR : 1056 EINVAL; 1057 } 1058 NFSZERO_ATTRBIT(&attrbits); 1059 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER); 1060 forat_ret = nfsvno_getattr(vp, &forat, nd, p, 1, &attrbits); 1061 if (!nd->nd_repstat) 1062 nd->nd_repstat = forat_ret; 1063 if (!nd->nd_repstat && 1064 (forat.na_uid != nd->nd_cred->cr_uid || 1065 NFSVNO_EXSTRICTACCESS(exp))) 1066 nd->nd_repstat = nfsvno_accchk(vp, VWRITE, 1067 nd->nd_cred, exp, p, 1068 NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL); 1069 /* 1070 * DS reads are marked by ND_DSSERVER or use the proxy special 1071 * stateid. 1072 */ 1073 if (nd->nd_repstat == 0 && (nd->nd_flag & (ND_NFSV4 | ND_DSSERVER)) == 1074 ND_NFSV4 && gotproxystateid == 0) 1075 nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, 1076 &stateid, exp, nd, p); 1077 if (nd->nd_repstat) { 1078 vput(vp); 1079 if (nd->nd_flag & ND_NFSV3) 1080 nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva); 1081 goto out; 1082 } 1083 1084 /* 1085 * For NFS Version 2, it is not obvious what a write of zero length 1086 * should do, but I might as well be consistent with Version 3, 1087 * which is to return ok so long as there are no permission problems. 1088 */ 1089 if (retlen > 0) { 1090 nd->nd_repstat = nfsvno_write(vp, off, retlen, &stable, 1091 nd->nd_md, nd->nd_dpos, nd->nd_cred, p); 1092 error = nfsm_advance(nd, NFSM_RNDUP(retlen), -1); 1093 if (error) 1094 goto nfsmout; 1095 } 1096 if (nd->nd_flag & ND_NFSV4) 1097 aftat_ret = 0; 1098 else 1099 aftat_ret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL); 1100 vput(vp); 1101 if (!nd->nd_repstat) 1102 nd->nd_repstat = aftat_ret; 1103 if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) { 1104 if (nd->nd_flag & ND_NFSV3) 1105 nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva); 1106 if (nd->nd_repstat) 1107 goto out; 1108 NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 1109 *tl++ = txdr_unsigned(retlen); 1110 /* 1111 * If nfs_async is set, then pretend the write was FILESYNC. 1112 * Warning: Doing this violates RFC1813 and runs a risk 1113 * of data written by a client being lost when the server 1114 * crashes/reboots. 1115 */ 1116 if (stable == NFSWRITE_UNSTABLE && nfs_async == 0) 1117 *tl++ = txdr_unsigned(stable); 1118 else 1119 *tl++ = txdr_unsigned(NFSWRITE_FILESYNC); 1120 /* 1121 * Actually, there is no need to txdr these fields, 1122 * but it may make the values more human readable, 1123 * for debugging purposes. 1124 */ 1125 *tl++ = txdr_unsigned(nfsboottime.tv_sec); 1126 *tl = txdr_unsigned(nfsboottime.tv_usec); 1127 } else if (!nd->nd_repstat) 1128 nfsrv_fillattr(nd, &nva); 1129 1130 out: 1131 NFSEXITCODE2(0, nd); 1132 return (0); 1133 nfsmout: 1134 vput(vp); 1135 NFSEXITCODE2(error, nd); 1136 return (error); 1137 } 1138 1139 /* 1140 * nfs create service (creates regular files for V2 and V3. Spec. files for V2.) 1141 * now does a truncate to 0 length via. setattr if it already exists 1142 * The core creation routine has been extracted out into nfsrv_creatsub(), 1143 * so it can also be used by nfsrv_open() for V4. 1144 */ 1145 int 1146 nfsrvd_create(struct nfsrv_descript *nd, __unused int isdgram, 1147 vnode_t dp, struct nfsexstuff *exp) 1148 { 1149 struct nfsvattr nva, dirfor, diraft; 1150 struct nfsv2_sattr *sp; 1151 struct nameidata named; 1152 u_int32_t *tl; 1153 int error = 0, tsize, dirfor_ret = 1, diraft_ret = 1; 1154 int how = NFSCREATE_UNCHECKED, exclusive_flag = 0; 1155 NFSDEV_T rdev = 0; 1156 vnode_t vp = NULL, dirp = NULL; 1157 fhandle_t fh; 1158 char *bufp; 1159 u_long *hashp; 1160 __enum_uint8(vtype) vtyp; 1161 int32_t cverf[2], tverf[2] = { 0, 0 }; 1162 struct thread *p = curthread; 1163 1164 if (nd->nd_repstat) { 1165 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1166 goto out; 1167 } 1168 NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, 1169 LOCKPARENT | LOCKLEAF | NOCACHE); 1170 nfsvno_setpathbuf(&named, &bufp, &hashp); 1171 error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 1172 if (error) 1173 goto nfsmout; 1174 if (!nd->nd_repstat) { 1175 NFSVNO_ATTRINIT(&nva); 1176 if (nd->nd_flag & ND_NFSV2) { 1177 NFSM_DISSECT(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1178 vtyp = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode)); 1179 if (vtyp == VNON) 1180 vtyp = VREG; 1181 NFSVNO_SETATTRVAL(&nva, type, vtyp); 1182 NFSVNO_SETATTRVAL(&nva, mode, 1183 nfstov_mode(sp->sa_mode)); 1184 switch (nva.na_type) { 1185 case VREG: 1186 tsize = fxdr_unsigned(int32_t, sp->sa_size); 1187 if (tsize != -1) 1188 NFSVNO_SETATTRVAL(&nva, size, 1189 (u_quad_t)tsize); 1190 break; 1191 case VCHR: 1192 case VBLK: 1193 case VFIFO: 1194 rdev = fxdr_unsigned(NFSDEV_T, sp->sa_size); 1195 break; 1196 default: 1197 break; 1198 } 1199 } else { 1200 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 1201 how = fxdr_unsigned(int, *tl); 1202 switch (how) { 1203 case NFSCREATE_GUARDED: 1204 case NFSCREATE_UNCHECKED: 1205 error = nfsrv_sattr(nd, NULL, &nva, NULL, NULL, p); 1206 if (error) 1207 goto nfsmout; 1208 break; 1209 case NFSCREATE_EXCLUSIVE: 1210 NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF); 1211 cverf[0] = *tl++; 1212 cverf[1] = *tl; 1213 exclusive_flag = 1; 1214 break; 1215 } 1216 NFSVNO_SETATTRVAL(&nva, type, VREG); 1217 } 1218 } 1219 if (nd->nd_repstat) { 1220 nfsvno_relpathbuf(&named); 1221 if (nd->nd_flag & ND_NFSV3) { 1222 dirfor_ret = nfsvno_getattr(dp, &dirfor, nd, p, 1, 1223 NULL); 1224 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, 1225 &diraft); 1226 } 1227 vput(dp); 1228 goto out; 1229 } 1230 1231 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, &dirp); 1232 if (dirp) { 1233 if (nd->nd_flag & ND_NFSV2) { 1234 vrele(dirp); 1235 dirp = NULL; 1236 } else { 1237 dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, 1238 NULL); 1239 } 1240 } 1241 if (nd->nd_repstat) { 1242 if (nd->nd_flag & ND_NFSV3) 1243 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, 1244 &diraft); 1245 if (dirp) 1246 vrele(dirp); 1247 goto out; 1248 } 1249 1250 if (!(nd->nd_flag & ND_NFSV2)) { 1251 switch (how) { 1252 case NFSCREATE_GUARDED: 1253 if (named.ni_vp) 1254 nd->nd_repstat = EEXIST; 1255 break; 1256 case NFSCREATE_UNCHECKED: 1257 break; 1258 case NFSCREATE_EXCLUSIVE: 1259 if (named.ni_vp == NULL) 1260 NFSVNO_SETATTRVAL(&nva, mode, 0); 1261 break; 1262 } 1263 } 1264 1265 /* 1266 * Iff doesn't exist, create it 1267 * otherwise just truncate to 0 length 1268 * should I set the mode too ? 1269 */ 1270 nd->nd_repstat = nfsvno_createsub(nd, &named, &vp, &nva, 1271 &exclusive_flag, cverf, rdev, exp); 1272 1273 if (!nd->nd_repstat) { 1274 nd->nd_repstat = nfsvno_getfh(vp, &fh, p); 1275 if (!nd->nd_repstat) 1276 nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, 1277 NULL); 1278 vput(vp); 1279 if (!nd->nd_repstat) { 1280 tverf[0] = nva.na_atime.tv_sec; 1281 tverf[1] = nva.na_atime.tv_nsec; 1282 } 1283 } 1284 if (nd->nd_flag & ND_NFSV2) { 1285 if (!nd->nd_repstat) { 1286 (void)nfsm_fhtom(NULL, nd, (u_int8_t *)&fh, 0, 0); 1287 nfsrv_fillattr(nd, &nva); 1288 } 1289 } else { 1290 if (exclusive_flag && !nd->nd_repstat && (cverf[0] != tverf[0] 1291 || cverf[1] != tverf[1])) 1292 nd->nd_repstat = EEXIST; 1293 diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL); 1294 vrele(dirp); 1295 if (!nd->nd_repstat) { 1296 (void)nfsm_fhtom(NULL, nd, (u_int8_t *)&fh, 0, 1); 1297 nfsrv_postopattr(nd, 0, &nva); 1298 } 1299 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1300 } 1301 1302 out: 1303 NFSEXITCODE2(0, nd); 1304 return (0); 1305 nfsmout: 1306 vput(dp); 1307 nfsvno_relpathbuf(&named); 1308 NFSEXITCODE2(error, nd); 1309 return (error); 1310 } 1311 1312 /* 1313 * nfs v3 mknod service (and v4 create) 1314 */ 1315 int 1316 nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram, 1317 vnode_t dp, vnode_t *vpp, fhandle_t *fhp, struct nfsexstuff *exp) 1318 { 1319 struct nfsvattr nva, dirfor, diraft; 1320 u_int32_t *tl; 1321 struct nameidata named; 1322 int error = 0, dirfor_ret = 1, diraft_ret = 1, pathlen; 1323 u_int32_t major, minor; 1324 __enum_uint8(vtype) vtyp = VNON; 1325 nfstype nfs4type = NFNON; 1326 vnode_t vp, dirp = NULL; 1327 nfsattrbit_t attrbits; 1328 char *bufp = NULL, *pathcp = NULL; 1329 u_long *hashp, cnflags; 1330 NFSACL_T *aclp = NULL; 1331 struct thread *p = curthread; 1332 1333 NFSVNO_ATTRINIT(&nva); 1334 cnflags = LOCKPARENT; 1335 if (nd->nd_repstat) { 1336 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1337 goto out; 1338 } 1339 #ifdef NFS4_ACL_EXTATTR_NAME 1340 aclp = acl_alloc(M_WAITOK); 1341 aclp->acl_cnt = 0; 1342 #endif 1343 1344 /* 1345 * For V4, the creation stuff is here, Yuck! 1346 */ 1347 if (nd->nd_flag & ND_NFSV4) { 1348 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 1349 vtyp = nfsv34tov_type(*tl); 1350 nfs4type = fxdr_unsigned(nfstype, *tl); 1351 switch (nfs4type) { 1352 case NFLNK: 1353 error = nfsvno_getsymlink(nd, &nva, p, &pathcp, 1354 &pathlen); 1355 if (error) 1356 goto nfsmout; 1357 break; 1358 case NFCHR: 1359 case NFBLK: 1360 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1361 major = fxdr_unsigned(u_int32_t, *tl++); 1362 minor = fxdr_unsigned(u_int32_t, *tl); 1363 nva.na_rdev = NFSMAKEDEV(major, minor); 1364 break; 1365 case NFSOCK: 1366 case NFFIFO: 1367 break; 1368 case NFDIR: 1369 cnflags = LOCKPARENT; 1370 break; 1371 default: 1372 nd->nd_repstat = NFSERR_BADTYPE; 1373 vrele(dp); 1374 #ifdef NFS4_ACL_EXTATTR_NAME 1375 acl_free(aclp); 1376 #endif 1377 goto out; 1378 } 1379 } 1380 NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, cnflags | NOCACHE); 1381 nfsvno_setpathbuf(&named, &bufp, &hashp); 1382 error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 1383 if (error) 1384 goto nfsmout; 1385 if (!nd->nd_repstat) { 1386 if (nd->nd_flag & ND_NFSV3) { 1387 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 1388 vtyp = nfsv34tov_type(*tl); 1389 } 1390 error = nfsrv_sattr(nd, NULL, &nva, &attrbits, aclp, p); 1391 if (error) 1392 goto nfsmout; 1393 nva.na_type = vtyp; 1394 if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV3) && 1395 (vtyp == VCHR || vtyp == VBLK)) { 1396 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1397 major = fxdr_unsigned(u_int32_t, *tl++); 1398 minor = fxdr_unsigned(u_int32_t, *tl); 1399 nva.na_rdev = NFSMAKEDEV(major, minor); 1400 } 1401 } 1402 1403 dirfor_ret = nfsvno_getattr(dp, &dirfor, nd, p, 0, NULL); 1404 if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) { 1405 if (!dirfor_ret && NFSVNO_ISSETGID(&nva) && 1406 dirfor.na_gid == nva.na_gid) 1407 NFSVNO_UNSET(&nva, gid); 1408 nd->nd_repstat = nfsrv_checkuidgid(nd, &nva); 1409 } 1410 if (nd->nd_repstat) { 1411 vrele(dp); 1412 #ifdef NFS4_ACL_EXTATTR_NAME 1413 acl_free(aclp); 1414 #endif 1415 nfsvno_relpathbuf(&named); 1416 if (pathcp) 1417 free(pathcp, M_TEMP); 1418 if (nd->nd_flag & ND_NFSV3) 1419 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, 1420 &diraft); 1421 goto out; 1422 } 1423 1424 /* 1425 * Yuck! For V4, mkdir and link are here and some V4 clients don't fill 1426 * in va_mode, so we'll have to set a default here. 1427 */ 1428 if (NFSVNO_NOTSETMODE(&nva)) { 1429 if (vtyp == VLNK) 1430 nva.na_mode = 0755; 1431 else 1432 nva.na_mode = 0400; 1433 } 1434 1435 if (vtyp == VDIR) 1436 named.ni_cnd.cn_flags |= WILLBEDIR; 1437 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, &dirp); 1438 if (nd->nd_repstat) { 1439 if (dirp) { 1440 if (nd->nd_flag & ND_NFSV3) 1441 dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, 1442 p, 0, NULL); 1443 vrele(dirp); 1444 } 1445 #ifdef NFS4_ACL_EXTATTR_NAME 1446 acl_free(aclp); 1447 #endif 1448 if (nd->nd_flag & ND_NFSV3) 1449 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, 1450 &diraft); 1451 goto out; 1452 } 1453 if (dirp) 1454 dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, NULL); 1455 1456 if ((nd->nd_flag & ND_NFSV4) && (vtyp == VDIR || vtyp == VLNK)) { 1457 if (vtyp == VDIR) { 1458 nfsrvd_mkdirsub(nd, &named, &nva, fhp, vpp, dirp, 1459 &dirfor, &diraft, &diraft_ret, &attrbits, aclp, p, 1460 exp); 1461 #ifdef NFS4_ACL_EXTATTR_NAME 1462 acl_free(aclp); 1463 #endif 1464 goto out; 1465 } else if (vtyp == VLNK) { 1466 nfsrvd_symlinksub(nd, &named, &nva, fhp, vpp, dirp, 1467 &dirfor, &diraft, &diraft_ret, &attrbits, 1468 aclp, p, exp, pathcp, pathlen); 1469 #ifdef NFS4_ACL_EXTATTR_NAME 1470 acl_free(aclp); 1471 #endif 1472 free(pathcp, M_TEMP); 1473 goto out; 1474 } 1475 } 1476 1477 nd->nd_repstat = nfsvno_mknod(&named, &nva, nd->nd_cred, p); 1478 if (!nd->nd_repstat) { 1479 vp = named.ni_vp; 1480 nfsrv_fixattr(nd, vp, &nva, aclp, p, &attrbits, exp); 1481 nd->nd_repstat = nfsvno_getfh(vp, fhp, p); 1482 if ((nd->nd_flag & ND_NFSV3) && !nd->nd_repstat) 1483 nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, 1484 NULL); 1485 if (vpp != NULL && nd->nd_repstat == 0) { 1486 NFSVOPUNLOCK(vp); 1487 *vpp = vp; 1488 } else 1489 vput(vp); 1490 } 1491 1492 diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL); 1493 vrele(dirp); 1494 if (!nd->nd_repstat) { 1495 if (nd->nd_flag & ND_NFSV3) { 1496 (void)nfsm_fhtom(NULL, nd, (u_int8_t *)fhp, 0, 1); 1497 nfsrv_postopattr(nd, 0, &nva); 1498 } else { 1499 NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 1500 *tl++ = newnfs_false; 1501 txdr_hyper(dirfor.na_filerev, tl); 1502 tl += 2; 1503 txdr_hyper(diraft.na_filerev, tl); 1504 (void) nfsrv_putattrbit(nd, &attrbits); 1505 } 1506 } 1507 if (nd->nd_flag & ND_NFSV3) 1508 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1509 #ifdef NFS4_ACL_EXTATTR_NAME 1510 acl_free(aclp); 1511 #endif 1512 1513 out: 1514 NFSEXITCODE2(0, nd); 1515 return (0); 1516 nfsmout: 1517 vrele(dp); 1518 #ifdef NFS4_ACL_EXTATTR_NAME 1519 acl_free(aclp); 1520 #endif 1521 if (bufp) 1522 nfsvno_relpathbuf(&named); 1523 if (pathcp) 1524 free(pathcp, M_TEMP); 1525 1526 NFSEXITCODE2(error, nd); 1527 return (error); 1528 } 1529 1530 /* 1531 * nfs remove service 1532 */ 1533 int 1534 nfsrvd_remove(struct nfsrv_descript *nd, __unused int isdgram, 1535 vnode_t dp, struct nfsexstuff *exp) 1536 { 1537 struct nameidata named; 1538 u_int32_t *tl; 1539 int error = 0, dirfor_ret = 1, diraft_ret = 1; 1540 vnode_t dirp = NULL; 1541 struct nfsvattr dirfor, diraft; 1542 char *bufp; 1543 u_long *hashp; 1544 struct thread *p = curthread; 1545 1546 if (nd->nd_repstat) { 1547 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1548 goto out; 1549 } 1550 NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, DELETE, 1551 LOCKPARENT | LOCKLEAF); 1552 nfsvno_setpathbuf(&named, &bufp, &hashp); 1553 error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 1554 if (error) { 1555 vput(dp); 1556 nfsvno_relpathbuf(&named); 1557 goto out; 1558 } 1559 if (!nd->nd_repstat) { 1560 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, &dirp); 1561 } else { 1562 vput(dp); 1563 nfsvno_relpathbuf(&named); 1564 } 1565 if (dirp) { 1566 if (!(nd->nd_flag & ND_NFSV2)) { 1567 dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, 1568 NULL); 1569 } else { 1570 vrele(dirp); 1571 dirp = NULL; 1572 } 1573 } 1574 if (!nd->nd_repstat) { 1575 if (nd->nd_flag & ND_NFSV4) { 1576 if (named.ni_vp->v_type == VDIR) 1577 nd->nd_repstat = nfsvno_rmdirsub(&named, 1, 1578 nd->nd_cred, p, exp); 1579 else 1580 nd->nd_repstat = nfsvno_removesub(&named, 1, 1581 nd->nd_cred, p, exp); 1582 } else if (nd->nd_procnum == NFSPROC_RMDIR) { 1583 nd->nd_repstat = nfsvno_rmdirsub(&named, 0, 1584 nd->nd_cred, p, exp); 1585 } else { 1586 nd->nd_repstat = nfsvno_removesub(&named, 0, 1587 nd->nd_cred, p, exp); 1588 } 1589 } 1590 if (!(nd->nd_flag & ND_NFSV2)) { 1591 if (dirp) { 1592 diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0, 1593 NULL); 1594 vrele(dirp); 1595 } 1596 if (nd->nd_flag & ND_NFSV3) { 1597 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, 1598 &diraft); 1599 } else if (!nd->nd_repstat) { 1600 NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 1601 *tl++ = newnfs_false; 1602 txdr_hyper(dirfor.na_filerev, tl); 1603 tl += 2; 1604 txdr_hyper(diraft.na_filerev, tl); 1605 } 1606 } 1607 1608 out: 1609 NFSEXITCODE2(error, nd); 1610 return (error); 1611 } 1612 1613 /* 1614 * nfs rename service 1615 */ 1616 int 1617 nfsrvd_rename(struct nfsrv_descript *nd, int isdgram, 1618 vnode_t dp, vnode_t todp, struct nfsexstuff *exp, struct nfsexstuff *toexp) 1619 { 1620 u_int32_t *tl; 1621 int error = 0, fdirfor_ret = 1, fdiraft_ret = 1; 1622 int tdirfor_ret = 1, tdiraft_ret = 1; 1623 struct nameidata fromnd, tond; 1624 vnode_t fdirp = NULL, tdirp = NULL, tdp = NULL; 1625 struct nfsvattr fdirfor, fdiraft, tdirfor, tdiraft; 1626 struct nfsexstuff tnes; 1627 struct nfsrvfh tfh; 1628 char *bufp, *tbufp = NULL; 1629 u_long *hashp; 1630 fhandle_t fh; 1631 struct thread *p = curthread; 1632 1633 if (nd->nd_repstat) { 1634 nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 1635 nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 1636 goto out; 1637 } 1638 if (!(nd->nd_flag & ND_NFSV2)) 1639 fdirfor_ret = nfsvno_getattr(dp, &fdirfor, nd, p, 1, NULL); 1640 tond.ni_cnd.cn_nameiop = 0; 1641 tond.ni_startdir = NULL; 1642 NFSNAMEICNDSET(&fromnd.ni_cnd, nd->nd_cred, DELETE, WANTPARENT); 1643 nfsvno_setpathbuf(&fromnd, &bufp, &hashp); 1644 error = nfsrv_parsename(nd, bufp, hashp, &fromnd.ni_pathlen); 1645 if (error) { 1646 vput(dp); 1647 if (todp) 1648 vrele(todp); 1649 nfsvno_relpathbuf(&fromnd); 1650 goto out; 1651 } 1652 /* 1653 * Unlock dp in this code section, so it is unlocked before 1654 * tdp gets locked. This avoids a potential LOR if tdp is the 1655 * parent directory of dp. 1656 */ 1657 if (nd->nd_flag & ND_NFSV4) { 1658 tdp = todp; 1659 tnes = *toexp; 1660 if (dp != tdp) { 1661 NFSVOPUNLOCK(dp); 1662 /* Might lock tdp. */ 1663 tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, p, 0, 1664 NULL); 1665 } else { 1666 tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, p, 1, 1667 NULL); 1668 NFSVOPUNLOCK(dp); 1669 } 1670 } else { 1671 tfh.nfsrvfh_len = 0; 1672 error = nfsrv_mtofh(nd, &tfh); 1673 if (error == 0) 1674 error = nfsvno_getfh(dp, &fh, p); 1675 if (error) { 1676 vput(dp); 1677 /* todp is always NULL except NFSv4 */ 1678 nfsvno_relpathbuf(&fromnd); 1679 goto out; 1680 } 1681 1682 /* If this is the same file handle, just VREF() the vnode. */ 1683 if (tfh.nfsrvfh_len == NFSX_MYFH && 1684 !NFSBCMP(tfh.nfsrvfh_data, &fh, NFSX_MYFH)) { 1685 VREF(dp); 1686 tdp = dp; 1687 tnes = *exp; 1688 tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, p, 1, 1689 NULL); 1690 NFSVOPUNLOCK(dp); 1691 } else { 1692 NFSVOPUNLOCK(dp); 1693 nd->nd_cred->cr_uid = nd->nd_saveduid; 1694 nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, NULL, 1695 0, -1); /* Locks tdp. */ 1696 if (tdp) { 1697 tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, 1698 p, 1, NULL); 1699 NFSVOPUNLOCK(tdp); 1700 } 1701 } 1702 } 1703 NFSNAMEICNDSET(&tond.ni_cnd, nd->nd_cred, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE); 1704 nfsvno_setpathbuf(&tond, &tbufp, &hashp); 1705 if (!nd->nd_repstat) { 1706 error = nfsrv_parsename(nd, tbufp, hashp, &tond.ni_pathlen); 1707 if (error) { 1708 if (tdp) 1709 vrele(tdp); 1710 vrele(dp); 1711 nfsvno_relpathbuf(&fromnd); 1712 nfsvno_relpathbuf(&tond); 1713 goto out; 1714 } 1715 } 1716 if (nd->nd_repstat) { 1717 if (nd->nd_flag & ND_NFSV3) { 1718 nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, 1719 &fdiraft); 1720 nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, 1721 &tdiraft); 1722 } 1723 if (tdp) 1724 vrele(tdp); 1725 vrele(dp); 1726 nfsvno_relpathbuf(&fromnd); 1727 nfsvno_relpathbuf(&tond); 1728 goto out; 1729 } 1730 1731 /* 1732 * Done parsing, now down to business. 1733 */ 1734 nd->nd_repstat = nfsvno_namei(nd, &fromnd, dp, 0, exp, &fdirp); 1735 if (nd->nd_repstat) { 1736 if (nd->nd_flag & ND_NFSV3) { 1737 nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, 1738 &fdiraft); 1739 nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, 1740 &tdiraft); 1741 } 1742 if (fdirp) 1743 vrele(fdirp); 1744 if (tdp) 1745 vrele(tdp); 1746 nfsvno_relpathbuf(&tond); 1747 goto out; 1748 } 1749 if (fromnd.ni_vp->v_type == VDIR) 1750 tond.ni_cnd.cn_flags |= WILLBEDIR; 1751 nd->nd_repstat = nfsvno_namei(nd, &tond, tdp, 0, &tnes, &tdirp); 1752 nd->nd_repstat = nfsvno_rename(&fromnd, &tond, nd->nd_repstat, 1753 nd->nd_flag, nd->nd_cred, p); 1754 if (fdirp) 1755 fdiraft_ret = nfsvno_getattr(fdirp, &fdiraft, nd, p, 0, NULL); 1756 if (tdirp) 1757 tdiraft_ret = nfsvno_getattr(tdirp, &tdiraft, nd, p, 0, NULL); 1758 if (fdirp) 1759 vrele(fdirp); 1760 if (tdirp) 1761 vrele(tdirp); 1762 if (nd->nd_flag & ND_NFSV3) { 1763 nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 1764 nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 1765 } else if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) { 1766 NFSM_BUILD(tl, u_int32_t *, 10 * NFSX_UNSIGNED); 1767 *tl++ = newnfs_false; 1768 txdr_hyper(fdirfor.na_filerev, tl); 1769 tl += 2; 1770 txdr_hyper(fdiraft.na_filerev, tl); 1771 tl += 2; 1772 *tl++ = newnfs_false; 1773 txdr_hyper(tdirfor.na_filerev, tl); 1774 tl += 2; 1775 txdr_hyper(tdiraft.na_filerev, tl); 1776 } 1777 1778 out: 1779 NFSEXITCODE2(error, nd); 1780 return (error); 1781 } 1782 1783 /* 1784 * nfs link service 1785 */ 1786 int 1787 nfsrvd_link(struct nfsrv_descript *nd, int isdgram, 1788 vnode_t vp, vnode_t tovp, struct nfsexstuff *exp, struct nfsexstuff *toexp) 1789 { 1790 struct nameidata named; 1791 u_int32_t *tl; 1792 int error = 0, dirfor_ret = 1, diraft_ret = 1, getret = 1; 1793 vnode_t dirp = NULL, dp = NULL; 1794 struct nfsvattr dirfor, diraft, at; 1795 struct nfsexstuff tnes; 1796 struct nfsrvfh dfh; 1797 char *bufp; 1798 u_long *hashp; 1799 struct thread *p = curthread; 1800 1801 if (nd->nd_repstat) { 1802 nfsrv_postopattr(nd, getret, &at); 1803 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1804 goto out; 1805 } 1806 NFSVOPUNLOCK(vp); 1807 if (vp->v_type == VDIR) { 1808 if (nd->nd_flag & ND_NFSV4) 1809 nd->nd_repstat = NFSERR_ISDIR; 1810 else 1811 nd->nd_repstat = NFSERR_INVAL; 1812 if (tovp) 1813 vrele(tovp); 1814 } 1815 if (!nd->nd_repstat) { 1816 if (nd->nd_flag & ND_NFSV4) { 1817 dp = tovp; 1818 tnes = *toexp; 1819 } else { 1820 error = nfsrv_mtofh(nd, &dfh); 1821 if (error) { 1822 vrele(vp); 1823 /* tovp is always NULL unless NFSv4 */ 1824 goto out; 1825 } 1826 nfsd_fhtovp(nd, &dfh, LK_EXCLUSIVE, &dp, &tnes, NULL, 1827 0, -1); 1828 if (dp) 1829 NFSVOPUNLOCK(dp); 1830 } 1831 } 1832 NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, LOCKPARENT | NOCACHE); 1833 if (!nd->nd_repstat) { 1834 nfsvno_setpathbuf(&named, &bufp, &hashp); 1835 error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 1836 if (error) { 1837 vrele(vp); 1838 if (dp) 1839 vrele(dp); 1840 nfsvno_relpathbuf(&named); 1841 goto out; 1842 } 1843 if (!nd->nd_repstat) { 1844 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, &tnes, 1845 &dirp); 1846 } else { 1847 if (dp) 1848 vrele(dp); 1849 nfsvno_relpathbuf(&named); 1850 } 1851 } 1852 if (dirp) { 1853 if (nd->nd_flag & ND_NFSV2) { 1854 vrele(dirp); 1855 dirp = NULL; 1856 } else { 1857 dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, 1858 NULL); 1859 } 1860 } 1861 if (!nd->nd_repstat) 1862 nd->nd_repstat = nfsvno_link(&named, vp, nd->nd_cred, p, exp); 1863 if (nd->nd_flag & ND_NFSV3) 1864 getret = nfsvno_getattr(vp, &at, nd, p, 0, NULL); 1865 if (dirp) { 1866 diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL); 1867 vrele(dirp); 1868 } 1869 vrele(vp); 1870 if (nd->nd_flag & ND_NFSV3) { 1871 nfsrv_postopattr(nd, getret, &at); 1872 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1873 } else if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) { 1874 NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 1875 *tl++ = newnfs_false; 1876 txdr_hyper(dirfor.na_filerev, tl); 1877 tl += 2; 1878 txdr_hyper(diraft.na_filerev, tl); 1879 } 1880 1881 out: 1882 NFSEXITCODE2(error, nd); 1883 return (error); 1884 } 1885 1886 /* 1887 * nfs symbolic link service 1888 */ 1889 int 1890 nfsrvd_symlink(struct nfsrv_descript *nd, __unused int isdgram, 1891 vnode_t dp, vnode_t *vpp, fhandle_t *fhp, struct nfsexstuff *exp) 1892 { 1893 struct nfsvattr nva, dirfor, diraft; 1894 struct nameidata named; 1895 int error = 0, dirfor_ret = 1, diraft_ret = 1, pathlen; 1896 vnode_t dirp = NULL; 1897 char *bufp, *pathcp = NULL; 1898 u_long *hashp; 1899 struct thread *p = curthread; 1900 1901 if (nd->nd_repstat) { 1902 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1903 goto out; 1904 } 1905 if (vpp) 1906 *vpp = NULL; 1907 NFSVNO_ATTRINIT(&nva); 1908 NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, 1909 LOCKPARENT | NOCACHE); 1910 nfsvno_setpathbuf(&named, &bufp, &hashp); 1911 error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 1912 if (!error && !nd->nd_repstat) 1913 error = nfsvno_getsymlink(nd, &nva, p, &pathcp, &pathlen); 1914 if (error) { 1915 vrele(dp); 1916 nfsvno_relpathbuf(&named); 1917 goto out; 1918 } 1919 if (!nd->nd_repstat) { 1920 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, &dirp); 1921 } else { 1922 vrele(dp); 1923 nfsvno_relpathbuf(&named); 1924 } 1925 if (dirp != NULL && !(nd->nd_flag & ND_NFSV3)) { 1926 vrele(dirp); 1927 dirp = NULL; 1928 } 1929 1930 /* 1931 * And call nfsrvd_symlinksub() to do the common code. It will 1932 * return EBADRPC upon a parsing error, 0 otherwise. 1933 */ 1934 if (!nd->nd_repstat) { 1935 if (dirp != NULL) 1936 dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, 1937 NULL); 1938 nfsrvd_symlinksub(nd, &named, &nva, fhp, vpp, dirp, 1939 &dirfor, &diraft, &diraft_ret, NULL, NULL, p, exp, 1940 pathcp, pathlen); 1941 } else if (dirp != NULL) { 1942 dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, NULL); 1943 vrele(dirp); 1944 } 1945 if (pathcp) 1946 free(pathcp, M_TEMP); 1947 1948 if (nd->nd_flag & ND_NFSV3) { 1949 if (!nd->nd_repstat) { 1950 (void)nfsm_fhtom(NULL, nd, (u_int8_t *)fhp, 0, 1); 1951 nfsrv_postopattr(nd, 0, &nva); 1952 } 1953 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1954 } 1955 1956 out: 1957 NFSEXITCODE2(error, nd); 1958 return (error); 1959 } 1960 1961 /* 1962 * Common code for creating a symbolic link. 1963 */ 1964 static void 1965 nfsrvd_symlinksub(struct nfsrv_descript *nd, struct nameidata *ndp, 1966 struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp, 1967 vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp, 1968 int *diraft_retp, nfsattrbit_t *attrbitp, 1969 NFSACL_T *aclp, NFSPROC_T *p, struct nfsexstuff *exp, char *pathcp, 1970 int pathlen) 1971 { 1972 u_int32_t *tl; 1973 1974 nd->nd_repstat = nfsvno_symlink(ndp, nvap, pathcp, pathlen, 1975 !(nd->nd_flag & ND_NFSV2), nd->nd_saveduid, nd->nd_cred, p, exp); 1976 if (!nd->nd_repstat && !(nd->nd_flag & ND_NFSV2)) { 1977 nfsrv_fixattr(nd, ndp->ni_vp, nvap, aclp, p, attrbitp, exp); 1978 if (nd->nd_flag & ND_NFSV3) { 1979 nd->nd_repstat = nfsvno_getfh(ndp->ni_vp, fhp, p); 1980 if (!nd->nd_repstat) 1981 nd->nd_repstat = nfsvno_getattr(ndp->ni_vp, 1982 nvap, nd, p, 1, NULL); 1983 } 1984 if (vpp != NULL && nd->nd_repstat == 0) { 1985 NFSVOPUNLOCK(ndp->ni_vp); 1986 *vpp = ndp->ni_vp; 1987 } else 1988 vput(ndp->ni_vp); 1989 } 1990 if (dirp) { 1991 *diraft_retp = nfsvno_getattr(dirp, diraftp, nd, p, 0, NULL); 1992 vrele(dirp); 1993 } 1994 if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) { 1995 NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 1996 *tl++ = newnfs_false; 1997 txdr_hyper(dirforp->na_filerev, tl); 1998 tl += 2; 1999 txdr_hyper(diraftp->na_filerev, tl); 2000 (void) nfsrv_putattrbit(nd, attrbitp); 2001 } 2002 2003 NFSEXITCODE2(0, nd); 2004 } 2005 2006 /* 2007 * nfs mkdir service 2008 */ 2009 int 2010 nfsrvd_mkdir(struct nfsrv_descript *nd, __unused int isdgram, 2011 vnode_t dp, vnode_t *vpp, fhandle_t *fhp, struct nfsexstuff *exp) 2012 { 2013 struct nfsvattr nva, dirfor, diraft; 2014 struct nameidata named; 2015 u_int32_t *tl; 2016 int error = 0, dirfor_ret = 1, diraft_ret = 1; 2017 vnode_t dirp = NULL; 2018 char *bufp; 2019 u_long *hashp; 2020 struct thread *p = curthread; 2021 2022 if (nd->nd_repstat) { 2023 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 2024 goto out; 2025 } 2026 NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, LOCKPARENT | NOCACHE); 2027 nfsvno_setpathbuf(&named, &bufp, &hashp); 2028 error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 2029 if (error) 2030 goto nfsmout; 2031 if (!nd->nd_repstat) { 2032 NFSVNO_ATTRINIT(&nva); 2033 if (nd->nd_flag & ND_NFSV3) { 2034 error = nfsrv_sattr(nd, NULL, &nva, NULL, NULL, p); 2035 if (error) 2036 goto nfsmout; 2037 } else { 2038 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2039 nva.na_mode = nfstov_mode(*tl++); 2040 } 2041 } 2042 if (!nd->nd_repstat) { 2043 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, &dirp); 2044 } else { 2045 vrele(dp); 2046 nfsvno_relpathbuf(&named); 2047 } 2048 if (dirp != NULL && !(nd->nd_flag & ND_NFSV3)) { 2049 vrele(dirp); 2050 dirp = NULL; 2051 } 2052 if (nd->nd_repstat) { 2053 if (dirp != NULL) { 2054 dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, 2055 NULL); 2056 vrele(dirp); 2057 } 2058 if (nd->nd_flag & ND_NFSV3) 2059 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, 2060 &diraft); 2061 goto out; 2062 } 2063 if (dirp != NULL) 2064 dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, NULL); 2065 2066 /* 2067 * Call nfsrvd_mkdirsub() for the code common to V4 as well. 2068 */ 2069 nfsrvd_mkdirsub(nd, &named, &nva, fhp, vpp, dirp, &dirfor, &diraft, 2070 &diraft_ret, NULL, NULL, p, exp); 2071 2072 if (nd->nd_flag & ND_NFSV3) { 2073 if (!nd->nd_repstat) { 2074 (void)nfsm_fhtom(NULL, nd, (u_int8_t *)fhp, 0, 1); 2075 nfsrv_postopattr(nd, 0, &nva); 2076 } 2077 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 2078 } else if (!nd->nd_repstat) { 2079 (void)nfsm_fhtom(NULL, nd, (u_int8_t *)fhp, 0, 0); 2080 nfsrv_fillattr(nd, &nva); 2081 } 2082 2083 out: 2084 NFSEXITCODE2(0, nd); 2085 return (0); 2086 nfsmout: 2087 vrele(dp); 2088 nfsvno_relpathbuf(&named); 2089 NFSEXITCODE2(error, nd); 2090 return (error); 2091 } 2092 2093 /* 2094 * Code common to mkdir for V2,3 and 4. 2095 */ 2096 static void 2097 nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct nameidata *ndp, 2098 struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp, 2099 vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp, 2100 int *diraft_retp, nfsattrbit_t *attrbitp, NFSACL_T *aclp, 2101 NFSPROC_T *p, struct nfsexstuff *exp) 2102 { 2103 vnode_t vp; 2104 u_int32_t *tl; 2105 2106 NFSVNO_SETATTRVAL(nvap, type, VDIR); 2107 nd->nd_repstat = nfsvno_mkdir(ndp, nvap, nd->nd_saveduid, 2108 nd->nd_cred, p, exp); 2109 if (!nd->nd_repstat) { 2110 vp = ndp->ni_vp; 2111 nfsrv_fixattr(nd, vp, nvap, aclp, p, attrbitp, exp); 2112 nd->nd_repstat = nfsvno_getfh(vp, fhp, p); 2113 if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) 2114 nd->nd_repstat = nfsvno_getattr(vp, nvap, nd, p, 1, 2115 NULL); 2116 if (vpp && !nd->nd_repstat) { 2117 NFSVOPUNLOCK(vp); 2118 *vpp = vp; 2119 } else { 2120 vput(vp); 2121 } 2122 } 2123 if (dirp) { 2124 *diraft_retp = nfsvno_getattr(dirp, diraftp, nd, p, 0, NULL); 2125 vrele(dirp); 2126 } 2127 if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) { 2128 NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 2129 *tl++ = newnfs_false; 2130 txdr_hyper(dirforp->na_filerev, tl); 2131 tl += 2; 2132 txdr_hyper(diraftp->na_filerev, tl); 2133 (void) nfsrv_putattrbit(nd, attrbitp); 2134 } 2135 2136 NFSEXITCODE2(0, nd); 2137 } 2138 2139 /* 2140 * nfs commit service 2141 */ 2142 int 2143 nfsrvd_commit(struct nfsrv_descript *nd, __unused int isdgram, 2144 vnode_t vp, __unused struct nfsexstuff *exp) 2145 { 2146 struct nfsvattr bfor, aft; 2147 u_int32_t *tl; 2148 int error = 0, for_ret = 1, aft_ret = 1, cnt; 2149 u_int64_t off; 2150 struct thread *p = curthread; 2151 2152 if (nd->nd_repstat) { 2153 nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft); 2154 goto out; 2155 } 2156 2157 /* Return NFSERR_ISDIR in NFSv4 when commit on a directory. */ 2158 if (vp->v_type != VREG) { 2159 if (nd->nd_flag & ND_NFSV3) 2160 error = NFSERR_NOTSUPP; 2161 else 2162 error = (vp->v_type == VDIR) ? NFSERR_ISDIR : NFSERR_INVAL; 2163 goto nfsmout; 2164 } 2165 NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2166 2167 /* 2168 * XXX At this time VOP_FSYNC() does not accept offset and byte 2169 * count parameters, so these arguments are useless (someday maybe). 2170 */ 2171 off = fxdr_hyper(tl); 2172 tl += 2; 2173 cnt = fxdr_unsigned(int, *tl); 2174 if (nd->nd_flag & ND_NFSV3) 2175 for_ret = nfsvno_getattr(vp, &bfor, nd, p, 1, NULL); 2176 nd->nd_repstat = nfsvno_fsync(vp, off, cnt, nd->nd_cred, p); 2177 if (nd->nd_flag & ND_NFSV3) { 2178 aft_ret = nfsvno_getattr(vp, &aft, nd, p, 1, NULL); 2179 nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft); 2180 } 2181 vput(vp); 2182 if (!nd->nd_repstat) { 2183 NFSM_BUILD(tl, u_int32_t *, NFSX_VERF); 2184 *tl++ = txdr_unsigned(nfsboottime.tv_sec); 2185 *tl = txdr_unsigned(nfsboottime.tv_usec); 2186 } 2187 2188 out: 2189 NFSEXITCODE2(0, nd); 2190 return (0); 2191 nfsmout: 2192 vput(vp); 2193 NFSEXITCODE2(error, nd); 2194 return (error); 2195 } 2196 2197 /* 2198 * nfs statfs service 2199 */ 2200 int 2201 nfsrvd_statfs(struct nfsrv_descript *nd, __unused int isdgram, 2202 vnode_t vp, __unused struct nfsexstuff *exp) 2203 { 2204 struct statfs *sf; 2205 u_int32_t *tl; 2206 int getret = 1; 2207 struct nfsvattr at; 2208 u_quad_t tval; 2209 struct thread *p = curthread; 2210 2211 sf = NULL; 2212 if (nd->nd_repstat) { 2213 nfsrv_postopattr(nd, getret, &at); 2214 goto out; 2215 } 2216 sf = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); 2217 nd->nd_repstat = nfsvno_statfs(vp, sf); 2218 getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL); 2219 vput(vp); 2220 if (nd->nd_flag & ND_NFSV3) 2221 nfsrv_postopattr(nd, getret, &at); 2222 if (nd->nd_repstat) 2223 goto out; 2224 if (nd->nd_flag & ND_NFSV2) { 2225 NFSM_BUILD(tl, u_int32_t *, NFSX_V2STATFS); 2226 *tl++ = txdr_unsigned(NFS_V2MAXDATA); 2227 *tl++ = txdr_unsigned(sf->f_bsize); 2228 *tl++ = txdr_unsigned(sf->f_blocks); 2229 *tl++ = txdr_unsigned(sf->f_bfree); 2230 *tl = txdr_unsigned(sf->f_bavail); 2231 } else { 2232 NFSM_BUILD(tl, u_int32_t *, NFSX_V3STATFS); 2233 tval = (u_quad_t)sf->f_blocks; 2234 tval *= (u_quad_t)sf->f_bsize; 2235 txdr_hyper(tval, tl); tl += 2; 2236 tval = (u_quad_t)sf->f_bfree; 2237 tval *= (u_quad_t)sf->f_bsize; 2238 txdr_hyper(tval, tl); tl += 2; 2239 tval = (u_quad_t)sf->f_bavail; 2240 tval *= (u_quad_t)sf->f_bsize; 2241 txdr_hyper(tval, tl); tl += 2; 2242 tval = (u_quad_t)sf->f_files; 2243 txdr_hyper(tval, tl); tl += 2; 2244 tval = (u_quad_t)sf->f_ffree; 2245 txdr_hyper(tval, tl); tl += 2; 2246 tval = (u_quad_t)sf->f_ffree; 2247 txdr_hyper(tval, tl); tl += 2; 2248 *tl = 0; 2249 } 2250 2251 out: 2252 free(sf, M_STATFS); 2253 NFSEXITCODE2(0, nd); 2254 return (0); 2255 } 2256 2257 /* 2258 * nfs fsinfo service 2259 */ 2260 int 2261 nfsrvd_fsinfo(struct nfsrv_descript *nd, int isdgram, 2262 vnode_t vp, __unused struct nfsexstuff *exp) 2263 { 2264 u_int32_t *tl; 2265 struct nfsfsinfo fs; 2266 int getret = 1; 2267 struct nfsvattr at; 2268 struct thread *p = curthread; 2269 2270 if (nd->nd_repstat) { 2271 nfsrv_postopattr(nd, getret, &at); 2272 goto out; 2273 } 2274 getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL); 2275 nfsvno_getfs(&fs, isdgram); 2276 vput(vp); 2277 nfsrv_postopattr(nd, getret, &at); 2278 NFSM_BUILD(tl, u_int32_t *, NFSX_V3FSINFO); 2279 *tl++ = txdr_unsigned(fs.fs_rtmax); 2280 *tl++ = txdr_unsigned(fs.fs_rtpref); 2281 *tl++ = txdr_unsigned(fs.fs_rtmult); 2282 *tl++ = txdr_unsigned(fs.fs_wtmax); 2283 *tl++ = txdr_unsigned(fs.fs_wtpref); 2284 *tl++ = txdr_unsigned(fs.fs_wtmult); 2285 *tl++ = txdr_unsigned(fs.fs_dtpref); 2286 txdr_hyper(fs.fs_maxfilesize, tl); 2287 tl += 2; 2288 txdr_nfsv3time(&fs.fs_timedelta, tl); 2289 tl += 2; 2290 *tl = txdr_unsigned(fs.fs_properties); 2291 2292 out: 2293 NFSEXITCODE2(0, nd); 2294 return (0); 2295 } 2296 2297 /* 2298 * nfs pathconf service 2299 */ 2300 int 2301 nfsrvd_pathconf(struct nfsrv_descript *nd, __unused int isdgram, 2302 vnode_t vp, __unused struct nfsexstuff *exp) 2303 { 2304 struct nfsv3_pathconf *pc; 2305 int getret = 1; 2306 long linkmax, namemax, chownres, notrunc; 2307 struct nfsvattr at; 2308 struct thread *p = curthread; 2309 2310 if (nd->nd_repstat) { 2311 nfsrv_postopattr(nd, getret, &at); 2312 goto out; 2313 } 2314 nd->nd_repstat = nfsvno_pathconf(vp, _PC_LINK_MAX, &linkmax, 2315 nd->nd_cred, p); 2316 if (!nd->nd_repstat) 2317 nd->nd_repstat = nfsvno_pathconf(vp, _PC_NAME_MAX, &namemax, 2318 nd->nd_cred, p); 2319 if (!nd->nd_repstat) 2320 nd->nd_repstat=nfsvno_pathconf(vp, _PC_CHOWN_RESTRICTED, 2321 &chownres, nd->nd_cred, p); 2322 if (!nd->nd_repstat) 2323 nd->nd_repstat = nfsvno_pathconf(vp, _PC_NO_TRUNC, ¬runc, 2324 nd->nd_cred, p); 2325 getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL); 2326 vput(vp); 2327 nfsrv_postopattr(nd, getret, &at); 2328 if (!nd->nd_repstat) { 2329 NFSM_BUILD(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF); 2330 pc->pc_linkmax = txdr_unsigned(linkmax); 2331 pc->pc_namemax = txdr_unsigned(namemax); 2332 pc->pc_notrunc = txdr_unsigned(notrunc); 2333 pc->pc_chownrestricted = txdr_unsigned(chownres); 2334 2335 /* 2336 * These should probably be supported by VOP_PATHCONF(), but 2337 * until msdosfs is exportable (why would you want to?), the 2338 * Unix defaults should be ok. 2339 */ 2340 pc->pc_caseinsensitive = newnfs_false; 2341 pc->pc_casepreserving = newnfs_true; 2342 } 2343 2344 out: 2345 NFSEXITCODE2(0, nd); 2346 return (0); 2347 } 2348 2349 /* 2350 * nfsv4 lock service 2351 */ 2352 int 2353 nfsrvd_lock(struct nfsrv_descript *nd, __unused int isdgram, 2354 vnode_t vp, struct nfsexstuff *exp) 2355 { 2356 u_int32_t *tl; 2357 int i; 2358 struct nfsstate *stp = NULL; 2359 struct nfslock *lop; 2360 struct nfslockconflict cf; 2361 int error = 0; 2362 u_short flags = NFSLCK_LOCK, lflags; 2363 u_int64_t offset, len; 2364 nfsv4stateid_t stateid; 2365 nfsquad_t clientid; 2366 struct thread *p = curthread; 2367 2368 NFSM_DISSECT(tl, u_int32_t *, 7 * NFSX_UNSIGNED); 2369 i = fxdr_unsigned(int, *tl++); 2370 switch (i) { 2371 case NFSV4LOCKT_READW: 2372 flags |= NFSLCK_BLOCKING; 2373 case NFSV4LOCKT_READ: 2374 lflags = NFSLCK_READ; 2375 break; 2376 case NFSV4LOCKT_WRITEW: 2377 flags |= NFSLCK_BLOCKING; 2378 case NFSV4LOCKT_WRITE: 2379 lflags = NFSLCK_WRITE; 2380 break; 2381 default: 2382 nd->nd_repstat = NFSERR_BADXDR; 2383 goto nfsmout; 2384 } 2385 if (*tl++ == newnfs_true) 2386 flags |= NFSLCK_RECLAIM; 2387 offset = fxdr_hyper(tl); 2388 tl += 2; 2389 len = fxdr_hyper(tl); 2390 tl += 2; 2391 if (*tl == newnfs_true) 2392 flags |= NFSLCK_OPENTOLOCK; 2393 if (flags & NFSLCK_OPENTOLOCK) { 2394 NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED + NFSX_STATEID); 2395 i = fxdr_unsigned(int, *(tl+4+(NFSX_STATEID / NFSX_UNSIGNED))); 2396 if (i <= 0 || i > NFSV4_OPAQUELIMIT) { 2397 nd->nd_repstat = NFSERR_BADXDR; 2398 goto nfsmout; 2399 } 2400 stp = malloc(sizeof (struct nfsstate) + i, 2401 M_NFSDSTATE, M_WAITOK); 2402 stp->ls_ownerlen = i; 2403 stp->ls_op = nd->nd_rp; 2404 stp->ls_seq = fxdr_unsigned(int, *tl++); 2405 stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 2406 NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, 2407 NFSX_STATEIDOTHER); 2408 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 2409 2410 /* 2411 * For the special stateid of other all 0s and seqid == 1, set 2412 * the stateid to the current stateid, if it is set. 2413 */ 2414 if ((nd->nd_flag & ND_NFSV41) != 0 && 2415 stp->ls_stateid.seqid == 1 && 2416 stp->ls_stateid.other[0] == 0 && 2417 stp->ls_stateid.other[1] == 0 && 2418 stp->ls_stateid.other[2] == 0) { 2419 if ((nd->nd_flag & ND_CURSTATEID) != 0) { 2420 stp->ls_stateid = nd->nd_curstateid; 2421 stp->ls_stateid.seqid = 0; 2422 } else { 2423 nd->nd_repstat = NFSERR_BADSTATEID; 2424 goto nfsmout; 2425 } 2426 } 2427 2428 stp->ls_opentolockseq = fxdr_unsigned(int, *tl++); 2429 clientid.lval[0] = *tl++; 2430 clientid.lval[1] = *tl++; 2431 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 2432 if ((nd->nd_flag & ND_NFSV41) != 0) 2433 clientid.qval = nd->nd_clientid.qval; 2434 else if (nd->nd_clientid.qval != clientid.qval) 2435 printf("EEK3 multiple clids\n"); 2436 } else { 2437 if ((nd->nd_flag & ND_NFSV41) != 0) 2438 printf("EEK! no clientid from session\n"); 2439 nd->nd_flag |= ND_IMPLIEDCLID; 2440 nd->nd_clientid.qval = clientid.qval; 2441 } 2442 error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen); 2443 if (error) 2444 goto nfsmout; 2445 } else { 2446 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED); 2447 stp = malloc(sizeof (struct nfsstate), 2448 M_NFSDSTATE, M_WAITOK); 2449 stp->ls_ownerlen = 0; 2450 stp->ls_op = nd->nd_rp; 2451 stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 2452 NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, 2453 NFSX_STATEIDOTHER); 2454 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 2455 2456 /* 2457 * For the special stateid of other all 0s and seqid == 1, set 2458 * the stateid to the current stateid, if it is set. 2459 */ 2460 if ((nd->nd_flag & ND_NFSV41) != 0 && 2461 stp->ls_stateid.seqid == 1 && 2462 stp->ls_stateid.other[0] == 0 && 2463 stp->ls_stateid.other[1] == 0 && 2464 stp->ls_stateid.other[2] == 0) { 2465 if ((nd->nd_flag & ND_CURSTATEID) != 0) { 2466 stp->ls_stateid = nd->nd_curstateid; 2467 stp->ls_stateid.seqid = 0; 2468 } else { 2469 nd->nd_repstat = NFSERR_BADSTATEID; 2470 goto nfsmout; 2471 } 2472 } 2473 2474 stp->ls_seq = fxdr_unsigned(int, *tl); 2475 clientid.lval[0] = stp->ls_stateid.other[0]; 2476 clientid.lval[1] = stp->ls_stateid.other[1]; 2477 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 2478 if ((nd->nd_flag & ND_NFSV41) != 0) 2479 clientid.qval = nd->nd_clientid.qval; 2480 else if (nd->nd_clientid.qval != clientid.qval) 2481 printf("EEK4 multiple clids\n"); 2482 } else { 2483 if ((nd->nd_flag & ND_NFSV41) != 0) 2484 printf("EEK! no clientid from session\n"); 2485 nd->nd_flag |= ND_IMPLIEDCLID; 2486 nd->nd_clientid.qval = clientid.qval; 2487 } 2488 } 2489 lop = malloc(sizeof (struct nfslock), 2490 M_NFSDLOCK, M_WAITOK); 2491 lop->lo_first = offset; 2492 if (len == NFS64BITSSET) { 2493 lop->lo_end = NFS64BITSSET; 2494 } else { 2495 lop->lo_end = offset + len; 2496 if (lop->lo_end <= lop->lo_first) 2497 nd->nd_repstat = NFSERR_INVAL; 2498 } 2499 lop->lo_flags = lflags; 2500 stp->ls_flags = flags; 2501 stp->ls_uid = nd->nd_cred->cr_uid; 2502 2503 /* 2504 * Do basic access checking. 2505 */ 2506 if (!nd->nd_repstat && vp->v_type != VREG) { 2507 if (vp->v_type == VDIR) 2508 nd->nd_repstat = NFSERR_ISDIR; 2509 else 2510 nd->nd_repstat = NFSERR_INVAL; 2511 } 2512 if (!nd->nd_repstat) { 2513 if (lflags & NFSLCK_WRITE) { 2514 nd->nd_repstat = nfsvno_accchk(vp, VWRITE, 2515 nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER, 2516 NFSACCCHK_VPISLOCKED, NULL); 2517 } else { 2518 nd->nd_repstat = nfsvno_accchk(vp, VREAD, 2519 nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER, 2520 NFSACCCHK_VPISLOCKED, NULL); 2521 if (nd->nd_repstat) 2522 nd->nd_repstat = nfsvno_accchk(vp, VEXEC, 2523 nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER, 2524 NFSACCCHK_VPISLOCKED, NULL); 2525 } 2526 } 2527 2528 /* 2529 * We call nfsrv_lockctrl() even if nd_repstat set, so that the 2530 * seqid# gets updated. nfsrv_lockctrl() will return the value 2531 * of nd_repstat, if it gets that far. 2532 */ 2533 nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, &cf, clientid, 2534 &stateid, exp, nd, p); 2535 if (lop) 2536 free(lop, M_NFSDLOCK); 2537 if (stp) 2538 free(stp, M_NFSDSTATE); 2539 if (!nd->nd_repstat) { 2540 /* For NFSv4.1, set the Current StateID. */ 2541 if ((nd->nd_flag & ND_NFSV41) != 0) { 2542 nd->nd_curstateid = stateid; 2543 nd->nd_flag |= ND_CURSTATEID; 2544 } 2545 NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID); 2546 *tl++ = txdr_unsigned(stateid.seqid); 2547 NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); 2548 } else if (nd->nd_repstat == NFSERR_DENIED) { 2549 NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED); 2550 txdr_hyper(cf.cl_first, tl); 2551 tl += 2; 2552 if (cf.cl_end == NFS64BITSSET) 2553 len = NFS64BITSSET; 2554 else 2555 len = cf.cl_end - cf.cl_first; 2556 txdr_hyper(len, tl); 2557 tl += 2; 2558 if (cf.cl_flags == NFSLCK_WRITE) 2559 *tl++ = txdr_unsigned(NFSV4LOCKT_WRITE); 2560 else 2561 *tl++ = txdr_unsigned(NFSV4LOCKT_READ); 2562 *tl++ = stateid.other[0]; 2563 *tl = stateid.other[1]; 2564 (void) nfsm_strtom(nd, cf.cl_owner, cf.cl_ownerlen); 2565 } 2566 vput(vp); 2567 NFSEXITCODE2(0, nd); 2568 return (0); 2569 nfsmout: 2570 vput(vp); 2571 if (stp) 2572 free(stp, M_NFSDSTATE); 2573 NFSEXITCODE2(error, nd); 2574 return (error); 2575 } 2576 2577 /* 2578 * nfsv4 lock test service 2579 */ 2580 int 2581 nfsrvd_lockt(struct nfsrv_descript *nd, __unused int isdgram, 2582 vnode_t vp, struct nfsexstuff *exp) 2583 { 2584 u_int32_t *tl; 2585 int i; 2586 struct nfsstate *stp = NULL; 2587 struct nfslock lo, *lop = &lo; 2588 struct nfslockconflict cf; 2589 int error = 0; 2590 nfsv4stateid_t stateid; 2591 nfsquad_t clientid; 2592 u_int64_t len; 2593 struct thread *p = curthread; 2594 2595 NFSM_DISSECT(tl, u_int32_t *, 8 * NFSX_UNSIGNED); 2596 i = fxdr_unsigned(int, *(tl + 7)); 2597 if (i <= 0 || i > NFSV4_OPAQUELIMIT) { 2598 nd->nd_repstat = NFSERR_BADXDR; 2599 goto nfsmout; 2600 } 2601 stp = malloc(sizeof (struct nfsstate) + i, 2602 M_NFSDSTATE, M_WAITOK); 2603 stp->ls_ownerlen = i; 2604 stp->ls_op = NULL; 2605 stp->ls_flags = NFSLCK_TEST; 2606 stp->ls_uid = nd->nd_cred->cr_uid; 2607 i = fxdr_unsigned(int, *tl++); 2608 switch (i) { 2609 case NFSV4LOCKT_READW: 2610 stp->ls_flags |= NFSLCK_BLOCKING; 2611 case NFSV4LOCKT_READ: 2612 lo.lo_flags = NFSLCK_READ; 2613 break; 2614 case NFSV4LOCKT_WRITEW: 2615 stp->ls_flags |= NFSLCK_BLOCKING; 2616 case NFSV4LOCKT_WRITE: 2617 lo.lo_flags = NFSLCK_WRITE; 2618 break; 2619 default: 2620 nd->nd_repstat = NFSERR_BADXDR; 2621 goto nfsmout; 2622 } 2623 lo.lo_first = fxdr_hyper(tl); 2624 tl += 2; 2625 len = fxdr_hyper(tl); 2626 if (len == NFS64BITSSET) { 2627 lo.lo_end = NFS64BITSSET; 2628 } else { 2629 lo.lo_end = lo.lo_first + len; 2630 if (lo.lo_end <= lo.lo_first) 2631 nd->nd_repstat = NFSERR_INVAL; 2632 } 2633 tl += 2; 2634 clientid.lval[0] = *tl++; 2635 clientid.lval[1] = *tl; 2636 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 2637 if ((nd->nd_flag & ND_NFSV41) != 0) 2638 clientid.qval = nd->nd_clientid.qval; 2639 else if (nd->nd_clientid.qval != clientid.qval) 2640 printf("EEK5 multiple clids\n"); 2641 } else { 2642 if ((nd->nd_flag & ND_NFSV41) != 0) 2643 printf("EEK! no clientid from session\n"); 2644 nd->nd_flag |= ND_IMPLIEDCLID; 2645 nd->nd_clientid.qval = clientid.qval; 2646 } 2647 error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen); 2648 if (error) 2649 goto nfsmout; 2650 if (!nd->nd_repstat && vp->v_type != VREG) { 2651 if (vp->v_type == VDIR) 2652 nd->nd_repstat = NFSERR_ISDIR; 2653 else 2654 nd->nd_repstat = NFSERR_INVAL; 2655 } 2656 if (!nd->nd_repstat) 2657 nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, &cf, clientid, 2658 &stateid, exp, nd, p); 2659 if (nd->nd_repstat) { 2660 if (nd->nd_repstat == NFSERR_DENIED) { 2661 NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED); 2662 txdr_hyper(cf.cl_first, tl); 2663 tl += 2; 2664 if (cf.cl_end == NFS64BITSSET) 2665 len = NFS64BITSSET; 2666 else 2667 len = cf.cl_end - cf.cl_first; 2668 txdr_hyper(len, tl); 2669 tl += 2; 2670 if (cf.cl_flags == NFSLCK_WRITE) 2671 *tl++ = txdr_unsigned(NFSV4LOCKT_WRITE); 2672 else 2673 *tl++ = txdr_unsigned(NFSV4LOCKT_READ); 2674 *tl++ = stp->ls_stateid.other[0]; 2675 *tl = stp->ls_stateid.other[1]; 2676 (void) nfsm_strtom(nd, cf.cl_owner, cf.cl_ownerlen); 2677 } 2678 } 2679 vput(vp); 2680 if (stp) 2681 free(stp, M_NFSDSTATE); 2682 NFSEXITCODE2(0, nd); 2683 return (0); 2684 nfsmout: 2685 vput(vp); 2686 if (stp) 2687 free(stp, M_NFSDSTATE); 2688 NFSEXITCODE2(error, nd); 2689 return (error); 2690 } 2691 2692 /* 2693 * nfsv4 unlock service 2694 */ 2695 int 2696 nfsrvd_locku(struct nfsrv_descript *nd, __unused int isdgram, 2697 vnode_t vp, struct nfsexstuff *exp) 2698 { 2699 u_int32_t *tl; 2700 int i; 2701 struct nfsstate *stp; 2702 struct nfslock *lop; 2703 int error = 0; 2704 nfsv4stateid_t stateid; 2705 nfsquad_t clientid; 2706 u_int64_t len; 2707 struct thread *p = curthread; 2708 2709 NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED + NFSX_STATEID); 2710 stp = malloc(sizeof (struct nfsstate), 2711 M_NFSDSTATE, M_WAITOK); 2712 lop = malloc(sizeof (struct nfslock), 2713 M_NFSDLOCK, M_WAITOK); 2714 stp->ls_flags = NFSLCK_UNLOCK; 2715 lop->lo_flags = NFSLCK_UNLOCK; 2716 stp->ls_op = nd->nd_rp; 2717 i = fxdr_unsigned(int, *tl++); 2718 switch (i) { 2719 case NFSV4LOCKT_READW: 2720 stp->ls_flags |= NFSLCK_BLOCKING; 2721 case NFSV4LOCKT_READ: 2722 break; 2723 case NFSV4LOCKT_WRITEW: 2724 stp->ls_flags |= NFSLCK_BLOCKING; 2725 case NFSV4LOCKT_WRITE: 2726 break; 2727 default: 2728 nd->nd_repstat = NFSERR_BADXDR; 2729 free(stp, M_NFSDSTATE); 2730 free(lop, M_NFSDLOCK); 2731 goto nfsmout; 2732 } 2733 stp->ls_ownerlen = 0; 2734 stp->ls_uid = nd->nd_cred->cr_uid; 2735 stp->ls_seq = fxdr_unsigned(int, *tl++); 2736 stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 2737 NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, 2738 NFSX_STATEIDOTHER); 2739 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 2740 2741 /* 2742 * For the special stateid of other all 0s and seqid == 1, set the 2743 * stateid to the current stateid, if it is set. 2744 */ 2745 if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 && 2746 stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 && 2747 stp->ls_stateid.other[2] == 0) { 2748 if ((nd->nd_flag & ND_CURSTATEID) != 0) { 2749 stp->ls_stateid = nd->nd_curstateid; 2750 stp->ls_stateid.seqid = 0; 2751 } else { 2752 nd->nd_repstat = NFSERR_BADSTATEID; 2753 free(stp, M_NFSDSTATE); 2754 free(lop, M_NFSDLOCK); 2755 goto nfsmout; 2756 } 2757 } 2758 2759 lop->lo_first = fxdr_hyper(tl); 2760 tl += 2; 2761 len = fxdr_hyper(tl); 2762 if (len == NFS64BITSSET) { 2763 lop->lo_end = NFS64BITSSET; 2764 } else { 2765 lop->lo_end = lop->lo_first + len; 2766 if (lop->lo_end <= lop->lo_first) 2767 nd->nd_repstat = NFSERR_INVAL; 2768 } 2769 clientid.lval[0] = stp->ls_stateid.other[0]; 2770 clientid.lval[1] = stp->ls_stateid.other[1]; 2771 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 2772 if ((nd->nd_flag & ND_NFSV41) != 0) 2773 clientid.qval = nd->nd_clientid.qval; 2774 else if (nd->nd_clientid.qval != clientid.qval) 2775 printf("EEK6 multiple clids\n"); 2776 } else { 2777 if ((nd->nd_flag & ND_NFSV41) != 0) 2778 printf("EEK! no clientid from session\n"); 2779 nd->nd_flag |= ND_IMPLIEDCLID; 2780 nd->nd_clientid.qval = clientid.qval; 2781 } 2782 if (!nd->nd_repstat && vp->v_type != VREG) { 2783 if (vp->v_type == VDIR) 2784 nd->nd_repstat = NFSERR_ISDIR; 2785 else 2786 nd->nd_repstat = NFSERR_INVAL; 2787 } 2788 /* 2789 * Call nfsrv_lockctrl() even if nd_repstat is set, so that the 2790 * seqid# gets incremented. nfsrv_lockctrl() will return the 2791 * value of nd_repstat, if it gets that far. 2792 */ 2793 nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, 2794 &stateid, exp, nd, p); 2795 if (stp) 2796 free(stp, M_NFSDSTATE); 2797 if (lop) 2798 free(lop, M_NFSDLOCK); 2799 if (!nd->nd_repstat) { 2800 NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID); 2801 *tl++ = txdr_unsigned(stateid.seqid); 2802 NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); 2803 } 2804 nfsmout: 2805 vput(vp); 2806 NFSEXITCODE2(error, nd); 2807 return (error); 2808 } 2809 2810 /* 2811 * nfsv4 open service 2812 */ 2813 int 2814 nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram, 2815 vnode_t dp, vnode_t *vpp, __unused fhandle_t *fhp, struct nfsexstuff *exp) 2816 { 2817 u_int32_t *tl; 2818 int i, retext; 2819 struct nfsstate *stp = NULL; 2820 int error = 0, create, claim, exclusive_flag = 0, override; 2821 u_int32_t rflags = NFSV4OPEN_LOCKTYPEPOSIX, acemask; 2822 int how = NFSCREATE_UNCHECKED; 2823 int32_t cverf[2], tverf[2] = { 0, 0 }; 2824 vnode_t vp = NULL, dirp = NULL; 2825 struct nfsvattr nva, dirfor, diraft; 2826 struct nameidata named; 2827 nfsv4stateid_t stateid, delegstateid; 2828 nfsattrbit_t attrbits; 2829 nfsquad_t clientid; 2830 char *bufp = NULL; 2831 u_long *hashp; 2832 NFSACL_T *aclp = NULL; 2833 struct thread *p = curthread; 2834 bool done_namei; 2835 2836 #ifdef NFS4_ACL_EXTATTR_NAME 2837 aclp = acl_alloc(M_WAITOK); 2838 aclp->acl_cnt = 0; 2839 #endif 2840 NFSZERO_ATTRBIT(&attrbits); 2841 done_namei = false; 2842 named.ni_cnd.cn_nameiop = 0; 2843 NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED); 2844 i = fxdr_unsigned(int, *(tl + 5)); 2845 if (i <= 0 || i > NFSV4_OPAQUELIMIT) { 2846 nd->nd_repstat = NFSERR_BADXDR; 2847 goto nfsmout; 2848 } 2849 stp = malloc(sizeof (struct nfsstate) + i, 2850 M_NFSDSTATE, M_WAITOK); 2851 stp->ls_ownerlen = i; 2852 stp->ls_op = nd->nd_rp; 2853 stp->ls_flags = NFSLCK_OPEN; 2854 stp->ls_uid = nd->nd_cred->cr_uid; 2855 stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++); 2856 i = fxdr_unsigned(int, *tl++); 2857 retext = 0; 2858 if ((i & (NFSV4OPEN_WANTDELEGMASK | NFSV4OPEN_WANTSIGNALDELEG | 2859 NFSV4OPEN_WANTPUSHDELEG)) != 0 && (nd->nd_flag & ND_NFSV41) != 0) { 2860 retext = 1; 2861 /* For now, ignore these. */ 2862 i &= ~(NFSV4OPEN_WANTPUSHDELEG | NFSV4OPEN_WANTSIGNALDELEG); 2863 switch (i & NFSV4OPEN_WANTDELEGMASK) { 2864 case NFSV4OPEN_WANTANYDELEG: 2865 stp->ls_flags |= (NFSLCK_WANTRDELEG | 2866 NFSLCK_WANTWDELEG); 2867 i &= ~NFSV4OPEN_WANTDELEGMASK; 2868 break; 2869 case NFSV4OPEN_WANTREADDELEG: 2870 stp->ls_flags |= NFSLCK_WANTRDELEG; 2871 i &= ~NFSV4OPEN_WANTDELEGMASK; 2872 break; 2873 case NFSV4OPEN_WANTWRITEDELEG: 2874 stp->ls_flags |= NFSLCK_WANTWDELEG; 2875 i &= ~NFSV4OPEN_WANTDELEGMASK; 2876 break; 2877 case NFSV4OPEN_WANTNODELEG: 2878 stp->ls_flags |= NFSLCK_WANTNODELEG; 2879 i &= ~NFSV4OPEN_WANTDELEGMASK; 2880 break; 2881 case NFSV4OPEN_WANTCANCEL: 2882 printf("NFSv4: ignore Open WantCancel\n"); 2883 i &= ~NFSV4OPEN_WANTDELEGMASK; 2884 break; 2885 default: 2886 /* nd_repstat will be set to NFSERR_INVAL below. */ 2887 break; 2888 } 2889 } 2890 switch (i) { 2891 case NFSV4OPEN_ACCESSREAD: 2892 stp->ls_flags |= NFSLCK_READACCESS; 2893 break; 2894 case NFSV4OPEN_ACCESSWRITE: 2895 stp->ls_flags |= NFSLCK_WRITEACCESS; 2896 break; 2897 case NFSV4OPEN_ACCESSBOTH: 2898 stp->ls_flags |= (NFSLCK_READACCESS | NFSLCK_WRITEACCESS); 2899 break; 2900 default: 2901 nd->nd_repstat = NFSERR_INVAL; 2902 } 2903 i = fxdr_unsigned(int, *tl++); 2904 switch (i) { 2905 case NFSV4OPEN_DENYNONE: 2906 break; 2907 case NFSV4OPEN_DENYREAD: 2908 stp->ls_flags |= NFSLCK_READDENY; 2909 break; 2910 case NFSV4OPEN_DENYWRITE: 2911 stp->ls_flags |= NFSLCK_WRITEDENY; 2912 break; 2913 case NFSV4OPEN_DENYBOTH: 2914 stp->ls_flags |= (NFSLCK_READDENY | NFSLCK_WRITEDENY); 2915 break; 2916 default: 2917 nd->nd_repstat = NFSERR_INVAL; 2918 } 2919 clientid.lval[0] = *tl++; 2920 clientid.lval[1] = *tl; 2921 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 2922 if ((nd->nd_flag & ND_NFSV41) != 0) 2923 clientid.qval = nd->nd_clientid.qval; 2924 else if (nd->nd_clientid.qval != clientid.qval) 2925 printf("EEK7 multiple clids\n"); 2926 } else { 2927 if ((nd->nd_flag & ND_NFSV41) != 0) 2928 printf("EEK! no clientid from session\n"); 2929 nd->nd_flag |= ND_IMPLIEDCLID; 2930 nd->nd_clientid.qval = clientid.qval; 2931 } 2932 error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen); 2933 if (error) 2934 goto nfsmout; 2935 NFSVNO_ATTRINIT(&nva); 2936 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2937 create = fxdr_unsigned(int, *tl); 2938 if (!nd->nd_repstat) 2939 nd->nd_repstat = nfsvno_getattr(dp, &dirfor, nd, p, 0, NULL); 2940 if (create == NFSV4OPEN_CREATE) { 2941 nva.na_type = VREG; 2942 nva.na_mode = 0; 2943 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2944 how = fxdr_unsigned(int, *tl); 2945 switch (how) { 2946 case NFSCREATE_UNCHECKED: 2947 case NFSCREATE_GUARDED: 2948 error = nfsv4_sattr(nd, NULL, &nva, &attrbits, aclp, p); 2949 if (error) 2950 goto nfsmout; 2951 /* 2952 * If the na_gid being set is the same as that of 2953 * the directory it is going in, clear it, since 2954 * that is what will be set by default. This allows 2955 * a user that isn't in that group to do the create. 2956 */ 2957 if (!nd->nd_repstat && NFSVNO_ISSETGID(&nva) && 2958 nva.na_gid == dirfor.na_gid) 2959 NFSVNO_UNSET(&nva, gid); 2960 if (!nd->nd_repstat) 2961 nd->nd_repstat = nfsrv_checkuidgid(nd, &nva); 2962 break; 2963 case NFSCREATE_EXCLUSIVE: 2964 NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF); 2965 cverf[0] = *tl++; 2966 cverf[1] = *tl; 2967 break; 2968 case NFSCREATE_EXCLUSIVE41: 2969 NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF); 2970 cverf[0] = *tl++; 2971 cverf[1] = *tl; 2972 error = nfsv4_sattr(nd, NULL, &nva, &attrbits, aclp, p); 2973 if (error != 0) 2974 goto nfsmout; 2975 if (NFSISSET_ATTRBIT(&attrbits, 2976 NFSATTRBIT_TIMEACCESSSET)) 2977 nd->nd_repstat = NFSERR_INVAL; 2978 /* 2979 * If the na_gid being set is the same as that of 2980 * the directory it is going in, clear it, since 2981 * that is what will be set by default. This allows 2982 * a user that isn't in that group to do the create. 2983 */ 2984 if (nd->nd_repstat == 0 && NFSVNO_ISSETGID(&nva) && 2985 nva.na_gid == dirfor.na_gid) 2986 NFSVNO_UNSET(&nva, gid); 2987 if (nd->nd_repstat == 0) 2988 nd->nd_repstat = nfsrv_checkuidgid(nd, &nva); 2989 break; 2990 default: 2991 nd->nd_repstat = NFSERR_BADXDR; 2992 goto nfsmout; 2993 } 2994 } else if (create != NFSV4OPEN_NOCREATE) { 2995 nd->nd_repstat = NFSERR_BADXDR; 2996 goto nfsmout; 2997 } 2998 2999 /* 3000 * Now, handle the claim, which usually includes looking up a 3001 * name in the directory referenced by dp. The exception is 3002 * NFSV4OPEN_CLAIMPREVIOUS. 3003 */ 3004 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3005 claim = fxdr_unsigned(int, *tl); 3006 if (claim == NFSV4OPEN_CLAIMDELEGATECUR) { 3007 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID); 3008 stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 3009 NFSBCOPY((caddr_t)tl,(caddr_t)stateid.other,NFSX_STATEIDOTHER); 3010 stp->ls_flags |= NFSLCK_DELEGCUR; 3011 } else if (claim == NFSV4OPEN_CLAIMDELEGATECURFH) { 3012 /* Fill in most of the stateid from the clientid. */ 3013 stateid.seqid = 0; 3014 stateid.other[0] = clientid.lval[0]; 3015 stateid.other[1] = clientid.lval[1]; 3016 stateid.other[2] = 0; 3017 stp->ls_flags |= NFSLCK_DELEGCUR; 3018 } else if (claim == NFSV4OPEN_CLAIMDELEGATEPREV || claim == 3019 NFSV4OPEN_CLAIMDELEGATEPREVFH) { 3020 stp->ls_flags |= NFSLCK_DELEGPREV; 3021 } 3022 if (claim == NFSV4OPEN_CLAIMNULL || claim == NFSV4OPEN_CLAIMDELEGATECUR 3023 || claim == NFSV4OPEN_CLAIMDELEGATEPREV) { 3024 if (!nd->nd_repstat && create == NFSV4OPEN_CREATE && 3025 claim != NFSV4OPEN_CLAIMNULL) 3026 nd->nd_repstat = NFSERR_INVAL; 3027 if (nd->nd_repstat) { 3028 nd->nd_repstat = nfsrv_opencheck(clientid, 3029 &stateid, stp, NULL, nd, p, nd->nd_repstat); 3030 goto nfsmout; 3031 } 3032 if (create == NFSV4OPEN_CREATE) 3033 NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, 3034 LOCKPARENT | LOCKLEAF | NOCACHE); 3035 else 3036 NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP, 3037 LOCKLEAF); 3038 nfsvno_setpathbuf(&named, &bufp, &hashp); 3039 error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 3040 if (error) { 3041 vrele(dp); 3042 #ifdef NFS4_ACL_EXTATTR_NAME 3043 acl_free(aclp); 3044 #endif 3045 free(stp, M_NFSDSTATE); 3046 nfsvno_relpathbuf(&named); 3047 NFSEXITCODE2(error, nd); 3048 return (error); 3049 } 3050 if (!nd->nd_repstat) { 3051 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, 3052 &dirp); 3053 } else { 3054 vrele(dp); 3055 nfsvno_relpathbuf(&named); 3056 } 3057 if (create == NFSV4OPEN_CREATE) { 3058 switch (how) { 3059 case NFSCREATE_UNCHECKED: 3060 if (nd->nd_repstat == 0 && named.ni_vp != NULL) { 3061 /* 3062 * Clear the setable attribute bits, except 3063 * for Size, if it is being truncated. 3064 */ 3065 NFSZERO_ATTRBIT(&attrbits); 3066 if (NFSVNO_ISSETSIZE(&nva)) 3067 NFSSETBIT_ATTRBIT(&attrbits, 3068 NFSATTRBIT_SIZE); 3069 } 3070 break; 3071 case NFSCREATE_GUARDED: 3072 if (nd->nd_repstat == 0 && named.ni_vp != NULL) { 3073 nd->nd_repstat = EEXIST; 3074 done_namei = true; 3075 } 3076 break; 3077 case NFSCREATE_EXCLUSIVE: 3078 exclusive_flag = 1; 3079 if (nd->nd_repstat == 0 && named.ni_vp == NULL) 3080 nva.na_mode = 0; 3081 break; 3082 case NFSCREATE_EXCLUSIVE41: 3083 exclusive_flag = 1; 3084 break; 3085 } 3086 } 3087 nfsvno_open(nd, &named, clientid, &stateid, stp, 3088 &exclusive_flag, &nva, cverf, create, aclp, &attrbits, 3089 nd->nd_cred, done_namei, exp, &vp); 3090 } else if (claim == NFSV4OPEN_CLAIMPREVIOUS || claim == 3091 NFSV4OPEN_CLAIMFH || claim == NFSV4OPEN_CLAIMDELEGATECURFH || 3092 claim == NFSV4OPEN_CLAIMDELEGATEPREVFH) { 3093 if (claim == NFSV4OPEN_CLAIMPREVIOUS) { 3094 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3095 i = fxdr_unsigned(int, *tl); 3096 switch (i) { 3097 case NFSV4OPEN_DELEGATEREAD: 3098 stp->ls_flags |= NFSLCK_DELEGREAD; 3099 break; 3100 case NFSV4OPEN_DELEGATEWRITE: 3101 stp->ls_flags |= NFSLCK_DELEGWRITE; 3102 case NFSV4OPEN_DELEGATENONE: 3103 break; 3104 default: 3105 nd->nd_repstat = NFSERR_BADXDR; 3106 goto nfsmout; 3107 } 3108 stp->ls_flags |= NFSLCK_RECLAIM; 3109 } else { 3110 if (nd->nd_repstat == 0 && create == NFSV4OPEN_CREATE) 3111 nd->nd_repstat = NFSERR_INVAL; 3112 } 3113 vp = dp; 3114 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 3115 if (!VN_IS_DOOMED(vp)) 3116 nd->nd_repstat = nfsrv_opencheck(clientid, &stateid, 3117 stp, vp, nd, p, nd->nd_repstat); 3118 else 3119 nd->nd_repstat = NFSERR_PERM; 3120 } else { 3121 nd->nd_repstat = NFSERR_BADXDR; 3122 goto nfsmout; 3123 } 3124 3125 /* 3126 * Do basic access checking. 3127 */ 3128 if (!nd->nd_repstat && vp->v_type != VREG) { 3129 /* 3130 * The IETF working group decided that this is the correct 3131 * error return for all non-regular files. 3132 */ 3133 nd->nd_repstat = (vp->v_type == VDIR) ? NFSERR_ISDIR : NFSERR_SYMLINK; 3134 } 3135 3136 /* 3137 * If the Open is being done for a file that already exists, apply 3138 * normal permission checking including for the file owner, if 3139 * vfs.nfsd.v4openaccess is set. 3140 * Previously, the owner was always allowed to open the file to 3141 * be consistent with the NFS tradition of always allowing the 3142 * owner of the file to write to the file regardless of permissions. 3143 * It now appears that the Linux client expects the owner 3144 * permissions to be checked for opens that are not creating the 3145 * file. I believe the correct approach is to use the Access 3146 * operation's results to be consistent with NFSv3, but that is 3147 * not what the current Linux client appears to be doing. 3148 * Since both the Linux and OpenSolaris NFSv4 servers do this check, 3149 * I have enabled it by default. Since Linux does not apply this 3150 * check for claim_delegate_cur, this code does the same. 3151 * If this semantic change causes a problem, it can be disabled by 3152 * setting the sysctl vfs.nfsd.v4openaccess to 0 to re-enable the 3153 * previous semantics. 3154 */ 3155 if (nfsrv_openaccess && create == NFSV4OPEN_NOCREATE && 3156 (stp->ls_flags & NFSLCK_DELEGCUR) == 0) 3157 override = NFSACCCHK_NOOVERRIDE; 3158 else 3159 override = NFSACCCHK_ALLOWOWNER; 3160 if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_WRITEACCESS)) 3161 nd->nd_repstat = nfsvno_accchk(vp, VWRITE, nd->nd_cred, 3162 exp, p, override, NFSACCCHK_VPISLOCKED, NULL); 3163 if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_READACCESS)) { 3164 nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred, 3165 exp, p, override, NFSACCCHK_VPISLOCKED, NULL); 3166 if (nd->nd_repstat) 3167 nd->nd_repstat = nfsvno_accchk(vp, VEXEC, 3168 nd->nd_cred, exp, p, override, 3169 NFSACCCHK_VPISLOCKED, NULL); 3170 } 3171 3172 if (!nd->nd_repstat) { 3173 nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, NULL); 3174 if (!nd->nd_repstat) { 3175 tverf[0] = nva.na_atime.tv_sec; 3176 tverf[1] = nva.na_atime.tv_nsec; 3177 } 3178 } 3179 if (!nd->nd_repstat && exclusive_flag && (cverf[0] != tverf[0] || 3180 cverf[1] != tverf[1])) 3181 nd->nd_repstat = EEXIST; 3182 /* 3183 * Do the open locking/delegation stuff. 3184 */ 3185 if (!nd->nd_repstat) 3186 nd->nd_repstat = nfsrv_openctrl(nd, vp, &stp, clientid, &stateid, 3187 &delegstateid, &rflags, exp, p, nva.na_filerev); 3188 3189 /* 3190 * vp must be unlocked before the call to nfsvno_getattr(dirp,...) 3191 * below, to avoid a deadlock with the lookup in nfsvno_namei() above. 3192 * (ie: Leave the NFSVOPUNLOCK() about here.) 3193 */ 3194 if (vp) 3195 NFSVOPUNLOCK(vp); 3196 if (stp) 3197 free(stp, M_NFSDSTATE); 3198 if (!nd->nd_repstat && dirp) 3199 nd->nd_repstat = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL); 3200 if (!nd->nd_repstat) { 3201 /* For NFSv4.1, set the Current StateID. */ 3202 if ((nd->nd_flag & ND_NFSV41) != 0) { 3203 nd->nd_curstateid = stateid; 3204 nd->nd_flag |= ND_CURSTATEID; 3205 } 3206 NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + 6 * NFSX_UNSIGNED); 3207 *tl++ = txdr_unsigned(stateid.seqid); 3208 NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); 3209 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 3210 if (claim == NFSV4OPEN_CLAIMPREVIOUS) { 3211 *tl++ = newnfs_true; 3212 *tl++ = 0; 3213 *tl++ = 0; 3214 *tl++ = 0; 3215 *tl++ = 0; 3216 } else { 3217 *tl++ = newnfs_false; /* Since dirp is not locked */ 3218 txdr_hyper(dirfor.na_filerev, tl); 3219 tl += 2; 3220 txdr_hyper(diraft.na_filerev, tl); 3221 tl += 2; 3222 } 3223 *tl = txdr_unsigned(rflags & NFSV4OPEN_RFLAGS); 3224 (void) nfsrv_putattrbit(nd, &attrbits); 3225 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 3226 if (rflags & NFSV4OPEN_READDELEGATE) 3227 *tl = txdr_unsigned(NFSV4OPEN_DELEGATEREAD); 3228 else if (rflags & NFSV4OPEN_WRITEDELEGATE) 3229 *tl = txdr_unsigned(NFSV4OPEN_DELEGATEWRITE); 3230 else if (retext != 0) { 3231 *tl = txdr_unsigned(NFSV4OPEN_DELEGATENONEEXT); 3232 if ((rflags & NFSV4OPEN_WDNOTWANTED) != 0) { 3233 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 3234 *tl = txdr_unsigned(NFSV4OPEN_NOTWANTED); 3235 } else if ((rflags & NFSV4OPEN_WDSUPPFTYPE) != 0) { 3236 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 3237 *tl = txdr_unsigned(NFSV4OPEN_NOTSUPPFTYPE); 3238 } else if ((rflags & NFSV4OPEN_WDCONTENTION) != 0) { 3239 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3240 *tl++ = txdr_unsigned(NFSV4OPEN_CONTENTION); 3241 *tl = newnfs_false; 3242 } else if ((rflags & NFSV4OPEN_WDRESOURCE) != 0) { 3243 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3244 *tl++ = txdr_unsigned(NFSV4OPEN_RESOURCE); 3245 *tl = newnfs_false; 3246 } else { 3247 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 3248 *tl = txdr_unsigned(NFSV4OPEN_NOTWANTED); 3249 } 3250 } else 3251 *tl = txdr_unsigned(NFSV4OPEN_DELEGATENONE); 3252 if (rflags & (NFSV4OPEN_READDELEGATE|NFSV4OPEN_WRITEDELEGATE)) { 3253 NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID+NFSX_UNSIGNED); 3254 *tl++ = txdr_unsigned(delegstateid.seqid); 3255 NFSBCOPY((caddr_t)delegstateid.other, (caddr_t)tl, 3256 NFSX_STATEIDOTHER); 3257 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 3258 if (rflags & NFSV4OPEN_RECALL) 3259 *tl = newnfs_true; 3260 else 3261 *tl = newnfs_false; 3262 if (rflags & NFSV4OPEN_WRITEDELEGATE) { 3263 NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 3264 *tl++ = txdr_unsigned(NFSV4OPEN_LIMITSIZE); 3265 txdr_hyper(nva.na_size, tl); 3266 } 3267 NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 3268 *tl++ = txdr_unsigned(NFSV4ACE_ALLOWEDTYPE); 3269 *tl++ = txdr_unsigned(0x0); 3270 acemask = NFSV4ACE_ALLFILESMASK; 3271 if (nva.na_mode & S_IRUSR) 3272 acemask |= NFSV4ACE_READMASK; 3273 if (nva.na_mode & S_IWUSR) 3274 acemask |= NFSV4ACE_WRITEMASK; 3275 if (nva.na_mode & S_IXUSR) 3276 acemask |= NFSV4ACE_EXECUTEMASK; 3277 *tl = txdr_unsigned(acemask); 3278 (void) nfsm_strtom(nd, "OWNER@", 6); 3279 } 3280 *vpp = vp; 3281 } else if (vp) { 3282 vrele(vp); 3283 } 3284 if (dirp) 3285 vrele(dirp); 3286 #ifdef NFS4_ACL_EXTATTR_NAME 3287 acl_free(aclp); 3288 #endif 3289 NFSEXITCODE2(0, nd); 3290 return (0); 3291 nfsmout: 3292 vrele(dp); 3293 #ifdef NFS4_ACL_EXTATTR_NAME 3294 acl_free(aclp); 3295 #endif 3296 if (stp) 3297 free(stp, M_NFSDSTATE); 3298 NFSEXITCODE2(error, nd); 3299 return (error); 3300 } 3301 3302 /* 3303 * nfsv4 close service 3304 */ 3305 int 3306 nfsrvd_close(struct nfsrv_descript *nd, __unused int isdgram, 3307 vnode_t vp, __unused struct nfsexstuff *exp) 3308 { 3309 u_int32_t *tl; 3310 struct nfsstate st, *stp = &st; 3311 int error = 0, writeacc; 3312 nfsv4stateid_t stateid; 3313 nfsquad_t clientid; 3314 struct nfsvattr na; 3315 struct thread *p = curthread; 3316 3317 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID); 3318 stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++); 3319 stp->ls_ownerlen = 0; 3320 stp->ls_op = nd->nd_rp; 3321 stp->ls_uid = nd->nd_cred->cr_uid; 3322 stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 3323 NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, 3324 NFSX_STATEIDOTHER); 3325 3326 /* 3327 * For the special stateid of other all 0s and seqid == 1, set the 3328 * stateid to the current stateid, if it is set. 3329 */ 3330 if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 && 3331 stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 && 3332 stp->ls_stateid.other[2] == 0) { 3333 if ((nd->nd_flag & ND_CURSTATEID) != 0) 3334 stp->ls_stateid = nd->nd_curstateid; 3335 else { 3336 nd->nd_repstat = NFSERR_BADSTATEID; 3337 goto nfsmout; 3338 } 3339 } 3340 3341 stp->ls_flags = NFSLCK_CLOSE; 3342 clientid.lval[0] = stp->ls_stateid.other[0]; 3343 clientid.lval[1] = stp->ls_stateid.other[1]; 3344 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 3345 if ((nd->nd_flag & ND_NFSV41) != 0) 3346 clientid.qval = nd->nd_clientid.qval; 3347 else if (nd->nd_clientid.qval != clientid.qval) 3348 printf("EEK8 multiple clids\n"); 3349 } else { 3350 if ((nd->nd_flag & ND_NFSV41) != 0) 3351 printf("EEK! no clientid from session\n"); 3352 nd->nd_flag |= ND_IMPLIEDCLID; 3353 nd->nd_clientid.qval = clientid.qval; 3354 } 3355 nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p, 3356 &writeacc); 3357 /* For pNFS, update the attributes. */ 3358 if (writeacc != 0 || nfsrv_pnfsatime != 0) 3359 nfsrv_updatemdsattr(vp, &na, p); 3360 vput(vp); 3361 if (!nd->nd_repstat) { 3362 /* 3363 * If the stateid that has been closed is the current stateid, 3364 * unset it. 3365 */ 3366 if ((nd->nd_flag & ND_CURSTATEID) != 0 && 3367 stateid.other[0] == nd->nd_curstateid.other[0] && 3368 stateid.other[1] == nd->nd_curstateid.other[1] && 3369 stateid.other[2] == nd->nd_curstateid.other[2]) 3370 nd->nd_flag &= ~ND_CURSTATEID; 3371 NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID); 3372 *tl++ = txdr_unsigned(stateid.seqid); 3373 NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); 3374 } 3375 NFSEXITCODE2(0, nd); 3376 return (0); 3377 nfsmout: 3378 vput(vp); 3379 NFSEXITCODE2(error, nd); 3380 return (error); 3381 } 3382 3383 /* 3384 * nfsv4 delegpurge service 3385 */ 3386 int 3387 nfsrvd_delegpurge(struct nfsrv_descript *nd, __unused int isdgram, 3388 __unused vnode_t vp, __unused struct nfsexstuff *exp) 3389 { 3390 u_int32_t *tl; 3391 int error = 0; 3392 nfsquad_t clientid; 3393 struct thread *p = curthread; 3394 3395 if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0) 3396 goto nfsmout; 3397 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3398 clientid.lval[0] = *tl++; 3399 clientid.lval[1] = *tl; 3400 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 3401 if ((nd->nd_flag & ND_NFSV41) != 0) 3402 clientid.qval = nd->nd_clientid.qval; 3403 else if (nd->nd_clientid.qval != clientid.qval) 3404 printf("EEK9 multiple clids\n"); 3405 } else { 3406 if ((nd->nd_flag & ND_NFSV41) != 0) 3407 printf("EEK! no clientid from session\n"); 3408 nd->nd_flag |= ND_IMPLIEDCLID; 3409 nd->nd_clientid.qval = clientid.qval; 3410 } 3411 nd->nd_repstat = nfsrv_delegupdate(nd, clientid, NULL, NULL, 3412 NFSV4OP_DELEGPURGE, nd->nd_cred, p, NULL); 3413 nfsmout: 3414 NFSEXITCODE2(error, nd); 3415 return (error); 3416 } 3417 3418 /* 3419 * nfsv4 delegreturn service 3420 */ 3421 int 3422 nfsrvd_delegreturn(struct nfsrv_descript *nd, __unused int isdgram, 3423 vnode_t vp, __unused struct nfsexstuff *exp) 3424 { 3425 u_int32_t *tl; 3426 int error = 0, writeacc; 3427 nfsv4stateid_t stateid; 3428 nfsquad_t clientid; 3429 struct nfsvattr na; 3430 struct thread *p = curthread; 3431 3432 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID); 3433 stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 3434 NFSBCOPY((caddr_t)tl, (caddr_t)stateid.other, NFSX_STATEIDOTHER); 3435 clientid.lval[0] = stateid.other[0]; 3436 clientid.lval[1] = stateid.other[1]; 3437 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 3438 if ((nd->nd_flag & ND_NFSV41) != 0) 3439 clientid.qval = nd->nd_clientid.qval; 3440 else if (nd->nd_clientid.qval != clientid.qval) 3441 printf("EEK10 multiple clids\n"); 3442 } else { 3443 if ((nd->nd_flag & ND_NFSV41) != 0) 3444 printf("EEK! no clientid from session\n"); 3445 nd->nd_flag |= ND_IMPLIEDCLID; 3446 nd->nd_clientid.qval = clientid.qval; 3447 } 3448 nd->nd_repstat = nfsrv_delegupdate(nd, clientid, &stateid, vp, 3449 NFSV4OP_DELEGRETURN, nd->nd_cred, p, &writeacc); 3450 /* For pNFS, update the attributes. */ 3451 if (writeacc != 0 || nfsrv_pnfsatime != 0) 3452 nfsrv_updatemdsattr(vp, &na, p); 3453 nfsmout: 3454 vput(vp); 3455 NFSEXITCODE2(error, nd); 3456 return (error); 3457 } 3458 3459 /* 3460 * nfsv4 get file handle service 3461 */ 3462 int 3463 nfsrvd_getfh(struct nfsrv_descript *nd, __unused int isdgram, 3464 vnode_t vp, __unused struct nfsexstuff *exp) 3465 { 3466 fhandle_t fh; 3467 struct thread *p = curthread; 3468 3469 nd->nd_repstat = nfsvno_getfh(vp, &fh, p); 3470 vput(vp); 3471 if (!nd->nd_repstat) 3472 (void)nfsm_fhtom(NULL, nd, (u_int8_t *)&fh, 0, 0); 3473 NFSEXITCODE2(0, nd); 3474 return (0); 3475 } 3476 3477 /* 3478 * nfsv4 open confirm service 3479 */ 3480 int 3481 nfsrvd_openconfirm(struct nfsrv_descript *nd, __unused int isdgram, 3482 vnode_t vp, __unused struct nfsexstuff *exp) 3483 { 3484 u_int32_t *tl; 3485 struct nfsstate st, *stp = &st; 3486 int error = 0; 3487 nfsv4stateid_t stateid; 3488 nfsquad_t clientid; 3489 struct thread *p = curthread; 3490 3491 if ((nd->nd_flag & ND_NFSV41) != 0) { 3492 nd->nd_repstat = NFSERR_NOTSUPP; 3493 goto nfsmout; 3494 } 3495 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED); 3496 stp->ls_ownerlen = 0; 3497 stp->ls_op = nd->nd_rp; 3498 stp->ls_uid = nd->nd_cred->cr_uid; 3499 stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 3500 NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, 3501 NFSX_STATEIDOTHER); 3502 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 3503 stp->ls_seq = fxdr_unsigned(u_int32_t, *tl); 3504 stp->ls_flags = NFSLCK_CONFIRM; 3505 clientid.lval[0] = stp->ls_stateid.other[0]; 3506 clientid.lval[1] = stp->ls_stateid.other[1]; 3507 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 3508 if ((nd->nd_flag & ND_NFSV41) != 0) 3509 clientid.qval = nd->nd_clientid.qval; 3510 else if (nd->nd_clientid.qval != clientid.qval) 3511 printf("EEK11 multiple clids\n"); 3512 } else { 3513 if ((nd->nd_flag & ND_NFSV41) != 0) 3514 printf("EEK! no clientid from session\n"); 3515 nd->nd_flag |= ND_IMPLIEDCLID; 3516 nd->nd_clientid.qval = clientid.qval; 3517 } 3518 nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p, 3519 NULL); 3520 if (!nd->nd_repstat) { 3521 NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID); 3522 *tl++ = txdr_unsigned(stateid.seqid); 3523 NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); 3524 } 3525 nfsmout: 3526 vput(vp); 3527 NFSEXITCODE2(error, nd); 3528 return (error); 3529 } 3530 3531 /* 3532 * nfsv4 open downgrade service 3533 */ 3534 int 3535 nfsrvd_opendowngrade(struct nfsrv_descript *nd, __unused int isdgram, 3536 vnode_t vp, __unused struct nfsexstuff *exp) 3537 { 3538 u_int32_t *tl; 3539 int i; 3540 struct nfsstate st, *stp = &st; 3541 int error = 0; 3542 nfsv4stateid_t stateid; 3543 nfsquad_t clientid; 3544 struct thread *p = curthread; 3545 3546 /* opendowngrade can only work on a file object.*/ 3547 if (vp->v_type != VREG) { 3548 error = NFSERR_INVAL; 3549 goto nfsmout; 3550 } 3551 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 3 * NFSX_UNSIGNED); 3552 stp->ls_ownerlen = 0; 3553 stp->ls_op = nd->nd_rp; 3554 stp->ls_uid = nd->nd_cred->cr_uid; 3555 stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 3556 NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, 3557 NFSX_STATEIDOTHER); 3558 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 3559 3560 /* 3561 * For the special stateid of other all 0s and seqid == 1, set the 3562 * stateid to the current stateid, if it is set. 3563 */ 3564 if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 && 3565 stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 && 3566 stp->ls_stateid.other[2] == 0) { 3567 if ((nd->nd_flag & ND_CURSTATEID) != 0) 3568 stp->ls_stateid = nd->nd_curstateid; 3569 else { 3570 nd->nd_repstat = NFSERR_BADSTATEID; 3571 goto nfsmout; 3572 } 3573 } 3574 3575 stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++); 3576 i = fxdr_unsigned(int, *tl++); 3577 if ((nd->nd_flag & ND_NFSV41) != 0) 3578 i &= ~NFSV4OPEN_WANTDELEGMASK; 3579 switch (i) { 3580 case NFSV4OPEN_ACCESSREAD: 3581 stp->ls_flags = (NFSLCK_READACCESS | NFSLCK_DOWNGRADE); 3582 break; 3583 case NFSV4OPEN_ACCESSWRITE: 3584 stp->ls_flags = (NFSLCK_WRITEACCESS | NFSLCK_DOWNGRADE); 3585 break; 3586 case NFSV4OPEN_ACCESSBOTH: 3587 stp->ls_flags = (NFSLCK_READACCESS | NFSLCK_WRITEACCESS | 3588 NFSLCK_DOWNGRADE); 3589 break; 3590 default: 3591 nd->nd_repstat = NFSERR_INVAL; 3592 } 3593 i = fxdr_unsigned(int, *tl); 3594 switch (i) { 3595 case NFSV4OPEN_DENYNONE: 3596 break; 3597 case NFSV4OPEN_DENYREAD: 3598 stp->ls_flags |= NFSLCK_READDENY; 3599 break; 3600 case NFSV4OPEN_DENYWRITE: 3601 stp->ls_flags |= NFSLCK_WRITEDENY; 3602 break; 3603 case NFSV4OPEN_DENYBOTH: 3604 stp->ls_flags |= (NFSLCK_READDENY | NFSLCK_WRITEDENY); 3605 break; 3606 default: 3607 nd->nd_repstat = NFSERR_INVAL; 3608 } 3609 3610 clientid.lval[0] = stp->ls_stateid.other[0]; 3611 clientid.lval[1] = stp->ls_stateid.other[1]; 3612 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 3613 if ((nd->nd_flag & ND_NFSV41) != 0) 3614 clientid.qval = nd->nd_clientid.qval; 3615 else if (nd->nd_clientid.qval != clientid.qval) 3616 printf("EEK12 multiple clids\n"); 3617 } else { 3618 if ((nd->nd_flag & ND_NFSV41) != 0) 3619 printf("EEK! no clientid from session\n"); 3620 nd->nd_flag |= ND_IMPLIEDCLID; 3621 nd->nd_clientid.qval = clientid.qval; 3622 } 3623 if (!nd->nd_repstat) 3624 nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, 3625 nd, p, NULL); 3626 if (!nd->nd_repstat) { 3627 /* For NFSv4.1, set the Current StateID. */ 3628 if ((nd->nd_flag & ND_NFSV41) != 0) { 3629 nd->nd_curstateid = stateid; 3630 nd->nd_flag |= ND_CURSTATEID; 3631 } 3632 NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID); 3633 *tl++ = txdr_unsigned(stateid.seqid); 3634 NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); 3635 } 3636 nfsmout: 3637 vput(vp); 3638 NFSEXITCODE2(error, nd); 3639 return (error); 3640 } 3641 3642 /* 3643 * nfsv4 renew lease service 3644 */ 3645 int 3646 nfsrvd_renew(struct nfsrv_descript *nd, __unused int isdgram, 3647 __unused vnode_t vp, __unused struct nfsexstuff *exp) 3648 { 3649 u_int32_t *tl; 3650 int error = 0; 3651 nfsquad_t clientid; 3652 struct thread *p = curthread; 3653 3654 if ((nd->nd_flag & ND_NFSV41) != 0) { 3655 nd->nd_repstat = NFSERR_NOTSUPP; 3656 goto nfsmout; 3657 } 3658 if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0) 3659 goto nfsmout; 3660 NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER); 3661 clientid.lval[0] = *tl++; 3662 clientid.lval[1] = *tl; 3663 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 3664 if ((nd->nd_flag & ND_NFSV41) != 0) 3665 clientid.qval = nd->nd_clientid.qval; 3666 else if (nd->nd_clientid.qval != clientid.qval) 3667 printf("EEK13 multiple clids\n"); 3668 } else { 3669 if ((nd->nd_flag & ND_NFSV41) != 0) 3670 printf("EEK! no clientid from session\n"); 3671 nd->nd_flag |= ND_IMPLIEDCLID; 3672 nd->nd_clientid.qval = clientid.qval; 3673 } 3674 nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_RENEWOP|CLOPS_RENEW), 3675 NULL, NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p); 3676 nfsmout: 3677 NFSEXITCODE2(error, nd); 3678 return (error); 3679 } 3680 3681 /* 3682 * nfsv4 security info service 3683 */ 3684 int 3685 nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram, 3686 vnode_t dp, struct nfsexstuff *exp) 3687 { 3688 u_int32_t *tl; 3689 int len; 3690 struct nameidata named; 3691 vnode_t dirp = NULL, vp; 3692 struct nfsrvfh fh; 3693 struct nfsexstuff retnes; 3694 u_int32_t *sizp; 3695 int error = 0, i; 3696 uint64_t savflag; 3697 char *bufp; 3698 u_long *hashp; 3699 struct thread *p = curthread; 3700 3701 /* 3702 * All this just to get the export flags for the name. 3703 */ 3704 NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP, 3705 LOCKLEAF); 3706 nfsvno_setpathbuf(&named, &bufp, &hashp); 3707 error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 3708 if (error) { 3709 vput(dp); 3710 nfsvno_relpathbuf(&named); 3711 goto out; 3712 } 3713 if (!nd->nd_repstat) { 3714 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, &dirp); 3715 } else { 3716 vput(dp); 3717 nfsvno_relpathbuf(&named); 3718 } 3719 if (dirp) 3720 vrele(dirp); 3721 if (nd->nd_repstat) 3722 goto out; 3723 nfsvno_relpathbuf(&named); 3724 fh.nfsrvfh_len = NFSX_MYFH; 3725 vp = named.ni_vp; 3726 nd->nd_repstat = nfsvno_getfh(vp, (fhandle_t *)fh.nfsrvfh_data, p); 3727 vput(vp); 3728 savflag = nd->nd_flag; 3729 if (!nd->nd_repstat) { 3730 /* 3731 * Pretend the next op is Secinfo, so that no wrongsec 3732 * test will be done. 3733 */ 3734 nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, NULL, 0, 3735 NFSV4OP_SECINFO); 3736 if (vp) 3737 vput(vp); 3738 } 3739 nd->nd_flag = savflag; 3740 if (nd->nd_repstat) 3741 goto out; 3742 3743 /* 3744 * Finally have the export flags for name, so we can create 3745 * the security info. 3746 */ 3747 len = 0; 3748 NFSM_BUILD(sizp, u_int32_t *, NFSX_UNSIGNED); 3749 3750 /* If nes_numsecflavor == 0, all are allowed. */ 3751 if (retnes.nes_numsecflavor == 0) { 3752 NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED); 3753 *tl++ = txdr_unsigned(RPCAUTH_UNIX); 3754 *tl = txdr_unsigned(RPCAUTH_GSS); 3755 nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3756 nfsgss_mechlist[KERBV_MECH].len); 3757 NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED); 3758 *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3759 *tl++ = txdr_unsigned(RPCAUTHGSS_SVCNONE); 3760 *tl = txdr_unsigned(RPCAUTH_GSS); 3761 nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3762 nfsgss_mechlist[KERBV_MECH].len); 3763 NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED); 3764 *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3765 *tl++ = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY); 3766 *tl = txdr_unsigned(RPCAUTH_GSS); 3767 nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3768 nfsgss_mechlist[KERBV_MECH].len); 3769 NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED); 3770 *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3771 *tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY); 3772 len = 4; 3773 } 3774 for (i = 0; i < retnes.nes_numsecflavor; i++) { 3775 if (retnes.nes_secflavors[i] == AUTH_SYS) { 3776 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 3777 *tl = txdr_unsigned(RPCAUTH_UNIX); 3778 len++; 3779 } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5) { 3780 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 3781 *tl++ = txdr_unsigned(RPCAUTH_GSS); 3782 (void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3783 nfsgss_mechlist[KERBV_MECH].len); 3784 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3785 *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3786 *tl = txdr_unsigned(RPCAUTHGSS_SVCNONE); 3787 len++; 3788 } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5I) { 3789 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 3790 *tl++ = txdr_unsigned(RPCAUTH_GSS); 3791 (void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3792 nfsgss_mechlist[KERBV_MECH].len); 3793 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3794 *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3795 *tl = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY); 3796 len++; 3797 } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5P) { 3798 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 3799 *tl++ = txdr_unsigned(RPCAUTH_GSS); 3800 (void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3801 nfsgss_mechlist[KERBV_MECH].len); 3802 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3803 *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3804 *tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY); 3805 len++; 3806 } 3807 } 3808 *sizp = txdr_unsigned(len); 3809 3810 out: 3811 NFSEXITCODE2(error, nd); 3812 return (error); 3813 } 3814 3815 /* 3816 * nfsv4 security info no name service 3817 */ 3818 int 3819 nfsrvd_secinfononame(struct nfsrv_descript *nd, int isdgram, 3820 vnode_t dp, struct nfsexstuff *exp) 3821 { 3822 uint32_t *tl, *sizp; 3823 struct nameidata named; 3824 vnode_t dirp = NULL, vp; 3825 struct nfsrvfh fh; 3826 struct nfsexstuff retnes; 3827 int error = 0, fhstyle, i, len; 3828 uint64_t savflag; 3829 char *bufp; 3830 u_long *hashp; 3831 struct thread *p = curthread; 3832 3833 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 3834 fhstyle = fxdr_unsigned(int, *tl); 3835 switch (fhstyle) { 3836 case NFSSECINFONONAME_PARENT: 3837 if (dp->v_type != VDIR) { 3838 vput(dp); 3839 nd->nd_repstat = NFSERR_NOTDIR; 3840 goto nfsmout; 3841 } 3842 NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP, 3843 LOCKLEAF); 3844 nfsvno_setpathbuf(&named, &bufp, &hashp); 3845 error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 3846 if (error != 0) { 3847 vput(dp); 3848 nfsvno_relpathbuf(&named); 3849 goto nfsmout; 3850 } 3851 if (nd->nd_repstat == 0) 3852 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, &dirp); 3853 else 3854 vput(dp); 3855 if (dirp != NULL) 3856 vrele(dirp); 3857 nfsvno_relpathbuf(&named); 3858 vp = named.ni_vp; 3859 break; 3860 case NFSSECINFONONAME_CURFH: 3861 vp = dp; 3862 break; 3863 default: 3864 nd->nd_repstat = NFSERR_INVAL; 3865 vput(dp); 3866 } 3867 if (nd->nd_repstat != 0) 3868 goto nfsmout; 3869 fh.nfsrvfh_len = NFSX_MYFH; 3870 nd->nd_repstat = nfsvno_getfh(vp, (fhandle_t *)fh.nfsrvfh_data, p); 3871 vput(vp); 3872 savflag = nd->nd_flag; 3873 if (nd->nd_repstat == 0) { 3874 /* 3875 * Pretend the next op is Secinfo, so that no wrongsec 3876 * test will be done. 3877 */ 3878 nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, NULL, 0, 3879 NFSV4OP_SECINFO); 3880 if (vp != NULL) 3881 vput(vp); 3882 } 3883 nd->nd_flag = savflag; 3884 if (nd->nd_repstat != 0) 3885 goto nfsmout; 3886 3887 /* 3888 * Finally have the export flags for fh/parent, so we can create 3889 * the security info. 3890 */ 3891 len = 0; 3892 NFSM_BUILD(sizp, uint32_t *, NFSX_UNSIGNED); 3893 3894 /* If nes_numsecflavor == 0, all are allowed. */ 3895 if (retnes.nes_numsecflavor == 0) { 3896 NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED); 3897 *tl++ = txdr_unsigned(RPCAUTH_UNIX); 3898 *tl = txdr_unsigned(RPCAUTH_GSS); 3899 nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3900 nfsgss_mechlist[KERBV_MECH].len); 3901 NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED); 3902 *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3903 *tl++ = txdr_unsigned(RPCAUTHGSS_SVCNONE); 3904 *tl = txdr_unsigned(RPCAUTH_GSS); 3905 nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3906 nfsgss_mechlist[KERBV_MECH].len); 3907 NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED); 3908 *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3909 *tl++ = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY); 3910 *tl = txdr_unsigned(RPCAUTH_GSS); 3911 nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3912 nfsgss_mechlist[KERBV_MECH].len); 3913 NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED); 3914 *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3915 *tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY); 3916 len = 4; 3917 } 3918 for (i = 0; i < retnes.nes_numsecflavor; i++) { 3919 if (retnes.nes_secflavors[i] == AUTH_SYS) { 3920 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); 3921 *tl = txdr_unsigned(RPCAUTH_UNIX); 3922 len++; 3923 } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5) { 3924 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); 3925 *tl = txdr_unsigned(RPCAUTH_GSS); 3926 nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3927 nfsgss_mechlist[KERBV_MECH].len); 3928 NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED); 3929 *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3930 *tl = txdr_unsigned(RPCAUTHGSS_SVCNONE); 3931 len++; 3932 } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5I) { 3933 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); 3934 *tl = txdr_unsigned(RPCAUTH_GSS); 3935 nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3936 nfsgss_mechlist[KERBV_MECH].len); 3937 NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED); 3938 *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3939 *tl = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY); 3940 len++; 3941 } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5P) { 3942 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); 3943 *tl = txdr_unsigned(RPCAUTH_GSS); 3944 nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3945 nfsgss_mechlist[KERBV_MECH].len); 3946 NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED); 3947 *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3948 *tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY); 3949 len++; 3950 } 3951 } 3952 *sizp = txdr_unsigned(len); 3953 3954 nfsmout: 3955 NFSEXITCODE2(error, nd); 3956 return (error); 3957 } 3958 3959 /* 3960 * nfsv4 set client id service 3961 */ 3962 int 3963 nfsrvd_setclientid(struct nfsrv_descript *nd, __unused int isdgram, 3964 __unused vnode_t vp, __unused struct nfsexstuff *exp) 3965 { 3966 u_int32_t *tl; 3967 int i; 3968 int error = 0, idlen; 3969 struct nfsclient *clp = NULL; 3970 #ifdef INET 3971 struct sockaddr_in *rin; 3972 #endif 3973 #ifdef INET6 3974 struct sockaddr_in6 *rin6; 3975 #endif 3976 #if defined(INET) || defined(INET6) 3977 u_char *ucp, *ucp2; 3978 #endif 3979 u_char *verf, *addrbuf; 3980 nfsquad_t clientid, confirm; 3981 struct thread *p = curthread; 3982 3983 if ((nd->nd_flag & ND_NFSV41) != 0) { 3984 nd->nd_repstat = NFSERR_NOTSUPP; 3985 goto nfsmout; 3986 } 3987 if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0) 3988 goto out; 3989 NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED); 3990 verf = (u_char *)tl; 3991 tl += (NFSX_VERF / NFSX_UNSIGNED); 3992 i = fxdr_unsigned(int, *tl); 3993 if (i > NFSV4_OPAQUELIMIT || i <= 0) { 3994 nd->nd_repstat = NFSERR_BADXDR; 3995 goto nfsmout; 3996 } 3997 idlen = i; 3998 if (nd->nd_flag & ND_GSS) 3999 i += nd->nd_princlen; 4000 clp = malloc(sizeof(struct nfsclient) + i, M_NFSDCLIENT, M_WAITOK | 4001 M_ZERO); 4002 clp->lc_stateid = malloc(sizeof(struct nfsstatehead) * 4003 nfsrv_statehashsize, M_NFSDCLIENT, M_WAITOK); 4004 NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx); 4005 /* Allocated large enough for an AF_INET or AF_INET6 socket. */ 4006 clp->lc_req.nr_nam = malloc(sizeof(struct sockaddr_in6), M_SONAME, 4007 M_WAITOK | M_ZERO); 4008 clp->lc_req.nr_cred = NULL; 4009 NFSBCOPY(verf, clp->lc_verf, NFSX_VERF); 4010 clp->lc_idlen = idlen; 4011 error = nfsrv_mtostr(nd, clp->lc_id, idlen); 4012 if (error) 4013 goto nfsmout; 4014 if (nd->nd_flag & ND_GSS) { 4015 clp->lc_flags = LCL_GSS; 4016 if (nd->nd_flag & ND_GSSINTEGRITY) 4017 clp->lc_flags |= LCL_GSSINTEGRITY; 4018 else if (nd->nd_flag & ND_GSSPRIVACY) 4019 clp->lc_flags |= LCL_GSSPRIVACY; 4020 } else { 4021 clp->lc_flags = 0; 4022 } 4023 if ((nd->nd_flag & ND_GSS) && nd->nd_princlen > 0) { 4024 clp->lc_flags |= LCL_NAME; 4025 clp->lc_namelen = nd->nd_princlen; 4026 clp->lc_name = &clp->lc_id[idlen]; 4027 NFSBCOPY(nd->nd_principal, clp->lc_name, clp->lc_namelen); 4028 } else { 4029 clp->lc_uid = nd->nd_cred->cr_uid; 4030 clp->lc_gid = nd->nd_cred->cr_gid; 4031 } 4032 4033 /* If the client is using TLS, do so for the callback connection. */ 4034 if (nd->nd_flag & ND_TLS) 4035 clp->lc_flags |= LCL_TLSCB; 4036 4037 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 4038 clp->lc_program = fxdr_unsigned(u_int32_t, *tl); 4039 error = nfsrv_getclientipaddr(nd, clp); 4040 if (error) 4041 goto nfsmout; 4042 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 4043 clp->lc_callback = fxdr_unsigned(u_int32_t, *tl); 4044 4045 /* 4046 * nfsrv_setclient() does the actual work of adding it to the 4047 * client list. If there is no error, the structure has been 4048 * linked into the client list and clp should no longer be used 4049 * here. When an error is returned, it has not been linked in, 4050 * so it should be free'd. 4051 */ 4052 nd->nd_repstat = nfsrv_setclient(nd, &clp, &clientid, &confirm, p); 4053 if (nd->nd_repstat == NFSERR_CLIDINUSE) { 4054 /* 4055 * 8 is the maximum length of the port# string. 4056 */ 4057 addrbuf = malloc(INET6_ADDRSTRLEN + 8, M_TEMP, M_WAITOK); 4058 switch (clp->lc_req.nr_nam->sa_family) { 4059 #ifdef INET 4060 case AF_INET: 4061 if (clp->lc_flags & LCL_TCPCALLBACK) 4062 (void) nfsm_strtom(nd, "tcp", 3); 4063 else 4064 (void) nfsm_strtom(nd, "udp", 3); 4065 rin = (struct sockaddr_in *)clp->lc_req.nr_nam; 4066 ucp = (u_char *)&rin->sin_addr.s_addr; 4067 ucp2 = (u_char *)&rin->sin_port; 4068 sprintf(addrbuf, "%d.%d.%d.%d.%d.%d", ucp[0] & 0xff, 4069 ucp[1] & 0xff, ucp[2] & 0xff, ucp[3] & 0xff, 4070 ucp2[0] & 0xff, ucp2[1] & 0xff); 4071 break; 4072 #endif 4073 #ifdef INET6 4074 case AF_INET6: 4075 if (clp->lc_flags & LCL_TCPCALLBACK) 4076 (void) nfsm_strtom(nd, "tcp6", 4); 4077 else 4078 (void) nfsm_strtom(nd, "udp6", 4); 4079 rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam; 4080 ucp = inet_ntop(AF_INET6, &rin6->sin6_addr, addrbuf, 4081 INET6_ADDRSTRLEN); 4082 if (ucp != NULL) 4083 i = strlen(ucp); 4084 else 4085 i = 0; 4086 ucp2 = (u_char *)&rin6->sin6_port; 4087 sprintf(&addrbuf[i], ".%d.%d", ucp2[0] & 0xff, 4088 ucp2[1] & 0xff); 4089 break; 4090 #endif 4091 } 4092 (void) nfsm_strtom(nd, addrbuf, strlen(addrbuf)); 4093 free(addrbuf, M_TEMP); 4094 } 4095 if (clp) { 4096 free(clp->lc_req.nr_nam, M_SONAME); 4097 NFSFREEMUTEX(&clp->lc_req.nr_mtx); 4098 free(clp->lc_stateid, M_NFSDCLIENT); 4099 free(clp, M_NFSDCLIENT); 4100 } 4101 if (!nd->nd_repstat) { 4102 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_HYPER); 4103 *tl++ = clientid.lval[0]; 4104 *tl++ = clientid.lval[1]; 4105 *tl++ = confirm.lval[0]; 4106 *tl = confirm.lval[1]; 4107 } 4108 4109 out: 4110 NFSEXITCODE2(0, nd); 4111 return (0); 4112 nfsmout: 4113 if (clp) { 4114 free(clp->lc_req.nr_nam, M_SONAME); 4115 NFSFREEMUTEX(&clp->lc_req.nr_mtx); 4116 free(clp->lc_stateid, M_NFSDCLIENT); 4117 free(clp, M_NFSDCLIENT); 4118 } 4119 NFSEXITCODE2(error, nd); 4120 return (error); 4121 } 4122 4123 /* 4124 * nfsv4 set client id confirm service 4125 */ 4126 int 4127 nfsrvd_setclientidcfrm(struct nfsrv_descript *nd, 4128 __unused int isdgram, __unused vnode_t vp, 4129 __unused struct nfsexstuff *exp) 4130 { 4131 u_int32_t *tl; 4132 int error = 0; 4133 nfsquad_t clientid, confirm; 4134 struct thread *p = curthread; 4135 4136 if ((nd->nd_flag & ND_NFSV41) != 0) { 4137 nd->nd_repstat = NFSERR_NOTSUPP; 4138 goto nfsmout; 4139 } 4140 if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0) 4141 goto nfsmout; 4142 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_HYPER); 4143 clientid.lval[0] = *tl++; 4144 clientid.lval[1] = *tl++; 4145 confirm.lval[0] = *tl++; 4146 confirm.lval[1] = *tl; 4147 4148 /* 4149 * nfsrv_getclient() searches the client list for a match and 4150 * returns the appropriate NFSERR status. 4151 */ 4152 nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_CONFIRM|CLOPS_RENEW), 4153 NULL, NULL, confirm, 0, nd, p); 4154 nfsmout: 4155 NFSEXITCODE2(error, nd); 4156 return (error); 4157 } 4158 4159 /* 4160 * nfsv4 verify service 4161 */ 4162 int 4163 nfsrvd_verify(struct nfsrv_descript *nd, int isdgram, 4164 vnode_t vp, __unused struct nfsexstuff *exp) 4165 { 4166 int error = 0, ret, fhsize = NFSX_MYFH; 4167 struct nfsvattr nva; 4168 struct statfs *sf; 4169 struct nfsfsinfo fs; 4170 fhandle_t fh; 4171 struct thread *p = curthread; 4172 4173 sf = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); 4174 nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, NULL); 4175 if (!nd->nd_repstat) 4176 nd->nd_repstat = nfsvno_statfs(vp, sf); 4177 if (!nd->nd_repstat) 4178 nd->nd_repstat = nfsvno_getfh(vp, &fh, p); 4179 if (!nd->nd_repstat) { 4180 nfsvno_getfs(&fs, isdgram); 4181 error = nfsv4_loadattr(nd, vp, &nva, NULL, &fh, fhsize, NULL, 4182 sf, NULL, &fs, NULL, 1, &ret, NULL, NULL, p, nd->nd_cred); 4183 if (!error) { 4184 if (nd->nd_procnum == NFSV4OP_NVERIFY) { 4185 if (ret == 0) 4186 nd->nd_repstat = NFSERR_SAME; 4187 else if (ret != NFSERR_NOTSAME) 4188 nd->nd_repstat = ret; 4189 } else if (ret) 4190 nd->nd_repstat = ret; 4191 } 4192 } 4193 vput(vp); 4194 free(sf, M_STATFS); 4195 NFSEXITCODE2(error, nd); 4196 return (error); 4197 } 4198 4199 /* 4200 * nfs openattr rpc 4201 */ 4202 int 4203 nfsrvd_openattr(struct nfsrv_descript *nd, __unused int isdgram, 4204 vnode_t dp, __unused vnode_t *vpp, __unused fhandle_t *fhp, 4205 __unused struct nfsexstuff *exp) 4206 { 4207 u_int32_t *tl; 4208 int error = 0, createdir __unused; 4209 4210 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 4211 createdir = fxdr_unsigned(int, *tl); 4212 nd->nd_repstat = NFSERR_NOTSUPP; 4213 nfsmout: 4214 vrele(dp); 4215 NFSEXITCODE2(error, nd); 4216 return (error); 4217 } 4218 4219 /* 4220 * nfsv4 release lock owner service 4221 */ 4222 int 4223 nfsrvd_releaselckown(struct nfsrv_descript *nd, __unused int isdgram, 4224 __unused vnode_t vp, __unused struct nfsexstuff *exp) 4225 { 4226 u_int32_t *tl; 4227 struct nfsstate *stp = NULL; 4228 int error = 0, len; 4229 nfsquad_t clientid; 4230 struct thread *p = curthread; 4231 4232 if ((nd->nd_flag & ND_NFSV41) != 0) { 4233 nd->nd_repstat = NFSERR_NOTSUPP; 4234 goto nfsmout; 4235 } 4236 if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0) 4237 goto nfsmout; 4238 NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 4239 len = fxdr_unsigned(int, *(tl + 2)); 4240 if (len <= 0 || len > NFSV4_OPAQUELIMIT) { 4241 nd->nd_repstat = NFSERR_BADXDR; 4242 goto nfsmout; 4243 } 4244 stp = malloc(sizeof (struct nfsstate) + len, 4245 M_NFSDSTATE, M_WAITOK); 4246 stp->ls_ownerlen = len; 4247 stp->ls_op = NULL; 4248 stp->ls_flags = NFSLCK_RELEASE; 4249 stp->ls_uid = nd->nd_cred->cr_uid; 4250 clientid.lval[0] = *tl++; 4251 clientid.lval[1] = *tl; 4252 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 4253 if ((nd->nd_flag & ND_NFSV41) != 0) 4254 clientid.qval = nd->nd_clientid.qval; 4255 else if (nd->nd_clientid.qval != clientid.qval) 4256 printf("EEK14 multiple clids\n"); 4257 } else { 4258 if ((nd->nd_flag & ND_NFSV41) != 0) 4259 printf("EEK! no clientid from session\n"); 4260 nd->nd_flag |= ND_IMPLIEDCLID; 4261 nd->nd_clientid.qval = clientid.qval; 4262 } 4263 error = nfsrv_mtostr(nd, stp->ls_owner, len); 4264 if (error) 4265 goto nfsmout; 4266 nd->nd_repstat = nfsrv_releaselckown(stp, clientid, p); 4267 free(stp, M_NFSDSTATE); 4268 4269 NFSEXITCODE2(0, nd); 4270 return (0); 4271 nfsmout: 4272 if (stp) 4273 free(stp, M_NFSDSTATE); 4274 NFSEXITCODE2(error, nd); 4275 return (error); 4276 } 4277 4278 /* 4279 * nfsv4 exchange_id service 4280 */ 4281 int 4282 nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused int isdgram, 4283 __unused vnode_t vp, __unused struct nfsexstuff *exp) 4284 { 4285 uint32_t *tl; 4286 int error = 0, i, idlen; 4287 struct nfsclient *clp = NULL; 4288 nfsquad_t clientid, confirm; 4289 uint8_t *verf; 4290 uint32_t sp4type, v41flags; 4291 struct timespec verstime; 4292 nfsopbit_t mustops, allowops; 4293 #ifdef INET 4294 struct sockaddr_in *sin, *rin; 4295 #endif 4296 #ifdef INET6 4297 struct sockaddr_in6 *sin6, *rin6; 4298 #endif 4299 struct thread *p = curthread; 4300 char *s; 4301 4302 if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0) 4303 goto nfsmout; 4304 NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED); 4305 verf = (uint8_t *)tl; 4306 tl += (NFSX_VERF / NFSX_UNSIGNED); 4307 i = fxdr_unsigned(int, *tl); 4308 if (i > NFSV4_OPAQUELIMIT || i <= 0) { 4309 nd->nd_repstat = NFSERR_BADXDR; 4310 goto nfsmout; 4311 } 4312 idlen = i; 4313 if (nd->nd_flag & ND_GSS) 4314 i += nd->nd_princlen; 4315 clp = malloc(sizeof(struct nfsclient) + i, M_NFSDCLIENT, M_WAITOK | 4316 M_ZERO); 4317 clp->lc_stateid = malloc(sizeof(struct nfsstatehead) * 4318 nfsrv_statehashsize, M_NFSDCLIENT, M_WAITOK); 4319 NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx); 4320 /* Allocated large enough for an AF_INET or AF_INET6 socket. */ 4321 clp->lc_req.nr_nam = malloc(sizeof(struct sockaddr_in6), M_SONAME, 4322 M_WAITOK | M_ZERO); 4323 switch (nd->nd_nam->sa_family) { 4324 #ifdef INET 4325 case AF_INET: 4326 rin = (struct sockaddr_in *)clp->lc_req.nr_nam; 4327 sin = (struct sockaddr_in *)nd->nd_nam; 4328 rin->sin_family = AF_INET; 4329 rin->sin_len = sizeof(struct sockaddr_in); 4330 rin->sin_port = 0; 4331 rin->sin_addr.s_addr = sin->sin_addr.s_addr; 4332 break; 4333 #endif 4334 #ifdef INET6 4335 case AF_INET6: 4336 rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam; 4337 sin6 = (struct sockaddr_in6 *)nd->nd_nam; 4338 rin6->sin6_family = AF_INET6; 4339 rin6->sin6_len = sizeof(struct sockaddr_in6); 4340 rin6->sin6_port = 0; 4341 rin6->sin6_addr = sin6->sin6_addr; 4342 break; 4343 #endif 4344 } 4345 clp->lc_req.nr_cred = NULL; 4346 NFSBCOPY(verf, clp->lc_verf, NFSX_VERF); 4347 clp->lc_idlen = idlen; 4348 error = nfsrv_mtostr(nd, clp->lc_id, idlen); 4349 if (error != 0) 4350 goto nfsmout; 4351 if ((nd->nd_flag & ND_GSS) != 0) { 4352 clp->lc_flags = LCL_GSS | LCL_NFSV41; 4353 if ((nd->nd_flag & ND_GSSINTEGRITY) != 0) 4354 clp->lc_flags |= LCL_GSSINTEGRITY; 4355 else if ((nd->nd_flag & ND_GSSPRIVACY) != 0) 4356 clp->lc_flags |= LCL_GSSPRIVACY; 4357 } else 4358 clp->lc_flags = LCL_NFSV41; 4359 if ((nd->nd_flag & ND_NFSV42) != 0) 4360 clp->lc_flags |= LCL_NFSV42; 4361 if ((nd->nd_flag & ND_GSS) != 0 && nd->nd_princlen > 0) { 4362 clp->lc_flags |= LCL_NAME; 4363 clp->lc_namelen = nd->nd_princlen; 4364 clp->lc_name = &clp->lc_id[idlen]; 4365 NFSBCOPY(nd->nd_principal, clp->lc_name, clp->lc_namelen); 4366 } else { 4367 clp->lc_uid = nd->nd_cred->cr_uid; 4368 clp->lc_gid = nd->nd_cred->cr_gid; 4369 } 4370 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 4371 v41flags = fxdr_unsigned(uint32_t, *tl++); 4372 if ((v41flags & ~(NFSV4EXCH_SUPPMOVEDREFER | NFSV4EXCH_SUPPMOVEDMIGR | 4373 NFSV4EXCH_BINDPRINCSTATEID | NFSV4EXCH_MASKPNFS | 4374 NFSV4EXCH_UPDCONFIRMEDRECA)) != 0) { 4375 nd->nd_repstat = NFSERR_INVAL; 4376 goto nfsmout; 4377 } 4378 if ((v41flags & NFSV4EXCH_UPDCONFIRMEDRECA) != 0) 4379 confirm.lval[1] = 1; 4380 else 4381 confirm.lval[1] = 0; 4382 if (nfsrv_devidcnt == 0) 4383 v41flags = NFSV4EXCH_USENONPNFS | NFSV4EXCH_USEPNFSDS; 4384 else 4385 v41flags = NFSV4EXCH_USEPNFSMDS; 4386 sp4type = fxdr_unsigned(uint32_t, *tl); 4387 if (sp4type == NFSV4EXCH_SP4MACHCRED) { 4388 if ((nd->nd_flag & (ND_GSSINTEGRITY | ND_GSSPRIVACY)) == 0 || 4389 nd->nd_princlen == 0) 4390 nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK); 4391 if (nd->nd_repstat == 0) 4392 nd->nd_repstat = nfsrv_getopbits(nd, &mustops, NULL); 4393 if (nd->nd_repstat == 0) 4394 nd->nd_repstat = nfsrv_getopbits(nd, &allowops, NULL); 4395 if (nd->nd_repstat != 0) 4396 goto nfsmout; 4397 NFSOPBIT_CLRNOTMUST(&mustops); 4398 NFSSET_OPBIT(&clp->lc_mustops, &mustops); 4399 NFSOPBIT_CLRNOTALLOWED(&allowops); 4400 NFSSET_OPBIT(&clp->lc_allowops, &allowops); 4401 clp->lc_flags |= LCL_MACHCRED; 4402 } else if (sp4type != NFSV4EXCH_SP4NONE) { 4403 nd->nd_repstat = NFSERR_NOTSUPP; 4404 goto nfsmout; 4405 } 4406 4407 /* 4408 * nfsrv_setclient() does the actual work of adding it to the 4409 * client list. If there is no error, the structure has been 4410 * linked into the client list and clp should no longer be used 4411 * here. When an error is returned, it has not been linked in, 4412 * so it should be free'd. 4413 */ 4414 nd->nd_repstat = nfsrv_setclient(nd, &clp, &clientid, &confirm, p); 4415 if (clp != NULL) { 4416 free(clp->lc_req.nr_nam, M_SONAME); 4417 NFSFREEMUTEX(&clp->lc_req.nr_mtx); 4418 free(clp->lc_stateid, M_NFSDCLIENT); 4419 free(clp, M_NFSDCLIENT); 4420 } 4421 if (nd->nd_repstat == 0) { 4422 if (confirm.lval[1] != 0) 4423 v41flags |= NFSV4EXCH_CONFIRMEDR; 4424 NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 3 * NFSX_UNSIGNED); 4425 *tl++ = clientid.lval[0]; /* ClientID */ 4426 *tl++ = clientid.lval[1]; 4427 *tl++ = txdr_unsigned(confirm.lval[0]); /* SequenceID */ 4428 *tl++ = txdr_unsigned(v41flags); /* Exch flags */ 4429 *tl = txdr_unsigned(sp4type); /* No SSV */ 4430 if (sp4type == NFSV4EXCH_SP4MACHCRED) { 4431 nfsrv_putopbit(nd, &mustops); 4432 nfsrv_putopbit(nd, &allowops); 4433 } 4434 NFSM_BUILD(tl, uint32_t *, NFSX_HYPER); 4435 txdr_hyper(nfsrv_owner_minor, tl); /* Owner Minor */ 4436 if (nfsrv_owner_major[0] != 0) 4437 s = nfsrv_owner_major; 4438 else 4439 s = nd->nd_cred->cr_prison->pr_hostuuid; 4440 nfsm_strtom(nd, s, strlen(s)); /* Owner Major */ 4441 if (nfsrv_scope[0] != 0) 4442 s = nfsrv_scope; 4443 else 4444 s = nd->nd_cred->cr_prison->pr_hostuuid; 4445 nfsm_strtom(nd, s, strlen(s) ); /* Scope */ 4446 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); 4447 *tl = txdr_unsigned(1); 4448 (void)nfsm_strtom(nd, "freebsd.org", strlen("freebsd.org")); 4449 (void)nfsm_strtom(nd, version, strlen(version)); 4450 NFSM_BUILD(tl, uint32_t *, NFSX_V4TIME); 4451 verstime.tv_sec = 1293840000; /* Jan 1, 2011 */ 4452 verstime.tv_nsec = 0; 4453 txdr_nfsv4time(&verstime, tl); 4454 } 4455 NFSEXITCODE2(0, nd); 4456 return (0); 4457 nfsmout: 4458 if (clp != NULL) { 4459 free(clp->lc_req.nr_nam, M_SONAME); 4460 NFSFREEMUTEX(&clp->lc_req.nr_mtx); 4461 free(clp->lc_stateid, M_NFSDCLIENT); 4462 free(clp, M_NFSDCLIENT); 4463 } 4464 NFSEXITCODE2(error, nd); 4465 return (error); 4466 } 4467 4468 /* 4469 * nfsv4 create session service 4470 */ 4471 int 4472 nfsrvd_createsession(struct nfsrv_descript *nd, __unused int isdgram, 4473 __unused vnode_t vp, __unused struct nfsexstuff *exp) 4474 { 4475 uint32_t *tl; 4476 int error = 0; 4477 nfsquad_t clientid, confirm; 4478 struct nfsdsession *sep = NULL; 4479 uint32_t rdmacnt; 4480 struct thread *p = curthread; 4481 static bool do_printf = true; 4482 4483 if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0) 4484 goto nfsmout; 4485 sep = (struct nfsdsession *)malloc(sizeof(struct nfsdsession), 4486 M_NFSDSESSION, M_WAITOK | M_ZERO); 4487 sep->sess_refcnt = 1; 4488 mtx_init(&sep->sess_cbsess.nfsess_mtx, "nfscbsession", NULL, MTX_DEF); 4489 NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED); 4490 clientid.lval[0] = *tl++; 4491 clientid.lval[1] = *tl++; 4492 confirm.lval[0] = fxdr_unsigned(uint32_t, *tl++); 4493 sep->sess_crflags = fxdr_unsigned(uint32_t, *tl); 4494 /* Persistent sessions and RDMA are not supported. */ 4495 sep->sess_crflags &= NFSV4CRSESS_CONNBACKCHAN; 4496 4497 /* Fore channel attributes. */ 4498 NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED); 4499 tl++; /* Header pad always 0. */ 4500 sep->sess_maxreq = fxdr_unsigned(uint32_t, *tl++); 4501 if (sep->sess_maxreq > sb_max_adj - NFS_MAXXDR) { 4502 sep->sess_maxreq = sb_max_adj - NFS_MAXXDR; 4503 if (do_printf) 4504 printf("Consider increasing kern.ipc.maxsockbuf\n"); 4505 do_printf = false; 4506 } 4507 sep->sess_maxresp = fxdr_unsigned(uint32_t, *tl++); 4508 if (sep->sess_maxresp > sb_max_adj - NFS_MAXXDR) { 4509 sep->sess_maxresp = sb_max_adj - NFS_MAXXDR; 4510 if (do_printf) 4511 printf("Consider increasing kern.ipc.maxsockbuf\n"); 4512 do_printf = false; 4513 } 4514 sep->sess_maxrespcached = fxdr_unsigned(uint32_t, *tl++); 4515 sep->sess_maxops = fxdr_unsigned(uint32_t, *tl++); 4516 sep->sess_maxslots = fxdr_unsigned(uint32_t, *tl++); 4517 if (sep->sess_maxslots > NFSV4_SLOTS) 4518 sep->sess_maxslots = NFSV4_SLOTS; 4519 rdmacnt = fxdr_unsigned(uint32_t, *tl); 4520 if (rdmacnt > 1) { 4521 nd->nd_repstat = NFSERR_BADXDR; 4522 goto nfsmout; 4523 } else if (rdmacnt == 1) 4524 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 4525 4526 /* Back channel attributes. */ 4527 NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED); 4528 tl++; /* Header pad always 0. */ 4529 sep->sess_cbmaxreq = fxdr_unsigned(uint32_t, *tl++); 4530 sep->sess_cbmaxresp = fxdr_unsigned(uint32_t, *tl++); 4531 sep->sess_cbmaxrespcached = fxdr_unsigned(uint32_t, *tl++); 4532 sep->sess_cbmaxops = fxdr_unsigned(uint32_t, *tl++); 4533 sep->sess_cbsess.nfsess_foreslots = fxdr_unsigned(uint32_t, *tl++); 4534 rdmacnt = fxdr_unsigned(uint32_t, *tl); 4535 if (rdmacnt > 1) { 4536 nd->nd_repstat = NFSERR_BADXDR; 4537 goto nfsmout; 4538 } else if (rdmacnt == 1) 4539 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 4540 4541 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 4542 sep->sess_cbprogram = fxdr_unsigned(uint32_t, *tl); 4543 4544 /* 4545 * nfsrv_getclient() searches the client list for a match and 4546 * returns the appropriate NFSERR status. 4547 */ 4548 nd->nd_repstat = nfsrv_getclient(clientid, CLOPS_CONFIRM | CLOPS_RENEW, 4549 NULL, sep, confirm, sep->sess_cbprogram, nd, p); 4550 if (nd->nd_repstat == 0) { 4551 NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID); 4552 NFSBCOPY(sep->sess_sessionid, tl, NFSX_V4SESSIONID); 4553 NFSM_BUILD(tl, uint32_t *, 18 * NFSX_UNSIGNED); 4554 *tl++ = txdr_unsigned(confirm.lval[0]); /* sequenceid */ 4555 *tl++ = txdr_unsigned(sep->sess_crflags); 4556 4557 /* Fore channel attributes. */ 4558 *tl++ = 0; 4559 *tl++ = txdr_unsigned(sep->sess_maxreq); 4560 *tl++ = txdr_unsigned(sep->sess_maxresp); 4561 *tl++ = txdr_unsigned(sep->sess_maxrespcached); 4562 *tl++ = txdr_unsigned(sep->sess_maxops); 4563 *tl++ = txdr_unsigned(sep->sess_maxslots); 4564 *tl++ = txdr_unsigned(1); 4565 *tl++ = txdr_unsigned(0); /* No RDMA. */ 4566 4567 /* Back channel attributes. */ 4568 *tl++ = 0; 4569 *tl++ = txdr_unsigned(sep->sess_cbmaxreq); 4570 *tl++ = txdr_unsigned(sep->sess_cbmaxresp); 4571 *tl++ = txdr_unsigned(sep->sess_cbmaxrespcached); 4572 *tl++ = txdr_unsigned(sep->sess_cbmaxops); 4573 *tl++ = txdr_unsigned(sep->sess_cbsess.nfsess_foreslots); 4574 *tl++ = txdr_unsigned(1); 4575 *tl = txdr_unsigned(0); /* No RDMA. */ 4576 } 4577 nfsmout: 4578 if (nd->nd_repstat != 0 && sep != NULL) 4579 free(sep, M_NFSDSESSION); 4580 NFSEXITCODE2(error, nd); 4581 return (error); 4582 } 4583 4584 /* 4585 * nfsv4 sequence service 4586 */ 4587 int 4588 nfsrvd_sequence(struct nfsrv_descript *nd, __unused int isdgram, 4589 __unused vnode_t vp, __unused struct nfsexstuff *exp) 4590 { 4591 uint32_t *tl; 4592 uint32_t highest_slotid, sequenceid, sflags, target_highest_slotid; 4593 int cache_this, error = 0; 4594 struct thread *p = curthread; 4595 4596 if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0) 4597 goto nfsmout; 4598 NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID); 4599 NFSBCOPY(tl, nd->nd_sessionid, NFSX_V4SESSIONID); 4600 NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED); 4601 sequenceid = fxdr_unsigned(uint32_t, *tl++); 4602 nd->nd_slotid = fxdr_unsigned(uint32_t, *tl++); 4603 highest_slotid = fxdr_unsigned(uint32_t, *tl++); 4604 if (*tl == newnfs_true) 4605 cache_this = 1; 4606 else 4607 cache_this = 0; 4608 nd->nd_repstat = nfsrv_checksequence(nd, sequenceid, &highest_slotid, 4609 &target_highest_slotid, cache_this, &sflags, p); 4610 if (nd->nd_repstat != NFSERR_BADSLOT) 4611 nd->nd_flag |= ND_HASSEQUENCE; 4612 if (nd->nd_repstat == 0) { 4613 NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID); 4614 NFSBCOPY(nd->nd_sessionid, tl, NFSX_V4SESSIONID); 4615 NFSM_BUILD(tl, uint32_t *, 5 * NFSX_UNSIGNED); 4616 *tl++ = txdr_unsigned(sequenceid); 4617 *tl++ = txdr_unsigned(nd->nd_slotid); 4618 *tl++ = txdr_unsigned(highest_slotid); 4619 *tl++ = txdr_unsigned(target_highest_slotid); 4620 *tl = txdr_unsigned(sflags); 4621 } 4622 nfsmout: 4623 NFSEXITCODE2(error, nd); 4624 return (error); 4625 } 4626 4627 /* 4628 * nfsv4 reclaim complete service 4629 */ 4630 int 4631 nfsrvd_reclaimcomplete(struct nfsrv_descript *nd, __unused int isdgram, 4632 __unused vnode_t vp, __unused struct nfsexstuff *exp) 4633 { 4634 uint32_t *tl; 4635 int error = 0, onefs; 4636 4637 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 4638 /* 4639 * I believe that a ReclaimComplete with rca_one_fs == TRUE is only 4640 * to be used after a file system has been transferred to a different 4641 * file server. However, RFC5661 is somewhat vague w.r.t. this and 4642 * the ESXi 6.7 client does both a ReclaimComplete with rca_one_fs 4643 * == TRUE and one with ReclaimComplete with rca_one_fs == FALSE. 4644 * Therefore, just ignore the rca_one_fs == TRUE operation and return 4645 * NFS_OK without doing anything. 4646 */ 4647 onefs = 0; 4648 if (*tl == newnfs_true) 4649 onefs = 1; 4650 nd->nd_repstat = nfsrv_checkreclaimcomplete(nd, onefs); 4651 nfsmout: 4652 NFSEXITCODE2(error, nd); 4653 return (error); 4654 } 4655 4656 /* 4657 * nfsv4 destroy clientid service 4658 */ 4659 int 4660 nfsrvd_destroyclientid(struct nfsrv_descript *nd, __unused int isdgram, 4661 __unused vnode_t vp, __unused struct nfsexstuff *exp) 4662 { 4663 uint32_t *tl; 4664 nfsquad_t clientid; 4665 int error = 0; 4666 struct thread *p = curthread; 4667 4668 if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0) 4669 goto nfsmout; 4670 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); 4671 clientid.lval[0] = *tl++; 4672 clientid.lval[1] = *tl; 4673 nd->nd_repstat = nfsrv_destroyclient(nd, clientid, p); 4674 nfsmout: 4675 NFSEXITCODE2(error, nd); 4676 return (error); 4677 } 4678 4679 /* 4680 * nfsv4 bind connection to session service 4681 */ 4682 int 4683 nfsrvd_bindconnsess(struct nfsrv_descript *nd, __unused int isdgram, 4684 __unused vnode_t vp, __unused struct nfsexstuff *exp) 4685 { 4686 uint32_t *tl; 4687 uint8_t sessid[NFSX_V4SESSIONID]; 4688 int error = 0, foreaft; 4689 4690 if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0) 4691 goto nfsmout; 4692 NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID + 2 * NFSX_UNSIGNED); 4693 NFSBCOPY(tl, sessid, NFSX_V4SESSIONID); 4694 tl += (NFSX_V4SESSIONID / NFSX_UNSIGNED); 4695 foreaft = fxdr_unsigned(int, *tl++); 4696 if (*tl == newnfs_true) { 4697 /* RDMA is not supported. */ 4698 nd->nd_repstat = NFSERR_NOTSUPP; 4699 goto nfsmout; 4700 } 4701 4702 nd->nd_repstat = nfsrv_bindconnsess(nd, sessid, &foreaft); 4703 if (nd->nd_repstat == 0) { 4704 NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 2 * 4705 NFSX_UNSIGNED); 4706 NFSBCOPY(sessid, tl, NFSX_V4SESSIONID); 4707 tl += (NFSX_V4SESSIONID / NFSX_UNSIGNED); 4708 *tl++ = txdr_unsigned(foreaft); 4709 *tl = newnfs_false; 4710 } 4711 nfsmout: 4712 NFSEXITCODE2(error, nd); 4713 return (error); 4714 } 4715 4716 /* 4717 * nfsv4 destroy session service 4718 */ 4719 int 4720 nfsrvd_destroysession(struct nfsrv_descript *nd, __unused int isdgram, 4721 __unused vnode_t vp, __unused struct nfsexstuff *exp) 4722 { 4723 uint8_t *cp, sessid[NFSX_V4SESSIONID]; 4724 int error = 0; 4725 4726 if ((nd->nd_repstat = nfsd_checkrootexp(nd)) != 0) 4727 goto nfsmout; 4728 NFSM_DISSECT(cp, uint8_t *, NFSX_V4SESSIONID); 4729 NFSBCOPY(cp, sessid, NFSX_V4SESSIONID); 4730 nd->nd_repstat = nfsrv_destroysession(nd, sessid); 4731 nfsmout: 4732 NFSEXITCODE2(error, nd); 4733 return (error); 4734 } 4735 4736 /* 4737 * nfsv4 free stateid service 4738 */ 4739 int 4740 nfsrvd_freestateid(struct nfsrv_descript *nd, __unused int isdgram, 4741 __unused vnode_t vp, __unused struct nfsexstuff *exp) 4742 { 4743 uint32_t *tl; 4744 nfsv4stateid_t stateid; 4745 int error = 0; 4746 struct thread *p = curthread; 4747 4748 NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID); 4749 stateid.seqid = fxdr_unsigned(uint32_t, *tl++); 4750 NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER); 4751 4752 /* 4753 * For the special stateid of other all 0s and seqid == 1, set the 4754 * stateid to the current stateid, if it is set. 4755 */ 4756 if (stateid.seqid == 1 && stateid.other[0] == 0 && 4757 stateid.other[1] == 0 && stateid.other[2] == 0) { 4758 if ((nd->nd_flag & ND_CURSTATEID) != 0) { 4759 stateid = nd->nd_curstateid; 4760 stateid.seqid = 0; 4761 } else { 4762 nd->nd_repstat = NFSERR_BADSTATEID; 4763 goto nfsmout; 4764 } 4765 } 4766 4767 nd->nd_repstat = nfsrv_freestateid(nd, &stateid, p); 4768 4769 /* If the current stateid has been free'd, unset it. */ 4770 if (nd->nd_repstat == 0 && (nd->nd_flag & ND_CURSTATEID) != 0 && 4771 stateid.other[0] == nd->nd_curstateid.other[0] && 4772 stateid.other[1] == nd->nd_curstateid.other[1] && 4773 stateid.other[2] == nd->nd_curstateid.other[2]) 4774 nd->nd_flag &= ~ND_CURSTATEID; 4775 nfsmout: 4776 NFSEXITCODE2(error, nd); 4777 return (error); 4778 } 4779 4780 /* 4781 * nfsv4 layoutget service 4782 */ 4783 int 4784 nfsrvd_layoutget(struct nfsrv_descript *nd, __unused int isdgram, 4785 vnode_t vp, struct nfsexstuff *exp) 4786 { 4787 uint32_t *tl; 4788 nfsv4stateid_t stateid; 4789 int error = 0, layoutlen, layouttype, iomode, maxcnt, retonclose; 4790 uint64_t offset, len, minlen; 4791 char *layp; 4792 struct thread *p = curthread; 4793 4794 NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED + 3 * NFSX_HYPER + 4795 NFSX_STATEID); 4796 tl++; /* Signal layout available. Ignore for now. */ 4797 layouttype = fxdr_unsigned(int, *tl++); 4798 iomode = fxdr_unsigned(int, *tl++); 4799 offset = fxdr_hyper(tl); tl += 2; 4800 len = fxdr_hyper(tl); tl += 2; 4801 minlen = fxdr_hyper(tl); tl += 2; 4802 stateid.seqid = fxdr_unsigned(uint32_t, *tl++); 4803 NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER); 4804 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 4805 maxcnt = fxdr_unsigned(int, *tl); 4806 NFSD_DEBUG(4, "layoutget ltyp=%d iom=%d off=%ju len=%ju mlen=%ju\n", 4807 layouttype, iomode, (uintmax_t)offset, (uintmax_t)len, 4808 (uintmax_t)minlen); 4809 if (len < minlen || 4810 (minlen != UINT64_MAX && offset + minlen < offset) || 4811 (len != UINT64_MAX && offset + len < offset)) { 4812 nd->nd_repstat = NFSERR_INVAL; 4813 goto nfsmout; 4814 } 4815 4816 /* 4817 * For the special stateid of other all 0s and seqid == 1, set the 4818 * stateid to the current stateid, if it is set. 4819 */ 4820 if (stateid.seqid == 1 && stateid.other[0] == 0 && 4821 stateid.other[1] == 0 && stateid.other[2] == 0) { 4822 if ((nd->nd_flag & ND_CURSTATEID) != 0) { 4823 stateid = nd->nd_curstateid; 4824 stateid.seqid = 0; 4825 } else { 4826 nd->nd_repstat = NFSERR_BADSTATEID; 4827 goto nfsmout; 4828 } 4829 } 4830 4831 layp = NULL; 4832 if (layouttype == NFSLAYOUT_NFSV4_1_FILES && nfsrv_maxpnfsmirror == 1) 4833 layp = malloc(NFSX_V4FILELAYOUT, M_TEMP, M_WAITOK); 4834 else if (layouttype == NFSLAYOUT_FLEXFILE) 4835 layp = malloc(NFSX_V4FLEXLAYOUT(nfsrv_maxpnfsmirror), M_TEMP, 4836 M_WAITOK); 4837 else 4838 nd->nd_repstat = NFSERR_UNKNLAYOUTTYPE; 4839 if (layp != NULL) 4840 nd->nd_repstat = nfsrv_layoutget(nd, vp, exp, layouttype, 4841 &iomode, &offset, &len, minlen, &stateid, maxcnt, 4842 &retonclose, &layoutlen, layp, nd->nd_cred, p); 4843 NFSD_DEBUG(4, "nfsrv_layoutget stat=%u layoutlen=%d\n", nd->nd_repstat, 4844 layoutlen); 4845 if (nd->nd_repstat == 0) { 4846 /* For NFSv4.1, set the Current StateID. */ 4847 if ((nd->nd_flag & ND_NFSV41) != 0) { 4848 nd->nd_curstateid = stateid; 4849 nd->nd_flag |= ND_CURSTATEID; 4850 } 4851 NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + NFSX_STATEID + 4852 2 * NFSX_HYPER); 4853 *tl++ = txdr_unsigned(retonclose); 4854 *tl++ = txdr_unsigned(stateid.seqid); 4855 NFSBCOPY(stateid.other, tl, NFSX_STATEIDOTHER); 4856 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 4857 *tl++ = txdr_unsigned(1); /* Only returns one layout. */ 4858 txdr_hyper(offset, tl); tl += 2; 4859 txdr_hyper(len, tl); tl += 2; 4860 *tl++ = txdr_unsigned(iomode); 4861 *tl = txdr_unsigned(layouttype); 4862 nfsm_strtom(nd, layp, layoutlen); 4863 } else if (nd->nd_repstat == NFSERR_LAYOUTTRYLATER) { 4864 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); 4865 *tl = newnfs_false; 4866 } 4867 free(layp, M_TEMP); 4868 nfsmout: 4869 vput(vp); 4870 NFSEXITCODE2(error, nd); 4871 return (error); 4872 } 4873 4874 /* 4875 * nfsv4 layoutcommit service 4876 */ 4877 int 4878 nfsrvd_layoutcommit(struct nfsrv_descript *nd, __unused int isdgram, 4879 vnode_t vp, struct nfsexstuff *exp) 4880 { 4881 uint32_t *tl; 4882 nfsv4stateid_t stateid; 4883 int error = 0, hasnewoff, hasnewmtime, layouttype, maxcnt, reclaim; 4884 int hasnewsize; 4885 uint64_t offset, len, newoff = 0, newsize; 4886 struct timespec newmtime; 4887 char *layp; 4888 struct thread *p = curthread; 4889 4890 layp = NULL; 4891 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + 2 * NFSX_HYPER + 4892 NFSX_STATEID); 4893 offset = fxdr_hyper(tl); tl += 2; 4894 len = fxdr_hyper(tl); tl += 2; 4895 reclaim = fxdr_unsigned(int, *tl++); 4896 stateid.seqid = fxdr_unsigned(uint32_t, *tl++); 4897 NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER); 4898 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 4899 /* 4900 * For the special stateid of other all 0s and seqid == 1, set the 4901 * stateid to the current stateid, if it is set. 4902 */ 4903 if (stateid.seqid == 1 && stateid.other[0] == 0 && 4904 stateid.other[1] == 0 && stateid.other[2] == 0) { 4905 if ((nd->nd_flag & ND_CURSTATEID) != 0) { 4906 stateid = nd->nd_curstateid; 4907 stateid.seqid = 0; 4908 } else { 4909 nd->nd_repstat = NFSERR_BADSTATEID; 4910 goto nfsmout; 4911 } 4912 } 4913 4914 hasnewoff = fxdr_unsigned(int, *tl); 4915 if (hasnewoff != 0) { 4916 NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED); 4917 newoff = fxdr_hyper(tl); tl += 2; 4918 } else 4919 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 4920 hasnewmtime = fxdr_unsigned(int, *tl); 4921 if (hasnewmtime != 0) { 4922 NFSM_DISSECT(tl, uint32_t *, NFSX_V4TIME + 2 * NFSX_UNSIGNED); 4923 fxdr_nfsv4time(tl, &newmtime); 4924 tl += (NFSX_V4TIME / NFSX_UNSIGNED); 4925 } else 4926 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); 4927 layouttype = fxdr_unsigned(int, *tl++); 4928 maxcnt = fxdr_unsigned(int, *tl); 4929 if (maxcnt > 0) { 4930 layp = malloc(maxcnt + 1, M_TEMP, M_WAITOK); 4931 error = nfsrv_mtostr(nd, layp, maxcnt); 4932 if (error != 0) 4933 goto nfsmout; 4934 } 4935 nd->nd_repstat = nfsrv_layoutcommit(nd, vp, layouttype, hasnewoff, 4936 newoff, offset, len, hasnewmtime, &newmtime, reclaim, &stateid, 4937 maxcnt, layp, &hasnewsize, &newsize, nd->nd_cred, p); 4938 NFSD_DEBUG(4, "nfsrv_layoutcommit stat=%u\n", nd->nd_repstat); 4939 if (nd->nd_repstat == 0) { 4940 if (hasnewsize != 0) { 4941 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED + NFSX_HYPER); 4942 *tl++ = newnfs_true; 4943 txdr_hyper(newsize, tl); 4944 } else { 4945 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); 4946 *tl = newnfs_false; 4947 } 4948 } 4949 nfsmout: 4950 free(layp, M_TEMP); 4951 vput(vp); 4952 NFSEXITCODE2(error, nd); 4953 return (error); 4954 } 4955 4956 /* 4957 * nfsv4 layoutreturn service 4958 */ 4959 int 4960 nfsrvd_layoutreturn(struct nfsrv_descript *nd, __unused int isdgram, 4961 vnode_t vp, struct nfsexstuff *exp) 4962 { 4963 uint32_t *tl, *layp; 4964 nfsv4stateid_t stateid; 4965 int error = 0, fnd, kind, layouttype, iomode, maxcnt, reclaim; 4966 uint64_t offset, len; 4967 struct thread *p = curthread; 4968 4969 layp = NULL; 4970 NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED); 4971 reclaim = *tl++; 4972 layouttype = fxdr_unsigned(int, *tl++); 4973 iomode = fxdr_unsigned(int, *tl++); 4974 kind = fxdr_unsigned(int, *tl); 4975 NFSD_DEBUG(4, "layoutreturn recl=%d ltyp=%d iom=%d kind=%d\n", reclaim, 4976 layouttype, iomode, kind); 4977 if (kind == NFSV4LAYOUTRET_FILE) { 4978 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_STATEID + 4979 NFSX_UNSIGNED); 4980 offset = fxdr_hyper(tl); tl += 2; 4981 len = fxdr_hyper(tl); tl += 2; 4982 stateid.seqid = fxdr_unsigned(uint32_t, *tl++); 4983 NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER); 4984 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 4985 4986 /* 4987 * For the special stateid of other all 0s and seqid == 1, set 4988 * the stateid to the current stateid, if it is set. 4989 */ 4990 if (stateid.seqid == 1 && stateid.other[0] == 0 && 4991 stateid.other[1] == 0 && stateid.other[2] == 0) { 4992 if ((nd->nd_flag & ND_CURSTATEID) != 0) { 4993 stateid = nd->nd_curstateid; 4994 stateid.seqid = 0; 4995 } else { 4996 nd->nd_repstat = NFSERR_BADSTATEID; 4997 goto nfsmout; 4998 } 4999 } 5000 5001 maxcnt = fxdr_unsigned(int, *tl); 5002 /* 5003 * There is no fixed upper bound defined in the RFCs, 5004 * but 128Kbytes should be more than sufficient. 5005 */ 5006 if (maxcnt < 0 || maxcnt > 131072) 5007 maxcnt = 0; 5008 if (maxcnt > 0) { 5009 layp = malloc(maxcnt + 1, M_TEMP, M_WAITOK); 5010 error = nfsrv_mtostr(nd, (char *)layp, maxcnt); 5011 if (error != 0) 5012 goto nfsmout; 5013 } 5014 } else { 5015 if (reclaim == newnfs_true) { 5016 nd->nd_repstat = NFSERR_INVAL; 5017 goto nfsmout; 5018 } 5019 offset = len = 0; 5020 maxcnt = 0; 5021 } 5022 nd->nd_repstat = nfsrv_layoutreturn(nd, vp, layouttype, iomode, 5023 offset, len, reclaim, kind, &stateid, maxcnt, layp, &fnd, 5024 nd->nd_cred, p); 5025 NFSD_DEBUG(4, "nfsrv_layoutreturn stat=%u fnd=%d\n", nd->nd_repstat, 5026 fnd); 5027 if (nd->nd_repstat == 0) { 5028 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); 5029 if (fnd != 0) { 5030 *tl = newnfs_true; 5031 NFSM_BUILD(tl, uint32_t *, NFSX_STATEID); 5032 *tl++ = txdr_unsigned(stateid.seqid); 5033 NFSBCOPY(stateid.other, tl, NFSX_STATEIDOTHER); 5034 } else 5035 *tl = newnfs_false; 5036 } 5037 nfsmout: 5038 free(layp, M_TEMP); 5039 vput(vp); 5040 NFSEXITCODE2(error, nd); 5041 return (error); 5042 } 5043 5044 /* 5045 * nfsv4 layout error service 5046 */ 5047 int 5048 nfsrvd_layouterror(struct nfsrv_descript *nd, __unused int isdgram, 5049 vnode_t vp, struct nfsexstuff *exp) 5050 { 5051 uint32_t *tl; 5052 nfsv4stateid_t stateid; 5053 int cnt, error = 0, i, stat; 5054 int opnum __unused; 5055 char devid[NFSX_V4DEVICEID]; 5056 uint64_t offset, len; 5057 5058 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_STATEID + 5059 NFSX_UNSIGNED); 5060 offset = fxdr_hyper(tl); tl += 2; 5061 len = fxdr_hyper(tl); tl += 2; 5062 stateid.seqid = fxdr_unsigned(uint32_t, *tl++); 5063 NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER); 5064 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 5065 cnt = fxdr_unsigned(int, *tl); 5066 NFSD_DEBUG(4, "layouterror off=%ju len=%ju cnt=%d\n", (uintmax_t)offset, 5067 (uintmax_t)len, cnt); 5068 /* 5069 * For the special stateid of other all 0s and seqid == 1, set 5070 * the stateid to the current stateid, if it is set. 5071 */ 5072 if (stateid.seqid == 1 && stateid.other[0] == 0 && 5073 stateid.other[1] == 0 && stateid.other[2] == 0) { 5074 if ((nd->nd_flag & ND_CURSTATEID) != 0) { 5075 stateid = nd->nd_curstateid; 5076 stateid.seqid = 0; 5077 } else { 5078 nd->nd_repstat = NFSERR_BADSTATEID; 5079 goto nfsmout; 5080 } 5081 } 5082 5083 /* 5084 * Ignore offset, len and stateid for now. 5085 */ 5086 for (i = 0; i < cnt; i++) { 5087 NFSM_DISSECT(tl, uint32_t *, NFSX_V4DEVICEID + 2 * 5088 NFSX_UNSIGNED); 5089 NFSBCOPY(tl, devid, NFSX_V4DEVICEID); 5090 tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED); 5091 stat = fxdr_unsigned(int, *tl++); 5092 opnum = fxdr_unsigned(int, *tl); 5093 NFSD_DEBUG(4, "nfsrvd_layouterr op=%d stat=%d\n", opnum, stat); 5094 /* 5095 * Except for NFSERR_ACCES, NFSERR_STALE and NFSERR_NOSPC 5096 * errors, disable the mirror. 5097 */ 5098 if (stat != NFSERR_ACCES && stat != NFSERR_STALE && 5099 stat != NFSERR_NOSPC) 5100 nfsrv_delds(devid, curthread); 5101 5102 /* For NFSERR_NOSPC, mark all deviceids and layouts. */ 5103 if (stat == NFSERR_NOSPC) 5104 nfsrv_marknospc(devid, true); 5105 } 5106 nfsmout: 5107 vput(vp); 5108 NFSEXITCODE2(error, nd); 5109 return (error); 5110 } 5111 5112 /* 5113 * nfsv4 layout stats service 5114 */ 5115 int 5116 nfsrvd_layoutstats(struct nfsrv_descript *nd, __unused int isdgram, 5117 vnode_t vp, struct nfsexstuff *exp) 5118 { 5119 uint32_t *tl; 5120 nfsv4stateid_t stateid; 5121 int cnt, error = 0; 5122 int layouttype __unused; 5123 char devid[NFSX_V4DEVICEID] __unused; 5124 uint64_t offset __unused, len __unused, readcount __unused; 5125 uint64_t readbytes __unused, writecount __unused, writebytes __unused; 5126 5127 NFSM_DISSECT(tl, uint32_t *, 6 * NFSX_HYPER + NFSX_STATEID + 5128 NFSX_V4DEVICEID + 2 * NFSX_UNSIGNED); 5129 offset = fxdr_hyper(tl); tl += 2; 5130 len = fxdr_hyper(tl); tl += 2; 5131 stateid.seqid = fxdr_unsigned(uint32_t, *tl++); 5132 NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER); 5133 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 5134 readcount = fxdr_hyper(tl); tl += 2; 5135 readbytes = fxdr_hyper(tl); tl += 2; 5136 writecount = fxdr_hyper(tl); tl += 2; 5137 writebytes = fxdr_hyper(tl); tl += 2; 5138 NFSBCOPY(tl, devid, NFSX_V4DEVICEID); 5139 tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED); 5140 layouttype = fxdr_unsigned(int, *tl++); 5141 cnt = fxdr_unsigned(int, *tl); 5142 error = nfsm_advance(nd, NFSM_RNDUP(cnt), -1); 5143 if (error != 0) 5144 goto nfsmout; 5145 NFSD_DEBUG(4, "layoutstats cnt=%d\n", cnt); 5146 /* 5147 * For the special stateid of other all 0s and seqid == 1, set 5148 * the stateid to the current stateid, if it is set. 5149 */ 5150 if (stateid.seqid == 1 && stateid.other[0] == 0 && 5151 stateid.other[1] == 0 && stateid.other[2] == 0) { 5152 if ((nd->nd_flag & ND_CURSTATEID) != 0) { 5153 stateid = nd->nd_curstateid; 5154 stateid.seqid = 0; 5155 } else { 5156 nd->nd_repstat = NFSERR_BADSTATEID; 5157 goto nfsmout; 5158 } 5159 } 5160 5161 /* 5162 * No use for the stats for now. 5163 */ 5164 nfsmout: 5165 vput(vp); 5166 NFSEXITCODE2(error, nd); 5167 return (error); 5168 } 5169 5170 /* 5171 * nfsv4 io_advise service 5172 */ 5173 int 5174 nfsrvd_ioadvise(struct nfsrv_descript *nd, __unused int isdgram, 5175 vnode_t vp, struct nfsexstuff *exp) 5176 { 5177 uint32_t *tl; 5178 nfsv4stateid_t stateid; 5179 nfsattrbit_t hints; 5180 int error = 0, ret; 5181 off_t offset, len; 5182 5183 NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID + 2 * NFSX_HYPER); 5184 stateid.seqid = fxdr_unsigned(uint32_t, *tl++); 5185 NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER); 5186 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 5187 offset = fxdr_hyper(tl); tl += 2; 5188 len = fxdr_hyper(tl); 5189 error = nfsrv_getattrbits(nd, &hints, NULL, NULL); 5190 if (error != 0) 5191 goto nfsmout; 5192 /* 5193 * For the special stateid of other all 0s and seqid == 1, set 5194 * the stateid to the current stateid, if it is set. 5195 */ 5196 if (stateid.seqid == 1 && stateid.other[0] == 0 && 5197 stateid.other[1] == 0 && stateid.other[2] == 0) { 5198 if ((nd->nd_flag & ND_CURSTATEID) != 0) { 5199 stateid = nd->nd_curstateid; 5200 stateid.seqid = 0; 5201 } else { 5202 nd->nd_repstat = NFSERR_BADSTATEID; 5203 goto nfsmout; 5204 } 5205 } 5206 5207 if (offset < 0) { 5208 nd->nd_repstat = NFSERR_INVAL; 5209 goto nfsmout; 5210 } 5211 if (len < 0) 5212 len = 0; 5213 if (vp->v_type != VREG) { 5214 if (vp->v_type == VDIR) 5215 nd->nd_repstat = NFSERR_ISDIR; 5216 else 5217 nd->nd_repstat = NFSERR_WRONGTYPE; 5218 goto nfsmout; 5219 } 5220 5221 /* 5222 * For now, we can only handle WILLNEED and DONTNEED and don't use 5223 * the stateid. 5224 */ 5225 if ((NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED) && 5226 !NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_DONTNEED)) || 5227 (NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_DONTNEED) && 5228 !NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED))) { 5229 NFSVOPUNLOCK(vp); 5230 if (NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED)) { 5231 ret = VOP_ADVISE(vp, offset, len, POSIX_FADV_WILLNEED); 5232 NFSZERO_ATTRBIT(&hints); 5233 if (ret == 0) 5234 NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED); 5235 else 5236 NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_NORMAL); 5237 } else { 5238 ret = VOP_ADVISE(vp, offset, len, POSIX_FADV_DONTNEED); 5239 NFSZERO_ATTRBIT(&hints); 5240 if (ret == 0) 5241 NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_DONTNEED); 5242 else 5243 NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_NORMAL); 5244 } 5245 vrele(vp); 5246 } else { 5247 NFSZERO_ATTRBIT(&hints); 5248 NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_NORMAL); 5249 vput(vp); 5250 } 5251 nfsrv_putattrbit(nd, &hints); 5252 NFSEXITCODE2(error, nd); 5253 return (error); 5254 nfsmout: 5255 vput(vp); 5256 NFSEXITCODE2(error, nd); 5257 return (error); 5258 } 5259 5260 /* 5261 * nfsv4 getdeviceinfo service 5262 */ 5263 int 5264 nfsrvd_getdevinfo(struct nfsrv_descript *nd, __unused int isdgram, 5265 __unused vnode_t vp, __unused struct nfsexstuff *exp) 5266 { 5267 uint32_t *tl, maxcnt, notify[NFSV4_NOTIFYBITMAP]; 5268 int cnt, devaddrlen, error = 0, i, layouttype; 5269 char devid[NFSX_V4DEVICEID], *devaddr; 5270 time_t dev_time; 5271 5272 NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED + NFSX_V4DEVICEID); 5273 NFSBCOPY(tl, devid, NFSX_V4DEVICEID); 5274 tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED); 5275 layouttype = fxdr_unsigned(int, *tl++); 5276 maxcnt = fxdr_unsigned(uint32_t, *tl++); 5277 cnt = fxdr_unsigned(int, *tl); 5278 NFSD_DEBUG(4, "getdevinfo ltyp=%d maxcnt=%u bitcnt=%d\n", layouttype, 5279 maxcnt, cnt); 5280 if (cnt > NFSV4_NOTIFYBITMAP || cnt < 0) { 5281 nd->nd_repstat = NFSERR_INVAL; 5282 goto nfsmout; 5283 } 5284 if (cnt > 0) { 5285 NFSM_DISSECT(tl, uint32_t *, cnt * NFSX_UNSIGNED); 5286 for (i = 0; i < cnt; i++) 5287 notify[i] = fxdr_unsigned(uint32_t, *tl++); 5288 } 5289 for (i = cnt; i < NFSV4_NOTIFYBITMAP; i++) 5290 notify[i] = 0; 5291 5292 /* 5293 * Check that the device id is not stale. Device ids are recreated 5294 * each time the nfsd threads are restarted. 5295 */ 5296 NFSBCOPY(devid, &dev_time, sizeof(dev_time)); 5297 if (dev_time != nfsdev_time) { 5298 nd->nd_repstat = NFSERR_NOENT; 5299 goto nfsmout; 5300 } 5301 5302 /* Look for the device id. */ 5303 nd->nd_repstat = nfsrv_getdevinfo(devid, layouttype, &maxcnt, 5304 notify, &devaddrlen, &devaddr); 5305 NFSD_DEBUG(4, "nfsrv_getdevinfo stat=%u\n", nd->nd_repstat); 5306 if (nd->nd_repstat == 0) { 5307 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); 5308 *tl = txdr_unsigned(layouttype); 5309 nfsm_strtom(nd, devaddr, devaddrlen); 5310 cnt = 0; 5311 for (i = 0; i < NFSV4_NOTIFYBITMAP; i++) { 5312 if (notify[i] != 0) 5313 cnt = i + 1; 5314 } 5315 NFSM_BUILD(tl, uint32_t *, (cnt + 1) * NFSX_UNSIGNED); 5316 *tl++ = txdr_unsigned(cnt); 5317 for (i = 0; i < cnt; i++) 5318 *tl++ = txdr_unsigned(notify[i]); 5319 } else if (nd->nd_repstat == NFSERR_TOOSMALL) { 5320 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); 5321 *tl = txdr_unsigned(maxcnt); 5322 } 5323 nfsmout: 5324 NFSEXITCODE2(error, nd); 5325 return (error); 5326 } 5327 5328 /* 5329 * nfsv4 test stateid service 5330 */ 5331 int 5332 nfsrvd_teststateid(struct nfsrv_descript *nd, __unused int isdgram, 5333 __unused vnode_t vp, __unused struct nfsexstuff *exp) 5334 { 5335 uint32_t *tl; 5336 nfsv4stateid_t *stateidp = NULL, *tstateidp; 5337 int cnt, error = 0, i, ret; 5338 struct thread *p = curthread; 5339 5340 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 5341 cnt = fxdr_unsigned(int, *tl); 5342 if (cnt <= 0 || cnt > 1024) { 5343 nd->nd_repstat = NFSERR_BADXDR; 5344 goto nfsmout; 5345 } 5346 stateidp = mallocarray(cnt, sizeof(nfsv4stateid_t), M_TEMP, M_WAITOK); 5347 tstateidp = stateidp; 5348 for (i = 0; i < cnt; i++) { 5349 NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID); 5350 tstateidp->seqid = fxdr_unsigned(uint32_t, *tl++); 5351 NFSBCOPY(tl, tstateidp->other, NFSX_STATEIDOTHER); 5352 tstateidp++; 5353 } 5354 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); 5355 *tl = txdr_unsigned(cnt); 5356 tstateidp = stateidp; 5357 for (i = 0; i < cnt; i++) { 5358 ret = nfsrv_teststateid(nd, tstateidp, p); 5359 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); 5360 *tl = txdr_unsigned(ret); 5361 tstateidp++; 5362 } 5363 nfsmout: 5364 free(stateidp, M_TEMP); 5365 NFSEXITCODE2(error, nd); 5366 return (error); 5367 } 5368 5369 /* 5370 * nfs allocate service 5371 */ 5372 int 5373 nfsrvd_allocate(struct nfsrv_descript *nd, __unused int isdgram, 5374 vnode_t vp, struct nfsexstuff *exp) 5375 { 5376 uint32_t *tl; 5377 struct nfsvattr forat; 5378 int error = 0, forat_ret = 1, gotproxystateid; 5379 off_t off, len; 5380 struct nfsstate st, *stp = &st; 5381 struct nfslock lo, *lop = &lo; 5382 nfsv4stateid_t stateid; 5383 nfsquad_t clientid; 5384 nfsattrbit_t attrbits; 5385 5386 if (!nfsrv_doallocate) { 5387 /* 5388 * If any exported file system, such as a ZFS one, cannot 5389 * do VOP_ALLOCATE(), this operation cannot be supported 5390 * for NFSv4.2. This cannot be done 'per filesystem', but 5391 * must be for the entire nfsd NFSv4.2 service. 5392 */ 5393 nd->nd_repstat = NFSERR_NOTSUPP; 5394 goto nfsmout; 5395 } 5396 gotproxystateid = 0; 5397 NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID + 2 * NFSX_HYPER); 5398 stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS); 5399 lop->lo_flags = NFSLCK_WRITE; 5400 stp->ls_ownerlen = 0; 5401 stp->ls_op = NULL; 5402 stp->ls_uid = nd->nd_cred->cr_uid; 5403 stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 5404 clientid.lval[0] = stp->ls_stateid.other[0] = *tl++; 5405 clientid.lval[1] = stp->ls_stateid.other[1] = *tl++; 5406 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 5407 if ((nd->nd_flag & ND_NFSV41) != 0) 5408 clientid.qval = nd->nd_clientid.qval; 5409 else if (nd->nd_clientid.qval != clientid.qval) 5410 printf("EEK2 multiple clids\n"); 5411 } else { 5412 if ((nd->nd_flag & ND_NFSV41) != 0) 5413 printf("EEK! no clientid from session\n"); 5414 nd->nd_flag |= ND_IMPLIEDCLID; 5415 nd->nd_clientid.qval = clientid.qval; 5416 } 5417 stp->ls_stateid.other[2] = *tl++; 5418 /* 5419 * Don't allow this to be done for a DS. 5420 */ 5421 if ((nd->nd_flag & ND_DSSERVER) != 0) 5422 nd->nd_repstat = NFSERR_NOTSUPP; 5423 /* However, allow the proxy stateid. */ 5424 if (stp->ls_stateid.seqid == 0xffffffff && 5425 stp->ls_stateid.other[0] == 0x55555555 && 5426 stp->ls_stateid.other[1] == 0x55555555 && 5427 stp->ls_stateid.other[2] == 0x55555555) 5428 gotproxystateid = 1; 5429 off = fxdr_hyper(tl); tl += 2; 5430 lop->lo_first = off; 5431 len = fxdr_hyper(tl); 5432 lop->lo_end = lop->lo_first + len; 5433 /* 5434 * Sanity check the offset and length. 5435 * off and len are off_t (signed int64_t) whereas 5436 * lo_first and lo_end are uint64_t and, as such, 5437 * if off >= 0 && len > 0, lo_end cannot overflow 5438 * unless off_t is changed to something other than 5439 * int64_t. Check lo_end < lo_first in case that 5440 * is someday the case. 5441 */ 5442 if (nd->nd_repstat == 0 && (len <= 0 || off < 0 || lop->lo_end > 5443 OFF_MAX || lop->lo_end < lop->lo_first)) 5444 nd->nd_repstat = NFSERR_INVAL; 5445 5446 if (nd->nd_repstat == 0 && vp->v_type != VREG) 5447 nd->nd_repstat = NFSERR_WRONGTYPE; 5448 NFSZERO_ATTRBIT(&attrbits); 5449 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER); 5450 forat_ret = nfsvno_getattr(vp, &forat, nd, curthread, 1, &attrbits); 5451 if (nd->nd_repstat == 0) 5452 nd->nd_repstat = forat_ret; 5453 if (nd->nd_repstat == 0 && (forat.na_uid != nd->nd_cred->cr_uid || 5454 NFSVNO_EXSTRICTACCESS(exp))) 5455 nd->nd_repstat = nfsvno_accchk(vp, VWRITE, nd->nd_cred, exp, 5456 curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, 5457 NULL); 5458 if (nd->nd_repstat == 0 && gotproxystateid == 0) 5459 nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, 5460 &stateid, exp, nd, curthread); 5461 5462 NFSD_DEBUG(4, "nfsrvd_allocate: off=%jd len=%jd stat=%d\n", 5463 (intmax_t)off, (intmax_t)len, nd->nd_repstat); 5464 if (nd->nd_repstat == 0) 5465 nd->nd_repstat = nfsvno_allocate(vp, off, len, nd->nd_cred, 5466 curthread); 5467 NFSD_DEBUG(4, "nfsrvd_allocate: aft nfsvno_allocate=%d\n", 5468 nd->nd_repstat); 5469 vput(vp); 5470 NFSEXITCODE2(0, nd); 5471 return (0); 5472 nfsmout: 5473 vput(vp); 5474 NFSEXITCODE2(error, nd); 5475 return (error); 5476 } 5477 5478 /* 5479 * nfs deallocate service 5480 */ 5481 int 5482 nfsrvd_deallocate(struct nfsrv_descript *nd, __unused int isdgram, 5483 vnode_t vp, struct nfsexstuff *exp) 5484 { 5485 uint32_t *tl; 5486 struct nfsvattr forat; 5487 int error = 0, forat_ret = 1, gotproxystateid; 5488 off_t off, len; 5489 struct nfsstate st, *stp = &st; 5490 struct nfslock lo, *lop = &lo; 5491 nfsv4stateid_t stateid; 5492 nfsquad_t clientid; 5493 nfsattrbit_t attrbits; 5494 5495 gotproxystateid = 0; 5496 NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID + 2 * NFSX_HYPER); 5497 stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS); 5498 lop->lo_flags = NFSLCK_WRITE; 5499 stp->ls_ownerlen = 0; 5500 stp->ls_op = NULL; 5501 stp->ls_uid = nd->nd_cred->cr_uid; 5502 stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 5503 clientid.lval[0] = stp->ls_stateid.other[0] = *tl++; 5504 clientid.lval[1] = stp->ls_stateid.other[1] = *tl++; 5505 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 5506 if ((nd->nd_flag & ND_NFSV41) != 0) 5507 clientid.qval = nd->nd_clientid.qval; 5508 else if (nd->nd_clientid.qval != clientid.qval) 5509 printf("EEK2 multiple clids\n"); 5510 } else { 5511 if ((nd->nd_flag & ND_NFSV41) != 0) 5512 printf("EEK! no clientid from session\n"); 5513 nd->nd_flag |= ND_IMPLIEDCLID; 5514 nd->nd_clientid.qval = clientid.qval; 5515 } 5516 stp->ls_stateid.other[2] = *tl++; 5517 /* 5518 * Don't allow this to be done for a DS. 5519 */ 5520 if ((nd->nd_flag & ND_DSSERVER) != 0) 5521 nd->nd_repstat = NFSERR_NOTSUPP; 5522 /* However, allow the proxy stateid. */ 5523 if (stp->ls_stateid.seqid == 0xffffffff && 5524 stp->ls_stateid.other[0] == 0x55555555 && 5525 stp->ls_stateid.other[1] == 0x55555555 && 5526 stp->ls_stateid.other[2] == 0x55555555) 5527 gotproxystateid = 1; 5528 off = fxdr_hyper(tl); tl += 2; 5529 lop->lo_first = off; 5530 len = fxdr_hyper(tl); 5531 if (len < 0) 5532 len = OFF_MAX; 5533 NFSD_DEBUG(4, "dealloc: off=%jd len=%jd\n", (intmax_t)off, 5534 (intmax_t)len); 5535 lop->lo_end = lop->lo_first + len; 5536 /* 5537 * Sanity check the offset and length. 5538 * off and len are off_t (signed int64_t) whereas 5539 * lo_first and lo_end are uint64_t and, as such, 5540 * if off >= 0 && len > 0, lo_end cannot overflow 5541 * unless off_t is changed to something other than 5542 * int64_t. Check lo_end < lo_first in case that 5543 * is someday the case. 5544 * The error to return is not specified by RFC 7862 so I 5545 * made this compatible with the Linux knfsd. 5546 */ 5547 if (nd->nd_repstat == 0) { 5548 if (off < 0 || lop->lo_end > NFSRV_MAXFILESIZE) 5549 nd->nd_repstat = NFSERR_FBIG; 5550 else if (len == 0 || lop->lo_end < lop->lo_first) 5551 nd->nd_repstat = NFSERR_INVAL; 5552 } 5553 5554 if (nd->nd_repstat == 0 && vp->v_type != VREG) 5555 nd->nd_repstat = NFSERR_WRONGTYPE; 5556 NFSZERO_ATTRBIT(&attrbits); 5557 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER); 5558 forat_ret = nfsvno_getattr(vp, &forat, nd, curthread, 1, &attrbits); 5559 if (nd->nd_repstat == 0) 5560 nd->nd_repstat = forat_ret; 5561 if (nd->nd_repstat == 0 && (forat.na_uid != nd->nd_cred->cr_uid || 5562 NFSVNO_EXSTRICTACCESS(exp))) 5563 nd->nd_repstat = nfsvno_accchk(vp, VWRITE, nd->nd_cred, exp, 5564 curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, 5565 NULL); 5566 if (nd->nd_repstat == 0 && gotproxystateid == 0) 5567 nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, 5568 &stateid, exp, nd, curthread); 5569 5570 if (nd->nd_repstat == 0) 5571 nd->nd_repstat = nfsvno_deallocate(vp, off, len, nd->nd_cred, 5572 curthread); 5573 vput(vp); 5574 NFSD_DEBUG(4, "eo deallocate=%d\n", nd->nd_repstat); 5575 NFSEXITCODE2(0, nd); 5576 return (0); 5577 nfsmout: 5578 vput(vp); 5579 NFSEXITCODE2(error, nd); 5580 return (error); 5581 } 5582 5583 /* 5584 * nfs copy service 5585 */ 5586 int 5587 nfsrvd_copy_file_range(struct nfsrv_descript *nd, __unused int isdgram, 5588 vnode_t vp, vnode_t tovp, struct nfsexstuff *exp, struct nfsexstuff *toexp) 5589 { 5590 uint32_t *tl; 5591 struct nfsvattr at; 5592 int cnt, error = 0, ret; 5593 off_t inoff, outoff; 5594 uint64_t len; 5595 size_t xfer; 5596 struct nfsstate inst, outst, *instp = &inst, *outstp = &outst; 5597 struct nfslock inlo, outlo, *inlop = &inlo, *outlop = &outlo; 5598 nfsquad_t clientid; 5599 nfsv4stateid_t stateid; 5600 nfsattrbit_t attrbits; 5601 void *rl_rcookie, *rl_wcookie; 5602 5603 rl_rcookie = rl_wcookie = NULL; 5604 if (nfsrv_maxcopyrange == 0 || nfsrv_devidcnt > 0) { 5605 /* 5606 * For a pNFS server, reply NFSERR_NOTSUPP so that the client 5607 * will do the copy via I/O on the DS(s). 5608 * If vfs.nfsd.maxcopyrange set to 0, disable Copy. 5609 */ 5610 nd->nd_repstat = NFSERR_NOTSUPP; 5611 goto nfsmout; 5612 } 5613 if (vp == tovp) { 5614 /* Copying a byte range within the same file is not allowed. */ 5615 nd->nd_repstat = NFSERR_INVAL; 5616 goto nfsmout; 5617 } 5618 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_STATEID + 3 * NFSX_HYPER + 5619 3 * NFSX_UNSIGNED); 5620 instp->ls_flags = (NFSLCK_CHECK | NFSLCK_READACCESS); 5621 inlop->lo_flags = NFSLCK_READ; 5622 instp->ls_ownerlen = 0; 5623 instp->ls_op = NULL; 5624 instp->ls_uid = nd->nd_cred->cr_uid; 5625 instp->ls_stateid.seqid = fxdr_unsigned(uint32_t, *tl++); 5626 clientid.lval[0] = instp->ls_stateid.other[0] = *tl++; 5627 clientid.lval[1] = instp->ls_stateid.other[1] = *tl++; 5628 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) 5629 clientid.qval = nd->nd_clientid.qval; 5630 instp->ls_stateid.other[2] = *tl++; 5631 outstp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS); 5632 outlop->lo_flags = NFSLCK_WRITE; 5633 outstp->ls_ownerlen = 0; 5634 outstp->ls_op = NULL; 5635 outstp->ls_uid = nd->nd_cred->cr_uid; 5636 outstp->ls_stateid.seqid = fxdr_unsigned(uint32_t, *tl++); 5637 outstp->ls_stateid.other[0] = *tl++; 5638 outstp->ls_stateid.other[1] = *tl++; 5639 outstp->ls_stateid.other[2] = *tl++; 5640 inoff = fxdr_hyper(tl); tl += 2; 5641 inlop->lo_first = inoff; 5642 outoff = fxdr_hyper(tl); tl += 2; 5643 outlop->lo_first = outoff; 5644 len = fxdr_hyper(tl); tl += 2; 5645 if (len == 0) { 5646 /* len == 0 means to EOF. */ 5647 inlop->lo_end = OFF_MAX; 5648 outlop->lo_end = OFF_MAX; 5649 } else { 5650 inlop->lo_end = inlop->lo_first + len; 5651 outlop->lo_end = outlop->lo_first + len; 5652 } 5653 5654 /* 5655 * At this time only consecutive, synchronous copy is supported, 5656 * so ca_consecutive and ca_synchronous can be ignored. 5657 */ 5658 tl += 2; 5659 5660 cnt = fxdr_unsigned(int, *tl); 5661 if ((nd->nd_flag & ND_DSSERVER) != 0 || cnt != 0) 5662 nd->nd_repstat = NFSERR_NOTSUPP; 5663 if (nd->nd_repstat == 0 && (inoff > OFF_MAX || outoff > OFF_MAX || 5664 inlop->lo_end > OFF_MAX || outlop->lo_end > OFF_MAX || 5665 inlop->lo_end < inlop->lo_first || outlop->lo_end < 5666 outlop->lo_first)) 5667 nd->nd_repstat = NFSERR_INVAL; 5668 5669 if (nd->nd_repstat == 0 && vp->v_type != VREG) 5670 nd->nd_repstat = NFSERR_WRONGTYPE; 5671 5672 /* Check permissions for the input file. */ 5673 NFSZERO_ATTRBIT(&attrbits); 5674 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER); 5675 ret = nfsvno_getattr(vp, &at, nd, curthread, 1, &attrbits); 5676 if (nd->nd_repstat == 0) 5677 nd->nd_repstat = ret; 5678 if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid || 5679 NFSVNO_EXSTRICTACCESS(exp))) 5680 nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred, exp, 5681 curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, 5682 NULL); 5683 if (nd->nd_repstat == 0) 5684 nd->nd_repstat = nfsrv_lockctrl(vp, &instp, &inlop, NULL, 5685 clientid, &stateid, exp, nd, curthread); 5686 NFSVOPUNLOCK(vp); 5687 if (nd->nd_repstat != 0) 5688 goto out; 5689 5690 error = NFSVOPLOCK(tovp, LK_SHARED); 5691 if (error != 0) 5692 goto out; 5693 if (tovp->v_type != VREG) 5694 nd->nd_repstat = NFSERR_WRONGTYPE; 5695 5696 /* For the output file, we only need the Owner attribute. */ 5697 ret = nfsvno_getattr(tovp, &at, nd, curthread, 1, &attrbits); 5698 if (nd->nd_repstat == 0) 5699 nd->nd_repstat = ret; 5700 if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid || 5701 NFSVNO_EXSTRICTACCESS(exp))) 5702 nd->nd_repstat = nfsvno_accchk(tovp, VWRITE, nd->nd_cred, toexp, 5703 curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, 5704 NULL); 5705 if (nd->nd_repstat == 0) 5706 nd->nd_repstat = nfsrv_lockctrl(tovp, &outstp, &outlop, NULL, 5707 clientid, &stateid, toexp, nd, curthread); 5708 NFSVOPUNLOCK(tovp); 5709 5710 /* Range lock the byte ranges for both invp and outvp. */ 5711 if (nd->nd_repstat == 0) { 5712 for (;;) { 5713 if (len == 0) { 5714 rl_wcookie = vn_rangelock_wlock(tovp, outoff, 5715 OFF_MAX); 5716 rl_rcookie = vn_rangelock_tryrlock(vp, inoff, 5717 OFF_MAX); 5718 } else { 5719 rl_wcookie = vn_rangelock_wlock(tovp, outoff, 5720 outoff + len); 5721 rl_rcookie = vn_rangelock_tryrlock(vp, inoff, 5722 inoff + len); 5723 } 5724 if (rl_rcookie != NULL) 5725 break; 5726 vn_rangelock_unlock(tovp, rl_wcookie); 5727 if (len == 0) 5728 rl_rcookie = vn_rangelock_rlock(vp, inoff, 5729 OFF_MAX); 5730 else 5731 rl_rcookie = vn_rangelock_rlock(vp, inoff, 5732 inoff + len); 5733 vn_rangelock_unlock(vp, rl_rcookie); 5734 } 5735 5736 error = NFSVOPLOCK(vp, LK_SHARED); 5737 if (error == 0) { 5738 ret = nfsvno_getattr(vp, &at, nd, curthread, 1, NULL); 5739 if (ret == 0) { 5740 /* 5741 * Since invp is range locked, na_size should 5742 * not change. 5743 */ 5744 if (len == 0 && at.na_size > inoff) { 5745 /* 5746 * If len == 0, set it based on invp's 5747 * size. If offset is past EOF, just 5748 * leave len == 0. 5749 */ 5750 len = at.na_size - inoff; 5751 } else if (nfsrv_linux42server == 0 && 5752 inoff + len > at.na_size) { 5753 /* 5754 * RFC-7862 says that NFSERR_INVAL must 5755 * be returned when inoff + len exceeds 5756 * the file size, however the NFSv4.2 5757 * Linux client likes to do this, so 5758 * only check if nfsrv_linux42server 5759 * is not set. 5760 */ 5761 nd->nd_repstat = NFSERR_INVAL; 5762 } 5763 } 5764 NFSVOPUNLOCK(vp); 5765 if (ret != 0 && nd->nd_repstat == 0) 5766 nd->nd_repstat = ret; 5767 } else if (nd->nd_repstat == 0) 5768 nd->nd_repstat = error; 5769 } 5770 5771 /* 5772 * Do the actual copy to an upper limit of vfs.nfsd.maxcopyrange. 5773 * This size limit can be set to limit the time a copy RPC will 5774 * take. 5775 */ 5776 if (len > nfsrv_maxcopyrange) 5777 xfer = nfsrv_maxcopyrange; 5778 else 5779 xfer = len; 5780 if (nd->nd_repstat == 0) { 5781 nd->nd_repstat = vn_copy_file_range(vp, &inoff, tovp, &outoff, 5782 &xfer, COPY_FILE_RANGE_TIMEO1SEC, nd->nd_cred, nd->nd_cred, 5783 NULL); 5784 if (nd->nd_repstat == 0) 5785 len = xfer; 5786 } 5787 5788 /* Unlock the ranges. */ 5789 if (rl_rcookie != NULL) 5790 vn_rangelock_unlock(vp, rl_rcookie); 5791 if (rl_wcookie != NULL) 5792 vn_rangelock_unlock(tovp, rl_wcookie); 5793 5794 if (nd->nd_repstat == 0) { 5795 NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + NFSX_HYPER + 5796 NFSX_VERF); 5797 *tl++ = txdr_unsigned(0); /* No callback ids. */ 5798 txdr_hyper(len, tl); tl += 2; 5799 *tl++ = txdr_unsigned(NFSWRITE_UNSTABLE); 5800 *tl++ = txdr_unsigned(nfsboottime.tv_sec); 5801 *tl++ = txdr_unsigned(nfsboottime.tv_usec); 5802 *tl++ = newnfs_true; 5803 *tl = newnfs_true; 5804 } 5805 out: 5806 vrele(vp); 5807 vrele(tovp); 5808 NFSEXITCODE2(error, nd); 5809 return (error); 5810 nfsmout: 5811 vput(vp); 5812 vrele(tovp); 5813 NFSEXITCODE2(error, nd); 5814 return (error); 5815 } 5816 5817 /* 5818 * nfs seek service 5819 */ 5820 int 5821 nfsrvd_seek(struct nfsrv_descript *nd, __unused int isdgram, 5822 vnode_t vp, struct nfsexstuff *exp) 5823 { 5824 uint32_t *tl; 5825 struct nfsvattr at; 5826 int content, error = 0; 5827 off_t off; 5828 u_long cmd; 5829 nfsattrbit_t attrbits; 5830 bool eof; 5831 5832 NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID + NFSX_HYPER + NFSX_UNSIGNED); 5833 /* Ignore the stateid for now. */ 5834 tl += (NFSX_STATEID / NFSX_UNSIGNED); 5835 off = fxdr_hyper(tl); tl += 2; 5836 content = fxdr_unsigned(int, *tl); 5837 if (content == NFSV4CONTENT_DATA) 5838 cmd = FIOSEEKDATA; 5839 else if (content == NFSV4CONTENT_HOLE) 5840 cmd = FIOSEEKHOLE; 5841 else 5842 nd->nd_repstat = NFSERR_BADXDR; 5843 if (nd->nd_repstat == 0 && vp->v_type == VDIR) 5844 nd->nd_repstat = NFSERR_ISDIR; 5845 if (nd->nd_repstat == 0 && vp->v_type != VREG) 5846 nd->nd_repstat = NFSERR_WRONGTYPE; 5847 if (nd->nd_repstat == 0 && off < 0) 5848 nd->nd_repstat = NFSERR_NXIO; 5849 if (nd->nd_repstat == 0) { 5850 /* Check permissions for the input file. */ 5851 NFSZERO_ATTRBIT(&attrbits); 5852 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER); 5853 nd->nd_repstat = nfsvno_getattr(vp, &at, nd, curthread, 1, 5854 &attrbits); 5855 } 5856 if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid || 5857 NFSVNO_EXSTRICTACCESS(exp))) 5858 nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred, exp, 5859 curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, 5860 NULL); 5861 if (nd->nd_repstat != 0) 5862 goto nfsmout; 5863 5864 /* nfsvno_seek() unlocks and vrele()s the vp. */ 5865 nd->nd_repstat = nfsvno_seek(nd, vp, cmd, &off, content, &eof, 5866 nd->nd_cred, curthread); 5867 if (nd->nd_repstat == 0 && eof && content == NFSV4CONTENT_DATA && 5868 nfsrv_linux42server != 0) 5869 nd->nd_repstat = NFSERR_NXIO; 5870 if (nd->nd_repstat == 0) { 5871 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED + NFSX_HYPER); 5872 if (eof) 5873 *tl++ = newnfs_true; 5874 else 5875 *tl++ = newnfs_false; 5876 txdr_hyper(off, tl); 5877 } 5878 NFSEXITCODE2(error, nd); 5879 return (error); 5880 nfsmout: 5881 vput(vp); 5882 NFSEXITCODE2(error, nd); 5883 return (error); 5884 } 5885 5886 /* 5887 * nfs get extended attribute service 5888 */ 5889 int 5890 nfsrvd_getxattr(struct nfsrv_descript *nd, __unused int isdgram, 5891 vnode_t vp, __unused struct nfsexstuff *exp) 5892 { 5893 uint32_t *tl; 5894 struct mbuf *mp = NULL, *mpend = NULL; 5895 int error, len; 5896 char *name; 5897 struct thread *p = curthread; 5898 uint16_t off; 5899 5900 error = 0; 5901 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 5902 len = fxdr_unsigned(int, *tl); 5903 if (len <= 0) { 5904 nd->nd_repstat = NFSERR_BADXDR; 5905 goto nfsmout; 5906 } 5907 if (len > EXTATTR_MAXNAMELEN) { 5908 nd->nd_repstat = NFSERR_NOXATTR; 5909 goto nfsmout; 5910 } 5911 name = malloc(len + 1, M_TEMP, M_WAITOK); 5912 nd->nd_repstat = nfsrv_mtostr(nd, name, len); 5913 if (nd->nd_repstat == 0) 5914 nd->nd_repstat = nfsvno_getxattr(vp, name, 5915 nd->nd_maxresp, nd->nd_cred, nd->nd_flag, 5916 nd->nd_maxextsiz, p, &mp, &mpend, &len); 5917 if (nd->nd_repstat == ENOATTR) 5918 nd->nd_repstat = NFSERR_NOXATTR; 5919 else if (nd->nd_repstat == EOPNOTSUPP) 5920 nd->nd_repstat = NFSERR_NOTSUPP; 5921 if (nd->nd_repstat == 0) { 5922 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); 5923 *tl = txdr_unsigned(len); 5924 if (len > 0) { 5925 nd->nd_mb->m_next = mp; 5926 nd->nd_mb = mpend; 5927 if ((mpend->m_flags & M_EXTPG) != 0) { 5928 nd->nd_flag |= ND_EXTPG; 5929 nd->nd_bextpg = mpend->m_epg_npgs - 1; 5930 nd->nd_bpos = (char *)(void *) 5931 PHYS_TO_DMAP(mpend->m_epg_pa[nd->nd_bextpg]); 5932 off = (nd->nd_bextpg == 0) ? 5933 mpend->m_epg_1st_off : 0; 5934 nd->nd_bpos += off + mpend->m_epg_last_len; 5935 nd->nd_bextpgsiz = PAGE_SIZE - 5936 mpend->m_epg_last_len - off; 5937 } else 5938 nd->nd_bpos = mtod(mpend, char *) + 5939 mpend->m_len; 5940 } 5941 } 5942 free(name, M_TEMP); 5943 5944 nfsmout: 5945 if (nd->nd_repstat == 0) 5946 nd->nd_repstat = error; 5947 vput(vp); 5948 NFSEXITCODE2(0, nd); 5949 return (0); 5950 } 5951 5952 /* 5953 * nfs set extended attribute service 5954 */ 5955 int 5956 nfsrvd_setxattr(struct nfsrv_descript *nd, __unused int isdgram, 5957 vnode_t vp, __unused struct nfsexstuff *exp) 5958 { 5959 uint32_t *tl; 5960 struct nfsvattr ova, nva; 5961 nfsattrbit_t attrbits; 5962 int error, len, opt; 5963 char *name; 5964 size_t siz; 5965 struct thread *p = curthread; 5966 5967 error = 0; 5968 name = NULL; 5969 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); 5970 opt = fxdr_unsigned(int, *tl++); 5971 len = fxdr_unsigned(int, *tl); 5972 if (len <= 0) { 5973 nd->nd_repstat = NFSERR_BADXDR; 5974 goto nfsmout; 5975 } 5976 if (len > EXTATTR_MAXNAMELEN) { 5977 nd->nd_repstat = NFSERR_NOXATTR; 5978 goto nfsmout; 5979 } 5980 name = malloc(len + 1, M_TEMP, M_WAITOK); 5981 error = nfsrv_mtostr(nd, name, len); 5982 if (error != 0) 5983 goto nfsmout; 5984 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 5985 len = fxdr_unsigned(int, *tl); 5986 if (len < 0 || len > IOSIZE_MAX) { 5987 nd->nd_repstat = NFSERR_XATTR2BIG; 5988 goto nfsmout; 5989 } 5990 switch (opt) { 5991 case NFSV4SXATTR_CREATE: 5992 error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL, 5993 &siz, nd->nd_cred, p); 5994 if (error != ENOATTR) 5995 nd->nd_repstat = NFSERR_EXIST; 5996 error = 0; 5997 break; 5998 case NFSV4SXATTR_REPLACE: 5999 error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL, 6000 &siz, nd->nd_cred, p); 6001 if (error != 0) 6002 nd->nd_repstat = NFSERR_NOXATTR; 6003 break; 6004 case NFSV4SXATTR_EITHER: 6005 break; 6006 default: 6007 nd->nd_repstat = NFSERR_BADXDR; 6008 } 6009 if (nd->nd_repstat != 0) 6010 goto nfsmout; 6011 6012 /* Now, do the Set Extended attribute, with Change before and after. */ 6013 NFSZERO_ATTRBIT(&attrbits); 6014 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE); 6015 nd->nd_repstat = nfsvno_getattr(vp, &ova, nd, p, 1, &attrbits); 6016 if (nd->nd_repstat == 0) { 6017 nd->nd_repstat = nfsvno_setxattr(vp, name, len, nd->nd_md, 6018 nd->nd_dpos, nd->nd_cred, p); 6019 if (nd->nd_repstat == ENXIO) 6020 nd->nd_repstat = NFSERR_XATTR2BIG; 6021 } 6022 if (nd->nd_repstat == 0 && len > 0) 6023 nd->nd_repstat = nfsm_advance(nd, NFSM_RNDUP(len), -1); 6024 if (nd->nd_repstat == 0) 6025 nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, &attrbits); 6026 if (nd->nd_repstat == 0) { 6027 NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_UNSIGNED); 6028 *tl++ = newnfs_true; 6029 txdr_hyper(ova.na_filerev, tl); tl += 2; 6030 txdr_hyper(nva.na_filerev, tl); 6031 } 6032 6033 nfsmout: 6034 free(name, M_TEMP); 6035 if (nd->nd_repstat == 0) 6036 nd->nd_repstat = error; 6037 vput(vp); 6038 NFSEXITCODE2(0, nd); 6039 return (0); 6040 } 6041 6042 /* 6043 * nfs remove extended attribute service 6044 */ 6045 int 6046 nfsrvd_rmxattr(struct nfsrv_descript *nd, __unused int isdgram, 6047 vnode_t vp, __unused struct nfsexstuff *exp) 6048 { 6049 uint32_t *tl; 6050 struct nfsvattr ova, nva; 6051 nfsattrbit_t attrbits; 6052 int error, len; 6053 char *name; 6054 struct thread *p = curthread; 6055 6056 error = 0; 6057 name = NULL; 6058 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 6059 len = fxdr_unsigned(int, *tl); 6060 if (len <= 0) { 6061 nd->nd_repstat = NFSERR_BADXDR; 6062 goto nfsmout; 6063 } 6064 if (len > EXTATTR_MAXNAMELEN) { 6065 nd->nd_repstat = NFSERR_NOXATTR; 6066 goto nfsmout; 6067 } 6068 name = malloc(len + 1, M_TEMP, M_WAITOK); 6069 error = nfsrv_mtostr(nd, name, len); 6070 if (error != 0) 6071 goto nfsmout; 6072 6073 if ((nd->nd_flag & ND_IMPLIEDCLID) == 0) { 6074 printf("EEK! nfsrvd_rmxattr: no implied clientid\n"); 6075 error = NFSERR_NOXATTR; 6076 goto nfsmout; 6077 } 6078 /* 6079 * Now, do the Remove Extended attribute, with Change before and 6080 * after. 6081 */ 6082 NFSZERO_ATTRBIT(&attrbits); 6083 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE); 6084 nd->nd_repstat = nfsvno_getattr(vp, &ova, nd, p, 1, &attrbits); 6085 if (nd->nd_repstat == 0) { 6086 nd->nd_repstat = nfsvno_rmxattr(nd, vp, name, nd->nd_cred, p); 6087 if (nd->nd_repstat == ENOATTR) 6088 nd->nd_repstat = NFSERR_NOXATTR; 6089 } 6090 if (nd->nd_repstat == 0) 6091 nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, &attrbits); 6092 if (nd->nd_repstat == 0) { 6093 NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_UNSIGNED); 6094 *tl++ = newnfs_true; 6095 txdr_hyper(ova.na_filerev, tl); tl += 2; 6096 txdr_hyper(nva.na_filerev, tl); 6097 } 6098 6099 nfsmout: 6100 free(name, M_TEMP); 6101 if (nd->nd_repstat == 0) 6102 nd->nd_repstat = error; 6103 vput(vp); 6104 NFSEXITCODE2(0, nd); 6105 return (0); 6106 } 6107 6108 /* 6109 * nfs list extended attribute service 6110 */ 6111 int 6112 nfsrvd_listxattr(struct nfsrv_descript *nd, __unused int isdgram, 6113 vnode_t vp, __unused struct nfsexstuff *exp) 6114 { 6115 uint32_t cnt, *tl, len, len2, i, pos, retlen; 6116 int error; 6117 uint64_t cookie, cookie2; 6118 u_char *buf; 6119 bool eof; 6120 struct thread *p = curthread; 6121 6122 error = 0; 6123 buf = NULL; 6124 NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED); 6125 /* 6126 * The cookie doesn't need to be in net byte order, but FreeBSD 6127 * does so to make it more readable in packet traces. 6128 */ 6129 cookie = fxdr_hyper(tl); tl += 2; 6130 len = fxdr_unsigned(uint32_t, *tl); 6131 if (len == 0 || cookie >= IOSIZE_MAX) { 6132 nd->nd_repstat = NFSERR_BADXDR; 6133 goto nfsmout; 6134 } 6135 if (len > nd->nd_maxresp - NFS_MAXXDR) 6136 len = nd->nd_maxresp - NFS_MAXXDR; 6137 len2 = len; 6138 nd->nd_repstat = nfsvno_listxattr(vp, cookie, nd->nd_cred, p, &buf, 6139 &len, &eof); 6140 if (nd->nd_repstat == EOPNOTSUPP) 6141 nd->nd_repstat = NFSERR_NOTSUPP; 6142 if (nd->nd_repstat == 0) { 6143 cookie2 = cookie + len; 6144 if (cookie2 < cookie) 6145 nd->nd_repstat = NFSERR_BADXDR; 6146 } 6147 retlen = NFSX_HYPER + 2 * NFSX_UNSIGNED; 6148 if (nd->nd_repstat == 0 && len2 < retlen) 6149 nd->nd_repstat = NFSERR_TOOSMALL; 6150 if (nd->nd_repstat == 0) { 6151 /* Now copy the entries out. */ 6152 if (len == 0) { 6153 /* The cookie was at eof. */ 6154 NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 2 * 6155 NFSX_UNSIGNED); 6156 txdr_hyper(cookie2, tl); tl += 2; 6157 *tl++ = txdr_unsigned(0); 6158 *tl = newnfs_true; 6159 goto nfsmout; 6160 } 6161 6162 /* Sanity check the cookie. */ 6163 for (pos = 0; pos < len; pos += (i + 1)) { 6164 if (pos == cookie) 6165 break; 6166 i = buf[pos]; 6167 } 6168 if (pos != cookie) { 6169 nd->nd_repstat = NFSERR_INVAL; 6170 goto nfsmout; 6171 } 6172 6173 /* Loop around copying the entrie(s) out. */ 6174 cnt = 0; 6175 len -= cookie; 6176 i = buf[pos]; 6177 while (i < len && len2 >= retlen + NFSM_RNDUP(i) + 6178 NFSX_UNSIGNED) { 6179 if (cnt == 0) { 6180 NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 6181 NFSX_UNSIGNED); 6182 txdr_hyper(cookie2, tl); tl += 2; 6183 } 6184 retlen += nfsm_strtom(nd, &buf[pos + 1], i); 6185 len -= (i + 1); 6186 pos += (i + 1); 6187 i = buf[pos]; 6188 cnt++; 6189 } 6190 /* 6191 * eof is set true/false by nfsvno_listxattr(), but if we 6192 * can't copy all entries returned by nfsvno_listxattr(), 6193 * we are not at eof. 6194 */ 6195 if (len > 0) 6196 eof = false; 6197 if (cnt > 0) { 6198 /* *tl is set above. */ 6199 *tl = txdr_unsigned(cnt); 6200 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); 6201 if (eof) 6202 *tl = newnfs_true; 6203 else 6204 *tl = newnfs_false; 6205 } else 6206 nd->nd_repstat = NFSERR_TOOSMALL; 6207 } 6208 6209 nfsmout: 6210 free(buf, M_TEMP); 6211 if (nd->nd_repstat == 0) 6212 nd->nd_repstat = error; 6213 vput(vp); 6214 NFSEXITCODE2(0, nd); 6215 return (0); 6216 } 6217 6218 /* 6219 * nfsv4 service not supported 6220 */ 6221 int 6222 nfsrvd_notsupp(struct nfsrv_descript *nd, __unused int isdgram, 6223 __unused vnode_t vp, __unused struct nfsexstuff *exp) 6224 { 6225 6226 nd->nd_repstat = NFSERR_NOTSUPP; 6227 NFSEXITCODE2(0, nd); 6228 return (0); 6229 } 6230