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