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