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