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