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