1 /*- 2 * Copyright (c) 1989, 1991, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 4. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 */ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 /* 38 * Socket operations for use by nfs 39 */ 40 41 #include "opt_inet6.h" 42 #include "opt_kgssapi.h" 43 #include "opt_nfs.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/kernel.h> 48 #include <sys/limits.h> 49 #include <sys/lock.h> 50 #include <sys/malloc.h> 51 #include <sys/mbuf.h> 52 #include <sys/mount.h> 53 #include <sys/mutex.h> 54 #include <sys/proc.h> 55 #include <sys/signalvar.h> 56 #include <sys/syscallsubr.h> 57 #include <sys/sysctl.h> 58 #include <sys/syslog.h> 59 #include <sys/vnode.h> 60 61 #include <rpc/rpc.h> 62 63 #include <kgssapi/krb5/kcrypto.h> 64 65 #include <fs/nfs/nfsport.h> 66 67 NFSSTATESPINLOCK; 68 NFSREQSPINLOCK; 69 extern struct nfsstats newnfsstats; 70 extern struct nfsreqhead nfsd_reqq; 71 extern int nfscl_ticks; 72 extern void (*ncl_call_invalcaches)(struct vnode *); 73 74 static int nfsrv_gsscallbackson = 0; 75 static int nfs_bufpackets = 4; 76 static int nfs_reconnects; 77 static int nfs3_jukebox_delay = 10; 78 static int nfs_skip_wcc_data_onerr = 1; 79 static int nfs_keytab_enctype = ETYPE_DES_CBC_CRC; 80 81 SYSCTL_DECL(_vfs_nfs); 82 83 SYSCTL_INT(_vfs_nfs, OID_AUTO, bufpackets, CTLFLAG_RW, &nfs_bufpackets, 0, 84 "Buffer reservation size 2 < x < 64"); 85 SYSCTL_INT(_vfs_nfs, OID_AUTO, reconnects, CTLFLAG_RD, &nfs_reconnects, 0, 86 "Number of times the nfs client has had to reconnect"); 87 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs3_jukebox_delay, CTLFLAG_RW, &nfs3_jukebox_delay, 0, 88 "Number of seconds to delay a retry after receiving EJUKEBOX"); 89 SYSCTL_INT(_vfs_nfs, OID_AUTO, skip_wcc_data_onerr, CTLFLAG_RW, &nfs_skip_wcc_data_onerr, 0, 90 "Disable weak cache consistency checking when server returns an error"); 91 SYSCTL_INT(_vfs_nfs, OID_AUTO, keytab_enctype, CTLFLAG_RW, &nfs_keytab_enctype, 0, 92 "Encryption type for the keytab entry used by nfs"); 93 94 static void nfs_down(struct nfsmount *, struct thread *, const char *, 95 int, int); 96 static void nfs_up(struct nfsmount *, struct thread *, const char *, 97 int, int); 98 static int nfs_msg(struct thread *, const char *, const char *, int); 99 100 struct nfs_cached_auth { 101 int ca_refs; /* refcount, including 1 from the cache */ 102 uid_t ca_uid; /* uid that corresponds to this auth */ 103 AUTH *ca_auth; /* RPC auth handle */ 104 }; 105 106 static int nfsv2_procid[NFS_V3NPROCS] = { 107 NFSV2PROC_NULL, 108 NFSV2PROC_GETATTR, 109 NFSV2PROC_SETATTR, 110 NFSV2PROC_LOOKUP, 111 NFSV2PROC_NOOP, 112 NFSV2PROC_READLINK, 113 NFSV2PROC_READ, 114 NFSV2PROC_WRITE, 115 NFSV2PROC_CREATE, 116 NFSV2PROC_MKDIR, 117 NFSV2PROC_SYMLINK, 118 NFSV2PROC_CREATE, 119 NFSV2PROC_REMOVE, 120 NFSV2PROC_RMDIR, 121 NFSV2PROC_RENAME, 122 NFSV2PROC_LINK, 123 NFSV2PROC_READDIR, 124 NFSV2PROC_NOOP, 125 NFSV2PROC_STATFS, 126 NFSV2PROC_NOOP, 127 NFSV2PROC_NOOP, 128 NFSV2PROC_NOOP, 129 }; 130 131 /* 132 * Initialize sockets and congestion for a new NFS connection. 133 * We do not free the sockaddr if error. 134 */ 135 int 136 newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp, 137 struct ucred *cred, NFSPROC_T *p, int callback_retry_mult) 138 { 139 int rcvreserve, sndreserve; 140 int pktscale; 141 struct sockaddr *saddr; 142 struct ucred *origcred; 143 CLIENT *client; 144 struct netconfig *nconf; 145 struct socket *so; 146 int one = 1, retries, error; 147 struct thread *td = curthread; 148 149 /* 150 * We need to establish the socket using the credentials of 151 * the mountpoint. Some parts of this process (such as 152 * sobind() and soconnect()) will use the curent thread's 153 * credential instead of the socket credential. To work 154 * around this, temporarily change the current thread's 155 * credential to that of the mountpoint. 156 * 157 * XXX: It would be better to explicitly pass the correct 158 * credential to sobind() and soconnect(). 159 */ 160 origcred = td->td_ucred; 161 162 /* 163 * Use the credential in nr_cred, if not NULL. 164 */ 165 if (nrp->nr_cred != NULL) 166 td->td_ucred = nrp->nr_cred; 167 else 168 td->td_ucred = cred; 169 saddr = nrp->nr_nam; 170 171 if (saddr->sa_family == AF_INET) 172 if (nrp->nr_sotype == SOCK_DGRAM) 173 nconf = getnetconfigent("udp"); 174 else 175 nconf = getnetconfigent("tcp"); 176 else 177 if (nrp->nr_sotype == SOCK_DGRAM) 178 nconf = getnetconfigent("udp6"); 179 else 180 nconf = getnetconfigent("tcp6"); 181 182 pktscale = nfs_bufpackets; 183 if (pktscale < 2) 184 pktscale = 2; 185 if (pktscale > 64) 186 pktscale = 64; 187 /* 188 * soreserve() can fail if sb_max is too small, so shrink pktscale 189 * and try again if there is an error. 190 * Print a log message suggesting increasing sb_max. 191 * Creating a socket and doing this is necessary since, if the 192 * reservation sizes are too large and will make soreserve() fail, 193 * the connection will work until a large send is attempted and 194 * then it will loop in the krpc code. 195 */ 196 so = NULL; 197 saddr = NFSSOCKADDR(nrp->nr_nam, struct sockaddr *); 198 error = socreate(saddr->sa_family, &so, nrp->nr_sotype, 199 nrp->nr_soproto, td->td_ucred, td); 200 if (error) { 201 td->td_ucred = origcred; 202 return (error); 203 } 204 do { 205 if (error != 0 && pktscale > 2) 206 pktscale--; 207 if (nrp->nr_sotype == SOCK_DGRAM) { 208 if (nmp != NULL) { 209 sndreserve = (NFS_MAXDGRAMDATA + NFS_MAXPKTHDR) * 210 pktscale; 211 rcvreserve = (NFS_MAXDGRAMDATA + NFS_MAXPKTHDR) * 212 pktscale; 213 } else { 214 sndreserve = rcvreserve = 1024 * pktscale; 215 } 216 } else { 217 if (nrp->nr_sotype != SOCK_STREAM) 218 panic("nfscon sotype"); 219 if (nmp != NULL) { 220 sndreserve = (NFS_MAXBSIZE + NFS_MAXPKTHDR + 221 sizeof (u_int32_t)) * pktscale; 222 rcvreserve = (NFS_MAXBSIZE + NFS_MAXPKTHDR + 223 sizeof (u_int32_t)) * pktscale; 224 } else { 225 sndreserve = rcvreserve = 1024 * pktscale; 226 } 227 } 228 error = soreserve(so, sndreserve, rcvreserve); 229 } while (error != 0 && pktscale > 2); 230 soclose(so); 231 if (error) { 232 td->td_ucred = origcred; 233 return (error); 234 } 235 236 client = clnt_reconnect_create(nconf, saddr, nrp->nr_prog, 237 nrp->nr_vers, sndreserve, rcvreserve); 238 CLNT_CONTROL(client, CLSET_WAITCHAN, "newnfsreq"); 239 if (nmp != NULL) { 240 if ((nmp->nm_flag & NFSMNT_INT)) 241 CLNT_CONTROL(client, CLSET_INTERRUPTIBLE, &one); 242 if ((nmp->nm_flag & NFSMNT_RESVPORT)) 243 CLNT_CONTROL(client, CLSET_PRIVPORT, &one); 244 if (NFSHASSOFT(nmp)) 245 retries = nmp->nm_retry; 246 else 247 retries = INT_MAX; 248 } else { 249 /* 250 * Three cases: 251 * - Null RPC callback to client 252 * - Non-Null RPC callback to client, wait a little longer 253 * - upcalls to nfsuserd and gssd (clp == NULL) 254 */ 255 if (callback_retry_mult == 0) { 256 retries = NFSV4_UPCALLRETRY; 257 CLNT_CONTROL(client, CLSET_PRIVPORT, &one); 258 } else { 259 retries = NFSV4_CALLBACKRETRY * callback_retry_mult; 260 } 261 } 262 CLNT_CONTROL(client, CLSET_RETRIES, &retries); 263 264 mtx_lock(&nrp->nr_mtx); 265 if (nrp->nr_client != NULL) { 266 /* 267 * Someone else already connected. 268 */ 269 CLNT_RELEASE(client); 270 } else { 271 nrp->nr_client = client; 272 } 273 274 /* 275 * Protocols that do not require connections may be optionally left 276 * unconnected for servers that reply from a port other than NFS_PORT. 277 */ 278 if (nmp == NULL || (nmp->nm_flag & NFSMNT_NOCONN) == 0) { 279 mtx_unlock(&nrp->nr_mtx); 280 CLNT_CONTROL(client, CLSET_CONNECT, &one); 281 } else { 282 mtx_unlock(&nrp->nr_mtx); 283 } 284 285 /* Restore current thread's credentials. */ 286 td->td_ucred = origcred; 287 return (0); 288 } 289 290 /* 291 * NFS disconnect. Clean up and unlink. 292 */ 293 void 294 newnfs_disconnect(struct nfssockreq *nrp) 295 { 296 CLIENT *client; 297 298 mtx_lock(&nrp->nr_mtx); 299 if (nrp->nr_client != NULL) { 300 client = nrp->nr_client; 301 nrp->nr_client = NULL; 302 mtx_unlock(&nrp->nr_mtx); 303 #ifdef KGSSAPI 304 rpc_gss_secpurge(client); 305 #endif 306 CLNT_CLOSE(client); 307 CLNT_RELEASE(client); 308 } else { 309 mtx_unlock(&nrp->nr_mtx); 310 } 311 } 312 313 static AUTH * 314 nfs_getauth(struct nfssockreq *nrp, int secflavour, char *clnt_principal, 315 char *srv_principal, gss_OID mech_oid, struct ucred *cred) 316 { 317 #ifdef KGSSAPI 318 rpc_gss_service_t svc; 319 AUTH *auth; 320 #ifdef notyet 321 rpc_gss_options_req_t req_options; 322 #endif 323 #endif 324 325 switch (secflavour) { 326 #ifdef KGSSAPI 327 case RPCSEC_GSS_KRB5: 328 case RPCSEC_GSS_KRB5I: 329 case RPCSEC_GSS_KRB5P: 330 if (!mech_oid) { 331 if (!rpc_gss_mech_to_oid("kerberosv5", &mech_oid)) 332 return (NULL); 333 } 334 if (secflavour == RPCSEC_GSS_KRB5) 335 svc = rpc_gss_svc_none; 336 else if (secflavour == RPCSEC_GSS_KRB5I) 337 svc = rpc_gss_svc_integrity; 338 else 339 svc = rpc_gss_svc_privacy; 340 #ifdef notyet 341 req_options.req_flags = GSS_C_MUTUAL_FLAG; 342 req_options.time_req = 0; 343 req_options.my_cred = GSS_C_NO_CREDENTIAL; 344 req_options.input_channel_bindings = NULL; 345 req_options.enc_type = nfs_keytab_enctype; 346 347 auth = rpc_gss_secfind(nrp->nr_client, cred, 348 clnt_principal, srv_principal, mech_oid, svc, 349 &req_options); 350 #else 351 /* 352 * Until changes to the rpcsec_gss code are committed, 353 * there is no support for host based initiator 354 * principals. As such, that case cannot yet be handled. 355 */ 356 if (clnt_principal == NULL) 357 auth = rpc_gss_secfind(nrp->nr_client, cred, 358 srv_principal, mech_oid, svc); 359 else 360 auth = NULL; 361 #endif 362 if (auth != NULL) 363 return (auth); 364 /* fallthrough */ 365 #endif /* KGSSAPI */ 366 case AUTH_SYS: 367 default: 368 return (authunix_create(cred)); 369 370 } 371 } 372 373 /* 374 * Callback from the RPC code to generate up/down notifications. 375 */ 376 377 struct nfs_feedback_arg { 378 struct nfsmount *nf_mount; 379 int nf_lastmsg; /* last tprintf */ 380 int nf_tprintfmsg; 381 struct thread *nf_td; 382 }; 383 384 static void 385 nfs_feedback(int type, int proc, void *arg) 386 { 387 struct nfs_feedback_arg *nf = (struct nfs_feedback_arg *) arg; 388 struct nfsmount *nmp = nf->nf_mount; 389 struct timeval now; 390 391 getmicrouptime(&now); 392 393 switch (type) { 394 case FEEDBACK_REXMIT2: 395 case FEEDBACK_RECONNECT: 396 if (nf->nf_lastmsg + nmp->nm_tprintf_delay < now.tv_sec) { 397 nfs_down(nmp, nf->nf_td, 398 "not responding", 0, NFSSTA_TIMEO); 399 nf->nf_tprintfmsg = TRUE; 400 nf->nf_lastmsg = now.tv_sec; 401 } 402 break; 403 404 case FEEDBACK_OK: 405 nfs_up(nf->nf_mount, nf->nf_td, 406 "is alive again", NFSSTA_TIMEO, nf->nf_tprintfmsg); 407 break; 408 } 409 } 410 411 /* 412 * newnfs_request - goes something like this 413 * - does the rpc by calling the krpc layer 414 * - break down rpc header and return with nfs reply 415 * nb: always frees up nd_mreq mbuf list 416 */ 417 int 418 newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp, 419 struct nfsclient *clp, struct nfssockreq *nrp, vnode_t vp, 420 struct thread *td, struct ucred *cred, u_int32_t prog, u_int32_t vers, 421 u_char *retsum, int toplevel, u_int64_t *xidp) 422 { 423 u_int32_t *tl; 424 time_t waituntil; 425 int i, j, set_uid = 0, set_sigset = 0; 426 int trycnt, error = 0, usegssname = 0, secflavour = AUTH_SYS; 427 u_int16_t procnum; 428 u_int trylater_delay = 1; 429 struct nfs_feedback_arg nf; 430 struct timeval timo, now; 431 AUTH *auth; 432 struct rpc_callextra ext; 433 enum clnt_stat stat; 434 struct nfsreq *rep = NULL; 435 char *srv_principal = NULL; 436 uid_t saved_uid = (uid_t)-1; 437 sigset_t oldset; 438 439 if (xidp != NULL) 440 *xidp = 0; 441 /* Reject requests while attempting a forced unmount. */ 442 if (nmp != NULL && (nmp->nm_mountp->mnt_kern_flag & MNTK_UNMOUNTF)) { 443 m_freem(nd->nd_mreq); 444 return (ESTALE); 445 } 446 447 /* For client side interruptible mounts, mask off the signals. */ 448 if (nmp != NULL && td != NULL && NFSHASINT(nmp)) { 449 newnfs_set_sigmask(td, &oldset); 450 set_sigset = 1; 451 } 452 453 /* 454 * XXX if not already connected call nfs_connect now. Longer 455 * term, change nfs_mount to call nfs_connect unconditionally 456 * and let clnt_reconnect_create handle reconnects. 457 */ 458 if (nrp->nr_client == NULL) 459 newnfs_connect(nmp, nrp, cred, td, 0); 460 461 /* 462 * For a client side mount, nmp is != NULL and clp == NULL. For 463 * server calls (callbacks or upcalls), nmp == NULL. 464 */ 465 if (clp != NULL) { 466 NFSLOCKSTATE(); 467 if ((clp->lc_flags & LCL_GSS) && nfsrv_gsscallbackson) { 468 secflavour = RPCSEC_GSS_KRB5; 469 if (nd->nd_procnum != NFSPROC_NULL) { 470 if (clp->lc_flags & LCL_GSSINTEGRITY) 471 secflavour = RPCSEC_GSS_KRB5I; 472 else if (clp->lc_flags & LCL_GSSPRIVACY) 473 secflavour = RPCSEC_GSS_KRB5P; 474 } 475 } 476 NFSUNLOCKSTATE(); 477 } else if (nmp != NULL && NFSHASKERB(nmp) && 478 nd->nd_procnum != NFSPROC_NULL) { 479 if (NFSHASALLGSSNAME(nmp) && nmp->nm_krbnamelen > 0) 480 nd->nd_flag |= ND_USEGSSNAME; 481 if ((nd->nd_flag & ND_USEGSSNAME) != 0) { 482 /* 483 * If there is a client side host based credential, 484 * use that, otherwise use the system uid, if set. 485 */ 486 if (nmp->nm_krbnamelen > 0) { 487 usegssname = 1; 488 } else if (nmp->nm_uid != (uid_t)-1) { 489 saved_uid = cred->cr_uid; 490 cred->cr_uid = nmp->nm_uid; 491 set_uid = 1; 492 } 493 } else if (nmp->nm_krbnamelen == 0 && 494 nmp->nm_uid != (uid_t)-1 && cred->cr_uid == (uid_t)0) { 495 /* 496 * If there is no host based principal name and 497 * the system uid is set and this is root, use the 498 * system uid, since root won't have user 499 * credentials in a credentials cache file. 500 */ 501 saved_uid = cred->cr_uid; 502 cred->cr_uid = nmp->nm_uid; 503 set_uid = 1; 504 } 505 if (NFSHASINTEGRITY(nmp)) 506 secflavour = RPCSEC_GSS_KRB5I; 507 else if (NFSHASPRIVACY(nmp)) 508 secflavour = RPCSEC_GSS_KRB5P; 509 else 510 secflavour = RPCSEC_GSS_KRB5; 511 srv_principal = NFSMNT_SRVKRBNAME(nmp); 512 } 513 514 if (nmp != NULL) { 515 bzero(&nf, sizeof(struct nfs_feedback_arg)); 516 nf.nf_mount = nmp; 517 nf.nf_td = td; 518 getmicrouptime(&now); 519 nf.nf_lastmsg = now.tv_sec - 520 ((nmp->nm_tprintf_delay)-(nmp->nm_tprintf_initial_delay)); 521 } 522 523 if (nd->nd_procnum == NFSPROC_NULL) 524 auth = authnone_create(); 525 else if (usegssname) 526 auth = nfs_getauth(nrp, secflavour, nmp->nm_krbname, 527 srv_principal, NULL, cred); 528 else 529 auth = nfs_getauth(nrp, secflavour, NULL, 530 srv_principal, NULL, cred); 531 if (set_uid) 532 cred->cr_uid = saved_uid; 533 if (auth == NULL) { 534 m_freem(nd->nd_mreq); 535 if (set_sigset) 536 newnfs_restore_sigmask(td, &oldset); 537 return (EACCES); 538 } 539 bzero(&ext, sizeof(ext)); 540 ext.rc_auth = auth; 541 if (nmp != NULL) { 542 ext.rc_feedback = nfs_feedback; 543 ext.rc_feedback_arg = &nf; 544 } 545 546 procnum = nd->nd_procnum; 547 if ((nd->nd_flag & ND_NFSV4) && 548 nd->nd_procnum != NFSPROC_NULL && 549 nd->nd_procnum != NFSV4PROC_CBCOMPOUND) 550 procnum = NFSV4PROC_COMPOUND; 551 552 if (nmp != NULL) { 553 NFSINCRGLOBAL(newnfsstats.rpcrequests); 554 555 /* Map the procnum to the old NFSv2 one, as required. */ 556 if ((nd->nd_flag & ND_NFSV2) != 0) { 557 if (nd->nd_procnum < NFS_V3NPROCS) 558 procnum = nfsv2_procid[nd->nd_procnum]; 559 else 560 procnum = NFSV2PROC_NOOP; 561 } 562 563 /* 564 * Now only used for the R_DONTRECOVER case, but until that is 565 * supported within the krpc code, I need to keep a queue of 566 * outstanding RPCs for nfsv4 client requests. 567 */ 568 if ((nd->nd_flag & ND_NFSV4) && procnum == NFSV4PROC_COMPOUND) 569 MALLOC(rep, struct nfsreq *, sizeof(struct nfsreq), 570 M_NFSDREQ, M_WAITOK); 571 } 572 trycnt = 0; 573 tryagain: 574 if (nmp == NULL) { 575 timo.tv_usec = 0; 576 if (clp == NULL) 577 timo.tv_sec = NFSV4_UPCALLTIMEO; 578 else 579 timo.tv_sec = NFSV4_CALLBACKTIMEO; 580 } else { 581 if (nrp->nr_sotype != SOCK_DGRAM) { 582 timo.tv_usec = 0; 583 if ((nmp->nm_flag & NFSMNT_NFSV4)) 584 timo.tv_sec = INT_MAX; 585 else 586 timo.tv_sec = NFS_TCPTIMEO; 587 } else { 588 timo.tv_sec = nmp->nm_timeo / NFS_HZ; 589 timo.tv_usec = (nmp->nm_timeo * 1000000) / NFS_HZ; 590 } 591 592 if (rep != NULL) { 593 rep->r_flags = 0; 594 rep->r_nmp = nmp; 595 /* 596 * Chain request into list of outstanding requests. 597 */ 598 NFSLOCKREQ(); 599 TAILQ_INSERT_TAIL(&nfsd_reqq, rep, r_chain); 600 NFSUNLOCKREQ(); 601 } 602 } 603 604 nd->nd_mrep = NULL; 605 stat = CLNT_CALL_MBUF(nrp->nr_client, &ext, procnum, nd->nd_mreq, 606 &nd->nd_mrep, timo); 607 608 if (rep != NULL) { 609 /* 610 * RPC done, unlink the request. 611 */ 612 NFSLOCKREQ(); 613 TAILQ_REMOVE(&nfsd_reqq, rep, r_chain); 614 NFSUNLOCKREQ(); 615 } 616 617 /* 618 * If there was a successful reply and a tprintf msg. 619 * tprintf a response. 620 */ 621 if (stat == RPC_SUCCESS) { 622 error = 0; 623 } else if (stat == RPC_TIMEDOUT) { 624 error = ETIMEDOUT; 625 } else if (stat == RPC_VERSMISMATCH) { 626 error = EOPNOTSUPP; 627 } else if (stat == RPC_PROGVERSMISMATCH) { 628 error = EPROTONOSUPPORT; 629 } else { 630 error = EACCES; 631 } 632 if (error) { 633 m_freem(nd->nd_mreq); 634 AUTH_DESTROY(auth); 635 if (rep != NULL) 636 FREE((caddr_t)rep, M_NFSDREQ); 637 if (set_sigset) 638 newnfs_restore_sigmask(td, &oldset); 639 return (error); 640 } 641 642 KASSERT(nd->nd_mrep != NULL, ("mrep shouldn't be NULL if no error\n")); 643 644 /* 645 * Search for any mbufs that are not a multiple of 4 bytes long 646 * or with m_data not longword aligned. 647 * These could cause pointer alignment problems, so copy them to 648 * well aligned mbufs. 649 */ 650 newnfs_realign(&nd->nd_mrep); 651 nd->nd_md = nd->nd_mrep; 652 nd->nd_dpos = NFSMTOD(nd->nd_md, caddr_t); 653 nd->nd_repstat = 0; 654 if (nd->nd_procnum != NFSPROC_NULL) { 655 /* 656 * and now the actual NFS xdr. 657 */ 658 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 659 nd->nd_repstat = fxdr_unsigned(u_int32_t, *tl); 660 if (nd->nd_repstat != 0) { 661 if ((nd->nd_repstat == NFSERR_DELAY && 662 (nd->nd_flag & ND_NFSV4) && 663 nd->nd_procnum != NFSPROC_SETATTR && 664 nd->nd_procnum != NFSPROC_READ && 665 nd->nd_procnum != NFSPROC_WRITE && 666 nd->nd_procnum != NFSPROC_OPEN && 667 nd->nd_procnum != NFSPROC_CREATE && 668 nd->nd_procnum != NFSPROC_OPENCONFIRM && 669 nd->nd_procnum != NFSPROC_OPENDOWNGRADE && 670 nd->nd_procnum != NFSPROC_CLOSE && 671 nd->nd_procnum != NFSPROC_LOCK && 672 nd->nd_procnum != NFSPROC_LOCKU) || 673 (nd->nd_repstat == NFSERR_DELAY && 674 (nd->nd_flag & ND_NFSV4) == 0) || 675 nd->nd_repstat == NFSERR_RESOURCE) { 676 if (trylater_delay > NFS_TRYLATERDEL) 677 trylater_delay = NFS_TRYLATERDEL; 678 waituntil = NFSD_MONOSEC + trylater_delay; 679 while (NFSD_MONOSEC < waituntil) 680 (void) nfs_catnap(PZERO, 0, "nfstry"); 681 trylater_delay *= 2; 682 goto tryagain; 683 } 684 685 /* 686 * If the File Handle was stale, invalidate the 687 * lookup cache, just in case. 688 * (vp != NULL implies a client side call) 689 */ 690 if (nd->nd_repstat == ESTALE && vp != NULL) { 691 cache_purge(vp); 692 if (ncl_call_invalcaches != NULL) 693 (*ncl_call_invalcaches)(vp); 694 } 695 } 696 697 /* 698 * Get rid of the tag, return count, and PUTFH result for V4. 699 */ 700 if (nd->nd_flag & ND_NFSV4) { 701 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 702 i = fxdr_unsigned(int, *tl); 703 error = nfsm_advance(nd, NFSM_RNDUP(i), -1); 704 if (error) 705 goto nfsmout; 706 NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 707 i = fxdr_unsigned(int, *++tl); 708 709 /* 710 * If the first op's status is non-zero, mark that 711 * there is no more data to process. 712 */ 713 if (*++tl) 714 nd->nd_flag |= ND_NOMOREDATA; 715 716 /* 717 * If the first op is Putfh, throw its results away 718 * and toss the op# and status for the first op. 719 */ 720 if (nmp != NULL && i == NFSV4OP_PUTFH && *tl == 0) { 721 NFSM_DISSECT(tl,u_int32_t *,2 * NFSX_UNSIGNED); 722 i = fxdr_unsigned(int, *tl++); 723 j = fxdr_unsigned(int, *tl); 724 /* 725 * All Compounds that do an Op that must 726 * be in sequence consist of NFSV4OP_PUTFH 727 * followed by one of these. As such, we 728 * can determine if the seqid# should be 729 * incremented, here. 730 */ 731 if ((i == NFSV4OP_OPEN || 732 i == NFSV4OP_OPENCONFIRM || 733 i == NFSV4OP_OPENDOWNGRADE || 734 i == NFSV4OP_CLOSE || 735 i == NFSV4OP_LOCK || 736 i == NFSV4OP_LOCKU) && 737 (j == 0 || 738 (j != NFSERR_STALECLIENTID && 739 j != NFSERR_STALESTATEID && 740 j != NFSERR_BADSTATEID && 741 j != NFSERR_BADSEQID && 742 j != NFSERR_BADXDR && 743 j != NFSERR_RESOURCE && 744 j != NFSERR_NOFILEHANDLE))) 745 nd->nd_flag |= ND_INCRSEQID; 746 /* 747 * If the first op's status is non-zero, mark 748 * that there is no more data to process. 749 */ 750 if (j) 751 nd->nd_flag |= ND_NOMOREDATA; 752 } 753 754 /* 755 * If R_DONTRECOVER is set, replace the stale error 756 * reply, so that recovery isn't initiated. 757 */ 758 if ((nd->nd_repstat == NFSERR_STALECLIENTID || 759 nd->nd_repstat == NFSERR_STALESTATEID) && 760 rep != NULL && (rep->r_flags & R_DONTRECOVER)) 761 nd->nd_repstat = NFSERR_STALEDONTRECOVER; 762 } 763 } 764 765 m_freem(nd->nd_mreq); 766 AUTH_DESTROY(auth); 767 if (rep != NULL) 768 FREE((caddr_t)rep, M_NFSDREQ); 769 if (set_sigset) 770 newnfs_restore_sigmask(td, &oldset); 771 return (0); 772 nfsmout: 773 mbuf_freem(nd->nd_mrep); 774 mbuf_freem(nd->nd_mreq); 775 AUTH_DESTROY(auth); 776 if (rep != NULL) 777 FREE((caddr_t)rep, M_NFSDREQ); 778 if (set_sigset) 779 newnfs_restore_sigmask(td, &oldset); 780 return (error); 781 } 782 783 /* 784 * Mark all of an nfs mount's outstanding requests with R_SOFTTERM and 785 * wait for all requests to complete. This is used by forced unmounts 786 * to terminate any outstanding RPCs. 787 */ 788 int 789 newnfs_nmcancelreqs(struct nfsmount *nmp) 790 { 791 792 if (nmp->nm_sockreq.nr_client != NULL) 793 CLNT_CLOSE(nmp->nm_sockreq.nr_client); 794 return (0); 795 } 796 797 /* 798 * Any signal that can interrupt an NFS operation in an intr mount 799 * should be added to this set. SIGSTOP and SIGKILL cannot be masked. 800 */ 801 int newnfs_sig_set[] = { 802 SIGINT, 803 SIGTERM, 804 SIGHUP, 805 SIGKILL, 806 SIGSTOP, 807 SIGQUIT 808 }; 809 810 /* 811 * Check to see if one of the signals in our subset is pending on 812 * the process (in an intr mount). 813 */ 814 static int 815 nfs_sig_pending(sigset_t set) 816 { 817 int i; 818 819 for (i = 0 ; i < sizeof(newnfs_sig_set)/sizeof(int) ; i++) 820 if (SIGISMEMBER(set, newnfs_sig_set[i])) 821 return (1); 822 return (0); 823 } 824 825 /* 826 * The set/restore sigmask functions are used to (temporarily) overwrite 827 * the process p_sigmask during an RPC call (for example). These are also 828 * used in other places in the NFS client that might tsleep(). 829 */ 830 void 831 newnfs_set_sigmask(struct thread *td, sigset_t *oldset) 832 { 833 sigset_t newset; 834 int i; 835 struct proc *p; 836 837 SIGFILLSET(newset); 838 if (td == NULL) 839 td = curthread; /* XXX */ 840 p = td->td_proc; 841 /* Remove the NFS set of signals from newset */ 842 PROC_LOCK(p); 843 mtx_lock(&p->p_sigacts->ps_mtx); 844 for (i = 0 ; i < sizeof(newnfs_sig_set)/sizeof(int) ; i++) { 845 /* 846 * But make sure we leave the ones already masked 847 * by the process, ie. remove the signal from the 848 * temporary signalmask only if it wasn't already 849 * in p_sigmask. 850 */ 851 if (!SIGISMEMBER(td->td_sigmask, newnfs_sig_set[i]) && 852 !SIGISMEMBER(p->p_sigacts->ps_sigignore, newnfs_sig_set[i])) 853 SIGDELSET(newset, newnfs_sig_set[i]); 854 } 855 mtx_unlock(&p->p_sigacts->ps_mtx); 856 PROC_UNLOCK(p); 857 kern_sigprocmask(td, SIG_SETMASK, &newset, oldset, 0); 858 } 859 860 void 861 newnfs_restore_sigmask(struct thread *td, sigset_t *set) 862 { 863 if (td == NULL) 864 td = curthread; /* XXX */ 865 kern_sigprocmask(td, SIG_SETMASK, set, NULL, 0); 866 } 867 868 /* 869 * NFS wrapper to msleep(), that shoves a new p_sigmask and restores the 870 * old one after msleep() returns. 871 */ 872 int 873 newnfs_msleep(struct thread *td, void *ident, struct mtx *mtx, int priority, char *wmesg, int timo) 874 { 875 sigset_t oldset; 876 int error; 877 struct proc *p; 878 879 if ((priority & PCATCH) == 0) 880 return msleep(ident, mtx, priority, wmesg, timo); 881 if (td == NULL) 882 td = curthread; /* XXX */ 883 newnfs_set_sigmask(td, &oldset); 884 error = msleep(ident, mtx, priority, wmesg, timo); 885 newnfs_restore_sigmask(td, &oldset); 886 p = td->td_proc; 887 return (error); 888 } 889 890 /* 891 * Test for a termination condition pending on the process. 892 * This is used for NFSMNT_INT mounts. 893 */ 894 int 895 newnfs_sigintr(struct nfsmount *nmp, struct thread *td) 896 { 897 struct proc *p; 898 sigset_t tmpset; 899 900 /* Terminate all requests while attempting a forced unmount. */ 901 if (nmp->nm_mountp->mnt_kern_flag & MNTK_UNMOUNTF) 902 return (EIO); 903 if (!(nmp->nm_flag & NFSMNT_INT)) 904 return (0); 905 if (td == NULL) 906 return (0); 907 p = td->td_proc; 908 PROC_LOCK(p); 909 tmpset = p->p_siglist; 910 SIGSETOR(tmpset, td->td_siglist); 911 SIGSETNAND(tmpset, td->td_sigmask); 912 mtx_lock(&p->p_sigacts->ps_mtx); 913 SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore); 914 mtx_unlock(&p->p_sigacts->ps_mtx); 915 if ((SIGNOTEMPTY(p->p_siglist) || SIGNOTEMPTY(td->td_siglist)) 916 && nfs_sig_pending(tmpset)) { 917 PROC_UNLOCK(p); 918 return (EINTR); 919 } 920 PROC_UNLOCK(p); 921 return (0); 922 } 923 924 static int 925 nfs_msg(struct thread *td, const char *server, const char *msg, int error) 926 { 927 struct proc *p; 928 929 p = td ? td->td_proc : NULL; 930 if (error) { 931 tprintf(p, LOG_INFO, "newnfs server %s: %s, error %d\n", 932 server, msg, error); 933 } else { 934 tprintf(p, LOG_INFO, "newnfs server %s: %s\n", server, msg); 935 } 936 return (0); 937 } 938 939 static void 940 nfs_down(struct nfsmount *nmp, struct thread *td, const char *msg, 941 int error, int flags) 942 { 943 if (nmp == NULL) 944 return; 945 mtx_lock(&nmp->nm_mtx); 946 if ((flags & NFSSTA_TIMEO) && !(nmp->nm_state & NFSSTA_TIMEO)) { 947 nmp->nm_state |= NFSSTA_TIMEO; 948 mtx_unlock(&nmp->nm_mtx); 949 vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid, 950 VQ_NOTRESP, 0); 951 } else 952 mtx_unlock(&nmp->nm_mtx); 953 mtx_lock(&nmp->nm_mtx); 954 if ((flags & NFSSTA_LOCKTIMEO) && !(nmp->nm_state & NFSSTA_LOCKTIMEO)) { 955 nmp->nm_state |= NFSSTA_LOCKTIMEO; 956 mtx_unlock(&nmp->nm_mtx); 957 vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid, 958 VQ_NOTRESPLOCK, 0); 959 } else 960 mtx_unlock(&nmp->nm_mtx); 961 nfs_msg(td, nmp->nm_mountp->mnt_stat.f_mntfromname, msg, error); 962 } 963 964 static void 965 nfs_up(struct nfsmount *nmp, struct thread *td, const char *msg, 966 int flags, int tprintfmsg) 967 { 968 if (nmp == NULL) 969 return; 970 if (tprintfmsg) { 971 nfs_msg(td, nmp->nm_mountp->mnt_stat.f_mntfromname, msg, 0); 972 } 973 974 mtx_lock(&nmp->nm_mtx); 975 if ((flags & NFSSTA_TIMEO) && (nmp->nm_state & NFSSTA_TIMEO)) { 976 nmp->nm_state &= ~NFSSTA_TIMEO; 977 mtx_unlock(&nmp->nm_mtx); 978 vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid, 979 VQ_NOTRESP, 1); 980 } else 981 mtx_unlock(&nmp->nm_mtx); 982 983 mtx_lock(&nmp->nm_mtx); 984 if ((flags & NFSSTA_LOCKTIMEO) && (nmp->nm_state & NFSSTA_LOCKTIMEO)) { 985 nmp->nm_state &= ~NFSSTA_LOCKTIMEO; 986 mtx_unlock(&nmp->nm_mtx); 987 vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid, 988 VQ_NOTRESPLOCK, 1); 989 } else 990 mtx_unlock(&nmp->nm_mtx); 991 } 992 993