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