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