1 /* $NetBSD: nfs_subs.c,v 1.72 1999/11/01 21:32:41 fvdl Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Rick Macklem at The University of Guelph. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95 39 */ 40 41 #include "fs_nfs.h" 42 #include "opt_nfsserver.h" 43 #include "opt_iso.h" 44 45 /* 46 * These functions support the macros and help fiddle mbuf chains for 47 * the nfs op functions. They do things like create the rpc header and 48 * copy data between mbuf chains and uio lists. 49 */ 50 #include <sys/param.h> 51 #include <sys/proc.h> 52 #include <sys/systm.h> 53 #include <sys/kernel.h> 54 #include <sys/mount.h> 55 #include <sys/vnode.h> 56 #include <sys/namei.h> 57 #include <sys/mbuf.h> 58 #include <sys/socket.h> 59 #include <sys/stat.h> 60 #include <sys/malloc.h> 61 #include <sys/time.h> 62 #include <sys/dirent.h> 63 64 #include <vm/vm.h> 65 66 #include <uvm/uvm_extern.h> 67 68 #include <nfs/rpcv2.h> 69 #include <nfs/nfsproto.h> 70 #include <nfs/nfsnode.h> 71 #include <nfs/nfs.h> 72 #include <nfs/xdr_subs.h> 73 #include <nfs/nfsm_subs.h> 74 #include <nfs/nfsmount.h> 75 #include <nfs/nqnfs.h> 76 #include <nfs/nfsrtt.h> 77 #include <nfs/nfs_var.h> 78 79 #include <miscfs/specfs/specdev.h> 80 81 #include <vm/vm.h> 82 83 #include <netinet/in.h> 84 #ifdef ISO 85 #include <netiso/iso.h> 86 #endif 87 88 /* 89 * Data items converted to xdr at startup, since they are constant 90 * This is kinda hokey, but may save a little time doing byte swaps 91 */ 92 u_int32_t nfs_xdrneg1; 93 u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr, 94 rpc_mismatch, rpc_auth_unix, rpc_msgaccepted, 95 rpc_auth_kerb; 96 u_int32_t nfs_prog, nqnfs_prog, nfs_true, nfs_false; 97 98 /* And other global data */ 99 static u_int32_t nfs_xid = 0; 100 nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON, 101 NFCHR, NFNON }; 102 nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK, 103 NFFIFO, NFNON }; 104 enum vtype nv2tov_type[8] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON }; 105 enum vtype nv3tov_type[8]={ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO }; 106 int nfs_ticks; 107 extern struct nfs_public nfs_pub; 108 109 /* NFS client/server stats. */ 110 struct nfsstats nfsstats; 111 112 /* 113 * Mapping of old NFS Version 2 RPC numbers to generic numbers. 114 */ 115 int nfsv3_procid[NFS_NPROCS] = { 116 NFSPROC_NULL, 117 NFSPROC_GETATTR, 118 NFSPROC_SETATTR, 119 NFSPROC_NOOP, 120 NFSPROC_LOOKUP, 121 NFSPROC_READLINK, 122 NFSPROC_READ, 123 NFSPROC_NOOP, 124 NFSPROC_WRITE, 125 NFSPROC_CREATE, 126 NFSPROC_REMOVE, 127 NFSPROC_RENAME, 128 NFSPROC_LINK, 129 NFSPROC_SYMLINK, 130 NFSPROC_MKDIR, 131 NFSPROC_RMDIR, 132 NFSPROC_READDIR, 133 NFSPROC_FSSTAT, 134 NFSPROC_NOOP, 135 NFSPROC_NOOP, 136 NFSPROC_NOOP, 137 NFSPROC_NOOP, 138 NFSPROC_NOOP, 139 NFSPROC_NOOP, 140 NFSPROC_NOOP, 141 NFSPROC_NOOP 142 }; 143 144 /* 145 * and the reverse mapping from generic to Version 2 procedure numbers 146 */ 147 int nfsv2_procid[NFS_NPROCS] = { 148 NFSV2PROC_NULL, 149 NFSV2PROC_GETATTR, 150 NFSV2PROC_SETATTR, 151 NFSV2PROC_LOOKUP, 152 NFSV2PROC_NOOP, 153 NFSV2PROC_READLINK, 154 NFSV2PROC_READ, 155 NFSV2PROC_WRITE, 156 NFSV2PROC_CREATE, 157 NFSV2PROC_MKDIR, 158 NFSV2PROC_SYMLINK, 159 NFSV2PROC_CREATE, 160 NFSV2PROC_REMOVE, 161 NFSV2PROC_RMDIR, 162 NFSV2PROC_RENAME, 163 NFSV2PROC_LINK, 164 NFSV2PROC_READDIR, 165 NFSV2PROC_NOOP, 166 NFSV2PROC_STATFS, 167 NFSV2PROC_NOOP, 168 NFSV2PROC_NOOP, 169 NFSV2PROC_NOOP, 170 NFSV2PROC_NOOP, 171 NFSV2PROC_NOOP, 172 NFSV2PROC_NOOP, 173 NFSV2PROC_NOOP, 174 }; 175 176 /* 177 * Maps errno values to nfs error numbers. 178 * Use NFSERR_IO as the catch all for ones not specifically defined in 179 * RFC 1094. 180 */ 181 static u_char nfsrv_v2errmap[ELAST] = { 182 NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO, 183 NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 184 NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO, 185 NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR, 186 NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 187 NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS, 188 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 189 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 190 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 191 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 192 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 193 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 194 NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO, 195 NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE, 196 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 197 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 198 NFSERR_IO, NFSERR_IO, 199 }; 200 201 /* 202 * Maps errno values to nfs error numbers. 203 * Although it is not obvious whether or not NFS clients really care if 204 * a returned error value is in the specified list for the procedure, the 205 * safest thing to do is filter them appropriately. For Version 2, the 206 * X/Open XNFS document is the only specification that defines error values 207 * for each RPC (The RFC simply lists all possible error values for all RPCs), 208 * so I have decided to not do this for Version 2. 209 * The first entry is the default error return and the rest are the valid 210 * errors for that RPC in increasing numeric order. 211 */ 212 static short nfsv3err_null[] = { 213 0, 214 0, 215 }; 216 217 static short nfsv3err_getattr[] = { 218 NFSERR_IO, 219 NFSERR_IO, 220 NFSERR_STALE, 221 NFSERR_BADHANDLE, 222 NFSERR_SERVERFAULT, 223 0, 224 }; 225 226 static short nfsv3err_setattr[] = { 227 NFSERR_IO, 228 NFSERR_PERM, 229 NFSERR_IO, 230 NFSERR_ACCES, 231 NFSERR_INVAL, 232 NFSERR_NOSPC, 233 NFSERR_ROFS, 234 NFSERR_DQUOT, 235 NFSERR_STALE, 236 NFSERR_BADHANDLE, 237 NFSERR_NOT_SYNC, 238 NFSERR_SERVERFAULT, 239 0, 240 }; 241 242 static short nfsv3err_lookup[] = { 243 NFSERR_IO, 244 NFSERR_NOENT, 245 NFSERR_IO, 246 NFSERR_ACCES, 247 NFSERR_NOTDIR, 248 NFSERR_NAMETOL, 249 NFSERR_STALE, 250 NFSERR_BADHANDLE, 251 NFSERR_SERVERFAULT, 252 0, 253 }; 254 255 static short nfsv3err_access[] = { 256 NFSERR_IO, 257 NFSERR_IO, 258 NFSERR_STALE, 259 NFSERR_BADHANDLE, 260 NFSERR_SERVERFAULT, 261 0, 262 }; 263 264 static short nfsv3err_readlink[] = { 265 NFSERR_IO, 266 NFSERR_IO, 267 NFSERR_ACCES, 268 NFSERR_INVAL, 269 NFSERR_STALE, 270 NFSERR_BADHANDLE, 271 NFSERR_NOTSUPP, 272 NFSERR_SERVERFAULT, 273 0, 274 }; 275 276 static short nfsv3err_read[] = { 277 NFSERR_IO, 278 NFSERR_IO, 279 NFSERR_NXIO, 280 NFSERR_ACCES, 281 NFSERR_INVAL, 282 NFSERR_STALE, 283 NFSERR_BADHANDLE, 284 NFSERR_SERVERFAULT, 285 NFSERR_JUKEBOX, 286 0, 287 }; 288 289 static short nfsv3err_write[] = { 290 NFSERR_IO, 291 NFSERR_IO, 292 NFSERR_ACCES, 293 NFSERR_INVAL, 294 NFSERR_FBIG, 295 NFSERR_NOSPC, 296 NFSERR_ROFS, 297 NFSERR_DQUOT, 298 NFSERR_STALE, 299 NFSERR_BADHANDLE, 300 NFSERR_SERVERFAULT, 301 NFSERR_JUKEBOX, 302 0, 303 }; 304 305 static short nfsv3err_create[] = { 306 NFSERR_IO, 307 NFSERR_IO, 308 NFSERR_ACCES, 309 NFSERR_EXIST, 310 NFSERR_NOTDIR, 311 NFSERR_NOSPC, 312 NFSERR_ROFS, 313 NFSERR_NAMETOL, 314 NFSERR_DQUOT, 315 NFSERR_STALE, 316 NFSERR_BADHANDLE, 317 NFSERR_NOTSUPP, 318 NFSERR_SERVERFAULT, 319 0, 320 }; 321 322 static short nfsv3err_mkdir[] = { 323 NFSERR_IO, 324 NFSERR_IO, 325 NFSERR_ACCES, 326 NFSERR_EXIST, 327 NFSERR_NOTDIR, 328 NFSERR_NOSPC, 329 NFSERR_ROFS, 330 NFSERR_NAMETOL, 331 NFSERR_DQUOT, 332 NFSERR_STALE, 333 NFSERR_BADHANDLE, 334 NFSERR_NOTSUPP, 335 NFSERR_SERVERFAULT, 336 0, 337 }; 338 339 static short nfsv3err_symlink[] = { 340 NFSERR_IO, 341 NFSERR_IO, 342 NFSERR_ACCES, 343 NFSERR_EXIST, 344 NFSERR_NOTDIR, 345 NFSERR_NOSPC, 346 NFSERR_ROFS, 347 NFSERR_NAMETOL, 348 NFSERR_DQUOT, 349 NFSERR_STALE, 350 NFSERR_BADHANDLE, 351 NFSERR_NOTSUPP, 352 NFSERR_SERVERFAULT, 353 0, 354 }; 355 356 static short nfsv3err_mknod[] = { 357 NFSERR_IO, 358 NFSERR_IO, 359 NFSERR_ACCES, 360 NFSERR_EXIST, 361 NFSERR_NOTDIR, 362 NFSERR_NOSPC, 363 NFSERR_ROFS, 364 NFSERR_NAMETOL, 365 NFSERR_DQUOT, 366 NFSERR_STALE, 367 NFSERR_BADHANDLE, 368 NFSERR_NOTSUPP, 369 NFSERR_SERVERFAULT, 370 NFSERR_BADTYPE, 371 0, 372 }; 373 374 static short nfsv3err_remove[] = { 375 NFSERR_IO, 376 NFSERR_NOENT, 377 NFSERR_IO, 378 NFSERR_ACCES, 379 NFSERR_NOTDIR, 380 NFSERR_ROFS, 381 NFSERR_NAMETOL, 382 NFSERR_STALE, 383 NFSERR_BADHANDLE, 384 NFSERR_SERVERFAULT, 385 0, 386 }; 387 388 static short nfsv3err_rmdir[] = { 389 NFSERR_IO, 390 NFSERR_NOENT, 391 NFSERR_IO, 392 NFSERR_ACCES, 393 NFSERR_EXIST, 394 NFSERR_NOTDIR, 395 NFSERR_INVAL, 396 NFSERR_ROFS, 397 NFSERR_NAMETOL, 398 NFSERR_NOTEMPTY, 399 NFSERR_STALE, 400 NFSERR_BADHANDLE, 401 NFSERR_NOTSUPP, 402 NFSERR_SERVERFAULT, 403 0, 404 }; 405 406 static short nfsv3err_rename[] = { 407 NFSERR_IO, 408 NFSERR_NOENT, 409 NFSERR_IO, 410 NFSERR_ACCES, 411 NFSERR_EXIST, 412 NFSERR_XDEV, 413 NFSERR_NOTDIR, 414 NFSERR_ISDIR, 415 NFSERR_INVAL, 416 NFSERR_NOSPC, 417 NFSERR_ROFS, 418 NFSERR_MLINK, 419 NFSERR_NAMETOL, 420 NFSERR_NOTEMPTY, 421 NFSERR_DQUOT, 422 NFSERR_STALE, 423 NFSERR_BADHANDLE, 424 NFSERR_NOTSUPP, 425 NFSERR_SERVERFAULT, 426 0, 427 }; 428 429 static short nfsv3err_link[] = { 430 NFSERR_IO, 431 NFSERR_IO, 432 NFSERR_ACCES, 433 NFSERR_EXIST, 434 NFSERR_XDEV, 435 NFSERR_NOTDIR, 436 NFSERR_INVAL, 437 NFSERR_NOSPC, 438 NFSERR_ROFS, 439 NFSERR_MLINK, 440 NFSERR_NAMETOL, 441 NFSERR_DQUOT, 442 NFSERR_STALE, 443 NFSERR_BADHANDLE, 444 NFSERR_NOTSUPP, 445 NFSERR_SERVERFAULT, 446 0, 447 }; 448 449 static short nfsv3err_readdir[] = { 450 NFSERR_IO, 451 NFSERR_IO, 452 NFSERR_ACCES, 453 NFSERR_NOTDIR, 454 NFSERR_STALE, 455 NFSERR_BADHANDLE, 456 NFSERR_BAD_COOKIE, 457 NFSERR_TOOSMALL, 458 NFSERR_SERVERFAULT, 459 0, 460 }; 461 462 static short nfsv3err_readdirplus[] = { 463 NFSERR_IO, 464 NFSERR_IO, 465 NFSERR_ACCES, 466 NFSERR_NOTDIR, 467 NFSERR_STALE, 468 NFSERR_BADHANDLE, 469 NFSERR_BAD_COOKIE, 470 NFSERR_NOTSUPP, 471 NFSERR_TOOSMALL, 472 NFSERR_SERVERFAULT, 473 0, 474 }; 475 476 static short nfsv3err_fsstat[] = { 477 NFSERR_IO, 478 NFSERR_IO, 479 NFSERR_STALE, 480 NFSERR_BADHANDLE, 481 NFSERR_SERVERFAULT, 482 0, 483 }; 484 485 static short nfsv3err_fsinfo[] = { 486 NFSERR_STALE, 487 NFSERR_STALE, 488 NFSERR_BADHANDLE, 489 NFSERR_SERVERFAULT, 490 0, 491 }; 492 493 static short nfsv3err_pathconf[] = { 494 NFSERR_STALE, 495 NFSERR_STALE, 496 NFSERR_BADHANDLE, 497 NFSERR_SERVERFAULT, 498 0, 499 }; 500 501 static short nfsv3err_commit[] = { 502 NFSERR_IO, 503 NFSERR_IO, 504 NFSERR_STALE, 505 NFSERR_BADHANDLE, 506 NFSERR_SERVERFAULT, 507 0, 508 }; 509 510 static short *nfsrv_v3errmap[] = { 511 nfsv3err_null, 512 nfsv3err_getattr, 513 nfsv3err_setattr, 514 nfsv3err_lookup, 515 nfsv3err_access, 516 nfsv3err_readlink, 517 nfsv3err_read, 518 nfsv3err_write, 519 nfsv3err_create, 520 nfsv3err_mkdir, 521 nfsv3err_symlink, 522 nfsv3err_mknod, 523 nfsv3err_remove, 524 nfsv3err_rmdir, 525 nfsv3err_rename, 526 nfsv3err_link, 527 nfsv3err_readdir, 528 nfsv3err_readdirplus, 529 nfsv3err_fsstat, 530 nfsv3err_fsinfo, 531 nfsv3err_pathconf, 532 nfsv3err_commit, 533 }; 534 535 extern struct nfsrtt nfsrtt; 536 extern time_t nqnfsstarttime; 537 extern int nqsrv_clockskew; 538 extern int nqsrv_writeslack; 539 extern int nqsrv_maxlease; 540 extern int nqnfs_piggy[NFS_NPROCS]; 541 extern nfstype nfsv2_type[9]; 542 extern nfstype nfsv3_type[9]; 543 extern struct nfsnodehashhead *nfsnodehashtbl; 544 extern u_long nfsnodehash; 545 546 LIST_HEAD(nfsnodehashhead, nfsnode); 547 u_long nfsdirhashmask; 548 549 int nfs_webnamei __P((struct nameidata *, struct vnode *, struct proc *)); 550 551 /* 552 * Create the header for an rpc request packet 553 * The hsiz is the size of the rest of the nfs request header. 554 * (just used to decide if a cluster is a good idea) 555 */ 556 struct mbuf * 557 nfsm_reqh(vp, procid, hsiz, bposp) 558 struct vnode *vp; 559 u_long procid; 560 int hsiz; 561 caddr_t *bposp; 562 { 563 register struct mbuf *mb; 564 register u_int32_t *tl; 565 register caddr_t bpos; 566 struct mbuf *mb2; 567 struct nfsmount *nmp; 568 int nqflag; 569 570 MGET(mb, M_WAIT, MT_DATA); 571 if (hsiz >= MINCLSIZE) 572 MCLGET(mb, M_WAIT); 573 mb->m_len = 0; 574 bpos = mtod(mb, caddr_t); 575 576 /* 577 * For NQNFS, add lease request. 578 */ 579 if (vp) { 580 nmp = VFSTONFS(vp->v_mount); 581 if (nmp->nm_flag & NFSMNT_NQNFS) { 582 nqflag = NQNFS_NEEDLEASE(vp, procid); 583 if (nqflag) { 584 nfsm_build(tl, u_int32_t *, 2*NFSX_UNSIGNED); 585 *tl++ = txdr_unsigned(nqflag); 586 *tl = txdr_unsigned(nmp->nm_leaseterm); 587 } else { 588 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); 589 *tl = 0; 590 } 591 } 592 } 593 /* Finally, return values */ 594 *bposp = bpos; 595 return (mb); 596 } 597 598 /* 599 * Build the RPC header and fill in the authorization info. 600 * The authorization string argument is only used when the credentials 601 * come from outside of the kernel. 602 * Returns the head of the mbuf list. 603 */ 604 struct mbuf * 605 nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len, 606 verf_str, mrest, mrest_len, mbp, xidp) 607 register struct ucred *cr; 608 int nmflag; 609 int procid; 610 int auth_type; 611 int auth_len; 612 char *auth_str; 613 int verf_len; 614 char *verf_str; 615 struct mbuf *mrest; 616 int mrest_len; 617 struct mbuf **mbp; 618 u_int32_t *xidp; 619 { 620 register struct mbuf *mb; 621 register u_int32_t *tl; 622 register caddr_t bpos; 623 register int i; 624 struct mbuf *mreq, *mb2; 625 int siz, grpsiz, authsiz; 626 struct timeval tv; 627 static u_int32_t base; 628 629 authsiz = nfsm_rndup(auth_len); 630 MGETHDR(mb, M_WAIT, MT_DATA); 631 if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) { 632 MCLGET(mb, M_WAIT); 633 } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) { 634 MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED); 635 } else { 636 MH_ALIGN(mb, 8 * NFSX_UNSIGNED); 637 } 638 mb->m_len = 0; 639 mreq = mb; 640 bpos = mtod(mb, caddr_t); 641 642 /* 643 * First the RPC header. 644 */ 645 nfsm_build(tl, u_int32_t *, 8 * NFSX_UNSIGNED); 646 647 /* 648 * derive initial xid from system time 649 * XXX time is invalid if root not yet mounted 650 */ 651 if (!base && (rootvp)) { 652 microtime(&tv); 653 base = tv.tv_sec << 12; 654 nfs_xid = base; 655 } 656 /* 657 * Skip zero xid if it should ever happen. 658 */ 659 if (++nfs_xid == 0) 660 nfs_xid++; 661 662 *tl++ = *xidp = txdr_unsigned(nfs_xid); 663 *tl++ = rpc_call; 664 *tl++ = rpc_vers; 665 if (nmflag & NFSMNT_NQNFS) { 666 *tl++ = txdr_unsigned(NQNFS_PROG); 667 *tl++ = txdr_unsigned(NQNFS_VER3); 668 } else { 669 *tl++ = txdr_unsigned(NFS_PROG); 670 if (nmflag & NFSMNT_NFSV3) 671 *tl++ = txdr_unsigned(NFS_VER3); 672 else 673 *tl++ = txdr_unsigned(NFS_VER2); 674 } 675 if (nmflag & NFSMNT_NFSV3) 676 *tl++ = txdr_unsigned(procid); 677 else 678 *tl++ = txdr_unsigned(nfsv2_procid[procid]); 679 680 /* 681 * And then the authorization cred. 682 */ 683 *tl++ = txdr_unsigned(auth_type); 684 *tl = txdr_unsigned(authsiz); 685 switch (auth_type) { 686 case RPCAUTH_UNIX: 687 nfsm_build(tl, u_int32_t *, auth_len); 688 *tl++ = 0; /* stamp ?? */ 689 *tl++ = 0; /* NULL hostname */ 690 *tl++ = txdr_unsigned(cr->cr_uid); 691 *tl++ = txdr_unsigned(cr->cr_gid); 692 grpsiz = (auth_len >> 2) - 5; 693 *tl++ = txdr_unsigned(grpsiz); 694 for (i = 0; i < grpsiz; i++) 695 *tl++ = txdr_unsigned(cr->cr_groups[i]); 696 break; 697 case RPCAUTH_KERB4: 698 siz = auth_len; 699 while (siz > 0) { 700 if (M_TRAILINGSPACE(mb) == 0) { 701 MGET(mb2, M_WAIT, MT_DATA); 702 if (siz >= MINCLSIZE) 703 MCLGET(mb2, M_WAIT); 704 mb->m_next = mb2; 705 mb = mb2; 706 mb->m_len = 0; 707 bpos = mtod(mb, caddr_t); 708 } 709 i = min(siz, M_TRAILINGSPACE(mb)); 710 memcpy(bpos, auth_str, i); 711 mb->m_len += i; 712 auth_str += i; 713 bpos += i; 714 siz -= i; 715 } 716 if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) { 717 for (i = 0; i < siz; i++) 718 *bpos++ = '\0'; 719 mb->m_len += siz; 720 } 721 break; 722 }; 723 724 /* 725 * And the verifier... 726 */ 727 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 728 if (verf_str) { 729 *tl++ = txdr_unsigned(RPCAUTH_KERB4); 730 *tl = txdr_unsigned(verf_len); 731 siz = verf_len; 732 while (siz > 0) { 733 if (M_TRAILINGSPACE(mb) == 0) { 734 MGET(mb2, M_WAIT, MT_DATA); 735 if (siz >= MINCLSIZE) 736 MCLGET(mb2, M_WAIT); 737 mb->m_next = mb2; 738 mb = mb2; 739 mb->m_len = 0; 740 bpos = mtod(mb, caddr_t); 741 } 742 i = min(siz, M_TRAILINGSPACE(mb)); 743 memcpy(bpos, verf_str, i); 744 mb->m_len += i; 745 verf_str += i; 746 bpos += i; 747 siz -= i; 748 } 749 if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) { 750 for (i = 0; i < siz; i++) 751 *bpos++ = '\0'; 752 mb->m_len += siz; 753 } 754 } else { 755 *tl++ = txdr_unsigned(RPCAUTH_NULL); 756 *tl = 0; 757 } 758 mb->m_next = mrest; 759 mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len; 760 mreq->m_pkthdr.rcvif = (struct ifnet *)0; 761 *mbp = mb; 762 return (mreq); 763 } 764 765 /* 766 * copies mbuf chain to the uio scatter/gather list 767 */ 768 int 769 nfsm_mbuftouio(mrep, uiop, siz, dpos) 770 struct mbuf **mrep; 771 register struct uio *uiop; 772 int siz; 773 caddr_t *dpos; 774 { 775 register char *mbufcp, *uiocp; 776 register int xfer, left, len; 777 register struct mbuf *mp; 778 long uiosiz, rem; 779 int error = 0; 780 781 mp = *mrep; 782 mbufcp = *dpos; 783 len = mtod(mp, caddr_t)+mp->m_len-mbufcp; 784 rem = nfsm_rndup(siz)-siz; 785 while (siz > 0) { 786 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 787 return (EFBIG); 788 left = uiop->uio_iov->iov_len; 789 uiocp = uiop->uio_iov->iov_base; 790 if (left > siz) 791 left = siz; 792 uiosiz = left; 793 while (left > 0) { 794 while (len == 0) { 795 mp = mp->m_next; 796 if (mp == NULL) 797 return (EBADRPC); 798 mbufcp = mtod(mp, caddr_t); 799 len = mp->m_len; 800 } 801 xfer = (left > len) ? len : left; 802 #ifdef notdef 803 /* Not Yet.. */ 804 if (uiop->uio_iov->iov_op != NULL) 805 (*(uiop->uio_iov->iov_op)) 806 (mbufcp, uiocp, xfer); 807 else 808 #endif 809 if (uiop->uio_segflg == UIO_SYSSPACE) 810 memcpy(uiocp, mbufcp, xfer); 811 else 812 copyout(mbufcp, uiocp, xfer); 813 left -= xfer; 814 len -= xfer; 815 mbufcp += xfer; 816 uiocp += xfer; 817 uiop->uio_offset += xfer; 818 uiop->uio_resid -= xfer; 819 } 820 if (uiop->uio_iov->iov_len <= siz) { 821 uiop->uio_iovcnt--; 822 uiop->uio_iov++; 823 } else { 824 (caddr_t)uiop->uio_iov->iov_base += uiosiz; 825 uiop->uio_iov->iov_len -= uiosiz; 826 } 827 siz -= uiosiz; 828 } 829 *dpos = mbufcp; 830 *mrep = mp; 831 if (rem > 0) { 832 if (len < rem) 833 error = nfs_adv(mrep, dpos, rem, len); 834 else 835 *dpos += rem; 836 } 837 return (error); 838 } 839 840 /* 841 * copies a uio scatter/gather list to an mbuf chain. 842 * NOTE: can ony handle iovcnt == 1 843 */ 844 int 845 nfsm_uiotombuf(uiop, mq, siz, bpos) 846 register struct uio *uiop; 847 struct mbuf **mq; 848 int siz; 849 caddr_t *bpos; 850 { 851 register char *uiocp; 852 register struct mbuf *mp, *mp2; 853 register int xfer, left, mlen; 854 int uiosiz, clflg, rem; 855 char *cp; 856 857 #ifdef DIAGNOSTIC 858 if (uiop->uio_iovcnt != 1) 859 panic("nfsm_uiotombuf: iovcnt != 1"); 860 #endif 861 862 if (siz > MLEN) /* or should it >= MCLBYTES ?? */ 863 clflg = 1; 864 else 865 clflg = 0; 866 rem = nfsm_rndup(siz)-siz; 867 mp = mp2 = *mq; 868 while (siz > 0) { 869 left = uiop->uio_iov->iov_len; 870 uiocp = uiop->uio_iov->iov_base; 871 if (left > siz) 872 left = siz; 873 uiosiz = left; 874 while (left > 0) { 875 mlen = M_TRAILINGSPACE(mp); 876 if (mlen == 0) { 877 MGET(mp, M_WAIT, MT_DATA); 878 if (clflg) 879 MCLGET(mp, M_WAIT); 880 mp->m_len = 0; 881 mp2->m_next = mp; 882 mp2 = mp; 883 mlen = M_TRAILINGSPACE(mp); 884 } 885 xfer = (left > mlen) ? mlen : left; 886 #ifdef notdef 887 /* Not Yet.. */ 888 if (uiop->uio_iov->iov_op != NULL) 889 (*(uiop->uio_iov->iov_op)) 890 (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer); 891 else 892 #endif 893 if (uiop->uio_segflg == UIO_SYSSPACE) 894 memcpy(mtod(mp, caddr_t)+mp->m_len, uiocp, xfer); 895 else 896 copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer); 897 mp->m_len += xfer; 898 left -= xfer; 899 uiocp += xfer; 900 uiop->uio_offset += xfer; 901 uiop->uio_resid -= xfer; 902 } 903 (caddr_t)uiop->uio_iov->iov_base += uiosiz; 904 uiop->uio_iov->iov_len -= uiosiz; 905 siz -= uiosiz; 906 } 907 if (rem > 0) { 908 if (rem > M_TRAILINGSPACE(mp)) { 909 MGET(mp, M_WAIT, MT_DATA); 910 mp->m_len = 0; 911 mp2->m_next = mp; 912 } 913 cp = mtod(mp, caddr_t)+mp->m_len; 914 for (left = 0; left < rem; left++) 915 *cp++ = '\0'; 916 mp->m_len += rem; 917 *bpos = cp; 918 } else 919 *bpos = mtod(mp, caddr_t)+mp->m_len; 920 *mq = mp; 921 return (0); 922 } 923 924 /* 925 * Get at least "siz" bytes of correctly aligned data. 926 * When called the mbuf pointers are not necessarily correct, 927 * dsosp points to what ought to be in m_data and left contains 928 * what ought to be in m_len. 929 * This is used by the macros nfsm_dissect and nfsm_dissecton for tough 930 * cases. (The macros use the vars. dpos and dpos2) 931 */ 932 int 933 nfsm_disct(mdp, dposp, siz, left, cp2) 934 struct mbuf **mdp; 935 caddr_t *dposp; 936 int siz; 937 int left; 938 caddr_t *cp2; 939 { 940 register struct mbuf *m1, *m2; 941 struct mbuf *havebuf = NULL; 942 caddr_t src = *dposp; 943 caddr_t dst; 944 int len; 945 946 #ifdef DEBUG 947 if (left < 0) 948 panic("nfsm_disct: left < 0"); 949 #endif 950 m1 = *mdp; 951 /* 952 * Skip through the mbuf chain looking for an mbuf with 953 * some data. If the first mbuf found has enough data 954 * and it is correctly aligned return it. 955 */ 956 while (left == 0) { 957 havebuf = m1; 958 *mdp = m1 = m1->m_next; 959 if (m1 == NULL) 960 return (EBADRPC); 961 src = mtod(m1, caddr_t); 962 left = m1->m_len; 963 /* 964 * If we start a new mbuf and it is big enough 965 * and correctly aligned just return it, don't 966 * do any pull up. 967 */ 968 if (left >= siz && nfsm_aligned(src)) { 969 *cp2 = src; 970 *dposp = src + siz; 971 return (0); 972 } 973 } 974 if (m1->m_flags & M_EXT) { 975 if (havebuf) { 976 /* If the first mbuf with data has external data 977 * and there is a previous empty mbuf use it 978 * to move the data into. 979 */ 980 m2 = m1; 981 *mdp = m1 = havebuf; 982 if (m1->m_flags & M_EXT) { 983 MEXTREMOVE(m1); 984 } 985 } else { 986 /* 987 * If the first mbuf has a external data 988 * and there is no previous empty mbuf 989 * allocate a new mbuf and move the external 990 * data to the new mbuf. Also make the first 991 * mbuf look empty. 992 */ 993 m2 = m_get(M_WAIT, MT_DATA); 994 m2->m_ext = m1->m_ext; 995 m2->m_data = src; 996 m2->m_len = left; 997 MCLADDREFERENCE(m1, m2); 998 MEXTREMOVE(m1); 999 m2->m_next = m1->m_next; 1000 m1->m_next = m2; 1001 } 1002 m1->m_len = 0; 1003 dst = m1->m_dat; 1004 } else { 1005 /* 1006 * If the first mbuf has no external data 1007 * move the data to the front of the mbuf. 1008 */ 1009 if ((dst = m1->m_dat) != src) 1010 memmove(dst, src, left); 1011 dst += left; 1012 m1->m_len = left; 1013 m2 = m1->m_next; 1014 } 1015 m1->m_flags &= ~M_PKTHDR; 1016 *cp2 = m1->m_data = m1->m_dat; /* data is at beginning of buffer */ 1017 *dposp = mtod(m1, caddr_t) + siz; 1018 /* 1019 * Loop through mbufs pulling data up into first mbuf until 1020 * the first mbuf is full or there is no more data to 1021 * pullup. 1022 */ 1023 while ((len = (MLEN - m1->m_len)) != 0 && m2) { 1024 if ((len = min(len, m2->m_len)) != 0) 1025 memcpy(dst, m2->m_data, len); 1026 m1->m_len += len; 1027 dst += len; 1028 m2->m_data += len; 1029 m2->m_len -= len; 1030 m2 = m2->m_next; 1031 } 1032 if (m1->m_len < siz) 1033 return (EBADRPC); 1034 return (0); 1035 } 1036 1037 /* 1038 * Advance the position in the mbuf chain. 1039 */ 1040 int 1041 nfs_adv(mdp, dposp, offs, left) 1042 struct mbuf **mdp; 1043 caddr_t *dposp; 1044 int offs; 1045 int left; 1046 { 1047 register struct mbuf *m; 1048 register int s; 1049 1050 m = *mdp; 1051 s = left; 1052 while (s < offs) { 1053 offs -= s; 1054 m = m->m_next; 1055 if (m == NULL) 1056 return (EBADRPC); 1057 s = m->m_len; 1058 } 1059 *mdp = m; 1060 *dposp = mtod(m, caddr_t)+offs; 1061 return (0); 1062 } 1063 1064 /* 1065 * Copy a string into mbufs for the hard cases... 1066 */ 1067 int 1068 nfsm_strtmbuf(mb, bpos, cp, siz) 1069 struct mbuf **mb; 1070 char **bpos; 1071 const char *cp; 1072 long siz; 1073 { 1074 register struct mbuf *m1 = NULL, *m2; 1075 long left, xfer, len, tlen; 1076 u_int32_t *tl; 1077 int putsize; 1078 1079 putsize = 1; 1080 m2 = *mb; 1081 left = M_TRAILINGSPACE(m2); 1082 if (left > 0) { 1083 tl = ((u_int32_t *)(*bpos)); 1084 *tl++ = txdr_unsigned(siz); 1085 putsize = 0; 1086 left -= NFSX_UNSIGNED; 1087 m2->m_len += NFSX_UNSIGNED; 1088 if (left > 0) { 1089 memcpy((caddr_t) tl, cp, left); 1090 siz -= left; 1091 cp += left; 1092 m2->m_len += left; 1093 left = 0; 1094 } 1095 } 1096 /* Loop around adding mbufs */ 1097 while (siz > 0) { 1098 MGET(m1, M_WAIT, MT_DATA); 1099 if (siz > MLEN) 1100 MCLGET(m1, M_WAIT); 1101 m1->m_len = NFSMSIZ(m1); 1102 m2->m_next = m1; 1103 m2 = m1; 1104 tl = mtod(m1, u_int32_t *); 1105 tlen = 0; 1106 if (putsize) { 1107 *tl++ = txdr_unsigned(siz); 1108 m1->m_len -= NFSX_UNSIGNED; 1109 tlen = NFSX_UNSIGNED; 1110 putsize = 0; 1111 } 1112 if (siz < m1->m_len) { 1113 len = nfsm_rndup(siz); 1114 xfer = siz; 1115 if (xfer < len) 1116 *(tl+(xfer>>2)) = 0; 1117 } else { 1118 xfer = len = m1->m_len; 1119 } 1120 memcpy((caddr_t) tl, cp, xfer); 1121 m1->m_len = len+tlen; 1122 siz -= xfer; 1123 cp += xfer; 1124 } 1125 *mb = m1; 1126 *bpos = mtod(m1, caddr_t)+m1->m_len; 1127 return (0); 1128 } 1129 1130 /* 1131 * Directory caching routines. They work as follows: 1132 * - a cache is maintained per VDIR nfsnode. 1133 * - for each offset cookie that is exported to userspace, and can 1134 * thus be thrown back at us as an offset to VOP_READDIR, store 1135 * information in the cache. 1136 * - cached are: 1137 * - cookie itself 1138 * - blocknumber (essentially just a search key in the buffer cache) 1139 * - entry number in block. 1140 * - offset cookie of block in which this entry is stored 1141 * - 32 bit cookie if NFSMNT_XLATECOOKIE is used. 1142 * - entries are looked up in a hash table 1143 * - also maintained is an LRU list of entries, used to determine 1144 * which ones to delete if the cache grows too large. 1145 * - if 32 <-> 64 translation mode is requested for a filesystem, 1146 * the cache also functions as a translation table 1147 * - in the translation case, invalidating the cache does not mean 1148 * flushing it, but just marking entries as invalid, except for 1149 * the <64bit cookie, 32bitcookie> pair which is still valid, to 1150 * still be able to use the cache as a translation table. 1151 * - 32 bit cookies are uniquely created by combining the hash table 1152 * entry value, and one generation count per hash table entry, 1153 * incremented each time an entry is appended to the chain. 1154 * - the cache is invalidated each time a direcory is modified 1155 * - sanity checks are also done; if an entry in a block turns 1156 * out not to have a matching cookie, the cache is invalidated 1157 * and a new block starting from the wanted offset is fetched from 1158 * the server. 1159 * - directory entries as read from the server are extended to contain 1160 * the 64bit and, optionally, the 32bit cookies, for sanity checking 1161 * the cache and exporting them to userspace through the cookie 1162 * argument to VOP_READDIR. 1163 */ 1164 1165 u_long 1166 nfs_dirhash(off) 1167 off_t off; 1168 { 1169 int i; 1170 char *cp = (char *)&off; 1171 u_long sum = 0L; 1172 1173 for (i = 0 ; i < sizeof (off); i++) 1174 sum += *cp++; 1175 1176 return sum; 1177 } 1178 1179 void 1180 nfs_initdircache(vp) 1181 struct vnode *vp; 1182 { 1183 struct nfsnode *np = VTONFS(vp); 1184 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1185 1186 np->n_dircachesize = 0; 1187 np->n_dblkno = 1; 1188 np->n_dircache = 1189 hashinit(NFS_DIRHASHSIZ, M_NFSDIROFF, M_WAITOK, &nfsdirhashmask); 1190 TAILQ_INIT(&np->n_dirchain); 1191 if (nmp->nm_flag & NFSMNT_XLATECOOKIE) { 1192 MALLOC(np->n_dirgens, unsigned *, 1193 NFS_DIRHASHSIZ * sizeof (unsigned), M_NFSDIROFF, 1194 M_WAITOK); 1195 memset((caddr_t)np->n_dirgens, 0, 1196 NFS_DIRHASHSIZ * sizeof (unsigned)); 1197 } 1198 } 1199 1200 static struct nfsdircache dzero = {0, 0, {0, 0}, {0, 0}, 0, 0, 0}; 1201 1202 struct nfsdircache * 1203 nfs_searchdircache(vp, off, do32, hashent) 1204 struct vnode *vp; 1205 off_t off; 1206 int do32; 1207 int *hashent; 1208 { 1209 struct nfsdirhashhead *ndhp; 1210 struct nfsdircache *ndp = NULL; 1211 struct nfsnode *np = VTONFS(vp); 1212 unsigned ent; 1213 1214 /* 1215 * Zero is always a valid cookie. 1216 */ 1217 if (off == 0) 1218 return &dzero; 1219 1220 /* 1221 * We use a 32bit cookie as search key, directly reconstruct 1222 * the hashentry. Else use the hashfunction. 1223 */ 1224 if (do32) { 1225 ent = (u_int32_t)off >> 24; 1226 if (ent >= NFS_DIRHASHSIZ) 1227 return NULL; 1228 ndhp = &np->n_dircache[ent]; 1229 } else { 1230 ndhp = NFSDIRHASH(np, off); 1231 } 1232 1233 if (hashent) 1234 *hashent = (int)(ndhp - np->n_dircache); 1235 if (do32) { 1236 for (ndp = ndhp->lh_first; ndp; ndp = ndp->dc_hash.le_next) { 1237 if (ndp->dc_cookie32 == (u_int32_t)off) { 1238 /* 1239 * An invalidated entry will become the 1240 * start of a new block fetched from 1241 * the server. 1242 */ 1243 if (ndp->dc_blkno == -1) { 1244 ndp->dc_blkcookie = ndp->dc_cookie; 1245 ndp->dc_blkno = np->n_dblkno++; 1246 ndp->dc_entry = 0; 1247 } 1248 break; 1249 } 1250 } 1251 } else { 1252 for (ndp = ndhp->lh_first; ndp; ndp = ndp->dc_hash.le_next) 1253 if (ndp->dc_cookie == off) 1254 break; 1255 } 1256 return ndp; 1257 } 1258 1259 1260 struct nfsdircache * 1261 nfs_enterdircache(vp, off, blkoff, en, blkno) 1262 struct vnode *vp; 1263 off_t off, blkoff; 1264 daddr_t blkno; 1265 int en; 1266 { 1267 struct nfsnode *np = VTONFS(vp); 1268 struct nfsdirhashhead *ndhp; 1269 struct nfsdircache *ndp = NULL, *first; 1270 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1271 int hashent, gen, overwrite; 1272 1273 if (!np->n_dircache) 1274 /* 1275 * XXX would like to do this in nfs_nget but vtype 1276 * isn't known at that time. 1277 */ 1278 nfs_initdircache(vp); 1279 1280 /* 1281 * XXX refuse entries for offset 0. amd(8) erroneously sets 1282 * cookie 0 for the '.' entry, making this necessary. This 1283 * isn't so bad, as 0 is a special case anyway. 1284 */ 1285 if (off == 0) 1286 return &dzero; 1287 1288 ndp = nfs_searchdircache(vp, off, 0, &hashent); 1289 1290 if (ndp && ndp->dc_blkno != -1) { 1291 /* 1292 * Overwriting an old entry. Check if it's the same. 1293 * If so, just return. If not, remove the old entry. 1294 */ 1295 if (ndp->dc_blkcookie == blkoff && ndp->dc_entry == en) 1296 return ndp; 1297 TAILQ_REMOVE(&np->n_dirchain, ndp, dc_chain); 1298 LIST_REMOVE(ndp, dc_hash); 1299 FREE(ndp, M_NFSDIROFF); 1300 ndp = 0; 1301 } 1302 1303 ndhp = &np->n_dircache[hashent]; 1304 1305 if (!ndp) { 1306 MALLOC(ndp, struct nfsdircache *, sizeof (*ndp), M_NFSDIROFF, 1307 M_WAITOK); 1308 overwrite = 0; 1309 if (nmp->nm_flag & NFSMNT_XLATECOOKIE) { 1310 /* 1311 * We're allocating a new entry, so bump the 1312 * generation number. 1313 */ 1314 gen = ++np->n_dirgens[hashent]; 1315 if (gen == 0) { 1316 np->n_dirgens[hashent]++; 1317 gen++; 1318 } 1319 ndp->dc_cookie32 = (hashent << 24) | (gen & 0xffffff); 1320 } 1321 } else 1322 overwrite = 1; 1323 1324 /* 1325 * If the entry number is 0, we are at the start of a new block, so 1326 * allocate a new blocknumber. 1327 */ 1328 if (en == 0) 1329 ndp->dc_blkno = np->n_dblkno++; 1330 else 1331 ndp->dc_blkno = blkno; 1332 1333 ndp->dc_cookie = off; 1334 ndp->dc_blkcookie = blkoff; 1335 ndp->dc_entry = en; 1336 1337 if (overwrite) 1338 return ndp; 1339 1340 /* 1341 * If the maximum directory cookie cache size has been reached 1342 * for this node, take one off the front. The idea is that 1343 * directories are typically read front-to-back once, so that 1344 * the oldest entries can be thrown away without much performance 1345 * loss. 1346 */ 1347 if (np->n_dircachesize == NFS_MAXDIRCACHE) { 1348 first = np->n_dirchain.tqh_first; 1349 TAILQ_REMOVE(&np->n_dirchain, first, dc_chain); 1350 LIST_REMOVE(first, dc_hash); 1351 FREE(first, M_NFSDIROFF); 1352 } else 1353 np->n_dircachesize++; 1354 1355 LIST_INSERT_HEAD(ndhp, ndp, dc_hash); 1356 TAILQ_INSERT_TAIL(&np->n_dirchain, ndp, dc_chain); 1357 return ndp; 1358 } 1359 1360 void 1361 nfs_invaldircache(vp, forcefree) 1362 struct vnode *vp; 1363 int forcefree; 1364 { 1365 struct nfsnode *np = VTONFS(vp); 1366 struct nfsdircache *ndp = NULL; 1367 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1368 1369 #ifdef DIAGNOSTIC 1370 if (vp->v_type != VDIR) 1371 panic("nfs: invaldircache: not dir"); 1372 #endif 1373 1374 if (!np->n_dircache) 1375 return; 1376 1377 if (!(nmp->nm_flag & NFSMNT_XLATECOOKIE) || forcefree) { 1378 while ((ndp = np->n_dirchain.tqh_first)) { 1379 TAILQ_REMOVE(&np->n_dirchain, ndp, dc_chain); 1380 LIST_REMOVE(ndp, dc_hash); 1381 FREE(ndp, M_NFSDIROFF); 1382 } 1383 np->n_dircachesize = 0; 1384 if (forcefree && np->n_dirgens) { 1385 FREE(np->n_dirgens, M_NFSDIROFF); 1386 } 1387 } else { 1388 for (ndp = np->n_dirchain.tqh_first; ndp; 1389 ndp = ndp->dc_chain.tqe_next) 1390 ndp->dc_blkno = -1; 1391 } 1392 1393 np->n_dblkno = 1; 1394 } 1395 1396 /* 1397 * Called once before VFS init to initialize shared and 1398 * server-specific data structures. 1399 */ 1400 void 1401 nfs_init() 1402 { 1403 1404 #if !defined(alpha) && defined(DIAGNOSTIC) 1405 /* 1406 * Check to see if major data structures haven't bloated. 1407 */ 1408 if (sizeof (struct nfsnode) > NFS_NODEALLOC) { 1409 printf("struct nfsnode bloated (> %dbytes)\n", NFS_NODEALLOC); 1410 printf("Try reducing NFS_SMALLFH\n"); 1411 } 1412 if (sizeof (struct nfssvc_sock) > NFS_SVCALLOC) { 1413 printf("struct nfssvc_sock bloated (> %dbytes)\n",NFS_SVCALLOC); 1414 printf("Try reducing NFS_UIDHASHSIZ\n"); 1415 } 1416 if (sizeof (struct nfsuid) > NFS_UIDALLOC) { 1417 printf("struct nfsuid bloated (> %dbytes)\n",NFS_UIDALLOC); 1418 printf("Try unionizing the nu_nickname and nu_flag fields\n"); 1419 } 1420 #endif 1421 1422 nfsrtt.pos = 0; 1423 rpc_vers = txdr_unsigned(RPC_VER2); 1424 rpc_call = txdr_unsigned(RPC_CALL); 1425 rpc_reply = txdr_unsigned(RPC_REPLY); 1426 rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED); 1427 rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED); 1428 rpc_mismatch = txdr_unsigned(RPC_MISMATCH); 1429 rpc_autherr = txdr_unsigned(RPC_AUTHERR); 1430 rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX); 1431 rpc_auth_kerb = txdr_unsigned(RPCAUTH_KERB4); 1432 nfs_prog = txdr_unsigned(NFS_PROG); 1433 nqnfs_prog = txdr_unsigned(NQNFS_PROG); 1434 nfs_true = txdr_unsigned(TRUE); 1435 nfs_false = txdr_unsigned(FALSE); 1436 nfs_xdrneg1 = txdr_unsigned(-1); 1437 nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000; 1438 if (nfs_ticks < 1) 1439 nfs_ticks = 1; 1440 #ifdef NFSSERVER 1441 nfsrv_init(0); /* Init server data structures */ 1442 nfsrv_initcache(); /* Init the server request cache */ 1443 #endif /* NFSSERVER */ 1444 1445 /* 1446 * Initialize the nqnfs data structures. 1447 */ 1448 if (nqnfsstarttime == 0) { 1449 nqnfsstarttime = boottime.tv_sec + nqsrv_maxlease 1450 + nqsrv_clockskew + nqsrv_writeslack; 1451 NQLOADNOVRAM(nqnfsstarttime); 1452 CIRCLEQ_INIT(&nqtimerhead); 1453 nqfhhashtbl = hashinit(NQLCHSZ, M_NQLEASE, M_WAITOK, &nqfhhash); 1454 } 1455 1456 /* 1457 * Initialize reply list and start timer 1458 */ 1459 TAILQ_INIT(&nfs_reqq); 1460 nfs_timer(NULL); 1461 } 1462 1463 #ifdef NFS 1464 /* 1465 * Called once at VFS init to initialize client-specific data structures. 1466 */ 1467 void 1468 nfs_vfs_init() 1469 { 1470 register int i; 1471 1472 /* Ensure async daemons disabled */ 1473 for (i = 0; i < NFS_MAXASYNCDAEMON; i++) { 1474 nfs_iodwant[i] = (struct proc *)0; 1475 nfs_iodmount[i] = (struct nfsmount *)0; 1476 } 1477 nfs_nhinit(); /* Init the nfsnode table */ 1478 } 1479 1480 /* 1481 * Attribute cache routines. 1482 * nfs_loadattrcache() - loads or updates the cache contents from attributes 1483 * that are on the mbuf list 1484 * nfs_getattrcache() - returns valid attributes if found in cache, returns 1485 * error otherwise 1486 */ 1487 1488 /* 1489 * Load the attribute cache (that lives in the nfsnode entry) with 1490 * the values on the mbuf list and 1491 * Iff vap not NULL 1492 * copy the attributes to *vaper 1493 */ 1494 int 1495 nfsm_loadattrcache(vpp, mdp, dposp, vaper) 1496 struct vnode **vpp; 1497 struct mbuf **mdp; 1498 caddr_t *dposp; 1499 struct vattr *vaper; 1500 { 1501 register int32_t t1; 1502 caddr_t cp2; 1503 int error = 0; 1504 struct mbuf *md; 1505 int v3 = NFS_ISV3(*vpp); 1506 1507 md = *mdp; 1508 t1 = (mtod(md, caddr_t) + md->m_len) - *dposp; 1509 error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2); 1510 if (error) 1511 return (error); 1512 return nfs_loadattrcache(vpp, (struct nfs_fattr *)cp2, vaper); 1513 } 1514 1515 int 1516 nfs_loadattrcache(vpp, fp, vaper) 1517 struct vnode **vpp; 1518 struct nfs_fattr *fp; 1519 struct vattr *vaper; 1520 { 1521 register struct vnode *vp = *vpp; 1522 register struct vattr *vap; 1523 int v3 = NFS_ISV3(vp); 1524 enum vtype vtyp; 1525 u_short vmode; 1526 struct timespec mtime; 1527 struct vnode *nvp; 1528 int32_t rdev; 1529 register struct nfsnode *np; 1530 extern int (**spec_nfsv2nodeop_p) __P((void *)); 1531 1532 if (v3) { 1533 vtyp = nfsv3tov_type(fp->fa_type); 1534 vmode = fxdr_unsigned(u_short, fp->fa_mode); 1535 rdev = makedev(fxdr_unsigned(u_int32_t, fp->fa3_rdev.specdata1), 1536 fxdr_unsigned(u_int32_t, fp->fa3_rdev.specdata2)); 1537 fxdr_nfsv3time(&fp->fa3_mtime, &mtime); 1538 } else { 1539 vtyp = nfsv2tov_type(fp->fa_type); 1540 vmode = fxdr_unsigned(u_short, fp->fa_mode); 1541 if (vtyp == VNON || vtyp == VREG) 1542 vtyp = IFTOVT(vmode); 1543 rdev = fxdr_unsigned(int32_t, fp->fa2_rdev); 1544 fxdr_nfsv2time(&fp->fa2_mtime, &mtime); 1545 1546 /* 1547 * Really ugly NFSv2 kludge. 1548 */ 1549 if (vtyp == VCHR && rdev == 0xffffffff) 1550 vtyp = VFIFO; 1551 } 1552 1553 /* 1554 * If v_type == VNON it is a new node, so fill in the v_type, 1555 * n_mtime fields. Check to see if it represents a special 1556 * device, and if so, check for a possible alias. Once the 1557 * correct vnode has been obtained, fill in the rest of the 1558 * information. 1559 */ 1560 np = VTONFS(vp); 1561 if (vp->v_type != vtyp) { 1562 vp->v_type = vtyp; 1563 if (vp->v_type == VFIFO) { 1564 extern int (**fifo_nfsv2nodeop_p) __P((void *)); 1565 vp->v_op = fifo_nfsv2nodeop_p; 1566 } 1567 if (vp->v_type == VCHR || vp->v_type == VBLK) { 1568 vp->v_op = spec_nfsv2nodeop_p; 1569 nvp = checkalias(vp, (dev_t)rdev, vp->v_mount); 1570 if (nvp) { 1571 /* 1572 * Discard unneeded vnode, but save its nfsnode. 1573 * Since the nfsnode does not have a lock, its 1574 * vnode lock has to be carried over. 1575 */ 1576 nvp->v_data = vp->v_data; 1577 vp->v_data = NULL; 1578 vp->v_op = spec_vnodeop_p; 1579 vput(vp); 1580 vgone(vp); 1581 /* 1582 * XXX When nfs starts locking, we need to 1583 * lock the new node here. 1584 */ 1585 /* 1586 * Reinitialize aliased node. 1587 */ 1588 np->n_vnode = nvp; 1589 *vpp = vp = nvp; 1590 } 1591 } 1592 np->n_mtime = mtime.tv_sec; 1593 } 1594 vap = np->n_vattr; 1595 vap->va_type = vtyp; 1596 vap->va_mode = vmode & ALLPERMS; 1597 vap->va_rdev = (dev_t)rdev; 1598 vap->va_mtime = mtime; 1599 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 1600 switch (vtyp) { 1601 case VDIR: 1602 vap->va_blocksize = NFS_DIRFRAGSIZ; 1603 break; 1604 case VBLK: 1605 vap->va_blocksize = BLKDEV_IOSIZE; 1606 break; 1607 case VCHR: 1608 vap->va_blocksize = MAXBSIZE; 1609 break; 1610 default: 1611 vap->va_blocksize = v3 ? vp->v_mount->mnt_stat.f_iosize : 1612 fxdr_unsigned(int32_t, fp->fa2_blocksize); 1613 break; 1614 } 1615 if (v3) { 1616 vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 1617 vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid); 1618 vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid); 1619 vap->va_size = fxdr_hyper(&fp->fa3_size); 1620 vap->va_bytes = fxdr_hyper(&fp->fa3_used); 1621 vap->va_fileid = fxdr_unsigned(int32_t, 1622 fp->fa3_fileid.nfsuquad[1]); 1623 fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime); 1624 fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime); 1625 vap->va_flags = 0; 1626 vap->va_filerev = 0; 1627 } else { 1628 vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 1629 vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid); 1630 vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid); 1631 vap->va_size = fxdr_unsigned(u_int32_t, fp->fa2_size); 1632 vap->va_bytes = fxdr_unsigned(int32_t, fp->fa2_blocks) 1633 * NFS_FABLKSIZE; 1634 vap->va_fileid = fxdr_unsigned(int32_t, fp->fa2_fileid); 1635 fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime); 1636 vap->va_flags = 0; 1637 vap->va_ctime.tv_sec = fxdr_unsigned(u_int32_t, 1638 fp->fa2_ctime.nfsv2_sec); 1639 vap->va_ctime.tv_nsec = 0; 1640 vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec); 1641 vap->va_filerev = 0; 1642 } 1643 if (vap->va_size != np->n_size) { 1644 if (vap->va_type == VREG) { 1645 if (np->n_flag & NMODIFIED) { 1646 if (vap->va_size < np->n_size) 1647 vap->va_size = np->n_size; 1648 else 1649 np->n_size = vap->va_size; 1650 } else 1651 np->n_size = vap->va_size; 1652 uvm_vnp_setsize(vp, np->n_size); 1653 } else 1654 np->n_size = vap->va_size; 1655 } 1656 np->n_attrstamp = time.tv_sec; 1657 if (vaper != NULL) { 1658 memcpy((caddr_t)vaper, (caddr_t)vap, sizeof(*vap)); 1659 if (np->n_flag & NCHG) { 1660 if (np->n_flag & NACC) 1661 vaper->va_atime = np->n_atim; 1662 if (np->n_flag & NUPD) 1663 vaper->va_mtime = np->n_mtim; 1664 } 1665 } 1666 return (0); 1667 } 1668 1669 /* 1670 * Check the time stamp 1671 * If the cache is valid, copy contents to *vap and return 0 1672 * otherwise return an error 1673 */ 1674 int 1675 nfs_getattrcache(vp, vaper) 1676 register struct vnode *vp; 1677 struct vattr *vaper; 1678 { 1679 register struct nfsnode *np = VTONFS(vp); 1680 register struct vattr *vap; 1681 1682 if ((time.tv_sec - np->n_attrstamp) >= NFS_ATTRTIMEO(np)) { 1683 nfsstats.attrcache_misses++; 1684 return (ENOENT); 1685 } 1686 nfsstats.attrcache_hits++; 1687 vap = np->n_vattr; 1688 if (vap->va_size != np->n_size) { 1689 if (vap->va_type == VREG) { 1690 if (np->n_flag & NMODIFIED) { 1691 if (vap->va_size < np->n_size) 1692 vap->va_size = np->n_size; 1693 else 1694 np->n_size = vap->va_size; 1695 } else 1696 np->n_size = vap->va_size; 1697 uvm_vnp_setsize(vp, np->n_size); 1698 } else 1699 np->n_size = vap->va_size; 1700 } 1701 memcpy((caddr_t)vaper, (caddr_t)vap, sizeof(struct vattr)); 1702 if (np->n_flag & NCHG) { 1703 if (np->n_flag & NACC) 1704 vaper->va_atime = np->n_atim; 1705 if (np->n_flag & NUPD) 1706 vaper->va_mtime = np->n_mtim; 1707 } 1708 return (0); 1709 } 1710 1711 /* 1712 * Heuristic to see if the server XDR encodes directory cookies or not. 1713 * it is not supposed to, but a lot of servers may do this. Also, since 1714 * most/all servers will implement V2 as well, it is expected that they 1715 * may return just 32 bits worth of cookie information, so we need to 1716 * find out in which 32 bits this information is available. We do this 1717 * to avoid trouble with emulated binaries that can't handle 64 bit 1718 * directory offsets. 1719 */ 1720 1721 void 1722 nfs_cookieheuristic(vp, flagp, p, cred) 1723 struct vnode *vp; 1724 int *flagp; 1725 struct proc *p; 1726 struct ucred *cred; 1727 { 1728 struct uio auio; 1729 struct iovec aiov; 1730 caddr_t buf, cp; 1731 struct dirent *dp; 1732 off_t *cookies = NULL, *cop; 1733 int error, eof, nc, len; 1734 1735 MALLOC(buf, caddr_t, NFS_DIRFRAGSIZ, M_TEMP, M_WAITOK); 1736 1737 aiov.iov_base = buf; 1738 aiov.iov_len = NFS_DIRFRAGSIZ; 1739 auio.uio_iov = &aiov; 1740 auio.uio_iovcnt = 1; 1741 auio.uio_rw = UIO_READ; 1742 auio.uio_segflg = UIO_SYSSPACE; 1743 auio.uio_procp = p; 1744 auio.uio_resid = NFS_DIRFRAGSIZ; 1745 auio.uio_offset = 0; 1746 1747 error = VOP_READDIR(vp, &auio, cred, &eof, &cookies, &nc); 1748 1749 len = NFS_DIRFRAGSIZ - auio.uio_resid; 1750 if (error || len == 0) { 1751 FREE(buf, M_TEMP); 1752 if (cookies) 1753 FREE(cookies, M_TEMP); 1754 return; 1755 } 1756 1757 /* 1758 * Find the first valid entry and look at its offset cookie. 1759 */ 1760 1761 cp = buf; 1762 for (cop = cookies; len > 0; len -= dp->d_reclen) { 1763 dp = (struct dirent *)cp; 1764 if (dp->d_fileno != 0 && len >= dp->d_reclen) { 1765 if ((*cop >> 32) != 0 && (*cop & 0xffffffffLL) == 0) { 1766 *flagp |= NFSMNT_SWAPCOOKIE; 1767 nfs_invaldircache(vp, 0); 1768 nfs_vinvalbuf(vp, 0, cred, p, 1); 1769 } 1770 break; 1771 } 1772 cop++; 1773 cp += dp->d_reclen; 1774 } 1775 1776 FREE(buf, M_TEMP); 1777 FREE(cookies, M_TEMP); 1778 } 1779 #endif /* NFS */ 1780 1781 /* 1782 * Set up nameidata for a lookup() call and do it. 1783 * 1784 * If pubflag is set, this call is done for a lookup operation on the 1785 * public filehandle. In that case we allow crossing mountpoints and 1786 * absolute pathnames. However, the caller is expected to check that 1787 * the lookup result is within the public fs, and deny access if 1788 * it is not. 1789 */ 1790 int 1791 nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag, pubflag) 1792 register struct nameidata *ndp; 1793 fhandle_t *fhp; 1794 int len; 1795 struct nfssvc_sock *slp; 1796 struct mbuf *nam; 1797 struct mbuf **mdp; 1798 caddr_t *dposp; 1799 struct vnode **retdirp; 1800 struct proc *p; 1801 int kerbflag, pubflag; 1802 { 1803 register int i, rem; 1804 register struct mbuf *md; 1805 register char *fromcp, *tocp, *cp; 1806 struct iovec aiov; 1807 struct uio auio; 1808 struct vnode *dp; 1809 int error, rdonly, linklen; 1810 struct componentname *cnp = &ndp->ni_cnd; 1811 1812 *retdirp = (struct vnode *)0; 1813 MALLOC(cnp->cn_pnbuf, char *, len + 1, M_NAMEI, M_WAITOK); 1814 /* 1815 * Copy the name from the mbuf list to ndp->ni_pnbuf 1816 * and set the various ndp fields appropriately. 1817 */ 1818 fromcp = *dposp; 1819 tocp = cnp->cn_pnbuf; 1820 md = *mdp; 1821 rem = mtod(md, caddr_t) + md->m_len - fromcp; 1822 for (i = 0; i < len; i++) { 1823 while (rem == 0) { 1824 md = md->m_next; 1825 if (md == NULL) { 1826 error = EBADRPC; 1827 goto out; 1828 } 1829 fromcp = mtod(md, caddr_t); 1830 rem = md->m_len; 1831 } 1832 if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) { 1833 error = EACCES; 1834 goto out; 1835 } 1836 *tocp++ = *fromcp++; 1837 rem--; 1838 } 1839 *tocp = '\0'; 1840 *mdp = md; 1841 *dposp = fromcp; 1842 len = nfsm_rndup(len)-len; 1843 if (len > 0) { 1844 if (rem >= len) 1845 *dposp += len; 1846 else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0) 1847 goto out; 1848 } 1849 1850 /* 1851 * Extract and set starting directory. 1852 */ 1853 error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp, 1854 nam, &rdonly, kerbflag, pubflag); 1855 if (error) 1856 goto out; 1857 if (dp->v_type != VDIR) { 1858 vrele(dp); 1859 error = ENOTDIR; 1860 goto out; 1861 } 1862 1863 if (rdonly) 1864 cnp->cn_flags |= RDONLY; 1865 1866 *retdirp = dp; 1867 1868 if (pubflag) { 1869 /* 1870 * Oh joy. For WebNFS, handle those pesky '%' escapes, 1871 * and the 'native path' indicator. 1872 */ 1873 MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 1874 fromcp = cnp->cn_pnbuf; 1875 tocp = cp; 1876 if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) { 1877 switch ((unsigned char)*fromcp) { 1878 case WEBNFS_NATIVE_CHAR: 1879 /* 1880 * 'Native' path for us is the same 1881 * as a path according to the NFS spec, 1882 * just skip the escape char. 1883 */ 1884 fromcp++; 1885 break; 1886 /* 1887 * More may be added in the future, range 0x80-0xff 1888 */ 1889 default: 1890 error = EIO; 1891 FREE(cp, M_NAMEI); 1892 goto out; 1893 } 1894 } 1895 /* 1896 * Translate the '%' escapes, URL-style. 1897 */ 1898 while (*fromcp != '\0') { 1899 if (*fromcp == WEBNFS_ESC_CHAR) { 1900 if (fromcp[1] != '\0' && fromcp[2] != '\0') { 1901 fromcp++; 1902 *tocp++ = HEXSTRTOI(fromcp); 1903 fromcp += 2; 1904 continue; 1905 } else { 1906 error = ENOENT; 1907 FREE(cp, M_NAMEI); 1908 goto out; 1909 } 1910 } else 1911 *tocp++ = *fromcp++; 1912 } 1913 *tocp = '\0'; 1914 FREE(cnp->cn_pnbuf, M_NAMEI); 1915 cnp->cn_pnbuf = cp; 1916 } 1917 1918 ndp->ni_pathlen = (tocp - cnp->cn_pnbuf) + 1; 1919 ndp->ni_segflg = UIO_SYSSPACE; 1920 1921 if (pubflag) { 1922 ndp->ni_rootdir = rootvnode; 1923 ndp->ni_loopcnt = 0; 1924 if (cnp->cn_pnbuf[0] == '/') 1925 dp = rootvnode; 1926 } else { 1927 cnp->cn_flags |= NOCROSSMOUNT; 1928 } 1929 1930 cnp->cn_proc = p; 1931 VREF(dp); 1932 1933 for (;;) { 1934 cnp->cn_nameptr = cnp->cn_pnbuf; 1935 ndp->ni_startdir = dp; 1936 /* 1937 * And call lookup() to do the real work 1938 */ 1939 error = lookup(ndp); 1940 if (error) 1941 break; 1942 /* 1943 * Check for encountering a symbolic link 1944 */ 1945 if ((cnp->cn_flags & ISSYMLINK) == 0) { 1946 if (cnp->cn_flags & (SAVENAME | SAVESTART)) { 1947 cnp->cn_flags |= HASBUF; 1948 return (0); 1949 } 1950 break; 1951 } else { 1952 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) 1953 VOP_UNLOCK(ndp->ni_dvp, 0); 1954 if (!pubflag) { 1955 vrele(ndp->ni_dvp); 1956 vput(ndp->ni_vp); 1957 ndp->ni_vp = NULL; 1958 error = EINVAL; 1959 break; 1960 } 1961 1962 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { 1963 error = ELOOP; 1964 break; 1965 } 1966 if (ndp->ni_pathlen > 1) 1967 MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 1968 else 1969 cp = cnp->cn_pnbuf; 1970 aiov.iov_base = cp; 1971 aiov.iov_len = MAXPATHLEN; 1972 auio.uio_iov = &aiov; 1973 auio.uio_iovcnt = 1; 1974 auio.uio_offset = 0; 1975 auio.uio_rw = UIO_READ; 1976 auio.uio_segflg = UIO_SYSSPACE; 1977 auio.uio_procp = (struct proc *)0; 1978 auio.uio_resid = MAXPATHLEN; 1979 error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred); 1980 if (error) { 1981 badlink: 1982 if (ndp->ni_pathlen > 1) 1983 FREE(cp, M_NAMEI); 1984 break; 1985 } 1986 linklen = MAXPATHLEN - auio.uio_resid; 1987 if (linklen == 0) { 1988 error = ENOENT; 1989 goto badlink; 1990 } 1991 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 1992 error = ENAMETOOLONG; 1993 goto badlink; 1994 } 1995 if (ndp->ni_pathlen > 1) { 1996 memcpy(cp + linklen, ndp->ni_next, ndp->ni_pathlen); 1997 FREE(cnp->cn_pnbuf, M_NAMEI); 1998 cnp->cn_pnbuf = cp; 1999 } else 2000 cnp->cn_pnbuf[linklen] = '\0'; 2001 ndp->ni_pathlen += linklen; 2002 vput(ndp->ni_vp); 2003 dp = ndp->ni_dvp; 2004 /* 2005 * Check if root directory should replace current directory. 2006 */ 2007 if (cnp->cn_pnbuf[0] == '/') { 2008 vrele(dp); 2009 dp = ndp->ni_rootdir; 2010 VREF(dp); 2011 } 2012 } 2013 } 2014 out: 2015 FREE(cnp->cn_pnbuf, M_NAMEI); 2016 return (error); 2017 } 2018 2019 /* 2020 * A fiddled version of m_adj() that ensures null fill to a long 2021 * boundary and only trims off the back end 2022 */ 2023 void 2024 nfsm_adj(mp, len, nul) 2025 struct mbuf *mp; 2026 register int len; 2027 int nul; 2028 { 2029 register struct mbuf *m; 2030 register int count, i; 2031 register char *cp; 2032 2033 /* 2034 * Trim from tail. Scan the mbuf chain, 2035 * calculating its length and finding the last mbuf. 2036 * If the adjustment only affects this mbuf, then just 2037 * adjust and return. Otherwise, rescan and truncate 2038 * after the remaining size. 2039 */ 2040 count = 0; 2041 m = mp; 2042 for (;;) { 2043 count += m->m_len; 2044 if (m->m_next == (struct mbuf *)0) 2045 break; 2046 m = m->m_next; 2047 } 2048 if (m->m_len > len) { 2049 m->m_len -= len; 2050 if (nul > 0) { 2051 cp = mtod(m, caddr_t)+m->m_len-nul; 2052 for (i = 0; i < nul; i++) 2053 *cp++ = '\0'; 2054 } 2055 return; 2056 } 2057 count -= len; 2058 if (count < 0) 2059 count = 0; 2060 /* 2061 * Correct length for chain is "count". 2062 * Find the mbuf with last data, adjust its length, 2063 * and toss data from remaining mbufs on chain. 2064 */ 2065 for (m = mp; m; m = m->m_next) { 2066 if (m->m_len >= count) { 2067 m->m_len = count; 2068 if (nul > 0) { 2069 cp = mtod(m, caddr_t)+m->m_len-nul; 2070 for (i = 0; i < nul; i++) 2071 *cp++ = '\0'; 2072 } 2073 break; 2074 } 2075 count -= m->m_len; 2076 } 2077 for (m = m->m_next;m;m = m->m_next) 2078 m->m_len = 0; 2079 } 2080 2081 /* 2082 * Make these functions instead of macros, so that the kernel text size 2083 * doesn't get too big... 2084 */ 2085 void 2086 nfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp) 2087 struct nfsrv_descript *nfsd; 2088 int before_ret; 2089 register struct vattr *before_vap; 2090 int after_ret; 2091 struct vattr *after_vap; 2092 struct mbuf **mbp; 2093 char **bposp; 2094 { 2095 register struct mbuf *mb = *mbp, *mb2; 2096 register char *bpos = *bposp; 2097 register u_int32_t *tl; 2098 2099 if (before_ret) { 2100 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); 2101 *tl = nfs_false; 2102 } else { 2103 nfsm_build(tl, u_int32_t *, 7 * NFSX_UNSIGNED); 2104 *tl++ = nfs_true; 2105 txdr_hyper(before_vap->va_size, tl); 2106 tl += 2; 2107 txdr_nfsv3time(&(before_vap->va_mtime), tl); 2108 tl += 2; 2109 txdr_nfsv3time(&(before_vap->va_ctime), tl); 2110 } 2111 *bposp = bpos; 2112 *mbp = mb; 2113 nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp); 2114 } 2115 2116 void 2117 nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp) 2118 struct nfsrv_descript *nfsd; 2119 int after_ret; 2120 struct vattr *after_vap; 2121 struct mbuf **mbp; 2122 char **bposp; 2123 { 2124 register struct mbuf *mb = *mbp, *mb2; 2125 register char *bpos = *bposp; 2126 register u_int32_t *tl; 2127 register struct nfs_fattr *fp; 2128 2129 if (after_ret) { 2130 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); 2131 *tl = nfs_false; 2132 } else { 2133 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR); 2134 *tl++ = nfs_true; 2135 fp = (struct nfs_fattr *)tl; 2136 nfsm_srvfattr(nfsd, after_vap, fp); 2137 } 2138 *mbp = mb; 2139 *bposp = bpos; 2140 } 2141 2142 void 2143 nfsm_srvfattr(nfsd, vap, fp) 2144 register struct nfsrv_descript *nfsd; 2145 register struct vattr *vap; 2146 register struct nfs_fattr *fp; 2147 { 2148 2149 fp->fa_nlink = txdr_unsigned(vap->va_nlink); 2150 fp->fa_uid = txdr_unsigned(vap->va_uid); 2151 fp->fa_gid = txdr_unsigned(vap->va_gid); 2152 if (nfsd->nd_flag & ND_NFSV3) { 2153 fp->fa_type = vtonfsv3_type(vap->va_type); 2154 fp->fa_mode = vtonfsv3_mode(vap->va_mode); 2155 txdr_hyper(vap->va_size, &fp->fa3_size); 2156 txdr_hyper(vap->va_bytes, &fp->fa3_used); 2157 fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev)); 2158 fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev)); 2159 fp->fa3_fsid.nfsuquad[0] = 0; 2160 fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid); 2161 fp->fa3_fileid.nfsuquad[0] = 0; 2162 fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid); 2163 txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime); 2164 txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime); 2165 txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime); 2166 } else { 2167 fp->fa_type = vtonfsv2_type(vap->va_type); 2168 fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 2169 fp->fa2_size = txdr_unsigned(vap->va_size); 2170 fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize); 2171 if (vap->va_type == VFIFO) 2172 fp->fa2_rdev = 0xffffffff; 2173 else 2174 fp->fa2_rdev = txdr_unsigned(vap->va_rdev); 2175 fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); 2176 fp->fa2_fsid = txdr_unsigned(vap->va_fsid); 2177 fp->fa2_fileid = txdr_unsigned(vap->va_fileid); 2178 txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime); 2179 txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime); 2180 txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime); 2181 } 2182 } 2183 2184 /* 2185 * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked) 2186 * - look up fsid in mount list (if not found ret error) 2187 * - get vp and export rights by calling VFS_FHTOVP() 2188 * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon 2189 * - if not lockflag unlock it with VOP_UNLOCK() 2190 */ 2191 int 2192 nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag) 2193 fhandle_t *fhp; 2194 int lockflag; 2195 struct vnode **vpp; 2196 struct ucred *cred; 2197 struct nfssvc_sock *slp; 2198 struct mbuf *nam; 2199 int *rdonlyp; 2200 int kerbflag; 2201 { 2202 register struct mount *mp; 2203 register int i; 2204 struct ucred *credanon; 2205 int error, exflags; 2206 struct sockaddr_in *saddr; 2207 2208 *vpp = (struct vnode *)0; 2209 2210 if (nfs_ispublicfh(fhp)) { 2211 if (!pubflag || !nfs_pub.np_valid) 2212 return (ESTALE); 2213 fhp = &nfs_pub.np_handle; 2214 } 2215 2216 mp = vfs_getvfs(&fhp->fh_fsid); 2217 if (!mp) 2218 return (ESTALE); 2219 error = VFS_CHECKEXP(mp, nam, &exflags, &credanon); 2220 if (error) 2221 return (error); 2222 error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp); 2223 if (error) 2224 return (error); 2225 2226 if (!(exflags & (MNT_EXNORESPORT|MNT_EXPUBLIC))) { 2227 saddr = mtod(nam, struct sockaddr_in *); 2228 if (saddr->sin_family == AF_INET && 2229 ntohs(saddr->sin_port) >= IPPORT_RESERVED) { 2230 vput(*vpp); 2231 return (NFSERR_AUTHERR | AUTH_TOOWEAK); 2232 } 2233 } 2234 /* 2235 * Check/setup credentials. 2236 */ 2237 if (exflags & MNT_EXKERB) { 2238 if (!kerbflag) { 2239 vput(*vpp); 2240 return (NFSERR_AUTHERR | AUTH_TOOWEAK); 2241 } 2242 } else if (kerbflag) { 2243 vput(*vpp); 2244 return (NFSERR_AUTHERR | AUTH_TOOWEAK); 2245 } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) { 2246 cred->cr_uid = credanon->cr_uid; 2247 cred->cr_gid = credanon->cr_gid; 2248 for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++) 2249 cred->cr_groups[i] = credanon->cr_groups[i]; 2250 cred->cr_ngroups = i; 2251 } 2252 if (exflags & MNT_EXRDONLY) 2253 *rdonlyp = 1; 2254 else 2255 *rdonlyp = 0; 2256 if (!lockflag) 2257 VOP_UNLOCK(*vpp, 0); 2258 return (0); 2259 } 2260 2261 /* 2262 * WebNFS: check if a filehandle is a public filehandle. For v3, this 2263 * means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has 2264 * transformed this to all zeroes in both cases, so check for it. 2265 */ 2266 int 2267 nfs_ispublicfh(fhp) 2268 fhandle_t *fhp; 2269 { 2270 char *cp = (char *)fhp; 2271 int i; 2272 2273 for (i = 0; i < NFSX_V3FH; i++) 2274 if (*cp++ != 0) 2275 return (FALSE); 2276 return (TRUE); 2277 } 2278 2279 /* 2280 * This function compares two net addresses by family and returns TRUE 2281 * if they are the same host. 2282 * If there is any doubt, return FALSE. 2283 * The AF_INET family is handled as a special case so that address mbufs 2284 * don't need to be saved to store "struct in_addr", which is only 4 bytes. 2285 */ 2286 int 2287 netaddr_match(family, haddr, nam) 2288 int family; 2289 union nethostaddr *haddr; 2290 struct mbuf *nam; 2291 { 2292 register struct sockaddr_in *inetaddr; 2293 2294 switch (family) { 2295 case AF_INET: 2296 inetaddr = mtod(nam, struct sockaddr_in *); 2297 if (inetaddr->sin_family == AF_INET && 2298 inetaddr->sin_addr.s_addr == haddr->had_inetaddr) 2299 return (1); 2300 break; 2301 #ifdef ISO 2302 case AF_ISO: 2303 { 2304 register struct sockaddr_iso *isoaddr1, *isoaddr2; 2305 2306 isoaddr1 = mtod(nam, struct sockaddr_iso *); 2307 isoaddr2 = mtod(haddr->had_nam, struct sockaddr_iso *); 2308 if (isoaddr1->siso_family == AF_ISO && 2309 isoaddr1->siso_nlen > 0 && 2310 isoaddr1->siso_nlen == isoaddr2->siso_nlen && 2311 SAME_ISOADDR(isoaddr1, isoaddr2)) 2312 return (1); 2313 break; 2314 } 2315 #endif /* ISO */ 2316 default: 2317 break; 2318 }; 2319 return (0); 2320 } 2321 2322 2323 /* 2324 * The write verifier has changed (probably due to a server reboot), so all 2325 * B_NEEDCOMMIT blocks will have to be written again. Since they are on the 2326 * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT 2327 * flag. Once done the new write verifier can be set for the mount point. 2328 */ 2329 void 2330 nfs_clearcommit(mp) 2331 struct mount *mp; 2332 { 2333 register struct vnode *vp, *nvp; 2334 register struct buf *bp, *nbp; 2335 int s; 2336 2337 s = splbio(); 2338 loop: 2339 for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) { 2340 if (vp->v_mount != mp) /* Paranoia */ 2341 goto loop; 2342 nvp = vp->v_mntvnodes.le_next; 2343 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2344 nbp = bp->b_vnbufs.le_next; 2345 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2346 == (B_DELWRI | B_NEEDCOMMIT)) 2347 bp->b_flags &= ~B_NEEDCOMMIT; 2348 } 2349 } 2350 splx(s); 2351 } 2352 2353 /* 2354 * Map errnos to NFS error numbers. For Version 3 also filter out error 2355 * numbers not specified for the associated procedure. 2356 */ 2357 int 2358 nfsrv_errmap(nd, err) 2359 struct nfsrv_descript *nd; 2360 register int err; 2361 { 2362 register short *defaulterrp, *errp; 2363 2364 if (nd->nd_flag & ND_NFSV3) { 2365 if (nd->nd_procnum <= NFSPROC_COMMIT) { 2366 errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum]; 2367 while (*++errp) { 2368 if (*errp == err) 2369 return (err); 2370 else if (*errp > err) 2371 break; 2372 } 2373 return ((int)*defaulterrp); 2374 } else 2375 return (err & 0xffff); 2376 } 2377 if (err <= ELAST) 2378 return ((int)nfsrv_v2errmap[err - 1]); 2379 return (NFSERR_IO); 2380 } 2381 2382 /* 2383 * Sort the group list in increasing numerical order. 2384 * (Insertion sort by Chris Torek, who was grossed out by the bubble sort 2385 * that used to be here.) 2386 */ 2387 void 2388 nfsrvw_sort(list, num) 2389 register gid_t *list; 2390 register int num; 2391 { 2392 register int i, j; 2393 gid_t v; 2394 2395 /* Insertion sort. */ 2396 for (i = 1; i < num; i++) { 2397 v = list[i]; 2398 /* find correct slot for value v, moving others up */ 2399 for (j = i; --j >= 0 && v < list[j];) 2400 list[j + 1] = list[j]; 2401 list[j + 1] = v; 2402 } 2403 } 2404 2405 /* 2406 * copy credentials making sure that the result can be compared with memcmp(). 2407 */ 2408 void 2409 nfsrv_setcred(incred, outcred) 2410 register struct ucred *incred, *outcred; 2411 { 2412 register int i; 2413 2414 memset((caddr_t)outcred, 0, sizeof (struct ucred)); 2415 outcred->cr_ref = 1; 2416 outcred->cr_uid = incred->cr_uid; 2417 outcred->cr_gid = incred->cr_gid; 2418 outcred->cr_ngroups = incred->cr_ngroups; 2419 for (i = 0; i < incred->cr_ngroups; i++) 2420 outcred->cr_groups[i] = incred->cr_groups[i]; 2421 nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups); 2422 } 2423