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