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