1 /*- 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. 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 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 4. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 */ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 /* 38 * Functions that perform the vfs operations required by the routines in 39 * nfsd_serv.c. It is hoped that this change will make the server more 40 * portable. 41 */ 42 43 #include <fs/nfs/nfsport.h> 44 #include <sys/hash.h> 45 #include <sys/sysctl.h> 46 #include <nlm/nlm_prot.h> 47 #include <nlm/nlm.h> 48 49 FEATURE(nfsd, "NFSv4 server"); 50 51 extern u_int32_t newnfs_true, newnfs_false, newnfs_xdrneg1; 52 extern int nfsrv_useacl; 53 extern int newnfs_numnfsd; 54 extern struct mount nfsv4root_mnt; 55 extern struct nfsrv_stablefirst nfsrv_stablefirst; 56 extern void (*nfsd_call_servertimer)(void); 57 struct vfsoptlist nfsv4root_opt, nfsv4root_newopt; 58 NFSDLOCKMUTEX; 59 struct mtx nfs_cache_mutex; 60 struct mtx nfs_v4root_mutex; 61 struct nfsrvfh nfs_rootfh, nfs_pubfh; 62 int nfs_pubfhset = 0, nfs_rootfhset = 0; 63 struct proc *nfsd_master_proc = NULL; 64 static pid_t nfsd_master_pid = (pid_t)-1; 65 static char nfsd_master_comm[MAXCOMLEN + 1]; 66 static struct timeval nfsd_master_start; 67 static uint32_t nfsv4_sysid = 0; 68 69 static int nfssvc_srvcall(struct thread *, struct nfssvc_args *, 70 struct ucred *); 71 72 static int enable_crossmntpt = 1; 73 static int nfs_commit_blks; 74 static int nfs_commit_miss; 75 extern int nfsrv_issuedelegs; 76 extern int nfsrv_dolocallocks; 77 78 SYSCTL_DECL(_vfs_newnfs); 79 SYSCTL_INT(_vfs_newnfs, OID_AUTO, mirrormnt, CTLFLAG_RW, &enable_crossmntpt, 80 0, "Enable nfsd to cross mount points"); 81 SYSCTL_INT(_vfs_newnfs, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 82 0, ""); 83 SYSCTL_INT(_vfs_newnfs, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 84 0, ""); 85 SYSCTL_INT(_vfs_newnfs, OID_AUTO, issue_delegations, CTLFLAG_RW, 86 &nfsrv_issuedelegs, 0, "Enable nfsd to issue delegations"); 87 SYSCTL_INT(_vfs_newnfs, OID_AUTO, enable_locallocks, CTLFLAG_RW, 88 &nfsrv_dolocallocks, 0, "Enable nfsd to acquire local locks on files"); 89 90 #define NUM_HEURISTIC 1017 91 #define NHUSE_INIT 64 92 #define NHUSE_INC 16 93 #define NHUSE_MAX 2048 94 95 static struct nfsheur { 96 struct vnode *nh_vp; /* vp to match (unreferenced pointer) */ 97 off_t nh_nextr; /* next offset for sequential detection */ 98 int nh_use; /* use count for selection */ 99 int nh_seqcount; /* heuristic */ 100 } nfsheur[NUM_HEURISTIC]; 101 102 103 /* 104 * Get attributes into nfsvattr structure. 105 */ 106 int 107 nfsvno_getattr(struct vnode *vp, struct nfsvattr *nvap, struct ucred *cred, 108 struct thread *p, int vpislocked) 109 { 110 int error, lockedit = 0; 111 112 if (vpislocked == 0) { 113 /* 114 * When vpislocked == 0, the vnode is either exclusively 115 * locked by this thread or not locked by this thread. 116 * As such, shared lock it, if not exclusively locked. 117 */ 118 if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { 119 lockedit = 1; 120 vn_lock(vp, LK_SHARED | LK_RETRY); 121 } 122 } 123 error = VOP_GETATTR(vp, &nvap->na_vattr, cred); 124 if (lockedit != 0) 125 VOP_UNLOCK(vp, 0); 126 return (error); 127 } 128 129 /* 130 * Get a file handle for a vnode. 131 */ 132 int 133 nfsvno_getfh(struct vnode *vp, fhandle_t *fhp, struct thread *p) 134 { 135 int error; 136 137 NFSBZERO((caddr_t)fhp, sizeof(fhandle_t)); 138 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 139 error = VOP_VPTOFH(vp, &fhp->fh_fid); 140 return (error); 141 } 142 143 /* 144 * Perform access checking for vnodes obtained from file handles that would 145 * refer to files already opened by a Unix client. You cannot just use 146 * vn_writechk() and VOP_ACCESSX() for two reasons. 147 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write 148 * case. 149 * 2 - The owner is to be given access irrespective of mode bits for some 150 * operations, so that processes that chmod after opening a file don't 151 * break. 152 */ 153 int 154 nfsvno_accchk(struct vnode *vp, accmode_t accmode, struct ucred *cred, 155 struct nfsexstuff *exp, struct thread *p, int override, int vpislocked, 156 u_int32_t *supportedtypep) 157 { 158 struct vattr vattr; 159 int error = 0, getret = 0; 160 161 if (vpislocked == 0) { 162 if (vn_lock(vp, LK_SHARED) != 0) 163 return (EPERM); 164 } 165 if (accmode & VWRITE) { 166 /* Just vn_writechk() changed to check rdonly */ 167 /* 168 * Disallow write attempts on read-only file systems; 169 * unless the file is a socket or a block or character 170 * device resident on the file system. 171 */ 172 if (NFSVNO_EXRDONLY(exp) || 173 (vp->v_mount->mnt_flag & MNT_RDONLY)) { 174 switch (vp->v_type) { 175 case VREG: 176 case VDIR: 177 case VLNK: 178 error = EROFS; 179 default: 180 break; 181 } 182 } 183 /* 184 * If there's shared text associated with 185 * the inode, try to free it up once. If 186 * we fail, we can't allow writing. 187 */ 188 if ((vp->v_vflag & VV_TEXT) != 0 && error == 0) 189 error = ETXTBSY; 190 } 191 if (error != 0) { 192 if (vpislocked == 0) 193 VOP_UNLOCK(vp, 0); 194 return (error); 195 } 196 197 /* 198 * Should the override still be applied when ACLs are enabled? 199 */ 200 error = VOP_ACCESSX(vp, accmode, cred, p); 201 if (error != 0 && (accmode & (VDELETE | VDELETE_CHILD))) { 202 /* 203 * Try again with VEXPLICIT_DENY, to see if the test for 204 * deletion is supported. 205 */ 206 error = VOP_ACCESSX(vp, accmode | VEXPLICIT_DENY, cred, p); 207 if (error == 0) { 208 if (vp->v_type == VDIR) { 209 accmode &= ~(VDELETE | VDELETE_CHILD); 210 accmode |= VWRITE; 211 error = VOP_ACCESSX(vp, accmode, cred, p); 212 } else if (supportedtypep != NULL) { 213 *supportedtypep &= ~NFSACCESS_DELETE; 214 } 215 } 216 } 217 218 /* 219 * Allow certain operations for the owner (reads and writes 220 * on files that are already open). 221 */ 222 if (override != NFSACCCHK_NOOVERRIDE && 223 (error == EPERM || error == EACCES)) { 224 if (cred->cr_uid == 0 && (override & NFSACCCHK_ALLOWROOT)) 225 error = 0; 226 else if (override & NFSACCCHK_ALLOWOWNER) { 227 getret = VOP_GETATTR(vp, &vattr, cred); 228 if (getret == 0 && cred->cr_uid == vattr.va_uid) 229 error = 0; 230 } 231 } 232 if (vpislocked == 0) 233 VOP_UNLOCK(vp, 0); 234 return (error); 235 } 236 237 /* 238 * Set attribute(s) vnop. 239 */ 240 int 241 nfsvno_setattr(struct vnode *vp, struct nfsvattr *nvap, struct ucred *cred, 242 struct thread *p, struct nfsexstuff *exp) 243 { 244 int error; 245 246 error = VOP_SETATTR(vp, &nvap->na_vattr, cred); 247 return (error); 248 } 249 250 /* 251 * Set up nameidata for a lookup() call and do it 252 * For the cases where we are crossing mount points 253 * (looking up the public fh path or the v4 root path when 254 * not using a pseudo-root fs), set/release the Giant lock, 255 * as required. 256 */ 257 int 258 nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp, 259 struct vnode *dp, int islocked, struct nfsexstuff *exp, struct thread *p, 260 struct vnode **retdirp) 261 { 262 struct componentname *cnp = &ndp->ni_cnd; 263 int i; 264 struct iovec aiov; 265 struct uio auio; 266 int lockleaf = (cnp->cn_flags & LOCKLEAF) != 0, linklen; 267 int error = 0, crossmnt; 268 char *cp; 269 270 *retdirp = NULL; 271 cnp->cn_nameptr = cnp->cn_pnbuf; 272 /* 273 * Extract and set starting directory. 274 */ 275 if (dp->v_type != VDIR) { 276 if (islocked) 277 vput(dp); 278 else 279 vrele(dp); 280 nfsvno_relpathbuf(ndp); 281 return (ENOTDIR); 282 } 283 if (islocked) 284 NFSVOPUNLOCK(dp, 0, p); 285 VREF(dp); 286 *retdirp = dp; 287 if (NFSVNO_EXRDONLY(exp)) 288 cnp->cn_flags |= RDONLY; 289 ndp->ni_segflg = UIO_SYSSPACE; 290 crossmnt = 1; 291 292 if (nd->nd_flag & ND_PUBLOOKUP) { 293 ndp->ni_loopcnt = 0; 294 if (cnp->cn_pnbuf[0] == '/') { 295 vrele(dp); 296 /* 297 * Check for degenerate pathnames here, since lookup() 298 * panics on them. 299 */ 300 for (i = 1; i < ndp->ni_pathlen; i++) 301 if (cnp->cn_pnbuf[i] != '/') 302 break; 303 if (i == ndp->ni_pathlen) { 304 error = NFSERR_ACCES; 305 goto out; 306 } 307 dp = rootvnode; 308 VREF(dp); 309 } 310 } else if ((enable_crossmntpt == 0 && NFSVNO_EXPORTED(exp)) || 311 (nd->nd_flag & ND_NFSV4) == 0) { 312 /* 313 * Only cross mount points for NFSv4 when doing a 314 * mount while traversing the file system above 315 * the mount point, unless enable_crossmntpt is set. 316 */ 317 cnp->cn_flags |= NOCROSSMOUNT; 318 crossmnt = 0; 319 } 320 321 /* 322 * Initialize for scan, set ni_startdir and bump ref on dp again 323 * becuase lookup() will dereference ni_startdir. 324 */ 325 326 cnp->cn_thread = p; 327 ndp->ni_startdir = dp; 328 ndp->ni_rootdir = rootvnode; 329 330 if (!lockleaf) 331 cnp->cn_flags |= LOCKLEAF; 332 for (;;) { 333 cnp->cn_nameptr = cnp->cn_pnbuf; 334 /* 335 * Call lookup() to do the real work. If an error occurs, 336 * ndp->ni_vp and ni_dvp are left uninitialized or NULL and 337 * we do not have to dereference anything before returning. 338 * In either case ni_startdir will be dereferenced and NULLed 339 * out. 340 */ 341 error = lookup(ndp); 342 if (error) 343 break; 344 345 /* 346 * Check for encountering a symbolic link. Trivial 347 * termination occurs if no symlink encountered. 348 */ 349 if ((cnp->cn_flags & ISSYMLINK) == 0) { 350 if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) 351 nfsvno_relpathbuf(ndp); 352 if (ndp->ni_vp && !lockleaf) 353 NFSVOPUNLOCK(ndp->ni_vp, 0, p); 354 break; 355 } 356 357 /* 358 * Validate symlink 359 */ 360 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) 361 NFSVOPUNLOCK(ndp->ni_dvp, 0, p); 362 if (!(nd->nd_flag & ND_PUBLOOKUP)) { 363 error = EINVAL; 364 goto badlink2; 365 } 366 367 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { 368 error = ELOOP; 369 goto badlink2; 370 } 371 if (ndp->ni_pathlen > 1) 372 cp = uma_zalloc(namei_zone, M_WAITOK); 373 else 374 cp = cnp->cn_pnbuf; 375 aiov.iov_base = cp; 376 aiov.iov_len = MAXPATHLEN; 377 auio.uio_iov = &aiov; 378 auio.uio_iovcnt = 1; 379 auio.uio_offset = 0; 380 auio.uio_rw = UIO_READ; 381 auio.uio_segflg = UIO_SYSSPACE; 382 auio.uio_td = NULL; 383 auio.uio_resid = MAXPATHLEN; 384 error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred); 385 if (error) { 386 badlink1: 387 if (ndp->ni_pathlen > 1) 388 uma_zfree(namei_zone, cp); 389 badlink2: 390 vrele(ndp->ni_dvp); 391 vput(ndp->ni_vp); 392 break; 393 } 394 linklen = MAXPATHLEN - auio.uio_resid; 395 if (linklen == 0) { 396 error = ENOENT; 397 goto badlink1; 398 } 399 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 400 error = ENAMETOOLONG; 401 goto badlink1; 402 } 403 404 /* 405 * Adjust or replace path 406 */ 407 if (ndp->ni_pathlen > 1) { 408 NFSBCOPY(ndp->ni_next, cp + linklen, ndp->ni_pathlen); 409 uma_zfree(namei_zone, cnp->cn_pnbuf); 410 cnp->cn_pnbuf = cp; 411 } else 412 cnp->cn_pnbuf[linklen] = '\0'; 413 ndp->ni_pathlen += linklen; 414 415 /* 416 * Cleanup refs for next loop and check if root directory 417 * should replace current directory. Normally ni_dvp 418 * becomes the new base directory and is cleaned up when 419 * we loop. Explicitly null pointers after invalidation 420 * to clarify operation. 421 */ 422 vput(ndp->ni_vp); 423 ndp->ni_vp = NULL; 424 425 if (cnp->cn_pnbuf[0] == '/') { 426 vrele(ndp->ni_dvp); 427 ndp->ni_dvp = ndp->ni_rootdir; 428 VREF(ndp->ni_dvp); 429 } 430 ndp->ni_startdir = ndp->ni_dvp; 431 ndp->ni_dvp = NULL; 432 } 433 if (!lockleaf) 434 cnp->cn_flags &= ~LOCKLEAF; 435 436 out: 437 if (error) { 438 uma_zfree(namei_zone, cnp->cn_pnbuf); 439 ndp->ni_vp = NULL; 440 ndp->ni_dvp = NULL; 441 ndp->ni_startdir = NULL; 442 cnp->cn_flags &= ~HASBUF; 443 } else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) { 444 ndp->ni_dvp = NULL; 445 } 446 return (error); 447 } 448 449 /* 450 * Set up a pathname buffer and return a pointer to it and, optionally 451 * set a hash pointer. 452 */ 453 void 454 nfsvno_setpathbuf(struct nameidata *ndp, char **bufpp, u_long **hashpp) 455 { 456 struct componentname *cnp = &ndp->ni_cnd; 457 458 cnp->cn_flags |= (NOMACCHECK | HASBUF); 459 cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); 460 if (hashpp != NULL) 461 *hashpp = NULL; 462 *bufpp = cnp->cn_pnbuf; 463 } 464 465 /* 466 * Release the above path buffer, if not released by nfsvno_namei(). 467 */ 468 void 469 nfsvno_relpathbuf(struct nameidata *ndp) 470 { 471 472 if ((ndp->ni_cnd.cn_flags & HASBUF) == 0) 473 panic("nfsrelpath"); 474 uma_zfree(namei_zone, ndp->ni_cnd.cn_pnbuf); 475 ndp->ni_cnd.cn_flags &= ~HASBUF; 476 } 477 478 /* 479 * Readlink vnode op into an mbuf list. 480 */ 481 int 482 nfsvno_readlink(struct vnode *vp, struct ucred *cred, struct thread *p, 483 struct mbuf **mpp, struct mbuf **mpendp, int *lenp) 484 { 485 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN]; 486 struct iovec *ivp = iv; 487 struct uio io, *uiop = &io; 488 struct mbuf *mp, *mp2 = NULL, *mp3 = NULL; 489 int i, len, tlen, error; 490 491 len = 0; 492 i = 0; 493 while (len < NFS_MAXPATHLEN) { 494 NFSMGET(mp); 495 MCLGET(mp, M_WAIT); 496 mp->m_len = NFSMSIZ(mp); 497 if (len == 0) { 498 mp3 = mp2 = mp; 499 } else { 500 mp2->m_next = mp; 501 mp2 = mp; 502 } 503 if ((len + mp->m_len) > NFS_MAXPATHLEN) { 504 mp->m_len = NFS_MAXPATHLEN - len; 505 len = NFS_MAXPATHLEN; 506 } else { 507 len += mp->m_len; 508 } 509 ivp->iov_base = mtod(mp, caddr_t); 510 ivp->iov_len = mp->m_len; 511 i++; 512 ivp++; 513 } 514 uiop->uio_iov = iv; 515 uiop->uio_iovcnt = i; 516 uiop->uio_offset = 0; 517 uiop->uio_resid = len; 518 uiop->uio_rw = UIO_READ; 519 uiop->uio_segflg = UIO_SYSSPACE; 520 uiop->uio_td = NULL; 521 error = VOP_READLINK(vp, uiop, cred); 522 if (error) { 523 m_freem(mp3); 524 *lenp = 0; 525 return (error); 526 } 527 if (uiop->uio_resid > 0) { 528 len -= uiop->uio_resid; 529 tlen = NFSM_RNDUP(len); 530 nfsrv_adj(mp3, NFS_MAXPATHLEN - tlen, tlen - len); 531 } 532 *lenp = len; 533 *mpp = mp3; 534 *mpendp = mp; 535 return (0); 536 } 537 538 /* 539 * Read vnode op call into mbuf list. 540 */ 541 int 542 nfsvno_read(struct vnode *vp, off_t off, int cnt, struct ucred *cred, 543 struct thread *p, struct mbuf **mpp, struct mbuf **mpendp) 544 { 545 struct mbuf *m; 546 int i; 547 struct iovec *iv; 548 struct iovec *iv2; 549 int error = 0, len, left, siz, tlen, ioflag = 0, hi, try = 32; 550 struct mbuf *m2 = NULL, *m3; 551 struct uio io, *uiop = &io; 552 struct nfsheur *nh; 553 554 /* 555 * Calculate seqcount for heuristic 556 */ 557 /* 558 * Locate best candidate 559 */ 560 561 hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) % NUM_HEURISTIC; 562 nh = &nfsheur[hi]; 563 564 while (try--) { 565 if (nfsheur[hi].nh_vp == vp) { 566 nh = &nfsheur[hi]; 567 break; 568 } 569 if (nfsheur[hi].nh_use > 0) 570 --nfsheur[hi].nh_use; 571 hi = (hi + 1) % NUM_HEURISTIC; 572 if (nfsheur[hi].nh_use < nh->nh_use) 573 nh = &nfsheur[hi]; 574 } 575 576 if (nh->nh_vp != vp) { 577 nh->nh_vp = vp; 578 nh->nh_nextr = off; 579 nh->nh_use = NHUSE_INIT; 580 if (off == 0) 581 nh->nh_seqcount = 4; 582 else 583 nh->nh_seqcount = 1; 584 } 585 586 /* 587 * Calculate heuristic 588 */ 589 590 if ((off == 0 && nh->nh_seqcount > 0) || off == nh->nh_nextr) { 591 if (++nh->nh_seqcount > IO_SEQMAX) 592 nh->nh_seqcount = IO_SEQMAX; 593 } else if (nh->nh_seqcount > 1) { 594 nh->nh_seqcount = 1; 595 } else { 596 nh->nh_seqcount = 0; 597 } 598 nh->nh_use += NHUSE_INC; 599 if (nh->nh_use > NHUSE_MAX) 600 nh->nh_use = NHUSE_MAX; 601 ioflag |= nh->nh_seqcount << IO_SEQSHIFT; 602 603 len = left = NFSM_RNDUP(cnt); 604 m3 = NULL; 605 /* 606 * Generate the mbuf list with the uio_iov ref. to it. 607 */ 608 i = 0; 609 while (left > 0) { 610 NFSMGET(m); 611 MCLGET(m, M_WAIT); 612 m->m_len = 0; 613 siz = min(M_TRAILINGSPACE(m), left); 614 left -= siz; 615 i++; 616 if (m3) 617 m2->m_next = m; 618 else 619 m3 = m; 620 m2 = m; 621 } 622 MALLOC(iv, struct iovec *, i * sizeof (struct iovec), 623 M_TEMP, M_WAITOK); 624 uiop->uio_iov = iv2 = iv; 625 m = m3; 626 left = len; 627 i = 0; 628 while (left > 0) { 629 if (m == NULL) 630 panic("nfsvno_read iov"); 631 siz = min(M_TRAILINGSPACE(m), left); 632 if (siz > 0) { 633 iv->iov_base = mtod(m, caddr_t) + m->m_len; 634 iv->iov_len = siz; 635 m->m_len += siz; 636 left -= siz; 637 iv++; 638 i++; 639 } 640 m = m->m_next; 641 } 642 uiop->uio_iovcnt = i; 643 uiop->uio_offset = off; 644 uiop->uio_resid = len; 645 uiop->uio_rw = UIO_READ; 646 uiop->uio_segflg = UIO_SYSSPACE; 647 error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred); 648 FREE((caddr_t)iv2, M_TEMP); 649 if (error) { 650 m_freem(m3); 651 *mpp = NULL; 652 return (error); 653 } 654 tlen = len - uiop->uio_resid; 655 cnt = cnt < tlen ? cnt : tlen; 656 tlen = NFSM_RNDUP(cnt); 657 if (tlen == 0) { 658 m_freem(m3); 659 m3 = NULL; 660 } else if (len != tlen || tlen != cnt) 661 nfsrv_adj(m3, len - tlen, tlen - cnt); 662 *mpp = m3; 663 *mpendp = m2; 664 return (0); 665 } 666 667 /* 668 * Write vnode op from an mbuf list. 669 */ 670 int 671 nfsvno_write(struct vnode *vp, off_t off, int retlen, int cnt, int stable, 672 struct mbuf *mp, char *cp, struct ucred *cred, struct thread *p) 673 { 674 struct iovec *ivp; 675 int i, len; 676 struct iovec *iv; 677 int ioflags, error; 678 struct uio io, *uiop = &io; 679 680 MALLOC(ivp, struct iovec *, cnt * sizeof (struct iovec), M_TEMP, 681 M_WAITOK); 682 uiop->uio_iov = iv = ivp; 683 uiop->uio_iovcnt = cnt; 684 i = mtod(mp, caddr_t) + mp->m_len - cp; 685 len = retlen; 686 while (len > 0) { 687 if (mp == NULL) 688 panic("nfsvno_write"); 689 if (i > 0) { 690 i = min(i, len); 691 ivp->iov_base = cp; 692 ivp->iov_len = i; 693 ivp++; 694 len -= i; 695 } 696 mp = mp->m_next; 697 if (mp) { 698 i = mp->m_len; 699 cp = mtod(mp, caddr_t); 700 } 701 } 702 703 if (stable == NFSWRITE_UNSTABLE) 704 ioflags = IO_NODELOCKED; 705 else 706 ioflags = (IO_SYNC | IO_NODELOCKED); 707 uiop->uio_resid = retlen; 708 uiop->uio_rw = UIO_WRITE; 709 uiop->uio_segflg = UIO_SYSSPACE; 710 NFSUIOPROC(uiop, p); 711 uiop->uio_offset = off; 712 error = VOP_WRITE(vp, uiop, ioflags, cred); 713 FREE((caddr_t)iv, M_TEMP); 714 return (error); 715 } 716 717 /* 718 * Common code for creating a regular file (plus special files for V2). 719 */ 720 int 721 nfsvno_createsub(struct nfsrv_descript *nd, struct nameidata *ndp, 722 struct vnode **vpp, struct nfsvattr *nvap, int *exclusive_flagp, 723 int32_t *cverf, NFSDEV_T rdev, struct thread *p, struct nfsexstuff *exp) 724 { 725 u_quad_t tempsize; 726 int error; 727 728 error = nd->nd_repstat; 729 if (!error && ndp->ni_vp == NULL) { 730 if (nvap->na_type == VREG || nvap->na_type == VSOCK) { 731 vrele(ndp->ni_startdir); 732 error = VOP_CREATE(ndp->ni_dvp, 733 &ndp->ni_vp, &ndp->ni_cnd, &nvap->na_vattr); 734 vput(ndp->ni_dvp); 735 nfsvno_relpathbuf(ndp); 736 if (!error) { 737 if (*exclusive_flagp) { 738 *exclusive_flagp = 0; 739 NFSVNO_ATTRINIT(nvap); 740 nvap->na_atime.tv_sec = cverf[0]; 741 nvap->na_atime.tv_nsec = cverf[1]; 742 error = VOP_SETATTR(ndp->ni_vp, 743 &nvap->na_vattr, nd->nd_cred); 744 } 745 } 746 /* 747 * NFS V2 Only. nfsrvd_mknod() does this for V3. 748 * (This implies, just get out on an error.) 749 */ 750 } else if (nvap->na_type == VCHR || nvap->na_type == VBLK || 751 nvap->na_type == VFIFO) { 752 if (nvap->na_type == VCHR && rdev == 0xffffffff) 753 nvap->na_type = VFIFO; 754 if (nvap->na_type != VFIFO && 755 (error = priv_check_cred(nd->nd_cred, 756 PRIV_VFS_MKNOD_DEV, 0))) { 757 vrele(ndp->ni_startdir); 758 nfsvno_relpathbuf(ndp); 759 vput(ndp->ni_dvp); 760 return (error); 761 } 762 nvap->na_rdev = rdev; 763 error = VOP_MKNOD(ndp->ni_dvp, &ndp->ni_vp, 764 &ndp->ni_cnd, &nvap->na_vattr); 765 vput(ndp->ni_dvp); 766 nfsvno_relpathbuf(ndp); 767 if (error) { 768 vrele(ndp->ni_startdir); 769 return (error); 770 } 771 } else { 772 vrele(ndp->ni_startdir); 773 nfsvno_relpathbuf(ndp); 774 vput(ndp->ni_dvp); 775 return (ENXIO); 776 } 777 *vpp = ndp->ni_vp; 778 } else { 779 /* 780 * Handle cases where error is already set and/or 781 * the file exists. 782 * 1 - clean up the lookup 783 * 2 - iff !error and na_size set, truncate it 784 */ 785 vrele(ndp->ni_startdir); 786 nfsvno_relpathbuf(ndp); 787 *vpp = ndp->ni_vp; 788 if (ndp->ni_dvp == *vpp) 789 vrele(ndp->ni_dvp); 790 else 791 vput(ndp->ni_dvp); 792 if (!error && nvap->na_size != VNOVAL) { 793 error = nfsvno_accchk(*vpp, VWRITE, 794 nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE, 795 NFSACCCHK_VPISLOCKED, NULL); 796 if (!error) { 797 tempsize = nvap->na_size; 798 NFSVNO_ATTRINIT(nvap); 799 nvap->na_size = tempsize; 800 error = VOP_SETATTR(*vpp, 801 &nvap->na_vattr, nd->nd_cred); 802 } 803 } 804 if (error) 805 vput(*vpp); 806 } 807 return (error); 808 } 809 810 /* 811 * Do a mknod vnode op. 812 */ 813 int 814 nfsvno_mknod(struct nameidata *ndp, struct nfsvattr *nvap, struct ucred *cred, 815 struct thread *p) 816 { 817 int error = 0; 818 enum vtype vtyp; 819 820 vtyp = nvap->na_type; 821 /* 822 * Iff doesn't exist, create it. 823 */ 824 if (ndp->ni_vp) { 825 vrele(ndp->ni_startdir); 826 nfsvno_relpathbuf(ndp); 827 vput(ndp->ni_dvp); 828 vrele(ndp->ni_vp); 829 return (EEXIST); 830 } 831 if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) { 832 vrele(ndp->ni_startdir); 833 nfsvno_relpathbuf(ndp); 834 vput(ndp->ni_dvp); 835 return (NFSERR_BADTYPE); 836 } 837 if (vtyp == VSOCK) { 838 vrele(ndp->ni_startdir); 839 error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, 840 &ndp->ni_cnd, &nvap->na_vattr); 841 vput(ndp->ni_dvp); 842 nfsvno_relpathbuf(ndp); 843 } else { 844 if (nvap->na_type != VFIFO && 845 (error = priv_check_cred(cred, PRIV_VFS_MKNOD_DEV, 0))) { 846 vrele(ndp->ni_startdir); 847 nfsvno_relpathbuf(ndp); 848 vput(ndp->ni_dvp); 849 return (error); 850 } 851 error = VOP_MKNOD(ndp->ni_dvp, &ndp->ni_vp, 852 &ndp->ni_cnd, &nvap->na_vattr); 853 vput(ndp->ni_dvp); 854 nfsvno_relpathbuf(ndp); 855 vrele(ndp->ni_startdir); 856 /* 857 * Since VOP_MKNOD returns the ni_vp, I can't 858 * see any reason to do the lookup. 859 */ 860 } 861 return (error); 862 } 863 864 /* 865 * Mkdir vnode op. 866 */ 867 int 868 nfsvno_mkdir(struct nameidata *ndp, struct nfsvattr *nvap, uid_t saved_uid, 869 struct ucred *cred, struct thread *p, struct nfsexstuff *exp) 870 { 871 int error = 0; 872 873 if (ndp->ni_vp != NULL) { 874 if (ndp->ni_dvp == ndp->ni_vp) 875 vrele(ndp->ni_dvp); 876 else 877 vput(ndp->ni_dvp); 878 vrele(ndp->ni_vp); 879 nfsvno_relpathbuf(ndp); 880 return (EEXIST); 881 } 882 error = VOP_MKDIR(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd, 883 &nvap->na_vattr); 884 vput(ndp->ni_dvp); 885 nfsvno_relpathbuf(ndp); 886 return (error); 887 } 888 889 /* 890 * symlink vnode op. 891 */ 892 int 893 nfsvno_symlink(struct nameidata *ndp, struct nfsvattr *nvap, char *pathcp, 894 int pathlen, int not_v2, uid_t saved_uid, struct ucred *cred, struct thread *p, 895 struct nfsexstuff *exp) 896 { 897 int error = 0; 898 899 if (ndp->ni_vp) { 900 vrele(ndp->ni_startdir); 901 nfsvno_relpathbuf(ndp); 902 if (ndp->ni_dvp == ndp->ni_vp) 903 vrele(ndp->ni_dvp); 904 else 905 vput(ndp->ni_dvp); 906 vrele(ndp->ni_vp); 907 return (EEXIST); 908 } 909 910 error = VOP_SYMLINK(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd, 911 &nvap->na_vattr, pathcp); 912 vput(ndp->ni_dvp); 913 vrele(ndp->ni_startdir); 914 nfsvno_relpathbuf(ndp); 915 /* 916 * Although FreeBSD still had the lookup code in 917 * it for 7/current, there doesn't seem to be any 918 * point, since VOP_SYMLINK() returns the ni_vp. 919 * Just vput it for v2. 920 */ 921 if (!not_v2 && !error) 922 vput(ndp->ni_vp); 923 return (error); 924 } 925 926 /* 927 * Parse symbolic link arguments. 928 * This function has an ugly side effect. It will MALLOC() an area for 929 * the symlink and set iov_base to point to it, only if it succeeds. 930 * So, if it returns with uiop->uio_iov->iov_base != NULL, that must 931 * be FREE'd later. 932 */ 933 int 934 nfsvno_getsymlink(struct nfsrv_descript *nd, struct nfsvattr *nvap, 935 struct thread *p, char **pathcpp, int *lenp) 936 { 937 u_int32_t *tl; 938 char *pathcp = NULL; 939 int error = 0, len; 940 struct nfsv2_sattr *sp; 941 942 *pathcpp = NULL; 943 *lenp = 0; 944 if ((nd->nd_flag & ND_NFSV3) && 945 (error = nfsrv_sattr(nd, nvap, NULL, NULL, p))) 946 goto nfsmout; 947 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 948 len = fxdr_unsigned(int, *tl); 949 if (len > NFS_MAXPATHLEN || len <= 0) { 950 error = EBADRPC; 951 goto nfsmout; 952 } 953 MALLOC(pathcp, caddr_t, len + 1, M_TEMP, M_WAITOK); 954 error = nfsrv_mtostr(nd, pathcp, len); 955 if (error) 956 goto nfsmout; 957 if (nd->nd_flag & ND_NFSV2) { 958 NFSM_DISSECT(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 959 nvap->na_mode = fxdr_unsigned(u_int16_t, sp->sa_mode); 960 } 961 *pathcpp = pathcp; 962 *lenp = len; 963 return (0); 964 nfsmout: 965 if (pathcp) 966 free(pathcp, M_TEMP); 967 return (error); 968 } 969 970 /* 971 * Remove a non-directory object. 972 */ 973 int 974 nfsvno_removesub(struct nameidata *ndp, int is_v4, struct ucred *cred, 975 struct thread *p, struct nfsexstuff *exp) 976 { 977 struct vnode *vp; 978 int error = 0; 979 980 vp = ndp->ni_vp; 981 if (vp->v_type == VDIR) 982 error = NFSERR_ISDIR; 983 else if (is_v4) 984 error = nfsrv_checkremove(vp, 1, p); 985 if (!error) 986 error = VOP_REMOVE(ndp->ni_dvp, vp, &ndp->ni_cnd); 987 if (ndp->ni_dvp == vp) 988 vrele(ndp->ni_dvp); 989 else 990 vput(ndp->ni_dvp); 991 vput(vp); 992 return (error); 993 } 994 995 /* 996 * Remove a directory. 997 */ 998 int 999 nfsvno_rmdirsub(struct nameidata *ndp, int is_v4, struct ucred *cred, 1000 struct thread *p, struct nfsexstuff *exp) 1001 { 1002 struct vnode *vp; 1003 int error = 0; 1004 1005 vp = ndp->ni_vp; 1006 if (vp->v_type != VDIR) { 1007 error = ENOTDIR; 1008 goto out; 1009 } 1010 /* 1011 * No rmdir "." please. 1012 */ 1013 if (ndp->ni_dvp == vp) { 1014 error = EINVAL; 1015 goto out; 1016 } 1017 /* 1018 * The root of a mounted filesystem cannot be deleted. 1019 */ 1020 if (vp->v_vflag & VV_ROOT) 1021 error = EBUSY; 1022 out: 1023 if (!error) 1024 error = VOP_RMDIR(ndp->ni_dvp, vp, &ndp->ni_cnd); 1025 if (ndp->ni_dvp == vp) 1026 vrele(ndp->ni_dvp); 1027 else 1028 vput(ndp->ni_dvp); 1029 vput(vp); 1030 return (error); 1031 } 1032 1033 /* 1034 * Rename vnode op. 1035 */ 1036 int 1037 nfsvno_rename(struct nameidata *fromndp, struct nameidata *tondp, 1038 u_int32_t ndstat, u_int32_t ndflag, struct ucred *cred, struct thread *p) 1039 { 1040 struct vnode *fvp, *tvp, *tdvp; 1041 int error = 0; 1042 1043 fvp = fromndp->ni_vp; 1044 if (ndstat) { 1045 vrele(fromndp->ni_dvp); 1046 vrele(fvp); 1047 error = ndstat; 1048 goto out1; 1049 } 1050 tdvp = tondp->ni_dvp; 1051 tvp = tondp->ni_vp; 1052 if (tvp != NULL) { 1053 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1054 error = (ndflag & ND_NFSV2) ? EISDIR : EEXIST; 1055 goto out; 1056 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1057 error = (ndflag & ND_NFSV2) ? ENOTDIR : EEXIST; 1058 goto out; 1059 } 1060 if (tvp->v_type == VDIR && tvp->v_mountedhere) { 1061 error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EXDEV; 1062 goto out; 1063 } 1064 1065 /* 1066 * A rename to '.' or '..' results in a prematurely 1067 * unlocked vnode on FreeBSD5, so I'm just going to fail that 1068 * here. 1069 */ 1070 if ((tondp->ni_cnd.cn_namelen == 1 && 1071 tondp->ni_cnd.cn_nameptr[0] == '.') || 1072 (tondp->ni_cnd.cn_namelen == 2 && 1073 tondp->ni_cnd.cn_nameptr[0] == '.' && 1074 tondp->ni_cnd.cn_nameptr[1] == '.')) { 1075 error = EINVAL; 1076 goto out; 1077 } 1078 } 1079 if (fvp->v_type == VDIR && fvp->v_mountedhere) { 1080 error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EXDEV; 1081 goto out; 1082 } 1083 if (fvp->v_mount != tdvp->v_mount) { 1084 error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EXDEV; 1085 goto out; 1086 } 1087 if (fvp == tdvp) { 1088 error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EINVAL; 1089 goto out; 1090 } 1091 if (fvp == tvp) { 1092 /* 1093 * If source and destination are the same, there is nothing to 1094 * do. Set error to -1 to indicate this. 1095 */ 1096 error = -1; 1097 goto out; 1098 } 1099 if (ndflag & ND_NFSV4) { 1100 if (vn_lock(fvp, LK_EXCLUSIVE) == 0) { 1101 error = nfsrv_checkremove(fvp, 0, p); 1102 VOP_UNLOCK(fvp, 0); 1103 } else 1104 error = EPERM; 1105 if (tvp && !error) 1106 error = nfsrv_checkremove(tvp, 1, p); 1107 } else { 1108 /* 1109 * For NFSv2 and NFSv3, try to get rid of the delegation, so 1110 * that the NFSv4 client won't be confused by the rename. 1111 * Since nfsd_recalldelegation() can only be called on an 1112 * unlocked vnode at this point and fvp is the file that will 1113 * still exist after the rename, just do fvp. 1114 */ 1115 nfsd_recalldelegation(fvp, p); 1116 } 1117 out: 1118 if (!error) { 1119 error = VOP_RENAME(fromndp->ni_dvp, fromndp->ni_vp, 1120 &fromndp->ni_cnd, tondp->ni_dvp, tondp->ni_vp, 1121 &tondp->ni_cnd); 1122 } else { 1123 if (tdvp == tvp) 1124 vrele(tdvp); 1125 else 1126 vput(tdvp); 1127 if (tvp) 1128 vput(tvp); 1129 vrele(fromndp->ni_dvp); 1130 vrele(fvp); 1131 if (error == -1) 1132 error = 0; 1133 } 1134 vrele(tondp->ni_startdir); 1135 nfsvno_relpathbuf(tondp); 1136 out1: 1137 vrele(fromndp->ni_startdir); 1138 nfsvno_relpathbuf(fromndp); 1139 return (error); 1140 } 1141 1142 /* 1143 * Link vnode op. 1144 */ 1145 int 1146 nfsvno_link(struct nameidata *ndp, struct vnode *vp, struct ucred *cred, 1147 struct thread *p, struct nfsexstuff *exp) 1148 { 1149 struct vnode *xp; 1150 int error = 0; 1151 1152 xp = ndp->ni_vp; 1153 if (xp != NULL) { 1154 error = EEXIST; 1155 } else { 1156 xp = ndp->ni_dvp; 1157 if (vp->v_mount != xp->v_mount) 1158 error = EXDEV; 1159 } 1160 if (!error) { 1161 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1162 if ((vp->v_iflag & VI_DOOMED) == 0) 1163 error = VOP_LINK(ndp->ni_dvp, vp, &ndp->ni_cnd); 1164 else 1165 error = EPERM; 1166 if (ndp->ni_dvp == vp) 1167 vrele(ndp->ni_dvp); 1168 else 1169 vput(ndp->ni_dvp); 1170 VOP_UNLOCK(vp, 0); 1171 } else { 1172 if (ndp->ni_dvp == ndp->ni_vp) 1173 vrele(ndp->ni_dvp); 1174 else 1175 vput(ndp->ni_dvp); 1176 if (ndp->ni_vp) 1177 vrele(ndp->ni_vp); 1178 } 1179 nfsvno_relpathbuf(ndp); 1180 return (error); 1181 } 1182 1183 /* 1184 * Do the fsync() appropriate for the commit. 1185 */ 1186 int 1187 nfsvno_fsync(struct vnode *vp, u_int64_t off, int cnt, struct ucred *cred, 1188 struct thread *td) 1189 { 1190 int error = 0; 1191 1192 if (cnt > MAX_COMMIT_COUNT) { 1193 /* 1194 * Give up and do the whole thing 1195 */ 1196 if (vp->v_object && 1197 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) { 1198 VM_OBJECT_LOCK(vp->v_object); 1199 vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC); 1200 VM_OBJECT_UNLOCK(vp->v_object); 1201 } 1202 error = VOP_FSYNC(vp, MNT_WAIT, td); 1203 } else { 1204 /* 1205 * Locate and synchronously write any buffers that fall 1206 * into the requested range. Note: we are assuming that 1207 * f_iosize is a power of 2. 1208 */ 1209 int iosize = vp->v_mount->mnt_stat.f_iosize; 1210 int iomask = iosize - 1; 1211 struct bufobj *bo; 1212 daddr_t lblkno; 1213 1214 /* 1215 * Align to iosize boundry, super-align to page boundry. 1216 */ 1217 if (off & iomask) { 1218 cnt += off & iomask; 1219 off &= ~(u_quad_t)iomask; 1220 } 1221 if (off & PAGE_MASK) { 1222 cnt += off & PAGE_MASK; 1223 off &= ~(u_quad_t)PAGE_MASK; 1224 } 1225 lblkno = off / iosize; 1226 1227 if (vp->v_object && 1228 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) { 1229 VM_OBJECT_LOCK(vp->v_object); 1230 vm_object_page_clean(vp->v_object, off, off + cnt, 1231 OBJPC_SYNC); 1232 VM_OBJECT_UNLOCK(vp->v_object); 1233 } 1234 1235 bo = &vp->v_bufobj; 1236 BO_LOCK(bo); 1237 while (cnt > 0) { 1238 struct buf *bp; 1239 1240 /* 1241 * If we have a buffer and it is marked B_DELWRI we 1242 * have to lock and write it. Otherwise the prior 1243 * write is assumed to have already been committed. 1244 * 1245 * gbincore() can return invalid buffers now so we 1246 * have to check that bit as well (though B_DELWRI 1247 * should not be set if B_INVAL is set there could be 1248 * a race here since we haven't locked the buffer). 1249 */ 1250 if ((bp = gbincore(&vp->v_bufobj, lblkno)) != NULL) { 1251 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL | 1252 LK_INTERLOCK, BO_MTX(bo)) == ENOLCK) { 1253 BO_LOCK(bo); 1254 continue; /* retry */ 1255 } 1256 if ((bp->b_flags & (B_DELWRI|B_INVAL)) == 1257 B_DELWRI) { 1258 bremfree(bp); 1259 bp->b_flags &= ~B_ASYNC; 1260 bwrite(bp); 1261 ++nfs_commit_miss; 1262 } else 1263 BUF_UNLOCK(bp); 1264 BO_LOCK(bo); 1265 } 1266 ++nfs_commit_blks; 1267 if (cnt < iosize) 1268 break; 1269 cnt -= iosize; 1270 ++lblkno; 1271 } 1272 BO_UNLOCK(bo); 1273 } 1274 return (error); 1275 } 1276 1277 /* 1278 * Statfs vnode op. 1279 */ 1280 int 1281 nfsvno_statfs(struct vnode *vp, struct statfs *sf) 1282 { 1283 1284 return (VFS_STATFS(vp->v_mount, sf)); 1285 } 1286 1287 /* 1288 * Do the vnode op stuff for Open. Similar to nfsvno_createsub(), but 1289 * must handle nfsrv_opencheck() calls after any other access checks. 1290 */ 1291 void 1292 nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp, 1293 nfsquad_t clientid, nfsv4stateid_t *stateidp, struct nfsstate *stp, 1294 int *exclusive_flagp, struct nfsvattr *nvap, int32_t *cverf, int create, 1295 NFSACL_T *aclp, nfsattrbit_t *attrbitp, struct ucred *cred, struct thread *p, 1296 struct nfsexstuff *exp, struct vnode **vpp) 1297 { 1298 struct vnode *vp = NULL; 1299 u_quad_t tempsize; 1300 struct nfsexstuff nes; 1301 1302 if (ndp->ni_vp == NULL) 1303 nd->nd_repstat = nfsrv_opencheck(clientid, 1304 stateidp, stp, NULL, nd, p, nd->nd_repstat); 1305 if (!nd->nd_repstat) { 1306 if (ndp->ni_vp == NULL) { 1307 vrele(ndp->ni_startdir); 1308 nd->nd_repstat = VOP_CREATE(ndp->ni_dvp, 1309 &ndp->ni_vp, &ndp->ni_cnd, &nvap->na_vattr); 1310 vput(ndp->ni_dvp); 1311 nfsvno_relpathbuf(ndp); 1312 if (!nd->nd_repstat) { 1313 if (*exclusive_flagp) { 1314 *exclusive_flagp = 0; 1315 NFSVNO_ATTRINIT(nvap); 1316 nvap->na_atime.tv_sec = cverf[0]; 1317 nvap->na_atime.tv_nsec = cverf[1]; 1318 nd->nd_repstat = VOP_SETATTR(ndp->ni_vp, 1319 &nvap->na_vattr, cred); 1320 } else { 1321 nfsrv_fixattr(nd, ndp->ni_vp, nvap, 1322 aclp, p, attrbitp, exp); 1323 } 1324 } 1325 vp = ndp->ni_vp; 1326 } else { 1327 if (ndp->ni_startdir) 1328 vrele(ndp->ni_startdir); 1329 nfsvno_relpathbuf(ndp); 1330 vp = ndp->ni_vp; 1331 if (create == NFSV4OPEN_CREATE) { 1332 if (ndp->ni_dvp == vp) 1333 vrele(ndp->ni_dvp); 1334 else 1335 vput(ndp->ni_dvp); 1336 } 1337 if (NFSVNO_ISSETSIZE(nvap) && vp->v_type == VREG) { 1338 if (ndp->ni_cnd.cn_flags & RDONLY) 1339 NFSVNO_SETEXRDONLY(&nes); 1340 else 1341 NFSVNO_EXINIT(&nes); 1342 nd->nd_repstat = nfsvno_accchk(vp, 1343 VWRITE, cred, &nes, p, 1344 NFSACCCHK_NOOVERRIDE, 1345 NFSACCCHK_VPISLOCKED, NULL); 1346 nd->nd_repstat = nfsrv_opencheck(clientid, 1347 stateidp, stp, vp, nd, p, nd->nd_repstat); 1348 if (!nd->nd_repstat) { 1349 tempsize = nvap->na_size; 1350 NFSVNO_ATTRINIT(nvap); 1351 nvap->na_size = tempsize; 1352 nd->nd_repstat = VOP_SETATTR(vp, 1353 &nvap->na_vattr, cred); 1354 } 1355 } else if (vp->v_type == VREG) { 1356 nd->nd_repstat = nfsrv_opencheck(clientid, 1357 stateidp, stp, vp, nd, p, nd->nd_repstat); 1358 } 1359 } 1360 } else { 1361 if (ndp->ni_cnd.cn_flags & HASBUF) 1362 nfsvno_relpathbuf(ndp); 1363 if (ndp->ni_startdir && create == NFSV4OPEN_CREATE) { 1364 vrele(ndp->ni_startdir); 1365 if (ndp->ni_dvp == ndp->ni_vp) 1366 vrele(ndp->ni_dvp); 1367 else 1368 vput(ndp->ni_dvp); 1369 if (ndp->ni_vp) 1370 vput(ndp->ni_vp); 1371 } 1372 } 1373 *vpp = vp; 1374 } 1375 1376 /* 1377 * Updates the file rev and sets the mtime and ctime 1378 * to the current clock time, returning the va_filerev and va_Xtime 1379 * values. 1380 */ 1381 void 1382 nfsvno_updfilerev(struct vnode *vp, struct nfsvattr *nvap, 1383 struct ucred *cred, struct thread *p) 1384 { 1385 struct vattr va; 1386 1387 VATTR_NULL(&va); 1388 getnanotime(&va.va_mtime); 1389 (void) VOP_SETATTR(vp, &va, cred); 1390 (void) nfsvno_getattr(vp, nvap, cred, p, 1); 1391 } 1392 1393 /* 1394 * Glue routine to nfsv4_fillattr(). 1395 */ 1396 int 1397 nfsvno_fillattr(struct nfsrv_descript *nd, struct vnode *vp, 1398 struct nfsvattr *nvap, fhandle_t *fhp, int rderror, nfsattrbit_t *attrbitp, 1399 struct ucred *cred, struct thread *p, int isdgram, int reterr) 1400 { 1401 int error; 1402 1403 error = nfsv4_fillattr(nd, vp, NULL, &nvap->na_vattr, fhp, rderror, 1404 attrbitp, cred, p, isdgram, reterr); 1405 return (error); 1406 } 1407 1408 /* Since the Readdir vnode ops vary, put the entire functions in here. */ 1409 /* 1410 * nfs readdir service 1411 * - mallocs what it thinks is enough to read 1412 * count rounded up to a multiple of DIRBLKSIZ <= NFS_MAXREADDIR 1413 * - calls VOP_READDIR() 1414 * - loops around building the reply 1415 * if the output generated exceeds count break out of loop 1416 * The NFSM_CLGET macro is used here so that the reply will be packed 1417 * tightly in mbuf clusters. 1418 * - it trims out records with d_fileno == 0 1419 * this doesn't matter for Unix clients, but they might confuse clients 1420 * for other os'. 1421 * - it trims out records with d_type == DT_WHT 1422 * these cannot be seen through NFS (unless we extend the protocol) 1423 * The alternate call nfsrvd_readdirplus() does lookups as well. 1424 * PS: The NFS protocol spec. does not clarify what the "count" byte 1425 * argument is a count of.. just name strings and file id's or the 1426 * entire reply rpc or ... 1427 * I tried just file name and id sizes and it confused the Sun client, 1428 * so I am using the full rpc size now. The "paranoia.." comment refers 1429 * to including the status longwords that are not a part of the dir. 1430 * "entry" structures, but are in the rpc. 1431 */ 1432 int 1433 nfsrvd_readdir(struct nfsrv_descript *nd, int isdgram, 1434 struct vnode *vp, struct thread *p, struct nfsexstuff *exp) 1435 { 1436 struct dirent *dp; 1437 u_int32_t *tl; 1438 int dirlen; 1439 char *cpos, *cend, *rbuf; 1440 struct nfsvattr at; 1441 int nlen, error = 0, getret = 1; 1442 int siz, cnt, fullsiz, eofflag, ncookies; 1443 u_int64_t off, toff, verf; 1444 u_long *cookies = NULL, *cookiep; 1445 struct uio io; 1446 struct iovec iv; 1447 int not_zfs; 1448 1449 if (nd->nd_repstat) { 1450 nfsrv_postopattr(nd, getret, &at); 1451 return (0); 1452 } 1453 if (nd->nd_flag & ND_NFSV2) { 1454 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1455 off = fxdr_unsigned(u_quad_t, *tl++); 1456 } else { 1457 NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 1458 off = fxdr_hyper(tl); 1459 tl += 2; 1460 verf = fxdr_hyper(tl); 1461 tl += 2; 1462 } 1463 toff = off; 1464 cnt = fxdr_unsigned(int, *tl); 1465 if (cnt > NFS_SRVMAXDATA(nd) || cnt < 0) 1466 cnt = NFS_SRVMAXDATA(nd); 1467 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 1468 fullsiz = siz; 1469 if (nd->nd_flag & ND_NFSV3) { 1470 nd->nd_repstat = getret = nfsvno_getattr(vp, &at, nd->nd_cred, 1471 p, 1); 1472 #if 0 1473 /* 1474 * va_filerev is not sufficient as a cookie verifier, 1475 * since it is not supposed to change when entries are 1476 * removed/added unless that offset cookies returned to 1477 * the client are no longer valid. 1478 */ 1479 if (!nd->nd_repstat && toff && verf != at.na_filerev) 1480 nd->nd_repstat = NFSERR_BAD_COOKIE; 1481 #endif 1482 } 1483 if (nd->nd_repstat == 0 && cnt == 0) { 1484 if (nd->nd_flag & ND_NFSV2) 1485 /* NFSv2 does not have NFSERR_TOOSMALL */ 1486 nd->nd_repstat = EPERM; 1487 else 1488 nd->nd_repstat = NFSERR_TOOSMALL; 1489 } 1490 if (!nd->nd_repstat) 1491 nd->nd_repstat = nfsvno_accchk(vp, VEXEC, 1492 nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE, 1493 NFSACCCHK_VPISLOCKED, NULL); 1494 if (nd->nd_repstat) { 1495 vput(vp); 1496 if (nd->nd_flag & ND_NFSV3) 1497 nfsrv_postopattr(nd, getret, &at); 1498 return (0); 1499 } 1500 not_zfs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs"); 1501 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 1502 again: 1503 eofflag = 0; 1504 if (cookies) { 1505 free((caddr_t)cookies, M_TEMP); 1506 cookies = NULL; 1507 } 1508 1509 iv.iov_base = rbuf; 1510 iv.iov_len = siz; 1511 io.uio_iov = &iv; 1512 io.uio_iovcnt = 1; 1513 io.uio_offset = (off_t)off; 1514 io.uio_resid = siz; 1515 io.uio_segflg = UIO_SYSSPACE; 1516 io.uio_rw = UIO_READ; 1517 io.uio_td = NULL; 1518 nd->nd_repstat = VOP_READDIR(vp, &io, nd->nd_cred, &eofflag, &ncookies, 1519 &cookies); 1520 off = (u_int64_t)io.uio_offset; 1521 if (io.uio_resid) 1522 siz -= io.uio_resid; 1523 1524 if (!cookies && !nd->nd_repstat) 1525 nd->nd_repstat = NFSERR_PERM; 1526 if (nd->nd_flag & ND_NFSV3) { 1527 getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1); 1528 if (!nd->nd_repstat) 1529 nd->nd_repstat = getret; 1530 } 1531 1532 /* 1533 * Handles the failed cases. nd->nd_repstat == 0 past here. 1534 */ 1535 if (nd->nd_repstat) { 1536 vput(vp); 1537 free((caddr_t)rbuf, M_TEMP); 1538 if (cookies) 1539 free((caddr_t)cookies, M_TEMP); 1540 if (nd->nd_flag & ND_NFSV3) 1541 nfsrv_postopattr(nd, getret, &at); 1542 return (0); 1543 } 1544 /* 1545 * If nothing read, return eof 1546 * rpc reply 1547 */ 1548 if (siz == 0) { 1549 vput(vp); 1550 if (nd->nd_flag & ND_NFSV2) { 1551 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1552 } else { 1553 nfsrv_postopattr(nd, getret, &at); 1554 NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 1555 txdr_hyper(at.na_filerev, tl); 1556 tl += 2; 1557 } 1558 *tl++ = newnfs_false; 1559 *tl = newnfs_true; 1560 FREE((caddr_t)rbuf, M_TEMP); 1561 FREE((caddr_t)cookies, M_TEMP); 1562 return (0); 1563 } 1564 1565 /* 1566 * Check for degenerate cases of nothing useful read. 1567 * If so go try again 1568 */ 1569 cpos = rbuf; 1570 cend = rbuf + siz; 1571 dp = (struct dirent *)cpos; 1572 cookiep = cookies; 1573 1574 /* 1575 * For some reason FreeBSD's ufs_readdir() chooses to back the 1576 * directory offset up to a block boundary, so it is necessary to 1577 * skip over the records that precede the requested offset. This 1578 * requires the assumption that file offset cookies monotonically 1579 * increase. 1580 * Since the offset cookies don't monotonically increase for ZFS, 1581 * this is not done when ZFS is the file system. 1582 */ 1583 while (cpos < cend && ncookies > 0 && 1584 (dp->d_fileno == 0 || dp->d_type == DT_WHT || 1585 (not_zfs != 0 && ((u_quad_t)(*cookiep)) <= toff))) { 1586 cpos += dp->d_reclen; 1587 dp = (struct dirent *)cpos; 1588 cookiep++; 1589 ncookies--; 1590 } 1591 if (cpos >= cend || ncookies == 0) { 1592 siz = fullsiz; 1593 toff = off; 1594 goto again; 1595 } 1596 vput(vp); 1597 1598 /* 1599 * dirlen is the size of the reply, including all XDR and must 1600 * not exceed cnt. For NFSv2, RFC1094 didn't clearly indicate 1601 * if the XDR should be included in "count", but to be safe, we do. 1602 * (Include the two booleans at the end of the reply in dirlen now.) 1603 */ 1604 if (nd->nd_flag & ND_NFSV3) { 1605 nfsrv_postopattr(nd, getret, &at); 1606 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1607 txdr_hyper(at.na_filerev, tl); 1608 dirlen = NFSX_V3POSTOPATTR + NFSX_VERF + 2 * NFSX_UNSIGNED; 1609 } else { 1610 dirlen = 2 * NFSX_UNSIGNED; 1611 } 1612 1613 /* Loop through the records and build reply */ 1614 while (cpos < cend && ncookies > 0) { 1615 nlen = dp->d_namlen; 1616 if (dp->d_fileno != 0 && dp->d_type != DT_WHT && 1617 nlen <= NFS_MAXNAMLEN) { 1618 if (nd->nd_flag & ND_NFSV3) 1619 dirlen += (6*NFSX_UNSIGNED + NFSM_RNDUP(nlen)); 1620 else 1621 dirlen += (4*NFSX_UNSIGNED + NFSM_RNDUP(nlen)); 1622 if (dirlen > cnt) { 1623 eofflag = 0; 1624 break; 1625 } 1626 1627 /* 1628 * Build the directory record xdr from 1629 * the dirent entry. 1630 */ 1631 if (nd->nd_flag & ND_NFSV3) { 1632 NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 1633 *tl++ = newnfs_true; 1634 *tl++ = 0; 1635 } else { 1636 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1637 *tl++ = newnfs_true; 1638 } 1639 *tl = txdr_unsigned(dp->d_fileno); 1640 (void) nfsm_strtom(nd, dp->d_name, nlen); 1641 if (nd->nd_flag & ND_NFSV3) { 1642 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1643 *tl++ = 0; 1644 } else 1645 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1646 *tl = txdr_unsigned(*cookiep); 1647 } 1648 cpos += dp->d_reclen; 1649 dp = (struct dirent *)cpos; 1650 cookiep++; 1651 ncookies--; 1652 } 1653 if (cpos < cend) 1654 eofflag = 0; 1655 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1656 *tl++ = newnfs_false; 1657 if (eofflag) 1658 *tl = newnfs_true; 1659 else 1660 *tl = newnfs_false; 1661 FREE((caddr_t)rbuf, M_TEMP); 1662 FREE((caddr_t)cookies, M_TEMP); 1663 return (0); 1664 nfsmout: 1665 vput(vp); 1666 return (error); 1667 } 1668 1669 /* 1670 * Readdirplus for V3 and Readdir for V4. 1671 */ 1672 int 1673 nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram, 1674 struct vnode *vp, struct thread *p, struct nfsexstuff *exp) 1675 { 1676 struct dirent *dp; 1677 u_int32_t *tl; 1678 int dirlen; 1679 char *cpos, *cend, *rbuf; 1680 struct vnode *nvp; 1681 fhandle_t nfh; 1682 struct nfsvattr nva, at, *nvap = &nva; 1683 struct mbuf *mb0, *mb1; 1684 struct nfsreferral *refp; 1685 int nlen, r, error = 0, getret = 1, usevget = 1; 1686 int siz, cnt, fullsiz, eofflag, ncookies, entrycnt; 1687 caddr_t bpos0, bpos1; 1688 u_int64_t off, toff, verf; 1689 u_long *cookies = NULL, *cookiep; 1690 nfsattrbit_t attrbits, rderrbits, savbits; 1691 struct uio io; 1692 struct iovec iv; 1693 struct componentname cn; 1694 int not_zfs; 1695 struct mount *mp; 1696 1697 if (nd->nd_repstat) { 1698 nfsrv_postopattr(nd, getret, &at); 1699 return (0); 1700 } 1701 NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED); 1702 off = fxdr_hyper(tl); 1703 toff = off; 1704 tl += 2; 1705 verf = fxdr_hyper(tl); 1706 tl += 2; 1707 siz = fxdr_unsigned(int, *tl++); 1708 cnt = fxdr_unsigned(int, *tl); 1709 1710 /* 1711 * Use the server's maximum data transfer size as the upper bound 1712 * on reply datalen. 1713 */ 1714 if (cnt > NFS_SRVMAXDATA(nd) || cnt < 0) 1715 cnt = NFS_SRVMAXDATA(nd); 1716 1717 /* 1718 * siz is a "hint" of how much directory information (name, fileid, 1719 * cookie) should be in the reply. At least one client "hints" 0, 1720 * so I set it to cnt for that case. I also round it up to the 1721 * next multiple of DIRBLKSIZ. 1722 */ 1723 if (siz <= 0) 1724 siz = cnt; 1725 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 1726 1727 if (nd->nd_flag & ND_NFSV4) { 1728 error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL); 1729 if (error) 1730 goto nfsmout; 1731 NFSSET_ATTRBIT(&savbits, &attrbits); 1732 NFSCLRNOTFILLABLE_ATTRBIT(&attrbits); 1733 NFSZERO_ATTRBIT(&rderrbits); 1734 NFSSETBIT_ATTRBIT(&rderrbits, NFSATTRBIT_RDATTRERROR); 1735 } else { 1736 NFSZERO_ATTRBIT(&attrbits); 1737 } 1738 fullsiz = siz; 1739 nd->nd_repstat = getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1); 1740 if (!nd->nd_repstat) { 1741 if (off && verf != at.na_filerev) { 1742 /* 1743 * va_filerev is not sufficient as a cookie verifier, 1744 * since it is not supposed to change when entries are 1745 * removed/added unless that offset cookies returned to 1746 * the client are no longer valid. 1747 */ 1748 #if 0 1749 if (nd->nd_flag & ND_NFSV4) { 1750 nd->nd_repstat = NFSERR_NOTSAME; 1751 } else { 1752 nd->nd_repstat = NFSERR_BAD_COOKIE; 1753 } 1754 #endif 1755 } else if ((nd->nd_flag & ND_NFSV4) && off == 0 && verf != 0) { 1756 nd->nd_repstat = NFSERR_BAD_COOKIE; 1757 } 1758 } 1759 if (!nd->nd_repstat && vp->v_type != VDIR) 1760 nd->nd_repstat = NFSERR_NOTDIR; 1761 if (!nd->nd_repstat && cnt == 0) 1762 nd->nd_repstat = NFSERR_TOOSMALL; 1763 if (!nd->nd_repstat) 1764 nd->nd_repstat = nfsvno_accchk(vp, VEXEC, 1765 nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE, 1766 NFSACCCHK_VPISLOCKED, NULL); 1767 if (nd->nd_repstat) { 1768 vput(vp); 1769 if (nd->nd_flag & ND_NFSV3) 1770 nfsrv_postopattr(nd, getret, &at); 1771 return (0); 1772 } 1773 not_zfs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs"); 1774 1775 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 1776 again: 1777 eofflag = 0; 1778 if (cookies) { 1779 free((caddr_t)cookies, M_TEMP); 1780 cookies = NULL; 1781 } 1782 1783 iv.iov_base = rbuf; 1784 iv.iov_len = siz; 1785 io.uio_iov = &iv; 1786 io.uio_iovcnt = 1; 1787 io.uio_offset = (off_t)off; 1788 io.uio_resid = siz; 1789 io.uio_segflg = UIO_SYSSPACE; 1790 io.uio_rw = UIO_READ; 1791 io.uio_td = NULL; 1792 nd->nd_repstat = VOP_READDIR(vp, &io, nd->nd_cred, &eofflag, &ncookies, 1793 &cookies); 1794 off = (u_int64_t)io.uio_offset; 1795 if (io.uio_resid) 1796 siz -= io.uio_resid; 1797 1798 getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1); 1799 1800 if (!cookies && !nd->nd_repstat) 1801 nd->nd_repstat = NFSERR_PERM; 1802 if (!nd->nd_repstat) 1803 nd->nd_repstat = getret; 1804 if (nd->nd_repstat) { 1805 vput(vp); 1806 if (cookies) 1807 free((caddr_t)cookies, M_TEMP); 1808 free((caddr_t)rbuf, M_TEMP); 1809 if (nd->nd_flag & ND_NFSV3) 1810 nfsrv_postopattr(nd, getret, &at); 1811 return (0); 1812 } 1813 /* 1814 * If nothing read, return eof 1815 * rpc reply 1816 */ 1817 if (siz == 0) { 1818 vput(vp); 1819 if (nd->nd_flag & ND_NFSV3) 1820 nfsrv_postopattr(nd, getret, &at); 1821 NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 1822 txdr_hyper(at.na_filerev, tl); 1823 tl += 2; 1824 *tl++ = newnfs_false; 1825 *tl = newnfs_true; 1826 free((caddr_t)cookies, M_TEMP); 1827 free((caddr_t)rbuf, M_TEMP); 1828 return (0); 1829 } 1830 1831 /* 1832 * Check for degenerate cases of nothing useful read. 1833 * If so go try again 1834 */ 1835 cpos = rbuf; 1836 cend = rbuf + siz; 1837 dp = (struct dirent *)cpos; 1838 cookiep = cookies; 1839 1840 /* 1841 * For some reason FreeBSD's ufs_readdir() chooses to back the 1842 * directory offset up to a block boundary, so it is necessary to 1843 * skip over the records that precede the requested offset. This 1844 * requires the assumption that file offset cookies monotonically 1845 * increase. 1846 * Since the offset cookies don't monotonically increase for ZFS, 1847 * this is not done when ZFS is the file system. 1848 */ 1849 while (cpos < cend && ncookies > 0 && 1850 (dp->d_fileno == 0 || dp->d_type == DT_WHT || 1851 (not_zfs != 0 && ((u_quad_t)(*cookiep)) <= toff) || 1852 ((nd->nd_flag & ND_NFSV4) && 1853 ((dp->d_namlen == 1 && dp->d_name[0] == '.') || 1854 (dp->d_namlen==2 && dp->d_name[0]=='.' && dp->d_name[1]=='.'))))) { 1855 cpos += dp->d_reclen; 1856 dp = (struct dirent *)cpos; 1857 cookiep++; 1858 ncookies--; 1859 } 1860 if (cpos >= cend || ncookies == 0) { 1861 siz = fullsiz; 1862 toff = off; 1863 goto again; 1864 } 1865 1866 /* 1867 * Busy the file system so that the mount point won't go away 1868 * and, as such, VFS_VGET() can be used safely. 1869 */ 1870 mp = vp->v_mount; 1871 vfs_ref(mp); 1872 VOP_UNLOCK(vp, 0); 1873 nd->nd_repstat = vfs_busy(mp, 0); 1874 vfs_rel(mp); 1875 if (nd->nd_repstat != 0) { 1876 vrele(vp); 1877 free(cookies, M_TEMP); 1878 free(rbuf, M_TEMP); 1879 if (nd->nd_flag & ND_NFSV3) 1880 nfsrv_postopattr(nd, getret, &at); 1881 return (0); 1882 } 1883 1884 /* 1885 * Save this position, in case there is an error before one entry 1886 * is created. 1887 */ 1888 mb0 = nd->nd_mb; 1889 bpos0 = nd->nd_bpos; 1890 1891 /* 1892 * Fill in the first part of the reply. 1893 * dirlen is the reply length in bytes and cannot exceed cnt. 1894 * (Include the two booleans at the end of the reply in dirlen now, 1895 * so we recognize when we have exceeded cnt.) 1896 */ 1897 if (nd->nd_flag & ND_NFSV3) { 1898 dirlen = NFSX_V3POSTOPATTR + NFSX_VERF + 2 * NFSX_UNSIGNED; 1899 nfsrv_postopattr(nd, getret, &at); 1900 } else { 1901 dirlen = NFSX_VERF + 2 * NFSX_UNSIGNED; 1902 } 1903 NFSM_BUILD(tl, u_int32_t *, NFSX_VERF); 1904 txdr_hyper(at.na_filerev, tl); 1905 1906 /* 1907 * Save this position, in case there is an empty reply needed. 1908 */ 1909 mb1 = nd->nd_mb; 1910 bpos1 = nd->nd_bpos; 1911 1912 /* Loop through the records and build reply */ 1913 entrycnt = 0; 1914 while (cpos < cend && ncookies > 0 && dirlen < cnt) { 1915 nlen = dp->d_namlen; 1916 if (dp->d_fileno != 0 && dp->d_type != DT_WHT && 1917 nlen <= NFS_MAXNAMLEN && 1918 ((nd->nd_flag & ND_NFSV3) || nlen > 2 || 1919 (nlen==2 && (dp->d_name[0]!='.' || dp->d_name[1]!='.')) 1920 || (nlen == 1 && dp->d_name[0] != '.'))) { 1921 /* 1922 * Save the current position in the reply, in case 1923 * this entry exceeds cnt. 1924 */ 1925 mb1 = nd->nd_mb; 1926 bpos1 = nd->nd_bpos; 1927 1928 /* 1929 * For readdir_and_lookup get the vnode using 1930 * the file number. 1931 */ 1932 nvp = NULL; 1933 refp = NULL; 1934 r = 0; 1935 if ((nd->nd_flag & ND_NFSV3) || 1936 NFSNONZERO_ATTRBIT(&savbits)) { 1937 if (nd->nd_flag & ND_NFSV4) 1938 refp = nfsv4root_getreferral(NULL, 1939 vp, dp->d_fileno); 1940 if (refp == NULL) { 1941 if (usevget) 1942 r = VFS_VGET(mp, dp->d_fileno, 1943 LK_SHARED, &nvp); 1944 else 1945 r = EOPNOTSUPP; 1946 if (r == EOPNOTSUPP) { 1947 if (usevget) { 1948 usevget = 0; 1949 cn.cn_nameiop = LOOKUP; 1950 cn.cn_lkflags = 1951 LK_SHARED | 1952 LK_RETRY; 1953 cn.cn_cred = 1954 nd->nd_cred; 1955 cn.cn_thread = p; 1956 } 1957 cn.cn_nameptr = dp->d_name; 1958 cn.cn_namelen = nlen; 1959 cn.cn_flags = ISLASTCN | 1960 NOFOLLOW | LOCKLEAF | 1961 MPSAFE; 1962 if (nlen == 2 && 1963 dp->d_name[0] == '.' && 1964 dp->d_name[1] == '.') 1965 cn.cn_flags |= 1966 ISDOTDOT; 1967 if (vn_lock(vp, LK_SHARED) 1968 != 0) { 1969 nd->nd_repstat = EPERM; 1970 break; 1971 } 1972 if ((vp->v_vflag & VV_ROOT) != 0 1973 && (cn.cn_flags & ISDOTDOT) 1974 != 0) { 1975 vref(vp); 1976 nvp = vp; 1977 r = 0; 1978 } else 1979 r = VOP_LOOKUP(vp, &nvp, 1980 &cn); 1981 } 1982 } 1983 if (!r) { 1984 if (refp == NULL && 1985 ((nd->nd_flag & ND_NFSV3) || 1986 NFSNONZERO_ATTRBIT(&attrbits))) { 1987 r = nfsvno_getfh(nvp, &nfh, p); 1988 if (!r) 1989 r = nfsvno_getattr(nvp, nvap, 1990 nd->nd_cred, p, 1); 1991 } 1992 } else { 1993 nvp = NULL; 1994 } 1995 if (r) { 1996 if (!NFSISSET_ATTRBIT(&attrbits, 1997 NFSATTRBIT_RDATTRERROR)) { 1998 if (nvp != NULL) 1999 vput(nvp); 2000 nd->nd_repstat = r; 2001 break; 2002 } 2003 } 2004 } 2005 2006 /* 2007 * Build the directory record xdr 2008 */ 2009 if (nd->nd_flag & ND_NFSV3) { 2010 NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2011 *tl++ = newnfs_true; 2012 *tl++ = 0; 2013 *tl = txdr_unsigned(dp->d_fileno); 2014 dirlen += nfsm_strtom(nd, dp->d_name, nlen); 2015 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2016 *tl++ = 0; 2017 *tl = txdr_unsigned(*cookiep); 2018 nfsrv_postopattr(nd, 0, nvap); 2019 dirlen += nfsm_fhtom(nd,(u_int8_t *)&nfh,0,1); 2020 dirlen += (5*NFSX_UNSIGNED+NFSX_V3POSTOPATTR); 2021 if (nvp != NULL) 2022 vput(nvp); 2023 } else { 2024 NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2025 *tl++ = newnfs_true; 2026 *tl++ = 0; 2027 *tl = txdr_unsigned(*cookiep); 2028 dirlen += nfsm_strtom(nd, dp->d_name, nlen); 2029 if (nvp != NULL) 2030 VOP_UNLOCK(nvp, 0); 2031 if (refp != NULL) { 2032 dirlen += nfsrv_putreferralattr(nd, 2033 &savbits, refp, 0, 2034 &nd->nd_repstat); 2035 if (nd->nd_repstat) { 2036 if (nvp != NULL) 2037 vrele(nvp); 2038 break; 2039 } 2040 } else if (r) { 2041 dirlen += nfsvno_fillattr(nd, nvp, nvap, 2042 &nfh, r, &rderrbits, nd->nd_cred, 2043 p, isdgram, 0); 2044 } else { 2045 dirlen += nfsvno_fillattr(nd, nvp, nvap, 2046 &nfh, r, &attrbits, nd->nd_cred, 2047 p, isdgram, 0); 2048 } 2049 if (nvp != NULL) 2050 vrele(nvp); 2051 dirlen += (3 * NFSX_UNSIGNED); 2052 } 2053 if (dirlen <= cnt) 2054 entrycnt++; 2055 } 2056 cpos += dp->d_reclen; 2057 dp = (struct dirent *)cpos; 2058 cookiep++; 2059 ncookies--; 2060 } 2061 vrele(vp); 2062 vfs_unbusy(mp); 2063 2064 /* 2065 * If dirlen > cnt, we must strip off the last entry. If that 2066 * results in an empty reply, report NFSERR_TOOSMALL. 2067 */ 2068 if (dirlen > cnt || nd->nd_repstat) { 2069 if (!nd->nd_repstat && entrycnt == 0) 2070 nd->nd_repstat = NFSERR_TOOSMALL; 2071 if (nd->nd_repstat) 2072 newnfs_trimtrailing(nd, mb0, bpos0); 2073 else 2074 newnfs_trimtrailing(nd, mb1, bpos1); 2075 eofflag = 0; 2076 } else if (cpos < cend) 2077 eofflag = 0; 2078 if (!nd->nd_repstat) { 2079 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2080 *tl++ = newnfs_false; 2081 if (eofflag) 2082 *tl = newnfs_true; 2083 else 2084 *tl = newnfs_false; 2085 } 2086 FREE((caddr_t)cookies, M_TEMP); 2087 FREE((caddr_t)rbuf, M_TEMP); 2088 return (0); 2089 nfsmout: 2090 vput(vp); 2091 return (error); 2092 } 2093 2094 /* 2095 * Get the settable attributes out of the mbuf list. 2096 * (Return 0 or EBADRPC) 2097 */ 2098 int 2099 nfsrv_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap, 2100 nfsattrbit_t *attrbitp, NFSACL_T *aclp, struct thread *p) 2101 { 2102 u_int32_t *tl; 2103 struct nfsv2_sattr *sp; 2104 struct timeval curtime; 2105 int error = 0, toclient = 0; 2106 2107 switch (nd->nd_flag & (ND_NFSV2 | ND_NFSV3 | ND_NFSV4)) { 2108 case ND_NFSV2: 2109 NFSM_DISSECT(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 2110 /* 2111 * Some old clients didn't fill in the high order 16bits. 2112 * --> check the low order 2 bytes for 0xffff 2113 */ 2114 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff) 2115 nvap->na_mode = nfstov_mode(sp->sa_mode); 2116 if (sp->sa_uid != newnfs_xdrneg1) 2117 nvap->na_uid = fxdr_unsigned(uid_t, sp->sa_uid); 2118 if (sp->sa_gid != newnfs_xdrneg1) 2119 nvap->na_gid = fxdr_unsigned(gid_t, sp->sa_gid); 2120 if (sp->sa_size != newnfs_xdrneg1) 2121 nvap->na_size = fxdr_unsigned(u_quad_t, sp->sa_size); 2122 if (sp->sa_atime.nfsv2_sec != newnfs_xdrneg1) { 2123 #ifdef notyet 2124 fxdr_nfsv2time(&sp->sa_atime, &nvap->na_atime); 2125 #else 2126 nvap->na_atime.tv_sec = 2127 fxdr_unsigned(u_int32_t,sp->sa_atime.nfsv2_sec); 2128 nvap->na_atime.tv_nsec = 0; 2129 #endif 2130 } 2131 if (sp->sa_mtime.nfsv2_sec != newnfs_xdrneg1) 2132 fxdr_nfsv2time(&sp->sa_mtime, &nvap->na_mtime); 2133 break; 2134 case ND_NFSV3: 2135 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2136 if (*tl == newnfs_true) { 2137 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2138 nvap->na_mode = nfstov_mode(*tl); 2139 } 2140 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2141 if (*tl == newnfs_true) { 2142 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2143 nvap->na_uid = fxdr_unsigned(uid_t, *tl); 2144 } 2145 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2146 if (*tl == newnfs_true) { 2147 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2148 nvap->na_gid = fxdr_unsigned(gid_t, *tl); 2149 } 2150 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2151 if (*tl == newnfs_true) { 2152 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2153 nvap->na_size = fxdr_hyper(tl); 2154 } 2155 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2156 switch (fxdr_unsigned(int, *tl)) { 2157 case NFSV3SATTRTIME_TOCLIENT: 2158 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2159 fxdr_nfsv3time(tl, &nvap->na_atime); 2160 toclient = 1; 2161 break; 2162 case NFSV3SATTRTIME_TOSERVER: 2163 NFSGETTIME(&curtime); 2164 nvap->na_atime.tv_sec = curtime.tv_sec; 2165 nvap->na_atime.tv_nsec = curtime.tv_usec * 1000; 2166 nvap->na_vaflags |= VA_UTIMES_NULL; 2167 break; 2168 }; 2169 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2170 switch (fxdr_unsigned(int, *tl)) { 2171 case NFSV3SATTRTIME_TOCLIENT: 2172 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2173 fxdr_nfsv3time(tl, &nvap->na_mtime); 2174 nvap->na_vaflags &= ~VA_UTIMES_NULL; 2175 break; 2176 case NFSV3SATTRTIME_TOSERVER: 2177 NFSGETTIME(&curtime); 2178 nvap->na_mtime.tv_sec = curtime.tv_sec; 2179 nvap->na_mtime.tv_nsec = curtime.tv_usec * 1000; 2180 if (!toclient) 2181 nvap->na_vaflags |= VA_UTIMES_NULL; 2182 break; 2183 }; 2184 break; 2185 case ND_NFSV4: 2186 error = nfsv4_sattr(nd, nvap, attrbitp, aclp, p); 2187 }; 2188 nfsmout: 2189 return (error); 2190 } 2191 2192 /* 2193 * Handle the setable attributes for V4. 2194 * Returns NFSERR_BADXDR if it can't be parsed, 0 otherwise. 2195 */ 2196 int 2197 nfsv4_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap, 2198 nfsattrbit_t *attrbitp, NFSACL_T *aclp, struct thread *p) 2199 { 2200 u_int32_t *tl; 2201 int attrsum = 0; 2202 int i, j; 2203 int error, attrsize, bitpos, aclsize, aceerr, retnotsup = 0; 2204 int toclient = 0; 2205 u_char *cp, namestr[NFSV4_SMALLSTR + 1]; 2206 uid_t uid; 2207 gid_t gid; 2208 struct timeval curtime; 2209 2210 error = nfsrv_getattrbits(nd, attrbitp, NULL, &retnotsup); 2211 if (error) 2212 return (error); 2213 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2214 attrsize = fxdr_unsigned(int, *tl); 2215 2216 /* 2217 * Loop around getting the setable attributes. If an unsupported 2218 * one is found, set nd_repstat == NFSERR_ATTRNOTSUPP and return. 2219 */ 2220 if (retnotsup) { 2221 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2222 bitpos = NFSATTRBIT_MAX; 2223 } else { 2224 bitpos = 0; 2225 } 2226 for (; bitpos < NFSATTRBIT_MAX; bitpos++) { 2227 if (attrsum > attrsize) { 2228 error = NFSERR_BADXDR; 2229 goto nfsmout; 2230 } 2231 if (NFSISSET_ATTRBIT(attrbitp, bitpos)) 2232 switch (bitpos) { 2233 case NFSATTRBIT_SIZE: 2234 NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER); 2235 nvap->na_size = fxdr_hyper(tl); 2236 attrsum += NFSX_HYPER; 2237 break; 2238 case NFSATTRBIT_ACL: 2239 error = nfsrv_dissectacl(nd, aclp, &aceerr, &aclsize, 2240 p); 2241 if (error) 2242 goto nfsmout; 2243 if (aceerr && !nd->nd_repstat) 2244 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2245 attrsum += aclsize; 2246 break; 2247 case NFSATTRBIT_ARCHIVE: 2248 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2249 if (!nd->nd_repstat) 2250 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2251 attrsum += NFSX_UNSIGNED; 2252 break; 2253 case NFSATTRBIT_HIDDEN: 2254 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2255 if (!nd->nd_repstat) 2256 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2257 attrsum += NFSX_UNSIGNED; 2258 break; 2259 case NFSATTRBIT_MIMETYPE: 2260 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2261 i = fxdr_unsigned(int, *tl); 2262 error = nfsm_advance(nd, NFSM_RNDUP(i), -1); 2263 if (error) 2264 goto nfsmout; 2265 if (!nd->nd_repstat) 2266 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2267 attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(i)); 2268 break; 2269 case NFSATTRBIT_MODE: 2270 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2271 nvap->na_mode = nfstov_mode(*tl); 2272 attrsum += NFSX_UNSIGNED; 2273 break; 2274 case NFSATTRBIT_OWNER: 2275 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2276 j = fxdr_unsigned(int, *tl); 2277 if (j < 0) 2278 return (NFSERR_BADXDR); 2279 if (j > NFSV4_SMALLSTR) 2280 cp = malloc(j + 1, M_NFSSTRING, M_WAITOK); 2281 else 2282 cp = namestr; 2283 error = nfsrv_mtostr(nd, cp, j); 2284 if (error) { 2285 if (j > NFSV4_SMALLSTR) 2286 free(cp, M_NFSSTRING); 2287 return (error); 2288 } 2289 if (!nd->nd_repstat) { 2290 nd->nd_repstat = nfsv4_strtouid(cp,j,&uid,p); 2291 if (!nd->nd_repstat) 2292 nvap->na_uid = uid; 2293 } 2294 if (j > NFSV4_SMALLSTR) 2295 free(cp, M_NFSSTRING); 2296 attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j)); 2297 break; 2298 case NFSATTRBIT_OWNERGROUP: 2299 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2300 j = fxdr_unsigned(int, *tl); 2301 if (j < 0) 2302 return (NFSERR_BADXDR); 2303 if (j > NFSV4_SMALLSTR) 2304 cp = malloc(j + 1, M_NFSSTRING, M_WAITOK); 2305 else 2306 cp = namestr; 2307 error = nfsrv_mtostr(nd, cp, j); 2308 if (error) { 2309 if (j > NFSV4_SMALLSTR) 2310 free(cp, M_NFSSTRING); 2311 return (error); 2312 } 2313 if (!nd->nd_repstat) { 2314 nd->nd_repstat = nfsv4_strtogid(cp,j,&gid,p); 2315 if (!nd->nd_repstat) 2316 nvap->na_gid = gid; 2317 } 2318 if (j > NFSV4_SMALLSTR) 2319 free(cp, M_NFSSTRING); 2320 attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j)); 2321 break; 2322 case NFSATTRBIT_SYSTEM: 2323 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2324 if (!nd->nd_repstat) 2325 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2326 attrsum += NFSX_UNSIGNED; 2327 break; 2328 case NFSATTRBIT_TIMEACCESSSET: 2329 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2330 attrsum += NFSX_UNSIGNED; 2331 if (fxdr_unsigned(int, *tl)==NFSV4SATTRTIME_TOCLIENT) { 2332 NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME); 2333 fxdr_nfsv4time(tl, &nvap->na_atime); 2334 toclient = 1; 2335 attrsum += NFSX_V4TIME; 2336 } else { 2337 NFSGETTIME(&curtime); 2338 nvap->na_atime.tv_sec = curtime.tv_sec; 2339 nvap->na_atime.tv_nsec = curtime.tv_usec * 1000; 2340 nvap->na_vaflags |= VA_UTIMES_NULL; 2341 } 2342 break; 2343 case NFSATTRBIT_TIMEBACKUP: 2344 NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME); 2345 if (!nd->nd_repstat) 2346 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2347 attrsum += NFSX_V4TIME; 2348 break; 2349 case NFSATTRBIT_TIMECREATE: 2350 NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME); 2351 if (!nd->nd_repstat) 2352 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2353 attrsum += NFSX_V4TIME; 2354 break; 2355 case NFSATTRBIT_TIMEMODIFYSET: 2356 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2357 attrsum += NFSX_UNSIGNED; 2358 if (fxdr_unsigned(int, *tl)==NFSV4SATTRTIME_TOCLIENT) { 2359 NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME); 2360 fxdr_nfsv4time(tl, &nvap->na_mtime); 2361 nvap->na_vaflags &= ~VA_UTIMES_NULL; 2362 attrsum += NFSX_V4TIME; 2363 } else { 2364 NFSGETTIME(&curtime); 2365 nvap->na_mtime.tv_sec = curtime.tv_sec; 2366 nvap->na_mtime.tv_nsec = curtime.tv_usec * 1000; 2367 if (!toclient) 2368 nvap->na_vaflags |= VA_UTIMES_NULL; 2369 } 2370 break; 2371 default: 2372 nd->nd_repstat = NFSERR_ATTRNOTSUPP; 2373 /* 2374 * set bitpos so we drop out of the loop. 2375 */ 2376 bitpos = NFSATTRBIT_MAX; 2377 break; 2378 }; 2379 } 2380 2381 /* 2382 * some clients pad the attrlist, so we need to skip over the 2383 * padding. 2384 */ 2385 if (attrsum > attrsize) { 2386 error = NFSERR_BADXDR; 2387 } else { 2388 attrsize = NFSM_RNDUP(attrsize); 2389 if (attrsum < attrsize) 2390 error = nfsm_advance(nd, attrsize - attrsum, -1); 2391 } 2392 nfsmout: 2393 return (error); 2394 } 2395 2396 /* 2397 * Check/setup export credentials. 2398 */ 2399 int 2400 nfsd_excred(struct nfsrv_descript *nd, struct nfsexstuff *exp, 2401 struct ucred *credanon) 2402 { 2403 int error = 0; 2404 2405 /* 2406 * Check/setup credentials. 2407 */ 2408 if (nd->nd_flag & ND_GSS) 2409 exp->nes_exflag &= ~MNT_EXPORTANON; 2410 2411 /* 2412 * Check to see if the operation is allowed for this security flavor. 2413 * RFC2623 suggests that the NFSv3 Fsinfo RPC be allowed to 2414 * AUTH_NONE or AUTH_SYS for file systems requiring RPCSEC_GSS. 2415 * Also, allow Secinfo, so that it can acquire the correct flavor(s). 2416 */ 2417 if (nfsvno_testexp(nd, exp) && 2418 nd->nd_procnum != NFSV4OP_SECINFO && 2419 nd->nd_procnum != NFSPROC_FSINFO) { 2420 if (nd->nd_flag & ND_NFSV4) 2421 error = NFSERR_WRONGSEC; 2422 else 2423 error = (NFSERR_AUTHERR | AUTH_TOOWEAK); 2424 return (error); 2425 } 2426 2427 /* 2428 * Check to see if the file system is exported V4 only. 2429 */ 2430 if (NFSVNO_EXV4ONLY(exp) && !(nd->nd_flag & ND_NFSV4)) 2431 return (NFSERR_PROGNOTV4); 2432 2433 /* 2434 * Now, map the user credentials. 2435 * (Note that ND_AUTHNONE will only be set for an NFSv3 2436 * Fsinfo RPC. If set for anything else, this code might need 2437 * to change.) 2438 */ 2439 if (NFSVNO_EXPORTED(exp) && 2440 ((!(nd->nd_flag & ND_GSS) && nd->nd_cred->cr_uid == 0) || 2441 NFSVNO_EXPORTANON(exp) || 2442 (nd->nd_flag & ND_AUTHNONE))) { 2443 nd->nd_cred->cr_uid = credanon->cr_uid; 2444 nd->nd_cred->cr_gid = credanon->cr_gid; 2445 crsetgroups(nd->nd_cred, credanon->cr_ngroups, 2446 credanon->cr_groups); 2447 } 2448 return (0); 2449 } 2450 2451 /* 2452 * Check exports. 2453 */ 2454 int 2455 nfsvno_checkexp(struct mount *mp, struct sockaddr *nam, struct nfsexstuff *exp, 2456 struct ucred **credp) 2457 { 2458 int i, error, *secflavors; 2459 2460 error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp, 2461 &exp->nes_numsecflavor, &secflavors); 2462 if (error) { 2463 if (nfs_rootfhset) { 2464 exp->nes_exflag = 0; 2465 exp->nes_numsecflavor = 0; 2466 error = 0; 2467 } 2468 } else { 2469 /* Copy the security flavors. */ 2470 for (i = 0; i < exp->nes_numsecflavor; i++) 2471 exp->nes_secflavors[i] = secflavors[i]; 2472 } 2473 return (error); 2474 } 2475 2476 /* 2477 * Get a vnode for a file handle and export stuff. 2478 */ 2479 int 2480 nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam, 2481 int lktype, struct vnode **vpp, struct nfsexstuff *exp, 2482 struct ucred **credp) 2483 { 2484 int i, error, *secflavors; 2485 2486 *credp = NULL; 2487 exp->nes_numsecflavor = 0; 2488 if (VFS_NEEDSGIANT(mp)) 2489 error = ESTALE; 2490 else 2491 error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp); 2492 if (error != 0) 2493 /* Make sure the server replies ESTALE to the client. */ 2494 error = ESTALE; 2495 if (nam && !error) { 2496 error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp, 2497 &exp->nes_numsecflavor, &secflavors); 2498 if (error) { 2499 if (nfs_rootfhset) { 2500 exp->nes_exflag = 0; 2501 exp->nes_numsecflavor = 0; 2502 error = 0; 2503 } else { 2504 vput(*vpp); 2505 } 2506 } else { 2507 /* Copy the security flavors. */ 2508 for (i = 0; i < exp->nes_numsecflavor; i++) 2509 exp->nes_secflavors[i] = secflavors[i]; 2510 } 2511 } 2512 if (error == 0 && lktype == LK_SHARED) 2513 /* 2514 * It would be much better to pass lktype to VFS_FHTOVP(), 2515 * but this will have to do until VFS_FHTOVP() has a lock 2516 * type argument like VFS_VGET(). 2517 */ 2518 vn_lock(*vpp, LK_DOWNGRADE | LK_RETRY); 2519 return (error); 2520 } 2521 2522 /* 2523 * Do the pathconf vnode op. 2524 */ 2525 int 2526 nfsvno_pathconf(struct vnode *vp, int flag, register_t *retf, 2527 struct ucred *cred, struct thread *p) 2528 { 2529 int error; 2530 2531 error = VOP_PATHCONF(vp, flag, retf); 2532 return (error); 2533 } 2534 2535 /* 2536 * nfsd_fhtovp() - convert a fh to a vnode ptr 2537 * - look up fsid in mount list (if not found ret error) 2538 * - get vp and export rights by calling nfsvno_fhtovp() 2539 * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon 2540 * for AUTH_SYS 2541 * - if mpp != NULL, return the mount point so that it can 2542 * be used for vn_finished_write() by the caller 2543 */ 2544 void 2545 nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, int lktype, 2546 struct vnode **vpp, struct nfsexstuff *exp, 2547 struct mount **mpp, int startwrite, struct thread *p) 2548 { 2549 struct mount *mp; 2550 struct ucred *credanon; 2551 fhandle_t *fhp; 2552 2553 fhp = (fhandle_t *)nfp->nfsrvfh_data; 2554 /* 2555 * Check for the special case of the nfsv4root_fh. 2556 */ 2557 mp = vfs_busyfs(&fhp->fh_fsid); 2558 if (mpp != NULL) 2559 *mpp = mp; 2560 if (mp == NULL) { 2561 *vpp = NULL; 2562 nd->nd_repstat = ESTALE; 2563 return; 2564 } 2565 2566 if (startwrite) 2567 vn_start_write(NULL, mpp, V_WAIT); 2568 2569 nd->nd_repstat = nfsvno_fhtovp(mp, fhp, nd->nd_nam, lktype, vpp, exp, 2570 &credanon); 2571 vfs_unbusy(mp); 2572 2573 /* 2574 * For NFSv4 without a pseudo root fs, unexported file handles 2575 * can be returned, so that Lookup works everywhere. 2576 */ 2577 if (!nd->nd_repstat && exp->nes_exflag == 0 && 2578 !(nd->nd_flag & ND_NFSV4)) { 2579 vput(*vpp); 2580 nd->nd_repstat = EACCES; 2581 } 2582 2583 /* 2584 * Personally, I've never seen any point in requiring a 2585 * reserved port#, since only in the rare case where the 2586 * clients are all boxes with secure system priviledges, 2587 * does it provide any enhanced security, but... some people 2588 * believe it to be useful and keep putting this code back in. 2589 * (There is also some "security checker" out there that 2590 * complains if the nfs server doesn't enforce this.) 2591 * However, note the following: 2592 * RFC3530 (NFSv4) specifies that a reserved port# not be 2593 * required. 2594 * RFC2623 recommends that, if a reserved port# is checked for, 2595 * that there be a way to turn that off--> ifdef'd. 2596 */ 2597 #ifdef NFS_REQRSVPORT 2598 if (!nd->nd_repstat) { 2599 struct sockaddr_in *saddr; 2600 struct sockaddr_in6 *saddr6; 2601 2602 saddr = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in *); 2603 saddr6 = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in6 *); 2604 if (!(nd->nd_flag & ND_NFSV4) && 2605 ((saddr->sin_family == AF_INET && 2606 ntohs(saddr->sin_port) >= IPPORT_RESERVED) || 2607 (saddr6->sin6_family == AF_INET6 && 2608 ntohs(saddr6->sin6_port) >= IPPORT_RESERVED))) { 2609 vput(*vpp); 2610 nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK); 2611 } 2612 } 2613 #endif /* NFS_REQRSVPORT */ 2614 2615 /* 2616 * Check/setup credentials. 2617 */ 2618 if (!nd->nd_repstat) { 2619 nd->nd_saveduid = nd->nd_cred->cr_uid; 2620 nd->nd_repstat = nfsd_excred(nd, exp, credanon); 2621 if (nd->nd_repstat) 2622 vput(*vpp); 2623 } 2624 if (credanon != NULL) 2625 crfree(credanon); 2626 if (nd->nd_repstat) { 2627 if (startwrite) 2628 vn_finished_write(mp); 2629 *vpp = NULL; 2630 if (mpp != NULL) 2631 *mpp = NULL; 2632 } 2633 } 2634 2635 /* 2636 * glue for fp. 2637 */ 2638 int 2639 fp_getfvp(struct thread *p, int fd, struct file **fpp, struct vnode **vpp) 2640 { 2641 struct filedesc *fdp; 2642 struct file *fp; 2643 2644 fdp = p->td_proc->p_fd; 2645 if (fd >= fdp->fd_nfiles || 2646 (fp = fdp->fd_ofiles[fd]) == NULL) 2647 return (EBADF); 2648 *fpp = fp; 2649 return (0); 2650 } 2651 2652 /* 2653 * Called from nfssvc() to update the exports list. Just call 2654 * vfs_export(). This has to be done, since the v4 root fake fs isn't 2655 * in the mount list. 2656 */ 2657 int 2658 nfsrv_v4rootexport(void *argp, struct ucred *cred, struct thread *p) 2659 { 2660 struct nfsex_args *nfsexargp = (struct nfsex_args *)argp; 2661 int error; 2662 struct nameidata nd; 2663 fhandle_t fh; 2664 2665 error = vfs_export(&nfsv4root_mnt, &nfsexargp->export); 2666 if ((nfsexargp->export.ex_flags & MNT_DELEXPORT) != 0) 2667 nfs_rootfhset = 0; 2668 else if (error == 0) { 2669 if (nfsexargp->fspec == NULL) 2670 return (EPERM); 2671 /* 2672 * If fspec != NULL, this is the v4root path. 2673 */ 2674 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_USERSPACE, 2675 nfsexargp->fspec, p); 2676 if ((error = namei(&nd)) != 0) 2677 return (error); 2678 error = nfsvno_getfh(nd.ni_vp, &fh, p); 2679 vrele(nd.ni_vp); 2680 if (!error) { 2681 nfs_rootfh.nfsrvfh_len = NFSX_MYFH; 2682 NFSBCOPY((caddr_t)&fh, 2683 nfs_rootfh.nfsrvfh_data, 2684 sizeof (fhandle_t)); 2685 nfs_rootfhset = 1; 2686 } 2687 } 2688 return (error); 2689 } 2690 2691 /* 2692 * Get the tcp socket sequence numbers we need. 2693 * (Maybe this should be moved to the tcp sources?) 2694 */ 2695 int 2696 nfsrv_getsocksndseq(struct socket *so, tcp_seq *maxp, tcp_seq *unap) 2697 { 2698 struct inpcb *inp; 2699 struct tcpcb *tp; 2700 2701 inp = sotoinpcb(so); 2702 KASSERT(inp != NULL, ("nfsrv_getsocksndseq: inp == NULL")); 2703 INP_RLOCK(inp); 2704 if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { 2705 INP_RUNLOCK(inp); 2706 return (EPIPE); 2707 } 2708 tp = intotcpcb(inp); 2709 if (tp->t_state != TCPS_ESTABLISHED) { 2710 INP_RUNLOCK(inp); 2711 return (EPIPE); 2712 } 2713 *maxp = tp->snd_max; 2714 *unap = tp->snd_una; 2715 INP_RUNLOCK(inp); 2716 return (0); 2717 } 2718 2719 /* 2720 * This function needs to test to see if the system is near its limit 2721 * for memory allocation via malloc() or mget() and return True iff 2722 * either of these resources are near their limit. 2723 * XXX (For now, this is just a stub.) 2724 */ 2725 int nfsrv_testmalloclimit = 0; 2726 int 2727 nfsrv_mallocmget_limit(void) 2728 { 2729 static int printmesg = 0; 2730 static int testval = 1; 2731 2732 if (nfsrv_testmalloclimit && (testval++ % 1000) == 0) { 2733 if ((printmesg++ % 100) == 0) 2734 printf("nfsd: malloc/mget near limit\n"); 2735 return (1); 2736 } 2737 return (0); 2738 } 2739 2740 /* 2741 * BSD specific initialization of a mount point. 2742 */ 2743 void 2744 nfsd_mntinit(void) 2745 { 2746 static int inited = 0; 2747 2748 if (inited) 2749 return; 2750 inited = 1; 2751 nfsv4root_mnt.mnt_flag = (MNT_RDONLY | MNT_EXPORTED); 2752 TAILQ_INIT(&nfsv4root_mnt.mnt_nvnodelist); 2753 nfsv4root_mnt.mnt_export = NULL; 2754 TAILQ_INIT(&nfsv4root_opt); 2755 TAILQ_INIT(&nfsv4root_newopt); 2756 nfsv4root_mnt.mnt_opt = &nfsv4root_opt; 2757 nfsv4root_mnt.mnt_optnew = &nfsv4root_newopt; 2758 nfsv4root_mnt.mnt_nvnodelistsize = 0; 2759 } 2760 2761 /* 2762 * Get a vnode for a file handle, without checking exports, etc. 2763 */ 2764 struct vnode * 2765 nfsvno_getvp(fhandle_t *fhp) 2766 { 2767 struct mount *mp; 2768 struct vnode *vp; 2769 int error; 2770 2771 mp = vfs_busyfs(&fhp->fh_fsid); 2772 if (mp == NULL) 2773 return (NULL); 2774 error = VFS_FHTOVP(mp, &fhp->fh_fid, &vp); 2775 vfs_unbusy(mp); 2776 if (error) 2777 return (NULL); 2778 return (vp); 2779 } 2780 2781 /* 2782 * Do a local VOP_ADVLOCK(). 2783 */ 2784 int 2785 nfsvno_advlock(struct vnode *vp, int ftype, u_int64_t first, 2786 u_int64_t end, struct thread *td) 2787 { 2788 int error; 2789 struct flock fl; 2790 u_int64_t tlen; 2791 2792 if (nfsrv_dolocallocks == 0) 2793 return (0); 2794 2795 /* Check for VI_DOOMED here, so that VOP_ADVLOCK() isn't performed. */ 2796 if ((vp->v_iflag & VI_DOOMED) != 0) 2797 return (EPERM); 2798 2799 fl.l_whence = SEEK_SET; 2800 fl.l_type = ftype; 2801 fl.l_start = (off_t)first; 2802 if (end == NFS64BITSSET) { 2803 fl.l_len = 0; 2804 } else { 2805 tlen = end - first; 2806 fl.l_len = (off_t)tlen; 2807 } 2808 /* 2809 * For FreeBSD8, the l_pid and l_sysid must be set to the same 2810 * values for all calls, so that all locks will be held by the 2811 * nfsd server. (The nfsd server handles conflicts between the 2812 * various clients.) 2813 * Since an NFSv4 lockowner is a ClientID plus an array of up to 1024 2814 * bytes, so it can't be put in l_sysid. 2815 */ 2816 if (nfsv4_sysid == 0) 2817 nfsv4_sysid = nlm_acquire_next_sysid(); 2818 fl.l_pid = (pid_t)0; 2819 fl.l_sysid = (int)nfsv4_sysid; 2820 2821 NFSVOPUNLOCK(vp, 0, td); 2822 if (ftype == F_UNLCK) 2823 error = VOP_ADVLOCK(vp, (caddr_t)td->td_proc, F_UNLCK, &fl, 2824 (F_POSIX | F_REMOTE)); 2825 else 2826 error = VOP_ADVLOCK(vp, (caddr_t)td->td_proc, F_SETLK, &fl, 2827 (F_POSIX | F_REMOTE)); 2828 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, td); 2829 return (error); 2830 } 2831 2832 /* 2833 * Check the nfsv4 root exports. 2834 */ 2835 int 2836 nfsvno_v4rootexport(struct nfsrv_descript *nd) 2837 { 2838 struct ucred *credanon; 2839 int exflags, error, numsecflavor, *secflavors, i; 2840 2841 error = vfs_stdcheckexp(&nfsv4root_mnt, nd->nd_nam, &exflags, 2842 &credanon, &numsecflavor, &secflavors); 2843 if (error) 2844 return (NFSERR_PROGUNAVAIL); 2845 if (credanon != NULL) 2846 crfree(credanon); 2847 for (i = 0; i < numsecflavor; i++) { 2848 if (secflavors[i] == AUTH_SYS) 2849 nd->nd_flag |= ND_EXAUTHSYS; 2850 else if (secflavors[i] == RPCSEC_GSS_KRB5) 2851 nd->nd_flag |= ND_EXGSS; 2852 else if (secflavors[i] == RPCSEC_GSS_KRB5I) 2853 nd->nd_flag |= ND_EXGSSINTEGRITY; 2854 else if (secflavors[i] == RPCSEC_GSS_KRB5P) 2855 nd->nd_flag |= ND_EXGSSPRIVACY; 2856 } 2857 return (0); 2858 } 2859 2860 /* 2861 * Nfs server psuedo system call for the nfsd's 2862 */ 2863 /* 2864 * MPSAFE 2865 */ 2866 static int 2867 nfssvc_nfsd(struct thread *td, struct nfssvc_args *uap) 2868 { 2869 struct file *fp; 2870 struct nfsd_addsock_args sockarg; 2871 struct nfsd_nfsd_args nfsdarg; 2872 int error; 2873 2874 if (uap->flag & NFSSVC_NFSDADDSOCK) { 2875 error = copyin(uap->argp, (caddr_t)&sockarg, sizeof (sockarg)); 2876 if (error) 2877 return (error); 2878 if ((error = fget(td, sockarg.sock, &fp)) != 0) { 2879 return (error); 2880 } 2881 if (fp->f_type != DTYPE_SOCKET) { 2882 fdrop(fp, td); 2883 return (EPERM); 2884 } 2885 error = nfsrvd_addsock(fp); 2886 fdrop(fp, td); 2887 } else if (uap->flag & NFSSVC_NFSDNFSD) { 2888 if (uap->argp == NULL) 2889 return (EINVAL); 2890 error = copyin(uap->argp, (caddr_t)&nfsdarg, 2891 sizeof (nfsdarg)); 2892 if (error) 2893 return (error); 2894 error = nfsrvd_nfsd(td, &nfsdarg); 2895 } else { 2896 error = nfssvc_srvcall(td, uap, td->td_ucred); 2897 } 2898 return (error); 2899 } 2900 2901 static int 2902 nfssvc_srvcall(struct thread *p, struct nfssvc_args *uap, struct ucred *cred) 2903 { 2904 struct nfsex_args export; 2905 struct file *fp = NULL; 2906 int stablefd, len; 2907 struct nfsd_clid adminrevoke; 2908 struct nfsd_dumplist dumplist; 2909 struct nfsd_dumpclients *dumpclients; 2910 struct nfsd_dumplocklist dumplocklist; 2911 struct nfsd_dumplocks *dumplocks; 2912 struct nameidata nd; 2913 vnode_t vp; 2914 int error = EINVAL; 2915 struct proc *procp; 2916 2917 if (uap->flag & NFSSVC_PUBLICFH) { 2918 NFSBZERO((caddr_t)&nfs_pubfh.nfsrvfh_data, 2919 sizeof (fhandle_t)); 2920 error = copyin(uap->argp, 2921 &nfs_pubfh.nfsrvfh_data, sizeof (fhandle_t)); 2922 if (!error) 2923 nfs_pubfhset = 1; 2924 } else if (uap->flag & NFSSVC_V4ROOTEXPORT) { 2925 error = copyin(uap->argp,(caddr_t)&export, 2926 sizeof (struct nfsex_args)); 2927 if (!error) 2928 error = nfsrv_v4rootexport(&export, cred, p); 2929 } else if (uap->flag & NFSSVC_NOPUBLICFH) { 2930 nfs_pubfhset = 0; 2931 error = 0; 2932 } else if (uap->flag & NFSSVC_STABLERESTART) { 2933 error = copyin(uap->argp, (caddr_t)&stablefd, 2934 sizeof (int)); 2935 if (!error) 2936 error = fp_getfvp(p, stablefd, &fp, &vp); 2937 if (!error && (NFSFPFLAG(fp) & (FREAD | FWRITE)) != (FREAD | FWRITE)) 2938 error = EBADF; 2939 if (!error && newnfs_numnfsd != 0) 2940 error = EPERM; 2941 if (!error) { 2942 nfsrv_stablefirst.nsf_fp = fp; 2943 nfsrv_setupstable(p); 2944 } 2945 } else if (uap->flag & NFSSVC_ADMINREVOKE) { 2946 error = copyin(uap->argp, (caddr_t)&adminrevoke, 2947 sizeof (struct nfsd_clid)); 2948 if (!error) 2949 error = nfsrv_adminrevoke(&adminrevoke, p); 2950 } else if (uap->flag & NFSSVC_DUMPCLIENTS) { 2951 error = copyin(uap->argp, (caddr_t)&dumplist, 2952 sizeof (struct nfsd_dumplist)); 2953 if (!error && (dumplist.ndl_size < 1 || 2954 dumplist.ndl_size > NFSRV_MAXDUMPLIST)) 2955 error = EPERM; 2956 if (!error) { 2957 len = sizeof (struct nfsd_dumpclients) * dumplist.ndl_size; 2958 dumpclients = (struct nfsd_dumpclients *)malloc(len, 2959 M_TEMP, M_WAITOK); 2960 nfsrv_dumpclients(dumpclients, dumplist.ndl_size); 2961 error = copyout(dumpclients, 2962 CAST_USER_ADDR_T(dumplist.ndl_list), len); 2963 free((caddr_t)dumpclients, M_TEMP); 2964 } 2965 } else if (uap->flag & NFSSVC_DUMPLOCKS) { 2966 error = copyin(uap->argp, (caddr_t)&dumplocklist, 2967 sizeof (struct nfsd_dumplocklist)); 2968 if (!error && (dumplocklist.ndllck_size < 1 || 2969 dumplocklist.ndllck_size > NFSRV_MAXDUMPLIST)) 2970 error = EPERM; 2971 if (!error) 2972 error = nfsrv_lookupfilename(&nd, 2973 dumplocklist.ndllck_fname, p); 2974 if (!error) { 2975 len = sizeof (struct nfsd_dumplocks) * 2976 dumplocklist.ndllck_size; 2977 dumplocks = (struct nfsd_dumplocks *)malloc(len, 2978 M_TEMP, M_WAITOK); 2979 nfsrv_dumplocks(nd.ni_vp, dumplocks, 2980 dumplocklist.ndllck_size, p); 2981 vput(nd.ni_vp); 2982 error = copyout(dumplocks, 2983 CAST_USER_ADDR_T(dumplocklist.ndllck_list), len); 2984 free((caddr_t)dumplocks, M_TEMP); 2985 } 2986 } else if (uap->flag & NFSSVC_BACKUPSTABLE) { 2987 procp = p->td_proc; 2988 PROC_LOCK(procp); 2989 nfsd_master_pid = procp->p_pid; 2990 bcopy(procp->p_comm, nfsd_master_comm, MAXCOMLEN + 1); 2991 nfsd_master_start = procp->p_stats->p_start; 2992 nfsd_master_proc = procp; 2993 PROC_UNLOCK(procp); 2994 } 2995 return (error); 2996 } 2997 2998 /* 2999 * Check exports. 3000 * Returns 0 if ok, 1 otherwise. 3001 */ 3002 int 3003 nfsvno_testexp(struct nfsrv_descript *nd, struct nfsexstuff *exp) 3004 { 3005 int i; 3006 3007 /* 3008 * This seems odd, but allow the case where the security flavor 3009 * list is empty. This happens when NFSv4 is traversing non-exported 3010 * file systems. Exported file systems should always have a non-empty 3011 * security flavor list. 3012 */ 3013 if (exp->nes_numsecflavor == 0) 3014 return (0); 3015 3016 for (i = 0; i < exp->nes_numsecflavor; i++) { 3017 /* 3018 * The tests for privacy and integrity must be first, 3019 * since ND_GSS is set for everything but AUTH_SYS. 3020 */ 3021 if (exp->nes_secflavors[i] == RPCSEC_GSS_KRB5P && 3022 (nd->nd_flag & ND_GSSPRIVACY)) 3023 return (0); 3024 if (exp->nes_secflavors[i] == RPCSEC_GSS_KRB5I && 3025 (nd->nd_flag & ND_GSSINTEGRITY)) 3026 return (0); 3027 if (exp->nes_secflavors[i] == RPCSEC_GSS_KRB5 && 3028 (nd->nd_flag & ND_GSS)) 3029 return (0); 3030 if (exp->nes_secflavors[i] == AUTH_SYS && 3031 (nd->nd_flag & ND_GSS) == 0) 3032 return (0); 3033 } 3034 return (1); 3035 } 3036 3037 /* 3038 * Calculate a hash value for the fid in a file handle. 3039 */ 3040 uint32_t 3041 nfsrv_hashfh(fhandle_t *fhp) 3042 { 3043 uint32_t hashval; 3044 3045 hashval = hash32_buf(&fhp->fh_fid, sizeof(struct fid), 0); 3046 return (hashval); 3047 } 3048 3049 /* 3050 * Signal the userland master nfsd to backup the stable restart file. 3051 */ 3052 void 3053 nfsrv_backupstable(void) 3054 { 3055 struct proc *procp; 3056 3057 if (nfsd_master_proc != NULL) { 3058 procp = pfind(nfsd_master_pid); 3059 /* Try to make sure it is the correct process. */ 3060 if (procp == nfsd_master_proc && 3061 procp->p_stats->p_start.tv_sec == 3062 nfsd_master_start.tv_sec && 3063 procp->p_stats->p_start.tv_usec == 3064 nfsd_master_start.tv_usec && 3065 strcmp(procp->p_comm, nfsd_master_comm) == 0) 3066 psignal(procp, SIGUSR2); 3067 else 3068 nfsd_master_proc = NULL; 3069 3070 if (procp != NULL) 3071 PROC_UNLOCK(procp); 3072 } 3073 } 3074 3075 extern int (*nfsd_call_nfsd)(struct thread *, struct nfssvc_args *); 3076 3077 /* 3078 * Called once to initialize data structures... 3079 */ 3080 static int 3081 nfsd_modevent(module_t mod, int type, void *data) 3082 { 3083 int error = 0; 3084 static int loaded = 0; 3085 3086 switch (type) { 3087 case MOD_LOAD: 3088 if (loaded) 3089 return (0); 3090 newnfs_portinit(); 3091 mtx_init(&nfs_cache_mutex, "nfs_cache_mutex", NULL, MTX_DEF); 3092 mtx_init(&nfs_v4root_mutex, "nfs_v4root_mutex", NULL, MTX_DEF); 3093 mtx_init(&nfsv4root_mnt.mnt_mtx, "struct mount mtx", NULL, 3094 MTX_DEF); 3095 lockinit(&nfsv4root_mnt.mnt_explock, PVFS, "explock", 0, 0); 3096 nfsrvd_initcache(); 3097 nfsd_init(); 3098 NFSD_LOCK(); 3099 nfsrvd_init(0); 3100 NFSD_UNLOCK(); 3101 nfsd_mntinit(); 3102 #ifdef VV_DISABLEDELEG 3103 vn_deleg_ops.vndeleg_recall = nfsd_recalldelegation; 3104 vn_deleg_ops.vndeleg_disable = nfsd_disabledelegation; 3105 #endif 3106 nfsd_call_servertimer = nfsrv_servertimer; 3107 nfsd_call_nfsd = nfssvc_nfsd; 3108 loaded = 1; 3109 break; 3110 3111 case MOD_UNLOAD: 3112 if (newnfs_numnfsd != 0) { 3113 error = EBUSY; 3114 break; 3115 } 3116 3117 #ifdef VV_DISABLEDELEG 3118 vn_deleg_ops.vndeleg_recall = NULL; 3119 vn_deleg_ops.vndeleg_disable = NULL; 3120 #endif 3121 nfsd_call_servertimer = NULL; 3122 nfsd_call_nfsd = NULL; 3123 3124 /* Clean the NFS server reply cache */ 3125 nfsrvd_cleancache(); 3126 3127 /* and get rid of the locks */ 3128 mtx_destroy(&nfs_cache_mutex); 3129 mtx_destroy(&nfs_v4root_mutex); 3130 mtx_destroy(&nfsv4root_mnt.mnt_mtx); 3131 lockdestroy(&nfsv4root_mnt.mnt_explock); 3132 loaded = 0; 3133 break; 3134 default: 3135 error = EOPNOTSUPP; 3136 break; 3137 } 3138 return error; 3139 } 3140 static moduledata_t nfsd_mod = { 3141 "nfsd", 3142 nfsd_modevent, 3143 NULL, 3144 }; 3145 DECLARE_MODULE(nfsd, nfsd_mod, SI_SUB_VFS, SI_ORDER_ANY); 3146 3147 /* So that loader and kldload(2) can find us, wherever we are.. */ 3148 MODULE_VERSION(nfsd, 1); 3149 MODULE_DEPEND(nfsd, nfscommon, 1, 1, 1); 3150 MODULE_DEPEND(nfsd, nfslock, 1, 1, 1); 3151 MODULE_DEPEND(nfsd, nfslockd, 1, 1, 1); 3152 MODULE_DEPEND(nfsd, krpc, 1, 1, 1); 3153 MODULE_DEPEND(nfsd, nfssvc, 1, 1, 1); 3154 3155