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