The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/rpc/clnt_vc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: clnt_vc.c,v 1.4 2000/07/14 08:40:42 fvdl Exp $ */
    2 
    3 /*-
    4  * SPDX-License-Identifier: BSD-3-Clause
    5  *
    6  * Copyright (c) 2009, Sun Microsystems, Inc.
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without 
   10  * modification, are permitted provided that the following conditions are met:
   11  * - Redistributions of source code must retain the above copyright notice, 
   12  *   this list of conditions and the following disclaimer.
   13  * - Redistributions in binary form must reproduce the above copyright notice, 
   14  *   this list of conditions and the following disclaimer in the documentation 
   15  *   and/or other materials provided with the distribution.
   16  * - Neither the name of Sun Microsystems, Inc. nor the names of its 
   17  *   contributors may be used to endorse or promote products derived 
   18  *   from this software without specific prior written permission.
   19  * 
   20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   21  * AND 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 COPYRIGHT HOLDER OR CONTRIBUTORS BE 
   24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   30  * POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 #if defined(LIBC_SCCS) && !defined(lint)
   34 static char *sccsid2 = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
   35 static char *sccsid = "@(#)clnt_tcp.c   2.2 88/08/01 4.0 RPCSRC";
   36 static char sccsid3[] = "@(#)clnt_vc.c 1.19 89/03/16 Copyr 1988 Sun Micro";
   37 #endif
   38 #include <sys/cdefs.h>
   39 __FBSDID("$FreeBSD$");
   40  
   41 /*
   42  * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
   43  *
   44  * Copyright (C) 1984, Sun Microsystems, Inc.
   45  *
   46  * TCP based RPC supports 'batched calls'.
   47  * A sequence of calls may be batched-up in a send buffer.  The rpc call
   48  * return immediately to the client even though the call was not necessarily
   49  * sent.  The batching occurs if the results' xdr routine is NULL (0) AND
   50  * the rpc timeout value is zero (see clnt.h, rpc).
   51  *
   52  * Clients should NOT casually batch calls that in fact return results; that is,
   53  * the server side should be aware that a call is batched and not produce any
   54  * return message.  Batched calls that produce many result messages can
   55  * deadlock (netlock) the client and the server....
   56  *
   57  * Now go hang yourself.
   58  */
   59 
   60 #include "opt_kern_tls.h"
   61 
   62 #include <sys/param.h>
   63 #include <sys/systm.h>
   64 #include <sys/kernel.h>
   65 #include <sys/kthread.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 enum clnt_stat clnt_vc_call(CLIENT *, struct rpc_callextra *,
   96     rpcproc_t, struct mbuf *, struct mbuf **, struct timeval);
   97 static void clnt_vc_geterr(CLIENT *, struct rpc_err *);
   98 static bool_t clnt_vc_freeres(CLIENT *, xdrproc_t, void *);
   99 static void clnt_vc_abort(CLIENT *);
  100 static bool_t clnt_vc_control(CLIENT *, u_int, void *);
  101 static void clnt_vc_close(CLIENT *);
  102 static void clnt_vc_destroy(CLIENT *);
  103 static bool_t time_not_ok(struct timeval *);
  104 static int clnt_vc_soupcall(struct socket *so, void *arg, int waitflag);
  105 static void clnt_vc_dotlsupcall(void *data);
  106 
  107 static const struct clnt_ops clnt_vc_ops = {
  108         .cl_call =      clnt_vc_call,
  109         .cl_abort =     clnt_vc_abort,
  110         .cl_geterr =    clnt_vc_geterr,
  111         .cl_freeres =   clnt_vc_freeres,
  112         .cl_close =     clnt_vc_close,
  113         .cl_destroy =   clnt_vc_destroy,
  114         .cl_control =   clnt_vc_control
  115 };
  116 
  117 static void clnt_vc_upcallsdone(struct ct_data *);
  118 
  119 /*
  120  * Create a client handle for a connection.
  121  * Default options are set, which the user can change using clnt_control()'s.
  122  * The rpc/vc package does buffering similar to stdio, so the client
  123  * must pick send and receive buffer sizes, 0 => use the default.
  124  * NB: fd is copied into a private area.
  125  * NB: The rpch->cl_auth is set null authentication. Caller may wish to
  126  * set this something more useful.
  127  *
  128  * fd should be an open socket
  129  */
  130 CLIENT *
  131 clnt_vc_create(
  132         struct socket *so,              /* open file descriptor */
  133         struct sockaddr *raddr,         /* servers address */
  134         const rpcprog_t prog,           /* program number */
  135         const rpcvers_t vers,           /* version number */
  136         size_t sendsz,                  /* buffer recv size */
  137         size_t recvsz,                  /* buffer send size */
  138         int intrflag)                   /* interruptible */
  139 {
  140         CLIENT *cl;                     /* client handle */
  141         struct ct_data *ct = NULL;      /* client handle */
  142         struct timeval now;
  143         struct rpc_msg call_msg;
  144         static uint32_t disrupt;
  145         struct __rpc_sockinfo si;
  146         XDR xdrs;
  147         int error, interrupted, one = 1, sleep_flag;
  148         struct sockopt sopt;
  149 
  150         if (disrupt == 0)
  151                 disrupt = (uint32_t)(long)raddr;
  152 
  153         cl = (CLIENT *)mem_alloc(sizeof (*cl));
  154         ct = (struct ct_data *)mem_alloc(sizeof (*ct));
  155 
  156         mtx_init(&ct->ct_lock, "ct->ct_lock", NULL, MTX_DEF);
  157         ct->ct_threads = 0;
  158         ct->ct_closing = FALSE;
  159         ct->ct_closed = FALSE;
  160         ct->ct_upcallrefs = 0;
  161         ct->ct_rcvstate = RPCRCVSTATE_NORMAL;
  162 
  163         if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
  164                 error = soconnect(so, raddr, curthread);
  165                 SOCK_LOCK(so);
  166                 interrupted = 0;
  167                 sleep_flag = PSOCK;
  168                 if (intrflag != 0)
  169                         sleep_flag |= PCATCH;
  170                 while ((so->so_state & SS_ISCONNECTING)
  171                     && so->so_error == 0) {
  172                         error = msleep(&so->so_timeo, SOCK_MTX(so),
  173                             sleep_flag, "connec", 0);
  174                         if (error) {
  175                                 if (error == EINTR || error == ERESTART)
  176                                         interrupted = 1;
  177                                 break;
  178                         }
  179                 }
  180                 if (error == 0) {
  181                         error = so->so_error;
  182                         so->so_error = 0;
  183                 }
  184                 SOCK_UNLOCK(so);
  185                 if (error) {
  186                         if (!interrupted)
  187                                 so->so_state &= ~SS_ISCONNECTING;
  188                         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  189                         rpc_createerr.cf_error.re_errno = error;
  190                         goto err;
  191                 }
  192         }
  193 
  194         if (!__rpc_socket2sockinfo(so, &si)) {
  195                 goto err;
  196         }
  197 
  198         if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
  199                 bzero(&sopt, sizeof(sopt));
  200                 sopt.sopt_dir = SOPT_SET;
  201                 sopt.sopt_level = SOL_SOCKET;
  202                 sopt.sopt_name = SO_KEEPALIVE;
  203                 sopt.sopt_val = &one;
  204                 sopt.sopt_valsize = sizeof(one);
  205                 sosetopt(so, &sopt);
  206         }
  207 
  208         if (so->so_proto->pr_protocol == IPPROTO_TCP) {
  209                 bzero(&sopt, sizeof(sopt));
  210                 sopt.sopt_dir = SOPT_SET;
  211                 sopt.sopt_level = IPPROTO_TCP;
  212                 sopt.sopt_name = TCP_NODELAY;
  213                 sopt.sopt_val = &one;
  214                 sopt.sopt_valsize = sizeof(one);
  215                 sosetopt(so, &sopt);
  216         }
  217 
  218         ct->ct_closeit = FALSE;
  219 
  220         /*
  221          * Set up private data struct
  222          */
  223         ct->ct_socket = so;
  224         ct->ct_wait.tv_sec = -1;
  225         ct->ct_wait.tv_usec = -1;
  226         memcpy(&ct->ct_addr, raddr, raddr->sa_len);
  227 
  228         /*
  229          * Initialize call message
  230          */
  231         getmicrotime(&now);
  232         ct->ct_xid = ((uint32_t)++disrupt) ^ __RPC_GETXID(&now);
  233         call_msg.rm_xid = ct->ct_xid;
  234         call_msg.rm_direction = CALL;
  235         call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  236         call_msg.rm_call.cb_prog = (uint32_t)prog;
  237         call_msg.rm_call.cb_vers = (uint32_t)vers;
  238 
  239         /*
  240          * pre-serialize the static part of the call msg and stash it away
  241          */
  242         xdrmem_create(&xdrs, ct->ct_mcallc, MCALL_MSG_SIZE,
  243             XDR_ENCODE);
  244         if (! xdr_callhdr(&xdrs, &call_msg)) {
  245                 if (ct->ct_closeit) {
  246                         soclose(ct->ct_socket);
  247                 }
  248                 goto err;
  249         }
  250         ct->ct_mpos = XDR_GETPOS(&xdrs);
  251         XDR_DESTROY(&xdrs);
  252         ct->ct_waitchan = "rpcrecv";
  253         ct->ct_waitflag = 0;
  254 
  255         /*
  256          * Create a client handle which uses xdrrec for serialization
  257          * and authnone for authentication.
  258          */
  259         sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
  260         recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
  261         error = soreserve(ct->ct_socket, sendsz, recvsz);
  262         if (error != 0) {
  263                 if (ct->ct_closeit) {
  264                         soclose(ct->ct_socket);
  265                 }
  266                 goto err;
  267         }
  268         cl->cl_refs = 1;
  269         cl->cl_ops = &clnt_vc_ops;
  270         cl->cl_private = ct;
  271         cl->cl_auth = authnone_create();
  272 
  273         SOCKBUF_LOCK(&ct->ct_socket->so_rcv);
  274         soupcall_set(ct->ct_socket, SO_RCV, clnt_vc_soupcall, ct);
  275         SOCKBUF_UNLOCK(&ct->ct_socket->so_rcv);
  276 
  277         ct->ct_raw = NULL;
  278         ct->ct_record = NULL;
  279         ct->ct_record_resid = 0;
  280         ct->ct_sslrefno = 0;
  281         TAILQ_INIT(&ct->ct_pending);
  282         return (cl);
  283 
  284 err:
  285         mtx_destroy(&ct->ct_lock);
  286         mem_free(ct, sizeof (struct ct_data));
  287         mem_free(cl, sizeof (CLIENT));
  288 
  289         return ((CLIENT *)NULL);
  290 }
  291 
  292 static enum clnt_stat
  293 clnt_vc_call(
  294         CLIENT          *cl,            /* client handle */
  295         struct rpc_callextra *ext,      /* call metadata */
  296         rpcproc_t       proc,           /* procedure number */
  297         struct mbuf     *args,          /* pointer to args */
  298         struct mbuf     **resultsp,     /* pointer to results */
  299         struct timeval  utimeout)
  300 {
  301         struct ct_data *ct = (struct ct_data *) cl->cl_private;
  302         AUTH *auth;
  303         struct rpc_err *errp;
  304         enum clnt_stat stat;
  305         XDR xdrs;
  306         struct rpc_msg reply_msg;
  307         bool_t ok;
  308         int nrefreshes = 2;             /* number of times to refresh cred */
  309         struct timeval timeout;
  310         uint32_t xid;
  311         struct mbuf *mreq = NULL, *results;
  312         struct ct_request *cr;
  313         int error, maxextsiz, trycnt;
  314 #ifdef KERN_TLS
  315         u_int maxlen;
  316 #endif
  317 
  318         cr = malloc(sizeof(struct ct_request), M_RPC, M_WAITOK);
  319 
  320         mtx_lock(&ct->ct_lock);
  321 
  322         if (ct->ct_closing || ct->ct_closed) {
  323                 mtx_unlock(&ct->ct_lock);
  324                 free(cr, M_RPC);
  325                 return (RPC_CANTSEND);
  326         }
  327         ct->ct_threads++;
  328 
  329         if (ext) {
  330                 auth = ext->rc_auth;
  331                 errp = &ext->rc_err;
  332         } else {
  333                 auth = cl->cl_auth;
  334                 errp = &ct->ct_error;
  335         }
  336 
  337         cr->cr_mrep = NULL;
  338         cr->cr_error = 0;
  339 
  340         if (ct->ct_wait.tv_usec == -1) {
  341                 timeout = utimeout;     /* use supplied timeout */
  342         } else {
  343                 timeout = ct->ct_wait;  /* use default timeout */
  344         }
  345 
  346         /*
  347          * After 15sec of looping, allow it to return RPC_CANTSEND, which will
  348          * cause the clnt_reconnect layer to create a new TCP connection.
  349          */
  350         trycnt = 15 * hz;
  351 call_again:
  352         mtx_assert(&ct->ct_lock, MA_OWNED);
  353         if (ct->ct_closing || ct->ct_closed) {
  354                 ct->ct_threads--;
  355                 wakeup(ct);
  356                 mtx_unlock(&ct->ct_lock);
  357                 free(cr, M_RPC);
  358                 return (RPC_CANTSEND);
  359         }
  360 
  361         ct->ct_xid++;
  362         xid = ct->ct_xid;
  363 
  364         mtx_unlock(&ct->ct_lock);
  365 
  366         /*
  367          * Leave space to pre-pend the record mark.
  368          */
  369         mreq = m_gethdr(M_WAITOK, MT_DATA);
  370         mreq->m_data += sizeof(uint32_t);
  371         KASSERT(ct->ct_mpos + sizeof(uint32_t) <= MHLEN,
  372             ("RPC header too big"));
  373         bcopy(ct->ct_mcallc, mreq->m_data, ct->ct_mpos);
  374         mreq->m_len = ct->ct_mpos;
  375 
  376         /*
  377          * The XID is the first thing in the request.
  378          */
  379         *mtod(mreq, uint32_t *) = htonl(xid);
  380 
  381         xdrmbuf_create(&xdrs, mreq, XDR_ENCODE);
  382 
  383         errp->re_status = stat = RPC_SUCCESS;
  384 
  385         if ((! XDR_PUTINT32(&xdrs, &proc)) ||
  386             (! AUTH_MARSHALL(auth, xid, &xdrs,
  387                 m_copym(args, 0, M_COPYALL, M_WAITOK)))) {
  388                 errp->re_status = stat = RPC_CANTENCODEARGS;
  389                 mtx_lock(&ct->ct_lock);
  390                 goto out;
  391         }
  392         mreq->m_pkthdr.len = m_length(mreq, NULL);
  393 
  394         /*
  395          * Prepend a record marker containing the packet length.
  396          */
  397         M_PREPEND(mreq, sizeof(uint32_t), M_WAITOK);
  398         *mtod(mreq, uint32_t *) =
  399                 htonl(0x80000000 | (mreq->m_pkthdr.len - sizeof(uint32_t)));
  400 
  401         cr->cr_xid = xid;
  402         mtx_lock(&ct->ct_lock);
  403         /*
  404          * Check to see if the other end has already started to close down
  405          * the connection. The upcall will have set ct_error.re_status
  406          * to RPC_CANTRECV if this is the case.
  407          * If the other end starts to close down the connection after this
  408          * point, it will be detected later when cr_error is checked,
  409          * since the request is in the ct_pending queue.
  410          */
  411         if (ct->ct_error.re_status == RPC_CANTRECV) {
  412                 if (errp != &ct->ct_error) {
  413                         errp->re_errno = ct->ct_error.re_errno;
  414                         errp->re_status = RPC_CANTRECV;
  415                 }
  416                 stat = RPC_CANTRECV;
  417                 goto out;
  418         }
  419 
  420         /* For TLS, wait for an upcall to be done, as required. */
  421         while ((ct->ct_rcvstate & (RPCRCVSTATE_NORMAL |
  422             RPCRCVSTATE_NONAPPDATA)) == 0)
  423                 msleep(&ct->ct_rcvstate, &ct->ct_lock, 0, "rpcrcvst", hz);
  424 
  425         TAILQ_INSERT_TAIL(&ct->ct_pending, cr, cr_link);
  426         mtx_unlock(&ct->ct_lock);
  427 
  428         if (ct->ct_sslrefno != 0) {
  429                 /*
  430                  * Copy the mbuf chain to a chain of ext_pgs mbuf(s)
  431                  * as required by KERN_TLS.
  432                  */
  433                 maxextsiz = TLS_MAX_MSG_SIZE_V10_2;
  434 #ifdef KERN_TLS
  435                 if (rpctls_getinfo(&maxlen, false, false))
  436                         maxextsiz = min(maxextsiz, maxlen);
  437 #endif
  438                 mreq = _rpc_copym_into_ext_pgs(mreq, maxextsiz);
  439         }
  440         /*
  441          * sosend consumes mreq.
  442          */
  443         error = sosend(ct->ct_socket, NULL, NULL, mreq, NULL, 0, curthread);
  444         mreq = NULL;
  445         if (error == EMSGSIZE || (error == ERESTART &&
  446             (ct->ct_waitflag & PCATCH) == 0 && trycnt-- > 0)) {
  447                 SOCKBUF_LOCK(&ct->ct_socket->so_snd);
  448                 sbwait(ct->ct_socket, SO_SND);
  449                 SOCKBUF_UNLOCK(&ct->ct_socket->so_snd);
  450                 AUTH_VALIDATE(auth, xid, NULL, NULL);
  451                 mtx_lock(&ct->ct_lock);
  452                 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
  453                 /* Sleep for 1 clock tick before trying the sosend() again. */
  454                 mtx_unlock(&ct->ct_lock);
  455                 pause("rpclpsnd", 1);
  456                 mtx_lock(&ct->ct_lock);
  457                 goto call_again;
  458         }
  459 
  460         reply_msg.acpted_rply.ar_verf.oa_flavor = AUTH_NULL;
  461         reply_msg.acpted_rply.ar_verf.oa_base = cr->cr_verf;
  462         reply_msg.acpted_rply.ar_verf.oa_length = 0;
  463         reply_msg.acpted_rply.ar_results.where = NULL;
  464         reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
  465 
  466         mtx_lock(&ct->ct_lock);
  467         if (error) {
  468                 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
  469                 errp->re_errno = error;
  470                 errp->re_status = stat = RPC_CANTSEND;
  471                 goto out;
  472         }
  473 
  474         /*
  475          * Check to see if we got an upcall while waiting for the
  476          * lock. In both these cases, the request has been removed
  477          * from ct->ct_pending.
  478          */
  479         if (cr->cr_error) {
  480                 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
  481                 errp->re_errno = cr->cr_error;
  482                 errp->re_status = stat = RPC_CANTRECV;
  483                 goto out;
  484         }
  485         if (cr->cr_mrep) {
  486                 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
  487                 goto got_reply;
  488         }
  489 
  490         /*
  491          * Hack to provide rpc-based message passing
  492          */
  493         if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
  494                 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
  495                 errp->re_status = stat = RPC_TIMEDOUT;
  496                 goto out;
  497         }
  498 
  499         error = msleep(cr, &ct->ct_lock, ct->ct_waitflag, ct->ct_waitchan,
  500             tvtohz(&timeout));
  501 
  502         TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
  503 
  504         if (error) {
  505                 /*
  506                  * The sleep returned an error so our request is still
  507                  * on the list. Turn the error code into an
  508                  * appropriate client status.
  509                  */
  510                 errp->re_errno = error;
  511                 switch (error) {
  512                 case EINTR:
  513                         stat = RPC_INTR;
  514                         break;
  515                 case EWOULDBLOCK:
  516                         stat = RPC_TIMEDOUT;
  517                         break;
  518                 default:
  519                         stat = RPC_CANTRECV;
  520                 }
  521                 errp->re_status = stat;
  522                 goto out;
  523         } else {
  524                 /*
  525                  * We were woken up by the upcall.  If the
  526                  * upcall had a receive error, report that,
  527                  * otherwise we have a reply.
  528                  */
  529                 if (cr->cr_error) {
  530                         errp->re_errno = cr->cr_error;
  531                         errp->re_status = stat = RPC_CANTRECV;
  532                         goto out;
  533                 }
  534         }
  535 
  536 got_reply:
  537         /*
  538          * Now decode and validate the response. We need to drop the
  539          * lock since xdr_replymsg may end up sleeping in malloc.
  540          */
  541         mtx_unlock(&ct->ct_lock);
  542 
  543         if (ext && ext->rc_feedback)
  544                 ext->rc_feedback(FEEDBACK_OK, proc, ext->rc_feedback_arg);
  545 
  546         xdrmbuf_create(&xdrs, cr->cr_mrep, XDR_DECODE);
  547         ok = xdr_replymsg(&xdrs, &reply_msg);
  548         cr->cr_mrep = NULL;
  549 
  550         if (ok) {
  551                 if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
  552                     (reply_msg.acpted_rply.ar_stat == SUCCESS))
  553                         errp->re_status = stat = RPC_SUCCESS;
  554                 else
  555                         stat = _seterr_reply(&reply_msg, errp);
  556 
  557                 if (stat == RPC_SUCCESS) {
  558                         results = xdrmbuf_getall(&xdrs);
  559                         if (!AUTH_VALIDATE(auth, xid,
  560                                 &reply_msg.acpted_rply.ar_verf,
  561                                 &results)) {
  562                                 errp->re_status = stat = RPC_AUTHERROR;
  563                                 errp->re_why = AUTH_INVALIDRESP;
  564                         } else {
  565                                 KASSERT(results,
  566                                     ("auth validated but no result"));
  567                                 *resultsp = results;
  568                         }
  569                 }               /* end successful completion */
  570                 /*
  571                  * If unsuccessful AND error is an authentication error
  572                  * then refresh credentials and try again, else break
  573                  */
  574                 else if (stat == RPC_AUTHERROR)
  575                         /* maybe our credentials need to be refreshed ... */
  576                         if (nrefreshes > 0 &&
  577                             AUTH_REFRESH(auth, &reply_msg)) {
  578                                 nrefreshes--;
  579                                 XDR_DESTROY(&xdrs);
  580                                 mtx_lock(&ct->ct_lock);
  581                                 goto call_again;
  582                         }
  583                 /* end of unsuccessful completion */
  584         }       /* end of valid reply message */
  585         else {
  586                 errp->re_status = stat = RPC_CANTDECODERES;
  587         }
  588         XDR_DESTROY(&xdrs);
  589         mtx_lock(&ct->ct_lock);
  590 out:
  591         mtx_assert(&ct->ct_lock, MA_OWNED);
  592 
  593         KASSERT(stat != RPC_SUCCESS || *resultsp,
  594             ("RPC_SUCCESS without reply"));
  595 
  596         if (mreq)
  597                 m_freem(mreq);
  598         if (cr->cr_mrep)
  599                 m_freem(cr->cr_mrep);
  600 
  601         ct->ct_threads--;
  602         if (ct->ct_closing)
  603                 wakeup(ct);
  604                 
  605         mtx_unlock(&ct->ct_lock);
  606 
  607         if (auth && stat != RPC_SUCCESS)
  608                 AUTH_VALIDATE(auth, xid, NULL, NULL);
  609 
  610         free(cr, M_RPC);
  611 
  612         return (stat);
  613 }
  614 
  615 static void
  616 clnt_vc_geterr(CLIENT *cl, struct rpc_err *errp)
  617 {
  618         struct ct_data *ct = (struct ct_data *) cl->cl_private;
  619 
  620         *errp = ct->ct_error;
  621 }
  622 
  623 static bool_t
  624 clnt_vc_freeres(CLIENT *cl, xdrproc_t xdr_res, void *res_ptr)
  625 {
  626         XDR xdrs;
  627         bool_t dummy;
  628 
  629         xdrs.x_op = XDR_FREE;
  630         dummy = (*xdr_res)(&xdrs, res_ptr);
  631 
  632         return (dummy);
  633 }
  634 
  635 /*ARGSUSED*/
  636 static void
  637 clnt_vc_abort(CLIENT *cl)
  638 {
  639 }
  640 
  641 static bool_t
  642 clnt_vc_control(CLIENT *cl, u_int request, void *info)
  643 {
  644         struct ct_data *ct = (struct ct_data *)cl->cl_private;
  645         void *infop = info;
  646         SVCXPRT *xprt;
  647         uint64_t *p;
  648         int error;
  649         static u_int thrdnum = 0;
  650 
  651         mtx_lock(&ct->ct_lock);
  652 
  653         switch (request) {
  654         case CLSET_FD_CLOSE:
  655                 ct->ct_closeit = TRUE;
  656                 mtx_unlock(&ct->ct_lock);
  657                 return (TRUE);
  658         case CLSET_FD_NCLOSE:
  659                 ct->ct_closeit = FALSE;
  660                 mtx_unlock(&ct->ct_lock);
  661                 return (TRUE);
  662         default:
  663                 break;
  664         }
  665 
  666         /* for other requests which use info */
  667         if (info == NULL) {
  668                 mtx_unlock(&ct->ct_lock);
  669                 return (FALSE);
  670         }
  671         switch (request) {
  672         case CLSET_TIMEOUT:
  673                 if (time_not_ok((struct timeval *)info)) {
  674                         mtx_unlock(&ct->ct_lock);
  675                         return (FALSE);
  676                 }
  677                 ct->ct_wait = *(struct timeval *)infop;
  678                 break;
  679         case CLGET_TIMEOUT:
  680                 *(struct timeval *)infop = ct->ct_wait;
  681                 break;
  682         case CLGET_SERVER_ADDR:
  683                 (void) memcpy(info, &ct->ct_addr, (size_t)ct->ct_addr.ss_len);
  684                 break;
  685         case CLGET_SVC_ADDR:
  686                 /*
  687                  * Slightly different semantics to userland - we use
  688                  * sockaddr instead of netbuf.
  689                  */
  690                 memcpy(info, &ct->ct_addr, ct->ct_addr.ss_len);
  691                 break;
  692         case CLSET_SVC_ADDR:            /* set to new address */
  693                 mtx_unlock(&ct->ct_lock);
  694                 return (FALSE);
  695         case CLGET_XID:
  696                 *(uint32_t *)info = ct->ct_xid;
  697                 break;
  698         case CLSET_XID:
  699                 /* This will set the xid of the NEXT call */
  700                 /* decrement by 1 as clnt_vc_call() increments once */
  701                 ct->ct_xid = *(uint32_t *)info - 1;
  702                 break;
  703         case CLGET_VERS:
  704                 /*
  705                  * This RELIES on the information that, in the call body,
  706                  * the version number field is the fifth field from the
  707                  * beginning of the RPC header. MUST be changed if the
  708                  * call_struct is changed
  709                  */
  710                 *(uint32_t *)info =
  711                     ntohl(*(uint32_t *)(void *)(ct->ct_mcallc +
  712                     4 * BYTES_PER_XDR_UNIT));
  713                 break;
  714 
  715         case CLSET_VERS:
  716                 *(uint32_t *)(void *)(ct->ct_mcallc +
  717                     4 * BYTES_PER_XDR_UNIT) =
  718                     htonl(*(uint32_t *)info);
  719                 break;
  720 
  721         case CLGET_PROG:
  722                 /*
  723                  * This RELIES on the information that, in the call body,
  724                  * the program number field is the fourth field from the
  725                  * beginning of the RPC header. MUST be changed if the
  726                  * call_struct is changed
  727                  */
  728                 *(uint32_t *)info =
  729                     ntohl(*(uint32_t *)(void *)(ct->ct_mcallc +
  730                     3 * BYTES_PER_XDR_UNIT));
  731                 break;
  732 
  733         case CLSET_PROG:
  734                 *(uint32_t *)(void *)(ct->ct_mcallc +
  735                     3 * BYTES_PER_XDR_UNIT) =
  736                     htonl(*(uint32_t *)info);
  737                 break;
  738 
  739         case CLSET_WAITCHAN:
  740                 ct->ct_waitchan = (const char *)info;
  741                 break;
  742 
  743         case CLGET_WAITCHAN:
  744                 *(const char **) info = ct->ct_waitchan;
  745                 break;
  746 
  747         case CLSET_INTERRUPTIBLE:
  748                 if (*(int *) info)
  749                         ct->ct_waitflag = PCATCH;
  750                 else
  751                         ct->ct_waitflag = 0;
  752                 break;
  753 
  754         case CLGET_INTERRUPTIBLE:
  755                 if (ct->ct_waitflag)
  756                         *(int *) info = TRUE;
  757                 else
  758                         *(int *) info = FALSE;
  759                 break;
  760 
  761         case CLSET_BACKCHANNEL:
  762                 xprt = (SVCXPRT *)info;
  763                 if (ct->ct_backchannelxprt == NULL) {
  764                         xprt->xp_p2 = ct;
  765                         if (ct->ct_sslrefno != 0)
  766                                 xprt->xp_tls = RPCTLS_FLAGS_HANDSHAKE;
  767                         ct->ct_backchannelxprt = xprt;
  768                 }
  769                 break;
  770 
  771         case CLSET_TLS:
  772                 p = (uint64_t *)info;
  773                 ct->ct_sslsec = *p++;
  774                 ct->ct_sslusec = *p++;
  775                 ct->ct_sslrefno = *p;
  776                 if (ct->ct_sslrefno != RPCTLS_REFNO_HANDSHAKE) {
  777                         mtx_unlock(&ct->ct_lock);
  778                         /* Start the kthread that handles upcalls. */
  779                         error = kthread_add(clnt_vc_dotlsupcall, ct,
  780                             NULL, NULL, 0, 0, "krpctls%u", thrdnum++);
  781                         if (error != 0)
  782                                 panic("Can't add KRPC thread error %d", error);
  783                 } else
  784                         mtx_unlock(&ct->ct_lock);
  785                 return (TRUE);
  786 
  787         case CLSET_BLOCKRCV:
  788                 if (*(int *) info) {
  789                         ct->ct_rcvstate &= ~RPCRCVSTATE_NORMAL;
  790                         ct->ct_rcvstate |= RPCRCVSTATE_TLSHANDSHAKE;
  791                 } else {
  792                         ct->ct_rcvstate &= ~RPCRCVSTATE_TLSHANDSHAKE;
  793                         ct->ct_rcvstate |= RPCRCVSTATE_NORMAL;
  794                 }
  795                 break;
  796 
  797         default:
  798                 mtx_unlock(&ct->ct_lock);
  799                 return (FALSE);
  800         }
  801 
  802         mtx_unlock(&ct->ct_lock);
  803         return (TRUE);
  804 }
  805 
  806 static void
  807 clnt_vc_close(CLIENT *cl)
  808 {
  809         struct ct_data *ct = (struct ct_data *) cl->cl_private;
  810         struct ct_request *cr;
  811 
  812         mtx_lock(&ct->ct_lock);
  813 
  814         if (ct->ct_closed) {
  815                 mtx_unlock(&ct->ct_lock);
  816                 return;
  817         }
  818 
  819         if (ct->ct_closing) {
  820                 while (ct->ct_closing)
  821                         msleep(ct, &ct->ct_lock, 0, "rpcclose", 0);
  822                 KASSERT(ct->ct_closed, ("client should be closed"));
  823                 mtx_unlock(&ct->ct_lock);
  824                 return;
  825         }
  826 
  827         if (ct->ct_socket) {
  828                 ct->ct_closing = TRUE;
  829                 mtx_unlock(&ct->ct_lock);
  830 
  831                 SOCKBUF_LOCK(&ct->ct_socket->so_rcv);
  832                 if (ct->ct_socket->so_rcv.sb_upcall != NULL) {
  833                         soupcall_clear(ct->ct_socket, SO_RCV);
  834                         clnt_vc_upcallsdone(ct);
  835                 }
  836                 SOCKBUF_UNLOCK(&ct->ct_socket->so_rcv);
  837 
  838                 /*
  839                  * Abort any pending requests and wait until everyone
  840                  * has finished with clnt_vc_call.
  841                  */
  842                 mtx_lock(&ct->ct_lock);
  843                 TAILQ_FOREACH(cr, &ct->ct_pending, cr_link) {
  844                         cr->cr_xid = 0;
  845                         cr->cr_error = ESHUTDOWN;
  846                         wakeup(cr);
  847                 }
  848 
  849                 while (ct->ct_threads)
  850                         msleep(ct, &ct->ct_lock, 0, "rpcclose", 0);
  851         }
  852 
  853         ct->ct_closing = FALSE;
  854         ct->ct_closed = TRUE;
  855         wakeup(&ct->ct_sslrefno);
  856         mtx_unlock(&ct->ct_lock);
  857         wakeup(ct);
  858 }
  859 
  860 static void
  861 clnt_vc_destroy(CLIENT *cl)
  862 {
  863         struct ct_data *ct = (struct ct_data *) cl->cl_private;
  864         struct socket *so = NULL;
  865         SVCXPRT *xprt;
  866         uint32_t reterr;
  867 
  868         clnt_vc_close(cl);
  869 
  870         mtx_lock(&ct->ct_lock);
  871         xprt = ct->ct_backchannelxprt;
  872         ct->ct_backchannelxprt = NULL;
  873         if (xprt != NULL) {
  874                 mtx_unlock(&ct->ct_lock);       /* To avoid a LOR. */
  875                 sx_xlock(&xprt->xp_lock);
  876                 mtx_lock(&ct->ct_lock);
  877                 xprt->xp_p2 = NULL;
  878                 sx_xunlock(&xprt->xp_lock);
  879         }
  880 
  881         if (ct->ct_socket) {
  882                 if (ct->ct_closeit) {
  883                         so = ct->ct_socket;
  884                 }
  885         }
  886 
  887         /* Wait for the upcall kthread to terminate. */
  888         while ((ct->ct_rcvstate & RPCRCVSTATE_UPCALLTHREAD) != 0)
  889                 msleep(&ct->ct_sslrefno, &ct->ct_lock, 0,
  890                     "clntvccl", hz);
  891         mtx_unlock(&ct->ct_lock);
  892 
  893         mtx_destroy(&ct->ct_lock);
  894         if (so) {
  895                 if (ct->ct_sslrefno != 0) {
  896                         /*
  897                          * If the TLS handshake is in progress, the upcall
  898                          * will fail, but the socket should be closed by the
  899                          * daemon, since the connect upcall has just failed.
  900                          */
  901                         if (ct->ct_sslrefno != RPCTLS_REFNO_HANDSHAKE) {
  902                                 /*
  903                                  * If the upcall fails, the socket has
  904                                  * probably been closed via the rpctlscd
  905                                  * daemon having crashed or been
  906                                  * restarted, so ignore return stat.
  907                                  */
  908                                 rpctls_cl_disconnect(ct->ct_sslsec,
  909                                     ct->ct_sslusec, ct->ct_sslrefno,
  910                                     &reterr);
  911                         }
  912                         /* Must sorele() to get rid of reference. */
  913                         CURVNET_SET(so->so_vnet);
  914                         sorele(so);
  915                         CURVNET_RESTORE();
  916                 } else {
  917                         soshutdown(so, SHUT_WR);
  918                         soclose(so);
  919                 }
  920         }
  921         m_freem(ct->ct_record);
  922         m_freem(ct->ct_raw);
  923         mem_free(ct, sizeof(struct ct_data));
  924         if (cl->cl_netid && cl->cl_netid[0])
  925                 mem_free(cl->cl_netid, strlen(cl->cl_netid) +1);
  926         if (cl->cl_tp && cl->cl_tp[0])
  927                 mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
  928         mem_free(cl, sizeof(CLIENT));
  929 }
  930 
  931 /*
  932  * Make sure that the time is not garbage.   -1 value is disallowed.
  933  * Note this is different from time_not_ok in clnt_dg.c
  934  */
  935 static bool_t
  936 time_not_ok(struct timeval *t)
  937 {
  938         return (t->tv_sec <= -1 || t->tv_sec > 100000000 ||
  939                 t->tv_usec <= -1 || t->tv_usec > 1000000);
  940 }
  941 
  942 int
  943 clnt_vc_soupcall(struct socket *so, void *arg, int waitflag)
  944 {
  945         struct ct_data *ct = (struct ct_data *) arg;
  946         struct uio uio;
  947         struct mbuf *m, *m2;
  948         struct ct_request *cr;
  949         int error, rcvflag, foundreq;
  950         uint32_t xid_plus_direction[2], header;
  951         SVCXPRT *xprt;
  952         struct cf_conn *cd;
  953         u_int rawlen;
  954         struct cmsghdr *cmsg;
  955         struct tls_get_record tgr;
  956 
  957         /*
  958          * RPC-over-TLS needs to block reception during
  959          * upcalls since the upcall will be doing I/O on
  960          * the socket via openssl library calls.
  961          */
  962         mtx_lock(&ct->ct_lock);
  963         if ((ct->ct_rcvstate & (RPCRCVSTATE_NORMAL |
  964             RPCRCVSTATE_NONAPPDATA)) == 0) {
  965                 /* Mark that a socket upcall needs to be done. */
  966                 if ((ct->ct_rcvstate & (RPCRCVSTATE_UPCALLNEEDED |
  967                     RPCRCVSTATE_UPCALLINPROG)) != 0)
  968                         ct->ct_rcvstate |= RPCRCVSTATE_SOUPCALLNEEDED;
  969                 mtx_unlock(&ct->ct_lock);
  970                 return (SU_OK);
  971         }
  972         mtx_unlock(&ct->ct_lock);
  973 
  974         /*
  975          * If another thread is already here, it must be in
  976          * soreceive(), so just return to avoid races with it.
  977          * ct_upcallrefs is protected by the SOCKBUF_LOCK(),
  978          * which is held in this function, except when
  979          * soreceive() is called.
  980          */
  981         if (ct->ct_upcallrefs > 0)
  982                 return (SU_OK);
  983         ct->ct_upcallrefs++;
  984 
  985         /*
  986          * Read as much as possible off the socket and link it
  987          * onto ct_raw.
  988          */
  989         for (;;) {
  990                 uio.uio_resid = 1000000000;
  991                 uio.uio_td = curthread;
  992                 m2 = m = NULL;
  993                 rcvflag = MSG_DONTWAIT | MSG_SOCALLBCK;
  994                 if (ct->ct_sslrefno != 0 && (ct->ct_rcvstate &
  995                     RPCRCVSTATE_NORMAL) != 0)
  996                         rcvflag |= MSG_TLSAPPDATA;
  997                 SOCKBUF_UNLOCK(&so->so_rcv);
  998                 error = soreceive(so, NULL, &uio, &m, &m2, &rcvflag);
  999                 SOCKBUF_LOCK(&so->so_rcv);
 1000 
 1001                 if (error == EWOULDBLOCK) {
 1002                         /*
 1003                          * We must re-test for readability after
 1004                          * taking the lock to protect us in the case
 1005                          * where a new packet arrives on the socket
 1006                          * after our call to soreceive fails with
 1007                          * EWOULDBLOCK.
 1008                          */
 1009                         error = 0;
 1010                         if (!soreadable(so))
 1011                                 break;
 1012                         continue;
 1013                 }
 1014                 if (error == 0 && m == NULL) {
 1015                         /*
 1016                          * We must have got EOF trying
 1017                          * to read from the stream.
 1018                          */
 1019                         error = ECONNRESET;
 1020                 }
 1021 
 1022                 /*
 1023                  * A return of ENXIO indicates that there is an
 1024                  * alert record at the head of the
 1025                  * socket's receive queue, for TLS connections.
 1026                  * This record needs to be handled in userland
 1027                  * via an SSL_read() call, so do an upcall to the daemon.
 1028                  */
 1029                 if (ct->ct_sslrefno != 0 && error == ENXIO) {
 1030                         /* Disable reception, marking an upcall needed. */
 1031                         mtx_lock(&ct->ct_lock);
 1032                         ct->ct_rcvstate |= RPCRCVSTATE_UPCALLNEEDED;
 1033                         /*
 1034                          * If an upcall in needed, wake up the kthread
 1035                          * that runs clnt_vc_dotlsupcall().
 1036                          */
 1037                         wakeup(&ct->ct_sslrefno);
 1038                         mtx_unlock(&ct->ct_lock);
 1039                         break;
 1040                 }
 1041                 if (error != 0)
 1042                         break;
 1043 
 1044                 /* Process any record header(s). */
 1045                 if (m2 != NULL) {
 1046                         cmsg = mtod(m2, struct cmsghdr *);
 1047                         if (cmsg->cmsg_type == TLS_GET_RECORD &&
 1048                             cmsg->cmsg_len == CMSG_LEN(sizeof(tgr))) {
 1049                                 memcpy(&tgr, CMSG_DATA(cmsg), sizeof(tgr));
 1050                                 /*
 1051                                  * TLS_RLTYPE_ALERT records should be handled
 1052                                  * since soreceive() would have returned
 1053                                  * ENXIO.  Just throw any other
 1054                                  * non-TLS_RLTYPE_APP records away.
 1055                                  */
 1056                                 if (tgr.tls_type != TLS_RLTYPE_APP) {
 1057                                         m_freem(m);
 1058                                         m_free(m2);
 1059                                         mtx_lock(&ct->ct_lock);
 1060                                         ct->ct_rcvstate &=
 1061                                             ~RPCRCVSTATE_NONAPPDATA;
 1062                                         ct->ct_rcvstate |= RPCRCVSTATE_NORMAL;
 1063                                         mtx_unlock(&ct->ct_lock);
 1064                                         continue;
 1065                                 }
 1066                         }
 1067                         m_free(m2);
 1068                 }
 1069 
 1070                 if (ct->ct_raw != NULL)
 1071                         m_last(ct->ct_raw)->m_next = m;
 1072                 else
 1073                         ct->ct_raw = m;
 1074         }
 1075         rawlen = m_length(ct->ct_raw, NULL);
 1076 
 1077         /* Now, process as much of ct_raw as possible. */
 1078         for (;;) {
 1079                 /*
 1080                  * If ct_record_resid is zero, we are waiting for a
 1081                  * record mark.
 1082                  */
 1083                 if (ct->ct_record_resid == 0) {
 1084                         if (rawlen < sizeof(uint32_t))
 1085                                 break;
 1086                         m_copydata(ct->ct_raw, 0, sizeof(uint32_t),
 1087                             (char *)&header);
 1088                         header = ntohl(header);
 1089                         ct->ct_record_resid = header & 0x7fffffff;
 1090                         ct->ct_record_eor = ((header & 0x80000000) != 0);
 1091                         m_adj(ct->ct_raw, sizeof(uint32_t));
 1092                         rawlen -= sizeof(uint32_t);
 1093                 } else {
 1094                         /*
 1095                          * Move as much of the record as possible to
 1096                          * ct_record.
 1097                          */
 1098                         if (rawlen == 0)
 1099                                 break;
 1100                         if (rawlen <= ct->ct_record_resid) {
 1101                                 if (ct->ct_record != NULL)
 1102                                         m_last(ct->ct_record)->m_next =
 1103                                             ct->ct_raw;
 1104                                 else
 1105                                         ct->ct_record = ct->ct_raw;
 1106                                 ct->ct_raw = NULL;
 1107                                 ct->ct_record_resid -= rawlen;
 1108                                 rawlen = 0;
 1109                         } else {
 1110                                 m = m_split(ct->ct_raw, ct->ct_record_resid,
 1111                                     M_NOWAIT);
 1112                                 if (m == NULL)
 1113                                         break;
 1114                                 if (ct->ct_record != NULL)
 1115                                         m_last(ct->ct_record)->m_next =
 1116                                             ct->ct_raw;
 1117                                 else
 1118                                         ct->ct_record = ct->ct_raw;
 1119                                 rawlen -= ct->ct_record_resid;
 1120                                 ct->ct_record_resid = 0;
 1121                                 ct->ct_raw = m;
 1122                         }
 1123                         if (ct->ct_record_resid > 0)
 1124                                 break;
 1125 
 1126                         /*
 1127                          * If we have the entire record, see if we can
 1128                          * match it to a request.
 1129                          */
 1130                         if (ct->ct_record_eor) {
 1131                                 /*
 1132                                  * The XID is in the first uint32_t of
 1133                                  * the reply and the message direction
 1134                                  * is the second one.
 1135                                  */
 1136                                 if (ct->ct_record->m_len <
 1137                                     sizeof(xid_plus_direction) &&
 1138                                     m_length(ct->ct_record, NULL) <
 1139                                     sizeof(xid_plus_direction)) {
 1140                                         /*
 1141                                          * What to do now?
 1142                                          * The data in the TCP stream is
 1143                                          * corrupted such that there is no
 1144                                          * valid RPC message to parse.
 1145                                          * I think it best to close this
 1146                                          * connection and allow
 1147                                          * clnt_reconnect_call() to try
 1148                                          * and establish a new one.
 1149                                          */
 1150                                         printf("clnt_vc_soupcall: "
 1151                                             "connection data corrupted\n");
 1152                                         error = ECONNRESET;
 1153                                         goto wakeup_all;
 1154                                 }
 1155                                 m_copydata(ct->ct_record, 0,
 1156                                     sizeof(xid_plus_direction),
 1157                                     (char *)xid_plus_direction);
 1158                                 xid_plus_direction[0] =
 1159                                     ntohl(xid_plus_direction[0]);
 1160                                 xid_plus_direction[1] =
 1161                                     ntohl(xid_plus_direction[1]);
 1162                                 /* Check message direction. */
 1163                                 if (xid_plus_direction[1] == CALL) {
 1164                                         /* This is a backchannel request. */
 1165                                         mtx_lock(&ct->ct_lock);
 1166                                         xprt = ct->ct_backchannelxprt;
 1167                                         if (xprt == NULL) {
 1168                                                 mtx_unlock(&ct->ct_lock);
 1169                                                 /* Just throw it away. */
 1170                                                 m_freem(ct->ct_record);
 1171                                                 ct->ct_record = NULL;
 1172                                         } else {
 1173                                                 cd = (struct cf_conn *)
 1174                                                     xprt->xp_p1;
 1175                                                 m2 = cd->mreq;
 1176                                                 /*
 1177                                                  * The requests are chained
 1178                                                  * in the m_nextpkt list.
 1179                                                  */
 1180                                                 while (m2 != NULL &&
 1181                                                     m2->m_nextpkt != NULL)
 1182                                                         /* Find end of list. */
 1183                                                         m2 = m2->m_nextpkt;
 1184                                                 if (m2 != NULL)
 1185                                                         m2->m_nextpkt =
 1186                                                             ct->ct_record;
 1187                                                 else
 1188                                                         cd->mreq =
 1189                                                             ct->ct_record;
 1190                                                 ct->ct_record->m_nextpkt =
 1191                                                     NULL;
 1192                                                 ct->ct_record = NULL;
 1193                                                 xprt_active(xprt);
 1194                                                 mtx_unlock(&ct->ct_lock);
 1195                                         }
 1196                                 } else {
 1197                                         mtx_lock(&ct->ct_lock);
 1198                                         foundreq = 0;
 1199                                         TAILQ_FOREACH(cr, &ct->ct_pending,
 1200                                             cr_link) {
 1201                                                 if (cr->cr_xid ==
 1202                                                     xid_plus_direction[0]) {
 1203                                                         /*
 1204                                                          * This one
 1205                                                          * matches. We leave
 1206                                                          * the reply mbuf in
 1207                                                          * cr->cr_mrep. Set
 1208                                                          * the XID to zero so
 1209                                                          * that we will ignore
 1210                                                          * any duplicated
 1211                                                          * replies.
 1212                                                          */
 1213                                                         cr->cr_xid = 0;
 1214                                                         cr->cr_mrep =
 1215                                                             ct->ct_record;
 1216                                                         cr->cr_error = 0;
 1217                                                         foundreq = 1;
 1218                                                         wakeup(cr);
 1219                                                         break;
 1220                                                 }
 1221                                         }
 1222                                         mtx_unlock(&ct->ct_lock);
 1223 
 1224                                         if (!foundreq)
 1225                                                 m_freem(ct->ct_record);
 1226                                         ct->ct_record = NULL;
 1227                                 }
 1228                         }
 1229                 }
 1230         }
 1231 
 1232         if (error != 0) {
 1233         wakeup_all:
 1234                 /*
 1235                  * This socket is broken, so mark that it cannot
 1236                  * receive and fail all RPCs waiting for a reply
 1237                  * on it, so that they will be retried on a new
 1238                  * TCP connection created by clnt_reconnect_X().
 1239                  */
 1240                 mtx_lock(&ct->ct_lock);
 1241                 ct->ct_error.re_status = RPC_CANTRECV;
 1242                 ct->ct_error.re_errno = error;
 1243                 TAILQ_FOREACH(cr, &ct->ct_pending, cr_link) {
 1244                         cr->cr_error = error;
 1245                         wakeup(cr);
 1246                 }
 1247                 mtx_unlock(&ct->ct_lock);
 1248         }
 1249 
 1250         ct->ct_upcallrefs--;
 1251         if (ct->ct_upcallrefs < 0)
 1252                 panic("rpcvc upcall refcnt");
 1253         if (ct->ct_upcallrefs == 0)
 1254                 wakeup(&ct->ct_upcallrefs);
 1255         return (SU_OK);
 1256 }
 1257 
 1258 /*
 1259  * Wait for all upcalls in progress to complete.
 1260  */
 1261 static void
 1262 clnt_vc_upcallsdone(struct ct_data *ct)
 1263 {
 1264 
 1265         SOCKBUF_LOCK_ASSERT(&ct->ct_socket->so_rcv);
 1266 
 1267         while (ct->ct_upcallrefs > 0)
 1268                 (void) msleep(&ct->ct_upcallrefs,
 1269                     SOCKBUF_MTX(&ct->ct_socket->so_rcv), 0, "rpcvcup", 0);
 1270 }
 1271 
 1272 /*
 1273  * Do a TLS upcall to the rpctlscd daemon, as required.
 1274  * This function runs as a kthread.
 1275  */
 1276 static void
 1277 clnt_vc_dotlsupcall(void *data)
 1278 {
 1279         struct ct_data *ct = (struct ct_data *)data;
 1280         enum clnt_stat ret;
 1281         uint32_t reterr;
 1282 
 1283         mtx_lock(&ct->ct_lock);
 1284         ct->ct_rcvstate |= RPCRCVSTATE_UPCALLTHREAD;
 1285         while (!ct->ct_closed) {
 1286                 if ((ct->ct_rcvstate & RPCRCVSTATE_UPCALLNEEDED) != 0) {
 1287                         ct->ct_rcvstate &= ~RPCRCVSTATE_UPCALLNEEDED;
 1288                         ct->ct_rcvstate |= RPCRCVSTATE_UPCALLINPROG;
 1289                         if (ct->ct_sslrefno != 0 && ct->ct_sslrefno !=
 1290                             RPCTLS_REFNO_HANDSHAKE) {
 1291                                 mtx_unlock(&ct->ct_lock);
 1292                                 ret = rpctls_cl_handlerecord(ct->ct_sslsec,
 1293                                     ct->ct_sslusec, ct->ct_sslrefno, &reterr);
 1294                                 mtx_lock(&ct->ct_lock);
 1295                         }
 1296                         ct->ct_rcvstate &= ~RPCRCVSTATE_UPCALLINPROG;
 1297                         if (ret == RPC_SUCCESS && reterr == RPCTLSERR_OK)
 1298                                 ct->ct_rcvstate |= RPCRCVSTATE_NORMAL;
 1299                         else
 1300                                 ct->ct_rcvstate |= RPCRCVSTATE_NONAPPDATA;
 1301                         wakeup(&ct->ct_rcvstate);
 1302                 }
 1303                 if ((ct->ct_rcvstate & RPCRCVSTATE_SOUPCALLNEEDED) != 0) {
 1304                         ct->ct_rcvstate &= ~RPCRCVSTATE_SOUPCALLNEEDED;
 1305                         mtx_unlock(&ct->ct_lock);
 1306                         SOCKBUF_LOCK(&ct->ct_socket->so_rcv);
 1307                         clnt_vc_soupcall(ct->ct_socket, ct, M_NOWAIT);
 1308                         SOCKBUF_UNLOCK(&ct->ct_socket->so_rcv);
 1309                         mtx_lock(&ct->ct_lock);
 1310                 }
 1311                 msleep(&ct->ct_sslrefno, &ct->ct_lock, 0, "clntvcdu", hz);
 1312         }
 1313         ct->ct_rcvstate &= ~RPCRCVSTATE_UPCALLTHREAD;
 1314         wakeup(&ct->ct_sslrefno);
 1315         mtx_unlock(&ct->ct_lock);
 1316         kthread_exit();
 1317 }

Cache object: 22fc2d19d88752d01b8088971fbe8aa6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.