1 /* $OpenBSD: nfs_subs.c,v 1.116 2014/07/08 17:19:26 deraadt Exp $ */ 2 /* $NetBSD: nfs_subs.c,v 1.27.4.3 1996/07/08 20:34:24 jtc Exp $ */ 3 4 /* 5 * Copyright (c) 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Rick Macklem at The University of Guelph. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95 36 */ 37 38 39 /* 40 * These functions support the macros and help fiddle mbuf chains for 41 * the nfs op functions. They do things like create the rpc header and 42 * copy data between mbuf chains and uio lists. 43 */ 44 #include <sys/param.h> 45 #include <sys/proc.h> 46 #include <sys/systm.h> 47 #include <sys/kernel.h> 48 #include <sys/mount.h> 49 #include <sys/vnode.h> 50 #include <sys/namei.h> 51 #include <sys/mbuf.h> 52 #include <sys/socket.h> 53 #include <sys/socketvar.h> 54 #include <sys/stat.h> 55 #include <sys/pool.h> 56 #include <sys/time.h> 57 #include <sys/specdev.h> 58 59 #include <nfs/rpcv2.h> 60 #include <nfs/nfsproto.h> 61 #include <nfs/nfsnode.h> 62 #include <nfs/nfs.h> 63 #include <nfs/xdr_subs.h> 64 #include <nfs/nfsm_subs.h> 65 #include <nfs/nfsmount.h> 66 #include <nfs/nfs_var.h> 67 68 69 #include <netinet/in.h> 70 71 #include <dev/rndvar.h> 72 #include <crypto/idgen.h> 73 74 int nfs_attrtimeo(struct nfsnode *np); 75 76 /* 77 * Data items converted to xdr at startup, since they are constant 78 * This is kinda hokey, but may save a little time doing byte swaps 79 */ 80 u_int32_t nfs_xdrneg1; 81 u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr, 82 rpc_mismatch, rpc_auth_unix, rpc_msgaccepted; 83 u_int32_t nfs_prog, nfs_true, nfs_false; 84 85 /* And other global data */ 86 nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON, 87 NFCHR, NFNON }; 88 nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK, 89 NFFIFO, NFNON }; 90 enum vtype nv2tov_type[8] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON }; 91 enum vtype nv3tov_type[8]={ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO }; 92 int nfs_ticks; 93 struct nfsstats nfsstats; 94 95 /* 96 * Mapping of old NFS Version 2 RPC numbers to generic numbers. 97 */ 98 int nfsv3_procid[NFS_NPROCS] = { 99 NFSPROC_NULL, 100 NFSPROC_GETATTR, 101 NFSPROC_SETATTR, 102 NFSPROC_NOOP, 103 NFSPROC_LOOKUP, 104 NFSPROC_READLINK, 105 NFSPROC_READ, 106 NFSPROC_NOOP, 107 NFSPROC_WRITE, 108 NFSPROC_CREATE, 109 NFSPROC_REMOVE, 110 NFSPROC_RENAME, 111 NFSPROC_LINK, 112 NFSPROC_SYMLINK, 113 NFSPROC_MKDIR, 114 NFSPROC_RMDIR, 115 NFSPROC_READDIR, 116 NFSPROC_FSSTAT, 117 NFSPROC_NOOP, 118 NFSPROC_NOOP, 119 NFSPROC_NOOP, 120 NFSPROC_NOOP, 121 NFSPROC_NOOP 122 }; 123 124 /* 125 * and the reverse mapping from generic to Version 2 procedure numbers 126 */ 127 int nfsv2_procid[NFS_NPROCS] = { 128 NFSV2PROC_NULL, 129 NFSV2PROC_GETATTR, 130 NFSV2PROC_SETATTR, 131 NFSV2PROC_LOOKUP, 132 NFSV2PROC_NOOP, 133 NFSV2PROC_READLINK, 134 NFSV2PROC_READ, 135 NFSV2PROC_WRITE, 136 NFSV2PROC_CREATE, 137 NFSV2PROC_MKDIR, 138 NFSV2PROC_SYMLINK, 139 NFSV2PROC_CREATE, 140 NFSV2PROC_REMOVE, 141 NFSV2PROC_RMDIR, 142 NFSV2PROC_RENAME, 143 NFSV2PROC_LINK, 144 NFSV2PROC_READDIR, 145 NFSV2PROC_NOOP, 146 NFSV2PROC_STATFS, 147 NFSV2PROC_NOOP, 148 NFSV2PROC_NOOP, 149 NFSV2PROC_NOOP, 150 NFSV2PROC_NOOP 151 }; 152 153 /* 154 * Maps errno values to nfs error numbers. 155 * Use NFSERR_IO as the catch all for ones not specifically defined in 156 * RFC 1094. 157 */ 158 static u_char nfsrv_v2errmap[] = { 159 NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO, 160 NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 161 NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO, 162 NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR, 163 NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 164 NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS, 165 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 166 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 167 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 168 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 169 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 170 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 171 NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO, 172 NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE 173 /* Everything after this maps to NFSERR_IO, so far */ 174 }; 175 176 /* 177 * Maps errno values to nfs error numbers. 178 * Although it is not obvious whether or not NFS clients really care if 179 * a returned error value is in the specified list for the procedure, the 180 * safest thing to do is filter them appropriately. For Version 2, the 181 * X/Open XNFS document is the only specification that defines error values 182 * for each RPC (The RFC simply lists all possible error values for all RPCs), 183 * so I have decided to not do this for Version 2. 184 * The first entry is the default error return and the rest are the valid 185 * errors for that RPC in increasing numeric order. 186 */ 187 static short nfsv3err_null[] = { 188 0, 189 0, 190 }; 191 192 static short nfsv3err_getattr[] = { 193 NFSERR_IO, 194 NFSERR_IO, 195 NFSERR_STALE, 196 NFSERR_BADHANDLE, 197 NFSERR_SERVERFAULT, 198 0, 199 }; 200 201 static short nfsv3err_setattr[] = { 202 NFSERR_IO, 203 NFSERR_PERM, 204 NFSERR_IO, 205 NFSERR_ACCES, 206 NFSERR_INVAL, 207 NFSERR_NOSPC, 208 NFSERR_ROFS, 209 NFSERR_DQUOT, 210 NFSERR_STALE, 211 NFSERR_BADHANDLE, 212 NFSERR_NOT_SYNC, 213 NFSERR_SERVERFAULT, 214 0, 215 }; 216 217 static short nfsv3err_lookup[] = { 218 NFSERR_IO, 219 NFSERR_NOENT, 220 NFSERR_IO, 221 NFSERR_ACCES, 222 NFSERR_NOTDIR, 223 NFSERR_NAMETOL, 224 NFSERR_STALE, 225 NFSERR_BADHANDLE, 226 NFSERR_SERVERFAULT, 227 0, 228 }; 229 230 static short nfsv3err_access[] = { 231 NFSERR_IO, 232 NFSERR_IO, 233 NFSERR_STALE, 234 NFSERR_BADHANDLE, 235 NFSERR_SERVERFAULT, 236 0, 237 }; 238 239 static short nfsv3err_readlink[] = { 240 NFSERR_IO, 241 NFSERR_IO, 242 NFSERR_ACCES, 243 NFSERR_INVAL, 244 NFSERR_STALE, 245 NFSERR_BADHANDLE, 246 NFSERR_NOTSUPP, 247 NFSERR_SERVERFAULT, 248 0, 249 }; 250 251 static short nfsv3err_read[] = { 252 NFSERR_IO, 253 NFSERR_IO, 254 NFSERR_NXIO, 255 NFSERR_ACCES, 256 NFSERR_INVAL, 257 NFSERR_STALE, 258 NFSERR_BADHANDLE, 259 NFSERR_SERVERFAULT, 260 0, 261 }; 262 263 static short nfsv3err_write[] = { 264 NFSERR_IO, 265 NFSERR_IO, 266 NFSERR_ACCES, 267 NFSERR_INVAL, 268 NFSERR_FBIG, 269 NFSERR_NOSPC, 270 NFSERR_ROFS, 271 NFSERR_DQUOT, 272 NFSERR_STALE, 273 NFSERR_BADHANDLE, 274 NFSERR_SERVERFAULT, 275 0, 276 }; 277 278 static short nfsv3err_create[] = { 279 NFSERR_IO, 280 NFSERR_IO, 281 NFSERR_ACCES, 282 NFSERR_EXIST, 283 NFSERR_NOTDIR, 284 NFSERR_NOSPC, 285 NFSERR_ROFS, 286 NFSERR_NAMETOL, 287 NFSERR_DQUOT, 288 NFSERR_STALE, 289 NFSERR_BADHANDLE, 290 NFSERR_NOTSUPP, 291 NFSERR_SERVERFAULT, 292 0, 293 }; 294 295 static short nfsv3err_mkdir[] = { 296 NFSERR_IO, 297 NFSERR_IO, 298 NFSERR_ACCES, 299 NFSERR_EXIST, 300 NFSERR_NOTDIR, 301 NFSERR_NOSPC, 302 NFSERR_ROFS, 303 NFSERR_NAMETOL, 304 NFSERR_DQUOT, 305 NFSERR_STALE, 306 NFSERR_BADHANDLE, 307 NFSERR_NOTSUPP, 308 NFSERR_SERVERFAULT, 309 0, 310 }; 311 312 static short nfsv3err_symlink[] = { 313 NFSERR_IO, 314 NFSERR_IO, 315 NFSERR_ACCES, 316 NFSERR_EXIST, 317 NFSERR_NOTDIR, 318 NFSERR_NOSPC, 319 NFSERR_ROFS, 320 NFSERR_NAMETOL, 321 NFSERR_DQUOT, 322 NFSERR_STALE, 323 NFSERR_BADHANDLE, 324 NFSERR_NOTSUPP, 325 NFSERR_SERVERFAULT, 326 0, 327 }; 328 329 static short nfsv3err_mknod[] = { 330 NFSERR_IO, 331 NFSERR_IO, 332 NFSERR_ACCES, 333 NFSERR_EXIST, 334 NFSERR_NOTDIR, 335 NFSERR_NOSPC, 336 NFSERR_ROFS, 337 NFSERR_NAMETOL, 338 NFSERR_DQUOT, 339 NFSERR_STALE, 340 NFSERR_BADHANDLE, 341 NFSERR_NOTSUPP, 342 NFSERR_SERVERFAULT, 343 NFSERR_BADTYPE, 344 0, 345 }; 346 347 static short nfsv3err_remove[] = { 348 NFSERR_IO, 349 NFSERR_NOENT, 350 NFSERR_IO, 351 NFSERR_ACCES, 352 NFSERR_NOTDIR, 353 NFSERR_ROFS, 354 NFSERR_NAMETOL, 355 NFSERR_STALE, 356 NFSERR_BADHANDLE, 357 NFSERR_SERVERFAULT, 358 0, 359 }; 360 361 static short nfsv3err_rmdir[] = { 362 NFSERR_IO, 363 NFSERR_NOENT, 364 NFSERR_IO, 365 NFSERR_ACCES, 366 NFSERR_EXIST, 367 NFSERR_NOTDIR, 368 NFSERR_INVAL, 369 NFSERR_ROFS, 370 NFSERR_NAMETOL, 371 NFSERR_NOTEMPTY, 372 NFSERR_STALE, 373 NFSERR_BADHANDLE, 374 NFSERR_NOTSUPP, 375 NFSERR_SERVERFAULT, 376 0, 377 }; 378 379 static short nfsv3err_rename[] = { 380 NFSERR_IO, 381 NFSERR_NOENT, 382 NFSERR_IO, 383 NFSERR_ACCES, 384 NFSERR_EXIST, 385 NFSERR_XDEV, 386 NFSERR_NOTDIR, 387 NFSERR_ISDIR, 388 NFSERR_INVAL, 389 NFSERR_NOSPC, 390 NFSERR_ROFS, 391 NFSERR_MLINK, 392 NFSERR_NAMETOL, 393 NFSERR_NOTEMPTY, 394 NFSERR_DQUOT, 395 NFSERR_STALE, 396 NFSERR_BADHANDLE, 397 NFSERR_NOTSUPP, 398 NFSERR_SERVERFAULT, 399 0, 400 }; 401 402 static short nfsv3err_link[] = { 403 NFSERR_IO, 404 NFSERR_IO, 405 NFSERR_ACCES, 406 NFSERR_EXIST, 407 NFSERR_XDEV, 408 NFSERR_NOTDIR, 409 NFSERR_INVAL, 410 NFSERR_NOSPC, 411 NFSERR_ROFS, 412 NFSERR_MLINK, 413 NFSERR_NAMETOL, 414 NFSERR_DQUOT, 415 NFSERR_STALE, 416 NFSERR_BADHANDLE, 417 NFSERR_NOTSUPP, 418 NFSERR_SERVERFAULT, 419 0, 420 }; 421 422 static short nfsv3err_readdir[] = { 423 NFSERR_IO, 424 NFSERR_IO, 425 NFSERR_ACCES, 426 NFSERR_NOTDIR, 427 NFSERR_STALE, 428 NFSERR_BADHANDLE, 429 NFSERR_BAD_COOKIE, 430 NFSERR_TOOSMALL, 431 NFSERR_SERVERFAULT, 432 0, 433 }; 434 435 static short nfsv3err_readdirplus[] = { 436 NFSERR_IO, 437 NFSERR_IO, 438 NFSERR_ACCES, 439 NFSERR_NOTDIR, 440 NFSERR_STALE, 441 NFSERR_BADHANDLE, 442 NFSERR_BAD_COOKIE, 443 NFSERR_NOTSUPP, 444 NFSERR_TOOSMALL, 445 NFSERR_SERVERFAULT, 446 0, 447 }; 448 449 static short nfsv3err_fsstat[] = { 450 NFSERR_IO, 451 NFSERR_IO, 452 NFSERR_STALE, 453 NFSERR_BADHANDLE, 454 NFSERR_SERVERFAULT, 455 0, 456 }; 457 458 static short nfsv3err_fsinfo[] = { 459 NFSERR_STALE, 460 NFSERR_STALE, 461 NFSERR_BADHANDLE, 462 NFSERR_SERVERFAULT, 463 0, 464 }; 465 466 static short nfsv3err_pathconf[] = { 467 NFSERR_STALE, 468 NFSERR_STALE, 469 NFSERR_BADHANDLE, 470 NFSERR_SERVERFAULT, 471 0, 472 }; 473 474 static short nfsv3err_commit[] = { 475 NFSERR_IO, 476 NFSERR_IO, 477 NFSERR_STALE, 478 NFSERR_BADHANDLE, 479 NFSERR_SERVERFAULT, 480 0, 481 }; 482 483 static short *nfsrv_v3errmap[] = { 484 nfsv3err_null, 485 nfsv3err_getattr, 486 nfsv3err_setattr, 487 nfsv3err_lookup, 488 nfsv3err_access, 489 nfsv3err_readlink, 490 nfsv3err_read, 491 nfsv3err_write, 492 nfsv3err_create, 493 nfsv3err_mkdir, 494 nfsv3err_symlink, 495 nfsv3err_mknod, 496 nfsv3err_remove, 497 nfsv3err_rmdir, 498 nfsv3err_rename, 499 nfsv3err_link, 500 nfsv3err_readdir, 501 nfsv3err_readdirplus, 502 nfsv3err_fsstat, 503 nfsv3err_fsinfo, 504 nfsv3err_pathconf, 505 nfsv3err_commit, 506 }; 507 508 struct pool nfsreqpl; 509 510 /* 511 * Create the header for an rpc request packet 512 * The hsiz is the size of the rest of the nfs request header. 513 * (just used to decide if a cluster is a good idea) 514 */ 515 struct mbuf * 516 nfsm_reqhead(int hsiz) 517 { 518 struct mbuf *mb; 519 520 MGET(mb, M_WAIT, MT_DATA); 521 if (hsiz > MLEN) 522 MCLGET(mb, M_WAIT); 523 mb->m_len = 0; 524 525 /* Finally, return values */ 526 return (mb); 527 } 528 529 /* 530 * Return an unpredictable XID in XDR form. 531 */ 532 u_int32_t 533 nfs_get_xid(void) 534 { 535 static struct idgen32_ctx nfs_xid_ctx; 536 static int called = 0; 537 538 if (!called) { 539 called = 1; 540 idgen32_init(&nfs_xid_ctx); 541 } 542 return (txdr_unsigned(idgen32(&nfs_xid_ctx))); 543 } 544 545 /* 546 * Build the RPC header and fill in the authorization info. 547 * Right now we are pretty centric around RPCAUTH_UNIX, in the 548 * future, this function will need some love to be able to handle 549 * other authorization methods, such as Kerberos. 550 */ 551 void 552 nfsm_rpchead(struct nfsreq *req, struct ucred *cr, int auth_type) 553 { 554 struct mbuf *mb; 555 u_int32_t *tl; 556 int i, authsiz, auth_len, ngroups; 557 558 KASSERT(auth_type == RPCAUTH_UNIX); 559 560 /* 561 * RPCAUTH_UNIX fits in an hdr mbuf, in the future other 562 * authorization methods need to figure out their own sizes 563 * and allocate and chain mbuf's accorindgly. 564 */ 565 mb = req->r_mreq; 566 567 /* 568 * We need to start out by finding how big the authorization cred 569 * and verifer are for the auth_type, to be able to correctly 570 * align the mbuf header/chain. 571 */ 572 switch (auth_type) { 573 case RPCAUTH_UNIX: 574 /* 575 * In the RPCAUTH_UNIX case, the size is the static 576 * part as shown in RFC1831 + the number of groups, 577 * RPCAUTH_UNIX has a zero verifer. 578 */ 579 if (cr->cr_ngroups > req->r_nmp->nm_numgrps) 580 ngroups = req->r_nmp->nm_numgrps; 581 else 582 ngroups = cr->cr_ngroups; 583 584 auth_len = (ngroups << 2) + 5 * NFSX_UNSIGNED; 585 authsiz = nfsm_rndup(auth_len); 586 /* The authorization size + the size of the static part */ 587 MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED); 588 break; 589 } 590 591 mb->m_len = 0; 592 593 /* First the RPC header. */ 594 tl = nfsm_build(&mb, 6 * NFSX_UNSIGNED); 595 596 /* Get a new (non-zero) xid */ 597 *tl++ = req->r_xid = nfs_get_xid(); 598 *tl++ = rpc_call; 599 *tl++ = rpc_vers; 600 *tl++ = nfs_prog; 601 if (ISSET(req->r_nmp->nm_flag, NFSMNT_NFSV3)) { 602 *tl++ = txdr_unsigned(NFS_VER3); 603 *tl = txdr_unsigned(req->r_procnum); 604 } else { 605 *tl++ = txdr_unsigned(NFS_VER2); 606 *tl = txdr_unsigned(nfsv2_procid[req->r_procnum]); 607 } 608 609 /* The Authorization cred and its verifier */ 610 switch (auth_type) { 611 case RPCAUTH_UNIX: 612 tl = nfsm_build(&mb, auth_len + 4 * NFSX_UNSIGNED); 613 *tl++ = txdr_unsigned(RPCAUTH_UNIX); 614 *tl++ = txdr_unsigned(authsiz); 615 616 /* The authorization cred */ 617 *tl++ = 0; /* stamp */ 618 *tl++ = 0; /* NULL hostname */ 619 *tl++ = txdr_unsigned(cr->cr_uid); 620 *tl++ = txdr_unsigned(cr->cr_gid); 621 *tl++ = txdr_unsigned(ngroups); 622 for (i = 0; i < ngroups; i++) 623 *tl++ = txdr_unsigned(cr->cr_groups[i]); 624 /* The authorization verifier */ 625 *tl++ = txdr_unsigned(RPCAUTH_NULL); 626 *tl = 0; 627 break; 628 } 629 630 mb->m_pkthdr.len += authsiz + 10 * NFSX_UNSIGNED; 631 mb->m_pkthdr.rcvif = NULL; 632 } 633 634 /* 635 * copies mbuf chain to the uio scatter/gather list 636 */ 637 int 638 nfsm_mbuftouio(struct mbuf **mrep, struct uio *uiop, int siz, caddr_t *dpos) 639 { 640 char *mbufcp, *uiocp; 641 int xfer, left, len; 642 struct mbuf *mp; 643 long uiosiz, rem; 644 int error = 0; 645 646 mp = *mrep; 647 mbufcp = *dpos; 648 len = mtod(mp, caddr_t)+mp->m_len-mbufcp; 649 rem = nfsm_padlen(siz); 650 while (siz > 0) { 651 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 652 return (EFBIG); 653 left = uiop->uio_iov->iov_len; 654 uiocp = uiop->uio_iov->iov_base; 655 if (left > siz) 656 left = siz; 657 uiosiz = left; 658 while (left > 0) { 659 while (len == 0) { 660 mp = mp->m_next; 661 if (mp == NULL) 662 return (EBADRPC); 663 mbufcp = mtod(mp, caddr_t); 664 len = mp->m_len; 665 } 666 xfer = (left > len) ? len : left; 667 if (uiop->uio_segflg == UIO_SYSSPACE) 668 bcopy(mbufcp, uiocp, xfer); 669 else 670 copyout(mbufcp, uiocp, xfer); 671 left -= xfer; 672 len -= xfer; 673 mbufcp += xfer; 674 uiocp += xfer; 675 uiop->uio_offset += xfer; 676 uiop->uio_resid -= xfer; 677 } 678 if (uiop->uio_iov->iov_len <= siz) { 679 uiop->uio_iovcnt--; 680 uiop->uio_iov++; 681 } else { 682 uiop->uio_iov->iov_base = 683 (char *)uiop->uio_iov->iov_base + uiosiz; 684 uiop->uio_iov->iov_len -= uiosiz; 685 } 686 siz -= uiosiz; 687 } 688 *dpos = mbufcp; 689 *mrep = mp; 690 if (rem > 0) { 691 if (len < rem) 692 error = nfs_adv(mrep, dpos, rem, len); 693 else 694 *dpos += rem; 695 } 696 return (error); 697 } 698 699 /* 700 * Copy a uio scatter/gather list to an mbuf chain. 701 */ 702 void 703 nfsm_uiotombuf(struct mbuf **mp, struct uio *uiop, size_t len) 704 { 705 struct mbuf *mb, *mb2; 706 size_t xfer, pad; 707 708 mb = *mp; 709 710 pad = nfsm_padlen(len); 711 712 /* XXX -- the following should be done by the caller */ 713 uiop->uio_resid = len; 714 uiop->uio_rw = UIO_WRITE; 715 716 while (len) { 717 xfer = min(len, M_TRAILINGSPACE(mb)); 718 uiomove(mb_offset(mb), xfer, uiop); 719 mb->m_len += xfer; 720 len -= xfer; 721 if (len > 0) { 722 MGET(mb2, M_WAIT, MT_DATA); 723 if (len > MLEN) 724 MCLGET(mb2, M_WAIT); 725 mb2->m_len = 0; 726 mb->m_next = mb2; 727 mb = mb2; 728 } 729 } 730 731 if (pad > 0) { 732 if (pad > M_TRAILINGSPACE(mb)) { 733 MGET(mb2, M_WAIT, MT_DATA); 734 mb2->m_len = 0; 735 mb->m_next = mb2; 736 mb = mb2; 737 } 738 bzero(mb_offset(mb), pad); 739 mb->m_len += pad; 740 } 741 742 *mp = mb; 743 } 744 745 /* 746 * Copy a buffer to an mbuf chain 747 */ 748 void 749 nfsm_buftombuf(struct mbuf **mp, void *buf, size_t len) 750 { 751 struct iovec iov; 752 struct uio io; 753 754 iov.iov_base = buf; 755 iov.iov_len = len; 756 757 io.uio_iov = &iov; 758 io.uio_iovcnt = 1; 759 io.uio_resid = len; 760 io.uio_segflg = UIO_SYSSPACE; 761 io.uio_rw = UIO_WRITE; 762 763 nfsm_uiotombuf(mp, &io, len); 764 } 765 766 /* 767 * Copy a string to an mbuf chain 768 */ 769 void 770 nfsm_strtombuf(struct mbuf **mp, void *str, size_t len) 771 { 772 struct iovec iov[2]; 773 struct uio io; 774 uint32_t strlen; 775 776 strlen = txdr_unsigned(len); 777 778 iov[0].iov_base = &strlen; 779 iov[0].iov_len = sizeof(uint32_t); 780 iov[1].iov_base = str; 781 iov[1].iov_len = len; 782 783 io.uio_iov = iov; 784 io.uio_iovcnt = 2; 785 io.uio_resid = sizeof(uint32_t) + len; 786 io.uio_segflg = UIO_SYSSPACE; 787 io.uio_rw = UIO_WRITE; 788 789 nfsm_uiotombuf(mp, &io, io.uio_resid); 790 } 791 792 /* 793 * Help break down an mbuf chain by setting the first siz bytes contiguous 794 * pointed to by returned val. 795 * This is used by the macros nfsm_dissect and nfsm_dissecton for tough 796 * cases. (The macros use the vars. dpos and dpos2) 797 */ 798 int 799 nfsm_disct(struct mbuf **mdp, caddr_t *dposp, int siz, int left, caddr_t *cp2) 800 { 801 struct mbuf *mp, *mp2; 802 int siz2, xfer; 803 caddr_t p; 804 805 mp = *mdp; 806 while (left == 0) { 807 *mdp = mp = mp->m_next; 808 if (mp == NULL) 809 return (EBADRPC); 810 left = mp->m_len; 811 *dposp = mtod(mp, caddr_t); 812 } 813 if (left >= siz) { 814 *cp2 = *dposp; 815 *dposp += siz; 816 } else if (mp->m_next == NULL) { 817 return (EBADRPC); 818 } else if (siz > MHLEN) { 819 panic("nfs S too big"); 820 } else { 821 MGET(mp2, M_WAIT, MT_DATA); 822 mp2->m_next = mp->m_next; 823 mp->m_next = mp2; 824 mp->m_len -= left; 825 mp = mp2; 826 *cp2 = p = mtod(mp, caddr_t); 827 bcopy(*dposp, p, left); /* Copy what was left */ 828 siz2 = siz-left; 829 p += left; 830 mp2 = mp->m_next; 831 /* Loop around copying up the siz2 bytes */ 832 while (siz2 > 0) { 833 if (mp2 == NULL) 834 return (EBADRPC); 835 xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2; 836 if (xfer > 0) { 837 bcopy(mtod(mp2, caddr_t), p, xfer); 838 mp2->m_data += xfer; 839 mp2->m_len -= xfer; 840 p += xfer; 841 siz2 -= xfer; 842 } 843 if (siz2 > 0) 844 mp2 = mp2->m_next; 845 } 846 mp->m_len = siz; 847 *mdp = mp2; 848 *dposp = mtod(mp2, caddr_t); 849 } 850 return (0); 851 } 852 853 /* 854 * Advance the position in the mbuf chain. 855 */ 856 int 857 nfs_adv(struct mbuf **mdp, caddr_t *dposp, int offs, int left) 858 { 859 struct mbuf *m; 860 int s; 861 862 m = *mdp; 863 s = left; 864 while (s < offs) { 865 offs -= s; 866 m = m->m_next; 867 if (m == NULL) 868 return (EBADRPC); 869 s = m->m_len; 870 } 871 *mdp = m; 872 *dposp = mtod(m, caddr_t)+offs; 873 return (0); 874 } 875 876 /* 877 * Called once to initialize data structures... 878 */ 879 void 880 nfs_init(void) 881 { 882 rpc_vers = txdr_unsigned(RPC_VER2); 883 rpc_call = txdr_unsigned(RPC_CALL); 884 rpc_reply = txdr_unsigned(RPC_REPLY); 885 rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED); 886 rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED); 887 rpc_mismatch = txdr_unsigned(RPC_MISMATCH); 888 rpc_autherr = txdr_unsigned(RPC_AUTHERR); 889 rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX); 890 nfs_prog = txdr_unsigned(NFS_PROG); 891 nfs_true = txdr_unsigned(1); 892 nfs_false = txdr_unsigned(0); 893 nfs_xdrneg1 = txdr_unsigned(-1); 894 nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000; 895 if (nfs_ticks < 1) 896 nfs_ticks = 1; 897 #ifdef NFSSERVER 898 nfsrv_init(0); /* Init server data structures */ 899 nfsrv_initcache(); /* Init the server request cache */ 900 #endif /* NFSSERVER */ 901 902 pool_init(&nfsreqpl, sizeof(struct nfsreq), 0, 0, 0, "nfsreqpl", 903 &pool_allocator_nointr); 904 } 905 906 #ifdef NFSCLIENT 907 int 908 nfs_vfs_init(struct vfsconf *vfsp) 909 { 910 extern struct pool nfs_node_pool; 911 912 TAILQ_INIT(&nfs_bufq); 913 914 pool_init(&nfs_node_pool, sizeof(struct nfsnode), 0, 0, 0, 915 "nfsnodepl", NULL); 916 917 return (0); 918 } 919 920 /* 921 * Attribute cache routines. 922 * nfs_loadattrcache() - loads or updates the cache contents from attributes 923 * that are on the mbuf list 924 * nfs_getattrcache() - returns valid attributes if found in cache, returns 925 * error otherwise 926 */ 927 928 /* 929 * Load the attribute cache (that lives in the nfsnode entry) with 930 * the values on the mbuf list and 931 * Iff vap not NULL 932 * copy the attributes to *vaper 933 */ 934 int 935 nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp, 936 struct vattr *vaper) 937 { 938 struct vnode *vp = *vpp; 939 struct vattr *vap; 940 struct nfs_fattr *fp; 941 extern struct vops nfs_specvops; 942 struct nfsnode *np; 943 int32_t t1; 944 caddr_t cp2; 945 int error = 0; 946 int32_t rdev; 947 struct mbuf *md; 948 enum vtype vtyp; 949 mode_t vmode; 950 struct timespec mtime; 951 struct vnode *nvp; 952 int v3 = NFS_ISV3(vp); 953 uid_t uid; 954 gid_t gid; 955 956 md = *mdp; 957 t1 = (mtod(md, caddr_t) + md->m_len) - *dposp; 958 error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2); 959 if (error) 960 return (error); 961 fp = (struct nfs_fattr *)cp2; 962 if (v3) { 963 vtyp = nfsv3tov_type(fp->fa_type); 964 vmode = fxdr_unsigned(mode_t, fp->fa_mode); 965 rdev = makedev(fxdr_unsigned(u_int32_t, fp->fa3_rdev.specdata1), 966 fxdr_unsigned(u_int32_t, fp->fa3_rdev.specdata2)); 967 fxdr_nfsv3time(&fp->fa3_mtime, &mtime); 968 } else { 969 vtyp = nfsv2tov_type(fp->fa_type); 970 vmode = fxdr_unsigned(mode_t, fp->fa_mode); 971 if (vtyp == VNON || vtyp == VREG) 972 vtyp = IFTOVT(vmode); 973 rdev = fxdr_unsigned(int32_t, fp->fa2_rdev); 974 fxdr_nfsv2time(&fp->fa2_mtime, &mtime); 975 976 /* 977 * Really ugly NFSv2 kludge. 978 */ 979 if (vtyp == VCHR && rdev == 0xffffffff) 980 vtyp = VFIFO; 981 } 982 983 /* 984 * If v_type == VNON it is a new node, so fill in the v_type, 985 * n_mtime fields. Check to see if it represents a special 986 * device, and if so, check for a possible alias. Once the 987 * correct vnode has been obtained, fill in the rest of the 988 * information. 989 */ 990 np = VTONFS(vp); 991 if (vp->v_type != vtyp) { 992 cache_purge(vp); 993 vp->v_type = vtyp; 994 if (vp->v_type == VFIFO) { 995 #ifndef FIFO 996 return (EOPNOTSUPP); 997 #else 998 extern struct vops nfs_fifovops; 999 vp->v_op = &nfs_fifovops; 1000 #endif /* FIFO */ 1001 } 1002 if (vp->v_type == VCHR || vp->v_type == VBLK) { 1003 vp->v_op = &nfs_specvops; 1004 nvp = checkalias(vp, (dev_t)rdev, vp->v_mount); 1005 if (nvp) { 1006 /* 1007 * Discard unneeded vnode, but save its nfsnode. 1008 * Since the nfsnode does not have a lock, its 1009 * vnode lock has to be carried over. 1010 */ 1011 1012 nvp->v_data = vp->v_data; 1013 vp->v_data = NULL; 1014 vp->v_op = &spec_vops; 1015 vrele(vp); 1016 vgone(vp); 1017 /* 1018 * Reinitialize aliased node. 1019 */ 1020 np->n_vnode = nvp; 1021 *vpp = vp = nvp; 1022 } 1023 } 1024 np->n_mtime = mtime; 1025 } 1026 vap = &np->n_vattr; 1027 vap->va_type = vtyp; 1028 vap->va_rdev = (dev_t)rdev; 1029 vap->va_mtime = mtime; 1030 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 1031 1032 uid = fxdr_unsigned(uid_t, fp->fa_uid); 1033 gid = fxdr_unsigned(gid_t, fp->fa_gid); 1034 /* Invalidate access cache if uid, gid or mode changed. */ 1035 if (np->n_accstamp != -1 && 1036 (gid != vap->va_gid || uid != vap->va_uid || 1037 (vmode & 07777) != vap->va_mode)) 1038 np->n_accstamp = -1; 1039 1040 vap->va_mode = (vmode & 07777); 1041 1042 switch (vtyp) { 1043 case VBLK: 1044 vap->va_blocksize = BLKDEV_IOSIZE; 1045 break; 1046 case VCHR: 1047 vap->va_blocksize = MAXBSIZE; 1048 break; 1049 default: 1050 vap->va_blocksize = v3 ? vp->v_mount->mnt_stat.f_iosize : 1051 fxdr_unsigned(int32_t, fp->fa2_blocksize); 1052 break; 1053 } 1054 if (v3) { 1055 vap->va_nlink = fxdr_unsigned(nlink_t, fp->fa_nlink); 1056 vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid); 1057 vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid); 1058 vap->va_size = fxdr_hyper(&fp->fa3_size); 1059 vap->va_bytes = fxdr_hyper(&fp->fa3_used); 1060 vap->va_fileid = fxdr_hyper(&fp->fa3_fileid); 1061 fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime); 1062 fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime); 1063 vap->va_flags = 0; 1064 vap->va_filerev = 0; 1065 } else { 1066 vap->va_nlink = fxdr_unsigned(nlink_t, fp->fa_nlink); 1067 vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid); 1068 vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid); 1069 vap->va_size = fxdr_unsigned(u_int32_t, fp->fa2_size); 1070 vap->va_bytes = 1071 (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) * 1072 NFS_FABLKSIZE; 1073 vap->va_fileid = fxdr_unsigned(int32_t, fp->fa2_fileid); 1074 fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime); 1075 vap->va_flags = 0; 1076 vap->va_ctime.tv_sec = fxdr_unsigned(u_int32_t, 1077 fp->fa2_ctime.nfsv2_sec); 1078 vap->va_ctime.tv_nsec = 0; 1079 vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec); 1080 vap->va_filerev = 0; 1081 } 1082 1083 if (vap->va_size != np->n_size) { 1084 if (vap->va_type == VREG) { 1085 if (np->n_flag & NMODIFIED) { 1086 if (vap->va_size < np->n_size) 1087 vap->va_size = np->n_size; 1088 else 1089 np->n_size = vap->va_size; 1090 } else 1091 np->n_size = vap->va_size; 1092 uvm_vnp_setsize(vp, np->n_size); 1093 } else 1094 np->n_size = vap->va_size; 1095 } 1096 np->n_attrstamp = time_second; 1097 if (vaper != NULL) { 1098 bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap)); 1099 if (np->n_flag & NCHG) { 1100 if (np->n_flag & NACC) 1101 vaper->va_atime = np->n_atim; 1102 if (np->n_flag & NUPD) 1103 vaper->va_mtime = np->n_mtim; 1104 } 1105 } 1106 return (0); 1107 } 1108 1109 int 1110 nfs_attrtimeo(struct nfsnode *np) 1111 { 1112 struct vnode *vp = np->n_vnode; 1113 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1114 int tenthage = (time_second - np->n_mtime.tv_sec) / 10; 1115 int minto, maxto; 1116 1117 if (vp->v_type == VDIR) { 1118 maxto = nmp->nm_acdirmax; 1119 minto = nmp->nm_acdirmin; 1120 } 1121 else { 1122 maxto = nmp->nm_acregmax; 1123 minto = nmp->nm_acregmin; 1124 } 1125 1126 if (np->n_flag & NMODIFIED || tenthage < minto) 1127 return minto; 1128 else if (tenthage < maxto) 1129 return tenthage; 1130 else 1131 return maxto; 1132 } 1133 1134 /* 1135 * Check the time stamp 1136 * If the cache is valid, copy contents to *vap and return 0 1137 * otherwise return an error 1138 */ 1139 int 1140 nfs_getattrcache(struct vnode *vp, struct vattr *vaper) 1141 { 1142 struct nfsnode *np = VTONFS(vp); 1143 struct vattr *vap; 1144 1145 if (np->n_attrstamp == 0 || 1146 (time_second - np->n_attrstamp) >= nfs_attrtimeo(np)) { 1147 nfsstats.attrcache_misses++; 1148 return (ENOENT); 1149 } 1150 nfsstats.attrcache_hits++; 1151 vap = &np->n_vattr; 1152 if (vap->va_size != np->n_size) { 1153 if (vap->va_type == VREG) { 1154 if (np->n_flag & NMODIFIED) { 1155 if (vap->va_size < np->n_size) 1156 vap->va_size = np->n_size; 1157 else 1158 np->n_size = vap->va_size; 1159 } else 1160 np->n_size = vap->va_size; 1161 uvm_vnp_setsize(vp, np->n_size); 1162 } else 1163 np->n_size = vap->va_size; 1164 } 1165 bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr)); 1166 if (np->n_flag & NCHG) { 1167 if (np->n_flag & NACC) 1168 vaper->va_atime = np->n_atim; 1169 if (np->n_flag & NUPD) 1170 vaper->va_mtime = np->n_mtim; 1171 } 1172 return (0); 1173 } 1174 #endif /* NFSCLIENT */ 1175 1176 /* 1177 * Set up nameidata for a lookup() call and do it 1178 */ 1179 int 1180 nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len, 1181 struct nfssvc_sock *slp, struct mbuf *nam, struct mbuf **mdp, 1182 caddr_t *dposp, struct vnode **retdirp, struct proc *p) 1183 { 1184 int i, rem; 1185 struct mbuf *md; 1186 char *fromcp, *tocp; 1187 struct vnode *dp; 1188 int error, rdonly; 1189 struct componentname *cnp = &ndp->ni_cnd; 1190 1191 *retdirp = NULL; 1192 cnp->cn_pnbuf = pool_get(&namei_pool, PR_WAITOK); 1193 /* 1194 * Copy the name from the mbuf list to ndp->ni_pnbuf 1195 * and set the various ndp fields appropriately. 1196 */ 1197 fromcp = *dposp; 1198 tocp = cnp->cn_pnbuf; 1199 md = *mdp; 1200 rem = mtod(md, caddr_t) + md->m_len - fromcp; 1201 for (i = 0; i < len; i++) { 1202 while (rem == 0) { 1203 md = md->m_next; 1204 if (md == NULL) { 1205 error = EBADRPC; 1206 goto out; 1207 } 1208 fromcp = mtod(md, caddr_t); 1209 rem = md->m_len; 1210 } 1211 if (*fromcp == '\0' || *fromcp == '/') { 1212 error = EACCES; 1213 goto out; 1214 } 1215 *tocp++ = *fromcp++; 1216 rem--; 1217 } 1218 *tocp = '\0'; 1219 *mdp = md; 1220 *dposp = fromcp; 1221 len = nfsm_padlen(len); 1222 if (len > 0) { 1223 if (rem >= len) 1224 *dposp += len; 1225 else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0) 1226 goto out; 1227 } 1228 ndp->ni_pathlen = tocp - cnp->cn_pnbuf; 1229 cnp->cn_nameptr = cnp->cn_pnbuf; 1230 /* 1231 * Extract and set starting directory. 1232 */ 1233 error = nfsrv_fhtovp(fhp, 0, &dp, ndp->ni_cnd.cn_cred, slp, 1234 nam, &rdonly); 1235 if (error) 1236 goto out; 1237 if (dp->v_type != VDIR) { 1238 vrele(dp); 1239 error = ENOTDIR; 1240 goto out; 1241 } 1242 vref(dp); 1243 *retdirp = dp; 1244 ndp->ni_startdir = dp; 1245 if (rdonly) 1246 cnp->cn_flags |= (NOCROSSMOUNT | RDONLY); 1247 else 1248 cnp->cn_flags |= NOCROSSMOUNT; 1249 /* 1250 * And call lookup() to do the real work 1251 */ 1252 cnp->cn_proc = p; 1253 error = vfs_lookup(ndp); 1254 if (error) 1255 goto out; 1256 /* 1257 * Check for encountering a symbolic link 1258 */ 1259 if (cnp->cn_flags & ISSYMLINK) { 1260 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) 1261 vput(ndp->ni_dvp); 1262 else 1263 vrele(ndp->ni_dvp); 1264 vput(ndp->ni_vp); 1265 ndp->ni_vp = NULL; 1266 error = EINVAL; 1267 goto out; 1268 } 1269 /* 1270 * Check for saved name request 1271 */ 1272 if (cnp->cn_flags & (SAVENAME | SAVESTART)) { 1273 cnp->cn_flags |= HASBUF; 1274 return (0); 1275 } 1276 out: 1277 pool_put(&namei_pool, cnp->cn_pnbuf); 1278 return (error); 1279 } 1280 1281 /* 1282 * A fiddled version of m_adj() that ensures null fill to a long 1283 * boundary and only trims off the back end 1284 */ 1285 void 1286 nfsm_adj(struct mbuf *mp, int len, int nul) 1287 { 1288 struct mbuf *m; 1289 int count, i; 1290 char *cp; 1291 1292 /* 1293 * Trim from tail. Scan the mbuf chain, 1294 * calculating its length and finding the last mbuf. 1295 * If the adjustment only affects this mbuf, then just 1296 * adjust and return. Otherwise, rescan and truncate 1297 * after the remaining size. 1298 */ 1299 count = 0; 1300 m = mp; 1301 for (;;) { 1302 count += m->m_len; 1303 if (m->m_next == NULL) 1304 break; 1305 m = m->m_next; 1306 } 1307 if (m->m_len > len) { 1308 m->m_len -= len; 1309 if (nul > 0) { 1310 cp = mtod(m, caddr_t)+m->m_len-nul; 1311 for (i = 0; i < nul; i++) 1312 *cp++ = '\0'; 1313 } 1314 return; 1315 } 1316 count -= len; 1317 if (count < 0) 1318 count = 0; 1319 /* 1320 * Correct length for chain is "count". 1321 * Find the mbuf with last data, adjust its length, 1322 * and toss data from remaining mbufs on chain. 1323 */ 1324 for (m = mp; m; m = m->m_next) { 1325 if (m->m_len >= count) { 1326 m->m_len = count; 1327 if (nul > 0) { 1328 cp = mtod(m, caddr_t)+m->m_len-nul; 1329 for (i = 0; i < nul; i++) 1330 *cp++ = '\0'; 1331 } 1332 break; 1333 } 1334 count -= m->m_len; 1335 } 1336 for (m = m->m_next;m;m = m->m_next) 1337 m->m_len = 0; 1338 } 1339 1340 /* 1341 * Make these functions instead of macros, so that the kernel text size 1342 * doesn't get too big... 1343 */ 1344 void 1345 nfsm_srvwcc(struct nfsrv_descript *nfsd, int before_ret, 1346 struct vattr *before_vap, int after_ret, struct vattr *after_vap, 1347 struct nfsm_info *info) 1348 { 1349 u_int32_t *tl; 1350 1351 if (before_ret) { 1352 tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED); 1353 *tl = nfs_false; 1354 } else { 1355 tl = nfsm_build(&info->nmi_mb, 7 * NFSX_UNSIGNED); 1356 *tl++ = nfs_true; 1357 txdr_hyper(before_vap->va_size, tl); 1358 tl += 2; 1359 txdr_nfsv3time(&(before_vap->va_mtime), tl); 1360 tl += 2; 1361 txdr_nfsv3time(&(before_vap->va_ctime), tl); 1362 } 1363 nfsm_srvpostop_attr(nfsd, after_ret, after_vap, info); 1364 } 1365 1366 void 1367 nfsm_srvpostop_attr(struct nfsrv_descript *nfsd, int after_ret, 1368 struct vattr *after_vap, struct nfsm_info *info) 1369 { 1370 u_int32_t *tl; 1371 struct nfs_fattr *fp; 1372 1373 if (after_ret) { 1374 tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED); 1375 *tl = nfs_false; 1376 } else { 1377 tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED + NFSX_V3FATTR); 1378 *tl++ = nfs_true; 1379 fp = (struct nfs_fattr *)tl; 1380 nfsm_srvfattr(nfsd, after_vap, fp); 1381 } 1382 } 1383 1384 void 1385 nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap, 1386 struct nfs_fattr *fp) 1387 { 1388 1389 fp->fa_nlink = txdr_unsigned(vap->va_nlink); 1390 fp->fa_uid = txdr_unsigned(vap->va_uid); 1391 fp->fa_gid = txdr_unsigned(vap->va_gid); 1392 if (nfsd->nd_flag & ND_NFSV3) { 1393 fp->fa_type = vtonfsv3_type(vap->va_type); 1394 fp->fa_mode = vtonfsv3_mode(vap->va_mode); 1395 txdr_hyper(vap->va_size, &fp->fa3_size); 1396 txdr_hyper(vap->va_bytes, &fp->fa3_used); 1397 fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev)); 1398 fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev)); 1399 fp->fa3_fsid.nfsuquad[0] = 0; 1400 fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid); 1401 txdr_hyper(vap->va_fileid, &fp->fa3_fileid); 1402 txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime); 1403 txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime); 1404 txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime); 1405 } else { 1406 fp->fa_type = vtonfsv2_type(vap->va_type); 1407 fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1408 fp->fa2_size = txdr_unsigned(vap->va_size); 1409 fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize); 1410 if (vap->va_type == VFIFO) 1411 fp->fa2_rdev = 0xffffffff; 1412 else 1413 fp->fa2_rdev = txdr_unsigned(vap->va_rdev); 1414 fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); 1415 fp->fa2_fsid = txdr_unsigned(vap->va_fsid); 1416 fp->fa2_fileid = txdr_unsigned((u_int32_t)vap->va_fileid); 1417 txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime); 1418 txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime); 1419 txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime); 1420 } 1421 } 1422 1423 /* 1424 * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked) 1425 * - look up fsid in mount list (if not found ret error) 1426 * - get vp and export rights by calling VFS_FHTOVP() and VFS_CHECKEXP() 1427 * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon 1428 * - if not lockflag unlock it with VOP_UNLOCK() 1429 */ 1430 int 1431 nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, 1432 struct ucred *cred, struct nfssvc_sock *slp, struct mbuf *nam, 1433 int *rdonlyp) 1434 { 1435 struct proc *p = curproc; /* XXX */ 1436 struct mount *mp; 1437 int i; 1438 struct ucred *credanon; 1439 int error, exflags; 1440 struct sockaddr_in *saddr; 1441 1442 *vpp = NULL; 1443 mp = vfs_getvfs(&fhp->fh_fsid); 1444 1445 if (!mp) 1446 return (ESTALE); 1447 error = VFS_CHECKEXP(mp, nam, &exflags, &credanon); 1448 if (error) 1449 return (error); 1450 error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp); 1451 if (error) 1452 return (error); 1453 1454 saddr = mtod(nam, struct sockaddr_in *); 1455 if (saddr->sin_family == AF_INET && 1456 (ntohs(saddr->sin_port) >= IPPORT_RESERVED || 1457 (slp->ns_so->so_type == SOCK_STREAM && ntohs(saddr->sin_port) == 20))) { 1458 vput(*vpp); 1459 return (NFSERR_AUTHERR | AUTH_TOOWEAK); 1460 } 1461 1462 /* Check/setup credentials. */ 1463 if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) { 1464 cred->cr_uid = credanon->cr_uid; 1465 cred->cr_gid = credanon->cr_gid; 1466 for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++) 1467 cred->cr_groups[i] = credanon->cr_groups[i]; 1468 cred->cr_ngroups = i; 1469 } 1470 if (exflags & MNT_EXRDONLY) 1471 *rdonlyp = 1; 1472 else 1473 *rdonlyp = 0; 1474 if (!lockflag) 1475 VOP_UNLOCK(*vpp, 0, p); 1476 1477 return (0); 1478 } 1479 1480 /* 1481 * This function compares two net addresses by family and returns non zero 1482 * if they are the same host, or if there is any doubt it returns 0. 1483 * The AF_INET family is handled as a special case so that address mbufs 1484 * don't need to be saved to store "struct in_addr", which is only 4 bytes. 1485 */ 1486 int 1487 netaddr_match(int family, union nethostaddr *haddr, struct mbuf *nam) 1488 { 1489 struct sockaddr_in *inetaddr; 1490 1491 switch (family) { 1492 case AF_INET: 1493 inetaddr = mtod(nam, struct sockaddr_in *); 1494 if (inetaddr->sin_family == AF_INET && 1495 inetaddr->sin_addr.s_addr == haddr->had_inetaddr) 1496 return (1); 1497 break; 1498 default: 1499 break; 1500 }; 1501 return (0); 1502 } 1503 1504 /* 1505 * The write verifier has changed (probably due to a server reboot), so all 1506 * B_NEEDCOMMIT blocks will have to be written again. Since they are on the 1507 * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT 1508 * flag. Once done the new write verifier can be set for the mount point. 1509 */ 1510 void 1511 nfs_clearcommit(struct mount *mp) 1512 { 1513 struct vnode *vp, *nvp; 1514 struct buf *bp, *nbp; 1515 int s; 1516 1517 s = splbio(); 1518 loop: 1519 for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp != NULL; vp = nvp) { 1520 if (vp->v_mount != mp) /* Paranoia */ 1521 goto loop; 1522 nvp = LIST_NEXT(vp, v_mntvnodes); 1523 for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) { 1524 nbp = LIST_NEXT(bp, b_vnbufs); 1525 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 1526 == (B_DELWRI | B_NEEDCOMMIT)) 1527 bp->b_flags &= ~B_NEEDCOMMIT; 1528 } 1529 } 1530 splx(s); 1531 } 1532 1533 void 1534 nfs_merge_commit_ranges(struct vnode *vp) 1535 { 1536 struct nfsnode *np = VTONFS(vp); 1537 1538 if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) { 1539 np->n_pushedlo = np->n_pushlo; 1540 np->n_pushedhi = np->n_pushhi; 1541 np->n_commitflags |= NFS_COMMIT_PUSHED_VALID; 1542 } else { 1543 if (np->n_pushlo < np->n_pushedlo) 1544 np->n_pushedlo = np->n_pushlo; 1545 if (np->n_pushhi > np->n_pushedhi) 1546 np->n_pushedhi = np->n_pushhi; 1547 } 1548 1549 np->n_pushlo = np->n_pushhi = 0; 1550 np->n_commitflags &= ~NFS_COMMIT_PUSH_VALID; 1551 } 1552 1553 int 1554 nfs_in_committed_range(struct vnode *vp, struct buf *bp) 1555 { 1556 struct nfsnode *np = VTONFS(vp); 1557 off_t lo, hi; 1558 1559 if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) 1560 return 0; 1561 lo = (off_t)bp->b_blkno * DEV_BSIZE; 1562 hi = lo + bp->b_dirtyend; 1563 1564 return (lo >= np->n_pushedlo && hi <= np->n_pushedhi); 1565 } 1566 1567 int 1568 nfs_in_tobecommitted_range(struct vnode *vp, struct buf *bp) 1569 { 1570 struct nfsnode *np = VTONFS(vp); 1571 off_t lo, hi; 1572 1573 if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID)) 1574 return 0; 1575 lo = (off_t)bp->b_blkno * DEV_BSIZE; 1576 hi = lo + bp->b_dirtyend; 1577 1578 return (lo >= np->n_pushlo && hi <= np->n_pushhi); 1579 } 1580 1581 void 1582 nfs_add_committed_range(struct vnode *vp, struct buf *bp) 1583 { 1584 struct nfsnode *np = VTONFS(vp); 1585 off_t lo, hi; 1586 1587 lo = (off_t)bp->b_blkno * DEV_BSIZE; 1588 hi = lo + bp->b_dirtyend; 1589 1590 if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) { 1591 np->n_pushedlo = lo; 1592 np->n_pushedhi = hi; 1593 np->n_commitflags |= NFS_COMMIT_PUSHED_VALID; 1594 } else { 1595 if (hi > np->n_pushedhi) 1596 np->n_pushedhi = hi; 1597 if (lo < np->n_pushedlo) 1598 np->n_pushedlo = lo; 1599 } 1600 } 1601 1602 void 1603 nfs_del_committed_range(struct vnode *vp, struct buf *bp) 1604 { 1605 struct nfsnode *np = VTONFS(vp); 1606 off_t lo, hi; 1607 1608 if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) 1609 return; 1610 1611 lo = (off_t)bp->b_blkno * DEV_BSIZE; 1612 hi = lo + bp->b_dirtyend; 1613 1614 if (lo > np->n_pushedhi || hi < np->n_pushedlo) 1615 return; 1616 if (lo <= np->n_pushedlo) 1617 np->n_pushedlo = hi; 1618 else if (hi >= np->n_pushedhi) 1619 np->n_pushedhi = lo; 1620 else { 1621 /* 1622 * XXX There's only one range. If the deleted range 1623 * is in the middle, pick the largest of the 1624 * contiguous ranges that it leaves. 1625 */ 1626 if ((np->n_pushedlo - lo) > (hi - np->n_pushedhi)) 1627 np->n_pushedhi = lo; 1628 else 1629 np->n_pushedlo = hi; 1630 } 1631 } 1632 1633 void 1634 nfs_add_tobecommitted_range(struct vnode *vp, struct buf *bp) 1635 { 1636 struct nfsnode *np = VTONFS(vp); 1637 off_t lo, hi; 1638 1639 lo = (off_t)bp->b_blkno * DEV_BSIZE; 1640 hi = lo + bp->b_dirtyend; 1641 1642 if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID)) { 1643 np->n_pushlo = lo; 1644 np->n_pushhi = hi; 1645 np->n_commitflags |= NFS_COMMIT_PUSH_VALID; 1646 } else { 1647 if (lo < np->n_pushlo) 1648 np->n_pushlo = lo; 1649 if (hi > np->n_pushhi) 1650 np->n_pushhi = hi; 1651 } 1652 } 1653 1654 void 1655 nfs_del_tobecommitted_range(struct vnode *vp, struct buf *bp) 1656 { 1657 struct nfsnode *np = VTONFS(vp); 1658 off_t lo, hi; 1659 1660 if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID)) 1661 return; 1662 1663 lo = (off_t)bp->b_blkno * DEV_BSIZE; 1664 hi = lo + bp->b_dirtyend; 1665 1666 if (lo > np->n_pushhi || hi < np->n_pushlo) 1667 return; 1668 1669 if (lo <= np->n_pushlo) 1670 np->n_pushlo = hi; 1671 else if (hi >= np->n_pushhi) 1672 np->n_pushhi = lo; 1673 else { 1674 /* 1675 * XXX There's only one range. If the deleted range 1676 * is in the middle, pick the largest of the 1677 * contiguous ranges that it leaves. 1678 */ 1679 if ((np->n_pushlo - lo) > (hi - np->n_pushhi)) 1680 np->n_pushhi = lo; 1681 else 1682 np->n_pushlo = hi; 1683 } 1684 } 1685 1686 /* 1687 * Map errnos to NFS error numbers. For Version 3 also filter out error 1688 * numbers not specified for the associated procedure. 1689 */ 1690 int 1691 nfsrv_errmap(struct nfsrv_descript *nd, int err) 1692 { 1693 short *defaulterrp, *errp; 1694 1695 if (nd->nd_flag & ND_NFSV3) { 1696 if (nd->nd_procnum <= NFSPROC_COMMIT) { 1697 errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum]; 1698 while (*++errp) { 1699 if (*errp == err) 1700 return (err); 1701 else if (*errp > err) 1702 break; 1703 } 1704 return ((int)*defaulterrp); 1705 } else 1706 return (err & 0xffff); 1707 } 1708 if (err <= nitems(nfsrv_v2errmap)) 1709 return ((int)nfsrv_v2errmap[err - 1]); 1710 return (NFSERR_IO); 1711 } 1712 1713 /* 1714 * If full is non zero, set all fields, otherwise just set mode and time fields 1715 */ 1716 void 1717 nfsm_v3attrbuild(struct mbuf **mp, struct vattr *a, int full) 1718 { 1719 struct mbuf *mb; 1720 u_int32_t *tl; 1721 1722 mb = *mp; 1723 1724 if (a->va_mode != (mode_t)VNOVAL) { 1725 tl = nfsm_build(&mb, 2 * NFSX_UNSIGNED); 1726 *tl++ = nfs_true; 1727 *tl = txdr_unsigned(a->va_mode); 1728 } else { 1729 tl = nfsm_build(&mb, NFSX_UNSIGNED); 1730 *tl = nfs_false; 1731 } 1732 if (full && a->va_uid != (uid_t)VNOVAL) { 1733 tl = nfsm_build(&mb, 2 * NFSX_UNSIGNED); 1734 *tl++ = nfs_true; 1735 *tl = txdr_unsigned(a->va_uid); 1736 } else { 1737 tl = nfsm_build(&mb, NFSX_UNSIGNED); 1738 *tl = nfs_false; 1739 } 1740 if (full && a->va_gid != (gid_t)VNOVAL) { 1741 tl = nfsm_build(&mb, 2 * NFSX_UNSIGNED); 1742 *tl++ = nfs_true; 1743 *tl = txdr_unsigned((a)->va_gid); 1744 } else { 1745 tl = nfsm_build(&mb, NFSX_UNSIGNED); 1746 *tl = nfs_false; 1747 } 1748 if (full && a->va_size != VNOVAL) { 1749 tl = nfsm_build(&mb, 3 * NFSX_UNSIGNED); 1750 *tl++ = nfs_true; 1751 txdr_hyper(a->va_size, tl); 1752 } else { 1753 tl = nfsm_build(&mb, NFSX_UNSIGNED); 1754 *tl = nfs_false; 1755 } 1756 if (a->va_atime.tv_sec != VNOVAL) { 1757 if (a->va_atime.tv_sec != time_second) { 1758 tl = nfsm_build(&mb, 3 * NFSX_UNSIGNED); 1759 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); 1760 txdr_nfsv3time(&a->va_atime, tl); 1761 } else { 1762 tl = nfsm_build(&mb, NFSX_UNSIGNED); 1763 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); 1764 } 1765 } else { 1766 tl = nfsm_build(&mb, NFSX_UNSIGNED); 1767 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); 1768 } 1769 if (a->va_mtime.tv_sec != VNOVAL) { 1770 if (a->va_mtime.tv_sec != time_second) { 1771 tl = nfsm_build(&mb, 3 * NFSX_UNSIGNED); 1772 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); 1773 txdr_nfsv3time(&a->va_mtime, tl); 1774 } else { 1775 tl = nfsm_build(&mb, NFSX_UNSIGNED); 1776 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); 1777 } 1778 } else { 1779 tl = nfsm_build(&mb, NFSX_UNSIGNED); 1780 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); 1781 } 1782 1783 *mp = mb; 1784 } 1785 1786 /* 1787 * Ensure a contiguous buffer len bytes long 1788 */ 1789 void * 1790 nfsm_build(struct mbuf **mp, u_int len) 1791 { 1792 struct mbuf *mb, *mb2; 1793 caddr_t bpos; 1794 1795 mb = *mp; 1796 bpos = mb_offset(mb); 1797 1798 if (len > M_TRAILINGSPACE(mb)) { 1799 MGET(mb2, M_WAIT, MT_DATA); 1800 if (len > MLEN) 1801 panic("build > MLEN"); 1802 mb->m_next = mb2; 1803 mb = mb2; 1804 mb->m_len = 0; 1805 bpos = mtod(mb, caddr_t); 1806 } 1807 mb->m_len += len; 1808 1809 *mp = mb; 1810 1811 return (bpos); 1812 } 1813 1814 void 1815 nfsm_fhtom(struct nfsm_info *info, struct vnode *v, int v3) 1816 { 1817 struct nfsnode *n = VTONFS(v); 1818 1819 if (v3) { 1820 nfsm_strtombuf(&info->nmi_mb, n->n_fhp, n->n_fhsize); 1821 } else { 1822 nfsm_buftombuf(&info->nmi_mb, n->n_fhp, NFSX_V2FH); 1823 } 1824 } 1825 1826 void 1827 nfsm_srvfhtom(struct mbuf **mp, fhandle_t *f, int v3) 1828 { 1829 if (v3) { 1830 nfsm_strtombuf(mp, f, NFSX_V3FH); 1831 } else { 1832 nfsm_buftombuf(mp, f, NFSX_V2FH); 1833 } 1834 } 1835 1836 int 1837 nfsm_srvsattr(struct mbuf **mp, struct vattr *va, struct mbuf *mrep, 1838 caddr_t *dposp) 1839 { 1840 struct nfsm_info info; 1841 uint32_t *tl, t1; 1842 caddr_t cp2; 1843 int error = 0; 1844 1845 info.nmi_md = *mp; 1846 info.nmi_dpos = *dposp; 1847 1848 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1849 if (*tl == nfs_true) { 1850 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1851 va->va_mode = nfstov_mode(*tl); 1852 } 1853 1854 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1855 if (*tl == nfs_true) { 1856 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1857 va->va_uid = fxdr_unsigned(uid_t, *tl); 1858 } 1859 1860 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1861 if (*tl == nfs_true) { 1862 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1863 va->va_gid = fxdr_unsigned(gid_t, *tl); 1864 } 1865 1866 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1867 if (*tl == nfs_true) { 1868 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1869 va->va_size = fxdr_hyper(tl); 1870 } 1871 1872 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1873 switch (fxdr_unsigned(int, *tl)) { 1874 case NFSV3SATTRTIME_TOCLIENT: 1875 va->va_vaflags &= ~VA_UTIMES_NULL; 1876 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1877 fxdr_nfsv3time(tl, &va->va_atime); 1878 break; 1879 case NFSV3SATTRTIME_TOSERVER: 1880 getnanotime(&va->va_atime); 1881 break; 1882 }; 1883 1884 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1885 switch (fxdr_unsigned(int, *tl)) { 1886 case NFSV3SATTRTIME_TOCLIENT: 1887 va->va_vaflags &= ~VA_UTIMES_NULL; 1888 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1889 fxdr_nfsv3time(tl, &va->va_mtime); 1890 break; 1891 case NFSV3SATTRTIME_TOSERVER: 1892 getnanotime(&va->va_mtime); 1893 break; 1894 }; 1895 1896 *dposp = info.nmi_dpos; 1897 *mp = info.nmi_md; 1898 nfsmout: 1899 return (error); 1900 } 1901