]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/rpc/clnt_vc.c
Add UPDATING entries and bump version.
[FreeBSD/FreeBSD.git] / sys / rpc / clnt_vc.c
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 <sys/param.h>
61 #include <sys/systm.h>
62 #include <sys/kernel.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
85 struct cmessage {
86         struct cmsghdr cmsg;
87         struct cmsgcred cmcred;
88 };
89
90 static enum clnt_stat clnt_vc_call(CLIENT *, struct rpc_callextra *,
91     rpcproc_t, struct mbuf *, struct mbuf **, struct timeval);
92 static void clnt_vc_geterr(CLIENT *, struct rpc_err *);
93 static bool_t clnt_vc_freeres(CLIENT *, xdrproc_t, void *);
94 static void clnt_vc_abort(CLIENT *);
95 static bool_t clnt_vc_control(CLIENT *, u_int, void *);
96 static void clnt_vc_close(CLIENT *);
97 static void clnt_vc_destroy(CLIENT *);
98 static bool_t time_not_ok(struct timeval *);
99 static int clnt_vc_soupcall(struct socket *so, void *arg, int waitflag);
100
101 static struct clnt_ops clnt_vc_ops = {
102         .cl_call =      clnt_vc_call,
103         .cl_abort =     clnt_vc_abort,
104         .cl_geterr =    clnt_vc_geterr,
105         .cl_freeres =   clnt_vc_freeres,
106         .cl_close =     clnt_vc_close,
107         .cl_destroy =   clnt_vc_destroy,
108         .cl_control =   clnt_vc_control
109 };
110
111 static void clnt_vc_upcallsdone(struct ct_data *);
112
113 static int      fake_wchan;
114
115 /*
116  * Create a client handle for a connection.
117  * Default options are set, which the user can change using clnt_control()'s.
118  * The rpc/vc package does buffering similar to stdio, so the client
119  * must pick send and receive buffer sizes, 0 => use the default.
120  * NB: fd is copied into a private area.
121  * NB: The rpch->cl_auth is set null authentication. Caller may wish to
122  * set this something more useful.
123  *
124  * fd should be an open socket
125  */
126 CLIENT *
127 clnt_vc_create(
128         struct socket *so,              /* open file descriptor */
129         struct sockaddr *raddr,         /* servers address */
130         const rpcprog_t prog,           /* program number */
131         const rpcvers_t vers,           /* version number */
132         size_t sendsz,                  /* buffer recv size */
133         size_t recvsz,                  /* buffer send size */
134         int intrflag)                   /* interruptible */
135 {
136         CLIENT *cl;                     /* client handle */
137         struct ct_data *ct = NULL;      /* client handle */
138         struct timeval now;
139         struct rpc_msg call_msg;
140         static uint32_t disrupt;
141         struct __rpc_sockinfo si;
142         XDR xdrs;
143         int error, interrupted, one = 1, sleep_flag;
144         struct sockopt sopt;
145
146         if (disrupt == 0)
147                 disrupt = (uint32_t)(long)raddr;
148
149         cl = (CLIENT *)mem_alloc(sizeof (*cl));
150         ct = (struct ct_data *)mem_alloc(sizeof (*ct));
151
152         mtx_init(&ct->ct_lock, "ct->ct_lock", NULL, MTX_DEF);
153         ct->ct_threads = 0;
154         ct->ct_closing = FALSE;
155         ct->ct_closed = FALSE;
156         ct->ct_upcallrefs = 0;
157
158         if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
159                 error = soconnect(so, raddr, curthread);
160                 SOCK_LOCK(so);
161                 interrupted = 0;
162                 sleep_flag = PSOCK;
163                 if (intrflag != 0)
164                         sleep_flag |= PCATCH;
165                 while ((so->so_state & SS_ISCONNECTING)
166                     && so->so_error == 0) {
167                         error = msleep(&so->so_timeo, SOCK_MTX(so),
168                             sleep_flag, "connec", 0);
169                         if (error) {
170                                 if (error == EINTR || error == ERESTART)
171                                         interrupted = 1;
172                                 break;
173                         }
174                 }
175                 if (error == 0) {
176                         error = so->so_error;
177                         so->so_error = 0;
178                 }
179                 SOCK_UNLOCK(so);
180                 if (error) {
181                         if (!interrupted)
182                                 so->so_state &= ~SS_ISCONNECTING;
183                         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
184                         rpc_createerr.cf_error.re_errno = error;
185                         goto err;
186                 }
187         }
188
189         if (!__rpc_socket2sockinfo(so, &si)) {
190                 goto err;
191         }
192
193         if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
194                 bzero(&sopt, sizeof(sopt));
195                 sopt.sopt_dir = SOPT_SET;
196                 sopt.sopt_level = SOL_SOCKET;
197                 sopt.sopt_name = SO_KEEPALIVE;
198                 sopt.sopt_val = &one;
199                 sopt.sopt_valsize = sizeof(one);
200                 sosetopt(so, &sopt);
201         }
202
203         if (so->so_proto->pr_protocol == IPPROTO_TCP) {
204                 bzero(&sopt, sizeof(sopt));
205                 sopt.sopt_dir = SOPT_SET;
206                 sopt.sopt_level = IPPROTO_TCP;
207                 sopt.sopt_name = TCP_NODELAY;
208                 sopt.sopt_val = &one;
209                 sopt.sopt_valsize = sizeof(one);
210                 sosetopt(so, &sopt);
211         }
212
213         ct->ct_closeit = FALSE;
214
215         /*
216          * Set up private data struct
217          */
218         ct->ct_socket = so;
219         ct->ct_wait.tv_sec = -1;
220         ct->ct_wait.tv_usec = -1;
221         memcpy(&ct->ct_addr, raddr, raddr->sa_len);
222
223         /*
224          * Initialize call message
225          */
226         getmicrotime(&now);
227         ct->ct_xid = ((uint32_t)++disrupt) ^ __RPC_GETXID(&now);
228         call_msg.rm_xid = ct->ct_xid;
229         call_msg.rm_direction = CALL;
230         call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
231         call_msg.rm_call.cb_prog = (uint32_t)prog;
232         call_msg.rm_call.cb_vers = (uint32_t)vers;
233
234         /*
235          * pre-serialize the static part of the call msg and stash it away
236          */
237         xdrmem_create(&xdrs, ct->ct_mcallc, MCALL_MSG_SIZE,
238             XDR_ENCODE);
239         if (! xdr_callhdr(&xdrs, &call_msg)) {
240                 if (ct->ct_closeit) {
241                         soclose(ct->ct_socket);
242                 }
243                 goto err;
244         }
245         ct->ct_mpos = XDR_GETPOS(&xdrs);
246         XDR_DESTROY(&xdrs);
247         ct->ct_waitchan = "rpcrecv";
248         ct->ct_waitflag = 0;
249
250         /*
251          * Create a client handle which uses xdrrec for serialization
252          * and authnone for authentication.
253          */
254         sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
255         recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
256         error = soreserve(ct->ct_socket, sendsz, recvsz);
257         if (error != 0) {
258                 if (ct->ct_closeit) {
259                         soclose(ct->ct_socket);
260                 }
261                 goto err;
262         }
263         cl->cl_refs = 1;
264         cl->cl_ops = &clnt_vc_ops;
265         cl->cl_private = ct;
266         cl->cl_auth = authnone_create();
267
268         SOCKBUF_LOCK(&ct->ct_socket->so_rcv);
269         soupcall_set(ct->ct_socket, SO_RCV, clnt_vc_soupcall, ct);
270         SOCKBUF_UNLOCK(&ct->ct_socket->so_rcv);
271
272         ct->ct_record = NULL;
273         ct->ct_record_resid = 0;
274         TAILQ_INIT(&ct->ct_pending);
275         return (cl);
276
277 err:
278         mtx_destroy(&ct->ct_lock);
279         mem_free(ct, sizeof (struct ct_data));
280         mem_free(cl, sizeof (CLIENT));
281
282         return ((CLIENT *)NULL);
283 }
284
285 static enum clnt_stat
286 clnt_vc_call(
287         CLIENT          *cl,            /* client handle */
288         struct rpc_callextra *ext,      /* call metadata */
289         rpcproc_t       proc,           /* procedure number */
290         struct mbuf     *args,          /* pointer to args */
291         struct mbuf     **resultsp,     /* pointer to results */
292         struct timeval  utimeout)
293 {
294         struct ct_data *ct = (struct ct_data *) cl->cl_private;
295         AUTH *auth;
296         struct rpc_err *errp;
297         enum clnt_stat stat;
298         XDR xdrs;
299         struct rpc_msg reply_msg;
300         bool_t ok;
301         int nrefreshes = 2;             /* number of times to refresh cred */
302         struct timeval timeout;
303         uint32_t xid;
304         struct mbuf *mreq = NULL, *results;
305         struct ct_request *cr;
306         int error, trycnt;
307
308         cr = malloc(sizeof(struct ct_request), M_RPC, M_WAITOK);
309
310         mtx_lock(&ct->ct_lock);
311
312         if (ct->ct_closing || ct->ct_closed) {
313                 mtx_unlock(&ct->ct_lock);
314                 free(cr, M_RPC);
315                 return (RPC_CANTSEND);
316         }
317         ct->ct_threads++;
318
319         if (ext) {
320                 auth = ext->rc_auth;
321                 errp = &ext->rc_err;
322         } else {
323                 auth = cl->cl_auth;
324                 errp = &ct->ct_error;
325         }
326
327         cr->cr_mrep = NULL;
328         cr->cr_error = 0;
329
330         if (ct->ct_wait.tv_usec == -1) {
331                 timeout = utimeout;     /* use supplied timeout */
332         } else {
333                 timeout = ct->ct_wait;  /* use default timeout */
334         }
335
336         /*
337          * After 15sec of looping, allow it to return RPC_CANTSEND, which will
338          * cause the clnt_reconnect layer to create a new TCP connection.
339          */
340         trycnt = 15 * hz;
341 call_again:
342         mtx_assert(&ct->ct_lock, MA_OWNED);
343         if (ct->ct_closing || ct->ct_closed) {
344                 ct->ct_threads--;
345                 wakeup(ct);
346                 mtx_unlock(&ct->ct_lock);
347                 free(cr, M_RPC);
348                 return (RPC_CANTSEND);
349         }
350
351         ct->ct_xid++;
352         xid = ct->ct_xid;
353
354         mtx_unlock(&ct->ct_lock);
355
356         /*
357          * Leave space to pre-pend the record mark.
358          */
359         mreq = m_gethdr(M_WAITOK, MT_DATA);
360         mreq->m_data += sizeof(uint32_t);
361         KASSERT(ct->ct_mpos + sizeof(uint32_t) <= MHLEN,
362             ("RPC header too big"));
363         bcopy(ct->ct_mcallc, mreq->m_data, ct->ct_mpos);
364         mreq->m_len = ct->ct_mpos;
365
366         /*
367          * The XID is the first thing in the request.
368          */
369         *mtod(mreq, uint32_t *) = htonl(xid);
370
371         xdrmbuf_create(&xdrs, mreq, XDR_ENCODE);
372
373         errp->re_status = stat = RPC_SUCCESS;
374
375         if ((! XDR_PUTINT32(&xdrs, &proc)) ||
376             (! AUTH_MARSHALL(auth, xid, &xdrs,
377                 m_copym(args, 0, M_COPYALL, M_WAITOK)))) {
378                 errp->re_status = stat = RPC_CANTENCODEARGS;
379                 mtx_lock(&ct->ct_lock);
380                 goto out;
381         }
382         mreq->m_pkthdr.len = m_length(mreq, NULL);
383
384         /*
385          * Prepend a record marker containing the packet length.
386          */
387         M_PREPEND(mreq, sizeof(uint32_t), M_WAITOK);
388         *mtod(mreq, uint32_t *) =
389                 htonl(0x80000000 | (mreq->m_pkthdr.len - sizeof(uint32_t)));
390
391         cr->cr_xid = xid;
392         mtx_lock(&ct->ct_lock);
393         /*
394          * Check to see if the other end has already started to close down
395          * the connection. The upcall will have set ct_error.re_status
396          * to RPC_CANTRECV if this is the case.
397          * If the other end starts to close down the connection after this
398          * point, it will be detected later when cr_error is checked,
399          * since the request is in the ct_pending queue.
400          */
401         if (ct->ct_error.re_status == RPC_CANTRECV) {
402                 if (errp != &ct->ct_error) {
403                         errp->re_errno = ct->ct_error.re_errno;
404                         errp->re_status = RPC_CANTRECV;
405                 }
406                 stat = RPC_CANTRECV;
407                 goto out;
408         }
409         TAILQ_INSERT_TAIL(&ct->ct_pending, cr, cr_link);
410         mtx_unlock(&ct->ct_lock);
411
412         /*
413          * sosend consumes mreq.
414          */
415         error = sosend(ct->ct_socket, NULL, NULL, mreq, NULL, 0, curthread);
416         mreq = NULL;
417         if (error == EMSGSIZE || (error == ERESTART &&
418             (ct->ct_waitflag & PCATCH) == 0 && trycnt-- > 0)) {
419                 SOCKBUF_LOCK(&ct->ct_socket->so_snd);
420                 sbwait(&ct->ct_socket->so_snd);
421                 SOCKBUF_UNLOCK(&ct->ct_socket->so_snd);
422                 AUTH_VALIDATE(auth, xid, NULL, NULL);
423                 mtx_lock(&ct->ct_lock);
424                 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
425                 /* Sleep for 1 clock tick before trying the sosend() again. */
426                 msleep(&fake_wchan, &ct->ct_lock, 0, "rpclpsnd", 1);
427                 goto call_again;
428         }
429
430         reply_msg.acpted_rply.ar_verf.oa_flavor = AUTH_NULL;
431         reply_msg.acpted_rply.ar_verf.oa_base = cr->cr_verf;
432         reply_msg.acpted_rply.ar_verf.oa_length = 0;
433         reply_msg.acpted_rply.ar_results.where = NULL;
434         reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
435
436         mtx_lock(&ct->ct_lock);
437         if (error) {
438                 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
439                 errp->re_errno = error;
440                 errp->re_status = stat = RPC_CANTSEND;
441                 goto out;
442         }
443
444         /*
445          * Check to see if we got an upcall while waiting for the
446          * lock. In both these cases, the request has been removed
447          * from ct->ct_pending.
448          */
449         if (cr->cr_error) {
450                 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
451                 errp->re_errno = cr->cr_error;
452                 errp->re_status = stat = RPC_CANTRECV;
453                 goto out;
454         }
455         if (cr->cr_mrep) {
456                 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
457                 goto got_reply;
458         }
459
460         /*
461          * Hack to provide rpc-based message passing
462          */
463         if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
464                 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
465                 errp->re_status = stat = RPC_TIMEDOUT;
466                 goto out;
467         }
468
469         error = msleep(cr, &ct->ct_lock, ct->ct_waitflag, ct->ct_waitchan,
470             tvtohz(&timeout));
471
472         TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
473
474         if (error) {
475                 /*
476                  * The sleep returned an error so our request is still
477                  * on the list. Turn the error code into an
478                  * appropriate client status.
479                  */
480                 errp->re_errno = error;
481                 switch (error) {
482                 case EINTR:
483                         stat = RPC_INTR;
484                         break;
485                 case EWOULDBLOCK:
486                         stat = RPC_TIMEDOUT;
487                         break;
488                 default:
489                         stat = RPC_CANTRECV;
490                 }
491                 errp->re_status = stat;
492                 goto out;
493         } else {
494                 /*
495                  * We were woken up by the upcall.  If the
496                  * upcall had a receive error, report that,
497                  * otherwise we have a reply.
498                  */
499                 if (cr->cr_error) {
500                         errp->re_errno = cr->cr_error;
501                         errp->re_status = stat = RPC_CANTRECV;
502                         goto out;
503                 }
504         }
505
506 got_reply:
507         /*
508          * Now decode and validate the response. We need to drop the
509          * lock since xdr_replymsg may end up sleeping in malloc.
510          */
511         mtx_unlock(&ct->ct_lock);
512
513         if (ext && ext->rc_feedback)
514                 ext->rc_feedback(FEEDBACK_OK, proc, ext->rc_feedback_arg);
515
516         xdrmbuf_create(&xdrs, cr->cr_mrep, XDR_DECODE);
517         ok = xdr_replymsg(&xdrs, &reply_msg);
518         cr->cr_mrep = NULL;
519
520         if (ok) {
521                 if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
522                     (reply_msg.acpted_rply.ar_stat == SUCCESS))
523                         errp->re_status = stat = RPC_SUCCESS;
524                 else
525                         stat = _seterr_reply(&reply_msg, errp);
526
527                 if (stat == RPC_SUCCESS) {
528                         results = xdrmbuf_getall(&xdrs);
529                         if (!AUTH_VALIDATE(auth, xid,
530                                 &reply_msg.acpted_rply.ar_verf,
531                                 &results)) {
532                                 errp->re_status = stat = RPC_AUTHERROR;
533                                 errp->re_why = AUTH_INVALIDRESP;
534                         } else {
535                                 KASSERT(results,
536                                     ("auth validated but no result"));
537                                 *resultsp = results;
538                         }
539                 }               /* end successful completion */
540                 /*
541                  * If unsuccessful AND error is an authentication error
542                  * then refresh credentials and try again, else break
543                  */
544                 else if (stat == RPC_AUTHERROR)
545                         /* maybe our credentials need to be refreshed ... */
546                         if (nrefreshes > 0 &&
547                             AUTH_REFRESH(auth, &reply_msg)) {
548                                 nrefreshes--;
549                                 XDR_DESTROY(&xdrs);
550                                 mtx_lock(&ct->ct_lock);
551                                 goto call_again;
552                         }
553                 /* end of unsuccessful completion */
554         }       /* end of valid reply message */
555         else {
556                 errp->re_status = stat = RPC_CANTDECODERES;
557         }
558         XDR_DESTROY(&xdrs);
559         mtx_lock(&ct->ct_lock);
560 out:
561         mtx_assert(&ct->ct_lock, MA_OWNED);
562
563         KASSERT(stat != RPC_SUCCESS || *resultsp,
564             ("RPC_SUCCESS without reply"));
565
566         if (mreq)
567                 m_freem(mreq);
568         if (cr->cr_mrep)
569                 m_freem(cr->cr_mrep);
570
571         ct->ct_threads--;
572         if (ct->ct_closing)
573                 wakeup(ct);
574                 
575         mtx_unlock(&ct->ct_lock);
576
577         if (auth && stat != RPC_SUCCESS)
578                 AUTH_VALIDATE(auth, xid, NULL, NULL);
579
580         free(cr, M_RPC);
581
582         return (stat);
583 }
584
585 static void
586 clnt_vc_geterr(CLIENT *cl, struct rpc_err *errp)
587 {
588         struct ct_data *ct = (struct ct_data *) cl->cl_private;
589
590         *errp = ct->ct_error;
591 }
592
593 static bool_t
594 clnt_vc_freeres(CLIENT *cl, xdrproc_t xdr_res, void *res_ptr)
595 {
596         XDR xdrs;
597         bool_t dummy;
598
599         xdrs.x_op = XDR_FREE;
600         dummy = (*xdr_res)(&xdrs, res_ptr);
601
602         return (dummy);
603 }
604
605 /*ARGSUSED*/
606 static void
607 clnt_vc_abort(CLIENT *cl)
608 {
609 }
610
611 static bool_t
612 clnt_vc_control(CLIENT *cl, u_int request, void *info)
613 {
614         struct ct_data *ct = (struct ct_data *)cl->cl_private;
615         void *infop = info;
616         SVCXPRT *xprt;
617
618         mtx_lock(&ct->ct_lock);
619
620         switch (request) {
621         case CLSET_FD_CLOSE:
622                 ct->ct_closeit = TRUE;
623                 mtx_unlock(&ct->ct_lock);
624                 return (TRUE);
625         case CLSET_FD_NCLOSE:
626                 ct->ct_closeit = FALSE;
627                 mtx_unlock(&ct->ct_lock);
628                 return (TRUE);
629         default:
630                 break;
631         }
632
633         /* for other requests which use info */
634         if (info == NULL) {
635                 mtx_unlock(&ct->ct_lock);
636                 return (FALSE);
637         }
638         switch (request) {
639         case CLSET_TIMEOUT:
640                 if (time_not_ok((struct timeval *)info)) {
641                         mtx_unlock(&ct->ct_lock);
642                         return (FALSE);
643                 }
644                 ct->ct_wait = *(struct timeval *)infop;
645                 break;
646         case CLGET_TIMEOUT:
647                 *(struct timeval *)infop = ct->ct_wait;
648                 break;
649         case CLGET_SERVER_ADDR:
650                 (void) memcpy(info, &ct->ct_addr, (size_t)ct->ct_addr.ss_len);
651                 break;
652         case CLGET_SVC_ADDR:
653                 /*
654                  * Slightly different semantics to userland - we use
655                  * sockaddr instead of netbuf.
656                  */
657                 memcpy(info, &ct->ct_addr, ct->ct_addr.ss_len);
658                 break;
659         case CLSET_SVC_ADDR:            /* set to new address */
660                 mtx_unlock(&ct->ct_lock);
661                 return (FALSE);
662         case CLGET_XID:
663                 *(uint32_t *)info = ct->ct_xid;
664                 break;
665         case CLSET_XID:
666                 /* This will set the xid of the NEXT call */
667                 /* decrement by 1 as clnt_vc_call() increments once */
668                 ct->ct_xid = *(uint32_t *)info - 1;
669                 break;
670         case CLGET_VERS:
671                 /*
672                  * This RELIES on the information that, in the call body,
673                  * the version number field is the fifth field from the
674                  * beginning of the RPC header. MUST be changed if the
675                  * call_struct is changed
676                  */
677                 *(uint32_t *)info =
678                     ntohl(*(uint32_t *)(void *)(ct->ct_mcallc +
679                     4 * BYTES_PER_XDR_UNIT));
680                 break;
681
682         case CLSET_VERS:
683                 *(uint32_t *)(void *)(ct->ct_mcallc +
684                     4 * BYTES_PER_XDR_UNIT) =
685                     htonl(*(uint32_t *)info);
686                 break;
687
688         case CLGET_PROG:
689                 /*
690                  * This RELIES on the information that, in the call body,
691                  * the program number field is the fourth field from the
692                  * beginning of the RPC header. MUST be changed if the
693                  * call_struct is changed
694                  */
695                 *(uint32_t *)info =
696                     ntohl(*(uint32_t *)(void *)(ct->ct_mcallc +
697                     3 * BYTES_PER_XDR_UNIT));
698                 break;
699
700         case CLSET_PROG:
701                 *(uint32_t *)(void *)(ct->ct_mcallc +
702                     3 * BYTES_PER_XDR_UNIT) =
703                     htonl(*(uint32_t *)info);
704                 break;
705
706         case CLSET_WAITCHAN:
707                 ct->ct_waitchan = (const char *)info;
708                 break;
709
710         case CLGET_WAITCHAN:
711                 *(const char **) info = ct->ct_waitchan;
712                 break;
713
714         case CLSET_INTERRUPTIBLE:
715                 if (*(int *) info)
716                         ct->ct_waitflag = PCATCH;
717                 else
718                         ct->ct_waitflag = 0;
719                 break;
720
721         case CLGET_INTERRUPTIBLE:
722                 if (ct->ct_waitflag)
723                         *(int *) info = TRUE;
724                 else
725                         *(int *) info = FALSE;
726                 break;
727
728         case CLSET_BACKCHANNEL:
729                 xprt = (SVCXPRT *)info;
730                 if (ct->ct_backchannelxprt == NULL) {
731                         xprt->xp_p2 = ct;
732                         ct->ct_backchannelxprt = xprt;
733                 }
734                 break;
735
736         default:
737                 mtx_unlock(&ct->ct_lock);
738                 return (FALSE);
739         }
740
741         mtx_unlock(&ct->ct_lock);
742         return (TRUE);
743 }
744
745 static void
746 clnt_vc_close(CLIENT *cl)
747 {
748         struct ct_data *ct = (struct ct_data *) cl->cl_private;
749         struct ct_request *cr;
750
751         mtx_lock(&ct->ct_lock);
752
753         if (ct->ct_closed) {
754                 mtx_unlock(&ct->ct_lock);
755                 return;
756         }
757
758         if (ct->ct_closing) {
759                 while (ct->ct_closing)
760                         msleep(ct, &ct->ct_lock, 0, "rpcclose", 0);
761                 KASSERT(ct->ct_closed, ("client should be closed"));
762                 mtx_unlock(&ct->ct_lock);
763                 return;
764         }
765
766         if (ct->ct_socket) {
767                 ct->ct_closing = TRUE;
768                 mtx_unlock(&ct->ct_lock);
769
770                 SOCKBUF_LOCK(&ct->ct_socket->so_rcv);
771                 soupcall_clear(ct->ct_socket, SO_RCV);
772                 clnt_vc_upcallsdone(ct);
773                 SOCKBUF_UNLOCK(&ct->ct_socket->so_rcv);
774
775                 /*
776                  * Abort any pending requests and wait until everyone
777                  * has finished with clnt_vc_call.
778                  */
779                 mtx_lock(&ct->ct_lock);
780                 TAILQ_FOREACH(cr, &ct->ct_pending, cr_link) {
781                         cr->cr_xid = 0;
782                         cr->cr_error = ESHUTDOWN;
783                         wakeup(cr);
784                 }
785
786                 while (ct->ct_threads)
787                         msleep(ct, &ct->ct_lock, 0, "rpcclose", 0);
788         }
789
790         ct->ct_closing = FALSE;
791         ct->ct_closed = TRUE;
792         mtx_unlock(&ct->ct_lock);
793         wakeup(ct);
794 }
795
796 static void
797 clnt_vc_destroy(CLIENT *cl)
798 {
799         struct ct_data *ct = (struct ct_data *) cl->cl_private;
800         struct socket *so = NULL;
801         SVCXPRT *xprt;
802
803         clnt_vc_close(cl);
804
805         mtx_lock(&ct->ct_lock);
806         xprt = ct->ct_backchannelxprt;
807         ct->ct_backchannelxprt = NULL;
808         if (xprt != NULL) {
809                 mtx_unlock(&ct->ct_lock);       /* To avoid a LOR. */
810                 sx_xlock(&xprt->xp_lock);
811                 mtx_lock(&ct->ct_lock);
812                 xprt->xp_p2 = NULL;
813                 sx_xunlock(&xprt->xp_lock);
814         }
815
816         if (ct->ct_socket) {
817                 if (ct->ct_closeit) {
818                         so = ct->ct_socket;
819                 }
820         }
821
822         mtx_unlock(&ct->ct_lock);
823
824         mtx_destroy(&ct->ct_lock);
825         if (so) {
826                 soshutdown(so, SHUT_WR);
827                 soclose(so);
828         }
829         mem_free(ct, sizeof(struct ct_data));
830         if (cl->cl_netid && cl->cl_netid[0])
831                 mem_free(cl->cl_netid, strlen(cl->cl_netid) +1);
832         if (cl->cl_tp && cl->cl_tp[0])
833                 mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
834         mem_free(cl, sizeof(CLIENT));
835 }
836
837 /*
838  * Make sure that the time is not garbage.   -1 value is disallowed.
839  * Note this is different from time_not_ok in clnt_dg.c
840  */
841 static bool_t
842 time_not_ok(struct timeval *t)
843 {
844         return (t->tv_sec <= -1 || t->tv_sec > 100000000 ||
845                 t->tv_usec <= -1 || t->tv_usec > 1000000);
846 }
847
848 int
849 clnt_vc_soupcall(struct socket *so, void *arg, int waitflag)
850 {
851         struct ct_data *ct = (struct ct_data *) arg;
852         struct uio uio;
853         struct mbuf *m, *m2;
854         struct ct_request *cr;
855         int error, rcvflag, foundreq;
856         uint32_t xid_plus_direction[2], header;
857         bool_t do_read;
858         SVCXPRT *xprt;
859         struct cf_conn *cd;
860
861         CTASSERT(sizeof(xid_plus_direction) == 2 * sizeof(uint32_t));
862         ct->ct_upcallrefs++;
863         uio.uio_td = curthread;
864         do {
865                 /*
866                  * If ct_record_resid is zero, we are waiting for a
867                  * record mark.
868                  */
869                 if (ct->ct_record_resid == 0) {
870
871                         /*
872                          * Make sure there is either a whole record
873                          * mark in the buffer or there is some other
874                          * error condition
875                          */
876                         do_read = FALSE;
877                         if (sbavail(&so->so_rcv) >= sizeof(uint32_t)
878                             || (so->so_rcv.sb_state & SBS_CANTRCVMORE)
879                             || so->so_error)
880                                 do_read = TRUE;
881
882                         if (!do_read)
883                                 break;
884
885                         SOCKBUF_UNLOCK(&so->so_rcv);
886                         uio.uio_resid = sizeof(uint32_t);
887                         m = NULL;
888                         rcvflag = MSG_DONTWAIT | MSG_SOCALLBCK;
889                         error = soreceive(so, NULL, &uio, &m, NULL, &rcvflag);
890                         SOCKBUF_LOCK(&so->so_rcv);
891
892                         if (error == EWOULDBLOCK)
893                                 break;
894                         
895                         /*
896                          * If there was an error, wake up all pending
897                          * requests.
898                          */
899                         if (error || uio.uio_resid > 0) {
900                         wakeup_all:
901                                 mtx_lock(&ct->ct_lock);
902                                 if (!error) {
903                                         /*
904                                          * We must have got EOF trying
905                                          * to read from the stream.
906                                          */
907                                         error = ECONNRESET;
908                                 }
909                                 ct->ct_error.re_status = RPC_CANTRECV;
910                                 ct->ct_error.re_errno = error;
911                                 TAILQ_FOREACH(cr, &ct->ct_pending, cr_link) {
912                                         cr->cr_error = error;
913                                         wakeup(cr);
914                                 }
915                                 mtx_unlock(&ct->ct_lock);
916                                 break;
917                         }
918                         m_copydata(m, 0, sizeof(uint32_t), (char *)&header);
919                         header = ntohl(header);
920                         ct->ct_record = NULL;
921                         ct->ct_record_resid = header & 0x7fffffff;
922                         ct->ct_record_eor = ((header & 0x80000000) != 0);
923                         m_freem(m);
924                 } else {
925                         /*
926                          * Wait until the socket has the whole record
927                          * buffered.
928                          */
929                         do_read = FALSE;
930                         if (sbavail(&so->so_rcv) >= ct->ct_record_resid
931                             || (so->so_rcv.sb_state & SBS_CANTRCVMORE)
932                             || so->so_error)
933                                 do_read = TRUE;
934
935                         if (!do_read)
936                                 break;
937
938                         /*
939                          * We have the record mark. Read as much as
940                          * the socket has buffered up to the end of
941                          * this record.
942                          */
943                         SOCKBUF_UNLOCK(&so->so_rcv);
944                         uio.uio_resid = ct->ct_record_resid;
945                         m = NULL;
946                         rcvflag = MSG_DONTWAIT | MSG_SOCALLBCK;
947                         error = soreceive(so, NULL, &uio, &m, NULL, &rcvflag);
948                         SOCKBUF_LOCK(&so->so_rcv);
949
950                         if (error == EWOULDBLOCK)
951                                 break;
952
953                         if (error || uio.uio_resid == ct->ct_record_resid)
954                                 goto wakeup_all;
955
956                         /*
957                          * If we have part of the record already,
958                          * chain this bit onto the end.
959                          */
960                         if (ct->ct_record)
961                                 m_last(ct->ct_record)->m_next = m;
962                         else
963                                 ct->ct_record = m;
964
965                         ct->ct_record_resid = uio.uio_resid;
966
967                         /*
968                          * If we have the entire record, see if we can
969                          * match it to a request.
970                          */
971                         if (ct->ct_record_resid == 0
972                             && ct->ct_record_eor) {
973                                 /*
974                                  * The XID is in the first uint32_t of
975                                  * the reply and the message direction
976                                  * is the second one.
977                                  */
978                                 if (ct->ct_record->m_len <
979                                     sizeof(xid_plus_direction) &&
980                                     m_length(ct->ct_record, NULL) <
981                                     sizeof(xid_plus_direction)) {
982                                         m_freem(ct->ct_record);
983                                         break;
984                                 }
985                                 m_copydata(ct->ct_record, 0,
986                                     sizeof(xid_plus_direction),
987                                     (char *)xid_plus_direction);
988                                 xid_plus_direction[0] =
989                                     ntohl(xid_plus_direction[0]);
990                                 xid_plus_direction[1] =
991                                     ntohl(xid_plus_direction[1]);
992                                 /* Check message direction. */
993                                 if (xid_plus_direction[1] == CALL) {
994                                         /* This is a backchannel request. */
995                                         mtx_lock(&ct->ct_lock);
996                                         xprt = ct->ct_backchannelxprt;
997                                         if (xprt == NULL) {
998                                                 mtx_unlock(&ct->ct_lock);
999                                                 /* Just throw it away. */
1000                                                 m_freem(ct->ct_record);
1001                                                 ct->ct_record = NULL;
1002                                         } else {
1003                                                 cd = (struct cf_conn *)
1004                                                     xprt->xp_p1;
1005                                                 m2 = cd->mreq;
1006                                                 /*
1007                                                  * The requests are chained
1008                                                  * in the m_nextpkt list.
1009                                                  */
1010                                                 while (m2 != NULL &&
1011                                                     m2->m_nextpkt != NULL)
1012                                                         /* Find end of list. */
1013                                                         m2 = m2->m_nextpkt;
1014                                                 if (m2 != NULL)
1015                                                         m2->m_nextpkt =
1016                                                             ct->ct_record;
1017                                                 else
1018                                                         cd->mreq =
1019                                                             ct->ct_record;
1020                                                 ct->ct_record->m_nextpkt =
1021                                                     NULL;
1022                                                 ct->ct_record = NULL;
1023                                                 xprt_active(xprt);
1024                                                 mtx_unlock(&ct->ct_lock);
1025                                         }
1026                                 } else {
1027                                         mtx_lock(&ct->ct_lock);
1028                                         foundreq = 0;
1029                                         TAILQ_FOREACH(cr, &ct->ct_pending,
1030                                             cr_link) {
1031                                                 if (cr->cr_xid ==
1032                                                     xid_plus_direction[0]) {
1033                                                         /*
1034                                                          * This one
1035                                                          * matches. We leave
1036                                                          * the reply mbuf in
1037                                                          * cr->cr_mrep. Set
1038                                                          * the XID to zero so
1039                                                          * that we will ignore
1040                                                          * any duplicated
1041                                                          * replies.
1042                                                          */
1043                                                         cr->cr_xid = 0;
1044                                                         cr->cr_mrep =
1045                                                             ct->ct_record;
1046                                                         cr->cr_error = 0;
1047                                                         foundreq = 1;
1048                                                         wakeup(cr);
1049                                                         break;
1050                                                 }
1051                                         }
1052                                         mtx_unlock(&ct->ct_lock);
1053
1054                                         if (!foundreq)
1055                                                 m_freem(ct->ct_record);
1056                                         ct->ct_record = NULL;
1057                                 }
1058                         }
1059                 }
1060         } while (m);
1061         ct->ct_upcallrefs--;
1062         if (ct->ct_upcallrefs < 0)
1063                 panic("rpcvc upcall refcnt");
1064         if (ct->ct_upcallrefs == 0)
1065                 wakeup(&ct->ct_upcallrefs);
1066         return (SU_OK);
1067 }
1068
1069 /*
1070  * Wait for all upcalls in progress to complete.
1071  */
1072 static void
1073 clnt_vc_upcallsdone(struct ct_data *ct)
1074 {
1075
1076         SOCKBUF_LOCK_ASSERT(&ct->ct_socket->so_rcv);
1077
1078         while (ct->ct_upcallrefs > 0)
1079                 (void) msleep(&ct->ct_upcallrefs,
1080                     SOCKBUF_MTX(&ct->ct_socket->so_rcv), 0, "rpcvcup", 0);
1081 }