1 /* $NetBSD: nfs_serv.c,v 1.26 1996/07/01 11:16:03 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)) 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)) 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)) 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) 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)) != 0) 574 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp); 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); 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); 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); 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 (void) vnode_pager_uncache(vp); 1660 out: 1661 if (!error) { 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 nqsrv_getl(tvp, ND_WRITE); 1836 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 1837 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 1838 } else { 1839 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 1840 if (tdvp == tvp) 1841 vrele(tdvp); 1842 else 1843 vput(tdvp); 1844 if (tvp) 1845 vput(tvp); 1846 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1847 vrele(fromnd.ni_dvp); 1848 vrele(fvp); 1849 if (error == -1) 1850 error = 0; 1851 } 1852 vrele(tond.ni_startdir); 1853 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 1854 out1: 1855 if (fdirp) { 1856 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, procp); 1857 vrele(fdirp); 1858 } 1859 if (tdirp) { 1860 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, procp); 1861 vrele(tdirp); 1862 } 1863 vrele(fromnd.ni_startdir); 1864 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 1865 nfsm_reply(2 * NFSX_WCCDATA(v3)); 1866 if (v3) { 1867 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 1868 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 1869 } 1870 return (0); 1871 1872 nfsmout: 1873 if (fdirp) 1874 vrele(fdirp); 1875 if (tdirp) 1876 vrele(tdirp); 1877 if (tond.ni_cnd.cn_nameiop) { 1878 vrele(tond.ni_startdir); 1879 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 1880 } 1881 if (fromnd.ni_cnd.cn_nameiop) { 1882 vrele(fromnd.ni_startdir); 1883 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 1884 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1885 vrele(fromnd.ni_dvp); 1886 vrele(fvp); 1887 } 1888 return (error); 1889 } 1890 1891 /* 1892 * nfs link service 1893 */ 1894 int 1895 nfsrv_link(nfsd, slp, procp, mrq) 1896 struct nfsrv_descript *nfsd; 1897 struct nfssvc_sock *slp; 1898 struct proc *procp; 1899 struct mbuf **mrq; 1900 { 1901 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 1902 struct mbuf *nam = nfsd->nd_nam; 1903 caddr_t dpos = nfsd->nd_dpos; 1904 struct ucred *cred = &nfsd->nd_cr; 1905 struct nameidata nd; 1906 register u_int32_t *tl; 1907 register int32_t t1; 1908 caddr_t bpos; 1909 int error = 0, rdonly, cache, len, dirfor_ret = 1, diraft_ret = 1; 1910 int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3); 1911 char *cp2; 1912 struct mbuf *mb, *mreq; 1913 struct vnode *vp, *xp, *dirp = (struct vnode *)0; 1914 struct vattr dirfor, diraft, at; 1915 nfsfh_t nfh, dnfh; 1916 fhandle_t *fhp, *dfhp; 1917 u_quad_t frev; 1918 1919 fhp = &nfh.fh_generic; 1920 dfhp = &dnfh.fh_generic; 1921 nfsm_srvmtofh(fhp); 1922 nfsm_srvmtofh(dfhp); 1923 nfsm_srvnamesiz(len); 1924 error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam, 1925 &rdonly, (nfsd->nd_flag & ND_KERBAUTH)); 1926 if (error) { 1927 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 1928 nfsm_srvpostop_attr(getret, &at); 1929 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1930 return (0); 1931 } 1932 if (vp->v_type == VDIR && (error = suser(cred, (u_short *)0)) != 0) 1933 goto out1; 1934 nd.ni_cnd.cn_cred = cred; 1935 nd.ni_cnd.cn_nameiop = CREATE; 1936 nd.ni_cnd.cn_flags = LOCKPARENT; 1937 error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos, 1938 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH)); 1939 if (dirp) { 1940 if (v3) 1941 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, 1942 procp); 1943 else { 1944 vrele(dirp); 1945 dirp = (struct vnode *)0; 1946 } 1947 } 1948 if (error) 1949 goto out1; 1950 xp = nd.ni_vp; 1951 if (xp != NULL) { 1952 error = EEXIST; 1953 goto out; 1954 } 1955 xp = nd.ni_dvp; 1956 if (vp->v_mount != xp->v_mount) 1957 error = EXDEV; 1958 out: 1959 if (!error) { 1960 nqsrv_getl(vp, ND_WRITE); 1961 nqsrv_getl(xp, ND_WRITE); 1962 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1963 } else { 1964 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1965 if (nd.ni_dvp == nd.ni_vp) 1966 vrele(nd.ni_dvp); 1967 else 1968 vput(nd.ni_dvp); 1969 if (nd.ni_vp) 1970 vrele(nd.ni_vp); 1971 } 1972 out1: 1973 if (v3) 1974 getret = VOP_GETATTR(vp, &at, cred, procp); 1975 if (dirp) { 1976 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp); 1977 vrele(dirp); 1978 } 1979 vrele(vp); 1980 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 1981 if (v3) { 1982 nfsm_srvpostop_attr(getret, &at); 1983 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1984 return (0); 1985 } 1986 nfsm_srvdone; 1987 } 1988 1989 /* 1990 * nfs symbolic link service 1991 */ 1992 int 1993 nfsrv_symlink(nfsd, slp, procp, mrq) 1994 struct nfsrv_descript *nfsd; 1995 struct nfssvc_sock *slp; 1996 struct proc *procp; 1997 struct mbuf **mrq; 1998 { 1999 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2000 struct mbuf *nam = nfsd->nd_nam; 2001 caddr_t dpos = nfsd->nd_dpos; 2002 struct ucred *cred = &nfsd->nd_cr; 2003 struct vattr va, dirfor, diraft; 2004 struct nameidata nd; 2005 register u_int32_t *tl; 2006 register int32_t t1; 2007 struct nfsv2_sattr *sp; 2008 char *bpos, *pathcp = NULL, *cp2; 2009 struct uio io; 2010 struct iovec iv; 2011 int error = 0, cache, len, len2, dirfor_ret = 1, diraft_ret = 1; 2012 int v3 = (nfsd->nd_flag & ND_NFSV3); 2013 struct mbuf *mb, *mreq, *mb2; 2014 struct vnode *dirp = (struct vnode *)0; 2015 nfsfh_t nfh; 2016 fhandle_t *fhp; 2017 u_quad_t frev; 2018 2019 nd.ni_cnd.cn_nameiop = 0; 2020 fhp = &nfh.fh_generic; 2021 nfsm_srvmtofh(fhp); 2022 nfsm_srvnamesiz(len); 2023 nd.ni_cnd.cn_cred = cred; 2024 nd.ni_cnd.cn_nameiop = CREATE; 2025 nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART; 2026 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos, 2027 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH)); 2028 if (dirp) { 2029 if (v3) 2030 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, 2031 procp); 2032 else { 2033 vrele(dirp); 2034 dirp = (struct vnode *)0; 2035 } 2036 } 2037 if (error) 2038 goto out; 2039 VATTR_NULL(&va); 2040 if (v3) 2041 nfsm_srvsattr(&va); 2042 nfsm_strsiz(len2, NFS_MAXPATHLEN); 2043 MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK); 2044 iv.iov_base = pathcp; 2045 iv.iov_len = len2; 2046 io.uio_resid = len2; 2047 io.uio_offset = 0; 2048 io.uio_iov = &iv; 2049 io.uio_iovcnt = 1; 2050 io.uio_segflg = UIO_SYSSPACE; 2051 io.uio_rw = UIO_READ; 2052 io.uio_procp = (struct proc *)0; 2053 nfsm_mtouio(&io, len2); 2054 if (!v3) { 2055 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 2056 va.va_mode = fxdr_unsigned(u_int16_t, sp->sa_mode); 2057 } 2058 *(pathcp + len2) = '\0'; 2059 if (nd.ni_vp) { 2060 vrele(nd.ni_startdir); 2061 free(nd.ni_cnd.cn_pnbuf, M_NAMEI); 2062 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2063 if (nd.ni_dvp == nd.ni_vp) 2064 vrele(nd.ni_dvp); 2065 else 2066 vput(nd.ni_dvp); 2067 vrele(nd.ni_vp); 2068 error = EEXIST; 2069 goto out; 2070 } 2071 nqsrv_getl(nd.ni_dvp, ND_WRITE); 2072 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va, pathcp); 2073 if (error) 2074 vrele(nd.ni_startdir); 2075 else { 2076 if (v3) { 2077 nd.ni_cnd.cn_nameiop = LOOKUP; 2078 nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART | FOLLOW); 2079 nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF); 2080 nd.ni_cnd.cn_proc = procp; 2081 nd.ni_cnd.cn_cred = cred; 2082 error = lookup(&nd); 2083 if (!error) { 2084 bzero((caddr_t)fhp, sizeof(nfh)); 2085 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid; 2086 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid); 2087 if (!error) 2088 error = VOP_GETATTR(nd.ni_vp, &va, cred, 2089 procp); 2090 vput(nd.ni_vp); 2091 } 2092 } else 2093 vrele(nd.ni_startdir); 2094 FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI); 2095 } 2096 out: 2097 if (pathcp) 2098 FREE(pathcp, M_TEMP); 2099 if (dirp) { 2100 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp); 2101 vrele(dirp); 2102 } 2103 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2104 if (v3) { 2105 if (!error) { 2106 nfsm_srvpostop_fh(fhp); 2107 nfsm_srvpostop_attr(0, &va); 2108 } 2109 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2110 } 2111 return (0); 2112 nfsmout: 2113 if (nd.ni_cnd.cn_nameiop) { 2114 vrele(nd.ni_startdir); 2115 free(nd.ni_cnd.cn_pnbuf, M_NAMEI); 2116 } 2117 if (dirp) 2118 vrele(dirp); 2119 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2120 if (nd.ni_dvp == nd.ni_vp) 2121 vrele(nd.ni_dvp); 2122 else 2123 vput(nd.ni_dvp); 2124 if (nd.ni_vp) 2125 vrele(nd.ni_vp); 2126 if (pathcp) 2127 FREE(pathcp, M_TEMP); 2128 return (error); 2129 } 2130 2131 /* 2132 * nfs mkdir service 2133 */ 2134 int 2135 nfsrv_mkdir(nfsd, slp, procp, mrq) 2136 struct nfsrv_descript *nfsd; 2137 struct nfssvc_sock *slp; 2138 struct proc *procp; 2139 struct mbuf **mrq; 2140 { 2141 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2142 struct mbuf *nam = nfsd->nd_nam; 2143 caddr_t dpos = nfsd->nd_dpos; 2144 struct ucred *cred = &nfsd->nd_cr; 2145 struct vattr va, dirfor, diraft; 2146 register struct nfs_fattr *fp; 2147 struct nameidata nd; 2148 register caddr_t cp; 2149 register u_int32_t *tl; 2150 register int32_t t1; 2151 caddr_t bpos; 2152 int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1; 2153 int v3 = (nfsd->nd_flag & ND_NFSV3); 2154 char *cp2; 2155 struct mbuf *mb, *mb2, *mreq; 2156 struct vnode *vp, *dirp = (struct vnode *)0; 2157 nfsfh_t nfh; 2158 fhandle_t *fhp; 2159 u_quad_t frev; 2160 2161 fhp = &nfh.fh_generic; 2162 nfsm_srvmtofh(fhp); 2163 nfsm_srvnamesiz(len); 2164 nd.ni_cnd.cn_cred = cred; 2165 nd.ni_cnd.cn_nameiop = CREATE; 2166 nd.ni_cnd.cn_flags = LOCKPARENT; 2167 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos, 2168 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH)); 2169 if (dirp) { 2170 if (v3) 2171 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, 2172 procp); 2173 else { 2174 vrele(dirp); 2175 dirp = (struct vnode *)0; 2176 } 2177 } 2178 if (error) { 2179 nfsm_reply(NFSX_WCCDATA(v3)); 2180 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2181 if (dirp) 2182 vrele(dirp); 2183 return (0); 2184 } 2185 VATTR_NULL(&va); 2186 if (v3) { 2187 nfsm_srvsattr(&va); 2188 } else { 2189 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2190 va.va_mode = nfstov_mode(*tl++); 2191 } 2192 va.va_type = VDIR; 2193 vp = nd.ni_vp; 2194 if (vp != NULL) { 2195 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2196 if (nd.ni_dvp == vp) 2197 vrele(nd.ni_dvp); 2198 else 2199 vput(nd.ni_dvp); 2200 vrele(vp); 2201 error = EEXIST; 2202 goto out; 2203 } 2204 nqsrv_getl(nd.ni_dvp, ND_WRITE); 2205 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va); 2206 if (!error) { 2207 vp = nd.ni_vp; 2208 bzero((caddr_t)fhp, sizeof(nfh)); 2209 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 2210 error = VFS_VPTOFH(vp, &fhp->fh_fid); 2211 if (!error) 2212 error = VOP_GETATTR(vp, &va, cred, procp); 2213 vput(vp); 2214 } 2215 out: 2216 if (dirp) { 2217 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp); 2218 vrele(dirp); 2219 } 2220 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2221 if (v3) { 2222 if (!error) { 2223 nfsm_srvpostop_fh(fhp); 2224 nfsm_srvpostop_attr(0, &va); 2225 } 2226 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2227 } else { 2228 nfsm_srvfhtom(fhp, v3); 2229 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 2230 nfsm_srvfillattr(&va, fp); 2231 } 2232 return (0); 2233 nfsmout: 2234 if (dirp) 2235 vrele(dirp); 2236 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2237 if (nd.ni_dvp == nd.ni_vp) 2238 vrele(nd.ni_dvp); 2239 else 2240 vput(nd.ni_dvp); 2241 if (nd.ni_vp) 2242 vrele(nd.ni_vp); 2243 return (error); 2244 } 2245 2246 /* 2247 * nfs rmdir service 2248 */ 2249 int 2250 nfsrv_rmdir(nfsd, slp, procp, mrq) 2251 struct nfsrv_descript *nfsd; 2252 struct nfssvc_sock *slp; 2253 struct proc *procp; 2254 struct mbuf **mrq; 2255 { 2256 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2257 struct mbuf *nam = nfsd->nd_nam; 2258 caddr_t dpos = nfsd->nd_dpos; 2259 struct ucred *cred = &nfsd->nd_cr; 2260 register u_int32_t *tl; 2261 register int32_t t1; 2262 caddr_t bpos; 2263 int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1; 2264 int v3 = (nfsd->nd_flag & ND_NFSV3); 2265 char *cp2; 2266 struct mbuf *mb, *mreq; 2267 struct vnode *vp, *dirp = (struct vnode *)0; 2268 struct vattr dirfor, diraft; 2269 nfsfh_t nfh; 2270 fhandle_t *fhp; 2271 struct nameidata nd; 2272 u_quad_t frev; 2273 2274 fhp = &nfh.fh_generic; 2275 nfsm_srvmtofh(fhp); 2276 nfsm_srvnamesiz(len); 2277 nd.ni_cnd.cn_cred = cred; 2278 nd.ni_cnd.cn_nameiop = DELETE; 2279 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; 2280 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos, 2281 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH)); 2282 if (dirp) { 2283 if (v3) 2284 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, 2285 procp); 2286 else { 2287 vrele(dirp); 2288 dirp = (struct vnode *)0; 2289 } 2290 } 2291 if (error) { 2292 nfsm_reply(NFSX_WCCDATA(v3)); 2293 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2294 if (dirp) 2295 vrele(dirp); 2296 return (0); 2297 } 2298 vp = nd.ni_vp; 2299 if (vp->v_type != VDIR) { 2300 error = ENOTDIR; 2301 goto out; 2302 } 2303 /* 2304 * No rmdir "." please. 2305 */ 2306 if (nd.ni_dvp == vp) { 2307 error = EINVAL; 2308 goto out; 2309 } 2310 /* 2311 * The root of a mounted filesystem cannot be deleted. 2312 */ 2313 if (vp->v_flag & VROOT) 2314 error = EBUSY; 2315 out: 2316 if (!error) { 2317 nqsrv_getl(nd.ni_dvp, ND_WRITE); 2318 nqsrv_getl(vp, ND_WRITE); 2319 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 2320 } else { 2321 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2322 if (nd.ni_dvp == nd.ni_vp) 2323 vrele(nd.ni_dvp); 2324 else 2325 vput(nd.ni_dvp); 2326 vput(vp); 2327 } 2328 if (dirp) { 2329 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp); 2330 vrele(dirp); 2331 } 2332 nfsm_reply(NFSX_WCCDATA(v3)); 2333 if (v3) { 2334 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2335 return (0); 2336 } 2337 nfsm_srvdone; 2338 } 2339 2340 /* 2341 * nfs readdir service 2342 * - mallocs what it thinks is enough to read 2343 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR 2344 * - calls VOP_READDIR() 2345 * - loops around building the reply 2346 * if the output generated exceeds count break out of loop 2347 * The nfsm_clget macro is used here so that the reply will be packed 2348 * tightly in mbuf clusters. 2349 * - it only knows that it has encountered eof when the VOP_READDIR() 2350 * reads nothing 2351 * - as such one readdir rpc will return eof false although you are there 2352 * and then the next will return eof 2353 * - it trims out records with d_fileno == 0 2354 * this doesn't matter for Unix clients, but they might confuse clients 2355 * for other os'. 2356 * - it trims out records with d_type == DT_WHT 2357 * these cannot be seen through NFS (unless we extend the protocol) 2358 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less 2359 * than requested, but this may not apply to all filesystems. For 2360 * example, client NFS does not { although it is never remote mounted 2361 * anyhow } 2362 * The alternate call nfsrv_readdirplus() does lookups as well. 2363 * PS: The NFS protocol spec. does not clarify what the "count" byte 2364 * argument is a count of.. just name strings and file id's or the 2365 * entire reply rpc or ... 2366 * I tried just file name and id sizes and it confused the Sun client, 2367 * so I am using the full rpc size now. The "paranoia.." comment refers 2368 * to including the status longwords that are not a part of the dir. 2369 * "entry" structures, but are in the rpc. 2370 */ 2371 struct flrep { 2372 nfsuint64 fl_off; 2373 u_int32_t fl_postopok; 2374 u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)]; 2375 u_int32_t fl_fhok; 2376 u_int32_t fl_fhsize; 2377 u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)]; 2378 }; 2379 2380 int 2381 nfsrv_readdir(nfsd, slp, procp, mrq) 2382 struct nfsrv_descript *nfsd; 2383 struct nfssvc_sock *slp; 2384 struct proc *procp; 2385 struct mbuf **mrq; 2386 { 2387 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2388 struct mbuf *nam = nfsd->nd_nam; 2389 caddr_t dpos = nfsd->nd_dpos; 2390 struct ucred *cred = &nfsd->nd_cr; 2391 register char *bp, *be; 2392 register struct mbuf *mp; 2393 register struct dirent *dp; 2394 register caddr_t cp; 2395 register u_int32_t *tl; 2396 register int32_t t1; 2397 caddr_t bpos; 2398 struct mbuf *mb, *mb2, *mreq, *mp2; 2399 char *cpos, *cend, *cp2, *rbuf; 2400 struct vnode *vp; 2401 struct vattr at; 2402 nfsfh_t nfh; 2403 fhandle_t *fhp; 2404 struct uio io; 2405 struct iovec iv; 2406 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1; 2407 int siz, cnt, fullsiz, eofflag, rdonly, cache, ncookies; 2408 int v3 = (nfsd->nd_flag & ND_NFSV3); 2409 u_quad_t frev, off, toff, verf; 2410 u_long *cookies = NULL, *cookiep; 2411 2412 fhp = &nfh.fh_generic; 2413 nfsm_srvmtofh(fhp); 2414 if (v3) { 2415 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 2416 fxdr_hyper(tl, &toff); 2417 tl += 2; 2418 fxdr_hyper(tl, &verf); 2419 tl += 2; 2420 } else { 2421 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2422 toff = fxdr_unsigned(u_quad_t, *tl++); 2423 } 2424 off = toff; 2425 cnt = fxdr_unsigned(int, *tl); 2426 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 2427 xfer = NFS_SRVMAXDATA(nfsd); 2428 if (siz > xfer) 2429 siz = xfer; 2430 fullsiz = siz; 2431 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 2432 &rdonly, (nfsd->nd_flag & ND_KERBAUTH)); 2433 if (error) { 2434 nfsm_reply(NFSX_UNSIGNED); 2435 nfsm_srvpostop_attr(getret, &at); 2436 return (0); 2437 } 2438 nqsrv_getl(vp, ND_READ); 2439 if (v3) { 2440 error = getret = VOP_GETATTR(vp, &at, cred, procp); 2441 #ifdef NFS3_STRICTVERF 2442 /* 2443 * XXX This check is too strict for Solaris 2.5 clients. 2444 */ 2445 if (!error && toff && verf != at.va_filerev) 2446 error = NFSERR_BAD_COOKIE; 2447 #endif 2448 } 2449 if (!error) 2450 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp); 2451 if (error) { 2452 vput(vp); 2453 nfsm_reply(NFSX_POSTOPATTR(v3)); 2454 nfsm_srvpostop_attr(getret, &at); 2455 return (0); 2456 } 2457 #ifdef Lite2_integrated 2458 VOP_UNLOCK(vp, 0, procp); 2459 #else 2460 VOP_UNLOCK(vp); 2461 #endif 2462 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 2463 ncookies = siz / (5 * NFSX_UNSIGNED); /*7 for V3, but it's an est. so*/ 2464 MALLOC(cookies, u_long *, ncookies * sizeof (u_long *), M_TEMP, 2465 M_WAITOK); 2466 again: 2467 iv.iov_base = rbuf; 2468 iv.iov_len = fullsiz; 2469 io.uio_iov = &iv; 2470 io.uio_iovcnt = 1; 2471 io.uio_offset = (off_t)off; 2472 io.uio_resid = fullsiz; 2473 io.uio_segflg = UIO_SYSSPACE; 2474 io.uio_rw = UIO_READ; 2475 io.uio_procp = (struct proc *)0; 2476 eofflag = 0; 2477 #ifdef Lite2_integrated 2478 VOP_LOCK(vp, 0, procp); 2479 #else 2480 VOP_LOCK(vp); 2481 #endif 2482 2483 error = VOP_READDIR(vp, &io, cred, &eofflag, cookies, ncookies); 2484 2485 off = (off_t)io.uio_offset; 2486 if (!cookies && !error) 2487 error = NFSERR_PERM; 2488 if (v3) { 2489 getret = VOP_GETATTR(vp, &at, cred, procp); 2490 if (!error) 2491 error = getret; 2492 } 2493 2494 #ifdef Lite2_integrated 2495 VOP_UNLOCK(vp, 0, procp); 2496 #else 2497 VOP_UNLOCK(vp); 2498 #endif 2499 if (error) { 2500 vrele(vp); 2501 free((caddr_t)rbuf, M_TEMP); 2502 if (cookies) 2503 free((caddr_t)cookies, M_TEMP); 2504 nfsm_reply(NFSX_POSTOPATTR(v3)); 2505 nfsm_srvpostop_attr(getret, &at); 2506 return (0); 2507 } 2508 if (io.uio_resid) { 2509 siz -= io.uio_resid; 2510 2511 /* 2512 * If nothing read, return eof 2513 * rpc reply 2514 */ 2515 if (siz == 0) { 2516 vrele(vp); 2517 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + 2518 2 * NFSX_UNSIGNED); 2519 if (v3) { 2520 nfsm_srvpostop_attr(getret, &at); 2521 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 2522 txdr_hyper(&at.va_filerev, tl); 2523 tl += 2; 2524 } else 2525 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2526 *tl++ = nfs_false; 2527 *tl = nfs_true; 2528 FREE((caddr_t)rbuf, M_TEMP); 2529 FREE((caddr_t)cookies, M_TEMP); 2530 return (0); 2531 } 2532 } 2533 2534 /* 2535 * Check for degenerate cases of nothing useful read. 2536 * If so go try again 2537 */ 2538 cpos = rbuf; 2539 cend = rbuf + siz; 2540 dp = (struct dirent *)cpos; 2541 cookiep = cookies; 2542 2543 while ((dp->d_fileno == 0 || dp->d_type == DT_WHT) && 2544 cpos < cend && ncookies > 0) { 2545 cpos += dp->d_reclen; 2546 dp = (struct dirent *)cpos; 2547 cookiep++; 2548 ncookies--; 2549 } 2550 if (cpos >= cend || ncookies == 0) { 2551 toff = off; 2552 siz = fullsiz; 2553 goto again; 2554 } 2555 2556 len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */ 2557 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz); 2558 if (v3) { 2559 nfsm_srvpostop_attr(getret, &at); 2560 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2561 txdr_hyper(&at.va_filerev, tl); 2562 } 2563 mp = mp2 = mb; 2564 bp = bpos; 2565 be = bp + M_TRAILINGSPACE(mp); 2566 2567 /* Loop through the records and build reply */ 2568 while (cpos < cend && ncookies > 0) { 2569 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) { 2570 nlen = dp->d_namlen; 2571 rem = nfsm_rndup(nlen)-nlen; 2572 len += (4 * NFSX_UNSIGNED + nlen + rem); 2573 if (v3) 2574 len += 2 * NFSX_UNSIGNED; 2575 if (len > cnt) { 2576 eofflag = 0; 2577 break; 2578 } 2579 /* 2580 * Build the directory record xdr from 2581 * the dirent entry. 2582 */ 2583 nfsm_clget; 2584 *tl = nfs_true; 2585 bp += NFSX_UNSIGNED; 2586 if (v3) { 2587 nfsm_clget; 2588 *tl = 0; 2589 bp += NFSX_UNSIGNED; 2590 } 2591 nfsm_clget; 2592 *tl = txdr_unsigned(dp->d_fileno); 2593 bp += NFSX_UNSIGNED; 2594 nfsm_clget; 2595 *tl = txdr_unsigned(nlen); 2596 bp += NFSX_UNSIGNED; 2597 2598 /* And loop around copying the name */ 2599 xfer = nlen; 2600 cp = dp->d_name; 2601 while (xfer > 0) { 2602 nfsm_clget; 2603 if ((bp+xfer) > be) 2604 tsiz = be-bp; 2605 else 2606 tsiz = xfer; 2607 bcopy(cp, bp, tsiz); 2608 bp += tsiz; 2609 xfer -= tsiz; 2610 if (xfer > 0) 2611 cp += tsiz; 2612 } 2613 /* And null pad to an int32_t boundary */ 2614 for (i = 0; i < rem; i++) 2615 *bp++ = '\0'; 2616 nfsm_clget; 2617 2618 /* Finish off the record */ 2619 if (v3) { 2620 *tl = 0; 2621 bp += NFSX_UNSIGNED; 2622 nfsm_clget; 2623 } 2624 *tl = txdr_unsigned(*cookiep); 2625 bp += NFSX_UNSIGNED; 2626 } 2627 cpos += dp->d_reclen; 2628 dp = (struct dirent *)cpos; 2629 cookiep++; 2630 ncookies--; 2631 } 2632 vrele(vp); 2633 nfsm_clget; 2634 *tl = nfs_false; 2635 bp += NFSX_UNSIGNED; 2636 nfsm_clget; 2637 if (eofflag) 2638 *tl = nfs_true; 2639 else 2640 *tl = nfs_false; 2641 bp += NFSX_UNSIGNED; 2642 if (mp != mb) { 2643 if (bp < be) 2644 mp->m_len = bp - mtod(mp, caddr_t); 2645 } else 2646 mp->m_len += bp - bpos; 2647 FREE((caddr_t)rbuf, M_TEMP); 2648 FREE((caddr_t)cookies, M_TEMP); 2649 nfsm_srvdone; 2650 } 2651 2652 int 2653 nfsrv_readdirplus(nfsd, slp, procp, mrq) 2654 struct nfsrv_descript *nfsd; 2655 struct nfssvc_sock *slp; 2656 struct proc *procp; 2657 struct mbuf **mrq; 2658 { 2659 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2660 struct mbuf *nam = nfsd->nd_nam; 2661 caddr_t dpos = nfsd->nd_dpos; 2662 struct ucred *cred = &nfsd->nd_cr; 2663 register char *bp, *be; 2664 register struct mbuf *mp; 2665 register struct dirent *dp; 2666 register caddr_t cp; 2667 register u_int32_t *tl; 2668 register int32_t t1; 2669 caddr_t bpos; 2670 struct mbuf *mb, *mb2, *mreq, *mp2; 2671 char *cpos, *cend, *cp2, *rbuf; 2672 struct vnode *vp, *nvp; 2673 struct flrep fl; 2674 nfsfh_t nfh; 2675 fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh; 2676 struct uio io; 2677 struct iovec iv; 2678 struct vattr va, at, *vap = &va; 2679 struct nfs_fattr *fp; 2680 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1; 2681 int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies; 2682 u_quad_t frev, off, toff, verf; 2683 u_long *cookies = NULL, *cookiep; 2684 2685 fhp = &nfh.fh_generic; 2686 nfsm_srvmtofh(fhp); 2687 nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); 2688 fxdr_hyper(tl, &toff); 2689 tl += 2; 2690 fxdr_hyper(tl, &verf); 2691 tl += 2; 2692 siz = fxdr_unsigned(int, *tl++); 2693 cnt = fxdr_unsigned(int, *tl); 2694 off = toff; 2695 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 2696 xfer = NFS_SRVMAXDATA(nfsd); 2697 if (siz > xfer) 2698 siz = xfer; 2699 fullsiz = siz; 2700 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 2701 &rdonly, (nfsd->nd_flag & ND_KERBAUTH)); 2702 if (error) { 2703 nfsm_reply(NFSX_UNSIGNED); 2704 nfsm_srvpostop_attr(getret, &at); 2705 return (0); 2706 } 2707 error = getret = VOP_GETATTR(vp, &at, cred, procp); 2708 #ifdef NFS3_STRICTVERF 2709 /* 2710 * XXX This check is too strict for Solaris 2.5 clients. 2711 */ 2712 if (!error && toff && verf != at.va_filerev) 2713 error = NFSERR_BAD_COOKIE; 2714 #endif 2715 if (!error) { 2716 nqsrv_getl(vp, ND_READ); 2717 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp); 2718 } 2719 if (error) { 2720 vput(vp); 2721 nfsm_reply(NFSX_V3POSTOPATTR); 2722 nfsm_srvpostop_attr(getret, &at); 2723 return (0); 2724 } 2725 #ifdef Lite2_integrated 2726 VOP_UNLOCK(vp, 0, procp); 2727 #else 2728 VOP_UNLOCK(vp); 2729 #endif 2730 2731 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 2732 ncookies = siz / (7 * NFSX_UNSIGNED); 2733 MALLOC(cookies, u_long *, ncookies * sizeof (u_long *), M_TEMP, 2734 M_WAITOK); 2735 again: 2736 iv.iov_base = rbuf; 2737 iv.iov_len = fullsiz; 2738 io.uio_iov = &iv; 2739 io.uio_iovcnt = 1; 2740 io.uio_offset = (off_t)off; 2741 io.uio_resid = fullsiz; 2742 io.uio_segflg = UIO_SYSSPACE; 2743 io.uio_rw = UIO_READ; 2744 io.uio_procp = (struct proc *)0; 2745 eofflag = 0; 2746 2747 #ifdef Lite2_integrated 2748 VOP_LOCK(vp, 0, procp); 2749 #else 2750 VOP_LOCK(vp); 2751 #endif 2752 error = VOP_READDIR(vp, &io, cred, &eofflag, cookies, ncookies); 2753 2754 off = (u_quad_t)io.uio_offset; 2755 getret = VOP_GETATTR(vp, &at, cred, procp); 2756 2757 #ifdef Lite2_integrated 2758 VOP_UNLOCK(vp, 0, procp); 2759 #else 2760 VOP_UNLOCK(vp); 2761 #endif 2762 if (!cookies && !error) 2763 error = NFSERR_PERM; 2764 if (!error) 2765 error = getret; 2766 if (error) { 2767 vrele(vp); 2768 if (cookies) 2769 free((caddr_t)cookies, M_TEMP); 2770 free((caddr_t)rbuf, M_TEMP); 2771 nfsm_reply(NFSX_V3POSTOPATTR); 2772 nfsm_srvpostop_attr(getret, &at); 2773 return (0); 2774 } 2775 if (io.uio_resid) { 2776 siz -= io.uio_resid; 2777 2778 /* 2779 * If nothing read, return eof 2780 * rpc reply 2781 */ 2782 if (siz == 0) { 2783 vrele(vp); 2784 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2785 2 * NFSX_UNSIGNED); 2786 nfsm_srvpostop_attr(getret, &at); 2787 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 2788 txdr_hyper(&at.va_filerev, tl); 2789 tl += 2; 2790 *tl++ = nfs_false; 2791 *tl = nfs_true; 2792 FREE((caddr_t)cookies, M_TEMP); 2793 FREE((caddr_t)rbuf, M_TEMP); 2794 return (0); 2795 } 2796 } 2797 2798 /* 2799 * Check for degenerate cases of nothing useful read. 2800 * If so go try again 2801 */ 2802 cpos = rbuf; 2803 cend = rbuf + siz; 2804 dp = (struct dirent *)cpos; 2805 cookiep = cookies; 2806 2807 while ((dp->d_fileno == 0 || dp->d_type == DT_WHT) 2808 && cpos < cend && ncookies > 0) { 2809 cpos += dp->d_reclen; 2810 dp = (struct dirent *)cpos; 2811 cookiep++; 2812 ncookies--; 2813 } 2814 if (cpos >= cend || ncookies == 0) { 2815 toff = off; 2816 siz = fullsiz; 2817 goto again; 2818 } 2819 2820 dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED; 2821 nfsm_reply(cnt); 2822 nfsm_srvpostop_attr(getret, &at); 2823 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2824 txdr_hyper(&at.va_filerev, tl); 2825 mp = mp2 = mb; 2826 bp = bpos; 2827 be = bp + M_TRAILINGSPACE(mp); 2828 2829 /* Loop through the records and build reply */ 2830 while (cpos < cend && ncookies > 0) { 2831 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) { 2832 nlen = dp->d_namlen; 2833 rem = nfsm_rndup(nlen)-nlen; 2834 2835 /* 2836 * For readdir_and_lookup get the vnode using 2837 * the file number. 2838 */ 2839 if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp)) 2840 goto invalid; 2841 bzero((caddr_t)nfhp, NFSX_V3FH); 2842 nfhp->fh_fsid = 2843 nvp->v_mount->mnt_stat.f_fsid; 2844 if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) { 2845 vput(nvp); 2846 goto invalid; 2847 } 2848 if (VOP_GETATTR(nvp, vap, cred, procp)) { 2849 vput(nvp); 2850 goto invalid; 2851 } 2852 vput(nvp); 2853 2854 /* 2855 * If either the dircount or maxcount will be 2856 * exceeded, get out now. Both of these lengths 2857 * are calculated conservatively, including all 2858 * XDR overheads. 2859 */ 2860 len += (7 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH + 2861 NFSX_V3POSTOPATTR); 2862 dirlen += (6 * NFSX_UNSIGNED + nlen + rem); 2863 if (len > cnt || dirlen > fullsiz) { 2864 eofflag = 0; 2865 break; 2866 } 2867 2868 /* 2869 * Build the directory record xdr from 2870 * the dirent entry. 2871 */ 2872 fp = (struct nfs_fattr *)&fl.fl_fattr; 2873 nfsm_srvfillattr(vap, fp); 2874 fl.fl_fhsize = txdr_unsigned(NFSX_V3FH); 2875 fl.fl_fhok = nfs_true; 2876 fl.fl_postopok = nfs_true; 2877 fl.fl_off.nfsuquad[0] = 0; 2878 fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep); 2879 2880 nfsm_clget; 2881 *tl = nfs_true; 2882 bp += NFSX_UNSIGNED; 2883 nfsm_clget; 2884 *tl = 0; 2885 bp += NFSX_UNSIGNED; 2886 nfsm_clget; 2887 *tl = txdr_unsigned(dp->d_fileno); 2888 bp += NFSX_UNSIGNED; 2889 nfsm_clget; 2890 *tl = txdr_unsigned(nlen); 2891 bp += NFSX_UNSIGNED; 2892 2893 /* And loop around copying the name */ 2894 xfer = nlen; 2895 cp = dp->d_name; 2896 while (xfer > 0) { 2897 nfsm_clget; 2898 if ((bp + xfer) > be) 2899 tsiz = be - bp; 2900 else 2901 tsiz = xfer; 2902 bcopy(cp, bp, tsiz); 2903 bp += tsiz; 2904 xfer -= tsiz; 2905 if (xfer > 0) 2906 cp += tsiz; 2907 } 2908 /* And null pad to an int32_t boundary */ 2909 for (i = 0; i < rem; i++) 2910 *bp++ = '\0'; 2911 2912 /* 2913 * Now copy the flrep structure out. 2914 */ 2915 xfer = sizeof (struct flrep); 2916 cp = (caddr_t)&fl; 2917 while (xfer > 0) { 2918 nfsm_clget; 2919 if ((bp + xfer) > be) 2920 tsiz = be - bp; 2921 else 2922 tsiz = xfer; 2923 bcopy(cp, bp, tsiz); 2924 bp += tsiz; 2925 xfer -= tsiz; 2926 if (xfer > 0) 2927 cp += tsiz; 2928 } 2929 } 2930 invalid: 2931 cpos += dp->d_reclen; 2932 dp = (struct dirent *)cpos; 2933 cookiep++; 2934 ncookies--; 2935 } 2936 vrele(vp); 2937 nfsm_clget; 2938 *tl = nfs_false; 2939 bp += NFSX_UNSIGNED; 2940 nfsm_clget; 2941 if (eofflag) 2942 *tl = nfs_true; 2943 else 2944 *tl = nfs_false; 2945 bp += NFSX_UNSIGNED; 2946 if (mp != mb) { 2947 if (bp < be) 2948 mp->m_len = bp - mtod(mp, caddr_t); 2949 } else 2950 mp->m_len += bp - bpos; 2951 FREE((caddr_t)cookies, M_TEMP); 2952 FREE((caddr_t)rbuf, M_TEMP); 2953 nfsm_srvdone; 2954 } 2955 2956 /* 2957 * nfs commit service 2958 */ 2959 int 2960 nfsrv_commit(nfsd, slp, procp, mrq) 2961 struct nfsrv_descript *nfsd; 2962 struct nfssvc_sock *slp; 2963 struct proc *procp; 2964 struct mbuf **mrq; 2965 { 2966 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2967 struct mbuf *nam = nfsd->nd_nam; 2968 caddr_t dpos = nfsd->nd_dpos; 2969 struct ucred *cred = &nfsd->nd_cr; 2970 struct vattr bfor, aft; 2971 struct vnode *vp; 2972 nfsfh_t nfh; 2973 fhandle_t *fhp; 2974 register u_int32_t *tl; 2975 register int32_t t1; 2976 caddr_t bpos; 2977 int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt, cache; 2978 char *cp2; 2979 struct mbuf *mb, *mb2, *mreq; 2980 u_quad_t frev, off; 2981 2982 #ifndef nolint 2983 cache = 0; 2984 #endif 2985 fhp = &nfh.fh_generic; 2986 nfsm_srvmtofh(fhp); 2987 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2988 2989 /* 2990 * XXX At this time VOP_FSYNC() does not accept offset and byte 2991 * count parameters, so these arguments are useless (someday maybe). 2992 */ 2993 fxdr_hyper(tl, &off); 2994 tl += 2; 2995 cnt = fxdr_unsigned(int, *tl); 2996 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 2997 &rdonly, (nfsd->nd_flag & ND_KERBAUTH)); 2998 if (error) { 2999 nfsm_reply(2 * NFSX_UNSIGNED); 3000 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); 3001 return (0); 3002 } 3003 for_ret = VOP_GETATTR(vp, &bfor, cred, procp); 3004 error = VOP_FSYNC(vp, cred, MNT_WAIT, procp); 3005 aft_ret = VOP_GETATTR(vp, &aft, cred, procp); 3006 vput(vp); 3007 nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF); 3008 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); 3009 if (!error) { 3010 nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF); 3011 *tl++ = txdr_unsigned(boottime.tv_sec); 3012 *tl = txdr_unsigned(boottime.tv_usec); 3013 } else 3014 return (0); 3015 nfsm_srvdone; 3016 } 3017 3018 /* 3019 * nfs statfs service 3020 */ 3021 int 3022 nfsrv_statfs(nfsd, slp, procp, mrq) 3023 struct nfsrv_descript *nfsd; 3024 struct nfssvc_sock *slp; 3025 struct proc *procp; 3026 struct mbuf **mrq; 3027 { 3028 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3029 struct mbuf *nam = nfsd->nd_nam; 3030 caddr_t dpos = nfsd->nd_dpos; 3031 struct ucred *cred = &nfsd->nd_cr; 3032 register struct statfs *sf; 3033 register struct nfs_statfs *sfp; 3034 register u_int32_t *tl; 3035 register int32_t t1; 3036 caddr_t bpos; 3037 int error = 0, rdonly, cache, getret = 1; 3038 int v3 = (nfsd->nd_flag & ND_NFSV3); 3039 char *cp2; 3040 struct mbuf *mb, *mb2, *mreq; 3041 struct vnode *vp; 3042 struct vattr at; 3043 nfsfh_t nfh; 3044 fhandle_t *fhp; 3045 struct statfs statfs; 3046 u_quad_t frev, tval; 3047 3048 #ifndef nolint 3049 cache = 0; 3050 #endif 3051 fhp = &nfh.fh_generic; 3052 nfsm_srvmtofh(fhp); 3053 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3054 &rdonly, (nfsd->nd_flag & ND_KERBAUTH)); 3055 if (error) { 3056 nfsm_reply(NFSX_UNSIGNED); 3057 nfsm_srvpostop_attr(getret, &at); 3058 return (0); 3059 } 3060 sf = &statfs; 3061 error = VFS_STATFS(vp->v_mount, sf, procp); 3062 getret = VOP_GETATTR(vp, &at, cred, procp); 3063 vput(vp); 3064 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3)); 3065 if (v3) 3066 nfsm_srvpostop_attr(getret, &at); 3067 if (error) 3068 return (0); 3069 nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); 3070 if (v3) { 3071 tval = (u_quad_t)sf->f_blocks; 3072 tval *= (u_quad_t)sf->f_bsize; 3073 txdr_hyper(&tval, &sfp->sf_tbytes); 3074 tval = (u_quad_t)sf->f_bfree; 3075 tval *= (u_quad_t)sf->f_bsize; 3076 txdr_hyper(&tval, &sfp->sf_fbytes); 3077 tval = (u_quad_t)sf->f_bavail; 3078 tval *= (u_quad_t)sf->f_bsize; 3079 txdr_hyper(&tval, &sfp->sf_abytes); 3080 sfp->sf_tfiles.nfsuquad[0] = 0; 3081 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files); 3082 sfp->sf_ffiles.nfsuquad[0] = 0; 3083 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree); 3084 sfp->sf_afiles.nfsuquad[0] = 0; 3085 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree); 3086 sfp->sf_invarsec = 0; 3087 } else { 3088 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA); 3089 sfp->sf_bsize = txdr_unsigned(sf->f_bsize); 3090 sfp->sf_blocks = txdr_unsigned(sf->f_blocks); 3091 sfp->sf_bfree = txdr_unsigned(sf->f_bfree); 3092 sfp->sf_bavail = txdr_unsigned(sf->f_bavail); 3093 } 3094 nfsm_srvdone; 3095 } 3096 3097 /* 3098 * nfs fsinfo service 3099 */ 3100 int 3101 nfsrv_fsinfo(nfsd, slp, procp, mrq) 3102 struct nfsrv_descript *nfsd; 3103 struct nfssvc_sock *slp; 3104 struct proc *procp; 3105 struct mbuf **mrq; 3106 { 3107 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3108 struct mbuf *nam = nfsd->nd_nam; 3109 caddr_t dpos = nfsd->nd_dpos; 3110 struct ucred *cred = &nfsd->nd_cr; 3111 register u_int32_t *tl; 3112 register struct nfsv3_fsinfo *sip; 3113 register int32_t t1; 3114 caddr_t bpos; 3115 int error = 0, rdonly, cache, getret = 1, pref; 3116 char *cp2; 3117 struct mbuf *mb, *mb2, *mreq; 3118 struct vnode *vp; 3119 struct vattr at; 3120 nfsfh_t nfh; 3121 fhandle_t *fhp; 3122 u_quad_t frev; 3123 3124 #ifndef nolint 3125 cache = 0; 3126 #endif 3127 fhp = &nfh.fh_generic; 3128 nfsm_srvmtofh(fhp); 3129 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3130 &rdonly, (nfsd->nd_flag & ND_KERBAUTH)); 3131 if (error) { 3132 nfsm_reply(NFSX_UNSIGNED); 3133 nfsm_srvpostop_attr(getret, &at); 3134 return (0); 3135 } 3136 getret = VOP_GETATTR(vp, &at, cred, procp); 3137 vput(vp); 3138 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO); 3139 nfsm_srvpostop_attr(getret, &at); 3140 nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO); 3141 3142 /* 3143 * XXX 3144 * There should be file system VFS OP(s) to get this information. 3145 * For now, assume ufs. 3146 */ 3147 if (slp->ns_so->so_type == SOCK_DGRAM) 3148 pref = NFS_MAXDGRAMDATA; 3149 else 3150 pref = NFS_MAXDATA; 3151 sip->fs_rtmax = txdr_unsigned(NFS_MAXDATA); 3152 sip->fs_rtpref = txdr_unsigned(pref); 3153 sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE); 3154 sip->fs_wtmax = txdr_unsigned(NFS_MAXDATA); 3155 sip->fs_wtpref = txdr_unsigned(pref); 3156 sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE); 3157 sip->fs_dtpref = txdr_unsigned(pref); 3158 sip->fs_maxfilesize.nfsuquad[0] = 0xffffffff; 3159 sip->fs_maxfilesize.nfsuquad[1] = 0xffffffff; 3160 sip->fs_timedelta.nfsv3_sec = 0; 3161 sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1); 3162 sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK | 3163 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS | 3164 NFSV3FSINFO_CANSETTIME); 3165 nfsm_srvdone; 3166 } 3167 3168 /* 3169 * nfs pathconf service 3170 */ 3171 int 3172 nfsrv_pathconf(nfsd, slp, procp, mrq) 3173 struct nfsrv_descript *nfsd; 3174 struct nfssvc_sock *slp; 3175 struct proc *procp; 3176 struct mbuf **mrq; 3177 { 3178 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3179 struct mbuf *nam = nfsd->nd_nam; 3180 caddr_t dpos = nfsd->nd_dpos; 3181 struct ucred *cred = &nfsd->nd_cr; 3182 register u_int32_t *tl; 3183 register struct nfsv3_pathconf *pc; 3184 register int32_t t1; 3185 caddr_t bpos; 3186 int error = 0, rdonly, cache, getret = 1; 3187 register_t linkmax, namemax, chownres, notrunc; 3188 char *cp2; 3189 struct mbuf *mb, *mb2, *mreq; 3190 struct vnode *vp; 3191 struct vattr at; 3192 nfsfh_t nfh; 3193 fhandle_t *fhp; 3194 u_quad_t frev; 3195 3196 #ifndef nolint 3197 cache = 0; 3198 #endif 3199 fhp = &nfh.fh_generic; 3200 nfsm_srvmtofh(fhp); 3201 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3202 &rdonly, (nfsd->nd_flag & ND_KERBAUTH)); 3203 if (error) { 3204 nfsm_reply(NFSX_UNSIGNED); 3205 nfsm_srvpostop_attr(getret, &at); 3206 return (0); 3207 } 3208 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax); 3209 if (!error) 3210 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax); 3211 if (!error) 3212 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres); 3213 if (!error) 3214 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc); 3215 getret = VOP_GETATTR(vp, &at, cred, procp); 3216 vput(vp); 3217 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF); 3218 nfsm_srvpostop_attr(getret, &at); 3219 if (error) 3220 return (0); 3221 nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF); 3222 3223 pc->pc_linkmax = txdr_unsigned(linkmax); 3224 pc->pc_namemax = txdr_unsigned(namemax); 3225 pc->pc_notrunc = txdr_unsigned(notrunc); 3226 pc->pc_chownrestricted = txdr_unsigned(chownres); 3227 3228 /* 3229 * These should probably be supported by VOP_PATHCONF(), but 3230 * until msdosfs is exportable (why would you want to?), the 3231 * Unix defaults should be ok. 3232 */ 3233 pc->pc_caseinsensitive = nfs_false; 3234 pc->pc_casepreserving = nfs_true; 3235 nfsm_srvdone; 3236 } 3237 3238 /* 3239 * Null operation, used by clients to ping server 3240 */ 3241 /* ARGSUSED */ 3242 int 3243 nfsrv_null(nfsd, slp, procp, mrq) 3244 struct nfsrv_descript *nfsd; 3245 struct nfssvc_sock *slp; 3246 struct proc *procp; 3247 struct mbuf **mrq; 3248 { 3249 struct mbuf *mrep = nfsd->nd_mrep; 3250 caddr_t bpos; 3251 int error = NFSERR_RETVOID, cache = 0; 3252 struct mbuf *mb, *mreq; 3253 u_quad_t frev; 3254 3255 nfsm_reply(0); 3256 return (0); 3257 } 3258 3259 /* 3260 * No operation, used for obsolete procedures 3261 */ 3262 /* ARGSUSED */ 3263 int 3264 nfsrv_noop(nfsd, slp, procp, mrq) 3265 struct nfsrv_descript *nfsd; 3266 struct nfssvc_sock *slp; 3267 struct proc *procp; 3268 struct mbuf **mrq; 3269 { 3270 struct mbuf *mrep = nfsd->nd_mrep; 3271 caddr_t bpos; 3272 int error, cache = 0; 3273 struct mbuf *mb, *mreq; 3274 u_quad_t frev; 3275 3276 if (nfsd->nd_repstat) 3277 error = nfsd->nd_repstat; 3278 else 3279 error = EPROCUNAVAIL; 3280 nfsm_reply(0); 3281 return (0); 3282 } 3283 3284 /* 3285 * Perform access checking for vnodes obtained from file handles that would 3286 * refer to files already opened by a Unix client. You cannot just use 3287 * vn_writechk() and VOP_ACCESS() for two reasons. 3288 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case 3289 * 2 - The owner is to be given access irrespective of mode bits so that 3290 * processes that chmod after opening a file don't break. I don't like 3291 * this because it opens a security hole, but since the nfs server opens 3292 * a security hole the size of a barn door anyhow, what the heck. 3293 */ 3294 int 3295 nfsrv_access(vp, flags, cred, rdonly, p) 3296 register struct vnode *vp; 3297 int flags; 3298 register struct ucred *cred; 3299 int rdonly; 3300 struct proc *p; 3301 { 3302 struct vattr vattr; 3303 int error; 3304 if (flags & VWRITE) { 3305 /* Just vn_writechk() changed to check rdonly */ 3306 /* 3307 * Disallow write attempts on read-only file systems; 3308 * unless the file is a socket or a block or character 3309 * device resident on the file system. 3310 */ 3311 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3312 switch (vp->v_type) { 3313 case VREG: 3314 case VDIR: 3315 case VLNK: 3316 return (EROFS); 3317 default: 3318 break; 3319 } 3320 } 3321 /* 3322 * If there's shared text associated with 3323 * the inode, try to free it up once. If 3324 * we fail, we can't allow writing. 3325 */ 3326 if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp)) 3327 return (ETXTBSY); 3328 } 3329 error = VOP_GETATTR(vp, &vattr, cred, p); 3330 if (error) 3331 return (error); 3332 if ((error = VOP_ACCESS(vp, flags, cred, p)) != 0 && 3333 cred->cr_uid != vattr.va_uid) 3334 return (error); 3335 return (0); 3336 } 3337