1 /* $NetBSD: nfs_serv.c,v 1.184 2023/03/23 19:53:01 riastradh Exp $ */ 2 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 * @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95 35 */ 36 37 /* 38 * nfs version 2 and 3 server calls to vnode ops 39 * - these routines generally have 3 phases 40 * 1 - break down and validate rpc request in mbuf list 41 * 2 - do the vnode ops for the request 42 * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c) 43 * 3 - build the rpc reply in an mbuf list 44 * nb: 45 * - do not mix the phases, since the nfsm_?? macros can return failures 46 * on a bad rpc or similar and do not do any vrele() or vput()'s 47 * 48 * - the nfsm_reply() macro generates an nfs rpc reply with the nfs 49 * error number iff error != 0 whereas 50 * returning an error from the server function implies a fatal error 51 * such as a badly constructed rpc request that should be dropped without 52 * a reply. 53 * For Version 3, nfsm_reply() does not return for the error case, since 54 * most version 3 rpcs return more than the status for error cases. 55 */ 56 57 #include <sys/cdefs.h> 58 __KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.184 2023/03/23 19:53:01 riastradh Exp $"); 59 60 #include <sys/param.h> 61 #include <sys/systm.h> 62 #include <sys/proc.h> 63 #include <sys/file.h> 64 #include <sys/namei.h> 65 #include <sys/vnode.h> 66 #include <sys/mount.h> 67 #include <sys/fstrans.h> 68 #include <sys/socket.h> 69 #include <sys/socketvar.h> 70 #include <sys/mbuf.h> 71 #include <sys/dirent.h> 72 #include <sys/stat.h> 73 #include <sys/kernel.h> 74 #include <sys/hash.h> 75 #include <sys/kauth.h> 76 #include <sys/module.h> 77 #include <sys/syscall.h> 78 #include <sys/syscallargs.h> 79 #include <sys/syscallvar.h> 80 81 #include <uvm/uvm_extern.h> 82 #include <uvm/uvm_loan.h> 83 #include <uvm/uvm_page.h> 84 85 #include <nfs/nfsproto.h> 86 #include <nfs/rpcv2.h> 87 #include <nfs/nfs.h> 88 #include <nfs/xdr_subs.h> 89 #include <nfs/nfsm_subs.h> 90 #include <nfs/nfs_var.h> 91 92 MODULE(MODULE_CLASS_MISC, nfsserver, "nfs"); 93 94 /* Global vars */ 95 extern u_int32_t nfs_xdrneg1; 96 extern u_int32_t nfs_false, nfs_true; 97 extern const enum vtype nv3tov_type[8]; 98 extern struct nfsstats nfsstats; 99 extern const nfstype nfsv2_type[9]; 100 extern const nfstype nfsv3_type[9]; 101 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000; 102 bool nfsd_use_loan = true; /* use page-loan for READ OP */ 103 104 #define nqsrv_getl(vp, rw) /* nothing */ 105 106 static const struct syscall_package nfsserver_syscalls[] = { 107 { SYS_nfssvc, 0, (sy_call_t *)sys_nfssvc }, 108 { 0, 0, NULL }, 109 }; 110 111 static int 112 nfsserver_modcmd(modcmd_t cmd, void *arg) 113 { 114 extern struct vfs_hooks nfs_export_hooks; /* XXX */ 115 int error; 116 117 switch (cmd) { 118 case MODULE_CMD_INIT: 119 error = syscall_establish(NULL, nfsserver_syscalls); 120 if (error != 0) { 121 return error; 122 } 123 nfs_init(); /* XXX for monolithic kernel */ 124 netexport_init(); 125 nfsrv_initcache(); /* Init the server request cache */ 126 nfsrv_init(0); /* Init server data structures */ 127 vfs_hooks_attach(&nfs_export_hooks); 128 nfs_timer_srvinit(nfsrv_timer); 129 return 0; 130 case MODULE_CMD_FINI: 131 error = syscall_disestablish(NULL, nfsserver_syscalls); 132 if (error != 0) { 133 return error; 134 } 135 /* 136 * Kill export list before detaching VFS hooks, so we 137 * we don't leak state due to a concurrent umount(). 138 */ 139 netexport_fini(); 140 vfs_hooks_detach(&nfs_export_hooks); 141 142 /* Kill timer before server goes away. */ 143 nfs_timer_srvfini(); 144 nfsrv_fini(); 145 146 /* Server uses server cache, so kill cache last. */ 147 nfsrv_finicache(); 148 nfs_fini(); 149 return 0; 150 case MODULE_CMD_AUTOUNLOAD: 151 if (netexport_hasexports()) 152 return EBUSY; 153 /*FALLTHROUGH*/ 154 default: 155 return ENOTTY; 156 } 157 } 158 159 /* 160 * nfs v3 access service 161 */ 162 int 163 nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 164 { 165 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 166 struct mbuf *nam = nfsd->nd_nam; 167 char *dpos = nfsd->nd_dpos; 168 kauth_cred_t cred = nfsd->nd_cr; 169 struct vnode *vp; 170 nfsrvfh_t nsfh; 171 u_int32_t *tl; 172 int32_t t1; 173 char *bpos; 174 int error = 0, rdonly, cache = 0, getret; 175 char *cp2; 176 struct mbuf *mb, *mreq __unused; 177 struct vattr va; 178 u_long inmode, testmode, outmode; 179 u_quad_t frev; 180 181 nfsm_srvmtofh(&nsfh); 182 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 183 error = nfsrv_fhtovp(&nsfh, 1, &vp, cred, slp, nam, &rdonly, 184 (nfsd->nd_flag & ND_KERBAUTH), false); 185 if (error) { 186 nfsm_reply(NFSX_UNSIGNED); 187 nfsm_srvpostop_attr(1, (struct vattr *)0); 188 return (0); 189 } 190 inmode = fxdr_unsigned(u_int32_t, *tl); 191 outmode = 0; 192 if ((inmode & NFSV3ACCESS_READ) && 193 nfsrv_access(vp, VREAD, cred, rdonly, lwp, 0) == 0) 194 outmode |= NFSV3ACCESS_READ; 195 if (vp->v_type != VDIR) { 196 testmode = inmode & (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND); 197 if (testmode && 198 nfsrv_access(vp, VWRITE, cred, rdonly, lwp, 0) == 0) 199 outmode |= testmode; 200 if ((inmode & NFSV3ACCESS_EXECUTE) && 201 nfsrv_access(vp, VEXEC, cred, rdonly, lwp, 0) == 0) 202 outmode |= NFSV3ACCESS_EXECUTE; 203 } else { 204 testmode = inmode & (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND | 205 NFSV3ACCESS_DELETE); 206 if (testmode && 207 nfsrv_access(vp, VWRITE, cred, rdonly, lwp, 0) == 0) 208 outmode |= testmode; 209 if ((inmode & NFSV3ACCESS_LOOKUP) && 210 nfsrv_access(vp, VEXEC, cred, rdonly, lwp, 0) == 0) 211 outmode |= NFSV3ACCESS_LOOKUP; 212 } 213 getret = VOP_GETATTR(vp, &va, cred); 214 vput(vp); 215 nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED); 216 nfsm_srvpostop_attr(getret, &va); 217 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); 218 *tl = txdr_unsigned(outmode); 219 nfsm_srvdone; 220 } 221 222 /* 223 * nfs getattr service 224 */ 225 int 226 nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 227 { 228 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 229 struct mbuf *nam = nfsd->nd_nam; 230 char *dpos = nfsd->nd_dpos; 231 kauth_cred_t cred = nfsd->nd_cr; 232 struct nfs_fattr *fp; 233 struct vattr va; 234 struct vnode *vp; 235 nfsrvfh_t nsfh; 236 u_int32_t *tl; 237 int32_t t1; 238 char *bpos; 239 int error = 0, rdonly, cache = 0; 240 char *cp2; 241 struct mbuf *mb, *mreq __unused; 242 u_quad_t frev; 243 244 nfsm_srvmtofh(&nsfh); 245 error = nfsrv_fhtovp(&nsfh, 1, &vp, cred, slp, nam, &rdonly, 246 (nfsd->nd_flag & ND_KERBAUTH), false); 247 if (error) { 248 nfsm_reply(0); 249 return (0); 250 } 251 nqsrv_getl(vp, ND_READ); 252 error = VOP_GETATTR(vp, &va, cred); 253 vput(vp); 254 nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3)); 255 if (error) 256 return (0); 257 nfsm_build(fp, struct nfs_fattr *, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3)); 258 nfsm_srvfillattr(&va, fp); 259 nfsm_srvdone; 260 } 261 262 /* 263 * nfs setattr service 264 */ 265 int 266 nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 267 { 268 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 269 struct mbuf *nam = nfsd->nd_nam; 270 char *dpos = nfsd->nd_dpos; 271 kauth_cred_t cred = nfsd->nd_cr; 272 struct vattr va, preat; 273 struct nfsv2_sattr *sp; 274 struct nfs_fattr *fp; 275 struct vnode *vp; 276 nfsrvfh_t nsfh; 277 u_int32_t *tl; 278 int32_t t1; 279 char *bpos; 280 int error = 0, rdonly, cache = 0, preat_ret = 1, postat_ret = 1; 281 int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0; 282 char *cp2; 283 struct mbuf *mb, *mreq __unused; 284 u_quad_t frev; 285 struct timespec guard; 286 287 memset(&guard, 0, sizeof guard); /* XXX gcc */ 288 289 nfsm_srvmtofh(&nsfh); 290 vattr_null(&va); 291 if (v3) { 292 nfsm_srvsattr(&va); 293 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 294 gcheck = fxdr_unsigned(int, *tl); 295 if (gcheck) { 296 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 297 fxdr_nfsv3time(tl, &guard); 298 } 299 } else { 300 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 301 /* 302 * Nah nah nah nah na nah 303 * There is a bug in the Sun client that puts 0xffff in the mode 304 * field of sattr when it should put in 0xffffffff. The u_short 305 * doesn't sign extend. 306 * --> check the low order 2 bytes for 0xffff 307 */ 308 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff) 309 va.va_mode = nfstov_mode(sp->sa_mode); 310 if (sp->sa_uid != nfs_xdrneg1) 311 va.va_uid = fxdr_unsigned(uid_t, sp->sa_uid); 312 if (sp->sa_gid != nfs_xdrneg1) 313 va.va_gid = fxdr_unsigned(gid_t, sp->sa_gid); 314 if (sp->sa_size != nfs_xdrneg1) 315 va.va_size = fxdr_unsigned(u_quad_t, sp->sa_size); 316 if (sp->sa_atime.nfsv2_sec != nfs_xdrneg1) { 317 #ifdef notyet 318 fxdr_nfsv2time(&sp->sa_atime, &va.va_atime); 319 #else 320 va.va_atime.tv_sec = 321 fxdr_unsigned(u_int32_t,sp->sa_atime.nfsv2_sec); 322 va.va_atime.tv_nsec = 0; 323 #endif 324 } 325 if (sp->sa_mtime.nfsv2_sec != nfs_xdrneg1) 326 fxdr_nfsv2time(&sp->sa_mtime, &va.va_mtime); 327 328 } 329 330 /* 331 * Now that we have all the fields, lets do it. 332 */ 333 error = nfsrv_fhtovp(&nsfh, 1, &vp, cred, slp, nam, &rdonly, 334 (nfsd->nd_flag & ND_KERBAUTH), false); 335 if (error) { 336 nfsm_reply(2 * NFSX_UNSIGNED); 337 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va); 338 return (0); 339 } 340 nqsrv_getl(vp, ND_WRITE); 341 if (v3) { 342 error = preat_ret = VOP_GETATTR(vp, &preat, cred); 343 if (!error && gcheck && 344 (preat.va_ctime.tv_sec != guard.tv_sec || 345 preat.va_ctime.tv_nsec != guard.tv_nsec)) 346 error = NFSERR_NOT_SYNC; 347 if (error) { 348 vput(vp); 349 nfsm_reply(NFSX_WCCDATA(v3)); 350 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va); 351 return (0); 352 } 353 } 354 355 /* 356 * If the size is being changed write access is required, otherwise 357 * just check for a read only file system. 358 */ 359 if (va.va_size == ((u_quad_t)((quad_t) -1))) { 360 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) { 361 error = EROFS; 362 goto out; 363 } 364 } else { 365 if (vp->v_type == VDIR) { 366 error = EISDIR; 367 goto out; 368 } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly, 369 lwp, 0)) != 0) 370 goto out; 371 } 372 error = VOP_SETATTR(vp, &va, cred); 373 postat_ret = VOP_GETATTR(vp, &va, cred); 374 if (!error) 375 error = postat_ret; 376 out: 377 vput(vp); 378 nfsm_reply(NFSX_WCCORFATTR(v3)); 379 if (v3) { 380 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va); 381 return (0); 382 } else { 383 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 384 nfsm_srvfillattr(&va, fp); 385 } 386 nfsm_srvdone; 387 } 388 389 /* 390 * nfs lookup rpc 391 */ 392 int 393 nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 394 { 395 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 396 struct mbuf *nam = nfsd->nd_nam; 397 char *dpos = nfsd->nd_dpos; 398 kauth_cred_t cred = nfsd->nd_cr; 399 struct nfs_fattr *fp; 400 struct nameidata nd, ind, *ndp = &nd; 401 struct pathbuf *ipb = NULL; 402 struct vnode *vp, *dirp; 403 nfsrvfh_t nsfh; 404 char *cp; 405 u_int32_t *tl; 406 int32_t t1; 407 char *bpos; 408 int error = 0, cache = 0, dirattr_ret = 1; 409 uint32_t len; 410 int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag; 411 char *cp2; 412 struct mbuf *mb, *mreq __unused; 413 struct vattr va, dirattr; 414 u_quad_t frev; 415 416 nfsm_srvmtofh(&nsfh); 417 nfsm_srvnamesiz(len); 418 419 pubflag = nfs_ispublicfh(&nsfh); 420 421 nd.ni_cnd.cn_cred = cred; 422 nd.ni_cnd.cn_nameiop = LOOKUP; 423 nd.ni_cnd.cn_flags = LOCKLEAF; 424 error = nfs_namei(&nd, &nsfh, len, slp, nam, &md, &dpos, 425 &dirp, NULL, NULL, 426 lwp, (nfsd->nd_flag & ND_KERBAUTH), pubflag); 427 428 if (!error && pubflag) { 429 if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL && 430 (ipb = pathbuf_create(nfs_pub.np_index)) != NULL) { 431 /* 432 * Setup call to lookup() to see if we can find 433 * the index file. Arguably, this doesn't belong 434 * in a kernel.. Ugh. 435 */ 436 ind = nd; 437 VOP_UNLOCK(nd.ni_vp); 438 ind.ni_pathbuf = ipb; 439 440 error = lookup_for_nfsd_index(&ind, nd.ni_vp); 441 if (!error) { 442 /* 443 * Found an index file. Get rid of 444 * the old references. 445 */ 446 if (dirp) 447 vrele(dirp); 448 dirp = nd.ni_vp; 449 ndp = &ind; 450 } else 451 error = 0; 452 } 453 /* 454 * If the public filehandle was used, check that this lookup 455 * didn't result in a filehandle outside the publicly exported 456 * filesystem. 457 */ 458 459 if (!error && ndp->ni_vp->v_mount != nfs_pub.np_mount) { 460 vput(nd.ni_vp); 461 error = EPERM; 462 } 463 } 464 465 if (error) { 466 if (nd.ni_pathbuf != NULL) { 467 pathbuf_destroy(nd.ni_pathbuf); 468 } 469 if (ipb != NULL) { 470 pathbuf_destroy(ipb); 471 } 472 if (dirp) { 473 if (v3) { 474 vn_lock(dirp, LK_SHARED | LK_RETRY); 475 dirattr_ret = VOP_GETATTR(dirp, &dirattr, cred); 476 vput(dirp); 477 } else 478 vrele(dirp); 479 } 480 nfsm_reply(NFSX_POSTOPATTR(v3)); 481 nfsm_srvpostop_attr(dirattr_ret, &dirattr); 482 return (0); 483 } 484 485 nqsrv_getl(ndp->ni_startdir, ND_READ); 486 pathbuf_destroy(nd.ni_pathbuf); 487 if (ipb != NULL) { 488 pathbuf_destroy(ipb); 489 } 490 vp = ndp->ni_vp; 491 error = nfsrv_composefh(vp, &nsfh, v3); 492 if (!error) 493 error = VOP_GETATTR(vp, &va, cred); 494 vput(vp); 495 if (dirp) { 496 if (v3) { 497 vn_lock(dirp, LK_SHARED | LK_RETRY); 498 dirattr_ret = VOP_GETATTR(dirp, &dirattr, cred); 499 vput(dirp); 500 } else 501 vrele(dirp); 502 } 503 nfsm_reply(NFSX_SRVFH(&nsfh, v3) + NFSX_POSTOPORFATTR(v3) + 504 NFSX_POSTOPATTR(v3)); 505 if (error) { 506 nfsm_srvpostop_attr(dirattr_ret, &dirattr); 507 return (0); 508 } 509 nfsm_srvfhtom(&nsfh, v3); 510 if (v3) { 511 nfsm_srvpostop_attr(0, &va); 512 nfsm_srvpostop_attr(dirattr_ret, &dirattr); 513 } else { 514 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 515 nfsm_srvfillattr(&va, fp); 516 } 517 nfsm_srvdone; 518 } 519 520 /* 521 * nfs readlink service 522 */ 523 int 524 nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 525 { 526 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 527 struct mbuf *nam = nfsd->nd_nam; 528 char *dpos = nfsd->nd_dpos; 529 kauth_cred_t cred = nfsd->nd_cr; 530 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN]; 531 struct iovec *ivp = iv; 532 struct mbuf *mp; 533 u_int32_t *tl; 534 int32_t t1; 535 char *bpos; 536 int error = 0, rdonly, cache = 0, i, padlen, getret; 537 uint32_t len; 538 int v3 = (nfsd->nd_flag & ND_NFSV3); 539 char *cp2; 540 struct mbuf *mb, *mp2 = NULL, *mp3 = NULL, *mreq __unused; 541 struct vnode *vp; 542 struct vattr attr; 543 nfsrvfh_t nsfh; 544 struct uio io, *uiop = &io; 545 u_quad_t frev; 546 547 nfsm_srvmtofh(&nsfh); 548 len = 0; 549 i = 0; 550 while (len < NFS_MAXPATHLEN) { 551 mp = m_get(M_WAIT, MT_DATA); 552 MCLAIM(mp, &nfs_mowner); 553 m_clget(mp, M_WAIT); 554 mp->m_len = NFSMSIZ(mp); 555 if (len == 0) 556 mp3 = mp2 = mp; 557 else { 558 mp2->m_next = mp; 559 mp2 = mp; 560 } 561 if ((len+mp->m_len) > NFS_MAXPATHLEN) { 562 mp->m_len = NFS_MAXPATHLEN-len; 563 len = NFS_MAXPATHLEN; 564 } else 565 len += mp->m_len; 566 ivp->iov_base = mtod(mp, void *); 567 ivp->iov_len = mp->m_len; 568 i++; 569 ivp++; 570 } 571 uiop->uio_iov = iv; 572 uiop->uio_iovcnt = i; 573 uiop->uio_offset = 0; 574 uiop->uio_resid = len; 575 uiop->uio_rw = UIO_READ; 576 UIO_SETUP_SYSSPACE(uiop); 577 error = nfsrv_fhtovp(&nsfh, 1, &vp, cred, slp, nam, 578 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), false); 579 if (error) { 580 m_freem(mp3); 581 nfsm_reply(2 * NFSX_UNSIGNED); 582 nfsm_srvpostop_attr(1, (struct vattr *)0); 583 return (0); 584 } 585 if (vp->v_type != VLNK) { 586 if (v3) 587 error = EINVAL; 588 else 589 error = ENXIO; 590 goto out; 591 } 592 nqsrv_getl(vp, ND_READ); 593 error = VOP_READLINK(vp, uiop, cred); 594 out: 595 getret = VOP_GETATTR(vp, &attr, cred); 596 vput(vp); 597 if (error) 598 m_freem(mp3); 599 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED); 600 if (v3) { 601 nfsm_srvpostop_attr(getret, &attr); 602 if (error) 603 return (0); 604 } 605 len -= uiop->uio_resid; 606 padlen = nfsm_padlen(len); 607 if (len == 0) { 608 m_freem(mp3); 609 mp3 = NULL; 610 } else if (uiop->uio_resid || padlen) 611 nfs_zeropad(mp3, uiop->uio_resid, padlen); 612 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); 613 *tl = txdr_unsigned(len); 614 mb->m_next = mp3; 615 nfsm_srvdone; 616 } 617 618 /* 619 * nfs read service 620 */ 621 int 622 nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 623 { 624 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 625 struct mbuf *nam = nfsd->nd_nam; 626 char *dpos = nfsd->nd_dpos; 627 kauth_cred_t cred = nfsd->nd_cr; 628 struct mbuf *m; 629 struct nfs_fattr *fp; 630 u_int32_t *tl; 631 int32_t t1; 632 int i; 633 char *bpos; 634 int error = 0, rdonly, cache = 0, getret; 635 int v3 = (nfsd->nd_flag & ND_NFSV3); 636 uint32_t reqlen, len, cnt, left; 637 int padlen; 638 char *cp2; 639 struct mbuf *mb, *mreq; 640 struct vnode *vp; 641 nfsrvfh_t nsfh; 642 struct uio io, *uiop = &io; 643 struct vattr va; 644 off_t off; 645 u_quad_t frev; 646 647 nfsm_srvmtofh(&nsfh); 648 if (v3) { 649 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 650 off = fxdr_hyper(tl); 651 } else { 652 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 653 off = (off_t)fxdr_unsigned(u_int32_t, *tl); 654 } 655 nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED); 656 reqlen = fxdr_unsigned(uint32_t, *tl); 657 reqlen = MIN(reqlen, NFS_SRVMAXDATA(nfsd)); 658 error = nfsrv_fhtovp(&nsfh, 1, &vp, cred, slp, nam, 659 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), false); 660 if (error) { 661 nfsm_reply(2 * NFSX_UNSIGNED); 662 nfsm_srvpostop_attr(1, (struct vattr *)0); 663 return (0); 664 } 665 if (vp->v_type != VREG) { 666 if (v3) 667 error = EINVAL; 668 else 669 error = (vp->v_type == VDIR) ? EISDIR : EACCES; 670 } 671 if (!error) { 672 nqsrv_getl(vp, ND_READ); 673 if ((error = nfsrv_access(vp, VREAD, cred, rdonly, lwp, 1)) != 0) 674 error = nfsrv_access(vp, VEXEC, cred, rdonly, lwp, 1); 675 } 676 getret = VOP_GETATTR(vp, &va, cred); 677 if (!error) 678 error = getret; 679 if (error) { 680 vput(vp); 681 nfsm_reply(NFSX_POSTOPATTR(v3)); 682 nfsm_srvpostop_attr(getret, &va); 683 return (0); 684 } 685 if (off >= va.va_size) 686 cnt = 0; 687 else if ((off + reqlen) > va.va_size) 688 cnt = va.va_size - off; 689 else 690 cnt = reqlen; 691 nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt)); 692 if (v3) { 693 nfsm_build(tl, u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED); 694 *tl++ = nfs_true; 695 fp = (struct nfs_fattr *)tl; 696 tl += (NFSX_V3FATTR / sizeof (u_int32_t)); 697 } else { 698 nfsm_build(tl, u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED); 699 fp = (struct nfs_fattr *)tl; 700 tl += (NFSX_V2FATTR / sizeof (u_int32_t)); 701 } 702 len = left = cnt; 703 if (cnt > 0) { 704 if (nfsd_use_loan) { 705 struct vm_page **pgpp; 706 voff_t pgoff = trunc_page(off); 707 int npages; 708 vaddr_t lva; 709 710 npages = (round_page(off + cnt) - pgoff) >> PAGE_SHIFT; 711 KASSERT(npages <= M_EXT_MAXPAGES); /* XXX */ 712 713 /* allocate kva for mbuf data */ 714 lva = sokvaalloc(pgoff, npages << PAGE_SHIFT, 715 slp->ns_so); 716 if (lva == 0) { 717 /* fall back to VOP_READ */ 718 goto loan_fail; 719 } 720 721 /* allocate mbuf */ 722 m = m_get(M_WAIT, MT_DATA); 723 MCLAIM(m, &nfs_mowner); 724 pgpp = m->m_ext.ext_pgs; 725 726 /* loan pages */ 727 error = uvm_loanuobjpages(&vp->v_uobj, pgoff, npages, 728 pgpp); 729 if (error) { 730 sokvafree(lva, npages << PAGE_SHIFT); 731 m_free(m); 732 if (error == EBUSY) 733 goto loan_fail; 734 goto read_error; 735 } 736 737 /* associate kva to mbuf */ 738 MEXTADD(m, (void *)(lva + ((vaddr_t)off & PAGE_MASK)), 739 cnt, M_MBUF, soloanfree, slp->ns_so); 740 m->m_flags |= M_EXT_PAGES | M_EXT_ROMAP; 741 m->m_len = cnt; 742 743 /* map pages */ 744 for (i = 0; i < npages; i++) { 745 pmap_kenter_pa(lva, VM_PAGE_TO_PHYS(pgpp[i]), 746 VM_PROT_READ, 0); 747 lva += PAGE_SIZE; 748 } 749 750 pmap_update(pmap_kernel()); 751 752 mb->m_next = m; 753 mb = m; 754 error = 0; 755 uiop->uio_resid = 0; 756 } else { 757 struct iovec *iv; 758 struct iovec *iv2; 759 struct mbuf *m2; 760 int siz; 761 loan_fail: 762 /* 763 * Generate the mbuf list with the uio_iov ref. to it. 764 */ 765 i = 0; 766 m = m2 = mb; 767 while (left > 0) { 768 siz = uimin(M_TRAILINGSPACE(m), left); 769 if (siz > 0) { 770 left -= siz; 771 i++; 772 } 773 if (left > 0) { 774 m = m_get(M_WAIT, MT_DATA); 775 MCLAIM(m, &nfs_mowner); 776 m_clget(m, M_WAIT); 777 m->m_len = 0; 778 m2->m_next = m; 779 m2 = m; 780 } 781 } 782 iv = malloc(i * sizeof(struct iovec), M_TEMP, M_WAITOK); 783 uiop->uio_iov = iv2 = iv; 784 m = mb; 785 left = cnt; 786 i = 0; 787 while (left > 0) { 788 if (m == NULL) 789 panic("nfsrv_read iov"); 790 siz = uimin(M_TRAILINGSPACE(m), left); 791 if (siz > 0) { 792 iv->iov_base = mtod(m, char *) + 793 m->m_len; 794 iv->iov_len = siz; 795 m->m_len += siz; 796 left -= siz; 797 iv++; 798 i++; 799 } 800 m = m->m_next; 801 } 802 uiop->uio_iovcnt = i; 803 uiop->uio_offset = off; 804 uiop->uio_resid = cnt; 805 uiop->uio_rw = UIO_READ; 806 UIO_SETUP_SYSSPACE(uiop); 807 error = VOP_READ(vp, uiop, IO_NODELOCKED, cred); 808 free((void *)iv2, M_TEMP); 809 } 810 read_error: 811 if (error || (getret = VOP_GETATTR(vp, &va, cred)) != 0){ 812 if (!error) 813 error = getret; 814 m_freem(mreq); 815 vput(vp); 816 nfsm_reply(NFSX_POSTOPATTR(v3)); 817 nfsm_srvpostop_attr(getret, &va); 818 return (0); 819 } 820 } else { 821 uiop->uio_resid = 0; 822 } 823 vput(vp); 824 nfsm_srvfillattr(&va, fp); 825 len -= uiop->uio_resid; 826 padlen = nfsm_padlen(len); 827 if (uiop->uio_resid || padlen) 828 nfs_zeropad(mb, uiop->uio_resid, padlen); 829 if (v3) { 830 /* count */ 831 *tl++ = txdr_unsigned(len); 832 /* eof */ 833 if (off + len >= va.va_size) 834 *tl++ = nfs_true; 835 else 836 *tl++ = nfs_false; 837 } 838 *tl = txdr_unsigned(len); 839 nfsm_srvdone; 840 } 841 842 /* 843 * nfs write service 844 */ 845 int 846 nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 847 { 848 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 849 struct mbuf *nam = nfsd->nd_nam; 850 char *dpos = nfsd->nd_dpos; 851 kauth_cred_t cred = nfsd->nd_cr; 852 struct iovec *ivp; 853 int i, cnt; 854 struct mbuf *mp; 855 struct nfs_fattr *fp; 856 struct iovec *iv; 857 struct vattr va, forat; 858 u_int32_t *tl; 859 int32_t t1; 860 char *bpos; 861 int error = 0, rdonly, cache = 0, len, forat_ret = 1; 862 int ioflags, aftat_ret = 1, retlen, zeroing, adjust; 863 int stable = NFSV3WRITE_FILESYNC; 864 int v3 = (nfsd->nd_flag & ND_NFSV3); 865 char *cp2; 866 struct mbuf *mb, *mreq __unused; 867 struct vnode *vp; 868 nfsrvfh_t nsfh; 869 struct uio io, *uiop = &io; 870 off_t off; 871 u_quad_t frev; 872 873 if (mrep == NULL) { 874 *mrq = NULL; 875 return (0); 876 } 877 nfsm_srvmtofh(&nsfh); 878 if (v3) { 879 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 880 off = fxdr_hyper(tl); 881 tl += 3; 882 stable = fxdr_unsigned(int, *tl++); 883 } else { 884 nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 885 off = (off_t)fxdr_unsigned(u_int32_t, *++tl); 886 tl += 2; 887 } 888 retlen = len = fxdr_unsigned(int32_t, *tl); 889 cnt = i = 0; 890 891 /* 892 * For NFS Version 2, it is not obvious what a write of zero length 893 * should do, but I might as well be consistent with Version 3, 894 * which is to return ok so long as there are no permission problems. 895 */ 896 if (len > 0) { 897 zeroing = 1; 898 mp = mrep; 899 while (mp) { 900 if (mp == md) { 901 zeroing = 0; 902 adjust = dpos - mtod(mp, char *); 903 mp->m_len -= adjust; 904 if (mp->m_len > 0 && adjust > 0) 905 NFSMADV(mp, adjust); 906 } 907 if (zeroing) 908 mp->m_len = 0; 909 else if (mp->m_len > 0) { 910 i += mp->m_len; 911 if (i > len) { 912 mp->m_len -= (i - len); 913 zeroing = 1; 914 } 915 if (mp->m_len > 0) 916 cnt++; 917 } 918 mp = mp->m_next; 919 } 920 } 921 if (len > NFS_MAXDATA || len < 0 || i < len) { 922 error = EIO; 923 nfsm_reply(2 * NFSX_UNSIGNED); 924 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va); 925 return (0); 926 } 927 error = nfsrv_fhtovp(&nsfh, 1, &vp, cred, slp, nam, 928 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), false); 929 if (error) { 930 nfsm_reply(2 * NFSX_UNSIGNED); 931 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va); 932 return (0); 933 } 934 if (v3) 935 forat_ret = VOP_GETATTR(vp, &forat, cred); 936 if (vp->v_type != VREG) { 937 if (v3) 938 error = EINVAL; 939 else 940 error = (vp->v_type == VDIR) ? EISDIR : EACCES; 941 } 942 if (!error) { 943 nqsrv_getl(vp, ND_WRITE); 944 error = nfsrv_access(vp, VWRITE, cred, rdonly, lwp, 1); 945 } 946 if (error) { 947 vput(vp); 948 nfsm_reply(NFSX_WCCDATA(v3)); 949 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va); 950 return (0); 951 } 952 953 if (len > 0) { 954 ivp = malloc(cnt * sizeof (struct iovec), M_TEMP, M_WAITOK); 955 uiop->uio_iov = iv = ivp; 956 uiop->uio_iovcnt = cnt; 957 mp = mrep; 958 while (mp) { 959 if (mp->m_len > 0) { 960 ivp->iov_base = mtod(mp, void *); 961 ivp->iov_len = mp->m_len; 962 ivp++; 963 } 964 mp = mp->m_next; 965 } 966 967 /* 968 * XXX 969 * The IO_METASYNC flag indicates that all metadata (and not 970 * just enough to ensure data integrity) must be written to 971 * stable storage synchronously. 972 * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.) 973 */ 974 if (stable == NFSV3WRITE_UNSTABLE) 975 ioflags = IO_NODELOCKED; 976 else if (stable == NFSV3WRITE_DATASYNC) 977 ioflags = (IO_SYNC | IO_NODELOCKED); 978 else 979 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED); 980 uiop->uio_resid = len; 981 uiop->uio_rw = UIO_WRITE; 982 uiop->uio_offset = off; 983 UIO_SETUP_SYSSPACE(uiop); 984 error = VOP_WRITE(vp, uiop, ioflags, cred); 985 nfsstats.srvvop_writes++; 986 free(iv, M_TEMP); 987 } 988 aftat_ret = VOP_GETATTR(vp, &va, cred); 989 vput(vp); 990 if (!error) 991 error = aftat_ret; 992 nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) + 993 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3)); 994 if (v3) { 995 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va); 996 if (error) 997 return (0); 998 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 999 *tl++ = txdr_unsigned(retlen); 1000 if (stable == NFSV3WRITE_UNSTABLE) 1001 *tl++ = txdr_unsigned(stable); 1002 else 1003 *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC); 1004 /* 1005 * Actually, there is no need to txdr these fields, 1006 * but it may make the values more human readable, 1007 * for debugging purposes. 1008 */ 1009 struct timeval btv; 1010 getmicroboottime(&btv); 1011 *tl++ = txdr_unsigned(btv.tv_sec); 1012 *tl = txdr_unsigned(btv.tv_usec); 1013 } else { 1014 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 1015 nfsm_srvfillattr(&va, fp); 1016 } 1017 nfsm_srvdone; 1018 } 1019 1020 /* 1021 * XXX elad: the original NFSW_SAMECRED() macro also made sure the 1022 * two nd_flag fields of the descriptors contained 1023 * ND_KERBAUTH. 1024 */ 1025 static int 1026 nfsrv_samecred(kauth_cred_t cred1, kauth_cred_t cred2) 1027 { 1028 int i, do_ngroups; 1029 1030 if (kauth_cred_geteuid(cred1) != kauth_cred_geteuid(cred2)) 1031 return (0); 1032 if (kauth_cred_ngroups(cred1) != kauth_cred_ngroups(cred2)) 1033 return (0); 1034 do_ngroups = kauth_cred_ngroups(cred1); 1035 for (i = 0; i < do_ngroups; i++) 1036 if (kauth_cred_group(cred1, i) != 1037 kauth_cred_group(cred2, i)) 1038 return (0); 1039 1040 return (1); 1041 } 1042 1043 static struct nfsrvw_delayhash * 1044 nfsrv_nwdelayhash(struct nfssvc_sock *slp, const nfsrvfh_t *nsfh) 1045 { 1046 uint32_t hash; 1047 1048 hash = hash32_buf(NFSRVFH_DATA(nsfh), NFSRVFH_SIZE(nsfh), 1049 HASH32_BUF_INIT); 1050 return &slp->ns_wdelayhashtbl[hash % NFS_WDELAYHASHSIZ]; 1051 } 1052 1053 /* 1054 * NFS write service with write gathering support. Called when 1055 * nfsrvw_procrastinate > 0. 1056 * See: Chet Juszczak, "Improving the Write Performance of an NFS Server", 1057 * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco, 1058 * Jan. 1994. 1059 */ 1060 int 1061 nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 1062 { 1063 struct timeval now; 1064 struct iovec *ivp; 1065 struct mbuf *mp; 1066 struct nfsrv_descript *wp, *nfsd, *owp, *swp; 1067 struct nfs_fattr *fp; 1068 int i = 0; 1069 struct iovec *iov; 1070 struct nfsrvw_delayhash *wpp; 1071 kauth_cred_t cred; 1072 struct vattr va, forat; 1073 u_int32_t *tl; 1074 int32_t t1; 1075 char *bpos, *dpos; 1076 int error = 0, rdonly, cache = 0, len = 0, forat_ret = 1; 1077 int ioflags, aftat_ret = 1, adjust, v3, zeroing; 1078 char *cp2; 1079 struct mbuf *mb, *mreq, *mrep, *md; 1080 struct vnode *vp; 1081 struct uio io, *uiop = &io; 1082 u_quad_t frev, cur_usec; 1083 1084 *mrq = NULL; 1085 if (*ndp) { 1086 nfsd = *ndp; 1087 *ndp = NULL; 1088 mrep = nfsd->nd_mrep; 1089 md = nfsd->nd_md; 1090 dpos = nfsd->nd_dpos; 1091 cred = nfsd->nd_cr; 1092 v3 = (nfsd->nd_flag & ND_NFSV3); 1093 LIST_INIT(&nfsd->nd_coalesce); 1094 nfsd->nd_mreq = NULL; 1095 nfsd->nd_stable = NFSV3WRITE_FILESYNC; 1096 getmicrotime(&now); 1097 cur_usec = (u_quad_t)now.tv_sec * 1000000 + (u_quad_t)now.tv_usec; 1098 nfsd->nd_time = cur_usec + nfsrvw_procrastinate; 1099 1100 /* 1101 * Now, get the write header.. 1102 */ 1103 nfsm_srvmtofh(&nfsd->nd_fh); 1104 if (v3) { 1105 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 1106 nfsd->nd_off = fxdr_hyper(tl); 1107 tl += 3; 1108 nfsd->nd_stable = fxdr_unsigned(int, *tl++); 1109 } else { 1110 nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 1111 nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl); 1112 tl += 2; 1113 } 1114 len = fxdr_unsigned(int32_t, *tl); 1115 nfsd->nd_len = len; 1116 nfsd->nd_eoff = nfsd->nd_off + len; 1117 1118 /* 1119 * Trim the header out of the mbuf list and trim off any trailing 1120 * junk so that the mbuf list has only the write data. 1121 */ 1122 zeroing = 1; 1123 i = 0; 1124 mp = mrep; 1125 while (mp) { 1126 if (mp == md) { 1127 zeroing = 0; 1128 adjust = dpos - mtod(mp, char *); 1129 mp->m_len -= adjust; 1130 if (mp->m_len > 0 && adjust > 0) 1131 NFSMADV(mp, adjust); 1132 } 1133 if (zeroing) 1134 mp->m_len = 0; 1135 else { 1136 i += mp->m_len; 1137 if (i > len) { 1138 mp->m_len -= (i - len); 1139 zeroing = 1; 1140 } 1141 } 1142 mp = mp->m_next; 1143 } 1144 if (len > NFS_MAXDATA || len < 0 || i < len) { 1145 nfsmout: 1146 m_freem(mrep); 1147 error = EIO; 1148 nfsm_writereply(2 * NFSX_UNSIGNED, v3); 1149 if (v3) 1150 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va); 1151 nfsd->nd_mreq = mreq; 1152 nfsd->nd_mrep = NULL; 1153 nfsd->nd_time = 0; 1154 } 1155 1156 /* 1157 * Add this entry to the hash and time queues. 1158 */ 1159 owp = NULL; 1160 mutex_enter(&nfsd_lock); 1161 wp = LIST_FIRST(&slp->ns_tq); 1162 while (wp && wp->nd_time < nfsd->nd_time) { 1163 owp = wp; 1164 wp = LIST_NEXT(wp, nd_tq); 1165 } 1166 if (owp) { 1167 LIST_INSERT_AFTER(owp, nfsd, nd_tq); 1168 } else { 1169 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq); 1170 } 1171 if (nfsd->nd_mrep) { 1172 wpp = nfsrv_nwdelayhash(slp, &nfsd->nd_fh); 1173 owp = NULL; 1174 wp = LIST_FIRST(wpp); 1175 while (wp && nfsrv_comparefh(&nfsd->nd_fh, &wp->nd_fh)) { 1176 owp = wp; 1177 wp = LIST_NEXT(wp, nd_hash); 1178 } 1179 while (wp && wp->nd_off < nfsd->nd_off && 1180 !nfsrv_comparefh(&nfsd->nd_fh, &wp->nd_fh)) { 1181 owp = wp; 1182 wp = LIST_NEXT(wp, nd_hash); 1183 } 1184 if (owp) { 1185 LIST_INSERT_AFTER(owp, nfsd, nd_hash); 1186 1187 /* 1188 * Search the hash list for overlapping entries and 1189 * coalesce. 1190 */ 1191 for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) { 1192 wp = LIST_NEXT(nfsd, nd_hash); 1193 if (nfsrv_samecred(owp->nd_cr, nfsd->nd_cr)) 1194 nfsrvw_coalesce(owp, nfsd); 1195 } 1196 } else { 1197 LIST_INSERT_HEAD(wpp, nfsd, nd_hash); 1198 } 1199 } 1200 mutex_exit(&nfsd_lock); 1201 } 1202 1203 /* 1204 * Now, do VOP_WRITE()s for any one(s) that need to be done now 1205 * and generate the associated reply mbuf list(s). 1206 */ 1207 loop1: 1208 getmicrotime(&now); 1209 cur_usec = (u_quad_t)now.tv_sec * 1000000 + (u_quad_t)now.tv_usec; 1210 mutex_enter(&nfsd_lock); 1211 for (nfsd = LIST_FIRST(&slp->ns_tq); nfsd; nfsd = owp) { 1212 owp = LIST_NEXT(nfsd, nd_tq); 1213 if (nfsd->nd_time > cur_usec) 1214 break; 1215 if (nfsd->nd_mreq) 1216 continue; 1217 LIST_REMOVE(nfsd, nd_tq); 1218 LIST_REMOVE(nfsd, nd_hash); 1219 mutex_exit(&nfsd_lock); 1220 1221 mrep = nfsd->nd_mrep; 1222 nfsd->nd_mrep = NULL; 1223 cred = nfsd->nd_cr; 1224 v3 = (nfsd->nd_flag & ND_NFSV3); 1225 forat_ret = aftat_ret = 1; 1226 error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp, 1227 nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH), 1228 false); 1229 if (!error) { 1230 if (v3) 1231 forat_ret = VOP_GETATTR(vp, &forat, cred); 1232 if (vp->v_type != VREG) { 1233 if (v3) 1234 error = EINVAL; 1235 else 1236 error = (vp->v_type == VDIR) ? EISDIR : EACCES; 1237 } 1238 } else 1239 vp = NULL; 1240 if (!error) { 1241 nqsrv_getl(vp, ND_WRITE); 1242 error = nfsrv_access(vp, VWRITE, cred, rdonly, lwp, 1); 1243 } 1244 1245 if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE) 1246 ioflags = IO_NODELOCKED; 1247 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC) 1248 ioflags = (IO_SYNC | IO_NODELOCKED); 1249 else 1250 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED); 1251 uiop->uio_rw = UIO_WRITE; 1252 uiop->uio_offset = nfsd->nd_off; 1253 uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off; 1254 UIO_SETUP_SYSSPACE(uiop); 1255 if (uiop->uio_resid > 0) { 1256 mp = mrep; 1257 i = 0; 1258 while (mp) { 1259 if (mp->m_len > 0) 1260 i++; 1261 mp = mp->m_next; 1262 } 1263 uiop->uio_iovcnt = i; 1264 iov = malloc(i * sizeof (struct iovec), M_TEMP, M_WAITOK); 1265 uiop->uio_iov = ivp = iov; 1266 mp = mrep; 1267 while (mp) { 1268 if (mp->m_len > 0) { 1269 ivp->iov_base = mtod(mp, void *); 1270 ivp->iov_len = mp->m_len; 1271 ivp++; 1272 } 1273 mp = mp->m_next; 1274 } 1275 if (!error) { 1276 error = VOP_WRITE(vp, uiop, ioflags, cred); 1277 nfsstats.srvvop_writes++; 1278 } 1279 free((void *)iov, M_TEMP); 1280 } 1281 m_freem(mrep); 1282 if (vp) { 1283 aftat_ret = VOP_GETATTR(vp, &va, cred); 1284 vput(vp); 1285 } 1286 1287 /* 1288 * Loop around generating replies for all write rpcs that have 1289 * now been completed. 1290 */ 1291 swp = nfsd; 1292 do { 1293 if (error) { 1294 nfsm_writereply(NFSX_WCCDATA(v3), v3); 1295 if (v3) { 1296 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va); 1297 } 1298 } else { 1299 nfsm_writereply(NFSX_PREOPATTR(v3) + 1300 NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED + 1301 NFSX_WRITEVERF(v3), v3); 1302 if (v3) { 1303 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va); 1304 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 1305 *tl++ = txdr_unsigned(nfsd->nd_len); 1306 *tl++ = txdr_unsigned(swp->nd_stable); 1307 /* 1308 * Actually, there is no need to txdr these fields, 1309 * but it may make the values more human readable, 1310 * for debugging purposes. 1311 */ 1312 struct timeval btv; 1313 getmicroboottime(&btv); 1314 *tl++ = txdr_unsigned(btv.tv_sec); 1315 *tl = txdr_unsigned(btv.tv_usec); 1316 } else { 1317 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 1318 nfsm_srvfillattr(&va, fp); 1319 } 1320 } 1321 nfsd->nd_mreq = mreq; 1322 if (nfsd->nd_mrep) 1323 panic("nfsrv_write: nd_mrep not free"); 1324 1325 /* 1326 * Done. Put it at the head of the timer queue so that 1327 * the final phase can return the reply. 1328 */ 1329 mutex_enter(&nfsd_lock); 1330 if (nfsd != swp) { 1331 nfsd->nd_time = 0; 1332 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq); 1333 } 1334 nfsd = LIST_FIRST(&swp->nd_coalesce); 1335 if (nfsd) { 1336 LIST_REMOVE(nfsd, nd_tq); 1337 } 1338 mutex_exit(&nfsd_lock); 1339 } while (nfsd); 1340 swp->nd_time = 0; 1341 1342 mutex_enter(&nfsd_lock); 1343 LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq); 1344 mutex_exit(&nfsd_lock); 1345 goto loop1; 1346 } 1347 mutex_exit(&nfsd_lock); 1348 nfs_timer_start(); 1349 1350 /* 1351 * Search for a reply to return. 1352 */ 1353 mutex_enter(&nfsd_lock); 1354 LIST_FOREACH(nfsd, &slp->ns_tq, nd_tq) { 1355 if (nfsd->nd_mreq) { 1356 LIST_REMOVE(nfsd, nd_tq); 1357 *mrq = nfsd->nd_mreq; 1358 *ndp = nfsd; 1359 break; 1360 } 1361 } 1362 mutex_exit(&nfsd_lock); 1363 return (0); 1364 } 1365 1366 /* 1367 * Coalesce the write request nfsd into owp. To do this we must: 1368 * - remove nfsd from the queues 1369 * - merge nfsd->nd_mrep into owp->nd_mrep 1370 * - update the nd_eoff and nd_stable for owp 1371 * - put nfsd on owp's nd_coalesce list 1372 * NB: Must be called at splsoftclock(). 1373 */ 1374 void 1375 nfsrvw_coalesce(struct nfsrv_descript *owp, struct nfsrv_descript *nfsd) 1376 { 1377 int overlap; 1378 struct mbuf *mp; 1379 struct nfsrv_descript *m; 1380 1381 KASSERT(mutex_owned(&nfsd_lock)); 1382 1383 LIST_REMOVE(nfsd, nd_hash); 1384 LIST_REMOVE(nfsd, nd_tq); 1385 if (owp->nd_eoff < nfsd->nd_eoff) { 1386 overlap = owp->nd_eoff - nfsd->nd_off; 1387 if (overlap < 0) 1388 panic("nfsrv_coalesce: bad off"); 1389 if (overlap > 0) 1390 m_adj(nfsd->nd_mrep, overlap); 1391 mp = owp->nd_mrep; 1392 while (mp->m_next) 1393 mp = mp->m_next; 1394 mp->m_next = nfsd->nd_mrep; 1395 owp->nd_eoff = nfsd->nd_eoff; 1396 } else 1397 m_freem(nfsd->nd_mrep); 1398 nfsd->nd_mrep = NULL; 1399 if (nfsd->nd_stable == NFSV3WRITE_FILESYNC) 1400 owp->nd_stable = NFSV3WRITE_FILESYNC; 1401 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC && 1402 owp->nd_stable == NFSV3WRITE_UNSTABLE) 1403 owp->nd_stable = NFSV3WRITE_DATASYNC; 1404 LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq); 1405 /* 1406 * nfsd might hold coalesce elements! Move them to owp. 1407 * Otherwise, requests may be lost and clients will be stuck. 1408 */ 1409 while ((m = LIST_FIRST(&nfsd->nd_coalesce)) != NULL) { 1410 LIST_REMOVE(m, nd_tq); 1411 LIST_INSERT_HEAD(&owp->nd_coalesce, m, nd_tq); 1412 } 1413 } 1414 1415 /* 1416 * nfs create service 1417 * now does a truncate to 0 length via. setattr if it already exists 1418 */ 1419 int 1420 nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 1421 { 1422 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 1423 struct mbuf *nam = nfsd->nd_nam; 1424 char *dpos = nfsd->nd_dpos; 1425 kauth_cred_t cred = nfsd->nd_cr; 1426 struct nfs_fattr *fp; 1427 struct vattr va, dirfor, diraft; 1428 struct nfsv2_sattr *sp; 1429 u_int32_t *tl; 1430 struct nameidata nd; 1431 char *cp; 1432 int32_t t1; 1433 char *bpos; 1434 int error = 0, cache = 0, len, tsize, dirfor_ret = 1, diraft_ret = 1; 1435 int rdev = 0, abort = 0; 1436 int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0; 1437 char *cp2; 1438 struct mbuf *mb, *mreq __unused; 1439 struct vnode *vp = NULL, *dirp = NULL; 1440 nfsrvfh_t nsfh; 1441 u_quad_t frev, tempsize; 1442 u_char cverf[NFSX_V3CREATEVERF]; 1443 1444 nd.ni_cnd.cn_nameiop = 0; 1445 nfsm_srvmtofh(&nsfh); 1446 nfsm_srvnamesiz(len); 1447 nd.ni_cnd.cn_cred = cred; 1448 nd.ni_cnd.cn_nameiop = CREATE; 1449 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; 1450 error = nfs_namei(&nd, &nsfh, len, slp, nam, &md, &dpos, 1451 &dirp, (v3 ? &dirfor_ret : NULL), &dirfor, 1452 lwp, (nfsd->nd_flag & ND_KERBAUTH), false); 1453 if (error) { 1454 nfsm_reply(NFSX_WCCDATA(v3)); 1455 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1456 if (dirp) 1457 vrele(dirp); 1458 if (nd.ni_pathbuf != NULL) { 1459 pathbuf_destroy(nd.ni_pathbuf); 1460 nd.ni_pathbuf = NULL; 1461 } 1462 return (0); 1463 } 1464 abort = 1; 1465 vattr_null(&va); 1466 if (v3) { 1467 va.va_mode = 0; 1468 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1469 how = fxdr_unsigned(int, *tl); 1470 switch (how) { 1471 case NFSV3CREATE_GUARDED: 1472 if (nd.ni_vp) { 1473 error = EEXIST; 1474 break; 1475 } 1476 /* FALLTHROUGH */ 1477 case NFSV3CREATE_UNCHECKED: 1478 nfsm_srvsattr(&va); 1479 break; 1480 case NFSV3CREATE_EXCLUSIVE: 1481 nfsm_dissect(cp, void *, NFSX_V3CREATEVERF); 1482 memcpy(cverf, cp, NFSX_V3CREATEVERF); 1483 exclusive_flag = 1; 1484 break; 1485 }; 1486 va.va_type = VREG; 1487 } else { 1488 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1489 va.va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode)); 1490 if (va.va_type == VNON) 1491 va.va_type = VREG; 1492 va.va_mode = nfstov_mode(sp->sa_mode); 1493 switch (va.va_type) { 1494 case VREG: 1495 tsize = fxdr_unsigned(int32_t, sp->sa_size); 1496 if (tsize != -1) 1497 va.va_size = (u_quad_t)tsize; 1498 break; 1499 case VCHR: 1500 case VBLK: 1501 case VFIFO: 1502 rdev = fxdr_unsigned(int32_t, sp->sa_size); 1503 break; 1504 default: 1505 break; 1506 }; 1507 } 1508 1509 /* 1510 * Iff doesn't exist, create it 1511 * otherwise just truncate to 0 length 1512 * should I set the mode too ?? 1513 */ 1514 if (nd.ni_vp == NULL) { 1515 if (va.va_type == VREG || va.va_type == VSOCK) { 1516 nqsrv_getl(nd.ni_dvp, ND_WRITE); 1517 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va); 1518 if (!error) { 1519 vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY); 1520 if (exclusive_flag) { 1521 exclusive_flag = 0; 1522 vattr_null(&va); 1523 /* 1524 * XXX 1525 * assuming NFSX_V3CREATEVERF 1526 * == sizeof(nfstime3) 1527 */ 1528 fxdr_nfsv3time(cverf, &va.va_atime); 1529 error = VOP_SETATTR(nd.ni_vp, &va, 1530 cred); 1531 } 1532 } 1533 } else if (va.va_type == VCHR || va.va_type == VBLK || 1534 va.va_type == VFIFO) { 1535 if (va.va_type == VCHR && rdev == 0xffffffff) 1536 va.va_type = VFIFO; 1537 if (va.va_type != VFIFO && 1538 (error = kauth_authorize_system(cred, 1539 KAUTH_SYSTEM_MKNOD, 0, NULL, NULL, NULL))) { 1540 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1541 vput(nd.ni_dvp); 1542 abort = 0; 1543 nfsm_reply(0); 1544 if (nd.ni_pathbuf != NULL) { 1545 pathbuf_destroy(nd.ni_pathbuf); 1546 nd.ni_pathbuf = NULL; 1547 } 1548 return (error); 1549 } else 1550 va.va_rdev = (dev_t)rdev; 1551 nqsrv_getl(nd.ni_dvp, ND_WRITE); 1552 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, 1553 &va); 1554 if (!error) { 1555 vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY); 1556 } else { 1557 nfsm_reply(0); 1558 } 1559 } else { 1560 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1561 if (nd.ni_pathbuf != NULL) { 1562 pathbuf_destroy(nd.ni_pathbuf); 1563 nd.ni_pathbuf = NULL; 1564 } 1565 error = ENXIO; 1566 abort = 0; 1567 } 1568 vp = nd.ni_vp; 1569 } else { 1570 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1571 if (nd.ni_pathbuf != NULL) { 1572 pathbuf_destroy(nd.ni_pathbuf); 1573 nd.ni_pathbuf = NULL; 1574 } 1575 vp = nd.ni_vp; 1576 abort = 0; 1577 if (!error && va.va_size != -1) { 1578 error = nfsrv_access(vp, VWRITE, cred, 1579 (nd.ni_cnd.cn_flags & RDONLY), lwp, 0); 1580 if (!error) { 1581 nqsrv_getl(vp, ND_WRITE); 1582 tempsize = va.va_size; 1583 vattr_null(&va); 1584 va.va_size = tempsize; 1585 error = VOP_SETATTR(vp, &va, cred); 1586 } 1587 } 1588 if (error) 1589 vput(vp); 1590 } 1591 if (!error) { 1592 error = nfsrv_composefh(vp, &nsfh, v3); 1593 if (!error) 1594 error = VOP_GETATTR(vp, &va, cred); 1595 vput(vp); 1596 } 1597 if (nd.ni_dvp == vp) 1598 vrele(nd.ni_dvp); 1599 else 1600 vput(nd.ni_dvp); 1601 if (v3) { 1602 if (exclusive_flag && !error) { 1603 /* 1604 * XXX assuming NFSX_V3CREATEVERF == sizeof(nfstime3) 1605 */ 1606 char oldverf[NFSX_V3CREATEVERF]; 1607 1608 txdr_nfsv3time(&va.va_atime, oldverf); 1609 if (memcmp(cverf, oldverf, NFSX_V3CREATEVERF)) 1610 error = EEXIST; 1611 } 1612 if (dirp) { 1613 vn_lock(dirp, LK_SHARED | LK_RETRY); 1614 diraft_ret = VOP_GETATTR(dirp, &diraft, cred); 1615 VOP_UNLOCK(dirp); 1616 } 1617 } 1618 if (dirp) { 1619 vrele(dirp); 1620 dirp = NULL; 1621 } 1622 if (nd.ni_pathbuf != NULL) { 1623 pathbuf_destroy(nd.ni_pathbuf); 1624 nd.ni_pathbuf = NULL; 1625 } 1626 abort = 0; 1627 nfsm_reply(NFSX_SRVFH(&nsfh, v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3)); 1628 if (v3) { 1629 if (!error) { 1630 nfsm_srvpostop_fh(&nsfh); 1631 nfsm_srvpostop_attr(0, &va); 1632 } 1633 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1634 } else { 1635 nfsm_srvfhtom(&nsfh, v3); 1636 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 1637 nfsm_srvfillattr(&va, fp); 1638 } 1639 return (0); 1640 nfsmout: 1641 if (dirp) 1642 vrele(dirp); 1643 if (abort) { 1644 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1645 if (nd.ni_dvp == nd.ni_vp) 1646 vrele(nd.ni_dvp); 1647 else 1648 vput(nd.ni_dvp); 1649 if (nd.ni_vp) 1650 vput(nd.ni_vp); 1651 if (nd.ni_pathbuf != NULL) { 1652 pathbuf_destroy(nd.ni_pathbuf); 1653 nd.ni_pathbuf = NULL; 1654 } 1655 } 1656 return (error); 1657 } 1658 1659 /* 1660 * nfs v3 mknod service 1661 */ 1662 int 1663 nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 1664 { 1665 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 1666 struct mbuf *nam = nfsd->nd_nam; 1667 char *dpos = nfsd->nd_dpos; 1668 kauth_cred_t cred = nfsd->nd_cr; 1669 struct vattr va, dirfor, diraft; 1670 u_int32_t *tl; 1671 struct nameidata nd; 1672 int32_t t1; 1673 char *bpos; 1674 int error = 0, cache = 0, len, dirfor_ret = 1, diraft_ret = 1; 1675 int abort = 0; 1676 u_int32_t major, minor; 1677 enum vtype vtyp; 1678 char *cp2; 1679 struct mbuf *mb, *mreq __unused; 1680 struct vnode *vp, *dirp = (struct vnode *)0; 1681 nfsrvfh_t nsfh; 1682 u_quad_t frev; 1683 1684 nd.ni_cnd.cn_nameiop = 0; 1685 nfsm_srvmtofh(&nsfh); 1686 nfsm_srvnamesiz(len); 1687 nd.ni_cnd.cn_cred = cred; 1688 nd.ni_cnd.cn_nameiop = CREATE; 1689 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; 1690 error = nfs_namei(&nd, &nsfh, len, slp, nam, &md, &dpos, 1691 &dirp, &dirfor_ret, &dirfor, 1692 lwp, (nfsd->nd_flag & ND_KERBAUTH), false); 1693 if (error) { 1694 nfsm_reply(NFSX_WCCDATA(1)); 1695 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1696 if (dirp) 1697 vrele(dirp); 1698 if (nd.ni_pathbuf != NULL) { 1699 pathbuf_destroy(nd.ni_pathbuf); 1700 nd.ni_pathbuf = NULL; 1701 } 1702 return (0); 1703 } 1704 abort = 1; 1705 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1706 vtyp = nfsv3tov_type(*tl); 1707 if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) { 1708 error = NFSERR_BADTYPE; 1709 goto abort; 1710 } 1711 vattr_null(&va); 1712 va.va_mode = 0; 1713 nfsm_srvsattr(&va); 1714 if (vtyp == VCHR || vtyp == VBLK) { 1715 dev_t rdev; 1716 1717 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1718 major = fxdr_unsigned(u_int32_t, *tl++); 1719 minor = fxdr_unsigned(u_int32_t, *tl); 1720 rdev = makedev(major, minor); 1721 if (major(rdev) != major || minor(rdev) != minor) { 1722 error = EINVAL; 1723 goto abort; 1724 } 1725 va.va_rdev = rdev; 1726 } 1727 1728 /* 1729 * Iff doesn't exist, create it. 1730 */ 1731 if (nd.ni_vp) { 1732 error = EEXIST; 1733 abort: 1734 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1735 if (nd.ni_vp) 1736 vput(nd.ni_vp); 1737 if (nd.ni_pathbuf != NULL) { 1738 pathbuf_destroy(nd.ni_pathbuf); 1739 nd.ni_pathbuf = NULL; 1740 } 1741 goto out; 1742 } 1743 va.va_type = vtyp; 1744 if (vtyp == VSOCK) { 1745 nqsrv_getl(nd.ni_dvp, ND_WRITE); 1746 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va); 1747 } else { 1748 if (va.va_type != VFIFO && 1749 (error = kauth_authorize_system(cred, 1750 KAUTH_SYSTEM_MKNOD, 0, NULL, NULL, NULL))) { 1751 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1752 vput(nd.ni_dvp); 1753 goto out; 1754 } 1755 nqsrv_getl(nd.ni_dvp, ND_WRITE); 1756 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va); 1757 if (error) 1758 goto out; 1759 } 1760 if (!error) { 1761 vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY); 1762 } 1763 out: 1764 vp = nd.ni_vp; 1765 if (!error) { 1766 error = nfsrv_composefh(vp, &nsfh, true); 1767 if (!error) 1768 error = VOP_GETATTR(vp, &va, cred); 1769 vput(vp); 1770 } 1771 if (nd.ni_dvp == nd.ni_vp) 1772 vrele(nd.ni_dvp); 1773 else 1774 vput(nd.ni_dvp); 1775 if (dirp) { 1776 vn_lock(dirp, LK_SHARED | LK_RETRY); 1777 diraft_ret = VOP_GETATTR(dirp, &diraft, cred); 1778 VOP_UNLOCK(dirp); 1779 vrele(dirp); 1780 dirp = NULL; 1781 } 1782 if (nd.ni_pathbuf != NULL) { 1783 pathbuf_destroy(nd.ni_pathbuf); 1784 nd.ni_pathbuf = NULL; 1785 } 1786 abort = 0; 1787 nfsm_reply(NFSX_SRVFH(&nsfh, true) + NFSX_POSTOPATTR(1) + 1788 NFSX_WCCDATA(1)); 1789 if (!error) { 1790 nfsm_srvpostop_fh(&nsfh); 1791 nfsm_srvpostop_attr(0, &va); 1792 } 1793 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1794 return (0); 1795 nfsmout: 1796 if (abort) { 1797 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1798 if (nd.ni_dvp == nd.ni_vp) 1799 vrele(nd.ni_dvp); 1800 else 1801 vput(nd.ni_dvp); 1802 if (nd.ni_vp) 1803 vput(nd.ni_vp); 1804 if (nd.ni_pathbuf != NULL) { 1805 pathbuf_destroy(nd.ni_pathbuf); 1806 nd.ni_pathbuf = NULL; 1807 } 1808 } 1809 if (dirp) 1810 vrele(dirp); 1811 return (error); 1812 } 1813 1814 /* 1815 * nfs remove service 1816 */ 1817 int 1818 nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 1819 { 1820 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 1821 struct mbuf *nam = nfsd->nd_nam; 1822 char *dpos = nfsd->nd_dpos; 1823 kauth_cred_t cred = nfsd->nd_cr; 1824 struct nameidata nd; 1825 u_int32_t *tl; 1826 int32_t t1; 1827 char *bpos; 1828 int error = 0, cache = 0, len, dirfor_ret = 1, diraft_ret = 1; 1829 int v3 = (nfsd->nd_flag & ND_NFSV3); 1830 char *cp2; 1831 struct mbuf *mb, *mreq __unused; 1832 struct vnode *vp, *dirp; 1833 struct vattr dirfor, diraft; 1834 nfsrvfh_t nsfh; 1835 u_quad_t frev; 1836 1837 #ifndef nolint 1838 vp = (struct vnode *)0; 1839 #endif 1840 nfsm_srvmtofh(&nsfh); 1841 nfsm_srvnamesiz(len); 1842 nd.ni_cnd.cn_cred = cred; 1843 nd.ni_cnd.cn_nameiop = DELETE; 1844 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; 1845 error = nfs_namei(&nd, &nsfh, len, slp, nam, &md, &dpos, 1846 &dirp, (v3 ? &dirfor_ret : NULL), &dirfor, 1847 lwp, (nfsd->nd_flag & ND_KERBAUTH), false); 1848 if (!error) { 1849 vp = nd.ni_vp; 1850 if (vp->v_type == VDIR) { 1851 error = EPERM; 1852 goto out; 1853 } 1854 /* 1855 * The root of a mounted filesystem cannot be deleted. 1856 */ 1857 if (vp->v_vflag & VV_ROOT) { 1858 error = EBUSY; 1859 } 1860 out: 1861 if (!error) { 1862 nqsrv_getl(nd.ni_dvp, ND_WRITE); 1863 nqsrv_getl(vp, ND_WRITE); 1864 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1865 vput(nd.ni_dvp); 1866 } else { 1867 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1868 if (nd.ni_dvp == vp) 1869 vrele(nd.ni_dvp); 1870 else 1871 vput(nd.ni_dvp); 1872 vput(vp); 1873 } 1874 } 1875 if (nd.ni_pathbuf != NULL) { 1876 pathbuf_destroy(nd.ni_pathbuf); 1877 nd.ni_pathbuf = NULL; 1878 } 1879 if (dirp) { 1880 if (v3) { 1881 vn_lock(dirp, LK_SHARED | LK_RETRY); 1882 diraft_ret = VOP_GETATTR(dirp, &diraft, cred); 1883 VOP_UNLOCK(dirp); 1884 } 1885 vrele(dirp); 1886 } 1887 nfsm_reply(NFSX_WCCDATA(v3)); 1888 if (v3) { 1889 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1890 return (0); 1891 } 1892 nfsm_srvdone; 1893 } 1894 1895 /* 1896 * nfs rename service 1897 */ 1898 int 1899 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 1900 { 1901 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 1902 struct mbuf *nam = nfsd->nd_nam; 1903 char *dpos = nfsd->nd_dpos; 1904 kauth_cred_t cred = nfsd->nd_cr; 1905 u_int32_t *tl; 1906 int32_t t1; 1907 char *bpos; 1908 int error = 0, cache = 0, fdirfor_ret = 1, fdiraft_ret = 1; 1909 uint32_t len, len2; 1910 int tdirfor_ret = 1, tdiraft_ret = 1; 1911 int v3 = (nfsd->nd_flag & ND_NFSV3); 1912 char *cp2; 1913 struct mbuf *mb, *mreq __unused; 1914 struct nameidata fromnd, tond; 1915 struct vnode *fvp, *tvp, *tdvp; 1916 struct vnode *fdirp = NULL, *tdirp = NULL; 1917 struct mount *localfs = NULL; 1918 struct vattr fdirfor, fdiraft, tdirfor, tdiraft; 1919 nfsrvfh_t fnsfh, tnsfh; 1920 u_quad_t frev; 1921 uid_t saved_uid; 1922 1923 #ifndef nolint 1924 fvp = (struct vnode *)0; 1925 #endif 1926 fromnd.ni_cnd.cn_nameiop = 0; 1927 tond.ni_cnd.cn_nameiop = 0; 1928 nfsm_srvmtofh(&fnsfh); 1929 nfsm_srvnamesiz(len); 1930 /* 1931 * Remember our original uid so that we can reset cr_uid before 1932 * the second nfs_namei() call, in case it is remapped. 1933 */ 1934 saved_uid = kauth_cred_geteuid(cred); 1935 fromnd.ni_cnd.cn_cred = cred; 1936 fromnd.ni_cnd.cn_nameiop = DELETE; 1937 fromnd.ni_cnd.cn_flags = LOCKPARENT; 1938 error = nfs_namei(&fromnd, &fnsfh, len, slp, nam, &md, 1939 &dpos, &fdirp, (v3 ? &fdirfor_ret : NULL), &fdirfor, 1940 lwp, (nfsd->nd_flag & ND_KERBAUTH), false); 1941 if (error) { 1942 fromnd.ni_cnd.cn_nameiop = 0; 1943 nfsm_reply(2 * NFSX_WCCDATA(v3)); 1944 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 1945 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 1946 if (fdirp) 1947 vrele(fdirp); 1948 if (fromnd.ni_pathbuf != NULL) { 1949 pathbuf_destroy(fromnd.ni_pathbuf); 1950 } 1951 return (0); 1952 } 1953 localfs = fromnd.ni_dvp->v_mount; 1954 fstrans_start(localfs); 1955 if (fromnd.ni_dvp != fromnd.ni_vp) { 1956 VOP_UNLOCK(fromnd.ni_dvp); 1957 } 1958 fvp = fromnd.ni_vp; 1959 1960 error = VFS_RENAMELOCK_ENTER(localfs); 1961 if (error) { 1962 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1963 vrele(fromnd.ni_dvp); 1964 vrele(fvp); 1965 goto out1; 1966 } 1967 1968 /* Copied, regrettably, from vfs_syscalls.c (q.v.) */ 1969 vrele(fvp); 1970 if ((fromnd.ni_cnd.cn_namelen == 1 && 1971 fromnd.ni_cnd.cn_nameptr[0] == '.') || 1972 (fromnd.ni_cnd.cn_namelen == 2 && 1973 fromnd.ni_cnd.cn_nameptr[0] == '.' && 1974 fromnd.ni_cnd.cn_nameptr[1] == '.')) { 1975 error = EINVAL; 1976 VFS_RENAMELOCK_EXIT(localfs); 1977 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1978 vrele(fromnd.ni_dvp); 1979 goto out1; 1980 } 1981 vn_lock(fromnd.ni_dvp, LK_EXCLUSIVE | LK_RETRY); 1982 error = relookup(fromnd.ni_dvp, &fromnd.ni_vp, &fromnd.ni_cnd, 0); 1983 if (error) { 1984 VOP_UNLOCK(fromnd.ni_dvp); 1985 VFS_RENAMELOCK_EXIT(localfs); 1986 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1987 vrele(fromnd.ni_dvp); 1988 goto out1; 1989 } 1990 VOP_UNLOCK(fromnd.ni_vp); 1991 if (fromnd.ni_dvp != fromnd.ni_vp) 1992 VOP_UNLOCK(fromnd.ni_dvp); 1993 fvp = fromnd.ni_vp; 1994 1995 nfsm_srvmtofh(&tnsfh); 1996 if (v3) { 1997 nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED); 1998 len2 = fxdr_unsigned(uint32_t, *tl); 1999 /* len2 will be checked by nfs_namei */ 2000 } 2001 else { 2002 /* NFSv2 */ 2003 nfsm_strsiz(len2, NFS_MAXNAMLEN); 2004 } 2005 kauth_cred_seteuid(cred, saved_uid); 2006 tond.ni_cnd.cn_cred = cred; 2007 tond.ni_cnd.cn_nameiop = RENAME; 2008 tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE; 2009 error = nfs_namei(&tond, &tnsfh, len2, slp, nam, &md, 2010 &dpos, &tdirp, (v3 ? &tdirfor_ret : NULL), &tdirfor, 2011 lwp, (nfsd->nd_flag & ND_KERBAUTH), false); 2012 if (error) { 2013 VFS_RENAMELOCK_EXIT(localfs); 2014 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2015 vrele(fromnd.ni_dvp); 2016 vrele(fvp); 2017 goto out1; 2018 } 2019 tdvp = tond.ni_dvp; 2020 tvp = tond.ni_vp; 2021 if (tvp != NULL) { 2022 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2023 if (v3) 2024 error = EEXIST; 2025 else 2026 error = EISDIR; 2027 goto out; 2028 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2029 if (v3) 2030 error = EEXIST; 2031 else 2032 error = ENOTDIR; 2033 goto out; 2034 } 2035 if (tvp->v_type == VDIR && tvp->v_mountedhere) { 2036 if (v3) 2037 error = EXDEV; 2038 else 2039 error = ENOTEMPTY; 2040 goto out; 2041 } 2042 } 2043 if (fvp->v_type == VDIR && fvp->v_mountedhere) { 2044 if (v3) 2045 error = EXDEV; 2046 else 2047 error = ENOTEMPTY; 2048 goto out; 2049 } 2050 if (fvp->v_mount != tdvp->v_mount) { 2051 if (v3) 2052 error = EXDEV; 2053 else 2054 error = ENOTEMPTY; 2055 goto out; 2056 } 2057 if (fvp == tdvp) { 2058 if (v3) 2059 error = EINVAL; 2060 else 2061 error = ENOTEMPTY; 2062 } 2063 /* 2064 * If source is the same as the destination (that is the 2065 * same vnode with the same name in the same directory), 2066 * then there is nothing to do. 2067 */ 2068 if (fvp == tvp && fromnd.ni_dvp == tdvp && 2069 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 2070 !memcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 2071 fromnd.ni_cnd.cn_namelen)) 2072 error = -1; 2073 out: 2074 if (!error) { 2075 nqsrv_getl(fromnd.ni_dvp, ND_WRITE); 2076 nqsrv_getl(tdvp, ND_WRITE); 2077 if (tvp) { 2078 nqsrv_getl(tvp, ND_WRITE); 2079 } 2080 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 2081 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 2082 VFS_RENAMELOCK_EXIT(localfs); 2083 } else { 2084 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 2085 if (tdvp == tvp) 2086 vrele(tdvp); 2087 else 2088 vput(tdvp); 2089 if (tvp) 2090 vput(tvp); 2091 VFS_RENAMELOCK_EXIT(localfs); 2092 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2093 vrele(fromnd.ni_dvp); 2094 vrele(fvp); 2095 if (error == -1) 2096 error = 0; 2097 } 2098 if (tond.ni_pathbuf != NULL) { 2099 pathbuf_destroy(tond.ni_pathbuf); 2100 tond.ni_pathbuf = NULL; 2101 } 2102 tond.ni_cnd.cn_nameiop = 0; 2103 out1: 2104 if (fdirp) { 2105 if (v3) { 2106 vn_lock(fdirp, LK_SHARED | LK_RETRY); 2107 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred); 2108 VOP_UNLOCK(fdirp); 2109 } 2110 vrele(fdirp); 2111 fdirp = NULL; 2112 } 2113 if (tdirp) { 2114 if (v3) { 2115 vn_lock(tdirp, LK_SHARED | LK_RETRY); 2116 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred); 2117 VOP_UNLOCK(tdirp); 2118 } 2119 vrele(tdirp); 2120 tdirp = NULL; 2121 } 2122 pathbuf_destroy(fromnd.ni_pathbuf); 2123 fromnd.ni_pathbuf = NULL; 2124 fromnd.ni_cnd.cn_nameiop = 0; 2125 fstrans_done(localfs); 2126 localfs = NULL; 2127 nfsm_reply(2 * NFSX_WCCDATA(v3)); 2128 if (v3) { 2129 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 2130 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 2131 } 2132 return (0); 2133 2134 nfsmout: 2135 if (fdirp) 2136 vrele(fdirp); 2137 #ifdef notdef 2138 if (tdirp) 2139 vrele(tdirp); 2140 #endif 2141 if (tond.ni_cnd.cn_nameiop) { 2142 if (tond.ni_pathbuf != NULL) { 2143 pathbuf_destroy(tond.ni_pathbuf); 2144 tond.ni_pathbuf = NULL; 2145 } 2146 } 2147 if (localfs) { 2148 VFS_RENAMELOCK_EXIT(localfs); 2149 fstrans_done(localfs); 2150 } 2151 if (fromnd.ni_cnd.cn_nameiop) { 2152 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2153 if (fromnd.ni_pathbuf != NULL) { 2154 pathbuf_destroy(fromnd.ni_pathbuf); 2155 fromnd.ni_pathbuf = NULL; 2156 } 2157 vrele(fromnd.ni_dvp); 2158 vrele(fvp); 2159 } 2160 return (error); 2161 } 2162 2163 /* 2164 * nfs link service 2165 */ 2166 int 2167 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 2168 { 2169 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2170 struct mbuf *nam = nfsd->nd_nam; 2171 char *dpos = nfsd->nd_dpos; 2172 kauth_cred_t cred = nfsd->nd_cr; 2173 struct nameidata nd; 2174 u_int32_t *tl; 2175 int32_t t1; 2176 char *bpos; 2177 int error = 0, rdonly, cache = 0, len, dirfor_ret = 1, diraft_ret = 1; 2178 int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3); 2179 char *cp2; 2180 struct mbuf *mb, *mreq __unused; 2181 struct vnode *vp, *xp, *dirp = (struct vnode *)0; 2182 struct vattr dirfor, diraft, at; 2183 nfsrvfh_t nsfh, dnsfh; 2184 u_quad_t frev; 2185 2186 nfsm_srvmtofh(&nsfh); 2187 nfsm_srvmtofh(&dnsfh); 2188 nfsm_srvnamesiz(len); 2189 error = nfsrv_fhtovp(&nsfh, false, &vp, cred, slp, nam, 2190 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), false); 2191 if (error) { 2192 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2193 nfsm_srvpostop_attr(getret, &at); 2194 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2195 return (0); 2196 } 2197 if (vp->v_type == VDIR) { 2198 error = EPERM; 2199 goto out1; 2200 } 2201 nd.ni_cnd.cn_cred = cred; 2202 nd.ni_cnd.cn_nameiop = CREATE; 2203 nd.ni_cnd.cn_flags = LOCKPARENT; 2204 error = nfs_namei(&nd, &dnsfh, len, slp, nam, &md, &dpos, 2205 &dirp, (v3 ? &dirfor_ret : NULL), &dirfor, 2206 lwp, (nfsd->nd_flag & ND_KERBAUTH), false); 2207 if (error) 2208 goto out1; 2209 xp = nd.ni_vp; 2210 if (xp != NULL) { 2211 error = EEXIST; 2212 goto out; 2213 } 2214 xp = nd.ni_dvp; 2215 if (vp->v_mount != xp->v_mount) 2216 error = EXDEV; 2217 out: 2218 if (!error) { 2219 nqsrv_getl(vp, ND_WRITE); 2220 nqsrv_getl(xp, ND_WRITE); 2221 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 2222 if (nd.ni_dvp != nd.ni_vp) 2223 VOP_UNLOCK(nd.ni_dvp); 2224 vrele(nd.ni_dvp); 2225 } else { 2226 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2227 if (nd.ni_dvp == nd.ni_vp) 2228 vrele(nd.ni_dvp); 2229 else 2230 vput(nd.ni_dvp); 2231 if (nd.ni_vp) 2232 vrele(nd.ni_vp); 2233 } 2234 out1: 2235 if (v3) { 2236 vn_lock(vp, LK_SHARED | LK_RETRY); 2237 getret = VOP_GETATTR(vp, &at, cred); 2238 VOP_UNLOCK(vp); 2239 } 2240 if (dirp) { 2241 if (v3) { 2242 vn_lock(dirp, LK_SHARED | LK_RETRY); 2243 diraft_ret = VOP_GETATTR(dirp, &diraft, cred); 2244 VOP_UNLOCK(dirp); 2245 } 2246 vrele(dirp); 2247 } 2248 vrele(vp); 2249 if (nd.ni_pathbuf != NULL) { 2250 pathbuf_destroy(nd.ni_pathbuf); 2251 nd.ni_pathbuf = NULL; 2252 } 2253 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2254 if (v3) { 2255 nfsm_srvpostop_attr(getret, &at); 2256 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2257 return (0); 2258 } 2259 nfsm_srvdone; 2260 } 2261 2262 /* 2263 * nfs symbolic link service 2264 */ 2265 int 2266 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 2267 { 2268 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2269 struct mbuf *nam = nfsd->nd_nam; 2270 char *dpos = nfsd->nd_dpos; 2271 kauth_cred_t cred = nfsd->nd_cr; 2272 struct vattr va, dirfor, diraft; 2273 struct nameidata nd; 2274 u_int32_t *tl; 2275 int32_t t1; 2276 struct nfsv2_sattr *sp; 2277 char *bpos, *pathcp = NULL, *cp2; 2278 struct uio io; 2279 struct iovec iv; 2280 int error = 0, cache = 0, dirfor_ret = 1, diraft_ret = 1, abort = 0; 2281 uint32_t len, len2; 2282 int v3 = (nfsd->nd_flag & ND_NFSV3); 2283 struct mbuf *mb, *mreq __unused; 2284 struct vnode *dirp = (struct vnode *)0; 2285 nfsrvfh_t nsfh; 2286 u_quad_t frev; 2287 2288 nd.ni_cnd.cn_nameiop = 0; 2289 nfsm_srvmtofh(&nsfh); 2290 nfsm_srvnamesiz(len); 2291 nd.ni_cnd.cn_cred = cred; 2292 nd.ni_cnd.cn_nameiop = CREATE; 2293 nd.ni_cnd.cn_flags = LOCKPARENT; 2294 error = nfs_namei(&nd, &nsfh, len, slp, nam, &md, &dpos, 2295 &dirp, (v3 ? &dirfor_ret : NULL), &dirfor, 2296 lwp, (nfsd->nd_flag & ND_KERBAUTH), false); 2297 if (error) 2298 goto out; 2299 abort = 1; 2300 vattr_null(&va); 2301 va.va_type = VLNK; 2302 if (v3) { 2303 va.va_mode = 0; 2304 nfsm_srvsattr(&va); 2305 nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED); 2306 len2 = fxdr_unsigned(uint32_t, *tl); 2307 if (len2 > PATH_MAX) { 2308 /* XXX should check _PC_NO_TRUNC */ 2309 error = ENAMETOOLONG; 2310 goto abortop; 2311 } 2312 } 2313 else { 2314 /* NFSv2 */ 2315 nfsm_strsiz(len2, NFS_MAXPATHLEN); 2316 } 2317 pathcp = malloc(len2 + 1, M_TEMP, M_WAITOK); 2318 iv.iov_base = pathcp; 2319 iv.iov_len = len2; 2320 io.uio_resid = len2; 2321 io.uio_offset = 0; 2322 io.uio_iov = &iv; 2323 io.uio_iovcnt = 1; 2324 io.uio_rw = UIO_READ; 2325 UIO_SETUP_SYSSPACE(&io); 2326 nfsm_mtouio(&io, len2); 2327 if (!v3) { 2328 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 2329 va.va_mode = fxdr_unsigned(u_int16_t, sp->sa_mode); 2330 } 2331 *(pathcp + len2) = '\0'; 2332 if (nd.ni_vp) { 2333 error = EEXIST; 2334 abortop: 2335 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2336 if (nd.ni_dvp == nd.ni_vp) 2337 vrele(nd.ni_dvp); 2338 else 2339 vput(nd.ni_dvp); 2340 if (nd.ni_vp) 2341 vrele(nd.ni_vp); 2342 goto out; 2343 } 2344 nqsrv_getl(nd.ni_dvp, ND_WRITE); 2345 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va, pathcp); 2346 if (!error) { 2347 if (v3) { 2348 vn_lock(nd.ni_vp, LK_SHARED | LK_RETRY); 2349 error = nfsrv_composefh(nd.ni_vp, &nsfh, v3); 2350 if (!error) 2351 error = VOP_GETATTR(nd.ni_vp, &va, cred); 2352 vput(nd.ni_vp); 2353 } else { 2354 vrele(nd.ni_vp); 2355 } 2356 } 2357 vput(nd.ni_dvp); 2358 out: 2359 if (pathcp) 2360 free(pathcp, M_TEMP); 2361 if (dirp) { 2362 if (v3) { 2363 vn_lock(dirp, LK_SHARED | LK_RETRY); 2364 diraft_ret = VOP_GETATTR(dirp, &diraft, cred); 2365 VOP_UNLOCK(dirp); 2366 } 2367 vrele(dirp); 2368 dirp = NULL; 2369 } 2370 if (nd.ni_pathbuf != NULL) { 2371 pathbuf_destroy(nd.ni_pathbuf); 2372 nd.ni_pathbuf = NULL; 2373 } 2374 abort = 0; 2375 nfsm_reply(NFSX_SRVFH(&nsfh, v3) + NFSX_POSTOPATTR(v3) + 2376 NFSX_WCCDATA(v3)); 2377 if (v3) { 2378 if (!error) { 2379 nfsm_srvpostop_fh(&nsfh); 2380 nfsm_srvpostop_attr(0, &va); 2381 } 2382 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2383 } 2384 return (0); 2385 nfsmout: 2386 if (abort) { 2387 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2388 if (nd.ni_dvp == nd.ni_vp) 2389 vrele(nd.ni_dvp); 2390 else 2391 vput(nd.ni_dvp); 2392 if (nd.ni_vp) 2393 vrele(nd.ni_vp); 2394 if (nd.ni_pathbuf != NULL) { 2395 pathbuf_destroy(nd.ni_pathbuf); 2396 nd.ni_pathbuf = NULL; 2397 } 2398 } 2399 if (dirp) 2400 vrele(dirp); 2401 if (pathcp) 2402 free(pathcp, M_TEMP); 2403 return (error); 2404 } 2405 2406 /* 2407 * nfs mkdir service 2408 */ 2409 int 2410 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 2411 { 2412 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2413 struct mbuf *nam = nfsd->nd_nam; 2414 char *dpos = nfsd->nd_dpos; 2415 kauth_cred_t cred = nfsd->nd_cr; 2416 struct vattr va, dirfor, diraft; 2417 struct nfs_fattr *fp; 2418 struct nameidata nd; 2419 char *cp; 2420 u_int32_t *tl; 2421 int32_t t1; 2422 char *bpos; 2423 int error = 0, cache = 0, len, dirfor_ret = 1, diraft_ret = 1; 2424 int abort = 0; 2425 int v3 = (nfsd->nd_flag & ND_NFSV3); 2426 char *cp2; 2427 struct mbuf *mb, *mreq __unused; 2428 struct vnode *vp, *dirp = (struct vnode *)0; 2429 nfsrvfh_t nsfh; 2430 u_quad_t frev; 2431 2432 nfsm_srvmtofh(&nsfh); 2433 nfsm_srvnamesiz(len); 2434 nd.ni_cnd.cn_cred = cred; 2435 nd.ni_cnd.cn_nameiop = CREATE; 2436 nd.ni_cnd.cn_flags = LOCKPARENT; 2437 error = nfs_namei(&nd, &nsfh, len, slp, nam, &md, &dpos, 2438 &dirp, (v3 ? &dirfor_ret : NULL), &dirfor, 2439 lwp, (nfsd->nd_flag & ND_KERBAUTH), false); 2440 if (error) { 2441 if (nd.ni_pathbuf != NULL) { 2442 pathbuf_destroy(nd.ni_pathbuf); 2443 nd.ni_pathbuf = NULL; 2444 } 2445 nfsm_reply(NFSX_WCCDATA(v3)); 2446 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2447 if (dirp) 2448 vrele(dirp); 2449 return (0); 2450 } 2451 abort = 1; 2452 vattr_null(&va); 2453 if (v3) { 2454 va.va_mode = 0; 2455 nfsm_srvsattr(&va); 2456 } else { 2457 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2458 va.va_mode = nfstov_mode(*tl++); 2459 } 2460 va.va_type = VDIR; 2461 vp = nd.ni_vp; 2462 if (vp != NULL) { 2463 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2464 if (nd.ni_dvp == vp) 2465 vrele(nd.ni_dvp); 2466 else 2467 vput(nd.ni_dvp); 2468 vrele(vp); 2469 error = EEXIST; 2470 goto out; 2471 } 2472 nqsrv_getl(nd.ni_dvp, ND_WRITE); 2473 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va); 2474 if (!error) { 2475 vp = nd.ni_vp; 2476 vn_lock(vp, LK_SHARED | LK_RETRY); 2477 error = nfsrv_composefh(vp, &nsfh, v3); 2478 if (!error) 2479 error = VOP_GETATTR(vp, &va, cred); 2480 vput(vp); 2481 } 2482 vput(nd.ni_dvp); 2483 out: 2484 if (dirp) { 2485 if (v3) { 2486 vn_lock(dirp, LK_SHARED | LK_RETRY); 2487 diraft_ret = VOP_GETATTR(dirp, &diraft, cred); 2488 VOP_UNLOCK(dirp); 2489 } 2490 vrele(dirp); 2491 dirp = NULL; 2492 } 2493 if (nd.ni_pathbuf != NULL) { 2494 pathbuf_destroy(nd.ni_pathbuf); 2495 nd.ni_pathbuf = NULL; 2496 } 2497 abort = 0; 2498 nfsm_reply(NFSX_SRVFH(&nsfh, v3) + NFSX_POSTOPATTR(v3) + 2499 NFSX_WCCDATA(v3)); 2500 if (v3) { 2501 if (!error) { 2502 nfsm_srvpostop_fh(&nsfh); 2503 nfsm_srvpostop_attr(0, &va); 2504 } 2505 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2506 } else { 2507 nfsm_srvfhtom(&nsfh, v3); 2508 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 2509 nfsm_srvfillattr(&va, fp); 2510 } 2511 return (0); 2512 nfsmout: 2513 if (abort) { 2514 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2515 if (nd.ni_dvp == nd.ni_vp) 2516 vrele(nd.ni_dvp); 2517 else 2518 vput(nd.ni_dvp); 2519 if (nd.ni_vp) 2520 vrele(nd.ni_vp); 2521 if (nd.ni_pathbuf != NULL) { 2522 pathbuf_destroy(nd.ni_pathbuf); 2523 nd.ni_pathbuf = NULL; 2524 } 2525 } 2526 if (dirp) 2527 vrele(dirp); 2528 return (error); 2529 } 2530 2531 /* 2532 * nfs rmdir service 2533 */ 2534 int 2535 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 2536 { 2537 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2538 struct mbuf *nam = nfsd->nd_nam; 2539 char *dpos = nfsd->nd_dpos; 2540 kauth_cred_t cred = nfsd->nd_cr; 2541 u_int32_t *tl; 2542 int32_t t1; 2543 char *bpos; 2544 int error = 0, cache = 0, len, dirfor_ret = 1, diraft_ret = 1; 2545 int v3 = (nfsd->nd_flag & ND_NFSV3); 2546 char *cp2; 2547 struct mbuf *mb, *mreq __unused; 2548 struct vnode *vp, *dirp = (struct vnode *)0; 2549 struct vattr dirfor, diraft; 2550 nfsrvfh_t nsfh; 2551 struct nameidata nd; 2552 u_quad_t frev; 2553 2554 nfsm_srvmtofh(&nsfh); 2555 nfsm_srvnamesiz(len); 2556 nd.ni_cnd.cn_cred = cred; 2557 nd.ni_cnd.cn_nameiop = DELETE; 2558 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; 2559 error = nfs_namei(&nd, &nsfh, len, slp, nam, &md, &dpos, 2560 &dirp, (v3 ? &dirfor_ret : NULL), &dirfor, 2561 lwp, (nfsd->nd_flag & ND_KERBAUTH), false); 2562 if (error) { 2563 if (nd.ni_pathbuf != NULL) { 2564 pathbuf_destroy(nd.ni_pathbuf); 2565 nd.ni_pathbuf = NULL; 2566 } 2567 nfsm_reply(NFSX_WCCDATA(v3)); 2568 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2569 if (dirp) 2570 vrele(dirp); 2571 return (0); 2572 } 2573 vp = nd.ni_vp; 2574 if (vp->v_type != VDIR) { 2575 error = ENOTDIR; 2576 goto out; 2577 } 2578 /* 2579 * No rmdir "." please. 2580 */ 2581 if (nd.ni_dvp == vp) { 2582 error = EINVAL; 2583 goto out; 2584 } 2585 /* 2586 * The root of a mounted filesystem cannot be deleted. 2587 */ 2588 if (vp->v_vflag & VV_ROOT) 2589 error = EBUSY; 2590 out: 2591 if (!error) { 2592 nqsrv_getl(nd.ni_dvp, ND_WRITE); 2593 nqsrv_getl(vp, ND_WRITE); 2594 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 2595 vput(nd.ni_dvp); 2596 } else { 2597 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2598 if (nd.ni_dvp == nd.ni_vp) 2599 vrele(nd.ni_dvp); 2600 else 2601 vput(nd.ni_dvp); 2602 vput(vp); 2603 } 2604 if (nd.ni_pathbuf != NULL) { 2605 pathbuf_destroy(nd.ni_pathbuf); 2606 nd.ni_pathbuf = NULL; 2607 } 2608 if (dirp) { 2609 if (v3) { 2610 vn_lock(dirp, LK_SHARED | LK_RETRY); 2611 diraft_ret = VOP_GETATTR(dirp, &diraft, cred); 2612 VOP_UNLOCK(dirp); 2613 } 2614 vrele(dirp); 2615 } 2616 nfsm_reply(NFSX_WCCDATA(v3)); 2617 if (v3) { 2618 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2619 return (0); 2620 } 2621 nfsm_srvdone; 2622 } 2623 2624 /* 2625 * nfs readdir service 2626 * - mallocs what it thinks is enough to read 2627 * count rounded up to a multiple of NFS_SRVDIRBLKSIZ <= NFS_MAXREADDIR 2628 * - calls VOP_READDIR() 2629 * - loops around building the reply 2630 * if the output generated exceeds count break out of loop 2631 * The nfsm_clget macro is used here so that the reply will be packed 2632 * tightly in mbuf clusters. 2633 * - it only knows that it has encountered eof when the VOP_READDIR() 2634 * reads nothing 2635 * - as such one readdir rpc will return eof false although you are there 2636 * and then the next will return eof 2637 * - it trims out records with d_fileno == 0 2638 * this doesn't matter for Unix clients, but they might confuse clients 2639 * for other os'. 2640 * - it trims out records with d_type == DT_WHT 2641 * these cannot be seen through NFS (unless we extend the protocol) 2642 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less 2643 * than requested, but this may not apply to all filesystems. For 2644 * example, client NFS does not { although it is never remote mounted 2645 * anyhow } 2646 * The alternate call nfsrv_readdirplus() does lookups as well. 2647 * PS: The NFS protocol spec. does not clarify what the "count" byte 2648 * argument is a count of.. just name strings and file id's or the 2649 * entire reply rpc or ... 2650 * I tried just file name and id sizes and it confused the Sun client, 2651 * so I am using the full rpc size now. The "paranoia.." comment refers 2652 * to including the status longwords that are not a part of the dir. 2653 * "entry" structures, but are in the rpc. 2654 */ 2655 2656 #define NFS_SRVDIRBLKSIZ 1024 2657 2658 struct flrep { 2659 nfsuint64 fl_off; 2660 u_int32_t fl_postopok; 2661 struct nfs_fattr fl_fattr; /* XXX: must be of fattr3 size */ 2662 u_int32_t fl_fhok; 2663 u_int32_t fl_fhsize; 2664 /* handle comes here, filled in dynamically */ 2665 }; 2666 2667 int 2668 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 2669 { 2670 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2671 struct mbuf *nam = nfsd->nd_nam; 2672 char *dpos = nfsd->nd_dpos; 2673 kauth_cred_t cred = nfsd->nd_cr; 2674 char *bp, *be; 2675 struct mbuf *mp; 2676 struct dirent *dp; 2677 char *cp; 2678 u_int32_t *tl; 2679 int32_t t1; 2680 char *bpos; 2681 struct mbuf *mb, *mreq __unused, *mp2; 2682 char *cpos, *cend, *cp2, *rbuf; 2683 struct vnode *vp; 2684 struct vattr at; 2685 nfsrvfh_t nsfh; 2686 struct uio io; 2687 struct iovec iv; 2688 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1; 2689 int siz, cnt, fullsiz, eofflag, rdonly, cache = 0, ncookies; 2690 int v3 = (nfsd->nd_flag & ND_NFSV3); 2691 u_quad_t frev, off, toff; 2692 #ifdef NFS3_STRICTVERF 2693 u_quad_t verf; 2694 #endif 2695 off_t *cookies = NULL, *cookiep; 2696 nfsuint64 jar; 2697 2698 nfsm_srvmtofh(&nsfh); 2699 if (v3) { 2700 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 2701 toff = fxdr_hyper(tl); 2702 tl += 2; 2703 #ifdef NFS3_STRICTVERF 2704 verf = fxdr_hyper(tl); 2705 #endif 2706 tl += 2; 2707 } else { 2708 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2709 toff = fxdr_unsigned(u_quad_t, *tl++); 2710 } 2711 off = toff; 2712 cnt = fxdr_unsigned(int, *tl); 2713 siz = ((cnt + NFS_SRVDIRBLKSIZ - 1) & ~(NFS_SRVDIRBLKSIZ - 1)); 2714 xfer = NFS_SRVMAXDATA(nfsd); 2715 if (siz > xfer) 2716 siz = xfer; 2717 fullsiz = siz; 2718 error = nfsrv_fhtovp(&nsfh, 1, &vp, cred, slp, nam, 2719 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), false); 2720 if (!error && vp->v_type != VDIR) { 2721 error = ENOTDIR; 2722 vput(vp); 2723 } 2724 if (error) { 2725 nfsm_reply(NFSX_UNSIGNED); 2726 nfsm_srvpostop_attr(getret, &at); 2727 return (0); 2728 } 2729 nqsrv_getl(vp, ND_READ); 2730 if (v3) { 2731 error = getret = VOP_GETATTR(vp, &at, cred); 2732 #ifdef NFS3_STRICTVERF 2733 /* 2734 * XXX This check is too strict for Solaris 2.5 clients. 2735 */ 2736 if (!error && toff && verf != at.va_filerev) 2737 error = NFSERR_BAD_COOKIE; 2738 #endif 2739 } 2740 if (!error) 2741 error = nfsrv_access(vp, VEXEC, cred, rdonly, lwp, 0); 2742 if (error) { 2743 vput(vp); 2744 nfsm_reply(NFSX_POSTOPATTR(v3)); 2745 nfsm_srvpostop_attr(getret, &at); 2746 return (0); 2747 } 2748 VOP_UNLOCK(vp); 2749 rbuf = malloc(siz, M_TEMP, M_WAITOK); 2750 again: 2751 iv.iov_base = rbuf; 2752 iv.iov_len = fullsiz; 2753 io.uio_iov = &iv; 2754 io.uio_iovcnt = 1; 2755 io.uio_offset = (off_t)off; 2756 io.uio_resid = fullsiz; 2757 io.uio_rw = UIO_READ; 2758 UIO_SETUP_SYSSPACE(&io); 2759 eofflag = 0; 2760 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2761 2762 error = VOP_READDIR(vp, &io, cred, &eofflag, &cookies, &ncookies); 2763 2764 off = (off_t)io.uio_offset; 2765 if (!cookies && !error) 2766 error = NFSERR_PERM; 2767 if (v3) { 2768 getret = VOP_GETATTR(vp, &at, cred); 2769 if (!error) 2770 error = getret; 2771 } 2772 2773 VOP_UNLOCK(vp); 2774 if (error) { 2775 vrele(vp); 2776 free((void *)rbuf, M_TEMP); 2777 if (cookies) 2778 free((void *)cookies, M_TEMP); 2779 nfsm_reply(NFSX_POSTOPATTR(v3)); 2780 nfsm_srvpostop_attr(getret, &at); 2781 return (0); 2782 } 2783 if (io.uio_resid) { 2784 siz -= io.uio_resid; 2785 2786 /* 2787 * If nothing read, return eof 2788 * rpc reply 2789 */ 2790 if (siz == 0) { 2791 vrele(vp); 2792 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + 2793 2 * NFSX_UNSIGNED); 2794 if (v3) { 2795 nfsm_srvpostop_attr(getret, &at); 2796 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 2797 txdr_hyper(at.va_filerev, tl); 2798 tl += 2; 2799 } else 2800 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2801 *tl++ = nfs_false; 2802 *tl = nfs_true; 2803 free((void *)rbuf, M_TEMP); 2804 free((void *)cookies, M_TEMP); 2805 return (0); 2806 } 2807 } 2808 2809 /* 2810 * Check for degenerate cases of nothing useful read. 2811 * If so go try again 2812 */ 2813 cpos = rbuf; 2814 cend = rbuf + siz; 2815 dp = (struct dirent *)cpos; 2816 cookiep = cookies; 2817 2818 while (cpos < cend && ncookies > 0 && 2819 (dp->d_fileno == 0 || dp->d_type == DT_WHT)) { 2820 cpos += dp->d_reclen; 2821 dp = (struct dirent *)cpos; 2822 cookiep++; 2823 ncookies--; 2824 } 2825 if (cpos >= cend || ncookies == 0) { 2826 toff = off; 2827 siz = fullsiz; 2828 free(cookies, M_TEMP); 2829 cookies = NULL; 2830 goto again; 2831 } 2832 2833 len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */ 2834 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz); 2835 if (v3) { 2836 nfsm_srvpostop_attr(getret, &at); 2837 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2838 txdr_hyper(at.va_filerev, tl); 2839 } 2840 mp = mp2 = mb; 2841 bp = bpos; 2842 be = bp + M_TRAILINGSPACE(mp); 2843 2844 /* Loop through the records and build reply */ 2845 while (cpos < cend && ncookies > 0) { 2846 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) { 2847 nlen = dp->d_namlen; 2848 rem = nfsm_rndup(nlen)-nlen; 2849 len += (4 * NFSX_UNSIGNED + nlen + rem); 2850 if (v3) 2851 len += 2 * NFSX_UNSIGNED; 2852 if (len > cnt) { 2853 eofflag = 0; 2854 break; 2855 } 2856 /* 2857 * Build the directory record xdr from 2858 * the dirent entry. 2859 */ 2860 nfsm_clget; 2861 *tl = nfs_true; 2862 bp += NFSX_UNSIGNED; 2863 if (v3) { 2864 nfsm_clget; 2865 *tl = txdr_unsigned(dp->d_fileno >> 32); 2866 bp += NFSX_UNSIGNED; 2867 } 2868 nfsm_clget; 2869 *tl = txdr_unsigned(dp->d_fileno); 2870 bp += NFSX_UNSIGNED; 2871 nfsm_clget; 2872 *tl = txdr_unsigned(nlen); 2873 bp += NFSX_UNSIGNED; 2874 2875 /* And loop around copying the name */ 2876 xfer = nlen; 2877 cp = dp->d_name; 2878 while (xfer > 0) { 2879 nfsm_clget; 2880 if ((bp+xfer) > be) 2881 tsiz = be-bp; 2882 else 2883 tsiz = xfer; 2884 memcpy(bp, cp, tsiz); 2885 bp += tsiz; 2886 xfer -= tsiz; 2887 if (xfer > 0) 2888 cp += tsiz; 2889 } 2890 /* And null pad to an int32_t boundary */ 2891 for (i = 0; i < rem; i++) 2892 *bp++ = '\0'; 2893 nfsm_clget; 2894 2895 /* Finish off the record */ 2896 txdr_hyper(*cookiep, &jar); 2897 if (v3) { 2898 *tl = jar.nfsuquad[0]; 2899 bp += NFSX_UNSIGNED; 2900 nfsm_clget; 2901 } 2902 *tl = jar.nfsuquad[1]; 2903 bp += NFSX_UNSIGNED; 2904 } 2905 cpos += dp->d_reclen; 2906 dp = (struct dirent *)cpos; 2907 cookiep++; 2908 ncookies--; 2909 } 2910 vrele(vp); 2911 nfsm_clget; 2912 *tl = nfs_false; 2913 bp += NFSX_UNSIGNED; 2914 nfsm_clget; 2915 if (eofflag) 2916 *tl = nfs_true; 2917 else 2918 *tl = nfs_false; 2919 bp += NFSX_UNSIGNED; 2920 if (mp != mb) { 2921 if (bp < be) 2922 mp->m_len = bp - mtod(mp, char *); 2923 } else 2924 mp->m_len += bp - bpos; 2925 free((void *)rbuf, M_TEMP); 2926 free((void *)cookies, M_TEMP); 2927 nfsm_srvdone; 2928 } 2929 2930 int 2931 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 2932 { 2933 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2934 struct mbuf *nam = nfsd->nd_nam; 2935 char *dpos = nfsd->nd_dpos; 2936 kauth_cred_t cred = nfsd->nd_cr; 2937 char *bp, *be; 2938 struct mbuf *mp; 2939 struct dirent *dp; 2940 char *cp; 2941 u_int32_t *tl; 2942 int32_t t1; 2943 char *bpos; 2944 struct mbuf *mb, *mreq __unused, *mp2; 2945 char *cpos, *cend, *cp2, *rbuf; 2946 struct vnode *vp, *nvp; 2947 struct flrep fl; 2948 nfsrvfh_t nsfh; 2949 struct uio io; 2950 struct iovec iv; 2951 struct vattr va, at, *vap = &va; 2952 struct nfs_fattr *fp; 2953 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1; 2954 int siz, cnt, fullsiz, eofflag, rdonly, cache = 0, dirlen, ncookies; 2955 u_quad_t frev, off, toff; 2956 #ifdef NFS3_STRICTVERF 2957 u_quad_t verf; 2958 #endif 2959 off_t *cookies = NULL, *cookiep; 2960 2961 nfsm_srvmtofh(&nsfh); 2962 nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); 2963 toff = fxdr_hyper(tl); 2964 tl += 2; 2965 #ifdef NFS3_STRICTVERF 2966 verf = fxdr_hyper(tl); 2967 #endif 2968 tl += 2; 2969 siz = fxdr_unsigned(int, *tl++); 2970 cnt = fxdr_unsigned(int, *tl); 2971 off = toff; 2972 siz = ((siz + NFS_SRVDIRBLKSIZ - 1) & ~(NFS_SRVDIRBLKSIZ - 1)); 2973 xfer = NFS_SRVMAXDATA(nfsd); 2974 if (siz > xfer) 2975 siz = xfer; 2976 fullsiz = siz; 2977 error = nfsrv_fhtovp(&nsfh, 1, &vp, cred, slp, nam, 2978 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), false); 2979 if (!error && vp->v_type != VDIR) { 2980 error = ENOTDIR; 2981 vput(vp); 2982 } 2983 if (error) { 2984 nfsm_reply(NFSX_UNSIGNED); 2985 nfsm_srvpostop_attr(getret, &at); 2986 return (0); 2987 } 2988 error = getret = VOP_GETATTR(vp, &at, cred); 2989 #ifdef NFS3_STRICTVERF 2990 /* 2991 * XXX This check is too strict for Solaris 2.5 clients. 2992 */ 2993 if (!error && toff && verf != at.va_filerev) 2994 error = NFSERR_BAD_COOKIE; 2995 #endif 2996 if (!error) { 2997 nqsrv_getl(vp, ND_READ); 2998 error = nfsrv_access(vp, VEXEC, cred, rdonly, lwp, 0); 2999 } 3000 if (error) { 3001 vput(vp); 3002 nfsm_reply(NFSX_V3POSTOPATTR); 3003 nfsm_srvpostop_attr(getret, &at); 3004 return (0); 3005 } 3006 VOP_UNLOCK(vp); 3007 3008 rbuf = malloc(siz, M_TEMP, M_WAITOK); 3009 again: 3010 iv.iov_base = rbuf; 3011 iv.iov_len = fullsiz; 3012 io.uio_iov = &iv; 3013 io.uio_iovcnt = 1; 3014 io.uio_offset = (off_t)off; 3015 io.uio_resid = fullsiz; 3016 io.uio_rw = UIO_READ; 3017 UIO_SETUP_SYSSPACE(&io); 3018 eofflag = 0; 3019 3020 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3021 3022 error = VOP_READDIR(vp, &io, cred, &eofflag, &cookies, &ncookies); 3023 3024 off = (u_quad_t)io.uio_offset; 3025 getret = VOP_GETATTR(vp, &at, cred); 3026 3027 VOP_UNLOCK(vp); 3028 3029 /* 3030 * If the VGET operation doesn't work for this filesystem, 3031 * we can't support readdirplus. Returning NOTSUPP should 3032 * make clients fall back to plain readdir. 3033 * There's no need to check for VPTOFH as well, we wouldn't 3034 * even be here otherwise. 3035 */ 3036 if (!getret) { 3037 if ((getret = VFS_VGET(vp->v_mount, at.va_fileid, 3038 LK_EXCLUSIVE, &nvp))) 3039 getret = (getret == EOPNOTSUPP) ? 3040 NFSERR_NOTSUPP : NFSERR_IO; 3041 else 3042 vput(nvp); 3043 } 3044 3045 if (!cookies && !error) 3046 error = NFSERR_PERM; 3047 if (!error) 3048 error = getret; 3049 if (error) { 3050 vrele(vp); 3051 if (cookies) 3052 free((void *)cookies, M_TEMP); 3053 free((void *)rbuf, M_TEMP); 3054 nfsm_reply(NFSX_V3POSTOPATTR); 3055 nfsm_srvpostop_attr(getret, &at); 3056 return (0); 3057 } 3058 if (io.uio_resid) { 3059 siz -= io.uio_resid; 3060 3061 /* 3062 * If nothing read, return eof 3063 * rpc reply 3064 */ 3065 if (siz == 0) { 3066 vrele(vp); 3067 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 3068 2 * NFSX_UNSIGNED); 3069 nfsm_srvpostop_attr(getret, &at); 3070 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 3071 txdr_hyper(at.va_filerev, tl); 3072 tl += 2; 3073 *tl++ = nfs_false; 3074 *tl = nfs_true; 3075 free((void *)cookies, M_TEMP); 3076 free((void *)rbuf, M_TEMP); 3077 return (0); 3078 } 3079 } 3080 3081 /* 3082 * Check for degenerate cases of nothing useful read. 3083 * If so go try again 3084 */ 3085 cpos = rbuf; 3086 cend = rbuf + siz; 3087 dp = (struct dirent *)cpos; 3088 cookiep = cookies; 3089 3090 while (cpos < cend && ncookies > 0 && 3091 (dp->d_fileno == 0 || dp->d_type == DT_WHT)) { 3092 cpos += dp->d_reclen; 3093 dp = (struct dirent *)cpos; 3094 cookiep++; 3095 ncookies--; 3096 } 3097 if (cpos >= cend || ncookies == 0) { 3098 toff = off; 3099 siz = fullsiz; 3100 free(cookies, M_TEMP); 3101 cookies = NULL; 3102 goto again; 3103 } 3104 3105 dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED; 3106 nfsm_reply(cnt); 3107 nfsm_srvpostop_attr(getret, &at); 3108 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3109 txdr_hyper(at.va_filerev, tl); 3110 mp = mp2 = mb; 3111 bp = bpos; 3112 be = bp + M_TRAILINGSPACE(mp); 3113 3114 /* Loop through the records and build reply */ 3115 while (cpos < cend && ncookies > 0) { 3116 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) { 3117 nfsrvfh_t nnsfh; 3118 3119 nlen = dp->d_namlen; 3120 rem = nfsm_rndup(nlen)-nlen; 3121 3122 /* 3123 * For readdir_and_lookup get the vnode using 3124 * the file number. 3125 */ 3126 if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE, 3127 &nvp)) 3128 goto invalid; 3129 if (nfsrv_composefh(nvp, &nnsfh, true)) { 3130 vput(nvp); 3131 goto invalid; 3132 } 3133 if (VOP_GETATTR(nvp, vap, cred)) { 3134 vput(nvp); 3135 goto invalid; 3136 } 3137 vput(nvp); 3138 3139 /* 3140 * If either the dircount or maxcount will be 3141 * exceeded, get out now. Both of these lengths 3142 * are calculated conservatively, including all 3143 * XDR overheads. 3144 */ 3145 len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH + 3146 NFSX_V3POSTOPATTR); 3147 dirlen += (6 * NFSX_UNSIGNED + nlen + rem); 3148 if (len > cnt || dirlen > fullsiz) { 3149 eofflag = 0; 3150 break; 3151 } 3152 3153 /* 3154 * Build the directory record xdr from 3155 * the dirent entry. 3156 */ 3157 fp = (struct nfs_fattr *)&fl.fl_fattr; 3158 nfsm_srvfillattr(vap, fp); 3159 fl.fl_fhsize = txdr_unsigned(NFSX_V3FH); 3160 fl.fl_fhok = nfs_true; 3161 fl.fl_postopok = nfs_true; 3162 txdr_hyper(*cookiep, fl.fl_off.nfsuquad); 3163 3164 nfsm_clget; 3165 *tl = nfs_true; 3166 bp += NFSX_UNSIGNED; 3167 nfsm_clget; 3168 *tl = txdr_unsigned(dp->d_fileno >> 32); 3169 bp += NFSX_UNSIGNED; 3170 nfsm_clget; 3171 *tl = txdr_unsigned(dp->d_fileno); 3172 bp += NFSX_UNSIGNED; 3173 nfsm_clget; 3174 *tl = txdr_unsigned(nlen); 3175 bp += NFSX_UNSIGNED; 3176 3177 /* And loop around copying the name */ 3178 xfer = nlen; 3179 cp = dp->d_name; 3180 while (xfer > 0) { 3181 nfsm_clget; 3182 if ((bp + xfer) > be) 3183 tsiz = be - bp; 3184 else 3185 tsiz = xfer; 3186 memcpy(bp, cp, tsiz); 3187 bp += tsiz; 3188 xfer -= tsiz; 3189 if (xfer > 0) 3190 cp += tsiz; 3191 } 3192 /* And null pad to an int32_t boundary */ 3193 for (i = 0; i < rem; i++) 3194 *bp++ = '\0'; 3195 3196 /* 3197 * Now copy the flrep structure out. 3198 */ 3199 xfer = sizeof(struct flrep); 3200 cp = (void *)&fl; 3201 while (xfer > 0) { 3202 nfsm_clget; 3203 if ((bp + xfer) > be) 3204 tsiz = be - bp; 3205 else 3206 tsiz = xfer; 3207 memcpy(bp, cp, tsiz); 3208 bp += tsiz; 3209 xfer -= tsiz; 3210 if (xfer > 0) 3211 cp += tsiz; 3212 } 3213 3214 /* 3215 * ... and filehandle. 3216 */ 3217 xfer = NFSRVFH_SIZE(&nnsfh); 3218 cp = NFSRVFH_DATA(&nnsfh); 3219 while (xfer > 0) { 3220 nfsm_clget; 3221 if ((bp + xfer) > be) 3222 tsiz = be - bp; 3223 else 3224 tsiz = xfer; 3225 memcpy(bp, cp, tsiz); 3226 bp += tsiz; 3227 xfer -= tsiz; 3228 if (xfer > 0) 3229 cp += tsiz; 3230 } 3231 } 3232 invalid: 3233 cpos += dp->d_reclen; 3234 dp = (struct dirent *)cpos; 3235 cookiep++; 3236 ncookies--; 3237 } 3238 vrele(vp); 3239 nfsm_clget; 3240 *tl = nfs_false; 3241 bp += NFSX_UNSIGNED; 3242 nfsm_clget; 3243 if (eofflag) 3244 *tl = nfs_true; 3245 else 3246 *tl = nfs_false; 3247 bp += NFSX_UNSIGNED; 3248 if (mp != mb) { 3249 if (bp < be) 3250 mp->m_len = bp - mtod(mp, char *); 3251 } else 3252 mp->m_len += bp - bpos; 3253 free((void *)cookies, M_TEMP); 3254 free((void *)rbuf, M_TEMP); 3255 nfsm_srvdone; 3256 } 3257 3258 /* 3259 * nfs commit service 3260 */ 3261 int 3262 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 3263 { 3264 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3265 struct mbuf *nam = nfsd->nd_nam; 3266 char *dpos = nfsd->nd_dpos; 3267 kauth_cred_t cred = nfsd->nd_cr; 3268 struct vattr bfor, aft; 3269 struct vnode *vp; 3270 nfsrvfh_t nsfh; 3271 u_int32_t *tl; 3272 int32_t t1; 3273 char *bpos; 3274 int error = 0, rdonly, for_ret = 1, aft_ret = 1, cache = 0; 3275 uint32_t cnt; 3276 char *cp2; 3277 struct mbuf *mb, *mreq __unused; 3278 u_quad_t frev, off, end; 3279 3280 nfsm_srvmtofh(&nsfh); 3281 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 3282 3283 off = fxdr_hyper(tl); 3284 tl += 2; 3285 cnt = fxdr_unsigned(uint32_t, *tl); 3286 error = nfsrv_fhtovp(&nsfh, 1, &vp, cred, slp, nam, 3287 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), false); 3288 if (error) { 3289 nfsm_reply(2 * NFSX_UNSIGNED); 3290 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); 3291 return (0); 3292 } 3293 for_ret = VOP_GETATTR(vp, &bfor, cred); 3294 end = (cnt > 0) ? off + cnt : vp->v_size; 3295 if (end < off || end > vp->v_size) 3296 end = vp->v_size; 3297 if (off < vp->v_size) 3298 error = VOP_FSYNC(vp, cred, FSYNC_WAIT, off, end); 3299 /* else error == 0, from nfsrv_fhtovp() */ 3300 aft_ret = VOP_GETATTR(vp, &aft, cred); 3301 vput(vp); 3302 nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF); 3303 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); 3304 if (!error) { 3305 nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF); 3306 struct timeval btv; 3307 getmicroboottime(&btv); 3308 *tl++ = txdr_unsigned(btv.tv_sec); 3309 *tl = txdr_unsigned(btv.tv_usec); 3310 } else { 3311 return (0); 3312 } 3313 nfsm_srvdone; 3314 } 3315 3316 /* 3317 * nfs statfs service 3318 */ 3319 int 3320 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 3321 { 3322 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3323 struct mbuf *nam = nfsd->nd_nam; 3324 char *dpos = nfsd->nd_dpos; 3325 kauth_cred_t cred = nfsd->nd_cr; 3326 struct statvfs *sf = NULL; 3327 struct nfs_statfs *sfp; 3328 u_int32_t *tl; 3329 int32_t t1; 3330 char *bpos; 3331 int error = 0, rdonly, cache = 0, getret = 1; 3332 int v3 = (nfsd->nd_flag & ND_NFSV3); 3333 char *cp2; 3334 struct mbuf *mb, *mreq __unused; 3335 struct vnode *vp; 3336 struct vattr at; 3337 nfsrvfh_t nsfh; 3338 u_quad_t frev, tval; 3339 3340 nfsm_srvmtofh(&nsfh); 3341 error = nfsrv_fhtovp(&nsfh, 1, &vp, cred, slp, nam, 3342 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), false); 3343 if (error) { 3344 nfsm_reply(NFSX_UNSIGNED); 3345 nfsm_srvpostop_attr(getret, &at); 3346 return (0); 3347 } 3348 sf = malloc(sizeof(*sf), M_TEMP, M_WAITOK); 3349 error = VFS_STATVFS(vp->v_mount, sf); 3350 getret = VOP_GETATTR(vp, &at, cred); 3351 vput(vp); 3352 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3)); 3353 if (v3) 3354 nfsm_srvpostop_attr(getret, &at); 3355 if (error) { 3356 free(sf, M_TEMP); 3357 return (0); 3358 } 3359 nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); 3360 if (v3) { 3361 tval = (u_quad_t)((quad_t)sf->f_blocks * (quad_t)sf->f_frsize); 3362 txdr_hyper(tval, &sfp->sf_tbytes); 3363 tval = (u_quad_t)((quad_t)sf->f_bfree * (quad_t)sf->f_frsize); 3364 txdr_hyper(tval, &sfp->sf_fbytes); 3365 tval = (u_quad_t)((quad_t)sf->f_bavail * (quad_t)sf->f_frsize); 3366 txdr_hyper(tval, &sfp->sf_abytes); 3367 tval = (u_quad_t)sf->f_files; 3368 txdr_hyper(tval, &sfp->sf_tfiles); 3369 tval = (u_quad_t)sf->f_ffree; 3370 txdr_hyper(tval, &sfp->sf_ffiles); 3371 txdr_hyper(tval, &sfp->sf_afiles); 3372 sfp->sf_invarsec = 0; 3373 } else { 3374 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA); 3375 sfp->sf_bsize = txdr_unsigned(NFS_V2CLAMP16(sf->f_frsize)); 3376 sfp->sf_blocks = txdr_unsigned(NFS_V2CLAMP32(sf->f_blocks)); 3377 sfp->sf_bfree = txdr_unsigned(NFS_V2CLAMP32(sf->f_bfree)); 3378 sfp->sf_bavail = txdr_unsigned(NFS_V2CLAMP32(sf->f_bavail)); 3379 } 3380 nfsmout: 3381 if (sf) 3382 free(sf, M_TEMP); 3383 return error; 3384 } 3385 3386 /* 3387 * nfs fsinfo service 3388 */ 3389 int 3390 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 3391 { 3392 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3393 struct mbuf *nam = nfsd->nd_nam; 3394 char *dpos = nfsd->nd_dpos; 3395 kauth_cred_t cred = nfsd->nd_cr; 3396 u_int32_t *tl; 3397 struct nfsv3_fsinfo *sip; 3398 int32_t t1; 3399 char *bpos; 3400 int error = 0, rdonly, cache = 0, getret = 1; 3401 uint32_t maxdata; 3402 char *cp2; 3403 struct mbuf *mb, *mreq __unused; 3404 struct vnode *vp; 3405 struct vattr at; 3406 nfsrvfh_t nsfh; 3407 u_quad_t frev, maxfsize; 3408 struct statvfs *sb; 3409 3410 nfsm_srvmtofh(&nsfh); 3411 error = nfsrv_fhtovp(&nsfh, 1, &vp, cred, slp, nam, 3412 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), false); 3413 if (error) { 3414 nfsm_reply(NFSX_UNSIGNED); 3415 nfsm_srvpostop_attr(getret, &at); 3416 return (0); 3417 } 3418 3419 /* XXX Try to make a guess on the max file size. */ 3420 sb = malloc(sizeof(*sb), M_TEMP, M_WAITOK); 3421 VFS_STATVFS(vp->v_mount, sb); 3422 maxfsize = (u_quad_t)0x80000000 * sb->f_frsize - 1; 3423 free(sb, M_TEMP); 3424 3425 getret = VOP_GETATTR(vp, &at, cred); 3426 vput(vp); 3427 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO); 3428 nfsm_srvpostop_attr(getret, &at); 3429 nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO); 3430 3431 /* 3432 * XXX 3433 * There should be file system VFS OP(s) to get this information. 3434 * For now, assume ufs. 3435 */ 3436 if (slp->ns_so->so_type == SOCK_DGRAM) 3437 maxdata = NFS_MAXDGRAMDATA; 3438 else 3439 maxdata = NFS_MAXDATA; 3440 sip->fs_rtmax = txdr_unsigned(maxdata); 3441 sip->fs_rtpref = txdr_unsigned(maxdata); 3442 sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE); 3443 sip->fs_wtmax = txdr_unsigned(maxdata); 3444 sip->fs_wtpref = txdr_unsigned(maxdata); 3445 sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE); 3446 sip->fs_dtpref = txdr_unsigned(maxdata); 3447 txdr_hyper(maxfsize, &sip->fs_maxfilesize); 3448 sip->fs_timedelta.nfsv3_sec = 0; 3449 sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1); 3450 sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK | 3451 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS | 3452 NFSV3FSINFO_CANSETTIME); 3453 nfsm_srvdone; 3454 } 3455 3456 /* 3457 * nfs pathconf service 3458 */ 3459 int 3460 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct lwp *lwp, struct mbuf **mrq) 3461 { 3462 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3463 struct mbuf *nam = nfsd->nd_nam; 3464 char *dpos = nfsd->nd_dpos; 3465 kauth_cred_t cred = nfsd->nd_cr; 3466 u_int32_t *tl; 3467 struct nfsv3_pathconf *pc; 3468 int32_t t1; 3469 char *bpos; 3470 int error = 0, rdonly, cache = 0, getret = 1; 3471 register_t linkmax, namemax, chownres, notrunc; 3472 char *cp2; 3473 struct mbuf *mb, *mreq __unused; 3474 struct vnode *vp; 3475 struct vattr at; 3476 nfsrvfh_t nsfh; 3477 u_quad_t frev; 3478 3479 nfsm_srvmtofh(&nsfh); 3480 error = nfsrv_fhtovp(&nsfh, 1, &vp, cred, slp, nam, 3481 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), false); 3482 if (error) { 3483 nfsm_reply(NFSX_UNSIGNED); 3484 nfsm_srvpostop_attr(getret, &at); 3485 return (0); 3486 } 3487 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax); 3488 if (!error) 3489 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax); 3490 if (!error) 3491 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres); 3492 if (!error) 3493 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc); 3494 getret = VOP_GETATTR(vp, &at, cred); 3495 vput(vp); 3496 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF); 3497 nfsm_srvpostop_attr(getret, &at); 3498 if (error) 3499 return (0); 3500 nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF); 3501 3502 pc->pc_linkmax = txdr_unsigned(linkmax); 3503 pc->pc_namemax = txdr_unsigned(namemax); 3504 pc->pc_notrunc = txdr_unsigned(notrunc); 3505 pc->pc_chownrestricted = txdr_unsigned(chownres); 3506 3507 /* 3508 * These should probably be supported by VOP_PATHCONF(), but 3509 * until msdosfs is exportable (why would you want to?), the 3510 * Unix defaults should be ok. 3511 */ 3512 pc->pc_caseinsensitive = nfs_false; 3513 pc->pc_casepreserving = nfs_true; 3514 nfsm_srvdone; 3515 } 3516 3517 /* 3518 * Null operation, used by clients to ping server 3519 */ 3520 /* ARGSUSED */ 3521 int 3522 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3523 struct lwp *lwp, struct mbuf **mrq) 3524 { 3525 struct mbuf *mrep = nfsd->nd_mrep; 3526 char *bpos; 3527 int error = NFSERR_RETVOID, cache = 0; 3528 struct mbuf *mb, *mreq __unused; 3529 u_quad_t frev; 3530 3531 nfsm_reply(0); 3532 nfsmout: 3533 return (0); 3534 } 3535 3536 /* 3537 * No operation, used for obsolete procedures 3538 */ 3539 /* ARGSUSED */ 3540 int 3541 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3542 struct lwp *lwp, struct mbuf **mrq) 3543 { 3544 struct mbuf *mrep = nfsd->nd_mrep; 3545 char *bpos; 3546 int error, cache = 0; 3547 struct mbuf *mb, *mreq __unused; 3548 u_quad_t frev; 3549 3550 if (nfsd->nd_repstat) 3551 error = nfsd->nd_repstat; 3552 else 3553 error = EPROCUNAVAIL; 3554 nfsm_reply(0); 3555 nfsmout: 3556 return (0); 3557 } 3558 3559 /* 3560 * Perform access checking for vnodes obtained from file handles that would 3561 * refer to files already opened by a Unix client. You cannot just use 3562 * vn_writechk() and VOP_ACCESS() for two reasons. 3563 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case 3564 * 2 - The owner is to be given access irrespective of mode bits for some 3565 * operations, so that processes that chmod after opening a file don't 3566 * break. I don't like this because it opens a security hole, but since 3567 * the nfs server opens a security hole the size of a barn door anyhow, 3568 * what the heck. 3569 * 3570 * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS() 3571 * will return EPERM instead of EACCES. EPERM is always an error. 3572 */ 3573 int 3574 nfsrv_access(struct vnode *vp, int flags, kauth_cred_t cred, int rdonly, struct lwp *lwp, int override) 3575 { 3576 struct vattr vattr; 3577 int error; 3578 if (flags & VWRITE) { 3579 /* Just vn_writechk() changed to check rdonly */ 3580 /* 3581 * Disallow write attempts on read-only file systems; 3582 * unless the file is a socket or a block or character 3583 * device resident on the file system. 3584 */ 3585 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3586 switch (vp->v_type) { 3587 case VREG: 3588 case VDIR: 3589 case VLNK: 3590 return (EROFS); 3591 default: 3592 break; 3593 } 3594 } 3595 3596 /* 3597 * If the vnode is in use as a process's text, 3598 * we can't allow writing. 3599 */ 3600 if (vp->v_iflag & VI_TEXT) 3601 return (ETXTBSY); 3602 } 3603 error = VOP_GETATTR(vp, &vattr, cred); 3604 if (error) 3605 return (error); 3606 error = VOP_ACCESS(vp, flags, cred); 3607 /* 3608 * Allow certain operations for the owner (reads and writes 3609 * on files that are already open). 3610 */ 3611 if (override && error == EACCES && kauth_cred_geteuid(cred) == vattr.va_uid) 3612 error = 0; 3613 return error; 3614 } 3615