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