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