71 72#include <nfs/rpcv2.h> 73#include <nfs/nfsproto.h> 74#include <nfsserver/nfs.h> 75#include <nfs/xdr_subs.h> 76#include <nfsserver/nfsm_subs.h> 77 78#include <netinet/in.h> 79 80/* 81 * Data items converted to xdr at startup, since they are constant 82 * This is kinda hokey, but may save a little time doing byte swaps 83 */ 84u_int32_t nfsrv_nfs_xdrneg1; 85u_int32_t nfsrv_rpc_call, nfsrv_rpc_vers, nfsrv_rpc_reply, 86 nfsrv_rpc_msgdenied, nfsrv_rpc_autherr, 87 nfsrv_rpc_mismatch, nfsrv_rpc_auth_unix, nfsrv_rpc_msgaccepted; 88u_int32_t nfsrv_nfs_prog, nfsrv_nfs_true, nfsrv_nfs_false; 89 90/* And other global data */ 91static nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, 92 NFNON, NFCHR, NFNON }; 93#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((int32_t)(a))]) 94#define vtonfsv3_mode(m) txdr_unsigned((m) & ALLPERMS) 95 96int nfsrv_ticks; 97 98struct nfssvc_sockhead nfssvc_sockhead; 99int nfssvc_sockhead_flag; 100struct nfsd_head nfsd_head; 101int nfsd_head_flag; 102 103static int nfs_prev_nfssvc_sy_narg; 104static sy_call_t *nfs_prev_nfssvc_sy_call; 105 106/* 107 * Mapping of old NFS Version 2 RPC numbers to generic numbers. 108 */ 109int nfsrv_nfsv3_procid[NFS_NPROCS] = { 110 NFSPROC_NULL, 111 NFSPROC_GETATTR, 112 NFSPROC_SETATTR, 113 NFSPROC_NOOP, 114 NFSPROC_LOOKUP, 115 NFSPROC_READLINK, 116 NFSPROC_READ, 117 NFSPROC_NOOP, 118 NFSPROC_WRITE, 119 NFSPROC_CREATE, 120 NFSPROC_REMOVE, 121 NFSPROC_RENAME, 122 NFSPROC_LINK, 123 NFSPROC_SYMLINK, 124 NFSPROC_MKDIR, 125 NFSPROC_RMDIR, 126 NFSPROC_READDIR, 127 NFSPROC_FSSTAT, 128 NFSPROC_NOOP, 129 NFSPROC_NOOP, 130 NFSPROC_NOOP, 131 NFSPROC_NOOP, 132 NFSPROC_NOOP, 133}; 134 135/* 136 * and the reverse mapping from generic to Version 2 procedure numbers 137 */ 138int nfsrvv2_procid[NFS_NPROCS] = { 139 NFSV2PROC_NULL, 140 NFSV2PROC_GETATTR, 141 NFSV2PROC_SETATTR, 142 NFSV2PROC_LOOKUP, 143 NFSV2PROC_NOOP, 144 NFSV2PROC_READLINK, 145 NFSV2PROC_READ, 146 NFSV2PROC_WRITE, 147 NFSV2PROC_CREATE, 148 NFSV2PROC_MKDIR, 149 NFSV2PROC_SYMLINK, 150 NFSV2PROC_CREATE, 151 NFSV2PROC_REMOVE, 152 NFSV2PROC_RMDIR, 153 NFSV2PROC_RENAME, 154 NFSV2PROC_LINK, 155 NFSV2PROC_READDIR, 156 NFSV2PROC_NOOP, 157 NFSV2PROC_STATFS, 158 NFSV2PROC_NOOP, 159 NFSV2PROC_NOOP, 160 NFSV2PROC_NOOP, 161 NFSV2PROC_NOOP, 162}; 163 164/* 165 * Maps errno values to nfs error numbers. 166 * Use NFSERR_IO as the catch all for ones not specifically defined in 167 * RFC 1094. 168 */ 169static u_char nfsrv_v2errmap[ELAST] = { 170 NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO, 171 NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 172 NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO, 173 NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR, 174 NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 175 NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS, 176 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 177 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 178 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 179 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 180 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 181 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 182 NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO, 183 NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE, 184 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 185 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 186 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 187 NFSERR_IO /* << Last is 86 */ 188}; 189 190/* 191 * Maps errno values to nfs error numbers. 192 * Although it is not obvious whether or not NFS clients really care if 193 * a returned error value is in the specified list for the procedure, the 194 * safest thing to do is filter them appropriately. For Version 2, the 195 * X/Open XNFS document is the only specification that defines error values 196 * for each RPC (The RFC simply lists all possible error values for all RPCs), 197 * so I have decided to not do this for Version 2. 198 * The first entry is the default error return and the rest are the valid 199 * errors for that RPC in increasing numeric order. 200 */ 201static short nfsv3err_null[] = { 202 0, 203 0, 204}; 205 206static short nfsv3err_getattr[] = { 207 NFSERR_IO, 208 NFSERR_IO, 209 NFSERR_STALE, 210 NFSERR_BADHANDLE, 211 NFSERR_SERVERFAULT, 212 0, 213}; 214 215static short nfsv3err_setattr[] = { 216 NFSERR_IO, 217 NFSERR_PERM, 218 NFSERR_IO, 219 NFSERR_ACCES, 220 NFSERR_INVAL, 221 NFSERR_NOSPC, 222 NFSERR_ROFS, 223 NFSERR_DQUOT, 224 NFSERR_STALE, 225 NFSERR_BADHANDLE, 226 NFSERR_NOT_SYNC, 227 NFSERR_SERVERFAULT, 228 0, 229}; 230 231static short nfsv3err_lookup[] = { 232 NFSERR_IO, 233 NFSERR_NOENT, 234 NFSERR_IO, 235 NFSERR_ACCES, 236 NFSERR_NOTDIR, 237 NFSERR_NAMETOL, 238 NFSERR_STALE, 239 NFSERR_BADHANDLE, 240 NFSERR_SERVERFAULT, 241 0, 242}; 243 244static short nfsv3err_access[] = { 245 NFSERR_IO, 246 NFSERR_IO, 247 NFSERR_STALE, 248 NFSERR_BADHANDLE, 249 NFSERR_SERVERFAULT, 250 0, 251}; 252 253static short nfsv3err_readlink[] = { 254 NFSERR_IO, 255 NFSERR_IO, 256 NFSERR_ACCES, 257 NFSERR_INVAL, 258 NFSERR_STALE, 259 NFSERR_BADHANDLE, 260 NFSERR_NOTSUPP, 261 NFSERR_SERVERFAULT, 262 0, 263}; 264 265static short nfsv3err_read[] = { 266 NFSERR_IO, 267 NFSERR_IO, 268 NFSERR_NXIO, 269 NFSERR_ACCES, 270 NFSERR_INVAL, 271 NFSERR_STALE, 272 NFSERR_BADHANDLE, 273 NFSERR_SERVERFAULT, 274 0, 275}; 276 277static short nfsv3err_write[] = { 278 NFSERR_IO, 279 NFSERR_IO, 280 NFSERR_ACCES, 281 NFSERR_INVAL, 282 NFSERR_FBIG, 283 NFSERR_NOSPC, 284 NFSERR_ROFS, 285 NFSERR_DQUOT, 286 NFSERR_STALE, 287 NFSERR_BADHANDLE, 288 NFSERR_SERVERFAULT, 289 0, 290}; 291 292static short nfsv3err_create[] = { 293 NFSERR_IO, 294 NFSERR_IO, 295 NFSERR_ACCES, 296 NFSERR_EXIST, 297 NFSERR_NOTDIR, 298 NFSERR_NOSPC, 299 NFSERR_ROFS, 300 NFSERR_NAMETOL, 301 NFSERR_DQUOT, 302 NFSERR_STALE, 303 NFSERR_BADHANDLE, 304 NFSERR_NOTSUPP, 305 NFSERR_SERVERFAULT, 306 0, 307}; 308 309static short nfsv3err_mkdir[] = { 310 NFSERR_IO, 311 NFSERR_IO, 312 NFSERR_ACCES, 313 NFSERR_EXIST, 314 NFSERR_NOTDIR, 315 NFSERR_NOSPC, 316 NFSERR_ROFS, 317 NFSERR_NAMETOL, 318 NFSERR_DQUOT, 319 NFSERR_STALE, 320 NFSERR_BADHANDLE, 321 NFSERR_NOTSUPP, 322 NFSERR_SERVERFAULT, 323 0, 324}; 325 326static short nfsv3err_symlink[] = { 327 NFSERR_IO, 328 NFSERR_IO, 329 NFSERR_ACCES, 330 NFSERR_EXIST, 331 NFSERR_NOTDIR, 332 NFSERR_NOSPC, 333 NFSERR_ROFS, 334 NFSERR_NAMETOL, 335 NFSERR_DQUOT, 336 NFSERR_STALE, 337 NFSERR_BADHANDLE, 338 NFSERR_NOTSUPP, 339 NFSERR_SERVERFAULT, 340 0, 341}; 342 343static short nfsv3err_mknod[] = { 344 NFSERR_IO, 345 NFSERR_IO, 346 NFSERR_ACCES, 347 NFSERR_EXIST, 348 NFSERR_NOTDIR, 349 NFSERR_NOSPC, 350 NFSERR_ROFS, 351 NFSERR_NAMETOL, 352 NFSERR_DQUOT, 353 NFSERR_STALE, 354 NFSERR_BADHANDLE, 355 NFSERR_NOTSUPP, 356 NFSERR_SERVERFAULT, 357 NFSERR_BADTYPE, 358 0, 359}; 360 361static short nfsv3err_remove[] = { 362 NFSERR_IO, 363 NFSERR_NOENT, 364 NFSERR_IO, 365 NFSERR_ACCES, 366 NFSERR_NOTDIR, 367 NFSERR_ROFS, 368 NFSERR_NAMETOL, 369 NFSERR_STALE, 370 NFSERR_BADHANDLE, 371 NFSERR_SERVERFAULT, 372 0, 373}; 374 375static short nfsv3err_rmdir[] = { 376 NFSERR_IO, 377 NFSERR_NOENT, 378 NFSERR_IO, 379 NFSERR_ACCES, 380 NFSERR_EXIST, 381 NFSERR_NOTDIR, 382 NFSERR_INVAL, 383 NFSERR_ROFS, 384 NFSERR_NAMETOL, 385 NFSERR_NOTEMPTY, 386 NFSERR_STALE, 387 NFSERR_BADHANDLE, 388 NFSERR_NOTSUPP, 389 NFSERR_SERVERFAULT, 390 0, 391}; 392 393static short nfsv3err_rename[] = { 394 NFSERR_IO, 395 NFSERR_NOENT, 396 NFSERR_IO, 397 NFSERR_ACCES, 398 NFSERR_EXIST, 399 NFSERR_XDEV, 400 NFSERR_NOTDIR, 401 NFSERR_ISDIR, 402 NFSERR_INVAL, 403 NFSERR_NOSPC, 404 NFSERR_ROFS, 405 NFSERR_MLINK, 406 NFSERR_NAMETOL, 407 NFSERR_NOTEMPTY, 408 NFSERR_DQUOT, 409 NFSERR_STALE, 410 NFSERR_BADHANDLE, 411 NFSERR_NOTSUPP, 412 NFSERR_SERVERFAULT, 413 0, 414}; 415 416static short nfsv3err_link[] = { 417 NFSERR_IO, 418 NFSERR_IO, 419 NFSERR_ACCES, 420 NFSERR_EXIST, 421 NFSERR_XDEV, 422 NFSERR_NOTDIR, 423 NFSERR_INVAL, 424 NFSERR_NOSPC, 425 NFSERR_ROFS, 426 NFSERR_MLINK, 427 NFSERR_NAMETOL, 428 NFSERR_DQUOT, 429 NFSERR_STALE, 430 NFSERR_BADHANDLE, 431 NFSERR_NOTSUPP, 432 NFSERR_SERVERFAULT, 433 0, 434}; 435 436static short nfsv3err_readdir[] = { 437 NFSERR_IO, 438 NFSERR_IO, 439 NFSERR_ACCES, 440 NFSERR_NOTDIR, 441 NFSERR_STALE, 442 NFSERR_BADHANDLE, 443 NFSERR_BAD_COOKIE, 444 NFSERR_TOOSMALL, 445 NFSERR_SERVERFAULT, 446 0, 447}; 448 449static short nfsv3err_readdirplus[] = { 450 NFSERR_IO, 451 NFSERR_IO, 452 NFSERR_ACCES, 453 NFSERR_NOTDIR, 454 NFSERR_STALE, 455 NFSERR_BADHANDLE, 456 NFSERR_BAD_COOKIE, 457 NFSERR_NOTSUPP, 458 NFSERR_TOOSMALL, 459 NFSERR_SERVERFAULT, 460 0, 461}; 462 463static short nfsv3err_fsstat[] = { 464 NFSERR_IO, 465 NFSERR_IO, 466 NFSERR_STALE, 467 NFSERR_BADHANDLE, 468 NFSERR_SERVERFAULT, 469 0, 470}; 471 472static short nfsv3err_fsinfo[] = { 473 NFSERR_STALE, 474 NFSERR_STALE, 475 NFSERR_BADHANDLE, 476 NFSERR_SERVERFAULT, 477 0, 478}; 479 480static short nfsv3err_pathconf[] = { 481 NFSERR_STALE, 482 NFSERR_STALE, 483 NFSERR_BADHANDLE, 484 NFSERR_SERVERFAULT, 485 0, 486}; 487 488static short nfsv3err_commit[] = { 489 NFSERR_IO, 490 NFSERR_IO, 491 NFSERR_STALE, 492 NFSERR_BADHANDLE, 493 NFSERR_SERVERFAULT, 494 0, 495}; 496 497static short *nfsrv_v3errmap[] = { 498 nfsv3err_null, 499 nfsv3err_getattr, 500 nfsv3err_setattr, 501 nfsv3err_lookup, 502 nfsv3err_access, 503 nfsv3err_readlink, 504 nfsv3err_read, 505 nfsv3err_write, 506 nfsv3err_create, 507 nfsv3err_mkdir, 508 nfsv3err_symlink, 509 nfsv3err_mknod, 510 nfsv3err_remove, 511 nfsv3err_rmdir, 512 nfsv3err_rename, 513 nfsv3err_link, 514 nfsv3err_readdir, 515 nfsv3err_readdirplus, 516 nfsv3err_fsstat, 517 nfsv3err_fsinfo, 518 nfsv3err_pathconf, 519 nfsv3err_commit, 520}; 521 522/* 523 * Called once to initialize data structures... 524 */ 525static int 526nfsrv_modevent(module_t mod, int type, void *data) 527{ 528 529 switch (type) { 530 case MOD_LOAD: 531 nfsrv_rpc_vers = txdr_unsigned(RPC_VER2); 532 nfsrv_rpc_call = txdr_unsigned(RPC_CALL); 533 nfsrv_rpc_reply = txdr_unsigned(RPC_REPLY); 534 nfsrv_rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED); 535 nfsrv_rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED); 536 nfsrv_rpc_mismatch = txdr_unsigned(RPC_MISMATCH); 537 nfsrv_rpc_autherr = txdr_unsigned(RPC_AUTHERR); 538 nfsrv_rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX); 539 nfsrv_nfs_prog = txdr_unsigned(NFS_PROG); 540 nfsrv_nfs_true = txdr_unsigned(TRUE); 541 nfsrv_nfs_false = txdr_unsigned(FALSE); 542 nfsrv_nfs_xdrneg1 = txdr_unsigned(-1); 543 nfsrv_ticks = (hz * NFS_TICKINTVL + 500) / 1000; 544 if (nfsrv_ticks < 1) 545 nfsrv_ticks = 1; 546 547 nfsrv_init(0); /* Init server data structures */ 548 nfsrv_initcache(); /* Init the server request cache */ 549 550 nfsrv_timer(0); 551 552 nfs_prev_nfssvc_sy_narg = sysent[SYS_nfssvc].sy_narg; 553 sysent[SYS_nfssvc].sy_narg = 2; 554 nfs_prev_nfssvc_sy_call = sysent[SYS_nfssvc].sy_call; 555 sysent[SYS_nfssvc].sy_call = (sy_call_t *)nfssvc; 556 break; 557 558 case MOD_UNLOAD: 559 560 untimeout(nfsrv_timer, (void *)NULL, nfsrv_timer_handle); 561 sysent[SYS_nfssvc].sy_narg = nfs_prev_nfssvc_sy_narg; 562 sysent[SYS_nfssvc].sy_call = nfs_prev_nfssvc_sy_call; 563 break; 564 } 565 return 0; 566} 567static moduledata_t nfsserver_mod = { 568 "nfsserver", 569 nfsrv_modevent, 570 NULL, 571}; 572DECLARE_MODULE(nfsserver, nfsserver_mod, SI_SUB_VFS, SI_ORDER_ANY); 573 574/* So that loader and kldload(2) can find us, wherever we are.. */ 575MODULE_VERSION(nfsserver, 1); 576 577/* 578 * Set up nameidata for a lookup() call and do it. 579 * 580 * If pubflag is set, this call is done for a lookup operation on the 581 * public filehandle. In that case we allow crossing mountpoints and 582 * absolute pathnames. However, the caller is expected to check that 583 * the lookup result is within the public fs, and deny access if 584 * it is not. 585 * 586 * nfs_namei() clears out garbage fields that namei() might leave garbage. 587 * This is mainly ni_vp and ni_dvp when an error occurs, and ni_dvp when no 588 * error occurs but the parent was not requested. 589 * 590 * dirp may be set whether an error is returned or not, and must be 591 * released by the caller. 592 */ 593int 594nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len, 595 struct nfssvc_sock *slp, struct sockaddr *nam, struct mbuf **mdp, 596 caddr_t *dposp, struct vnode **retdirp, struct thread *td, int pubflag) 597{ 598 int i, rem; 599 struct mbuf *md; 600 char *fromcp, *tocp, *cp; 601 struct iovec aiov; 602 struct uio auio; 603 struct vnode *dp; 604 int error, rdonly, linklen; 605 struct componentname *cnp = &ndp->ni_cnd; 606 607 *retdirp = (struct vnode *)0;
|
852 ndp->ni_vp = NULL; 853 ndp->ni_dvp = NULL; 854 ndp->ni_startdir = NULL; 855 cnp->cn_flags &= ~HASBUF; 856 } else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) { 857 ndp->ni_dvp = NULL; 858 } 859 return (error); 860} 861 862/* 863 * A fiddled version of m_adj() that ensures null fill to a long 864 * boundary and only trims off the back end 865 */ 866void 867nfsm_adj(struct mbuf *mp, int len, int nul) 868{ 869 struct mbuf *m; 870 int count, i; 871 char *cp; 872 873 /* 874 * Trim from tail. Scan the mbuf chain, 875 * calculating its length and finding the last mbuf. 876 * If the adjustment only affects this mbuf, then just 877 * adjust and return. Otherwise, rescan and truncate 878 * after the remaining size. 879 */ 880 count = 0; 881 m = mp; 882 for (;;) { 883 count += m->m_len; 884 if (m->m_next == (struct mbuf *)0) 885 break; 886 m = m->m_next; 887 } 888 if (m->m_len > len) { 889 m->m_len -= len; 890 if (nul > 0) { 891 cp = mtod(m, caddr_t)+m->m_len-nul; 892 for (i = 0; i < nul; i++) 893 *cp++ = '\0'; 894 } 895 return; 896 } 897 count -= len; 898 if (count < 0) 899 count = 0; 900 /* 901 * Correct length for chain is "count". 902 * Find the mbuf with last data, adjust its length, 903 * and toss data from remaining mbufs on chain. 904 */ 905 for (m = mp; m; m = m->m_next) { 906 if (m->m_len >= count) { 907 m->m_len = count; 908 if (nul > 0) { 909 cp = mtod(m, caddr_t)+m->m_len-nul; 910 for (i = 0; i < nul; i++) 911 *cp++ = '\0'; 912 } 913 break; 914 } 915 count -= m->m_len; 916 } 917 for (m = m->m_next;m;m = m->m_next) 918 m->m_len = 0; 919} 920 921/* 922 * Make these functions instead of macros, so that the kernel text size 923 * doesn't get too big... 924 */ 925void 926nfsm_srvwcc(struct nfsrv_descript *nfsd, int before_ret, 927 struct vattr *before_vap, int after_ret, struct vattr *after_vap, 928 struct mbuf **mbp, char **bposp) 929{ 930 struct mbuf *mb = *mbp; 931 char *bpos = *bposp; 932 u_int32_t *tl; 933 934 if (before_ret) { 935 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED); 936 *tl = nfsrv_nfs_false; 937 } else { 938 tl = nfsm_build(u_int32_t *, 7 * NFSX_UNSIGNED); 939 *tl++ = nfsrv_nfs_true; 940 txdr_hyper(before_vap->va_size, tl); 941 tl += 2; 942 txdr_nfsv3time(&(before_vap->va_mtime), tl); 943 tl += 2; 944 txdr_nfsv3time(&(before_vap->va_ctime), tl); 945 } 946 *bposp = bpos; 947 *mbp = mb; 948 nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp); 949} 950 951void 952nfsm_srvpostopattr(struct nfsrv_descript *nfsd, int after_ret, 953 struct vattr *after_vap, struct mbuf **mbp, char **bposp) 954{ 955 struct mbuf *mb = *mbp; 956 char *bpos = *bposp; 957 u_int32_t *tl; 958 struct nfs_fattr *fp; 959 960 if (after_ret) { 961 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED); 962 *tl = nfsrv_nfs_false; 963 } else { 964 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR); 965 *tl++ = nfsrv_nfs_true; 966 fp = (struct nfs_fattr *)tl; 967 nfsm_srvfattr(nfsd, after_vap, fp); 968 } 969 *mbp = mb; 970 *bposp = bpos; 971} 972 973void 974nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap, 975 struct nfs_fattr *fp) 976{ 977 978 fp->fa_nlink = txdr_unsigned(vap->va_nlink); 979 fp->fa_uid = txdr_unsigned(vap->va_uid); 980 fp->fa_gid = txdr_unsigned(vap->va_gid); 981 if (nfsd->nd_flag & ND_NFSV3) { 982 fp->fa_type = vtonfsv3_type(vap->va_type); 983 fp->fa_mode = vtonfsv3_mode(vap->va_mode); 984 txdr_hyper(vap->va_size, &fp->fa3_size); 985 txdr_hyper(vap->va_bytes, &fp->fa3_used); 986 fp->fa3_rdev.specdata1 = txdr_unsigned(umajor(vap->va_rdev)); 987 fp->fa3_rdev.specdata2 = txdr_unsigned(uminor(vap->va_rdev)); 988 fp->fa3_fsid.nfsuquad[0] = 0; 989 fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid); 990 fp->fa3_fileid.nfsuquad[0] = 0; 991 fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid); 992 txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime); 993 txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime); 994 txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime); 995 } else { 996 fp->fa_type = vtonfsv2_type(vap->va_type); 997 fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 998 fp->fa2_size = txdr_unsigned(vap->va_size); 999 fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize); 1000 if (vap->va_type == VFIFO) 1001 fp->fa2_rdev = 0xffffffff; 1002 else 1003 fp->fa2_rdev = txdr_unsigned(vap->va_rdev); 1004 fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); 1005 fp->fa2_fsid = txdr_unsigned(vap->va_fsid); 1006 fp->fa2_fileid = txdr_unsigned(vap->va_fileid); 1007 txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime); 1008 txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime); 1009 txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime); 1010 } 1011} 1012 1013/* 1014 * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked) 1015 * - look up fsid in mount list (if not found ret error) 1016 * - get vp and export rights by calling VFS_FHTOVP() 1017 * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon 1018 * - if not lockflag unlock it with VOP_UNLOCK() 1019 */ 1020int 1021nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, 1022 struct ucred *cred, struct nfssvc_sock *slp, struct sockaddr *nam, 1023 int *rdonlyp, int pubflag) 1024{ 1025 struct thread *td = curthread; /* XXX */ 1026 struct mount *mp; 1027 int i; 1028 struct ucred *credanon; 1029 int error, exflags; 1030#ifdef MNT_EXNORESPORT /* XXX needs mountd and /etc/exports help yet */ 1031 struct sockaddr_int *saddr; 1032#endif 1033 1034 *vpp = (struct vnode *)0; 1035 1036 if (nfs_ispublicfh(fhp)) { 1037 if (!pubflag || !nfs_pub.np_valid) 1038 return (ESTALE); 1039 fhp = &nfs_pub.np_handle; 1040 } 1041 1042 mp = vfs_getvfs(&fhp->fh_fsid); 1043 if (!mp) 1044 return (ESTALE); 1045 error = VFS_CHECKEXP(mp, nam, &exflags, &credanon); 1046 if (error) 1047 return (error); 1048 error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp); 1049 if (error) 1050 return (error); 1051#ifdef MNT_EXNORESPORT 1052 if (!(exflags & (MNT_EXNORESPORT|MNT_EXPUBLIC))) { 1053 saddr = (struct sockaddr_in *)nam; 1054 if (saddr->sin_family == AF_INET && 1055 ntohs(saddr->sin_port) >= IPPORT_RESERVED) { 1056 vput(*vpp); 1057 *vpp = NULL; 1058 return (NFSERR_AUTHERR | AUTH_TOOWEAK); 1059 } 1060 } 1061#endif 1062 /* 1063 * Check/setup credentials. 1064 */ 1065 if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) { 1066 cred->cr_uid = credanon->cr_uid; 1067 for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++) 1068 cred->cr_groups[i] = credanon->cr_groups[i]; 1069 cred->cr_ngroups = i; 1070 } 1071 if (exflags & MNT_EXRDONLY) 1072 *rdonlyp = 1; 1073 else 1074 *rdonlyp = 0; 1075 1076 nfsrv_object_create(*vpp); 1077 1078 if (!lockflag) 1079 VOP_UNLOCK(*vpp, 0, td); 1080 return (0); 1081} 1082 1083 1084/* 1085 * WebNFS: check if a filehandle is a public filehandle. For v3, this 1086 * means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has 1087 * transformed this to all zeroes in both cases, so check for it. 1088 */ 1089int 1090nfs_ispublicfh(fhandle_t *fhp) 1091{ 1092 char *cp = (char *)fhp; 1093 int i; 1094 1095 for (i = 0; i < NFSX_V3FH; i++) 1096 if (*cp++ != 0) 1097 return (FALSE); 1098 return (TRUE); 1099} 1100 1101/* 1102 * This function compares two net addresses by family and returns TRUE 1103 * if they are the same host. 1104 * If there is any doubt, return FALSE. 1105 * The AF_INET family is handled as a special case so that address mbufs 1106 * don't need to be saved to store "struct in_addr", which is only 4 bytes. 1107 */ 1108int 1109netaddr_match(int family, union nethostaddr *haddr, struct sockaddr *nam) 1110{ 1111 struct sockaddr_in *inetaddr; 1112 1113 switch (family) { 1114 case AF_INET: 1115 inetaddr = (struct sockaddr_in *)nam; 1116 if (inetaddr->sin_family == AF_INET && 1117 inetaddr->sin_addr.s_addr == haddr->had_inetaddr) 1118 return (1); 1119 break; 1120 default: 1121 break; 1122 }; 1123 return (0); 1124} 1125 1126/* 1127 * Map errnos to NFS error numbers. For Version 3 also filter out error 1128 * numbers not specified for the associated procedure. 1129 */ 1130int 1131nfsrv_errmap(struct nfsrv_descript *nd, int err) 1132{ 1133 short *defaulterrp, *errp; 1134 1135 if (nd->nd_flag & ND_NFSV3) { 1136 if (nd->nd_procnum <= NFSPROC_COMMIT) { 1137 errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum]; 1138 while (*++errp) { 1139 if (*errp == err) 1140 return (err); 1141 else if (*errp > err) 1142 break; 1143 } 1144 return ((int)*defaulterrp); 1145 } else 1146 return (err & 0xffff); 1147 } 1148 if (err <= ELAST) 1149 return ((int)nfsrv_v2errmap[err - 1]); 1150 return (NFSERR_IO); 1151} 1152 1153int 1154nfsrv_object_create(struct vnode *vp) 1155{ 1156 1157 if (vp == NULL || vp->v_type != VREG) 1158 return (1); 1159 return (vfs_object_create(vp, curthread, curthread->td_ucred)); 1160} 1161 1162/* 1163 * Sort the group list in increasing numerical order. 1164 * (Insertion sort by Chris Torek, who was grossed out by the bubble sort 1165 * that used to be here.) 1166 */ 1167void 1168nfsrvw_sort(gid_t *list, int num) 1169{ 1170 int i, j; 1171 gid_t v; 1172 1173 /* Insertion sort. */ 1174 for (i = 1; i < num; i++) { 1175 v = list[i]; 1176 /* find correct slot for value v, moving others up */ 1177 for (j = i; --j >= 0 && v < list[j];) 1178 list[j + 1] = list[j]; 1179 list[j + 1] = v; 1180 } 1181} 1182 1183/* 1184 * copy credentials making sure that the result can be compared with bcmp(). 1185 */ 1186void 1187nfsrv_setcred(struct ucred *incred, struct ucred *outcred) 1188{ 1189 int i; 1190 1191 bzero((caddr_t)outcred, sizeof (struct ucred)); 1192 outcred->cr_ref = 1; 1193 outcred->cr_uid = incred->cr_uid; 1194 outcred->cr_ngroups = incred->cr_ngroups; 1195 for (i = 0; i < incred->cr_ngroups; i++) 1196 outcred->cr_groups[i] = incred->cr_groups[i]; 1197 nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups); 1198} 1199 1200/* 1201 * Helper functions for macros. 1202 */ 1203 1204void 1205nfsm_srvfhtom_xx(fhandle_t *f, int v3, struct mbuf **mb, caddr_t *bpos) 1206{ 1207 u_int32_t *tl; 1208 1209 if (v3) { 1210 tl = nfsm_build_xx(NFSX_UNSIGNED + NFSX_V3FH, mb, bpos); 1211 *tl++ = txdr_unsigned(NFSX_V3FH); 1212 bcopy(f, tl, NFSX_V3FH); 1213 } else { 1214 tl = nfsm_build_xx(NFSX_V2FH, mb, bpos); 1215 bcopy(f, tl, NFSX_V2FH); 1216 } 1217} 1218 1219void 1220nfsm_srvpostop_fh_xx(fhandle_t *f, struct mbuf **mb, caddr_t *bpos) 1221{ 1222 u_int32_t *tl; 1223 1224 tl = nfsm_build_xx(2 * NFSX_UNSIGNED + NFSX_V3FH, mb, bpos); 1225 *tl++ = nfsrv_nfs_true; 1226 *tl++ = txdr_unsigned(NFSX_V3FH); 1227 bcopy(f, tl, NFSX_V3FH); 1228} 1229 1230int 1231nfsm_srvstrsiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos) 1232{ 1233 u_int32_t *tl; 1234 1235 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); 1236 if (tl == NULL) 1237 return EBADRPC; 1238 *s = fxdr_unsigned(int32_t, *tl); 1239 if (*s > m || *s <= 0) 1240 return EBADRPC; 1241 return 0; 1242} 1243 1244int 1245nfsm_srvnamesiz_xx(int *s, struct mbuf **md, caddr_t *dpos) 1246{ 1247 u_int32_t *tl; 1248 1249 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); 1250 if (tl == NULL) 1251 return EBADRPC; 1252 *s = fxdr_unsigned(int32_t, *tl); 1253 if (*s > NFS_MAXNAMLEN) 1254 return NFSERR_NAMETOL; 1255 if (*s <= 0) 1256 return EBADRPC; 1257 return 0; 1258} 1259 1260void 1261nfsm_clget_xx(u_int32_t **tl, struct mbuf *mb, struct mbuf **mp, 1262 char **bp, char **be, caddr_t bpos) 1263{ 1264 struct mbuf *nmp; 1265 1266 if (*bp >= *be) { 1267 if (*mp == mb) 1268 (*mp)->m_len += *bp - bpos; 1269 MGET(nmp, M_TRYWAIT, MT_DATA); 1270 MCLGET(nmp, M_TRYWAIT); 1271 nmp->m_len = NFSMSIZ(nmp); 1272 (*mp)->m_next = nmp; 1273 *mp = nmp; 1274 *bp = mtod(*mp, caddr_t); 1275 *be = *bp + (*mp)->m_len; 1276 } 1277 *tl = (u_int32_t *)*bp; 1278} 1279 1280int 1281nfsm_srvmtofh_xx(fhandle_t *f, struct nfsrv_descript *nfsd, struct mbuf **md, 1282 caddr_t *dpos) 1283{ 1284 u_int32_t *tl; 1285 int fhlen; 1286 1287 if (nfsd->nd_flag & ND_NFSV3) { 1288 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); 1289 if (tl == NULL) 1290 return EBADRPC; 1291 fhlen = fxdr_unsigned(int, *tl); 1292 if (fhlen != 0 && fhlen != NFSX_V3FH) 1293 return EBADRPC; 1294 } else { 1295 fhlen = NFSX_V2FH; 1296 } 1297 if (fhlen != 0) { 1298 tl = nfsm_dissect_xx(fhlen, md, dpos); 1299 if (tl == NULL) 1300 return EBADRPC; 1301 bcopy((caddr_t)tl, (caddr_t)(f), fhlen); 1302 } else { 1303 bzero((caddr_t)(f), NFSX_V3FH); 1304 } 1305 return 0; 1306} 1307 1308int 1309nfsm_srvsattr_xx(struct vattr *a, struct mbuf **md, caddr_t *dpos) 1310{ 1311 u_int32_t *tl; 1312 1313 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); 1314 if (tl == NULL) 1315 return EBADRPC; 1316 if (*tl == nfsrv_nfs_true) { 1317 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); 1318 if (tl == NULL) 1319 return EBADRPC; 1320 (a)->va_mode = nfstov_mode(*tl); 1321 } 1322 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); 1323 if (tl == NULL) 1324 return EBADRPC; 1325 if (*tl == nfsrv_nfs_true) { 1326 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); 1327 if (tl == NULL) 1328 return EBADRPC; 1329 (a)->va_uid = fxdr_unsigned(uid_t, *tl); 1330 } 1331 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); 1332 if (tl == NULL) 1333 return EBADRPC; 1334 if (*tl == nfsrv_nfs_true) { 1335 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); 1336 if (tl == NULL) 1337 return EBADRPC; 1338 (a)->va_gid = fxdr_unsigned(gid_t, *tl); 1339 } 1340 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); 1341 if (tl == NULL) 1342 return EBADRPC; 1343 if (*tl == nfsrv_nfs_true) { 1344 tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos); 1345 if (tl == NULL) 1346 return EBADRPC; 1347 (a)->va_size = fxdr_hyper(tl); 1348 } 1349 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); 1350 if (tl == NULL) 1351 return EBADRPC; 1352 switch (fxdr_unsigned(int, *tl)) { 1353 case NFSV3SATTRTIME_TOCLIENT: 1354 tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos); 1355 if (tl == NULL) 1356 return EBADRPC; 1357 fxdr_nfsv3time(tl, &(a)->va_atime); 1358 break; 1359 case NFSV3SATTRTIME_TOSERVER: 1360 getnanotime(&(a)->va_atime); 1361 break; 1362 } 1363 tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); 1364 if (tl == NULL) 1365 return EBADRPC; 1366 switch (fxdr_unsigned(int, *tl)) { 1367 case NFSV3SATTRTIME_TOCLIENT: 1368 tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos); 1369 if (tl == NULL) 1370 return EBADRPC; 1371 fxdr_nfsv3time(tl, &(a)->va_mtime); 1372 break; 1373 case NFSV3SATTRTIME_TOSERVER: 1374 getnanotime(&(a)->va_mtime); 1375 break; 1376 } 1377 return 0; 1378}
|