1 /* $NetBSD: clnt_vc.c,v 1.4 2000/07/14 08:40:42 fvdl Exp $ */ 2 3 /*- 4 * Copyright (c) 2009, Sun Microsystems, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * - Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * - Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * - Neither the name of Sun Microsystems, Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 /* 33 * clnt_tcp.c, Implements a TCP/IP based, client side RPC. 34 * 35 * Copyright (C) 1984, Sun Microsystems, Inc. 36 * 37 * TCP based RPC supports 'batched calls'. 38 * A sequence of calls may be batched-up in a send buffer. The rpc call 39 * return immediately to the client even though the call was not necessarily 40 * sent. The batching occurs if the results' xdr routine is NULL (0) AND 41 * the rpc timeout value is zero (see clnt.h, rpc). 42 * 43 * Clients should NOT casually batch calls that in fact return results; that is, 44 * the server side should be aware that a call is batched and not produce any 45 * return message. Batched calls that produce many result messages can 46 * deadlock (netlock) the client and the server.... 47 * 48 * Now go hang yourself. 49 */ 50 51 /* 52 * This code handles the special case of a NFSv4.n backchannel for 53 * callback RPCs. It is similar to clnt_vc.c, but uses the TCP 54 * connection provided by the client to the server. 55 */ 56 57 #include "opt_kern_tls.h" 58 59 #include <sys/param.h> 60 #include <sys/systm.h> 61 #include <sys/jail.h> 62 #include <sys/ktls.h> 63 #include <sys/lock.h> 64 #include <sys/malloc.h> 65 #include <sys/mbuf.h> 66 #include <sys/mutex.h> 67 #include <sys/pcpu.h> 68 #include <sys/proc.h> 69 #include <sys/protosw.h> 70 #include <sys/socket.h> 71 #include <sys/socketvar.h> 72 #include <sys/sx.h> 73 #include <sys/syslog.h> 74 #include <sys/time.h> 75 #include <sys/uio.h> 76 77 #include <net/vnet.h> 78 79 #include <netinet/tcp.h> 80 81 #include <rpc/rpc.h> 82 #include <rpc/rpc_com.h> 83 #include <rpc/krpc.h> 84 #include <rpc/rpcsec_tls.h> 85 86 /* The RDMA module will set this function pointer non-NULL. */ 87 clnt_bck_rdma_send_ftype *clnt_bck_rdma_send = NULL; 88 89 struct cmessage { 90 struct cmsghdr cmsg; 91 struct cmsgcred cmcred; 92 }; 93 94 static void clnt_bck_geterr(CLIENT *, struct rpc_err *); 95 static bool_t clnt_bck_freeres(CLIENT *, xdrproc_t, void *); 96 static void clnt_bck_abort(CLIENT *); 97 static bool_t clnt_bck_control(CLIENT *, u_int, void *); 98 static void clnt_bck_close(CLIENT *); 99 static void clnt_bck_destroy(CLIENT *); 100 101 static const struct clnt_ops clnt_bck_ops = { 102 .cl_abort = clnt_bck_abort, 103 .cl_geterr = clnt_bck_geterr, 104 .cl_freeres = clnt_bck_freeres, 105 .cl_close = clnt_bck_close, 106 .cl_destroy = clnt_bck_destroy, 107 .cl_control = clnt_bck_control 108 }; 109 110 /* 111 * Create a client handle for a connection. 112 * Default options are set, which the user can change using clnt_control()'s. 113 * This code handles the special case of an NFSv4.1 session backchannel 114 * call, which is sent on a TCP connection created against the server 115 * by a client. 116 */ 117 void * 118 clnt_bck_create( 119 struct socket *so, /* Server transport socket. */ 120 const rpcprog_t prog, /* program number */ 121 const rpcvers_t vers) /* version number */ 122 { 123 CLIENT *cl; /* client handle */ 124 struct ct_data *ct = NULL; /* client handle */ 125 struct timeval now; 126 struct rpc_msg call_msg; 127 static uint32_t disrupt; 128 XDR xdrs; 129 130 if (disrupt == 0) 131 disrupt = (uint32_t)(long)so; 132 133 cl = (CLIENT *)mem_alloc(sizeof (*cl)); 134 ct = (struct ct_data *)mem_alloc(sizeof (*ct)); 135 136 mtx_init(&ct->ct_lock, "ct->ct_lock", NULL, MTX_DEF); 137 ct->ct_threads = 0; 138 ct->ct_closing = FALSE; 139 ct->ct_closed = FALSE; 140 ct->ct_upcallrefs = 0; 141 ct->ct_closeit = FALSE; 142 143 /* 144 * Set up private data struct 145 */ 146 ct->ct_wait.tv_sec = -1; 147 ct->ct_wait.tv_usec = -1; 148 149 /* 150 * Initialize call message 151 */ 152 getmicrotime(&now); 153 ct->ct_xid = ((uint32_t)++disrupt) ^ __RPC_GETXID(&now); 154 call_msg.rm_xid = ct->ct_xid; 155 call_msg.rm_direction = CALL; 156 call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; 157 call_msg.rm_call.cb_prog = (uint32_t)prog; 158 call_msg.rm_call.cb_vers = (uint32_t)vers; 159 160 /* 161 * pre-serialize the static part of the call msg and stash it away 162 */ 163 xdrmem_create(&xdrs, ct->ct_mcallc, MCALL_MSG_SIZE, 164 XDR_ENCODE); 165 if (!xdr_callhdr(&xdrs, &call_msg)) 166 goto err; 167 ct->ct_mpos = XDR_GETPOS(&xdrs); 168 XDR_DESTROY(&xdrs); 169 ct->ct_waitchan = "rpcbck"; 170 ct->ct_waitflag = 0; 171 cl->cl_refs = 1; 172 cl->cl_ops = &clnt_bck_ops; 173 cl->cl_private = ct; 174 cl->cl_auth = authnone_create(); 175 TAILQ_INIT(&ct->ct_pending); 176 return (cl); 177 178 err: 179 mtx_destroy(&ct->ct_lock); 180 mem_free(ct, sizeof (struct ct_data)); 181 mem_free(cl, sizeof (CLIENT)); 182 return (NULL); 183 } 184 185 enum clnt_stat 186 clnt_bck_call( 187 CLIENT *cl, /* client handle */ 188 struct rpc_callextra *ext, /* call metadata */ 189 rpcproc_t proc, /* procedure number */ 190 struct mbuf *args, /* pointer to args */ 191 struct mbuf **resultsp, /* pointer to results */ 192 struct timeval utimeout, 193 SVCXPRT *xprt) 194 { 195 struct ct_data *ct = (struct ct_data *) cl->cl_private; 196 AUTH *auth; 197 struct rpc_err *errp; 198 enum clnt_stat stat; 199 XDR xdrs; 200 struct rpc_msg reply_msg; 201 bool_t ok; 202 int nrefreshes = 2; /* number of times to refresh cred */ 203 struct timeval timeout; 204 uint32_t xid; 205 struct mbuf *mreq = NULL, *results; 206 struct ct_request *cr; 207 int error, maxextsiz; 208 #ifdef KERN_TLS 209 u_int maxlen; 210 #endif 211 212 cr = malloc(sizeof(struct ct_request), M_RPC, M_WAITOK); 213 214 mtx_lock(&ct->ct_lock); 215 216 if (ct->ct_closing || ct->ct_closed) { 217 mtx_unlock(&ct->ct_lock); 218 free(cr, M_RPC); 219 return (RPC_CANTSEND); 220 } 221 ct->ct_threads++; 222 223 if (ext) { 224 auth = ext->rc_auth; 225 errp = &ext->rc_err; 226 } else { 227 auth = cl->cl_auth; 228 errp = &ct->ct_error; 229 } 230 231 cr->cr_mrep = NULL; 232 cr->cr_error = 0; 233 234 if (ct->ct_wait.tv_usec == -1) 235 timeout = utimeout; /* use supplied timeout */ 236 else 237 timeout = ct->ct_wait; /* use default timeout */ 238 239 call_again: 240 mtx_assert(&ct->ct_lock, MA_OWNED); 241 242 ct->ct_xid++; 243 xid = ct->ct_xid; 244 245 mtx_unlock(&ct->ct_lock); 246 247 /* 248 * Leave space to pre-pend the record mark. 249 */ 250 mreq = m_gethdr(M_WAITOK, MT_DATA); 251 mreq->m_data += sizeof(uint32_t); 252 KASSERT(ct->ct_mpos + sizeof(uint32_t) <= MHLEN, 253 ("RPC header too big")); 254 bcopy(ct->ct_mcallc, mreq->m_data, ct->ct_mpos); 255 mreq->m_len = ct->ct_mpos; 256 257 /* 258 * The XID is the first thing in the request. 259 */ 260 *mtod(mreq, uint32_t *) = htonl(xid); 261 262 xdrmbuf_create(&xdrs, mreq, XDR_ENCODE); 263 264 errp->re_status = stat = RPC_SUCCESS; 265 266 if ((!XDR_PUTINT32(&xdrs, &proc)) || 267 (!AUTH_MARSHALL(auth, xid, &xdrs, 268 m_copym(args, 0, M_COPYALL, M_WAITOK)))) { 269 errp->re_status = stat = RPC_CANTENCODEARGS; 270 mtx_lock(&ct->ct_lock); 271 goto out; 272 } 273 mreq->m_pkthdr.len = m_length(mreq, NULL); 274 275 /* RDMA doesn't need a record marker. */ 276 if (xprt->xp_socket != NULL) { 277 /* 278 * Prepend a record marker containing the packet length. 279 */ 280 M_PREPEND(mreq, sizeof(uint32_t), M_WAITOK); 281 *mtod(mreq, uint32_t *) = 282 htonl(0x80000000 | (mreq->m_pkthdr.len - sizeof(uint32_t))); 283 } 284 285 cr->cr_xid = xid; 286 mtx_lock(&ct->ct_lock); 287 /* 288 * Check to see if the client end has already started to close down 289 * the connection. The svc code will have set ct_error.re_status 290 * to RPC_CANTRECV if this is the case. 291 * If the client starts to close down the connection after this 292 * point, it will be detected later when cr_error is checked, 293 * since the request is in the ct_pending queue. 294 */ 295 if (ct->ct_error.re_status == RPC_CANTRECV) { 296 if (errp != &ct->ct_error) { 297 errp->re_errno = ct->ct_error.re_errno; 298 errp->re_status = RPC_CANTRECV; 299 } 300 stat = RPC_CANTRECV; 301 goto out; 302 } 303 TAILQ_INSERT_TAIL(&ct->ct_pending, cr, cr_link); 304 mtx_unlock(&ct->ct_lock); 305 306 error = 0; /* Keep compilers happy. */ 307 if (xprt->xp_socket != NULL) { 308 /* Handle TCP sockets. */ 309 /* For RPC-over-TLS, copy mrep to a chain of ext_pgs. */ 310 if ((xprt->xp_tls & RPCTLS_FLAGS_HANDSHAKE) != 0) { 311 /* 312 * Copy the mbuf chain to a chain of 313 * ext_pgs mbuf(s) as required by KERN_TLS. 314 */ 315 maxextsiz = TLS_MAX_MSG_SIZE_V10_2; 316 #ifdef KERN_TLS 317 if (rpctls_getinfo(&maxlen, false, false)) 318 maxextsiz = min(maxextsiz, maxlen); 319 #endif 320 mreq = _rpc_copym_into_ext_pgs(mreq, maxextsiz); 321 } 322 /* 323 * sosend consumes mreq. 324 */ 325 sx_xlock(&xprt->xp_lock); 326 error = sosend(xprt->xp_socket, NULL, NULL, mreq, NULL, 0, 327 curthread); 328 mreq = NULL; 329 if (error == EMSGSIZE) { 330 SOCK_SENDBUF_LOCK(xprt->xp_socket); 331 sbwait(xprt->xp_socket, SO_SND); 332 SOCK_SENDBUF_UNLOCK(xprt->xp_socket); 333 sx_xunlock(&xprt->xp_lock); 334 AUTH_VALIDATE(auth, xid, NULL, NULL); 335 mtx_lock(&ct->ct_lock); 336 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link); 337 goto call_again; 338 } 339 sx_xunlock(&xprt->xp_lock); 340 } else { 341 /* Handle RDMA. */ 342 if (clnt_bck_rdma_send != NULL) { 343 error = clnt_bck_rdma_send(xprt, mreq); 344 mreq = NULL; 345 } else 346 error = ENOTCONN; 347 } 348 349 reply_msg.acpted_rply.ar_verf.oa_flavor = AUTH_NULL; 350 reply_msg.acpted_rply.ar_verf.oa_base = cr->cr_verf; 351 reply_msg.acpted_rply.ar_verf.oa_length = 0; 352 reply_msg.acpted_rply.ar_results.where = NULL; 353 reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; 354 355 mtx_lock(&ct->ct_lock); 356 if (error) { 357 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link); 358 errp->re_errno = error; 359 errp->re_status = stat = RPC_CANTSEND; 360 goto out; 361 } 362 363 /* 364 * Check to see if we got an upcall while waiting for the 365 * lock. In both these cases, the request has been removed 366 * from ct->ct_pending. 367 */ 368 if (cr->cr_error) { 369 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link); 370 errp->re_errno = cr->cr_error; 371 errp->re_status = stat = RPC_CANTRECV; 372 goto out; 373 } 374 if (cr->cr_mrep) { 375 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link); 376 goto got_reply; 377 } 378 379 /* 380 * Hack to provide rpc-based message passing 381 */ 382 if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { 383 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link); 384 errp->re_status = stat = RPC_TIMEDOUT; 385 goto out; 386 } 387 388 error = msleep(cr, &ct->ct_lock, ct->ct_waitflag, ct->ct_waitchan, 389 tvtohz(&timeout)); 390 391 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link); 392 393 if (error) { 394 /* 395 * The sleep returned an error so our request is still 396 * on the list. Turn the error code into an 397 * appropriate client status. 398 */ 399 errp->re_errno = error; 400 switch (error) { 401 case EINTR: 402 stat = RPC_INTR; 403 break; 404 case EWOULDBLOCK: 405 stat = RPC_TIMEDOUT; 406 break; 407 default: 408 stat = RPC_CANTRECV; 409 } 410 errp->re_status = stat; 411 goto out; 412 } else { 413 /* 414 * We were woken up by the svc thread. If the 415 * upcall had a receive error, report that, 416 * otherwise we have a reply. 417 */ 418 if (cr->cr_error) { 419 errp->re_errno = cr->cr_error; 420 errp->re_status = stat = RPC_CANTRECV; 421 goto out; 422 } 423 } 424 425 got_reply: 426 /* 427 * Now decode and validate the response. We need to drop the 428 * lock since xdr_replymsg may end up sleeping in malloc. 429 */ 430 mtx_unlock(&ct->ct_lock); 431 432 if (ext && ext->rc_feedback) 433 ext->rc_feedback(FEEDBACK_OK, proc, ext->rc_feedback_arg); 434 435 xdrmbuf_create(&xdrs, cr->cr_mrep, XDR_DECODE); 436 ok = xdr_replymsg(&xdrs, &reply_msg); 437 cr->cr_mrep = NULL; 438 439 if (ok) { 440 if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) && 441 (reply_msg.acpted_rply.ar_stat == SUCCESS)) 442 errp->re_status = stat = RPC_SUCCESS; 443 else 444 stat = _seterr_reply(&reply_msg, errp); 445 446 if (stat == RPC_SUCCESS) { 447 results = xdrmbuf_getall(&xdrs); 448 if (!AUTH_VALIDATE(auth, xid, 449 &reply_msg.acpted_rply.ar_verf, &results)) { 450 errp->re_status = stat = RPC_AUTHERROR; 451 errp->re_why = AUTH_INVALIDRESP; 452 } else { 453 KASSERT(results, 454 ("auth validated but no result")); 455 *resultsp = results; 456 } 457 } /* end successful completion */ 458 /* 459 * If unsuccessful AND error is an authentication error 460 * then refresh credentials and try again, else break 461 */ 462 else if (stat == RPC_AUTHERROR) { 463 /* maybe our credentials need to be refreshed ... */ 464 CURVNET_SET_QUIET(TD_TO_VNET(curthread)); 465 if (nrefreshes > 0 && AUTH_REFRESH(auth, &reply_msg)) { 466 CURVNET_RESTORE(); 467 nrefreshes--; 468 XDR_DESTROY(&xdrs); 469 mtx_lock(&ct->ct_lock); 470 goto call_again; 471 } 472 CURVNET_RESTORE(); 473 /* end of unsuccessful completion */ 474 } 475 /* end of valid reply message */ 476 } else 477 errp->re_status = stat = RPC_CANTDECODERES; 478 XDR_DESTROY(&xdrs); 479 mtx_lock(&ct->ct_lock); 480 out: 481 mtx_assert(&ct->ct_lock, MA_OWNED); 482 483 KASSERT(stat != RPC_SUCCESS || *resultsp, 484 ("RPC_SUCCESS without reply")); 485 486 if (mreq != NULL) 487 m_freem(mreq); 488 if (cr->cr_mrep != NULL) 489 m_freem(cr->cr_mrep); 490 491 ct->ct_threads--; 492 if (ct->ct_closing) 493 wakeup(ct); 494 495 mtx_unlock(&ct->ct_lock); 496 497 if (auth && stat != RPC_SUCCESS) 498 AUTH_VALIDATE(auth, xid, NULL, NULL); 499 500 free(cr, M_RPC); 501 502 return (stat); 503 } 504 505 static void 506 clnt_bck_geterr(CLIENT *cl, struct rpc_err *errp) 507 { 508 struct ct_data *ct = (struct ct_data *) cl->cl_private; 509 510 *errp = ct->ct_error; 511 } 512 513 static bool_t 514 clnt_bck_freeres(CLIENT *cl, xdrproc_t xdr_res, void *res_ptr) 515 { 516 XDR xdrs; 517 bool_t dummy; 518 519 xdrs.x_op = XDR_FREE; 520 dummy = (*xdr_res)(&xdrs, res_ptr); 521 522 return (dummy); 523 } 524 525 /*ARGSUSED*/ 526 static void 527 clnt_bck_abort(CLIENT *cl) 528 { 529 } 530 531 static bool_t 532 clnt_bck_control(CLIENT *cl, u_int request, void *info) 533 { 534 535 return (TRUE); 536 } 537 538 static void 539 clnt_bck_close(CLIENT *cl) 540 { 541 struct ct_data *ct = (struct ct_data *) cl->cl_private; 542 543 mtx_lock(&ct->ct_lock); 544 545 if (ct->ct_closed) { 546 mtx_unlock(&ct->ct_lock); 547 return; 548 } 549 550 if (ct->ct_closing) { 551 while (ct->ct_closing) 552 msleep(ct, &ct->ct_lock, 0, "rpcclose", 0); 553 KASSERT(ct->ct_closed, ("client should be closed")); 554 mtx_unlock(&ct->ct_lock); 555 return; 556 } 557 558 ct->ct_closing = FALSE; 559 ct->ct_closed = TRUE; 560 mtx_unlock(&ct->ct_lock); 561 wakeup(ct); 562 } 563 564 static void 565 clnt_bck_destroy(CLIENT *cl) 566 { 567 struct ct_data *ct = (struct ct_data *) cl->cl_private; 568 569 clnt_bck_close(cl); 570 571 mtx_destroy(&ct->ct_lock); 572 mem_free(ct, sizeof(struct ct_data)); 573 if (cl->cl_netid && cl->cl_netid[0]) 574 mem_free(cl->cl_netid, strlen(cl->cl_netid) +1); 575 if (cl->cl_tp && cl->cl_tp[0]) 576 mem_free(cl->cl_tp, strlen(cl->cl_tp) +1); 577 mem_free(cl, sizeof(CLIENT)); 578 } 579 580 /* 581 * This call is done by the svc code when a backchannel RPC reply is 582 * received. 583 * For the server end, where callback RPCs to the client are performed, 584 * xp_p2 points to the "CLIENT" and not the associated "struct ct_data" 585 * so that svc_vc_destroy() can CLNT_RELEASE() the reference count on it. 586 */ 587 void 588 clnt_bck_svccall(void *arg, struct mbuf *mrep, uint32_t xid) 589 { 590 CLIENT *cl = (CLIENT *)arg; 591 struct ct_data *ct; 592 struct ct_request *cr; 593 int foundreq; 594 595 ct = (struct ct_data *)cl->cl_private; 596 mtx_lock(&ct->ct_lock); 597 if (ct->ct_closing || ct->ct_closed) { 598 mtx_unlock(&ct->ct_lock); 599 m_freem(mrep); 600 return; 601 } 602 603 ct->ct_upcallrefs++; 604 /* 605 * See if we can match this reply to a request. 606 */ 607 foundreq = 0; 608 TAILQ_FOREACH(cr, &ct->ct_pending, cr_link) { 609 if (cr->cr_xid == xid) { 610 /* 611 * This one matches. We leave the reply mbuf list in 612 * cr->cr_mrep. Set the XID to zero so that we will 613 * ignore any duplicated replies. 614 */ 615 cr->cr_xid = 0; 616 cr->cr_mrep = mrep; 617 cr->cr_error = 0; 618 foundreq = 1; 619 wakeup(cr); 620 break; 621 } 622 } 623 624 ct->ct_upcallrefs--; 625 if (ct->ct_upcallrefs < 0) 626 panic("rpcvc svccall refcnt"); 627 if (ct->ct_upcallrefs == 0) 628 wakeup(&ct->ct_upcallrefs); 629 mtx_unlock(&ct->ct_lock); 630 if (foundreq == 0) 631 m_freem(mrep); 632 } 633 634