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