1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: @(#)nfs_serv.c 7.40 (Berkeley) 5/15/91 37 * $Id: nfs_serv.c,v 1.14 1994/04/21 07:49:09 cgd Exp $ 38 */ 39 40 /* 41 * nfs version 2 server calls to vnode ops 42 * - these routines generally have 3 phases 43 * 1 - break down and validate rpc request in mbuf list 44 * 2 - do the vnode ops for the request 45 * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c) 46 * 3 - build the rpc reply in an mbuf list 47 * nb: 48 * - do not mix the phases, since the nfsm_?? macros can return failures 49 * on a bad rpc or similar and do not do any vrele() or vput()'s 50 * 51 * - the nfsm_reply() macro generates an nfs rpc reply with the nfs 52 * error number iff error != 0 whereas 53 * returning an error from the server function implies a fatal error 54 * such as a badly constructed rpc request that should be dropped without 55 * a reply. 56 */ 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/mbuf.h> 66 #include <sys/dir.h> 67 68 #include <ufs/quota.h> 69 #include <ufs/inode.h> /* for IFTOVT */ 70 71 #include <nfs/nfsv2.h> 72 #include <nfs/nfs.h> 73 #include <nfs/xdr_subs.h> 74 #include <nfs/nfsm_subs.h> 75 76 /* Defs */ 77 #define TRUE 1 78 #define FALSE 0 79 80 /* Global vars */ 81 extern u_long nfs_procids[NFS_NPROCS]; 82 extern u_long nfs_xdrneg1; 83 extern u_long nfs_false, nfs_true; 84 nfstype nfs_type[9]={ NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON, 85 NFCHR, NFNON }; 86 87 int nfsrv_null(), 88 nfsrv_getattr(), 89 nfsrv_setattr(), 90 nfsrv_lookup(), 91 nfsrv_readlink(), 92 nfsrv_read(), 93 nfsrv_write(), 94 nfsrv_create(), 95 nfsrv_remove(), 96 nfsrv_rename(), 97 nfsrv_link(), 98 nfsrv_symlink(), 99 nfsrv_mkdir(), 100 nfsrv_rmdir(), 101 nfsrv_readdir(), 102 nfsrv_statfs(), 103 nfsrv_noop(); 104 105 int (*nfsrv_procs[NFS_NPROCS])() = { 106 nfsrv_null, 107 nfsrv_getattr, 108 nfsrv_setattr, 109 nfsrv_noop, 110 nfsrv_lookup, 111 nfsrv_readlink, 112 nfsrv_read, 113 nfsrv_noop, 114 nfsrv_write, 115 nfsrv_create, 116 nfsrv_remove, 117 nfsrv_rename, 118 nfsrv_link, 119 nfsrv_symlink, 120 nfsrv_mkdir, 121 nfsrv_rmdir, 122 nfsrv_readdir, 123 nfsrv_statfs, 124 }; 125 /* 126 * nfs getattr service 127 */ 128 nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat, p) 129 struct mbuf **mrq; 130 struct mbuf *mrep, *md; 131 caddr_t dpos; 132 struct ucred *cred; 133 u_long xid; 134 int *repstat; 135 struct proc *p; 136 { 137 register struct nfsv2_fattr *fp; 138 struct vattr va; 139 register struct vattr *vap = &va; 140 struct vnode *vp; 141 nfsv2fh_t nfh; 142 fhandle_t *fhp; 143 register u_long *tl; 144 register long t1; 145 caddr_t bpos; 146 int error = 0; 147 char *cp2; 148 struct mbuf *mb, *mb2, *mreq; 149 150 fhp = &nfh.fh_generic; 151 nfsm_srvmtofh(fhp); 152 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 153 nfsm_reply(0); 154 error = VOP_GETATTR(vp, vap, cred, p); 155 vput(vp); 156 nfsm_reply(NFSX_FATTR); 157 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 158 nfsm_srvfillattr; 159 nfsm_srvdone; 160 } 161 162 /* 163 * nfs setattr service 164 */ 165 nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat, p) 166 struct mbuf **mrq; 167 struct mbuf *mrep, *md; 168 caddr_t dpos; 169 struct ucred *cred; 170 u_long xid; 171 int *repstat; 172 struct proc *p; 173 { 174 struct vattr va; 175 register struct vattr *vap = &va; 176 register struct nfsv2_sattr *sp; 177 register struct nfsv2_fattr *fp; 178 struct vnode *vp; 179 nfsv2fh_t nfh; 180 fhandle_t *fhp; 181 register u_long *tl; 182 register long t1; 183 caddr_t bpos; 184 int error = 0; 185 char *cp2; 186 struct mbuf *mb, *mb2, *mreq; 187 188 fhp = &nfh.fh_generic; 189 nfsm_srvmtofh(fhp); 190 nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR); 191 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 192 nfsm_reply(0); 193 if (error = nfsrv_access(vp, VWRITE, cred, p)) 194 goto out; 195 VATTR_NULL(vap); 196 /* 197 * Nah nah nah nah na nah 198 * There is a bug in the Sun client that puts 0xffff in the mode 199 * field of sattr when it should put in 0xffffffff. The u_short 200 * doesn't sign extend. 201 * --> check the low order 2 bytes for 0xffff 202 */ 203 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff) 204 vap->va_mode = nfstov_mode(sp->sa_mode); 205 if (sp->sa_uid != nfs_xdrneg1) 206 vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid); 207 if (sp->sa_gid != nfs_xdrneg1) 208 vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid); 209 if (sp->sa_size != nfs_xdrneg1) 210 vap->va_size = fxdr_unsigned(u_long, sp->sa_size); 211 /* 212 * The usec field of sa_atime is overloaded with the va_flags field 213 * for 4.4BSD clients. Hopefully other clients always set both the 214 * sec and usec fields to -1 when not setting the atime. 215 * 216 * jfw@ksr.com (6/2/93): Suns certainly don't set the usec field to 217 * -1 when *setting* the atime, resulting in 218 * va_flags acquiring random contents. 219 */ 220 #if 0 /* bad assumption, NFS is too fragile to extend. */ 221 if (sp->sa_atime.tv_sec != nfs_xdrneg1) { 222 vap->va_atime.tv_sec = fxdr_unsigned(long, sp->sa_atime.tv_sec); 223 vap->va_atime.tv_usec = 0; 224 } 225 if (sp->sa_atime.tv_usec != nfs_xdrneg1) 226 vap->va_flags = fxdr_unsigned(u_long, sp->sa_atime.tv_usec); 227 #else 228 if (sp->sa_atime.tv_sec != nfs_xdrneg1) 229 fxdr_time(&sp->sa_atime, &vap->va_atime); 230 #endif 231 if (sp->sa_mtime.tv_sec != nfs_xdrneg1) 232 fxdr_time(&sp->sa_mtime, &vap->va_mtime); 233 if (error = VOP_SETATTR(vp, vap, cred, p)) { 234 vput(vp); 235 nfsm_reply(0); 236 } 237 error = VOP_GETATTR(vp, vap, cred, p); 238 out: 239 vput(vp); 240 nfsm_reply(NFSX_FATTR); 241 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 242 nfsm_srvfillattr; 243 nfsm_srvdone; 244 } 245 246 /* 247 * nfs lookup rpc 248 */ 249 nfsrv_lookup(mrep, md, dpos, cred, xid, mrq, repstat, p) 250 struct mbuf **mrq; 251 struct mbuf *mrep, *md; 252 caddr_t dpos; 253 struct ucred *cred; 254 u_long xid; 255 int *repstat; 256 struct proc *p; 257 { 258 register struct nfsv2_fattr *fp; 259 struct nameidata nd; 260 struct vnode *vp; 261 nfsv2fh_t nfh; 262 fhandle_t *fhp; 263 register caddr_t cp; 264 register u_long *tl; 265 register long t1; 266 caddr_t bpos; 267 int error = 0; 268 char *cp2; 269 struct mbuf *mb, *mb2, *mreq; 270 long len; 271 struct vattr va, *vap = &va; 272 273 fhp = &nfh.fh_generic; 274 nfsm_srvmtofh(fhp); 275 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 276 nd.ni_cred = cred; 277 nd.ni_nameiop = LOOKUP | LOCKLEAF; 278 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) 279 nfsm_reply(0); 280 vp = nd.ni_vp; 281 bzero((caddr_t)fhp, sizeof(nfh)); 282 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 283 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { 284 vput(vp); 285 nfsm_reply(0); 286 } 287 error = VOP_GETATTR(vp, vap, cred, p); 288 vput(vp); 289 nfsm_reply(NFSX_FH+NFSX_FATTR); 290 nfsm_srvfhtom(fhp); 291 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 292 nfsm_srvfillattr; 293 nfsm_srvdone; 294 } 295 296 /* 297 * nfs readlink service 298 */ 299 nfsrv_readlink(mrep, md, dpos, cred, xid, mrq, repstat, p) 300 struct mbuf **mrq; 301 struct mbuf *mrep, *md; 302 caddr_t dpos; 303 struct ucred *cred; 304 u_long xid; 305 int *repstat; 306 struct proc *p; 307 { 308 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN]; 309 register struct iovec *ivp = iv; 310 register struct mbuf *mp; 311 register u_long *tl; 312 register long t1; 313 caddr_t bpos; 314 int error = 0; 315 char *cp2; 316 struct mbuf *mb, *mb2, *mp2, *mp3, *mreq; 317 struct vnode *vp; 318 nfsv2fh_t nfh; 319 fhandle_t *fhp; 320 struct uio io, *uiop = &io; 321 int i, tlen, len; 322 323 fhp = &nfh.fh_generic; 324 nfsm_srvmtofh(fhp); 325 len = 0; 326 i = 0; 327 while (len < NFS_MAXPATHLEN) { 328 MGET(mp, M_WAIT, MT_DATA); 329 MCLGET(mp, M_WAIT); 330 mp->m_len = NFSMSIZ(mp); 331 if (len == 0) 332 mp3 = mp2 = mp; 333 else { 334 mp2->m_next = mp; 335 mp2 = mp; 336 } 337 if ((len+mp->m_len) > NFS_MAXPATHLEN) { 338 mp->m_len = NFS_MAXPATHLEN-len; 339 len = NFS_MAXPATHLEN; 340 } else 341 len += mp->m_len; 342 ivp->iov_base = mtod(mp, caddr_t); 343 ivp->iov_len = mp->m_len; 344 i++; 345 ivp++; 346 } 347 uiop->uio_iov = iv; 348 uiop->uio_iovcnt = i; 349 uiop->uio_offset = 0; 350 uiop->uio_resid = len; 351 uiop->uio_rw = UIO_READ; 352 uiop->uio_segflg = UIO_SYSSPACE; 353 uiop->uio_procp = (struct proc *)0; 354 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) { 355 m_freem(mp3); 356 nfsm_reply(0); 357 } 358 if (vp->v_type != VLNK) { 359 error = EINVAL; 360 goto out; 361 } 362 error = VOP_READLINK(vp, uiop, cred); 363 out: 364 vput(vp); 365 if (error) 366 m_freem(mp3); 367 nfsm_reply(NFSX_UNSIGNED); 368 if (uiop->uio_resid > 0) { 369 len -= uiop->uio_resid; 370 tlen = nfsm_rndup(len); 371 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len); 372 } 373 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 374 *tl = txdr_unsigned(len); 375 mb->m_next = mp3; 376 nfsm_srvdone; 377 } 378 379 /* 380 * nfs read service 381 */ 382 nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat, p) 383 struct mbuf **mrq; 384 struct mbuf *mrep, *md; 385 caddr_t dpos; 386 struct ucred *cred; 387 u_long xid; 388 int *repstat; 389 struct proc *p; 390 { 391 register struct iovec *iv; 392 struct iovec *iv2; 393 register struct mbuf *m; 394 register struct nfsv2_fattr *fp; 395 register u_long *tl; 396 register long t1; 397 caddr_t bpos; 398 int error = 0; 399 char *cp2; 400 struct mbuf *mb, *mb2, *mreq; 401 struct mbuf *m2, *m3; 402 struct vnode *vp; 403 nfsv2fh_t nfh; 404 fhandle_t *fhp; 405 struct uio io, *uiop = &io; 406 struct vattr va, *vap = &va; 407 int i, cnt, len, left, siz, tlen; 408 off_t off; 409 410 fhp = &nfh.fh_generic; 411 nfsm_srvmtofh(fhp); 412 nfsm_disect(tl, u_long *, NFSX_UNSIGNED); 413 off = fxdr_unsigned(off_t, *tl); 414 nfsm_srvstrsiz(cnt, NFS_MAXDATA); 415 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 416 nfsm_reply(0); 417 if ((error = nfsrv_access(vp, VREAD, cred, p)) && 418 (error = nfsrv_access(vp, VEXEC, cred, p))) { 419 vput(vp); 420 nfsm_reply(0); 421 } 422 len = left = cnt; 423 /* 424 * Generate the mbuf list with the uio_iov ref. to it. 425 */ 426 i = 0; 427 m3 = (struct mbuf *)0; 428 #ifdef lint 429 m2 = (struct mbuf *)0; 430 #endif /* lint */ 431 MALLOC(iv, struct iovec *, 432 ((NFS_MAXDATA+MLEN-1)/MLEN) * sizeof (struct iovec), M_TEMP, 433 M_WAITOK); 434 iv2 = iv; 435 while (left > 0) { 436 MGET(m, M_WAIT, MT_DATA); 437 if (left > MINCLSIZE) 438 MCLGET(m, M_WAIT); 439 m->m_len = 0; 440 siz = min(M_TRAILINGSPACE(m), left); 441 m->m_len = siz; 442 iv->iov_base = mtod(m, caddr_t); 443 iv->iov_len = siz; 444 iv++; 445 i++; 446 left -= siz; 447 if (m3) { 448 m2->m_next = m; 449 m2 = m; 450 } else 451 m3 = m2 = m; 452 } 453 uiop->uio_iov = iv2; 454 uiop->uio_iovcnt = i; 455 uiop->uio_offset = off; 456 uiop->uio_resid = cnt; 457 uiop->uio_rw = UIO_READ; 458 uiop->uio_segflg = UIO_SYSSPACE; 459 uiop->uio_procp = (struct proc *)0; 460 error = VOP_READ(vp, uiop, IO_NODELOCKED, cred); 461 off = uiop->uio_offset; 462 FREE((caddr_t)iv2, M_TEMP); 463 if (error) { 464 m_freem(m3); 465 vput(vp); 466 nfsm_reply(0); 467 } 468 if (error = VOP_GETATTR(vp, vap, cred, p)) 469 m_freem(m3); 470 vput(vp); 471 nfsm_reply(NFSX_FATTR+NFSX_UNSIGNED); 472 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 473 nfsm_srvfillattr; 474 len -= uiop->uio_resid; 475 if (len > 0) { 476 tlen = nfsm_rndup(len); 477 if (cnt != tlen || tlen != len) 478 nfsm_adj(m3, cnt-tlen, tlen-len); 479 } else { 480 m_freem(m3); 481 m3 = (struct mbuf *)0; 482 } 483 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 484 *tl = txdr_unsigned(len); 485 mb->m_next = m3; 486 nfsm_srvdone; 487 } 488 489 /* 490 * nfs write service 491 */ 492 nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat, p) 493 struct mbuf *mrep, *md, **mrq; 494 caddr_t dpos; 495 struct ucred *cred; 496 u_long xid; 497 int *repstat; 498 struct proc *p; 499 { 500 register struct iovec *ivp; 501 register struct mbuf *mp; 502 register struct nfsv2_fattr *fp; 503 struct iovec iv[NFS_MAXIOVEC]; 504 struct vattr va; 505 register struct vattr *vap = &va; 506 register u_long *tl; 507 register long t1; 508 caddr_t bpos; 509 int error = 0; 510 char *cp2; 511 struct mbuf *mb, *mb2, *mreq; 512 struct vnode *vp; 513 nfsv2fh_t nfh; 514 fhandle_t *fhp; 515 struct uio io, *uiop = &io; 516 off_t off; 517 long siz, len, xfer; 518 519 fhp = &nfh.fh_generic; 520 nfsm_srvmtofh(fhp); 521 nfsm_disect(tl, u_long *, 4*NFSX_UNSIGNED); 522 off = fxdr_unsigned(off_t, *++tl); 523 tl += 2; 524 len = fxdr_unsigned(long, *tl); 525 if (len > NFS_MAXDATA || len <= 0) { 526 error = EBADRPC; 527 nfsm_reply(0); 528 } 529 if (dpos == (mtod(md, caddr_t)+md->m_len)) { 530 mp = md->m_next; 531 if (mp == NULL) { 532 error = EBADRPC; 533 nfsm_reply(0); 534 } 535 } else { 536 mp = md; 537 siz = dpos-mtod(mp, caddr_t); 538 mp->m_len -= siz; 539 NFSMADV(mp, siz); 540 } 541 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 542 nfsm_reply(0); 543 if (error = nfsrv_access(vp, VWRITE, cred, p)) { 544 vput(vp); 545 nfsm_reply(0); 546 } 547 uiop->uio_resid = 0; 548 uiop->uio_rw = UIO_WRITE; 549 uiop->uio_segflg = UIO_SYSSPACE; 550 uiop->uio_procp = (struct proc *)0; 551 /* 552 * Do up to NFS_MAXIOVEC mbufs of write each iteration of the 553 * loop until done. 554 */ 555 while (len > 0 && uiop->uio_resid == 0) { 556 ivp = iv; 557 siz = 0; 558 uiop->uio_iov = ivp; 559 uiop->uio_iovcnt = 0; 560 uiop->uio_offset = off; 561 while (len > 0 && uiop->uio_iovcnt < NFS_MAXIOVEC && mp != NULL) { 562 ivp->iov_base = mtod(mp, caddr_t); 563 if (len < mp->m_len) 564 ivp->iov_len = xfer = len; 565 else 566 ivp->iov_len = xfer = mp->m_len; 567 #ifdef notdef 568 /* Not Yet .. */ 569 if (M_HASCL(mp) && (((u_long)ivp->iov_base) & CLOFSET) == 0) 570 ivp->iov_op = NULL; /* what should it be ?? */ 571 else 572 ivp->iov_op = NULL; 573 #endif 574 uiop->uio_iovcnt++; 575 ivp++; 576 len -= xfer; 577 siz += xfer; 578 mp = mp->m_next; 579 } 580 if (len > 0 && mp == NULL) { 581 error = EBADRPC; 582 vput(vp); 583 nfsm_reply(0); 584 } 585 uiop->uio_resid = siz; 586 if (error = VOP_WRITE(vp, uiop, IO_SYNC | IO_NODELOCKED, 587 cred)) { 588 vput(vp); 589 nfsm_reply(0); 590 } 591 off = uiop->uio_offset; 592 } 593 error = VOP_GETATTR(vp, vap, cred, p); 594 vput(vp); 595 nfsm_reply(NFSX_FATTR); 596 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 597 nfsm_srvfillattr; 598 nfsm_srvdone; 599 } 600 601 /* 602 * nfs create service 603 * if it already exists, just set length 604 * do NOT truncate unconditionally ! 605 */ 606 nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat, p) 607 struct mbuf *mrep, *md, **mrq; 608 caddr_t dpos; 609 struct ucred *cred; 610 u_long xid; 611 int *repstat; 612 struct proc *p; 613 { 614 register struct nfsv2_fattr *fp; 615 struct vattr va; 616 register struct vattr *vap = &va; 617 struct nameidata nd; 618 register caddr_t cp; 619 register u_long *tl; 620 register long t1; 621 caddr_t bpos; 622 long rdev; 623 int error = 0; 624 char *cp2; 625 struct mbuf *mb, *mb2, *mreq; 626 struct vnode *vp; 627 nfsv2fh_t nfh; 628 fhandle_t *fhp; 629 long len; 630 631 nd.ni_nameiop = 0; 632 fhp = &nfh.fh_generic; 633 nfsm_srvmtofh(fhp); 634 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 635 nd.ni_cred = cred; 636 nd.ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF | SAVESTART; 637 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) 638 nfsm_reply(0); 639 VATTR_NULL(vap); 640 nfsm_disect(tl, u_long *, NFSX_SATTR); 641 /* 642 * If it doesn't exist, create it 643 * otherwise just set length from attributes 644 * should I set the mode too ?? 645 */ 646 if (nd.ni_vp == NULL) { 647 vap->va_type = IFTOVT(fxdr_unsigned(u_long, *tl)); 648 if (vap->va_type == VNON) 649 vap->va_type = VREG; 650 vap->va_mode = nfstov_mode(*tl); 651 rdev = fxdr_unsigned(long, *(tl+3)); 652 if (vap->va_type == VREG || vap->va_type == VSOCK) { 653 vrele(nd.ni_startdir); 654 if (error = VOP_CREATE(&nd, vap, p)) 655 nfsm_reply(0); 656 FREE(nd.ni_pnbuf, M_NAMEI); 657 } else if (vap->va_type == VCHR || vap->va_type == VBLK || 658 vap->va_type == VFIFO) { 659 if (vap->va_type == VCHR && rdev == 0xffffffff) 660 vap->va_type = VFIFO; 661 if (vap->va_type == VFIFO) { 662 #ifndef FIFO 663 VOP_ABORTOP(&nd); 664 vput(nd.ni_dvp); 665 error = ENXIO; 666 goto out; 667 #endif /* FIFO */ 668 } else if (error = suser(cred, (u_short *)0)) { 669 VOP_ABORTOP(&nd); 670 vput(nd.ni_dvp); 671 goto out; 672 } else 673 vap->va_rdev = (dev_t)rdev; 674 if (error = VOP_MKNOD(&nd, vap, cred, p)) { 675 vrele(nd.ni_startdir); 676 nfsm_reply(0); 677 } 678 nd.ni_nameiop &= ~(OPMASK | LOCKPARENT | SAVESTART); 679 nd.ni_nameiop |= LOOKUP; 680 if (error = lookup(&nd, p)) { 681 free(nd.ni_pnbuf, M_NAMEI); 682 nfsm_reply(0); 683 } 684 FREE(nd.ni_pnbuf, M_NAMEI); 685 if (nd.ni_more) { 686 vrele(nd.ni_dvp); 687 vput(nd.ni_vp); 688 VOP_ABORTOP(&nd); 689 error = EINVAL; 690 nfsm_reply(0); 691 } 692 } else { 693 VOP_ABORTOP(&nd); 694 vput(nd.ni_dvp); 695 error = ENXIO; 696 goto out; 697 } 698 vp = nd.ni_vp; 699 } else { 700 vrele(nd.ni_startdir); 701 free(nd.ni_pnbuf, M_NAMEI); 702 vp = nd.ni_vp; 703 if (nd.ni_dvp == vp) 704 vrele(nd.ni_dvp); 705 else 706 vput(nd.ni_dvp); 707 VOP_ABORTOP(&nd); 708 vap->va_size = fxdr_unsigned(long, *(tl+3)); 709 if (vap->va_size != -1 && 710 (error = VOP_SETATTR(vp, vap, cred, p))) { 711 vput(vp); 712 nfsm_reply(0); 713 } 714 } 715 bzero((caddr_t)fhp, sizeof(nfh)); 716 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 717 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { 718 vput(vp); 719 nfsm_reply(0); 720 } 721 error = VOP_GETATTR(vp, vap, cred, p); 722 vput(vp); 723 nfsm_reply(NFSX_FH+NFSX_FATTR); 724 nfsm_srvfhtom(fhp); 725 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 726 nfsm_srvfillattr; 727 return (error); 728 nfsmout: 729 if (nd.ni_nameiop) 730 vrele(nd.ni_startdir); 731 VOP_ABORTOP(&nd); 732 if (nd.ni_dvp == nd.ni_vp) 733 vrele(nd.ni_dvp); 734 else 735 vput(nd.ni_dvp); 736 if (nd.ni_vp) 737 vput(nd.ni_vp); 738 return (error); 739 740 out: 741 vrele(nd.ni_startdir); 742 free(nd.ni_pnbuf, M_NAMEI); 743 nfsm_reply(0); 744 } 745 746 /* 747 * nfs remove service 748 */ 749 nfsrv_remove(mrep, md, dpos, cred, xid, mrq, repstat, p) 750 struct mbuf *mrep, *md, **mrq; 751 caddr_t dpos; 752 struct ucred *cred; 753 u_long xid; 754 int *repstat; 755 struct proc *p; 756 { 757 struct nameidata nd; 758 register u_long *tl; 759 register long t1; 760 caddr_t bpos; 761 int error = 0; 762 char *cp2; 763 struct mbuf *mb, *mreq; 764 struct vnode *vp; 765 nfsv2fh_t nfh; 766 fhandle_t *fhp; 767 long len; 768 769 fhp = &nfh.fh_generic; 770 nfsm_srvmtofh(fhp); 771 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 772 nd.ni_cred = cred; 773 nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 774 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) 775 nfsm_reply(0); 776 vp = nd.ni_vp; 777 if (vp->v_type == VDIR && 778 (error = suser(cred, (u_short *)0))) 779 goto out; 780 /* 781 * The root of a mounted filesystem cannot be deleted. 782 */ 783 if (vp->v_flag & VROOT) { 784 error = EBUSY; 785 goto out; 786 } 787 if (vp->v_flag & VTEXT) 788 (void) vnode_pager_uncache(vp); 789 out: 790 if (!error) { 791 error = VOP_REMOVE(&nd, p); 792 } else { 793 VOP_ABORTOP(&nd); 794 if (nd.ni_dvp == vp) 795 vrele(nd.ni_dvp); 796 else 797 vput(nd.ni_dvp); 798 vput(vp); 799 } 800 nfsm_reply(0); 801 nfsm_srvdone; 802 } 803 804 /* 805 * nfs rename service 806 */ 807 nfsrv_rename(mrep, md, dpos, cred, xid, mrq, repstat, p) 808 struct mbuf *mrep, *md, **mrq; 809 caddr_t dpos; 810 struct ucred *cred; 811 u_long xid; 812 int *repstat; 813 struct proc *p; 814 { 815 register u_long *tl; 816 register long t1; 817 caddr_t bpos; 818 int error = 0; 819 char *cp2; 820 struct mbuf *mb, *mreq; 821 struct nameidata fromnd, tond; 822 struct vnode *fvp, *tvp, *tdvp; 823 nfsv2fh_t fnfh, tnfh; 824 fhandle_t *ffhp, *tfhp; 825 long len, len2; 826 int rootflg = 0; 827 828 ffhp = &fnfh.fh_generic; 829 tfhp = &tnfh.fh_generic; 830 fromnd.ni_nameiop = 0; 831 tond.ni_nameiop = 0; 832 nfsm_srvmtofh(ffhp); 833 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 834 /* 835 * Remember if we are root so that we can reset cr_uid before 836 * the second nfs_namei() call 837 */ 838 if (cred->cr_uid == 0) 839 rootflg++; 840 fromnd.ni_cred = cred; 841 fromnd.ni_nameiop = DELETE | WANTPARENT | SAVESTART; 842 if (error = nfs_namei(&fromnd, ffhp, len, &md, &dpos, p)) 843 nfsm_reply(0); 844 fvp = fromnd.ni_vp; 845 nfsm_srvmtofh(tfhp); 846 nfsm_strsiz(len2, NFS_MAXNAMLEN); 847 if (rootflg) 848 cred->cr_uid = 0; 849 tond.ni_cred = cred; 850 tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE 851 | SAVESTART; 852 if (error = nfs_namei(&tond, tfhp, len2, &md, &dpos, p)) { 853 VOP_ABORTOP(&fromnd); 854 vrele(fromnd.ni_dvp); 855 vrele(fvp); 856 goto out1; 857 } 858 tdvp = tond.ni_dvp; 859 tvp = tond.ni_vp; 860 if (tvp != NULL) { 861 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 862 error = EISDIR; 863 goto out; 864 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 865 error = ENOTDIR; 866 goto out; 867 } 868 } 869 if (fvp->v_mount != tdvp->v_mount) { 870 error = EXDEV; 871 goto out; 872 } 873 if (fvp == tdvp) 874 error = EINVAL; 875 /* 876 * If source is the same as the destination (that is the 877 * same vnode with the same name in the same directory), 878 * then there is nothing to do. 879 */ 880 if (fvp == tvp && fromnd.ni_dvp == tdvp && 881 fromnd.ni_namelen == tond.ni_namelen && 882 !bcmp(fromnd.ni_ptr, tond.ni_ptr, fromnd.ni_namelen)) 883 error = -1; 884 out: 885 if (!error) { 886 error = VOP_RENAME(&fromnd, &tond, p); 887 } else { 888 VOP_ABORTOP(&tond); 889 if (tdvp == tvp) 890 vrele(tdvp); 891 else 892 vput(tdvp); 893 if (tvp) 894 vput(tvp); 895 VOP_ABORTOP(&fromnd); 896 vrele(fromnd.ni_dvp); 897 vrele(fvp); 898 } 899 vrele(tond.ni_startdir); 900 FREE(tond.ni_pnbuf, M_NAMEI); 901 out1: 902 vrele(fromnd.ni_startdir); 903 FREE(fromnd.ni_pnbuf, M_NAMEI); 904 nfsm_reply(0); 905 return (error); 906 907 nfsmout: 908 if (tond.ni_nameiop) { 909 vrele(tond.ni_startdir); 910 FREE(tond.ni_pnbuf, M_NAMEI); 911 } 912 if (fromnd.ni_nameiop) { 913 vrele(fromnd.ni_startdir); 914 FREE(fromnd.ni_pnbuf, M_NAMEI); 915 VOP_ABORTOP(&fromnd); 916 vrele(fromnd.ni_dvp); 917 vrele(fvp); 918 } 919 return (error); 920 } 921 922 /* 923 * nfs link service 924 */ 925 nfsrv_link(mrep, md, dpos, cred, xid, mrq, repstat, p) 926 struct mbuf *mrep, *md, **mrq; 927 caddr_t dpos; 928 struct ucred *cred; 929 u_long xid; 930 int *repstat; 931 struct proc *p; 932 { 933 struct nameidata nd; 934 register u_long *tl; 935 register long t1; 936 caddr_t bpos; 937 int error = 0; 938 char *cp2; 939 struct mbuf *mb, *mreq; 940 struct vnode *vp, *xp; 941 nfsv2fh_t nfh, dnfh; 942 fhandle_t *fhp, *dfhp; 943 long len; 944 945 fhp = &nfh.fh_generic; 946 dfhp = &dnfh.fh_generic; 947 nfsm_srvmtofh(fhp); 948 nfsm_srvmtofh(dfhp); 949 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 950 if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred)) 951 nfsm_reply(0); 952 if (vp->v_type == VDIR && (error = suser(cred, NULL))) 953 goto out1; 954 nd.ni_cred = cred; 955 nd.ni_nameiop = CREATE | LOCKPARENT; 956 if (error = nfs_namei(&nd, dfhp, len, &md, &dpos, p)) 957 goto out1; 958 xp = nd.ni_vp; 959 if (xp != NULL) { 960 error = EEXIST; 961 goto out; 962 } 963 xp = nd.ni_dvp; 964 if (vp->v_mount != xp->v_mount) 965 error = EXDEV; 966 out: 967 if (!error) { 968 error = VOP_LINK(vp, &nd, p); 969 } else { 970 VOP_ABORTOP(&nd); 971 if (nd.ni_dvp == nd.ni_vp) 972 vrele(nd.ni_dvp); 973 else 974 vput(nd.ni_dvp); 975 if (nd.ni_vp) 976 vrele(nd.ni_vp); 977 } 978 out1: 979 vrele(vp); 980 nfsm_reply(0); 981 nfsm_srvdone; 982 } 983 984 /* 985 * nfs symbolic link service 986 */ 987 nfsrv_symlink(mrep, md, dpos, cred, xid, mrq, repstat, p) 988 struct mbuf *mrep, *md, **mrq; 989 caddr_t dpos; 990 struct ucred *cred; 991 u_long xid; 992 int *repstat; 993 struct proc *p; 994 { 995 struct vattr va; 996 struct nameidata nd; 997 register struct vattr *vap = &va; 998 register u_long *tl; 999 register long t1; 1000 struct nfsv2_sattr *sp; 1001 caddr_t bpos; 1002 struct uio io; 1003 struct iovec iv; 1004 int error = 0; 1005 char *pathcp, *cp2; 1006 struct mbuf *mb, *mreq; 1007 nfsv2fh_t nfh; 1008 fhandle_t *fhp; 1009 long len, len2; 1010 1011 pathcp = (char *)0; 1012 fhp = &nfh.fh_generic; 1013 nfsm_srvmtofh(fhp); 1014 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 1015 nd.ni_cred = cred; 1016 nd.ni_nameiop = CREATE | LOCKPARENT; 1017 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) 1018 goto out; 1019 nfsm_strsiz(len2, NFS_MAXPATHLEN); 1020 MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK); 1021 iv.iov_base = pathcp; 1022 iv.iov_len = len2; 1023 io.uio_resid = len2; 1024 io.uio_offset = 0; 1025 io.uio_iov = &iv; 1026 io.uio_iovcnt = 1; 1027 io.uio_segflg = UIO_SYSSPACE; 1028 io.uio_rw = UIO_READ; 1029 io.uio_procp = (struct proc *)0; 1030 nfsm_mtouio(&io, len2); 1031 nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR); 1032 *(pathcp + len2) = '\0'; 1033 if (nd.ni_vp) { 1034 VOP_ABORTOP(&nd); 1035 if (nd.ni_dvp == nd.ni_vp) 1036 vrele(nd.ni_dvp); 1037 else 1038 vput(nd.ni_dvp); 1039 vrele(nd.ni_vp); 1040 error = EEXIST; 1041 goto out; 1042 } 1043 VATTR_NULL(vap); 1044 vap->va_mode = fxdr_unsigned(u_short, sp->sa_mode); 1045 error = VOP_SYMLINK(&nd, vap, pathcp, p); 1046 out: 1047 if (pathcp) 1048 FREE(pathcp, M_TEMP); 1049 nfsm_reply(0); 1050 return (error); 1051 nfsmout: 1052 VOP_ABORTOP(&nd); 1053 if (nd.ni_dvp == nd.ni_vp) 1054 vrele(nd.ni_dvp); 1055 else 1056 vput(nd.ni_dvp); 1057 if (nd.ni_vp) 1058 vrele(nd.ni_vp); 1059 if (pathcp) 1060 FREE(pathcp, M_TEMP); 1061 return (error); 1062 } 1063 1064 /* 1065 * nfs mkdir service 1066 */ 1067 nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq, repstat, p) 1068 struct mbuf *mrep, *md, **mrq; 1069 caddr_t dpos; 1070 struct ucred *cred; 1071 u_long xid; 1072 int *repstat; 1073 struct proc *p; 1074 { 1075 struct vattr va; 1076 register struct vattr *vap = &va; 1077 register struct nfsv2_fattr *fp; 1078 struct nameidata nd; 1079 register caddr_t cp; 1080 register u_long *tl; 1081 register long t1; 1082 caddr_t bpos; 1083 int error = 0; 1084 char *cp2; 1085 struct mbuf *mb, *mb2, *mreq; 1086 struct vnode *vp; 1087 nfsv2fh_t nfh; 1088 fhandle_t *fhp; 1089 long len; 1090 1091 fhp = &nfh.fh_generic; 1092 nfsm_srvmtofh(fhp); 1093 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 1094 nd.ni_cred = cred; 1095 nd.ni_nameiop = CREATE | LOCKPARENT; 1096 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) 1097 nfsm_reply(0); 1098 nfsm_disect(tl, u_long *, NFSX_UNSIGNED); 1099 VATTR_NULL(vap); 1100 vap->va_type = VDIR; 1101 vap->va_mode = nfstov_mode(*tl++); 1102 vp = nd.ni_vp; 1103 if (vp != NULL) { 1104 VOP_ABORTOP(&nd); 1105 if (nd.ni_dvp == vp) 1106 vrele(nd.ni_dvp); 1107 else 1108 vput(nd.ni_dvp); 1109 vrele(vp); 1110 error = EEXIST; 1111 nfsm_reply(0); 1112 } 1113 if (error = VOP_MKDIR(&nd, vap, p)) 1114 nfsm_reply(0); 1115 vp = nd.ni_vp; 1116 bzero((caddr_t)fhp, sizeof(nfh)); 1117 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 1118 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { 1119 vput(vp); 1120 nfsm_reply(0); 1121 } 1122 error = VOP_GETATTR(vp, vap, cred, p); 1123 vput(vp); 1124 nfsm_reply(NFSX_FH+NFSX_FATTR); 1125 nfsm_srvfhtom(fhp); 1126 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); 1127 nfsm_srvfillattr; 1128 return (error); 1129 nfsmout: 1130 VOP_ABORTOP(&nd); 1131 if (nd.ni_dvp == nd.ni_vp) 1132 vrele(nd.ni_dvp); 1133 else 1134 vput(nd.ni_dvp); 1135 if (nd.ni_vp) 1136 vrele(nd.ni_vp); 1137 return (error); 1138 } 1139 1140 /* 1141 * nfs rmdir service 1142 */ 1143 nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq, repstat, p) 1144 struct mbuf *mrep, *md, **mrq; 1145 caddr_t dpos; 1146 struct ucred *cred; 1147 u_long xid; 1148 int *repstat; 1149 struct proc *p; 1150 { 1151 register u_long *tl; 1152 register long t1; 1153 caddr_t bpos; 1154 int error = 0; 1155 char *cp2; 1156 struct mbuf *mb, *mreq; 1157 struct vnode *vp; 1158 nfsv2fh_t nfh; 1159 fhandle_t *fhp; 1160 long len; 1161 struct nameidata nd; 1162 1163 fhp = &nfh.fh_generic; 1164 nfsm_srvmtofh(fhp); 1165 nfsm_srvstrsiz(len, NFS_MAXNAMLEN); 1166 nd.ni_cred = cred; 1167 nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; 1168 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) 1169 nfsm_reply(0); 1170 vp = nd.ni_vp; 1171 if (vp->v_type != VDIR) { 1172 error = ENOTDIR; 1173 goto out; 1174 } 1175 /* 1176 * No rmdir "." please. 1177 */ 1178 if (nd.ni_dvp == vp) { 1179 error = EINVAL; 1180 goto out; 1181 } 1182 /* 1183 * The root of a mounted filesystem cannot be deleted. 1184 */ 1185 if (vp->v_flag & VROOT) 1186 error = EBUSY; 1187 out: 1188 if (!error) { 1189 error = VOP_RMDIR(&nd, p); 1190 } else { 1191 VOP_ABORTOP(&nd); 1192 if (nd.ni_dvp == nd.ni_vp) 1193 vrele(nd.ni_dvp); 1194 else 1195 vput(nd.ni_dvp); 1196 vput(vp); 1197 } 1198 nfsm_reply(0); 1199 nfsm_srvdone; 1200 } 1201 1202 /* 1203 * nfs readdir service 1204 * - mallocs what it thinks is enough to read 1205 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR 1206 * - calls VOP_READDIR() 1207 * - loops around building the reply 1208 * if the output generated exceeds count break out of loop 1209 * The nfsm_clget macro is used here so that the reply will be packed 1210 * tightly in mbuf clusters. 1211 * - it only knows that it has encountered eof when the VOP_READDIR() 1212 * reads nothing 1213 * - as such one readdir rpc will return eof false although you are there 1214 * and then the next will return eof 1215 * - it trims out records with d_fileno == 0 1216 * this doesn't matter for Unix clients, but they might confuse clients 1217 * for other os'. 1218 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less 1219 * than requested, but this may not apply to all filesystems. For 1220 * example, client NFS does not { although it is never remote mounted 1221 * anyhow } 1222 * PS: The NFS protocol spec. does not clarify what the "count" byte 1223 * argument is a count of.. just name strings and file id's or the 1224 * entire reply rpc or ... 1225 * I tried just file name and id sizes and it confused the Sun client, 1226 * so I am using the full rpc size now. The "paranoia.." comment refers 1227 * to including the status longwords that are not a part of the dir. 1228 * "entry" structures, but are in the rpc. 1229 */ 1230 nfsrv_readdir(mrep, md, dpos, cred, xid, mrq, repstat, p) 1231 struct mbuf **mrq; 1232 struct mbuf *mrep, *md; 1233 caddr_t dpos; 1234 struct ucred *cred; 1235 u_long xid; 1236 int *repstat; 1237 struct proc *p; 1238 { 1239 register char *bp, *be; 1240 register struct mbuf *mp; 1241 register struct dirent *dp; 1242 register caddr_t cp; 1243 register u_long *tl; 1244 register long t1; 1245 caddr_t bpos; 1246 int error = 0; 1247 char *cp2; 1248 struct mbuf *mb, *mb2, *mreq; 1249 char *cpos, *cend; 1250 int len, nlen, rem, xfer, tsiz, i; 1251 struct vnode *vp; 1252 struct mbuf *mp2, *mp3; 1253 nfsv2fh_t nfh; 1254 fhandle_t *fhp; 1255 struct uio io; 1256 struct iovec iv; 1257 int siz, cnt, fullsiz, eofflag; 1258 char *rbuf; 1259 off_t off; 1260 u_int *cookiebuf, *cookie; 1261 int ncookies; 1262 1263 fhp = &nfh.fh_generic; 1264 nfsm_srvmtofh(fhp); 1265 nfsm_disect(tl, u_long *, 2*NFSX_UNSIGNED); 1266 off = fxdr_unsigned(off_t, *tl++); 1267 cnt = fxdr_unsigned(int, *tl); 1268 siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1)); 1269 if (cnt > NFS_MAXREADDIR) 1270 siz = NFS_MAXREADDIR; 1271 fullsiz = siz; 1272 ncookies = siz / 16; /* guess on the number of cookies needed */ 1273 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 1274 nfsm_reply(0); 1275 if (error = nfsrv_access(vp, VEXEC, cred, p)) { 1276 vput(vp); 1277 nfsm_reply(0); 1278 } 1279 VOP_UNLOCK(vp); 1280 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 1281 MALLOC(cookiebuf, u_int *, ncookies * sizeof(u_int), M_TEMP, M_WAITOK); 1282 again: 1283 iv.iov_base = rbuf; 1284 iv.iov_len = fullsiz; 1285 io.uio_iov = &iv; 1286 io.uio_iovcnt = 1; 1287 io.uio_offset = off; 1288 io.uio_resid = fullsiz; 1289 io.uio_segflg = UIO_SYSSPACE; 1290 io.uio_rw = UIO_READ; 1291 io.uio_procp = (struct proc *)0; 1292 1293 error = VOP_READDIR(vp, &io, cred, &eofflag, cookiebuf, ncookies); 1294 cookie = cookiebuf; 1295 off = io.uio_offset; 1296 if (error) { 1297 vrele(vp); 1298 free((caddr_t)rbuf, M_TEMP); 1299 free(cookiebuf,M_TEMP); 1300 nfsm_reply(0); 1301 } 1302 if (io.uio_resid) { 1303 siz -= io.uio_resid; 1304 1305 /* 1306 * If nothing read, return eof 1307 * rpc reply 1308 */ 1309 if (siz == 0) { 1310 vrele(vp); 1311 nfsm_reply(2*NFSX_UNSIGNED); 1312 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED); 1313 *tl++ = nfs_false; 1314 *tl = nfs_true; 1315 FREE((caddr_t)cookiebuf, M_TEMP); 1316 FREE((caddr_t)rbuf, M_TEMP); 1317 return (0); 1318 } 1319 } 1320 1321 /* 1322 * Check for degenerate cases of nothing useful read. 1323 * If so go try again 1324 */ 1325 cpos = rbuf; 1326 cend = rbuf + siz; 1327 while (cpos < cend) { 1328 dp = (struct dirent *)cpos; 1329 if (cpos < rbuf || dp->d_fileno == 0) { 1330 cpos += dp->d_reclen; 1331 cookie++; 1332 } else 1333 break; 1334 } 1335 if (cpos >= cend) { 1336 siz = fullsiz; 1337 goto again; 1338 } 1339 1340 vrele(vp); 1341 len = 3*NFSX_UNSIGNED; /* paranoia, probably can be 0 */ 1342 bp = be = (caddr_t)0; 1343 mp3 = (struct mbuf *)0; 1344 nfsm_reply(siz); 1345 1346 /* Loop through the records and build reply */ 1347 while (cpos < cend) { 1348 if (dp->d_fileno != 0) { 1349 nlen = dp->d_namlen; 1350 rem = nfsm_rndup(nlen)-nlen; 1351 1352 /* 1353 * As noted above, the NFS spec. is not clear about what 1354 * should be included in "count" as totalled up here in 1355 * "len". 1356 */ 1357 len += (4*NFSX_UNSIGNED+nlen+rem); 1358 if (len > cnt) { 1359 eofflag = 0; 1360 break; 1361 } 1362 1363 /* Build the directory record xdr from the dirent entry */ 1364 nfsm_clget; 1365 *tl = nfs_true; 1366 bp += NFSX_UNSIGNED; 1367 nfsm_clget; 1368 *tl = txdr_unsigned(dp->d_fileno); 1369 bp += NFSX_UNSIGNED; 1370 nfsm_clget; 1371 *tl = txdr_unsigned(nlen); 1372 bp += NFSX_UNSIGNED; 1373 1374 /* And loop arround copying the name */ 1375 xfer = nlen; 1376 cp = dp->d_name; 1377 while (xfer > 0) { 1378 nfsm_clget; 1379 if ((bp+xfer) > be) 1380 tsiz = be-bp; 1381 else 1382 tsiz = xfer; 1383 bcopy(cp, bp, tsiz); 1384 bp += tsiz; 1385 xfer -= tsiz; 1386 if (xfer > 0) 1387 cp += tsiz; 1388 } 1389 /* And null pad to a long boundary */ 1390 for (i = 0; i < rem; i++) 1391 *bp++ = '\0'; 1392 nfsm_clget; 1393 1394 /* Finish off the record */ 1395 *tl = txdr_unsigned(*cookie); 1396 bp += NFSX_UNSIGNED; 1397 } 1398 cpos += dp->d_reclen; 1399 dp = (struct dirent *)cpos; 1400 cookie++; 1401 } 1402 nfsm_clget; 1403 *tl = nfs_false; 1404 bp += NFSX_UNSIGNED; 1405 nfsm_clget; 1406 if (eofflag) 1407 *tl = nfs_true; 1408 else 1409 *tl = nfs_false; 1410 bp += NFSX_UNSIGNED; 1411 if (bp < be) 1412 mp->m_len = bp-mtod(mp, caddr_t); 1413 mb->m_next = mp3; 1414 FREE(cookiebuf, M_TEMP); 1415 FREE(rbuf, M_TEMP); 1416 nfsm_srvdone; 1417 } 1418 1419 /* 1420 * nfs statfs service 1421 */ 1422 nfsrv_statfs(mrep, md, dpos, cred, xid, mrq, repstat, p) 1423 struct mbuf **mrq; 1424 struct mbuf *mrep, *md; 1425 caddr_t dpos; 1426 struct ucred *cred; 1427 u_long xid; 1428 int *repstat; 1429 struct proc *p; 1430 { 1431 register struct statfs *sf; 1432 register struct nfsv2_statfs *sfp; 1433 register u_long *tl; 1434 register long t1; 1435 caddr_t bpos; 1436 int error = 0; 1437 char *cp2; 1438 struct mbuf *mb, *mb2, *mreq; 1439 struct vnode *vp; 1440 nfsv2fh_t nfh; 1441 fhandle_t *fhp; 1442 struct statfs statfs; 1443 1444 fhp = &nfh.fh_generic; 1445 nfsm_srvmtofh(fhp); 1446 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) 1447 nfsm_reply(0); 1448 sf = &statfs; 1449 error = VFS_STATFS(vp->v_mount, sf, p); 1450 vput(vp); 1451 nfsm_reply(NFSX_STATFS); 1452 nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS); 1453 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA); 1454 sfp->sf_bsize = txdr_unsigned(sf->f_bsize); 1455 sfp->sf_blocks = txdr_unsigned(sf->f_blocks); 1456 sfp->sf_bfree = txdr_unsigned(sf->f_bfree); 1457 sfp->sf_bavail = txdr_unsigned(sf->f_bavail); 1458 nfsm_srvdone; 1459 } 1460 1461 /* 1462 * Null operation, used by clients to ping server 1463 */ 1464 /* ARGSUSED */ 1465 nfsrv_null(mrep, md, dpos, cred, xid, mrq, repstat, p) 1466 struct mbuf **mrq; 1467 struct mbuf *mrep, *md; 1468 caddr_t dpos; 1469 struct ucred *cred; 1470 u_long xid; 1471 int *repstat; 1472 struct proc *p; 1473 { 1474 caddr_t bpos; 1475 int error = 0; 1476 struct mbuf *mb, *mreq; 1477 1478 error = VNOVAL; 1479 nfsm_reply(0); 1480 return (error); 1481 } 1482 1483 /* 1484 * No operation, used for obsolete procedures 1485 */ 1486 /* ARGSUSED */ 1487 nfsrv_noop(mrep, md, dpos, cred, xid, mrq, repstat, p) 1488 struct mbuf **mrq; 1489 struct mbuf *mrep, *md; 1490 caddr_t dpos; 1491 struct ucred *cred; 1492 u_long xid; 1493 int *repstat; 1494 struct proc *p; 1495 { 1496 caddr_t bpos; 1497 int error; 1498 struct mbuf *mb, *mreq; 1499 1500 if (*repstat) 1501 error = *repstat; 1502 else 1503 error = EPROCUNAVAIL; 1504 nfsm_reply(0); 1505 return (error); 1506 } 1507 1508 /* 1509 * Perform access checking for vnodes obtained from file handles that would 1510 * refer to files already opened by a Unix client. You cannot just use 1511 * vn_writechk() and VOP_ACCESS() for two reasons. 1512 * 1 - You must check for MNT_EXRDONLY as well as MNT_RDONLY for the write case 1513 * 2 - The owner is to be given access irrespective of mode bits so that 1514 * processes that chmod after opening a file don't break. I don't like 1515 * this because it opens a security hole, but since the nfs server opens 1516 * a security hole the size of a barn door anyhow, what the heck. 1517 */ 1518 nfsrv_access(vp, flags, cred, p) 1519 register struct vnode *vp; 1520 int flags; 1521 register struct ucred *cred; 1522 struct proc *p; 1523 { 1524 struct vattr vattr; 1525 int error; 1526 if (flags & VWRITE) { 1527 /* Just vn_writechk() changed to check MNT_EXRDONLY */ 1528 /* 1529 * Disallow write attempts on read-only file systems; 1530 * unless the file is a socket or a block or character 1531 * device resident on the file system. 1532 */ 1533 if (vp->v_mount->mnt_flag & (MNT_RDONLY | MNT_EXRDONLY)) { 1534 switch (vp->v_type) { 1535 case VREG: case VDIR: case VLNK: 1536 return (EROFS); 1537 } 1538 } 1539 /* 1540 * If there's shared text associated with 1541 * the inode, try to free it up once. If 1542 * we fail, we can't allow writing. 1543 */ 1544 if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp)) 1545 return (ETXTBSY); 1546 } 1547 if (error = VOP_GETATTR(vp, &vattr, cred, p)) 1548 return (error); 1549 if ((error = VOP_ACCESS(vp, flags, cred, p)) && 1550 cred->cr_uid != vattr.va_uid) 1551 return (error); 1552 return (0); 1553 } 1554