1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ 5 * Authors: Doug Rabson <dfr@rabson.org> 6 * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org> 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 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/limits.h> 34 #include <sys/lock.h> 35 #include <sys/malloc.h> 36 #include <sys/mbuf.h> 37 #include <sys/mutex.h> 38 #include <sys/pcpu.h> 39 #include <sys/proc.h> 40 #include <sys/socket.h> 41 #include <sys/socketvar.h> 42 #include <sys/time.h> 43 #include <sys/uio.h> 44 45 #include <netinet/tcp.h> 46 47 #include <rpc/rpc.h> 48 #include <rpc/rpc_com.h> 49 #include <rpc/krpc.h> 50 #include <rpc/rpcsec_tls.h> 51 52 xprt_rdma_check_route_ftype *rdma_check_route = NULL; 53 clnt_rdma_create_ftype *clnt_rdma_create_call = NULL; 54 svc_rdma_create_backchannel_ftype *svc_rdma_create_backchannel_call = NULL; 55 56 static enum clnt_stat clnt_reconnect_call(CLIENT *, struct rpc_callextra *, 57 rpcproc_t, struct mbuf *, struct mbuf **, struct timeval); 58 static void clnt_reconnect_geterr(CLIENT *, struct rpc_err *); 59 static bool_t clnt_reconnect_freeres(CLIENT *, xdrproc_t, void *); 60 static void clnt_reconnect_abort(CLIENT *); 61 static bool_t clnt_reconnect_control(CLIENT *, u_int, void *); 62 static void clnt_reconnect_close(CLIENT *); 63 static void clnt_reconnect_destroy(CLIENT *); 64 65 static const struct clnt_ops clnt_reconnect_ops = { 66 .cl_call = clnt_reconnect_call, 67 .cl_abort = clnt_reconnect_abort, 68 .cl_geterr = clnt_reconnect_geterr, 69 .cl_freeres = clnt_reconnect_freeres, 70 .cl_close = clnt_reconnect_close, 71 .cl_destroy = clnt_reconnect_destroy, 72 .cl_control = clnt_reconnect_control 73 }; 74 75 static int fake_wchan; 76 77 CLIENT * 78 clnt_reconnect_create( 79 struct netconfig *nconf, /* network type */ 80 struct sockaddr *svcaddr, /* servers address */ 81 rpcprog_t program, /* program number */ 82 rpcvers_t version, /* version number */ 83 size_t sendsz, /* buffer recv size */ 84 size_t recvsz) /* buffer send size */ 85 { 86 CLIENT *cl = NULL; /* client handle */ 87 struct rc_data *rc = NULL; /* private data */ 88 89 if (svcaddr == NULL) { 90 rpc_createerr.cf_stat = RPC_UNKNOWNADDR; 91 return (NULL); 92 } 93 94 cl = mem_alloc(sizeof (CLIENT)); 95 rc = mem_alloc(sizeof (*rc)); 96 mtx_init(&rc->rc_lock, "rc->rc_lock", NULL, MTX_DEF); 97 (void) memcpy(&rc->rc_addr, svcaddr, (size_t)svcaddr->sa_len); 98 rc->rc_nconf = nconf; 99 rc->rc_prog = program; 100 rc->rc_vers = version; 101 rc->rc_sendsz = sendsz; 102 rc->rc_recvsz = recvsz; 103 rc->rc_timeout.tv_sec = -1; 104 rc->rc_timeout.tv_usec = -1; 105 rc->rc_retry.tv_sec = 3; 106 rc->rc_retry.tv_usec = 0; 107 rc->rc_retries = INT_MAX; 108 rc->rc_privport = FALSE; 109 rc->rc_waitchan = "rpcrecv"; 110 rc->rc_intr = 0; 111 rc->rc_connecting = FALSE; 112 rc->rc_closed = FALSE; 113 rc->rc_ucred = crdup(curthread->td_ucred); 114 rc->rc_client = NULL; 115 rc->rc_tls = false; 116 rc->rc_tlscertname = NULL; 117 rc->rc_reconcall = NULL; 118 rc->rc_reconarg = NULL; 119 120 cl->cl_refs = 1; 121 cl->cl_ops = &clnt_reconnect_ops; 122 cl->cl_private = (caddr_t)(void *)rc; 123 cl->cl_auth = authnone_create(); 124 cl->cl_tp = NULL; 125 cl->cl_netid = NULL; 126 return (cl); 127 } 128 129 static enum clnt_stat 130 clnt_reconnect_connect(CLIENT *cl) 131 { 132 struct thread *td = curthread; 133 struct rc_data *rc = (struct rc_data *)cl->cl_private; 134 struct socket *so; 135 enum clnt_stat stat; 136 int error; 137 int one = 1; 138 struct ucred *oldcred; 139 CLIENT *newclient = NULL; 140 uint32_t reterr; 141 bool dordma; 142 143 dordma = false; 144 mtx_lock(&rc->rc_lock); 145 while (rc->rc_connecting) { 146 error = msleep(rc, &rc->rc_lock, 147 rc->rc_intr ? PCATCH : 0, "rpcrecon", 0); 148 if (error) { 149 mtx_unlock(&rc->rc_lock); 150 return (RPC_INTR); 151 } 152 } 153 if (rc->rc_closed) { 154 mtx_unlock(&rc->rc_lock); 155 return (RPC_CANTSEND); 156 } 157 if (rc->rc_client) { 158 mtx_unlock(&rc->rc_lock); 159 return (RPC_SUCCESS); 160 } 161 162 /* 163 * My turn to attempt a connect. The rc_connecting variable 164 * serializes the following code sequence, so it is guaranteed 165 * that rc_client will still be NULL after it is re-locked below, 166 * since that is the only place it is set non-NULL. 167 */ 168 rc->rc_connecting = TRUE; 169 mtx_unlock(&rc->rc_lock); 170 171 oldcred = td->td_ucred; 172 td->td_ucred = rc->rc_ucred; 173 174 /* Handle RDMA. */ 175 if (strcmp("rdma", rc->rc_nconf->nc_netid) == 0 || 176 strcmp("rdma6", rc->rc_nconf->nc_netid) == 0) 177 dordma = true; 178 if (dordma) { 179 if (clnt_rdma_create_call != NULL) { 180 /* Set up the QP. */ 181 stat = RPC_SUCCESS; 182 newclient = clnt_rdma_create_call( 183 (struct sockaddr *)&rc->rc_addr, rc->rc_prog, 184 rc->rc_vers, rc->rc_intr, rc->rc_rdmasmall_reply, 185 rc->rc_rdmamax_io, rc->rc_rdma_cbslots, 186 &rc->rc_err); 187 } else { 188 rc->rc_err.re_status = stat = RPC_FAILED; 189 newclient = NULL; 190 } 191 } else { 192 so = __rpc_nconf2socket(rc->rc_nconf); 193 if (!so) { 194 stat = rpc_createerr.cf_stat = RPC_TLIERROR; 195 rpc_createerr.cf_error.re_errno = 0; 196 td->td_ucred = oldcred; 197 goto out; 198 } 199 200 if (rc->rc_privport) 201 bindresvport(so, NULL); 202 203 if (rc->rc_nconf->nc_semantics == NC_TPI_CLTS) 204 newclient = clnt_dg_create(so, 205 (struct sockaddr *) &rc->rc_addr, rc->rc_prog, 206 rc->rc_vers, rc->rc_sendsz, rc->rc_recvsz); 207 else { 208 /* 209 * I do not believe a timeout of less than 1sec would 210 * make sense here since short delays can occur when a 211 * server is temporarily overloaded. 212 */ 213 if (rc->rc_timeout.tv_sec > 0 && 214 rc->rc_timeout.tv_usec >= 0) { 215 error = so_setsockopt(so, SOL_SOCKET, 216 SO_SNDTIMEO, &rc->rc_timeout, 217 sizeof(struct timeval)); 218 if (error != 0) { 219 stat = rpc_createerr.cf_stat = 220 RPC_CANTSEND; 221 rpc_createerr.cf_error.re_errno = error; 222 td->td_ucred = oldcred; 223 goto out; 224 } 225 } 226 newclient = clnt_vc_create(so, 227 (struct sockaddr *) &rc->rc_addr, rc->rc_prog, 228 rc->rc_vers, rc->rc_sendsz, rc->rc_recvsz, 229 rc->rc_intr); 230 /* 231 * CLSET_FD_CLOSE must be done now, in case 232 * rpctls_connect() fails just below. 233 */ 234 if (newclient != NULL) 235 CLNT_CONTROL(newclient, CLSET_FD_CLOSE, 0); 236 if (rc->rc_tls && newclient != NULL) { 237 CURVNET_SET(so->so_vnet); 238 stat = rpctls_connect(newclient, 239 rc->rc_tlscertname, so, &reterr); 240 CURVNET_RESTORE(); 241 if (stat != RPC_SUCCESS || 242 reterr != RPCTLSERR_OK) { 243 if (stat == RPC_SUCCESS) 244 stat = RPC_FAILED; 245 stat = rpc_createerr.cf_stat = stat; 246 rpc_createerr.cf_error.re_errno = 0; 247 CLNT_CLOSE(newclient); 248 CLNT_RELEASE(newclient); 249 newclient = NULL; 250 td->td_ucred = oldcred; 251 goto out; 252 } 253 CLNT_CONTROL(newclient, CLSET_TLS, 254 &(int){RPCTLS_COMPLETE}); 255 } 256 if (newclient != NULL) { 257 int optval = 1; 258 259 (void)so_setsockopt(so, IPPROTO_TCP, 260 TCP_USE_DDP, &optval, sizeof(optval)); 261 } 262 } 263 } 264 if (newclient != NULL && rc->rc_reconcall != NULL) 265 (*rc->rc_reconcall)(newclient, rc->rc_reconarg, 266 rc->rc_ucred); 267 td->td_ucred = oldcred; 268 269 if (!newclient) { 270 if (!dordma) { 271 soclose(so); 272 rc->rc_err = rpc_createerr.cf_error; 273 stat = rpc_createerr.cf_stat; 274 } else { 275 stat = rc->rc_err.re_status; 276 } 277 goto out; 278 } 279 280 CLNT_CONTROL(newclient, CLSET_CONNECT, &one); 281 CLNT_CONTROL(newclient, CLSET_TIMEOUT, &rc->rc_timeout); 282 CLNT_CONTROL(newclient, CLSET_RETRY_TIMEOUT, &rc->rc_retry); 283 CLNT_CONTROL(newclient, CLSET_WAITCHAN, rc->rc_waitchan); 284 CLNT_CONTROL(newclient, CLSET_INTERRUPTIBLE, &rc->rc_intr); 285 if (rc->rc_backchannel != NULL) 286 CLNT_CONTROL(newclient, CLSET_BACKCHANNEL, rc->rc_backchannel); 287 stat = RPC_SUCCESS; 288 289 out: 290 mtx_lock(&rc->rc_lock); 291 KASSERT(rc->rc_client == NULL, ("rc_client not null")); 292 if (!rc->rc_closed) { 293 rc->rc_client = newclient; 294 newclient = NULL; 295 } 296 rc->rc_connecting = FALSE; 297 wakeup(rc); 298 mtx_unlock(&rc->rc_lock); 299 300 if (newclient) { 301 /* 302 * It has been closed, so discard the new client. 303 * nb: clnt_[dg|vc]_close()/clnt_[dg|vc]_destroy() cannot 304 * be called with the rc_lock mutex held, since they may 305 * msleep() while holding a different mutex. 306 */ 307 CLNT_CLOSE(newclient); 308 CLNT_RELEASE(newclient); 309 } 310 311 return (stat); 312 } 313 314 static enum clnt_stat 315 clnt_reconnect_call( 316 CLIENT *cl, /* client handle */ 317 struct rpc_callextra *ext, /* call metadata */ 318 rpcproc_t proc, /* procedure number */ 319 struct mbuf *args, /* pointer to args */ 320 struct mbuf **resultsp, /* pointer to results */ 321 struct timeval utimeout) 322 { 323 struct rc_data *rc = (struct rc_data *)cl->cl_private; 324 CLIENT *client; 325 enum clnt_stat stat; 326 int tries, error; 327 328 tries = 0; 329 do { 330 mtx_lock(&rc->rc_lock); 331 if (rc->rc_closed) { 332 mtx_unlock(&rc->rc_lock); 333 return (RPC_CANTSEND); 334 } 335 336 if (!rc->rc_client) { 337 mtx_unlock(&rc->rc_lock); 338 stat = clnt_reconnect_connect(cl); 339 if (stat == RPC_SYSTEMERROR) { 340 error = tsleep(&fake_wchan, 341 rc->rc_intr ? PCATCH : 0, "rpccon", hz); 342 if (error == EINTR || error == ERESTART) 343 return (RPC_INTR); 344 tries++; 345 if (tries >= rc->rc_retries) 346 return (stat); 347 continue; 348 } 349 if (stat != RPC_SUCCESS) 350 return (stat); 351 mtx_lock(&rc->rc_lock); 352 } 353 354 if (!rc->rc_client) { 355 mtx_unlock(&rc->rc_lock); 356 stat = RPC_FAILED; 357 continue; 358 } 359 CLNT_ACQUIRE(rc->rc_client); 360 client = rc->rc_client; 361 mtx_unlock(&rc->rc_lock); 362 stat = CLNT_CALL_MBUF(client, ext, proc, args, 363 resultsp, utimeout); 364 365 if (stat != RPC_SUCCESS) { 366 if (!ext) 367 CLNT_GETERR(client, &rc->rc_err); 368 } 369 370 if (stat == RPC_TIMEDOUT) { 371 /* 372 * Check for async send misfeature for NLM 373 * protocol. 374 */ 375 if ((rc->rc_timeout.tv_sec == 0 376 && rc->rc_timeout.tv_usec == 0) 377 || (rc->rc_timeout.tv_sec == -1 378 && utimeout.tv_sec == 0 379 && utimeout.tv_usec == 0)) { 380 CLNT_RELEASE(client); 381 break; 382 } 383 } 384 385 if (stat == RPC_TIMEDOUT || stat == RPC_CANTSEND 386 || stat == RPC_CANTRECV) { 387 tries++; 388 if (tries >= rc->rc_retries) { 389 CLNT_RELEASE(client); 390 break; 391 } 392 393 if (ext && ext->rc_feedback) 394 ext->rc_feedback(FEEDBACK_RECONNECT, proc, 395 ext->rc_feedback_arg); 396 397 mtx_lock(&rc->rc_lock); 398 /* 399 * Make sure that someone else hasn't already 400 * reconnected by checking if rc_client has changed. 401 * If not, we are done with the client and must 402 * do CLNT_RELEASE(client) twice to dispose of it, 403 * because there is both an initial refcnt and one 404 * acquired by CLNT_ACQUIRE() above. 405 */ 406 if (rc->rc_client == client) { 407 rc->rc_client = NULL; 408 mtx_unlock(&rc->rc_lock); 409 CLNT_RELEASE(client); 410 } else { 411 mtx_unlock(&rc->rc_lock); 412 } 413 CLNT_RELEASE(client); 414 } else { 415 CLNT_RELEASE(client); 416 break; 417 } 418 } while (stat != RPC_SUCCESS); 419 420 KASSERT(stat != RPC_SUCCESS || *resultsp, 421 ("RPC_SUCCESS without reply")); 422 423 return (stat); 424 } 425 426 static void 427 clnt_reconnect_geterr(CLIENT *cl, struct rpc_err *errp) 428 { 429 struct rc_data *rc = (struct rc_data *)cl->cl_private; 430 431 *errp = rc->rc_err; 432 } 433 434 /* 435 * Since this function requires that rc_client be valid, it can 436 * only be called when that is guaranteed to be the case. 437 */ 438 static bool_t 439 clnt_reconnect_freeres(CLIENT *cl, xdrproc_t xdr_res, void *res_ptr) 440 { 441 struct rc_data *rc = (struct rc_data *)cl->cl_private; 442 443 return (CLNT_FREERES(rc->rc_client, xdr_res, res_ptr)); 444 } 445 446 /*ARGSUSED*/ 447 static void 448 clnt_reconnect_abort(CLIENT *h) 449 { 450 } 451 452 /* 453 * CLNT_CONTROL() on the client returned by clnt_reconnect_create() must 454 * always be called before CLNT_CALL_MBUF() by a single thread only. 455 */ 456 static bool_t 457 clnt_reconnect_control(CLIENT *cl, u_int request, void *info) 458 { 459 struct rc_data *rc = (struct rc_data *)cl->cl_private; 460 SVCXPRT *xprt; 461 size_t slen; 462 struct rpc_reconupcall *upcp; 463 464 if (info == NULL) { 465 return (FALSE); 466 } 467 switch (request) { 468 case CLSET_TIMEOUT: 469 rc->rc_timeout = *(struct timeval *)info; 470 if (rc->rc_client) 471 CLNT_CONTROL(rc->rc_client, request, info); 472 break; 473 474 case CLGET_TIMEOUT: 475 *(struct timeval *)info = rc->rc_timeout; 476 break; 477 478 case CLSET_RETRY_TIMEOUT: 479 rc->rc_retry = *(struct timeval *)info; 480 if (rc->rc_client) 481 CLNT_CONTROL(rc->rc_client, request, info); 482 break; 483 484 case CLGET_RETRY_TIMEOUT: 485 *(struct timeval *)info = rc->rc_retry; 486 break; 487 488 case CLGET_VERS: 489 *(uint32_t *)info = rc->rc_vers; 490 break; 491 492 case CLSET_VERS: 493 rc->rc_vers = *(uint32_t *) info; 494 if (rc->rc_client) 495 CLNT_CONTROL(rc->rc_client, CLSET_VERS, info); 496 break; 497 498 case CLGET_PROG: 499 *(uint32_t *)info = rc->rc_prog; 500 break; 501 502 case CLSET_PROG: 503 rc->rc_prog = *(uint32_t *) info; 504 if (rc->rc_client) 505 CLNT_CONTROL(rc->rc_client, request, info); 506 break; 507 508 case CLSET_WAITCHAN: 509 rc->rc_waitchan = (char *)info; 510 if (rc->rc_client) 511 CLNT_CONTROL(rc->rc_client, request, info); 512 break; 513 514 case CLGET_WAITCHAN: 515 *(const char **) info = rc->rc_waitchan; 516 break; 517 518 case CLSET_INTERRUPTIBLE: 519 rc->rc_intr = *(int *) info; 520 if (rc->rc_client) 521 CLNT_CONTROL(rc->rc_client, request, info); 522 break; 523 524 case CLGET_INTERRUPTIBLE: 525 *(int *) info = rc->rc_intr; 526 break; 527 528 case CLSET_RETRIES: 529 rc->rc_retries = *(int *) info; 530 break; 531 532 case CLGET_RETRIES: 533 *(int *) info = rc->rc_retries; 534 break; 535 536 case CLSET_PRIVPORT: 537 rc->rc_privport = *(int *) info; 538 break; 539 540 case CLGET_PRIVPORT: 541 *(int *) info = rc->rc_privport; 542 break; 543 544 case CLSET_BACKCHANNEL: 545 xprt = (SVCXPRT *)info; 546 xprt_register(xprt); 547 rc->rc_backchannel = info; 548 break; 549 550 case CLSET_TLS: 551 rc->rc_tls = true; 552 break; 553 554 case CLSET_TLSCERTNAME: 555 slen = strlen(info) + 1; 556 /* 557 * tlscertname with "key.pem" appended to it forms a file 558 * name. As such, the maximum allowable strlen(info) is 559 * NAME_MAX - 7. However, "slen" includes the nul termination 560 * byte so it can be up to NAME_MAX - 6. 561 */ 562 if (slen <= 1 || slen > NAME_MAX - 6) 563 return (FALSE); 564 rc->rc_tlscertname = mem_alloc(slen); 565 strlcpy(rc->rc_tlscertname, info, slen); 566 break; 567 568 case CLSET_RECONUPCALL: 569 upcp = (struct rpc_reconupcall *)info; 570 rc->rc_reconcall = upcp->call; 571 rc->rc_reconarg = upcp->arg; 572 break; 573 574 case CLSET_RDMASMALL_REPLY: 575 rc->rc_rdmasmall_reply = *(int *)info; 576 break; 577 578 case CLSET_RDMA_CBSLOTS: 579 rc->rc_rdma_cbslots = *(int *)info; 580 break; 581 582 583 case CLSET_RDMAMAX_IO: 584 rc->rc_rdmamax_io = *(int *)info; 585 if (rc->rc_client) 586 CLNT_CONTROL(rc->rc_client, request, info); 587 break; 588 589 case CLGET_RDMAMAX_IO: 590 if (rc->rc_client) 591 CLNT_CONTROL(rc->rc_client, request, info); 592 break; 593 594 default: 595 return (FALSE); 596 } 597 598 return (TRUE); 599 } 600 601 static void 602 clnt_reconnect_close(CLIENT *cl) 603 { 604 struct rc_data *rc = (struct rc_data *)cl->cl_private; 605 CLIENT *client; 606 607 mtx_lock(&rc->rc_lock); 608 609 if (rc->rc_closed) { 610 mtx_unlock(&rc->rc_lock); 611 return; 612 } 613 614 rc->rc_closed = TRUE; 615 client = rc->rc_client; 616 rc->rc_client = NULL; 617 618 mtx_unlock(&rc->rc_lock); 619 620 if (client) { 621 CLNT_CLOSE(client); 622 CLNT_RELEASE(client); 623 } 624 } 625 626 static void 627 clnt_reconnect_destroy(CLIENT *cl) 628 { 629 struct rc_data *rc = (struct rc_data *)cl->cl_private; 630 SVCXPRT *xprt; 631 632 if (rc->rc_client) 633 CLNT_DESTROY(rc->rc_client); 634 if (rc->rc_backchannel) { 635 xprt = (SVCXPRT *)rc->rc_backchannel; 636 KASSERT(xprt->xp_socket == NULL, 637 ("clnt_reconnect_destroy: xp_socket not NULL")); 638 xprt_unregister(xprt); 639 SVC_RELEASE(xprt); 640 } 641 crfree(rc->rc_ucred); 642 mtx_destroy(&rc->rc_lock); 643 mem_free(rc->rc_tlscertname, 0); /* 0 ok, since arg. ignored. */ 644 mem_free(rc->rc_reconarg, 0); 645 mem_free(rc, sizeof(*rc)); 646 mem_free(cl, sizeof (CLIENT)); 647 } 648