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