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