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