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