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