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