1 /*- 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 4. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 */ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 #ifndef APPLEKEXT 38 /* 39 * These functions support the macros and help fiddle mbuf chains for 40 * the nfs op functions. They do things like create the rpc header and 41 * copy data between mbuf chains and uio lists. 42 */ 43 #include <fs/nfs/nfsport.h> 44 45 extern u_int32_t newnfs_true, newnfs_false; 46 extern int nfs_pubfhset; 47 extern struct nfsclienthashhead nfsclienthash[NFSCLIENTHASHSIZE]; 48 extern struct nfslockhashhead nfslockhash[NFSLOCKHASHSIZE]; 49 extern struct nfssessionhash nfssessionhash[NFSSESSIONHASHSIZE]; 50 extern int nfsrv_useacl; 51 extern uid_t nfsrv_defaultuid; 52 extern gid_t nfsrv_defaultgid; 53 54 char nfs_v2pubfh[NFSX_V2FH]; 55 static nfstype newnfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, 56 NFNON, NFCHR, NFNON }; 57 extern nfstype nfsv34_type[9]; 58 #endif /* !APPLEKEXT */ 59 60 static u_int32_t nfsrv_isannfserr(u_int32_t); 61 62 SYSCTL_DECL(_vfs_nfsd); 63 64 static int disable_checkutf8 = 0; 65 SYSCTL_INT(_vfs_nfsd, OID_AUTO, disable_checkutf8, CTLFLAG_RW, 66 &disable_checkutf8, 0, 67 "Disable the NFSv4 check for a UTF8 compliant name"); 68 69 static char nfsrv_hexdigit(char, int *); 70 71 /* 72 * Maps errno values to nfs error numbers. 73 * Use NFSERR_IO as the catch all for ones not specifically defined in 74 * RFC 1094. (It now includes the errors added for NFSv3.) 75 */ 76 static u_char nfsrv_v2errmap[NFSERR_REMOTE] = { 77 NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO, 78 NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 79 NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO, 80 NFSERR_IO, NFSERR_EXIST, NFSERR_XDEV, NFSERR_NODEV, NFSERR_NOTDIR, 81 NFSERR_ISDIR, NFSERR_INVAL, NFSERR_IO, NFSERR_IO, NFSERR_IO, 82 NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS, 83 NFSERR_MLINK, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 84 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 85 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 86 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 87 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 88 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 89 NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO, 90 NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE, 91 NFSERR_REMOTE, 92 }; 93 94 /* 95 * Maps errno values to nfs error numbers. 96 * Although it is not obvious whether or not NFS clients really care if 97 * a returned error value is in the specified list for the procedure, the 98 * safest thing to do is filter them appropriately. For Version 2, the 99 * X/Open XNFS document is the only specification that defines error values 100 * for each RPC (The RFC simply lists all possible error values for all RPCs), 101 * so I have decided to not do this for Version 2. 102 * The first entry is the default error return and the rest are the valid 103 * errors for that RPC in increasing numeric order. 104 */ 105 static short nfsv3err_null[] = { 106 0, 107 0, 108 }; 109 110 static short nfsv3err_getattr[] = { 111 NFSERR_IO, 112 NFSERR_IO, 113 NFSERR_STALE, 114 NFSERR_BADHANDLE, 115 NFSERR_SERVERFAULT, 116 NFSERR_DELAY, 117 0, 118 }; 119 120 static short nfsv3err_setattr[] = { 121 NFSERR_IO, 122 NFSERR_ACCES, 123 NFSERR_PERM, 124 NFSERR_IO, 125 NFSERR_INVAL, 126 NFSERR_NOSPC, 127 NFSERR_ROFS, 128 NFSERR_DQUOT, 129 NFSERR_STALE, 130 NFSERR_BADHANDLE, 131 NFSERR_NOT_SYNC, 132 NFSERR_SERVERFAULT, 133 NFSERR_DELAY, 134 0, 135 }; 136 137 static short nfsv3err_lookup[] = { 138 NFSERR_IO, 139 NFSERR_NOENT, 140 NFSERR_ACCES, 141 NFSERR_NAMETOL, 142 NFSERR_IO, 143 NFSERR_NOTDIR, 144 NFSERR_STALE, 145 NFSERR_BADHANDLE, 146 NFSERR_SERVERFAULT, 147 NFSERR_DELAY, 148 0, 149 }; 150 151 static short nfsv3err_access[] = { 152 NFSERR_IO, 153 NFSERR_IO, 154 NFSERR_STALE, 155 NFSERR_BADHANDLE, 156 NFSERR_SERVERFAULT, 157 NFSERR_DELAY, 158 0, 159 }; 160 161 static short nfsv3err_readlink[] = { 162 NFSERR_IO, 163 NFSERR_IO, 164 NFSERR_ACCES, 165 NFSERR_INVAL, 166 NFSERR_STALE, 167 NFSERR_BADHANDLE, 168 NFSERR_NOTSUPP, 169 NFSERR_SERVERFAULT, 170 NFSERR_DELAY, 171 0, 172 }; 173 174 static short nfsv3err_read[] = { 175 NFSERR_IO, 176 NFSERR_IO, 177 NFSERR_NXIO, 178 NFSERR_ACCES, 179 NFSERR_INVAL, 180 NFSERR_STALE, 181 NFSERR_BADHANDLE, 182 NFSERR_SERVERFAULT, 183 NFSERR_DELAY, 184 0, 185 }; 186 187 static short nfsv3err_write[] = { 188 NFSERR_IO, 189 NFSERR_IO, 190 NFSERR_ACCES, 191 NFSERR_NOSPC, 192 NFSERR_INVAL, 193 NFSERR_FBIG, 194 NFSERR_ROFS, 195 NFSERR_DQUOT, 196 NFSERR_STALE, 197 NFSERR_BADHANDLE, 198 NFSERR_SERVERFAULT, 199 NFSERR_DELAY, 200 0, 201 }; 202 203 static short nfsv3err_create[] = { 204 NFSERR_IO, 205 NFSERR_EXIST, 206 NFSERR_NAMETOL, 207 NFSERR_ACCES, 208 NFSERR_IO, 209 NFSERR_NOTDIR, 210 NFSERR_NOSPC, 211 NFSERR_ROFS, 212 NFSERR_DQUOT, 213 NFSERR_STALE, 214 NFSERR_BADHANDLE, 215 NFSERR_NOTSUPP, 216 NFSERR_SERVERFAULT, 217 NFSERR_DELAY, 218 0, 219 }; 220 221 static short nfsv3err_mkdir[] = { 222 NFSERR_IO, 223 NFSERR_EXIST, 224 NFSERR_ACCES, 225 NFSERR_NAMETOL, 226 NFSERR_IO, 227 NFSERR_NOTDIR, 228 NFSERR_NOSPC, 229 NFSERR_ROFS, 230 NFSERR_DQUOT, 231 NFSERR_STALE, 232 NFSERR_BADHANDLE, 233 NFSERR_NOTSUPP, 234 NFSERR_SERVERFAULT, 235 NFSERR_DELAY, 236 0, 237 }; 238 239 static short nfsv3err_symlink[] = { 240 NFSERR_IO, 241 NFSERR_ACCES, 242 NFSERR_EXIST, 243 NFSERR_NAMETOL, 244 NFSERR_NOSPC, 245 NFSERR_IO, 246 NFSERR_NOTDIR, 247 NFSERR_ROFS, 248 NFSERR_DQUOT, 249 NFSERR_STALE, 250 NFSERR_BADHANDLE, 251 NFSERR_NOTSUPP, 252 NFSERR_SERVERFAULT, 253 NFSERR_DELAY, 254 0, 255 }; 256 257 static short nfsv3err_mknod[] = { 258 NFSERR_IO, 259 NFSERR_ACCES, 260 NFSERR_EXIST, 261 NFSERR_NAMETOL, 262 NFSERR_NOSPC, 263 NFSERR_IO, 264 NFSERR_NOTDIR, 265 NFSERR_ROFS, 266 NFSERR_DQUOT, 267 NFSERR_STALE, 268 NFSERR_BADHANDLE, 269 NFSERR_NOTSUPP, 270 NFSERR_SERVERFAULT, 271 NFSERR_DELAY, 272 NFSERR_BADTYPE, 273 0, 274 }; 275 276 static short nfsv3err_remove[] = { 277 NFSERR_IO, 278 NFSERR_NOENT, 279 NFSERR_ACCES, 280 NFSERR_NAMETOL, 281 NFSERR_IO, 282 NFSERR_NOTDIR, 283 NFSERR_ROFS, 284 NFSERR_STALE, 285 NFSERR_BADHANDLE, 286 NFSERR_SERVERFAULT, 287 NFSERR_DELAY, 288 0, 289 }; 290 291 static short nfsv3err_rmdir[] = { 292 NFSERR_IO, 293 NFSERR_NOENT, 294 NFSERR_ACCES, 295 NFSERR_NOTDIR, 296 NFSERR_NAMETOL, 297 NFSERR_IO, 298 NFSERR_EXIST, 299 NFSERR_INVAL, 300 NFSERR_ROFS, 301 NFSERR_NOTEMPTY, 302 NFSERR_STALE, 303 NFSERR_BADHANDLE, 304 NFSERR_NOTSUPP, 305 NFSERR_SERVERFAULT, 306 NFSERR_DELAY, 307 0, 308 }; 309 310 static short nfsv3err_rename[] = { 311 NFSERR_IO, 312 NFSERR_NOENT, 313 NFSERR_ACCES, 314 NFSERR_EXIST, 315 NFSERR_NAMETOL, 316 NFSERR_XDEV, 317 NFSERR_IO, 318 NFSERR_NOTDIR, 319 NFSERR_ISDIR, 320 NFSERR_INVAL, 321 NFSERR_NOSPC, 322 NFSERR_ROFS, 323 NFSERR_MLINK, 324 NFSERR_NOTEMPTY, 325 NFSERR_DQUOT, 326 NFSERR_STALE, 327 NFSERR_BADHANDLE, 328 NFSERR_NOTSUPP, 329 NFSERR_SERVERFAULT, 330 NFSERR_DELAY, 331 0, 332 }; 333 334 static short nfsv3err_link[] = { 335 NFSERR_IO, 336 NFSERR_ACCES, 337 NFSERR_EXIST, 338 NFSERR_NAMETOL, 339 NFSERR_IO, 340 NFSERR_XDEV, 341 NFSERR_NOTDIR, 342 NFSERR_INVAL, 343 NFSERR_NOSPC, 344 NFSERR_ROFS, 345 NFSERR_MLINK, 346 NFSERR_DQUOT, 347 NFSERR_STALE, 348 NFSERR_BADHANDLE, 349 NFSERR_NOTSUPP, 350 NFSERR_SERVERFAULT, 351 NFSERR_DELAY, 352 0, 353 }; 354 355 static short nfsv3err_readdir[] = { 356 NFSERR_IO, 357 NFSERR_ACCES, 358 NFSERR_NOTDIR, 359 NFSERR_IO, 360 NFSERR_STALE, 361 NFSERR_BADHANDLE, 362 NFSERR_BAD_COOKIE, 363 NFSERR_TOOSMALL, 364 NFSERR_SERVERFAULT, 365 NFSERR_DELAY, 366 0, 367 }; 368 369 static short nfsv3err_readdirplus[] = { 370 NFSERR_IO, 371 NFSERR_ACCES, 372 NFSERR_NOTDIR, 373 NFSERR_IO, 374 NFSERR_STALE, 375 NFSERR_BADHANDLE, 376 NFSERR_BAD_COOKIE, 377 NFSERR_NOTSUPP, 378 NFSERR_TOOSMALL, 379 NFSERR_SERVERFAULT, 380 NFSERR_DELAY, 381 0, 382 }; 383 384 static short nfsv3err_fsstat[] = { 385 NFSERR_IO, 386 NFSERR_IO, 387 NFSERR_STALE, 388 NFSERR_BADHANDLE, 389 NFSERR_SERVERFAULT, 390 NFSERR_DELAY, 391 0, 392 }; 393 394 static short nfsv3err_fsinfo[] = { 395 NFSERR_STALE, 396 NFSERR_STALE, 397 NFSERR_BADHANDLE, 398 NFSERR_SERVERFAULT, 399 NFSERR_DELAY, 400 0, 401 }; 402 403 static short nfsv3err_pathconf[] = { 404 NFSERR_STALE, 405 NFSERR_STALE, 406 NFSERR_BADHANDLE, 407 NFSERR_SERVERFAULT, 408 NFSERR_DELAY, 409 0, 410 }; 411 412 static short nfsv3err_commit[] = { 413 NFSERR_IO, 414 NFSERR_IO, 415 NFSERR_STALE, 416 NFSERR_BADHANDLE, 417 NFSERR_SERVERFAULT, 418 NFSERR_DELAY, 419 0, 420 }; 421 422 static short *nfsrv_v3errmap[] = { 423 nfsv3err_null, 424 nfsv3err_getattr, 425 nfsv3err_setattr, 426 nfsv3err_lookup, 427 nfsv3err_access, 428 nfsv3err_readlink, 429 nfsv3err_read, 430 nfsv3err_write, 431 nfsv3err_create, 432 nfsv3err_mkdir, 433 nfsv3err_symlink, 434 nfsv3err_mknod, 435 nfsv3err_remove, 436 nfsv3err_rmdir, 437 nfsv3err_rename, 438 nfsv3err_link, 439 nfsv3err_readdir, 440 nfsv3err_readdirplus, 441 nfsv3err_fsstat, 442 nfsv3err_fsinfo, 443 nfsv3err_pathconf, 444 nfsv3err_commit, 445 }; 446 447 /* 448 * And the same for V4. 449 */ 450 static short nfsv4err_null[] = { 451 0, 452 0, 453 }; 454 455 static short nfsv4err_access[] = { 456 NFSERR_IO, 457 NFSERR_ACCES, 458 NFSERR_BADHANDLE, 459 NFSERR_BADXDR, 460 NFSERR_DELAY, 461 NFSERR_FHEXPIRED, 462 NFSERR_INVAL, 463 NFSERR_IO, 464 NFSERR_MOVED, 465 NFSERR_NOFILEHANDLE, 466 NFSERR_RESOURCE, 467 NFSERR_SERVERFAULT, 468 NFSERR_STALE, 469 0, 470 }; 471 472 static short nfsv4err_close[] = { 473 NFSERR_EXPIRED, 474 NFSERR_ADMINREVOKED, 475 NFSERR_BADHANDLE, 476 NFSERR_BADSEQID, 477 NFSERR_BADSTATEID, 478 NFSERR_BADXDR, 479 NFSERR_DELAY, 480 NFSERR_EXPIRED, 481 NFSERR_FHEXPIRED, 482 NFSERR_INVAL, 483 NFSERR_ISDIR, 484 NFSERR_LEASEMOVED, 485 NFSERR_LOCKSHELD, 486 NFSERR_MOVED, 487 NFSERR_NOFILEHANDLE, 488 NFSERR_OLDSTATEID, 489 NFSERR_RESOURCE, 490 NFSERR_SERVERFAULT, 491 NFSERR_STALE, 492 NFSERR_STALESTATEID, 493 0, 494 }; 495 496 static short nfsv4err_commit[] = { 497 NFSERR_IO, 498 NFSERR_ACCES, 499 NFSERR_BADHANDLE, 500 NFSERR_BADXDR, 501 NFSERR_FHEXPIRED, 502 NFSERR_INVAL, 503 NFSERR_IO, 504 NFSERR_ISDIR, 505 NFSERR_MOVED, 506 NFSERR_NOFILEHANDLE, 507 NFSERR_RESOURCE, 508 NFSERR_ROFS, 509 NFSERR_SERVERFAULT, 510 NFSERR_STALE, 511 0, 512 }; 513 514 static short nfsv4err_create[] = { 515 NFSERR_IO, 516 NFSERR_ACCES, 517 NFSERR_ATTRNOTSUPP, 518 NFSERR_BADCHAR, 519 NFSERR_BADHANDLE, 520 NFSERR_BADNAME, 521 NFSERR_BADOWNER, 522 NFSERR_BADTYPE, 523 NFSERR_BADXDR, 524 NFSERR_DELAY, 525 NFSERR_DQUOT, 526 NFSERR_EXIST, 527 NFSERR_FHEXPIRED, 528 NFSERR_INVAL, 529 NFSERR_IO, 530 NFSERR_MOVED, 531 NFSERR_NAMETOL, 532 NFSERR_NOFILEHANDLE, 533 NFSERR_NOSPC, 534 NFSERR_NOTDIR, 535 NFSERR_PERM, 536 NFSERR_RESOURCE, 537 NFSERR_ROFS, 538 NFSERR_SERVERFAULT, 539 NFSERR_STALE, 540 0, 541 }; 542 543 static short nfsv4err_delegpurge[] = { 544 NFSERR_SERVERFAULT, 545 NFSERR_BADXDR, 546 NFSERR_NOTSUPP, 547 NFSERR_LEASEMOVED, 548 NFSERR_MOVED, 549 NFSERR_RESOURCE, 550 NFSERR_SERVERFAULT, 551 NFSERR_STALECLIENTID, 552 0, 553 }; 554 555 static short nfsv4err_delegreturn[] = { 556 NFSERR_SERVERFAULT, 557 NFSERR_ADMINREVOKED, 558 NFSERR_BADSTATEID, 559 NFSERR_BADXDR, 560 NFSERR_EXPIRED, 561 NFSERR_INVAL, 562 NFSERR_LEASEMOVED, 563 NFSERR_MOVED, 564 NFSERR_NOFILEHANDLE, 565 NFSERR_NOTSUPP, 566 NFSERR_OLDSTATEID, 567 NFSERR_RESOURCE, 568 NFSERR_SERVERFAULT, 569 NFSERR_STALE, 570 NFSERR_STALESTATEID, 571 0, 572 }; 573 574 static short nfsv4err_getattr[] = { 575 NFSERR_IO, 576 NFSERR_ACCES, 577 NFSERR_BADHANDLE, 578 NFSERR_BADXDR, 579 NFSERR_DELAY, 580 NFSERR_FHEXPIRED, 581 NFSERR_INVAL, 582 NFSERR_IO, 583 NFSERR_MOVED, 584 NFSERR_NOFILEHANDLE, 585 NFSERR_RESOURCE, 586 NFSERR_SERVERFAULT, 587 NFSERR_STALE, 588 0, 589 }; 590 591 static short nfsv4err_getfh[] = { 592 NFSERR_BADHANDLE, 593 NFSERR_BADHANDLE, 594 NFSERR_FHEXPIRED, 595 NFSERR_MOVED, 596 NFSERR_NOFILEHANDLE, 597 NFSERR_RESOURCE, 598 NFSERR_SERVERFAULT, 599 NFSERR_STALE, 600 0, 601 }; 602 603 static short nfsv4err_link[] = { 604 NFSERR_IO, 605 NFSERR_ACCES, 606 NFSERR_BADCHAR, 607 NFSERR_BADHANDLE, 608 NFSERR_BADNAME, 609 NFSERR_BADXDR, 610 NFSERR_DELAY, 611 NFSERR_DQUOT, 612 NFSERR_EXIST, 613 NFSERR_FHEXPIRED, 614 NFSERR_FILEOPEN, 615 NFSERR_INVAL, 616 NFSERR_IO, 617 NFSERR_ISDIR, 618 NFSERR_MLINK, 619 NFSERR_MOVED, 620 NFSERR_NAMETOL, 621 NFSERR_NOENT, 622 NFSERR_NOFILEHANDLE, 623 NFSERR_NOSPC, 624 NFSERR_NOTDIR, 625 NFSERR_NOTSUPP, 626 NFSERR_RESOURCE, 627 NFSERR_ROFS, 628 NFSERR_SERVERFAULT, 629 NFSERR_STALE, 630 NFSERR_WRONGSEC, 631 NFSERR_XDEV, 632 0, 633 }; 634 635 static short nfsv4err_lock[] = { 636 NFSERR_SERVERFAULT, 637 NFSERR_ACCES, 638 NFSERR_ADMINREVOKED, 639 NFSERR_BADHANDLE, 640 NFSERR_BADRANGE, 641 NFSERR_BADSEQID, 642 NFSERR_BADSTATEID, 643 NFSERR_BADXDR, 644 NFSERR_DEADLOCK, 645 NFSERR_DELAY, 646 NFSERR_DENIED, 647 NFSERR_EXPIRED, 648 NFSERR_FHEXPIRED, 649 NFSERR_GRACE, 650 NFSERR_INVAL, 651 NFSERR_ISDIR, 652 NFSERR_LEASEMOVED, 653 NFSERR_LOCKNOTSUPP, 654 NFSERR_LOCKRANGE, 655 NFSERR_MOVED, 656 NFSERR_NOFILEHANDLE, 657 NFSERR_NOGRACE, 658 NFSERR_OLDSTATEID, 659 NFSERR_OPENMODE, 660 NFSERR_RECLAIMBAD, 661 NFSERR_RECLAIMCONFLICT, 662 NFSERR_RESOURCE, 663 NFSERR_SERVERFAULT, 664 NFSERR_STALE, 665 NFSERR_STALECLIENTID, 666 NFSERR_STALESTATEID, 667 0, 668 }; 669 670 static short nfsv4err_lockt[] = { 671 NFSERR_SERVERFAULT, 672 NFSERR_ACCES, 673 NFSERR_BADHANDLE, 674 NFSERR_BADRANGE, 675 NFSERR_BADXDR, 676 NFSERR_DELAY, 677 NFSERR_DENIED, 678 NFSERR_FHEXPIRED, 679 NFSERR_GRACE, 680 NFSERR_INVAL, 681 NFSERR_ISDIR, 682 NFSERR_LEASEMOVED, 683 NFSERR_LOCKRANGE, 684 NFSERR_MOVED, 685 NFSERR_NOFILEHANDLE, 686 NFSERR_RESOURCE, 687 NFSERR_SERVERFAULT, 688 NFSERR_STALE, 689 NFSERR_STALECLIENTID, 690 0, 691 }; 692 693 static short nfsv4err_locku[] = { 694 NFSERR_SERVERFAULT, 695 NFSERR_ACCES, 696 NFSERR_ADMINREVOKED, 697 NFSERR_BADHANDLE, 698 NFSERR_BADRANGE, 699 NFSERR_BADSEQID, 700 NFSERR_BADSTATEID, 701 NFSERR_BADXDR, 702 NFSERR_EXPIRED, 703 NFSERR_FHEXPIRED, 704 NFSERR_GRACE, 705 NFSERR_INVAL, 706 NFSERR_ISDIR, 707 NFSERR_LEASEMOVED, 708 NFSERR_LOCKRANGE, 709 NFSERR_MOVED, 710 NFSERR_NOFILEHANDLE, 711 NFSERR_OLDSTATEID, 712 NFSERR_RESOURCE, 713 NFSERR_SERVERFAULT, 714 NFSERR_STALE, 715 NFSERR_STALESTATEID, 716 0, 717 }; 718 719 static short nfsv4err_lookup[] = { 720 NFSERR_IO, 721 NFSERR_ACCES, 722 NFSERR_BADCHAR, 723 NFSERR_BADHANDLE, 724 NFSERR_BADNAME, 725 NFSERR_BADXDR, 726 NFSERR_FHEXPIRED, 727 NFSERR_INVAL, 728 NFSERR_IO, 729 NFSERR_MOVED, 730 NFSERR_NAMETOL, 731 NFSERR_NOENT, 732 NFSERR_NOFILEHANDLE, 733 NFSERR_NOTDIR, 734 NFSERR_RESOURCE, 735 NFSERR_SERVERFAULT, 736 NFSERR_STALE, 737 NFSERR_SYMLINK, 738 NFSERR_WRONGSEC, 739 0, 740 }; 741 742 static short nfsv4err_lookupp[] = { 743 NFSERR_IO, 744 NFSERR_ACCES, 745 NFSERR_BADHANDLE, 746 NFSERR_FHEXPIRED, 747 NFSERR_IO, 748 NFSERR_MOVED, 749 NFSERR_NOENT, 750 NFSERR_NOFILEHANDLE, 751 NFSERR_NOTDIR, 752 NFSERR_RESOURCE, 753 NFSERR_SERVERFAULT, 754 NFSERR_STALE, 755 0, 756 }; 757 758 static short nfsv4err_nverify[] = { 759 NFSERR_IO, 760 NFSERR_ACCES, 761 NFSERR_ATTRNOTSUPP, 762 NFSERR_BADCHAR, 763 NFSERR_BADHANDLE, 764 NFSERR_BADXDR, 765 NFSERR_DELAY, 766 NFSERR_FHEXPIRED, 767 NFSERR_INVAL, 768 NFSERR_IO, 769 NFSERR_MOVED, 770 NFSERR_NOFILEHANDLE, 771 NFSERR_RESOURCE, 772 NFSERR_SAME, 773 NFSERR_SERVERFAULT, 774 NFSERR_STALE, 775 0, 776 }; 777 778 static short nfsv4err_open[] = { 779 NFSERR_IO, 780 NFSERR_ACCES, 781 NFSERR_ADMINREVOKED, 782 NFSERR_ATTRNOTSUPP, 783 NFSERR_BADCHAR, 784 NFSERR_BADHANDLE, 785 NFSERR_BADNAME, 786 NFSERR_BADOWNER, 787 NFSERR_BADSEQID, 788 NFSERR_BADXDR, 789 NFSERR_DELAY, 790 NFSERR_DQUOT, 791 NFSERR_EXIST, 792 NFSERR_EXPIRED, 793 NFSERR_FHEXPIRED, 794 NFSERR_GRACE, 795 NFSERR_IO, 796 NFSERR_INVAL, 797 NFSERR_ISDIR, 798 NFSERR_LEASEMOVED, 799 NFSERR_MOVED, 800 NFSERR_NAMETOL, 801 NFSERR_NOENT, 802 NFSERR_NOFILEHANDLE, 803 NFSERR_NOGRACE, 804 NFSERR_NOSPC, 805 NFSERR_NOTDIR, 806 NFSERR_NOTSUPP, 807 NFSERR_PERM, 808 NFSERR_RECLAIMBAD, 809 NFSERR_RECLAIMCONFLICT, 810 NFSERR_RESOURCE, 811 NFSERR_ROFS, 812 NFSERR_SERVERFAULT, 813 NFSERR_SHAREDENIED, 814 NFSERR_STALE, 815 NFSERR_STALECLIENTID, 816 NFSERR_SYMLINK, 817 NFSERR_WRONGSEC, 818 0, 819 }; 820 821 static short nfsv4err_openattr[] = { 822 NFSERR_IO, 823 NFSERR_ACCES, 824 NFSERR_BADHANDLE, 825 NFSERR_BADXDR, 826 NFSERR_DELAY, 827 NFSERR_DQUOT, 828 NFSERR_FHEXPIRED, 829 NFSERR_IO, 830 NFSERR_MOVED, 831 NFSERR_NOENT, 832 NFSERR_NOFILEHANDLE, 833 NFSERR_NOSPC, 834 NFSERR_NOTSUPP, 835 NFSERR_RESOURCE, 836 NFSERR_ROFS, 837 NFSERR_SERVERFAULT, 838 NFSERR_STALE, 839 0, 840 }; 841 842 static short nfsv4err_openconfirm[] = { 843 NFSERR_SERVERFAULT, 844 NFSERR_ADMINREVOKED, 845 NFSERR_BADHANDLE, 846 NFSERR_BADSEQID, 847 NFSERR_BADSTATEID, 848 NFSERR_BADXDR, 849 NFSERR_EXPIRED, 850 NFSERR_FHEXPIRED, 851 NFSERR_INVAL, 852 NFSERR_ISDIR, 853 NFSERR_MOVED, 854 NFSERR_NOFILEHANDLE, 855 NFSERR_OLDSTATEID, 856 NFSERR_RESOURCE, 857 NFSERR_SERVERFAULT, 858 NFSERR_STALE, 859 NFSERR_STALESTATEID, 860 0, 861 }; 862 863 static short nfsv4err_opendowngrade[] = { 864 NFSERR_SERVERFAULT, 865 NFSERR_ADMINREVOKED, 866 NFSERR_BADHANDLE, 867 NFSERR_BADSEQID, 868 NFSERR_BADSTATEID, 869 NFSERR_BADXDR, 870 NFSERR_EXPIRED, 871 NFSERR_FHEXPIRED, 872 NFSERR_INVAL, 873 NFSERR_MOVED, 874 NFSERR_NOFILEHANDLE, 875 NFSERR_OLDSTATEID, 876 NFSERR_RESOURCE, 877 NFSERR_SERVERFAULT, 878 NFSERR_STALE, 879 NFSERR_STALESTATEID, 880 0, 881 }; 882 883 static short nfsv4err_putfh[] = { 884 NFSERR_SERVERFAULT, 885 NFSERR_BADHANDLE, 886 NFSERR_BADXDR, 887 NFSERR_FHEXPIRED, 888 NFSERR_MOVED, 889 NFSERR_RESOURCE, 890 NFSERR_SERVERFAULT, 891 NFSERR_STALE, 892 NFSERR_WRONGSEC, 893 0, 894 }; 895 896 static short nfsv4err_putpubfh[] = { 897 NFSERR_SERVERFAULT, 898 NFSERR_RESOURCE, 899 NFSERR_SERVERFAULT, 900 NFSERR_WRONGSEC, 901 0, 902 }; 903 904 static short nfsv4err_putrootfh[] = { 905 NFSERR_SERVERFAULT, 906 NFSERR_RESOURCE, 907 NFSERR_SERVERFAULT, 908 NFSERR_WRONGSEC, 909 0, 910 }; 911 912 static short nfsv4err_read[] = { 913 NFSERR_IO, 914 NFSERR_ACCES, 915 NFSERR_ADMINREVOKED, 916 NFSERR_BADHANDLE, 917 NFSERR_BADSTATEID, 918 NFSERR_BADXDR, 919 NFSERR_DELAY, 920 NFSERR_EXPIRED, 921 NFSERR_FHEXPIRED, 922 NFSERR_GRACE, 923 NFSERR_IO, 924 NFSERR_INVAL, 925 NFSERR_ISDIR, 926 NFSERR_LEASEMOVED, 927 NFSERR_LOCKED, 928 NFSERR_MOVED, 929 NFSERR_NOFILEHANDLE, 930 NFSERR_NXIO, 931 NFSERR_OLDSTATEID, 932 NFSERR_OPENMODE, 933 NFSERR_RESOURCE, 934 NFSERR_SERVERFAULT, 935 NFSERR_STALE, 936 NFSERR_STALESTATEID, 937 0, 938 }; 939 940 static short nfsv4err_readdir[] = { 941 NFSERR_IO, 942 NFSERR_ACCES, 943 NFSERR_BADHANDLE, 944 NFSERR_BAD_COOKIE, 945 NFSERR_BADXDR, 946 NFSERR_DELAY, 947 NFSERR_FHEXPIRED, 948 NFSERR_INVAL, 949 NFSERR_IO, 950 NFSERR_MOVED, 951 NFSERR_NOFILEHANDLE, 952 NFSERR_NOTDIR, 953 NFSERR_NOTSAME, 954 NFSERR_RESOURCE, 955 NFSERR_SERVERFAULT, 956 NFSERR_STALE, 957 NFSERR_TOOSMALL, 958 0, 959 }; 960 961 static short nfsv4err_readlink[] = { 962 NFSERR_IO, 963 NFSERR_ACCES, 964 NFSERR_BADHANDLE, 965 NFSERR_DELAY, 966 NFSERR_FHEXPIRED, 967 NFSERR_INVAL, 968 NFSERR_IO, 969 NFSERR_ISDIR, 970 NFSERR_MOVED, 971 NFSERR_NOFILEHANDLE, 972 NFSERR_NOTSUPP, 973 NFSERR_RESOURCE, 974 NFSERR_SERVERFAULT, 975 NFSERR_STALE, 976 0, 977 }; 978 979 static short nfsv4err_remove[] = { 980 NFSERR_IO, 981 NFSERR_ACCES, 982 NFSERR_BADCHAR, 983 NFSERR_BADHANDLE, 984 NFSERR_BADNAME, 985 NFSERR_BADXDR, 986 NFSERR_DELAY, 987 NFSERR_FHEXPIRED, 988 NFSERR_FILEOPEN, 989 NFSERR_INVAL, 990 NFSERR_IO, 991 NFSERR_MOVED, 992 NFSERR_NAMETOL, 993 NFSERR_NOENT, 994 NFSERR_NOFILEHANDLE, 995 NFSERR_NOTDIR, 996 NFSERR_NOTEMPTY, 997 NFSERR_RESOURCE, 998 NFSERR_ROFS, 999 NFSERR_SERVERFAULT, 1000 NFSERR_STALE, 1001 0, 1002 }; 1003 1004 static short nfsv4err_rename[] = { 1005 NFSERR_IO, 1006 NFSERR_ACCES, 1007 NFSERR_BADCHAR, 1008 NFSERR_BADHANDLE, 1009 NFSERR_BADNAME, 1010 NFSERR_BADXDR, 1011 NFSERR_DELAY, 1012 NFSERR_DQUOT, 1013 NFSERR_EXIST, 1014 NFSERR_FHEXPIRED, 1015 NFSERR_FILEOPEN, 1016 NFSERR_INVAL, 1017 NFSERR_IO, 1018 NFSERR_MOVED, 1019 NFSERR_NAMETOL, 1020 NFSERR_NOENT, 1021 NFSERR_NOFILEHANDLE, 1022 NFSERR_NOSPC, 1023 NFSERR_NOTDIR, 1024 NFSERR_NOTEMPTY, 1025 NFSERR_RESOURCE, 1026 NFSERR_ROFS, 1027 NFSERR_SERVERFAULT, 1028 NFSERR_STALE, 1029 NFSERR_WRONGSEC, 1030 NFSERR_XDEV, 1031 0, 1032 }; 1033 1034 static short nfsv4err_renew[] = { 1035 NFSERR_SERVERFAULT, 1036 NFSERR_ACCES, 1037 NFSERR_ADMINREVOKED, 1038 NFSERR_BADXDR, 1039 NFSERR_CBPATHDOWN, 1040 NFSERR_EXPIRED, 1041 NFSERR_LEASEMOVED, 1042 NFSERR_RESOURCE, 1043 NFSERR_SERVERFAULT, 1044 NFSERR_STALECLIENTID, 1045 0, 1046 }; 1047 1048 static short nfsv4err_restorefh[] = { 1049 NFSERR_SERVERFAULT, 1050 NFSERR_BADHANDLE, 1051 NFSERR_FHEXPIRED, 1052 NFSERR_MOVED, 1053 NFSERR_RESOURCE, 1054 NFSERR_RESTOREFH, 1055 NFSERR_SERVERFAULT, 1056 NFSERR_STALE, 1057 NFSERR_WRONGSEC, 1058 0, 1059 }; 1060 1061 static short nfsv4err_savefh[] = { 1062 NFSERR_SERVERFAULT, 1063 NFSERR_BADHANDLE, 1064 NFSERR_FHEXPIRED, 1065 NFSERR_MOVED, 1066 NFSERR_NOFILEHANDLE, 1067 NFSERR_RESOURCE, 1068 NFSERR_SERVERFAULT, 1069 NFSERR_STALE, 1070 0, 1071 }; 1072 1073 static short nfsv4err_secinfo[] = { 1074 NFSERR_SERVERFAULT, 1075 NFSERR_ACCES, 1076 NFSERR_BADCHAR, 1077 NFSERR_BADHANDLE, 1078 NFSERR_BADNAME, 1079 NFSERR_BADXDR, 1080 NFSERR_FHEXPIRED, 1081 NFSERR_INVAL, 1082 NFSERR_MOVED, 1083 NFSERR_NAMETOL, 1084 NFSERR_NOENT, 1085 NFSERR_NOFILEHANDLE, 1086 NFSERR_NOTDIR, 1087 NFSERR_RESOURCE, 1088 NFSERR_SERVERFAULT, 1089 NFSERR_STALE, 1090 0, 1091 }; 1092 1093 static short nfsv4err_setattr[] = { 1094 NFSERR_IO, 1095 NFSERR_ACCES, 1096 NFSERR_ADMINREVOKED, 1097 NFSERR_ATTRNOTSUPP, 1098 NFSERR_BADCHAR, 1099 NFSERR_BADHANDLE, 1100 NFSERR_BADOWNER, 1101 NFSERR_BADSTATEID, 1102 NFSERR_BADXDR, 1103 NFSERR_DELAY, 1104 NFSERR_DQUOT, 1105 NFSERR_EXPIRED, 1106 NFSERR_FBIG, 1107 NFSERR_FHEXPIRED, 1108 NFSERR_GRACE, 1109 NFSERR_INVAL, 1110 NFSERR_IO, 1111 NFSERR_ISDIR, 1112 NFSERR_LOCKED, 1113 NFSERR_MOVED, 1114 NFSERR_NOFILEHANDLE, 1115 NFSERR_NOSPC, 1116 NFSERR_OLDSTATEID, 1117 NFSERR_OPENMODE, 1118 NFSERR_PERM, 1119 NFSERR_RESOURCE, 1120 NFSERR_ROFS, 1121 NFSERR_SERVERFAULT, 1122 NFSERR_STALE, 1123 NFSERR_STALESTATEID, 1124 0, 1125 }; 1126 1127 static short nfsv4err_setclientid[] = { 1128 NFSERR_SERVERFAULT, 1129 NFSERR_BADXDR, 1130 NFSERR_CLIDINUSE, 1131 NFSERR_INVAL, 1132 NFSERR_RESOURCE, 1133 NFSERR_SERVERFAULT, 1134 0, 1135 }; 1136 1137 static short nfsv4err_setclientidconfirm[] = { 1138 NFSERR_SERVERFAULT, 1139 NFSERR_BADXDR, 1140 NFSERR_CLIDINUSE, 1141 NFSERR_RESOURCE, 1142 NFSERR_SERVERFAULT, 1143 NFSERR_STALECLIENTID, 1144 0, 1145 }; 1146 1147 static short nfsv4err_verify[] = { 1148 NFSERR_SERVERFAULT, 1149 NFSERR_ACCES, 1150 NFSERR_ATTRNOTSUPP, 1151 NFSERR_BADCHAR, 1152 NFSERR_BADHANDLE, 1153 NFSERR_BADXDR, 1154 NFSERR_DELAY, 1155 NFSERR_FHEXPIRED, 1156 NFSERR_INVAL, 1157 NFSERR_MOVED, 1158 NFSERR_NOFILEHANDLE, 1159 NFSERR_NOTSAME, 1160 NFSERR_RESOURCE, 1161 NFSERR_SERVERFAULT, 1162 NFSERR_STALE, 1163 0, 1164 }; 1165 1166 static short nfsv4err_write[] = { 1167 NFSERR_IO, 1168 NFSERR_ACCES, 1169 NFSERR_ADMINREVOKED, 1170 NFSERR_BADHANDLE, 1171 NFSERR_BADSTATEID, 1172 NFSERR_BADXDR, 1173 NFSERR_DELAY, 1174 NFSERR_DQUOT, 1175 NFSERR_EXPIRED, 1176 NFSERR_FBIG, 1177 NFSERR_FHEXPIRED, 1178 NFSERR_GRACE, 1179 NFSERR_INVAL, 1180 NFSERR_IO, 1181 NFSERR_ISDIR, 1182 NFSERR_LEASEMOVED, 1183 NFSERR_LOCKED, 1184 NFSERR_MOVED, 1185 NFSERR_NOFILEHANDLE, 1186 NFSERR_NOSPC, 1187 NFSERR_NXIO, 1188 NFSERR_OLDSTATEID, 1189 NFSERR_OPENMODE, 1190 NFSERR_RESOURCE, 1191 NFSERR_ROFS, 1192 NFSERR_SERVERFAULT, 1193 NFSERR_STALE, 1194 NFSERR_STALESTATEID, 1195 0, 1196 }; 1197 1198 static short nfsv4err_releaselockowner[] = { 1199 NFSERR_SERVERFAULT, 1200 NFSERR_ADMINREVOKED, 1201 NFSERR_BADXDR, 1202 NFSERR_EXPIRED, 1203 NFSERR_LEASEMOVED, 1204 NFSERR_LOCKSHELD, 1205 NFSERR_RESOURCE, 1206 NFSERR_SERVERFAULT, 1207 NFSERR_STALECLIENTID, 1208 0, 1209 }; 1210 1211 static short *nfsrv_v4errmap[] = { 1212 nfsv4err_null, 1213 nfsv4err_null, 1214 nfsv4err_null, 1215 nfsv4err_access, 1216 nfsv4err_close, 1217 nfsv4err_commit, 1218 nfsv4err_create, 1219 nfsv4err_delegpurge, 1220 nfsv4err_delegreturn, 1221 nfsv4err_getattr, 1222 nfsv4err_getfh, 1223 nfsv4err_link, 1224 nfsv4err_lock, 1225 nfsv4err_lockt, 1226 nfsv4err_locku, 1227 nfsv4err_lookup, 1228 nfsv4err_lookupp, 1229 nfsv4err_nverify, 1230 nfsv4err_open, 1231 nfsv4err_openattr, 1232 nfsv4err_openconfirm, 1233 nfsv4err_opendowngrade, 1234 nfsv4err_putfh, 1235 nfsv4err_putpubfh, 1236 nfsv4err_putrootfh, 1237 nfsv4err_read, 1238 nfsv4err_readdir, 1239 nfsv4err_readlink, 1240 nfsv4err_remove, 1241 nfsv4err_rename, 1242 nfsv4err_renew, 1243 nfsv4err_restorefh, 1244 nfsv4err_savefh, 1245 nfsv4err_secinfo, 1246 nfsv4err_setattr, 1247 nfsv4err_setclientid, 1248 nfsv4err_setclientidconfirm, 1249 nfsv4err_verify, 1250 nfsv4err_write, 1251 nfsv4err_releaselockowner, 1252 }; 1253 1254 /* 1255 * A fiddled version of m_adj() that ensures null fill to a long 1256 * boundary and only trims off the back end 1257 */ 1258 APPLESTATIC void 1259 nfsrv_adj(mbuf_t mp, int len, int nul) 1260 { 1261 mbuf_t m; 1262 int count, i; 1263 char *cp; 1264 1265 /* 1266 * Trim from tail. Scan the mbuf chain, 1267 * calculating its length and finding the last mbuf. 1268 * If the adjustment only affects this mbuf, then just 1269 * adjust and return. Otherwise, rescan and truncate 1270 * after the remaining size. 1271 */ 1272 count = 0; 1273 m = mp; 1274 for (;;) { 1275 count += mbuf_len(m); 1276 if (mbuf_next(m) == NULL) 1277 break; 1278 m = mbuf_next(m); 1279 } 1280 if (mbuf_len(m) > len) { 1281 mbuf_setlen(m, mbuf_len(m) - len); 1282 if (nul > 0) { 1283 cp = NFSMTOD(m, caddr_t) + mbuf_len(m) - nul; 1284 for (i = 0; i < nul; i++) 1285 *cp++ = '\0'; 1286 } 1287 return; 1288 } 1289 count -= len; 1290 if (count < 0) 1291 count = 0; 1292 /* 1293 * Correct length for chain is "count". 1294 * Find the mbuf with last data, adjust its length, 1295 * and toss data from remaining mbufs on chain. 1296 */ 1297 for (m = mp; m; m = mbuf_next(m)) { 1298 if (mbuf_len(m) >= count) { 1299 mbuf_setlen(m, count); 1300 if (nul > 0) { 1301 cp = NFSMTOD(m, caddr_t) + mbuf_len(m) - nul; 1302 for (i = 0; i < nul; i++) 1303 *cp++ = '\0'; 1304 } 1305 break; 1306 } 1307 count -= mbuf_len(m); 1308 } 1309 for (m = mbuf_next(m); m; m = mbuf_next(m)) 1310 mbuf_setlen(m, 0); 1311 } 1312 1313 /* 1314 * Make these functions instead of macros, so that the kernel text size 1315 * doesn't get too big... 1316 */ 1317 APPLESTATIC void 1318 nfsrv_wcc(struct nfsrv_descript *nd, int before_ret, 1319 struct nfsvattr *before_nvap, int after_ret, struct nfsvattr *after_nvap) 1320 { 1321 u_int32_t *tl; 1322 1323 if (before_ret) { 1324 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1325 *tl = newnfs_false; 1326 } else { 1327 NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED); 1328 *tl++ = newnfs_true; 1329 txdr_hyper(before_nvap->na_size, tl); 1330 tl += 2; 1331 txdr_nfsv3time(&(before_nvap->na_mtime), tl); 1332 tl += 2; 1333 txdr_nfsv3time(&(before_nvap->na_ctime), tl); 1334 } 1335 nfsrv_postopattr(nd, after_ret, after_nvap); 1336 } 1337 1338 APPLESTATIC void 1339 nfsrv_postopattr(struct nfsrv_descript *nd, int after_ret, 1340 struct nfsvattr *after_nvap) 1341 { 1342 u_int32_t *tl; 1343 1344 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1345 if (after_ret) 1346 *tl = newnfs_false; 1347 else { 1348 *tl = newnfs_true; 1349 nfsrv_fillattr(nd, after_nvap); 1350 } 1351 } 1352 1353 /* 1354 * Fill in file attributes for V2 and 3. For V4, call a separate 1355 * routine that sifts through all the attribute bits. 1356 */ 1357 APPLESTATIC void 1358 nfsrv_fillattr(struct nfsrv_descript *nd, struct nfsvattr *nvap) 1359 { 1360 struct nfs_fattr *fp; 1361 int fattr_size; 1362 1363 /* 1364 * Build space for the attribute structure. 1365 */ 1366 if (nd->nd_flag & ND_NFSV3) 1367 fattr_size = NFSX_V3FATTR; 1368 else 1369 fattr_size = NFSX_V2FATTR; 1370 NFSM_BUILD(fp, struct nfs_fattr *, fattr_size); 1371 1372 /* 1373 * Now just fill it all in. 1374 */ 1375 fp->fa_nlink = txdr_unsigned(nvap->na_nlink); 1376 fp->fa_uid = txdr_unsigned(nvap->na_uid); 1377 fp->fa_gid = txdr_unsigned(nvap->na_gid); 1378 if (nd->nd_flag & ND_NFSV3) { 1379 fp->fa_type = vtonfsv34_type(nvap->na_type); 1380 fp->fa_mode = vtonfsv34_mode(nvap->na_mode); 1381 txdr_hyper(nvap->na_size, &fp->fa3_size); 1382 txdr_hyper(nvap->na_bytes, &fp->fa3_used); 1383 fp->fa3_rdev.specdata1 = txdr_unsigned(NFSMAJOR(nvap->na_rdev)); 1384 fp->fa3_rdev.specdata2 = txdr_unsigned(NFSMINOR(nvap->na_rdev)); 1385 fp->fa3_fsid.nfsuquad[0] = 0; 1386 fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(nvap->na_fsid); 1387 fp->fa3_fileid.nfsuquad[0] = 0; 1388 fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(nvap->na_fileid); 1389 txdr_nfsv3time(&nvap->na_atime, &fp->fa3_atime); 1390 txdr_nfsv3time(&nvap->na_mtime, &fp->fa3_mtime); 1391 txdr_nfsv3time(&nvap->na_ctime, &fp->fa3_ctime); 1392 } else { 1393 fp->fa_type = vtonfsv2_type(nvap->na_type); 1394 fp->fa_mode = vtonfsv2_mode(nvap->na_type, nvap->na_mode); 1395 fp->fa2_size = txdr_unsigned(nvap->na_size); 1396 fp->fa2_blocksize = txdr_unsigned(nvap->na_blocksize); 1397 if (nvap->na_type == VFIFO) 1398 fp->fa2_rdev = 0xffffffff; 1399 else 1400 fp->fa2_rdev = txdr_unsigned(nvap->na_rdev); 1401 fp->fa2_blocks = txdr_unsigned(nvap->na_bytes / NFS_FABLKSIZE); 1402 fp->fa2_fsid = txdr_unsigned(nvap->na_fsid); 1403 fp->fa2_fileid = txdr_unsigned(nvap->na_fileid); 1404 txdr_nfsv2time(&nvap->na_atime, &fp->fa2_atime); 1405 txdr_nfsv2time(&nvap->na_mtime, &fp->fa2_mtime); 1406 txdr_nfsv2time(&nvap->na_ctime, &fp->fa2_ctime); 1407 } 1408 } 1409 1410 /* 1411 * This function gets a file handle out of an mbuf list. 1412 * It returns 0 for success, EBADRPC otherwise. 1413 * If sets the third flagp argument to 1 if the file handle is 1414 * the public file handle. 1415 * For NFSv4, if the length is incorrect, set nd_repstat == NFSERR_BADHANDLE 1416 */ 1417 APPLESTATIC int 1418 nfsrv_mtofh(struct nfsrv_descript *nd, struct nfsrvfh *fhp) 1419 { 1420 u_int32_t *tl; 1421 int error = 0, len, copylen; 1422 1423 if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) { 1424 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 1425 len = fxdr_unsigned(int, *tl); 1426 if (len == 0 && nfs_pubfhset && (nd->nd_flag & ND_NFSV3) && 1427 nd->nd_procnum == NFSPROC_LOOKUP) { 1428 nd->nd_flag |= ND_PUBLOOKUP; 1429 goto nfsmout; 1430 } 1431 if (len < NFSRV_MINFH || len > NFSRV_MAXFH) { 1432 if (nd->nd_flag & ND_NFSV4) { 1433 if (len > 0 && len <= NFSX_V4FHMAX) { 1434 error = nfsm_advance(nd, NFSM_RNDUP(len), -1); 1435 if (error) 1436 goto nfsmout; 1437 nd->nd_repstat = NFSERR_BADHANDLE; 1438 goto nfsmout; 1439 } else { 1440 error = EBADRPC; 1441 goto nfsmout; 1442 } 1443 } else { 1444 error = EBADRPC; 1445 goto nfsmout; 1446 } 1447 } 1448 copylen = len; 1449 } else { 1450 /* 1451 * For NFSv2, the file handle is always 32 bytes on the 1452 * wire, but this server only cares about the first 1453 * NFSRV_MAXFH bytes. 1454 */ 1455 len = NFSX_V2FH; 1456 copylen = NFSRV_MAXFH; 1457 } 1458 NFSM_DISSECT(tl, u_int32_t *, len); 1459 if ((nd->nd_flag & ND_NFSV2) && nfs_pubfhset && 1460 nd->nd_procnum == NFSPROC_LOOKUP && 1461 !NFSBCMP((caddr_t)tl, nfs_v2pubfh, NFSX_V2FH)) { 1462 nd->nd_flag |= ND_PUBLOOKUP; 1463 goto nfsmout; 1464 } 1465 NFSBCOPY(tl, (caddr_t)fhp->nfsrvfh_data, copylen); 1466 fhp->nfsrvfh_len = copylen; 1467 nfsmout: 1468 NFSEXITCODE2(error, nd); 1469 return (error); 1470 } 1471 1472 /* 1473 * Map errnos to NFS error numbers. For Version 3 and 4 also filter out error 1474 * numbers not specified for the associated procedure. 1475 * NFSPROC_NOOP is a special case, where the high order bits of nd_repstat 1476 * should be cleared. NFSPROC_NOOP is used to return errors when a valid 1477 * RPC procedure is not involved. 1478 * Returns the error number in XDR. 1479 */ 1480 APPLESTATIC int 1481 nfsd_errmap(struct nfsrv_descript *nd) 1482 { 1483 short *defaulterrp, *errp; 1484 1485 if (!nd->nd_repstat) 1486 return (0); 1487 if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) { 1488 if (nd->nd_procnum == NFSPROC_NOOP) 1489 return (txdr_unsigned(nd->nd_repstat & 0xffff)); 1490 if (nd->nd_flag & ND_NFSV3) 1491 errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum]; 1492 else if (nd->nd_repstat == EBADRPC) 1493 return (txdr_unsigned(NFSERR_BADXDR)); 1494 else if (nd->nd_repstat == NFSERR_MINORVERMISMATCH || 1495 nd->nd_repstat == NFSERR_OPILLEGAL) 1496 return (txdr_unsigned(nd->nd_repstat)); 1497 else if ((nd->nd_flag & ND_NFSV41) != 0) { 1498 if (nd->nd_repstat == EOPNOTSUPP) 1499 nd->nd_repstat = NFSERR_NOTSUPP; 1500 nd->nd_repstat = nfsrv_isannfserr(nd->nd_repstat); 1501 return (txdr_unsigned(nd->nd_repstat)); 1502 } else 1503 errp = defaulterrp = nfsrv_v4errmap[nd->nd_procnum]; 1504 while (*++errp) 1505 if (*errp == nd->nd_repstat) 1506 return (txdr_unsigned(nd->nd_repstat)); 1507 return (txdr_unsigned(*defaulterrp)); 1508 } 1509 if (nd->nd_repstat <= NFSERR_REMOTE) 1510 return (txdr_unsigned(nfsrv_v2errmap[nd->nd_repstat - 1])); 1511 return (txdr_unsigned(NFSERR_IO)); 1512 } 1513 1514 /* 1515 * Check to see if the error is a valid NFS one. If not, replace it with 1516 * NFSERR_IO. 1517 */ 1518 static u_int32_t 1519 nfsrv_isannfserr(u_int32_t errval) 1520 { 1521 1522 if (errval == NFSERR_OK) 1523 return (errval); 1524 if (errval >= NFSERR_BADHANDLE && errval <= NFSERR_DELEGREVOKED) 1525 return (errval); 1526 if (errval > 0 && errval <= NFSERR_REMOTE) 1527 return (nfsrv_v2errmap[errval - 1]); 1528 return (NFSERR_IO); 1529 } 1530 1531 /* 1532 * Check to see if setting a uid/gid is permitted when creating a new 1533 * file object. (Called when uid and/or gid is specified in the 1534 * settable attributes for V4. 1535 */ 1536 APPLESTATIC int 1537 nfsrv_checkuidgid(struct nfsrv_descript *nd, struct nfsvattr *nvap) 1538 { 1539 int error = 0; 1540 1541 /* 1542 * If not setting either uid nor gid, it's OK. 1543 */ 1544 if (NFSVNO_NOTSETUID(nvap) && NFSVNO_NOTSETGID(nvap)) 1545 goto out; 1546 if ((NFSVNO_ISSETUID(nvap) && nvap->na_uid == nfsrv_defaultuid) 1547 || (NFSVNO_ISSETGID(nvap) && nvap->na_gid == nfsrv_defaultgid)) { 1548 error = NFSERR_BADOWNER; 1549 goto out; 1550 } 1551 if (nd->nd_cred->cr_uid == 0) 1552 goto out; 1553 if ((NFSVNO_ISSETUID(nvap) && nvap->na_uid != nd->nd_cred->cr_uid) || 1554 (NFSVNO_ISSETGID(nvap) && nvap->na_gid != nd->nd_cred->cr_gid && 1555 !groupmember(nvap->na_gid, nd->nd_cred))) 1556 error = NFSERR_PERM; 1557 1558 out: 1559 NFSEXITCODE2(error, nd); 1560 return (error); 1561 } 1562 1563 /* 1564 * and this routine fixes up the settable attributes for V4 if allowed 1565 * by nfsrv_checkuidgid(). 1566 */ 1567 APPLESTATIC void 1568 nfsrv_fixattr(struct nfsrv_descript *nd, vnode_t vp, 1569 struct nfsvattr *nvap, NFSACL_T *aclp, NFSPROC_T *p, nfsattrbit_t *attrbitp, 1570 struct nfsexstuff *exp) 1571 { 1572 int change = 0; 1573 struct nfsvattr nva; 1574 uid_t tuid; 1575 int error; 1576 nfsattrbit_t nattrbits; 1577 1578 /* 1579 * Maybe this should be done for V2 and 3 but it never has been 1580 * and nobody seems to be upset, so I think it's best not to change 1581 * the V2 and 3 semantics. 1582 */ 1583 if ((nd->nd_flag & ND_NFSV4) == 0) 1584 goto out; 1585 NFSVNO_ATTRINIT(&nva); 1586 NFSZERO_ATTRBIT(&nattrbits); 1587 tuid = nd->nd_cred->cr_uid; 1588 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) && 1589 NFSVNO_ISSETUID(nvap) && 1590 nvap->na_uid != nd->nd_cred->cr_uid) { 1591 if (nd->nd_cred->cr_uid == 0) { 1592 nva.na_uid = nvap->na_uid; 1593 change++; 1594 NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_OWNER); 1595 } else { 1596 NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_OWNER); 1597 } 1598 } 1599 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEACCESSSET) && 1600 NFSVNO_ISSETATIME(nvap)) { 1601 nva.na_atime = nvap->na_atime; 1602 change++; 1603 NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_TIMEACCESSSET); 1604 } 1605 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEMODIFYSET) && 1606 NFSVNO_ISSETMTIME(nvap)) { 1607 nva.na_mtime = nvap->na_mtime; 1608 change++; 1609 NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_TIMEMODIFYSET); 1610 } 1611 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) && 1612 NFSVNO_ISSETGID(nvap)) { 1613 if (nvap->na_gid == nd->nd_cred->cr_gid || 1614 groupmember(nvap->na_gid, nd->nd_cred)) { 1615 nd->nd_cred->cr_uid = 0; 1616 nva.na_gid = nvap->na_gid; 1617 change++; 1618 NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_OWNERGROUP); 1619 } else { 1620 NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP); 1621 } 1622 } 1623 if (change) { 1624 error = nfsvno_setattr(vp, &nva, nd->nd_cred, p, exp); 1625 if (error) { 1626 NFSCLRALL_ATTRBIT(attrbitp, &nattrbits); 1627 } 1628 } 1629 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE) && 1630 NFSVNO_ISSETSIZE(nvap) && nvap->na_size != (u_quad_t)0) { 1631 NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_SIZE); 1632 } 1633 #ifdef NFS4_ACL_EXTATTR_NAME 1634 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL) && 1635 nfsrv_useacl != 0 && aclp != NULL) { 1636 if (aclp->acl_cnt > 0) { 1637 error = nfsrv_setacl(vp, aclp, nd->nd_cred, p); 1638 if (error) { 1639 NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_ACL); 1640 } 1641 } 1642 } else 1643 #endif 1644 NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_ACL); 1645 nd->nd_cred->cr_uid = tuid; 1646 1647 out: 1648 NFSEXITCODE2(0, nd); 1649 } 1650 1651 /* 1652 * Translate an ASCII hex digit to it's binary value. Return -1 if the 1653 * char isn't a hex digit. 1654 */ 1655 static char 1656 nfsrv_hexdigit(char c, int *err) 1657 { 1658 1659 *err = 0; 1660 if (c >= '0' && c <= '9') 1661 return (c - '0'); 1662 if (c >= 'a' && c <= 'f') 1663 return (c - 'a' + ((char)10)); 1664 if (c >= 'A' && c <= 'F') 1665 return (c - 'A' + ((char)10)); 1666 /* Not valid ! */ 1667 *err = 1; 1668 return (1); /* BOGUS */ 1669 } 1670 1671 /* 1672 * Check to see if NFSERR_MOVED can be returned for this op. Return 1 iff 1673 * it can be. 1674 */ 1675 APPLESTATIC int 1676 nfsrv_errmoved(int op) 1677 { 1678 short *errp; 1679 1680 errp = nfsrv_v4errmap[op]; 1681 while (*errp != 0) { 1682 if (*errp == NFSERR_MOVED) 1683 return (1); 1684 errp++; 1685 } 1686 return (0); 1687 } 1688 1689 /* 1690 * Fill in attributes for a Referral. 1691 * (Return the number of bytes of XDR created.) 1692 */ 1693 APPLESTATIC int 1694 nfsrv_putreferralattr(struct nfsrv_descript *nd, nfsattrbit_t *retbitp, 1695 struct nfsreferral *refp, int getattr, int *reterrp) 1696 { 1697 u_int32_t *tl, *retnump; 1698 u_char *cp, *cp2; 1699 int prefixnum, retnum = 0, i, len, bitpos, rderrbit = 0, nonrefbit = 0; 1700 int fslocationsbit = 0; 1701 nfsattrbit_t tmpbits, refbits; 1702 1703 NFSREFERRAL_ATTRBIT(&refbits); 1704 if (getattr) 1705 NFSCLRBIT_ATTRBIT(&refbits, NFSATTRBIT_RDATTRERROR); 1706 else if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_RDATTRERROR)) 1707 rderrbit = 1; 1708 if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_FSLOCATIONS)) 1709 fslocationsbit = 1; 1710 1711 /* 1712 * Check for the case where unsupported referral attributes are 1713 * requested. 1714 */ 1715 NFSSET_ATTRBIT(&tmpbits, retbitp); 1716 NFSCLRALL_ATTRBIT(&tmpbits, &refbits); 1717 if (NFSNONZERO_ATTRBIT(&tmpbits)) 1718 nonrefbit = 1; 1719 1720 if (nonrefbit && !fslocationsbit && (getattr || !rderrbit)) { 1721 *reterrp = NFSERR_MOVED; 1722 return (0); 1723 } 1724 1725 /* 1726 * Now we can fill in the attributes. 1727 */ 1728 NFSSET_ATTRBIT(&tmpbits, retbitp); 1729 NFSCLRNOT_ATTRBIT(&tmpbits, &refbits); 1730 1731 /* 1732 * Put out the attribute bitmap for the ones being filled in 1733 * and get the field for the number of attributes returned. 1734 */ 1735 prefixnum = nfsrv_putattrbit(nd, &tmpbits); 1736 NFSM_BUILD(retnump, u_int32_t *, NFSX_UNSIGNED); 1737 prefixnum += NFSX_UNSIGNED; 1738 1739 /* 1740 * Now, loop around filling in the attributes for each bit set. 1741 */ 1742 for (bitpos = 0; bitpos < NFSATTRBIT_MAX; bitpos++) { 1743 if (NFSISSET_ATTRBIT(&tmpbits, bitpos)) { 1744 switch (bitpos) { 1745 case NFSATTRBIT_TYPE: 1746 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1747 *tl = txdr_unsigned(NFDIR); 1748 retnum += NFSX_UNSIGNED; 1749 break; 1750 case NFSATTRBIT_FSID: 1751 NFSM_BUILD(tl, u_int32_t *, NFSX_V4FSID); 1752 *tl++ = 0; 1753 *tl++ = txdr_unsigned(NFSV4ROOT_FSID0); 1754 *tl++ = 0; 1755 *tl = txdr_unsigned(NFSV4ROOT_REFERRAL); 1756 retnum += NFSX_V4FSID; 1757 break; 1758 case NFSATTRBIT_RDATTRERROR: 1759 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1760 if (nonrefbit) 1761 *tl = txdr_unsigned(NFSERR_MOVED); 1762 else 1763 *tl = 0; 1764 retnum += NFSX_UNSIGNED; 1765 break; 1766 case NFSATTRBIT_FSLOCATIONS: 1767 retnum += nfsm_strtom(nd, "/", 1); 1768 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1769 *tl = txdr_unsigned(refp->nfr_srvcnt); 1770 retnum += NFSX_UNSIGNED; 1771 cp = refp->nfr_srvlist; 1772 for (i = 0; i < refp->nfr_srvcnt; i++) { 1773 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1774 *tl = txdr_unsigned(1); 1775 retnum += NFSX_UNSIGNED; 1776 cp2 = STRCHR(cp, ':'); 1777 if (cp2 != NULL) 1778 len = cp2 - cp; 1779 else 1780 len = 1; 1781 retnum += nfsm_strtom(nd, cp, len); 1782 if (cp2 != NULL) 1783 cp = cp2 + 1; 1784 cp2 = STRCHR(cp, ','); 1785 if (cp2 != NULL) 1786 len = cp2 - cp; 1787 else 1788 len = strlen(cp); 1789 retnum += nfsm_strtom(nd, cp, len); 1790 if (cp2 != NULL) 1791 cp = cp2 + 1; 1792 } 1793 break; 1794 case NFSATTRBIT_MOUNTEDONFILEID: 1795 NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER); 1796 *tl++ = 0; 1797 *tl = txdr_unsigned(refp->nfr_dfileno); 1798 retnum += NFSX_HYPER; 1799 break; 1800 default: 1801 printf("EEK! Bad V4 refattr bitpos=%d\n", bitpos); 1802 }; 1803 } 1804 } 1805 *retnump = txdr_unsigned(retnum); 1806 return (retnum + prefixnum); 1807 } 1808 1809 /* 1810 * Parse a file name out of a request. 1811 */ 1812 APPLESTATIC int 1813 nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp, 1814 NFSPATHLEN_T *outlenp) 1815 { 1816 char *fromcp, *tocp, val = '\0'; 1817 mbuf_t md; 1818 int i; 1819 int rem, len, error = 0, pubtype = 0, outlen = 0, percent = 0; 1820 char digit; 1821 u_int32_t *tl; 1822 u_long hash = 0; 1823 1824 if (hashp != NULL) 1825 *hashp = 0; 1826 tocp = bufp; 1827 /* 1828 * For V4, check for lookup parent. 1829 * Otherwise, get the component name. 1830 */ 1831 if ((nd->nd_flag & ND_NFSV4) && nd->nd_procnum == NFSV4OP_LOOKUPP) { 1832 *tocp++ = '.'; 1833 hash += ((u_char)'.'); 1834 *tocp++ = '.'; 1835 hash += ((u_char)'.'); 1836 outlen = 2; 1837 } else { 1838 /* 1839 * First, get the name length. 1840 */ 1841 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 1842 len = fxdr_unsigned(int, *tl); 1843 if (len > NFS_MAXNAMLEN) { 1844 nd->nd_repstat = NFSERR_NAMETOL; 1845 error = 0; 1846 goto nfsmout; 1847 } else if (len <= 0) { 1848 nd->nd_repstat = NFSERR_INVAL; 1849 error = 0; 1850 goto nfsmout; 1851 } 1852 1853 /* 1854 * Now, copy the component name into the buffer. 1855 */ 1856 fromcp = nd->nd_dpos; 1857 md = nd->nd_md; 1858 rem = NFSMTOD(md, caddr_t) + mbuf_len(md) - fromcp; 1859 for (i = 0; i < len; i++) { 1860 while (rem == 0) { 1861 md = mbuf_next(md); 1862 if (md == NULL) { 1863 error = EBADRPC; 1864 goto nfsmout; 1865 } 1866 fromcp = NFSMTOD(md, caddr_t); 1867 rem = mbuf_len(md); 1868 } 1869 if (*fromcp == '\0') { 1870 nd->nd_repstat = EACCES; 1871 error = 0; 1872 goto nfsmout; 1873 } 1874 /* 1875 * For lookups on the public filehandle, do some special 1876 * processing on the name. (The public file handle is the 1877 * root of the public file system for this server.) 1878 */ 1879 if (nd->nd_flag & ND_PUBLOOKUP) { 1880 /* 1881 * If the first char is ASCII, it is a canonical 1882 * path, otherwise it is a native path. (RFC2054 1883 * doesn't actually state what it is if the first 1884 * char isn't ASCII or 0x80, so I assume native.) 1885 * pubtype == 1 -> native path 1886 * pubtype == 2 -> canonical path 1887 */ 1888 if (i == 0) { 1889 if (*fromcp & 0x80) { 1890 /* 1891 * Since RFC2054 doesn't indicate 1892 * that a native path of just 0x80 1893 * isn't allowed, I'll replace the 1894 * 0x80 with '/' instead of just 1895 * throwing it away. 1896 */ 1897 *fromcp = '/'; 1898 pubtype = 1; 1899 } else { 1900 pubtype = 2; 1901 } 1902 } 1903 /* 1904 * '/' only allowed in a native path 1905 */ 1906 if (*fromcp == '/' && pubtype != 1) { 1907 nd->nd_repstat = EACCES; 1908 error = 0; 1909 goto nfsmout; 1910 } 1911 1912 /* 1913 * For the special case of 2 hex digits after a 1914 * '%' in an absolute path, calculate the value. 1915 * percent == 1 -> indicates "get first hex digit" 1916 * percent == 2 -> indicates "get second hex digit" 1917 */ 1918 if (percent > 0) { 1919 digit = nfsrv_hexdigit(*fromcp, &error); 1920 if (error) { 1921 nd->nd_repstat = EACCES; 1922 error = 0; 1923 goto nfsmout; 1924 } 1925 if (percent == 1) { 1926 val = (digit << 4); 1927 percent = 2; 1928 } else { 1929 val += digit; 1930 percent = 0; 1931 *tocp++ = val; 1932 hash += ((u_char)val); 1933 outlen++; 1934 } 1935 } else { 1936 if (*fromcp == '%' && pubtype == 2) { 1937 /* 1938 * Must be followed by 2 hex digits 1939 */ 1940 if ((len - i) < 3) { 1941 nd->nd_repstat = EACCES; 1942 error = 0; 1943 goto nfsmout; 1944 } 1945 percent = 1; 1946 } else { 1947 *tocp++ = *fromcp; 1948 hash += ((u_char)*fromcp); 1949 outlen++; 1950 } 1951 } 1952 } else { 1953 /* 1954 * Normal, non lookup on public, name. 1955 */ 1956 if (*fromcp == '/') { 1957 if (nd->nd_flag & ND_NFSV4) 1958 nd->nd_repstat = NFSERR_BADNAME; 1959 else 1960 nd->nd_repstat = EACCES; 1961 error = 0; 1962 goto nfsmout; 1963 } 1964 hash += ((u_char)*fromcp); 1965 *tocp++ = *fromcp; 1966 outlen++; 1967 } 1968 fromcp++; 1969 rem--; 1970 } 1971 nd->nd_md = md; 1972 nd->nd_dpos = fromcp; 1973 i = NFSM_RNDUP(len) - len; 1974 if (i > 0) { 1975 if (rem >= i) { 1976 nd->nd_dpos += i; 1977 } else { 1978 error = nfsm_advance(nd, i, rem); 1979 if (error) 1980 goto nfsmout; 1981 } 1982 } 1983 1984 /* 1985 * For v4, don't allow lookups of '.' or '..' and 1986 * also check for non-utf8 strings. 1987 */ 1988 if (nd->nd_flag & ND_NFSV4) { 1989 if ((outlen == 1 && bufp[0] == '.') || 1990 (outlen == 2 && bufp[0] == '.' && 1991 bufp[1] == '.')) { 1992 nd->nd_repstat = NFSERR_BADNAME; 1993 error = 0; 1994 goto nfsmout; 1995 } 1996 if (disable_checkutf8 == 0 && 1997 nfsrv_checkutf8((u_int8_t *)bufp, outlen)) { 1998 nd->nd_repstat = NFSERR_INVAL; 1999 error = 0; 2000 goto nfsmout; 2001 } 2002 } 2003 } 2004 *tocp = '\0'; 2005 *outlenp = (size_t)outlen; 2006 if (hashp != NULL) 2007 *hashp = hash; 2008 nfsmout: 2009 NFSEXITCODE2(error, nd); 2010 return (error); 2011 } 2012 2013 void 2014 nfsd_init(void) 2015 { 2016 int i; 2017 static int inited = 0; 2018 2019 if (inited) 2020 return; 2021 inited = 1; 2022 2023 /* 2024 * Initialize client queues. Don't free/reinitialize 2025 * them when nfsds are restarted. 2026 */ 2027 for (i = 0; i < NFSCLIENTHASHSIZE; i++) 2028 LIST_INIT(&nfsclienthash[i]); 2029 for (i = 0; i < NFSLOCKHASHSIZE; i++) 2030 LIST_INIT(&nfslockhash[i]); 2031 for (i = 0; i < NFSSESSIONHASHSIZE; i++) 2032 LIST_INIT(&nfssessionhash[i].list); 2033 2034 /* and the v2 pubfh should be all zeros */ 2035 NFSBZERO(nfs_v2pubfh, NFSX_V2FH); 2036 } 2037 2038 /* 2039 * Check the v4 root exports. 2040 * Return 0 if ok, 1 otherwise. 2041 */ 2042 int 2043 nfsd_checkrootexp(struct nfsrv_descript *nd) 2044 { 2045 2046 if ((nd->nd_flag & (ND_GSS | ND_EXAUTHSYS)) == ND_EXAUTHSYS) 2047 return (0); 2048 if ((nd->nd_flag & (ND_GSSINTEGRITY | ND_EXGSSINTEGRITY)) == 2049 (ND_GSSINTEGRITY | ND_EXGSSINTEGRITY)) 2050 return (0); 2051 if ((nd->nd_flag & (ND_GSSPRIVACY | ND_EXGSSPRIVACY)) == 2052 (ND_GSSPRIVACY | ND_EXGSSPRIVACY)) 2053 return (0); 2054 if ((nd->nd_flag & (ND_GSS | ND_GSSINTEGRITY | ND_GSSPRIVACY | 2055 ND_EXGSS)) == (ND_GSS | ND_EXGSS)) 2056 return (0); 2057 return (1); 2058 } 2059 2060 /* 2061 * Parse the first part of an NFSv4 compound to find out what the minor 2062 * version# is. 2063 */ 2064 void 2065 nfsd_getminorvers(struct nfsrv_descript *nd, u_char *tag, u_char **tagstrp, 2066 int *taglenp, u_int32_t *minversp) 2067 { 2068 uint32_t *tl; 2069 int error = 0, taglen = -1; 2070 u_char *tagstr = NULL; 2071 2072 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 2073 taglen = fxdr_unsigned(int, *tl); 2074 if (taglen < 0 || taglen > NFSV4_OPAQUELIMIT) { 2075 error = EBADRPC; 2076 goto nfsmout; 2077 } 2078 if (taglen <= NFSV4_SMALLSTR) 2079 tagstr = tag; 2080 else 2081 tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK); 2082 error = nfsrv_mtostr(nd, tagstr, taglen); 2083 if (error != 0) 2084 goto nfsmout; 2085 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 2086 *minversp = fxdr_unsigned(u_int32_t, *tl); 2087 *tagstrp = tagstr; 2088 if (*minversp == NFSV41_MINORVERSION) 2089 nd->nd_flag |= ND_NFSV41; 2090 nfsmout: 2091 if (error != 0) { 2092 if (tagstr != NULL && taglen > NFSV4_SMALLSTR) 2093 free(tagstr, M_TEMP); 2094 taglen = -1; 2095 } 2096 *taglenp = taglen; 2097 } 2098 2099