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