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