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