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