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