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