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