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