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