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