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