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