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