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