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