1dfdcada3SDoug Rabson /* $NetBSD: svc_vc.c,v 1.7 2000/08/03 00:01:53 fvdl Exp $ */ 2dfdcada3SDoug Rabson 32e322d37SHiroki Sato /*- 451369649SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 551369649SPedro F. Giffuni * 62e322d37SHiroki Sato * Copyright (c) 2009, Sun Microsystems, Inc. 72e322d37SHiroki Sato * All rights reserved. 8dfdcada3SDoug Rabson * 92e322d37SHiroki Sato * Redistribution and use in source and binary forms, with or without 102e322d37SHiroki Sato * modification, are permitted provided that the following conditions are met: 112e322d37SHiroki Sato * - Redistributions of source code must retain the above copyright notice, 122e322d37SHiroki Sato * this list of conditions and the following disclaimer. 132e322d37SHiroki Sato * - Redistributions in binary form must reproduce the above copyright notice, 142e322d37SHiroki Sato * this list of conditions and the following disclaimer in the documentation 152e322d37SHiroki Sato * and/or other materials provided with the distribution. 162e322d37SHiroki Sato * - Neither the name of Sun Microsystems, Inc. nor the names of its 172e322d37SHiroki Sato * contributors may be used to endorse or promote products derived 182e322d37SHiroki Sato * from this software without specific prior written permission. 19dfdcada3SDoug Rabson * 202e322d37SHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 212e322d37SHiroki Sato * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 222e322d37SHiroki Sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 232e322d37SHiroki Sato * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 242e322d37SHiroki Sato * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 252e322d37SHiroki Sato * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 262e322d37SHiroki Sato * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 272e322d37SHiroki Sato * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 282e322d37SHiroki Sato * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 292e322d37SHiroki Sato * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 302e322d37SHiroki Sato * POSSIBILITY OF SUCH DAMAGE. 31dfdcada3SDoug Rabson */ 32dfdcada3SDoug Rabson 33dfdcada3SDoug Rabson #include <sys/cdefs.h> 34dfdcada3SDoug Rabson /* 35dfdcada3SDoug Rabson * svc_vc.c, Server side for Connection Oriented based RPC. 36dfdcada3SDoug Rabson * 37dfdcada3SDoug Rabson * Actually implements two flavors of transporter - 38eb8ba6fbSAssume-Zhan * a tcp rendezvouser (a listener and connection establisher) 39dfdcada3SDoug Rabson * and a record/tcp stream. 40dfdcada3SDoug Rabson */ 41dfdcada3SDoug Rabson 42ab0c29afSRick Macklem #include "opt_kern_tls.h" 43ab0c29afSRick Macklem 44dfdcada3SDoug Rabson #include <sys/param.h> 4591898857SMark Johnston #include <sys/limits.h> 46dfdcada3SDoug Rabson #include <sys/lock.h> 47dfdcada3SDoug Rabson #include <sys/kernel.h> 48ab0c29afSRick Macklem #include <sys/ktls.h> 49dfdcada3SDoug Rabson #include <sys/malloc.h> 50dfdcada3SDoug Rabson #include <sys/mbuf.h> 51dfdcada3SDoug Rabson #include <sys/mutex.h> 520da4382aSRobert Watson #include <sys/proc.h> 53dfdcada3SDoug Rabson #include <sys/protosw.h> 54dfdcada3SDoug Rabson #include <sys/queue.h> 55dfdcada3SDoug Rabson #include <sys/socket.h> 56dfdcada3SDoug Rabson #include <sys/socketvar.h> 57a9148abdSDoug Rabson #include <sys/sx.h> 58dfdcada3SDoug Rabson #include <sys/systm.h> 59dfdcada3SDoug Rabson #include <sys/uio.h> 600348c661SMarko Zec 610348c661SMarko Zec #include <net/vnet.h> 620348c661SMarko Zec 63dfdcada3SDoug Rabson #include <netinet/tcp.h> 64dfdcada3SDoug Rabson 65dfdcada3SDoug Rabson #include <rpc/rpc.h> 66ab0c29afSRick Macklem #include <rpc/rpcsec_tls.h> 67dfdcada3SDoug Rabson 68e2adc47dSRick Macklem #include <rpc/krpc.h> 69ee31b83aSDoug Rabson #include <rpc/rpc_com.h> 70dfdcada3SDoug Rabson 710da4382aSRobert Watson #include <security/mac/mac_framework.h> 720da4382aSRobert Watson 731a878807SRick Macklem SYSCTL_NODE(_kern, OID_AUTO, rpc, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 741a878807SRick Macklem "RPC"); 751a878807SRick Macklem SYSCTL_NODE(_kern_rpc, OID_AUTO, tls, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 761a878807SRick Macklem "TLS"); 771a878807SRick Macklem SYSCTL_NODE(_kern_rpc, OID_AUTO, unenc, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 781a878807SRick Macklem "unencrypted"); 791a878807SRick Macklem 801a878807SRick Macklem KRPC_VNET_DEFINE_STATIC(uint64_t, svc_vc_rx_msgbytes) = 0; 811a878807SRick Macklem SYSCTL_U64(_kern_rpc_unenc, OID_AUTO, rx_msgbytes, CTLFLAG_KRPC_VNET | CTLFLAG_RW, 821a878807SRick Macklem &KRPC_VNET_NAME(svc_vc_rx_msgbytes), 0, "Count of non-TLS rx bytes"); 831a878807SRick Macklem 841a878807SRick Macklem KRPC_VNET_DEFINE_STATIC(uint64_t, svc_vc_rx_msgcnt) = 0; 851a878807SRick Macklem SYSCTL_U64(_kern_rpc_unenc, OID_AUTO, rx_msgcnt, CTLFLAG_KRPC_VNET | CTLFLAG_RW, 861a878807SRick Macklem &KRPC_VNET_NAME(svc_vc_rx_msgcnt), 0, "Count of non-TLS rx messages"); 871a878807SRick Macklem 881a878807SRick Macklem KRPC_VNET_DEFINE_STATIC(uint64_t, svc_vc_tx_msgbytes) = 0; 891a878807SRick Macklem SYSCTL_U64(_kern_rpc_unenc, OID_AUTO, tx_msgbytes, CTLFLAG_KRPC_VNET | CTLFLAG_RW, 901a878807SRick Macklem &KRPC_VNET_NAME(svc_vc_tx_msgbytes), 0, "Count of non-TLS tx bytes"); 911a878807SRick Macklem 921a878807SRick Macklem KRPC_VNET_DEFINE_STATIC(uint64_t, svc_vc_tx_msgcnt) = 0; 931a878807SRick Macklem SYSCTL_U64(_kern_rpc_unenc, OID_AUTO, tx_msgcnt, CTLFLAG_KRPC_VNET | CTLFLAG_RW, 941a878807SRick Macklem &KRPC_VNET_NAME(svc_vc_tx_msgcnt), 0, "Count of non-TLS tx messages"); 951a878807SRick Macklem 961a878807SRick Macklem KRPC_VNET_DEFINE_STATIC(uint64_t, svc_vc_tls_alerts) = 0; 971a878807SRick Macklem SYSCTL_U64(_kern_rpc_tls, OID_AUTO, alerts, 981a878807SRick Macklem CTLFLAG_KRPC_VNET | CTLFLAG_RW, &KRPC_VNET_NAME(svc_vc_tls_alerts), 0, 991a878807SRick Macklem "Count of TLS alert messages"); 1001a878807SRick Macklem 1011a878807SRick Macklem KRPC_VNET_DEFINE(uint64_t, svc_vc_tls_handshake_failed) = 0; 1021a878807SRick Macklem SYSCTL_U64(_kern_rpc_tls, OID_AUTO, handshake_failed, 1031a878807SRick Macklem CTLFLAG_KRPC_VNET | CTLFLAG_RW, 1041a878807SRick Macklem &KRPC_VNET_NAME(svc_vc_tls_handshake_failed), 0, 1051a878807SRick Macklem "Count of TLS failed handshakes"); 1061a878807SRick Macklem 1071a878807SRick Macklem KRPC_VNET_DEFINE(uint64_t, svc_vc_tls_handshake_success) = 0; 1081a878807SRick Macklem SYSCTL_U64(_kern_rpc_tls, OID_AUTO, handshake_success, 1091a878807SRick Macklem CTLFLAG_KRPC_VNET | CTLFLAG_RW, 1101a878807SRick Macklem &KRPC_VNET_NAME(svc_vc_tls_handshake_success), 0, 1111a878807SRick Macklem "Count of TLS successful handshakes"); 1121a878807SRick Macklem 1131a878807SRick Macklem KRPC_VNET_DEFINE_STATIC(uint64_t, svc_vc_tls_rx_msgbytes) = 0; 1141a878807SRick Macklem SYSCTL_U64(_kern_rpc_tls, OID_AUTO, rx_msgbytes, 1151a878807SRick Macklem CTLFLAG_KRPC_VNET | CTLFLAG_RW, &KRPC_VNET_NAME(svc_vc_tls_rx_msgbytes), 0, 1161a878807SRick Macklem "Count of TLS rx bytes"); 1171a878807SRick Macklem 1181a878807SRick Macklem KRPC_VNET_DEFINE_STATIC(uint64_t, svc_vc_tls_rx_msgcnt) = 0; 1191a878807SRick Macklem SYSCTL_U64(_kern_rpc_tls, OID_AUTO, rx_msgcnt, 1201a878807SRick Macklem CTLFLAG_KRPC_VNET | CTLFLAG_RW, &KRPC_VNET_NAME(svc_vc_tls_rx_msgcnt), 0, 1211a878807SRick Macklem "Count of TLS rx messages"); 1221a878807SRick Macklem 1231a878807SRick Macklem KRPC_VNET_DEFINE_STATIC(uint64_t, svc_vc_tls_tx_msgbytes) = 0; 1241a878807SRick Macklem SYSCTL_U64(_kern_rpc_tls, OID_AUTO, tx_msgbytes, 1251a878807SRick Macklem CTLFLAG_KRPC_VNET | CTLFLAG_RW, &KRPC_VNET_NAME(svc_vc_tls_tx_msgbytes), 0, 1261a878807SRick Macklem "Count of TLS tx bytes"); 1271a878807SRick Macklem 1281a878807SRick Macklem KRPC_VNET_DEFINE_STATIC(uint64_t, svc_vc_tls_tx_msgcnt) = 0; 1291a878807SRick Macklem SYSCTL_U64(_kern_rpc_tls, OID_AUTO, tx_msgcnt, 1301a878807SRick Macklem CTLFLAG_KRPC_VNET | CTLFLAG_RW, &KRPC_VNET_NAME(svc_vc_tls_tx_msgcnt), 0, 1311a878807SRick Macklem "Count of TLS tx messages"); 1321a878807SRick Macklem 133a9148abdSDoug Rabson static bool_t svc_vc_rendezvous_recv(SVCXPRT *, struct rpc_msg *, 134a9148abdSDoug Rabson struct sockaddr **, struct mbuf **); 135dfdcada3SDoug Rabson static enum xprt_stat svc_vc_rendezvous_stat(SVCXPRT *); 136dfdcada3SDoug Rabson static void svc_vc_rendezvous_destroy(SVCXPRT *); 137dfdcada3SDoug Rabson static bool_t svc_vc_null(void); 138dfdcada3SDoug Rabson static void svc_vc_destroy(SVCXPRT *); 139dfdcada3SDoug Rabson static enum xprt_stat svc_vc_stat(SVCXPRT *); 140d473bac7SAlexander Motin static bool_t svc_vc_ack(SVCXPRT *, uint32_t *); 141a9148abdSDoug Rabson static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *, 142a9148abdSDoug Rabson struct sockaddr **, struct mbuf **); 143a9148abdSDoug Rabson static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *, 144d473bac7SAlexander Motin struct sockaddr *, struct mbuf *, uint32_t *seq); 145dfdcada3SDoug Rabson static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in); 146dfdcada3SDoug Rabson static bool_t svc_vc_rendezvous_control (SVCXPRT *xprt, const u_int rq, 147dfdcada3SDoug Rabson void *in); 148e2adc47dSRick Macklem static void svc_vc_backchannel_destroy(SVCXPRT *); 149e2adc47dSRick Macklem static enum xprt_stat svc_vc_backchannel_stat(SVCXPRT *); 150e2adc47dSRick Macklem static bool_t svc_vc_backchannel_recv(SVCXPRT *, struct rpc_msg *, 151e2adc47dSRick Macklem struct sockaddr **, struct mbuf **); 152e2adc47dSRick Macklem static bool_t svc_vc_backchannel_reply(SVCXPRT *, struct rpc_msg *, 153d473bac7SAlexander Motin struct sockaddr *, struct mbuf *, uint32_t *); 154e2adc47dSRick Macklem static bool_t svc_vc_backchannel_control(SVCXPRT *xprt, const u_int rq, 155e2adc47dSRick Macklem void *in); 156dfdcada3SDoug Rabson static SVCXPRT *svc_vc_create_conn(SVCPOOL *pool, struct socket *so, 157dfdcada3SDoug Rabson struct sockaddr *raddr); 158dfdcada3SDoug Rabson static int svc_vc_accept(struct socket *head, struct socket **sop); 15974fb0ba7SJohn Baldwin static int svc_vc_soupcall(struct socket *so, void *arg, int waitflag); 160779f106aSGleb Smirnoff static int svc_vc_rendezvous_soupcall(struct socket *, void *, int); 161dfdcada3SDoug Rabson 16220d728b5SMark Johnston static const struct xp_ops svc_vc_rendezvous_ops = { 163dfdcada3SDoug Rabson .xp_recv = svc_vc_rendezvous_recv, 164dfdcada3SDoug Rabson .xp_stat = svc_vc_rendezvous_stat, 165a9148abdSDoug Rabson .xp_reply = (bool_t (*)(SVCXPRT *, struct rpc_msg *, 166d473bac7SAlexander Motin struct sockaddr *, struct mbuf *, uint32_t *))svc_vc_null, 167dfdcada3SDoug Rabson .xp_destroy = svc_vc_rendezvous_destroy, 168dfdcada3SDoug Rabson .xp_control = svc_vc_rendezvous_control 169dfdcada3SDoug Rabson }; 170dfdcada3SDoug Rabson 17120d728b5SMark Johnston static const struct xp_ops svc_vc_ops = { 172dfdcada3SDoug Rabson .xp_recv = svc_vc_recv, 173dfdcada3SDoug Rabson .xp_stat = svc_vc_stat, 174d473bac7SAlexander Motin .xp_ack = svc_vc_ack, 175dfdcada3SDoug Rabson .xp_reply = svc_vc_reply, 176dfdcada3SDoug Rabson .xp_destroy = svc_vc_destroy, 177dfdcada3SDoug Rabson .xp_control = svc_vc_control 178dfdcada3SDoug Rabson }; 179dfdcada3SDoug Rabson 18020d728b5SMark Johnston static const struct xp_ops svc_vc_backchannel_ops = { 181e2adc47dSRick Macklem .xp_recv = svc_vc_backchannel_recv, 182e2adc47dSRick Macklem .xp_stat = svc_vc_backchannel_stat, 183e2adc47dSRick Macklem .xp_reply = svc_vc_backchannel_reply, 184e2adc47dSRick Macklem .xp_destroy = svc_vc_backchannel_destroy, 185e2adc47dSRick Macklem .xp_control = svc_vc_backchannel_control 186dfdcada3SDoug Rabson }; 187dfdcada3SDoug Rabson 188dfdcada3SDoug Rabson /* 189dfdcada3SDoug Rabson * Usage: 190dfdcada3SDoug Rabson * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size); 191dfdcada3SDoug Rabson * 192dfdcada3SDoug Rabson * Creates, registers, and returns a (rpc) tcp based transporter. 193dfdcada3SDoug Rabson * Once *xprt is initialized, it is registered as a transporter 194dfdcada3SDoug Rabson * see (svc.h, xprt_register). This routine returns 195dfdcada3SDoug Rabson * a NULL if a problem occurred. 196dfdcada3SDoug Rabson * 197dfdcada3SDoug Rabson * The filedescriptor passed in is expected to refer to a bound, but 198dfdcada3SDoug Rabson * not yet connected socket. 199dfdcada3SDoug Rabson * 200dfdcada3SDoug Rabson * Since streams do buffered io similar to stdio, the caller can specify 201dfdcada3SDoug Rabson * how big the send and receive buffers are via the second and third parms; 202dfdcada3SDoug Rabson * 0 => use the system default. 203dfdcada3SDoug Rabson */ 204dfdcada3SDoug Rabson SVCXPRT * 205dfdcada3SDoug Rabson svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize, 206dfdcada3SDoug Rabson size_t recvsize) 207dfdcada3SDoug Rabson { 2081b537781SEnji Cooper SVCXPRT *xprt; 209dfdcada3SDoug Rabson int error; 210dfdcada3SDoug Rabson 211dad14216SJohn Baldwin SOCK_LOCK(so); 212dad14216SJohn Baldwin if (so->so_state & (SS_ISCONNECTED|SS_ISDISCONNECTED)) { 2130fac350cSGleb Smirnoff struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; 2140fac350cSGleb Smirnoff 215dad14216SJohn Baldwin SOCK_UNLOCK(so); 2160fac350cSGleb Smirnoff error = sopeeraddr(so, (struct sockaddr *)&ss); 217c675522fSDoug Rabson if (error) 218c675522fSDoug Rabson return (NULL); 2190fac350cSGleb Smirnoff xprt = svc_vc_create_conn(pool, so, (struct sockaddr *)&ss); 220c675522fSDoug Rabson return (xprt); 221c675522fSDoug Rabson } 222dad14216SJohn Baldwin SOCK_UNLOCK(so); 223c675522fSDoug Rabson 224a9148abdSDoug Rabson xprt = svc_xprt_alloc(); 225a9148abdSDoug Rabson sx_init(&xprt->xp_lock, "xprt->xp_lock"); 226dfdcada3SDoug Rabson xprt->xp_pool = pool; 227dfdcada3SDoug Rabson xprt->xp_socket = so; 228dfdcada3SDoug Rabson xprt->xp_p1 = NULL; 229dfdcada3SDoug Rabson xprt->xp_p2 = NULL; 230dfdcada3SDoug Rabson xprt->xp_ops = &svc_vc_rendezvous_ops; 231dfdcada3SDoug Rabson 2320fac350cSGleb Smirnoff xprt->xp_ltaddr.ss_len = sizeof(xprt->xp_ltaddr); 2330fac350cSGleb Smirnoff error = sosockaddr(so, (struct sockaddr *)&xprt->xp_ltaddr); 2340348c661SMarko Zec if (error) { 235dfdcada3SDoug Rabson goto cleanup_svc_vc_create; 2360348c661SMarko Zec } 237dfdcada3SDoug Rabson 238dfdcada3SDoug Rabson xprt_register(xprt); 239dfdcada3SDoug Rabson 24080867e61SAlexander Motin solisten(so, -1, curthread); 241dfdcada3SDoug Rabson 242779f106aSGleb Smirnoff SOLISTEN_LOCK(so); 243a4fa5e6dSRick Macklem xprt->xp_upcallset = 1; 244779f106aSGleb Smirnoff solisten_upcall_set(so, svc_vc_rendezvous_soupcall, xprt); 245779f106aSGleb Smirnoff SOLISTEN_UNLOCK(so); 246dfdcada3SDoug Rabson 247dfdcada3SDoug Rabson return (xprt); 2481b537781SEnji Cooper 249dfdcada3SDoug Rabson cleanup_svc_vc_create: 250d473bac7SAlexander Motin sx_destroy(&xprt->xp_lock); 251a9148abdSDoug Rabson svc_xprt_free(xprt); 2521b537781SEnji Cooper 253dfdcada3SDoug Rabson return (NULL); 254dfdcada3SDoug Rabson } 255dfdcada3SDoug Rabson 256dfdcada3SDoug Rabson /* 257dfdcada3SDoug Rabson * Create a new transport for a socket optained via soaccept(). 258dfdcada3SDoug Rabson */ 259dfdcada3SDoug Rabson SVCXPRT * 260dfdcada3SDoug Rabson svc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr) 261dfdcada3SDoug Rabson { 2621b537781SEnji Cooper SVCXPRT *xprt; 2631b537781SEnji Cooper struct cf_conn *cd; 264c675522fSDoug Rabson struct sockopt opt; 265c675522fSDoug Rabson int one = 1; 266dfdcada3SDoug Rabson int error; 267dfdcada3SDoug Rabson 268c675522fSDoug Rabson bzero(&opt, sizeof(struct sockopt)); 269c675522fSDoug Rabson opt.sopt_dir = SOPT_SET; 270c675522fSDoug Rabson opt.sopt_level = SOL_SOCKET; 271c675522fSDoug Rabson opt.sopt_name = SO_KEEPALIVE; 272c675522fSDoug Rabson opt.sopt_val = &one; 273c675522fSDoug Rabson opt.sopt_valsize = sizeof(one); 274c675522fSDoug Rabson error = sosetopt(so, &opt); 2750348c661SMarko Zec if (error) { 276c675522fSDoug Rabson return (NULL); 2770348c661SMarko Zec } 278c675522fSDoug Rabson 279c675522fSDoug Rabson if (so->so_proto->pr_protocol == IPPROTO_TCP) { 280c675522fSDoug Rabson bzero(&opt, sizeof(struct sockopt)); 281c675522fSDoug Rabson opt.sopt_dir = SOPT_SET; 282c675522fSDoug Rabson opt.sopt_level = IPPROTO_TCP; 283c675522fSDoug Rabson opt.sopt_name = TCP_NODELAY; 284c675522fSDoug Rabson opt.sopt_val = &one; 285c675522fSDoug Rabson opt.sopt_valsize = sizeof(one); 286c675522fSDoug Rabson error = sosetopt(so, &opt); 2870348c661SMarko Zec if (error) { 288c675522fSDoug Rabson return (NULL); 289c675522fSDoug Rabson } 2900348c661SMarko Zec } 291c675522fSDoug Rabson 292dfdcada3SDoug Rabson cd = mem_alloc(sizeof(*cd)); 293dfdcada3SDoug Rabson cd->strm_stat = XPRT_IDLE; 294dfdcada3SDoug Rabson 295a9148abdSDoug Rabson xprt = svc_xprt_alloc(); 296a9148abdSDoug Rabson sx_init(&xprt->xp_lock, "xprt->xp_lock"); 297dfdcada3SDoug Rabson xprt->xp_pool = pool; 298dfdcada3SDoug Rabson xprt->xp_socket = so; 299dfdcada3SDoug Rabson xprt->xp_p1 = cd; 300dfdcada3SDoug Rabson xprt->xp_p2 = NULL; 301dfdcada3SDoug Rabson xprt->xp_ops = &svc_vc_ops; 302dfdcada3SDoug Rabson 303a9148abdSDoug Rabson /* 304a9148abdSDoug Rabson * See http://www.connectathon.org/talks96/nfstcp.pdf - client 305a9148abdSDoug Rabson * has a 5 minute timer, server has a 6 minute timer. 306a9148abdSDoug Rabson */ 307a9148abdSDoug Rabson xprt->xp_idletimeout = 6 * 60; 308a9148abdSDoug Rabson 309a9148abdSDoug Rabson memcpy(&xprt->xp_rtaddr, raddr, raddr->sa_len); 310dfdcada3SDoug Rabson 3110fac350cSGleb Smirnoff xprt->xp_ltaddr.ss_len = sizeof(xprt->xp_ltaddr); 3120fac350cSGleb Smirnoff error = sosockaddr(so, (struct sockaddr *)&xprt->xp_ltaddr); 313dfdcada3SDoug Rabson if (error) 314dfdcada3SDoug Rabson goto cleanup_svc_vc_create; 315dfdcada3SDoug Rabson 316dfdcada3SDoug Rabson xprt_register(xprt); 317dfdcada3SDoug Rabson 318e205fd31SGleb Smirnoff SOCK_RECVBUF_LOCK(so); 319a4fa5e6dSRick Macklem xprt->xp_upcallset = 1; 32074fb0ba7SJohn Baldwin soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt); 321e205fd31SGleb Smirnoff SOCK_RECVBUF_UNLOCK(so); 322dfdcada3SDoug Rabson 323dfdcada3SDoug Rabson /* 324dfdcada3SDoug Rabson * Throw the transport into the active list in case it already 325dfdcada3SDoug Rabson * has some data buffered. 326dfdcada3SDoug Rabson */ 327a9148abdSDoug Rabson sx_xlock(&xprt->xp_lock); 328dfdcada3SDoug Rabson xprt_active(xprt); 329a9148abdSDoug Rabson sx_xunlock(&xprt->xp_lock); 330dfdcada3SDoug Rabson 331dfdcada3SDoug Rabson return (xprt); 332dfdcada3SDoug Rabson cleanup_svc_vc_create: 333d473bac7SAlexander Motin sx_destroy(&xprt->xp_lock); 334d473bac7SAlexander Motin svc_xprt_free(xprt); 335dfdcada3SDoug Rabson mem_free(cd, sizeof(*cd)); 3361b537781SEnji Cooper 337dfdcada3SDoug Rabson return (NULL); 338dfdcada3SDoug Rabson } 339dfdcada3SDoug Rabson 340dfdcada3SDoug Rabson /* 341e2adc47dSRick Macklem * Create a new transport for a backchannel on a clnt_vc socket. 342e2adc47dSRick Macklem */ 343e2adc47dSRick Macklem SVCXPRT * 344e2adc47dSRick Macklem svc_vc_create_backchannel(SVCPOOL *pool) 345e2adc47dSRick Macklem { 346e2adc47dSRick Macklem SVCXPRT *xprt = NULL; 347e2adc47dSRick Macklem struct cf_conn *cd = NULL; 348e2adc47dSRick Macklem 349e2adc47dSRick Macklem cd = mem_alloc(sizeof(*cd)); 350e2adc47dSRick Macklem cd->strm_stat = XPRT_IDLE; 351e2adc47dSRick Macklem 352e2adc47dSRick Macklem xprt = svc_xprt_alloc(); 353e2adc47dSRick Macklem sx_init(&xprt->xp_lock, "xprt->xp_lock"); 354e2adc47dSRick Macklem xprt->xp_pool = pool; 355e2adc47dSRick Macklem xprt->xp_socket = NULL; 356e2adc47dSRick Macklem xprt->xp_p1 = cd; 357e2adc47dSRick Macklem xprt->xp_p2 = NULL; 358e2adc47dSRick Macklem xprt->xp_ops = &svc_vc_backchannel_ops; 359e2adc47dSRick Macklem return (xprt); 360e2adc47dSRick Macklem } 361e2adc47dSRick Macklem 362e2adc47dSRick Macklem /* 363dfdcada3SDoug Rabson * This does all of the accept except the final call to soaccept. The 364dfdcada3SDoug Rabson * caller will call soaccept after dropping its locks (soaccept may 365dfdcada3SDoug Rabson * call malloc). 366dfdcada3SDoug Rabson */ 367dfdcada3SDoug Rabson int 368dfdcada3SDoug Rabson svc_vc_accept(struct socket *head, struct socket **sop) 369dfdcada3SDoug Rabson { 370dfdcada3SDoug Rabson struct socket *so; 371779f106aSGleb Smirnoff int error = 0; 372779f106aSGleb Smirnoff short nbio; 373dfdcada3SDoug Rabson 3747fabaac2SMark Johnston KASSERT(SOLISTENING(head), 3757fabaac2SMark Johnston ("%s: socket %p is not listening", __func__, head)); 3767fabaac2SMark Johnston 377dfdcada3SDoug Rabson #ifdef MAC 3780da4382aSRobert Watson error = mac_socket_check_accept(curthread->td_ucred, head); 379dfdcada3SDoug Rabson if (error != 0) 380dfdcada3SDoug Rabson goto done; 381dfdcada3SDoug Rabson #endif 382dfdcada3SDoug Rabson /* 383779f106aSGleb Smirnoff * XXXGL: we want non-blocking semantics. The socket could be a 384779f106aSGleb Smirnoff * socket created by kernel as well as socket shared with userland, 385779f106aSGleb Smirnoff * so we can't be sure about presense of SS_NBIO. We also shall not 386779f106aSGleb Smirnoff * toggle it on the socket, since that may surprise userland. So we 387779f106aSGleb Smirnoff * set SS_NBIO only temporarily. 388dfdcada3SDoug Rabson */ 389779f106aSGleb Smirnoff SOLISTEN_LOCK(head); 390779f106aSGleb Smirnoff nbio = head->so_state & SS_NBIO; 391779f106aSGleb Smirnoff head->so_state |= SS_NBIO; 392779f106aSGleb Smirnoff error = solisten_dequeue(head, &so, 0); 393779f106aSGleb Smirnoff head->so_state &= (nbio & ~SS_NBIO); 394779f106aSGleb Smirnoff if (error) 395779f106aSGleb Smirnoff goto done; 396dfdcada3SDoug Rabson 397779f106aSGleb Smirnoff so->so_state |= nbio; 398dfdcada3SDoug Rabson *sop = so; 399dfdcada3SDoug Rabson 400dfdcada3SDoug Rabson /* connection has been removed from the listen queue */ 401779f106aSGleb Smirnoff KNOTE_UNLOCKED(&head->so_rdsel.si_note, 0); 402dfdcada3SDoug Rabson done: 403dfdcada3SDoug Rabson return (error); 404dfdcada3SDoug Rabson } 405dfdcada3SDoug Rabson 406dfdcada3SDoug Rabson /*ARGSUSED*/ 407dfdcada3SDoug Rabson static bool_t 408a9148abdSDoug Rabson svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg, 409a9148abdSDoug Rabson struct sockaddr **addrp, struct mbuf **mp) 410dfdcada3SDoug Rabson { 411dfdcada3SDoug Rabson struct socket *so = NULL; 412cfb1e929SGleb Smirnoff struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; 413dfdcada3SDoug Rabson int error; 4146b97c9f0SRick Macklem SVCXPRT *new_xprt; 415dfdcada3SDoug Rabson 416dfdcada3SDoug Rabson /* 417dfdcada3SDoug Rabson * The socket upcall calls xprt_active() which will eventually 418dfdcada3SDoug Rabson * cause the server to call us here. We attempt to accept a 419dfdcada3SDoug Rabson * connection from the socket and turn it into a new 420dfdcada3SDoug Rabson * transport. If the accept fails, we have drained all pending 421dfdcada3SDoug Rabson * connections so we call xprt_inactive(). 422dfdcada3SDoug Rabson */ 423a9148abdSDoug Rabson sx_xlock(&xprt->xp_lock); 424dfdcada3SDoug Rabson 425dfdcada3SDoug Rabson error = svc_vc_accept(xprt->xp_socket, &so); 426dfdcada3SDoug Rabson 427dfdcada3SDoug Rabson if (error == EWOULDBLOCK) { 428a9148abdSDoug Rabson /* 429a9148abdSDoug Rabson * We must re-test for new connections after taking 430a9148abdSDoug Rabson * the lock to protect us in the case where a new 431a9148abdSDoug Rabson * connection arrives after our call to accept fails 4327455eb71SAlexander Motin * with EWOULDBLOCK. 433a9148abdSDoug Rabson */ 434779f106aSGleb Smirnoff SOLISTEN_LOCK(xprt->xp_socket); 435779f106aSGleb Smirnoff if (TAILQ_EMPTY(&xprt->xp_socket->sol_comp)) 4365c42b9dcSAlexander Motin xprt_inactive_self(xprt); 437779f106aSGleb Smirnoff SOLISTEN_UNLOCK(xprt->xp_socket); 438a9148abdSDoug Rabson sx_xunlock(&xprt->xp_lock); 439dfdcada3SDoug Rabson return (FALSE); 440dfdcada3SDoug Rabson } 441dfdcada3SDoug Rabson 442dfdcada3SDoug Rabson if (error) { 443779f106aSGleb Smirnoff SOLISTEN_LOCK(xprt->xp_socket); 444a4fa5e6dSRick Macklem if (xprt->xp_upcallset) { 445a4fa5e6dSRick Macklem xprt->xp_upcallset = 0; 44674fb0ba7SJohn Baldwin soupcall_clear(xprt->xp_socket, SO_RCV); 447a4fa5e6dSRick Macklem } 448779f106aSGleb Smirnoff SOLISTEN_UNLOCK(xprt->xp_socket); 4495c42b9dcSAlexander Motin xprt_inactive_self(xprt); 450a9148abdSDoug Rabson sx_xunlock(&xprt->xp_lock); 451dfdcada3SDoug Rabson return (FALSE); 452dfdcada3SDoug Rabson } 453dfdcada3SDoug Rabson 454a9148abdSDoug Rabson sx_xunlock(&xprt->xp_lock); 455dfdcada3SDoug Rabson 456cfb1e929SGleb Smirnoff error = soaccept(so, (struct sockaddr *)&ss); 457dfdcada3SDoug Rabson 458dfdcada3SDoug Rabson if (error) { 459dfdcada3SDoug Rabson /* 460dfdcada3SDoug Rabson * XXX not sure if I need to call sofree or soclose here. 461dfdcada3SDoug Rabson */ 462dfdcada3SDoug Rabson return (FALSE); 463dfdcada3SDoug Rabson } 464dfdcada3SDoug Rabson 465dfdcada3SDoug Rabson /* 466dfdcada3SDoug Rabson * svc_vc_create_conn will call xprt_register - we don't need 4676b97c9f0SRick Macklem * to do anything with the new connection except derefence it. 468dfdcada3SDoug Rabson */ 469cfb1e929SGleb Smirnoff new_xprt = svc_vc_create_conn(xprt->xp_pool, so, 470cfb1e929SGleb Smirnoff (struct sockaddr *)&ss); 4716b97c9f0SRick Macklem if (!new_xprt) { 472c675522fSDoug Rabson soclose(so); 4736b97c9f0SRick Macklem } else { 4746b97c9f0SRick Macklem SVC_RELEASE(new_xprt); 4756b97c9f0SRick Macklem } 476c675522fSDoug Rabson 477dfdcada3SDoug Rabson return (FALSE); /* there is never an rpc msg to be processed */ 478dfdcada3SDoug Rabson } 479dfdcada3SDoug Rabson 480dfdcada3SDoug Rabson /*ARGSUSED*/ 481dfdcada3SDoug Rabson static enum xprt_stat 482dfdcada3SDoug Rabson svc_vc_rendezvous_stat(SVCXPRT *xprt) 483dfdcada3SDoug Rabson { 484dfdcada3SDoug Rabson 485dfdcada3SDoug Rabson return (XPRT_IDLE); 486dfdcada3SDoug Rabson } 487dfdcada3SDoug Rabson 488dfdcada3SDoug Rabson static void 489dfdcada3SDoug Rabson svc_vc_destroy_common(SVCXPRT *xprt) 490dfdcada3SDoug Rabson { 491ab0c29afSRick Macklem uint32_t reterr; 492dfdcada3SDoug Rabson 493ab0c29afSRick Macklem if (xprt->xp_socket) { 494ab0c29afSRick Macklem if ((xprt->xp_tls & (RPCTLS_FLAGS_HANDSHAKE | 495ab0c29afSRick Macklem RPCTLS_FLAGS_HANDSHFAIL)) != 0) { 496*48866036SGleb Smirnoff CURVNET_SET(xprt->xp_socket->so_vnet); 497ab0c29afSRick Macklem if ((xprt->xp_tls & RPCTLS_FLAGS_HANDSHAKE) != 0) { 498ab0c29afSRick Macklem /* 499ab0c29afSRick Macklem * If the upcall fails, the socket has 500ab0c29afSRick Macklem * probably been closed via the rpctlssd 501ab0c29afSRick Macklem * daemon having crashed or been 502ab0c29afSRick Macklem * restarted, so just ignore returned stat. 503ab0c29afSRick Macklem */ 5046e671ec1SWarner Losh rpctls_srv_disconnect(xprt->xp_sslsec, 505ab0c29afSRick Macklem xprt->xp_sslusec, xprt->xp_sslrefno, 506564ed8e8SRick Macklem xprt->xp_sslproc, &reterr); 507ab0c29afSRick Macklem } 508ab0c29afSRick Macklem /* Must sorele() to get rid of reference. */ 509ab0c29afSRick Macklem sorele(xprt->xp_socket); 510ab0c29afSRick Macklem CURVNET_RESTORE(); 511ab0c29afSRick Macklem } else 512dfdcada3SDoug Rabson (void)soclose(xprt->xp_socket); 513ab0c29afSRick Macklem } 514dfdcada3SDoug Rabson 515a9148abdSDoug Rabson if (xprt->xp_netid) 516a9148abdSDoug Rabson (void) mem_free(xprt->xp_netid, strlen(xprt->xp_netid) + 1); 517a9148abdSDoug Rabson svc_xprt_free(xprt); 518dfdcada3SDoug Rabson } 519dfdcada3SDoug Rabson 520dfdcada3SDoug Rabson static void 521dfdcada3SDoug Rabson svc_vc_rendezvous_destroy(SVCXPRT *xprt) 522dfdcada3SDoug Rabson { 523dfdcada3SDoug Rabson 524779f106aSGleb Smirnoff SOLISTEN_LOCK(xprt->xp_socket); 525779f106aSGleb Smirnoff if (xprt->xp_upcallset) { 526779f106aSGleb Smirnoff xprt->xp_upcallset = 0; 527779f106aSGleb Smirnoff solisten_upcall_set(xprt->xp_socket, NULL, NULL); 528779f106aSGleb Smirnoff } 529779f106aSGleb Smirnoff SOLISTEN_UNLOCK(xprt->xp_socket); 530779f106aSGleb Smirnoff 531dfdcada3SDoug Rabson svc_vc_destroy_common(xprt); 532dfdcada3SDoug Rabson } 533dfdcada3SDoug Rabson 534dfdcada3SDoug Rabson static void 535dfdcada3SDoug Rabson svc_vc_destroy(SVCXPRT *xprt) 536dfdcada3SDoug Rabson { 537dfdcada3SDoug Rabson struct cf_conn *cd = (struct cf_conn *)xprt->xp_p1; 538e1a907a2SRick Macklem CLIENT *cl = (CLIENT *)xprt->xp_p2; 539dfdcada3SDoug Rabson 540e205fd31SGleb Smirnoff SOCK_RECVBUF_LOCK(xprt->xp_socket); 541779f106aSGleb Smirnoff if (xprt->xp_upcallset) { 542779f106aSGleb Smirnoff xprt->xp_upcallset = 0; 543ab0c29afSRick Macklem if (xprt->xp_socket->so_rcv.sb_upcall != NULL) 544779f106aSGleb Smirnoff soupcall_clear(xprt->xp_socket, SO_RCV); 545779f106aSGleb Smirnoff } 546e205fd31SGleb Smirnoff SOCK_RECVBUF_UNLOCK(xprt->xp_socket); 547779f106aSGleb Smirnoff 548e1a907a2SRick Macklem if (cl != NULL) 549e1a907a2SRick Macklem CLNT_RELEASE(cl); 550e1a907a2SRick Macklem 551dfdcada3SDoug Rabson svc_vc_destroy_common(xprt); 552dfdcada3SDoug Rabson 553dfdcada3SDoug Rabson if (cd->mreq) 554dfdcada3SDoug Rabson m_freem(cd->mreq); 555dfdcada3SDoug Rabson if (cd->mpending) 556dfdcada3SDoug Rabson m_freem(cd->mpending); 557dfdcada3SDoug Rabson mem_free(cd, sizeof(*cd)); 558dfdcada3SDoug Rabson } 559dfdcada3SDoug Rabson 560e2adc47dSRick Macklem static void 561e2adc47dSRick Macklem svc_vc_backchannel_destroy(SVCXPRT *xprt) 562e2adc47dSRick Macklem { 563e2adc47dSRick Macklem struct cf_conn *cd = (struct cf_conn *)xprt->xp_p1; 564e2adc47dSRick Macklem struct mbuf *m, *m2; 565e2adc47dSRick Macklem 566e2adc47dSRick Macklem svc_xprt_free(xprt); 567e2adc47dSRick Macklem m = cd->mreq; 568e2adc47dSRick Macklem while (m != NULL) { 569e2adc47dSRick Macklem m2 = m; 570e2adc47dSRick Macklem m = m->m_nextpkt; 571e2adc47dSRick Macklem m_freem(m2); 572e2adc47dSRick Macklem } 573e2adc47dSRick Macklem mem_free(cd, sizeof(*cd)); 574e2adc47dSRick Macklem } 575e2adc47dSRick Macklem 576dfdcada3SDoug Rabson /*ARGSUSED*/ 577dfdcada3SDoug Rabson static bool_t 578dfdcada3SDoug Rabson svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in) 579dfdcada3SDoug Rabson { 580dfdcada3SDoug Rabson return (FALSE); 581dfdcada3SDoug Rabson } 582dfdcada3SDoug Rabson 583dfdcada3SDoug Rabson static bool_t 584dfdcada3SDoug Rabson svc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, void *in) 585dfdcada3SDoug Rabson { 586dfdcada3SDoug Rabson 587dfdcada3SDoug Rabson return (FALSE); 588dfdcada3SDoug Rabson } 589dfdcada3SDoug Rabson 590e2adc47dSRick Macklem static bool_t 591e2adc47dSRick Macklem svc_vc_backchannel_control(SVCXPRT *xprt, const u_int rq, void *in) 592e2adc47dSRick Macklem { 593e2adc47dSRick Macklem 594e2adc47dSRick Macklem return (FALSE); 595e2adc47dSRick Macklem } 596e2adc47dSRick Macklem 597dfdcada3SDoug Rabson static enum xprt_stat 598dfdcada3SDoug Rabson svc_vc_stat(SVCXPRT *xprt) 599dfdcada3SDoug Rabson { 600dfdcada3SDoug Rabson struct cf_conn *cd; 601dfdcada3SDoug Rabson 602dfdcada3SDoug Rabson cd = (struct cf_conn *)(xprt->xp_p1); 603dfdcada3SDoug Rabson 604dfdcada3SDoug Rabson if (cd->strm_stat == XPRT_DIED) 605dfdcada3SDoug Rabson return (XPRT_DIED); 606dfdcada3SDoug Rabson 6077455eb71SAlexander Motin if (cd->mreq != NULL && cd->resid == 0 && cd->eor) 608dfdcada3SDoug Rabson return (XPRT_MOREREQS); 609dfdcada3SDoug Rabson 610a9148abdSDoug Rabson if (soreadable(xprt->xp_socket)) 611a9148abdSDoug Rabson return (XPRT_MOREREQS); 612a9148abdSDoug Rabson 613dfdcada3SDoug Rabson return (XPRT_IDLE); 614dfdcada3SDoug Rabson } 615dfdcada3SDoug Rabson 616d473bac7SAlexander Motin static bool_t 617d473bac7SAlexander Motin svc_vc_ack(SVCXPRT *xprt, uint32_t *ack) 618d473bac7SAlexander Motin { 619d473bac7SAlexander Motin 620c809a67aSAlexander Motin *ack = atomic_load_acq_32(&xprt->xp_snt_cnt); 621cfa6009eSGleb Smirnoff *ack -= sbused(&xprt->xp_socket->so_snd); 622d473bac7SAlexander Motin return (TRUE); 623d473bac7SAlexander Motin } 624d473bac7SAlexander Motin 625e2adc47dSRick Macklem static enum xprt_stat 626e2adc47dSRick Macklem svc_vc_backchannel_stat(SVCXPRT *xprt) 627e2adc47dSRick Macklem { 628e2adc47dSRick Macklem struct cf_conn *cd; 629e2adc47dSRick Macklem 630e2adc47dSRick Macklem cd = (struct cf_conn *)(xprt->xp_p1); 631e2adc47dSRick Macklem 632e2adc47dSRick Macklem if (cd->mreq != NULL) 633e2adc47dSRick Macklem return (XPRT_MOREREQS); 634e2adc47dSRick Macklem 635e2adc47dSRick Macklem return (XPRT_IDLE); 636e2adc47dSRick Macklem } 637e2adc47dSRick Macklem 6387455eb71SAlexander Motin /* 6397455eb71SAlexander Motin * If we have an mbuf chain in cd->mpending, try to parse a record from it, 6407455eb71SAlexander Motin * leaving the result in cd->mreq. If we don't have a complete record, leave 6417455eb71SAlexander Motin * the partial result in cd->mreq and try to read more from the socket. 6427455eb71SAlexander Motin */ 643679659adSAlexander Motin static int 6447455eb71SAlexander Motin svc_vc_process_pending(SVCXPRT *xprt) 645dfdcada3SDoug Rabson { 646dfdcada3SDoug Rabson struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1; 6477455eb71SAlexander Motin struct socket *so = xprt->xp_socket; 648dfdcada3SDoug Rabson struct mbuf *m; 649dfdcada3SDoug Rabson 650a9148abdSDoug Rabson /* 651dfdcada3SDoug Rabson * If cd->resid is non-zero, we have part of the 652dfdcada3SDoug Rabson * record already, otherwise we are expecting a record 653dfdcada3SDoug Rabson * marker. 654dfdcada3SDoug Rabson */ 6557455eb71SAlexander Motin if (!cd->resid && cd->mpending) { 656dfdcada3SDoug Rabson /* 657dfdcada3SDoug Rabson * See if there is enough data buffered to 658dfdcada3SDoug Rabson * make up a record marker. Make sure we can 659dfdcada3SDoug Rabson * handle the case where the record marker is 660dfdcada3SDoug Rabson * split across more than one mbuf. 661dfdcada3SDoug Rabson */ 662dfdcada3SDoug Rabson size_t n = 0; 663dfdcada3SDoug Rabson uint32_t header; 664dfdcada3SDoug Rabson 665dfdcada3SDoug Rabson m = cd->mpending; 666dfdcada3SDoug Rabson while (n < sizeof(uint32_t) && m) { 667dfdcada3SDoug Rabson n += m->m_len; 668dfdcada3SDoug Rabson m = m->m_next; 669dfdcada3SDoug Rabson } 6707455eb71SAlexander Motin if (n < sizeof(uint32_t)) { 6717455eb71SAlexander Motin so->so_rcv.sb_lowat = sizeof(uint32_t) - n; 672679659adSAlexander Motin return (FALSE); 6737455eb71SAlexander Motin } 6742a1e0fb4SRick Macklem m_copydata(cd->mpending, 0, sizeof(header), 6752a1e0fb4SRick Macklem (char *)&header); 676dfdcada3SDoug Rabson header = ntohl(header); 677dfdcada3SDoug Rabson cd->eor = (header & 0x80000000) != 0; 678dfdcada3SDoug Rabson cd->resid = header & 0x7fffffff; 679dfdcada3SDoug Rabson m_adj(cd->mpending, sizeof(uint32_t)); 680dfdcada3SDoug Rabson } 681dfdcada3SDoug Rabson 682dfdcada3SDoug Rabson /* 683dfdcada3SDoug Rabson * Start pulling off mbufs from cd->mpending 684dfdcada3SDoug Rabson * until we either have a complete record or 685dfdcada3SDoug Rabson * we run out of data. We use m_split to pull 686dfdcada3SDoug Rabson * data - it will pull as much as possible and 687dfdcada3SDoug Rabson * split the last mbuf if necessary. 688dfdcada3SDoug Rabson */ 689dfdcada3SDoug Rabson while (cd->mpending && cd->resid) { 690dfdcada3SDoug Rabson m = cd->mpending; 691a9148abdSDoug Rabson if (cd->mpending->m_next 692a9148abdSDoug Rabson || cd->mpending->m_len > cd->resid) 693a9148abdSDoug Rabson cd->mpending = m_split(cd->mpending, 694eb1b1807SGleb Smirnoff cd->resid, M_WAITOK); 695a9148abdSDoug Rabson else 696a9148abdSDoug Rabson cd->mpending = NULL; 697dfdcada3SDoug Rabson if (cd->mreq) 698dfdcada3SDoug Rabson m_last(cd->mreq)->m_next = m; 699dfdcada3SDoug Rabson else 700dfdcada3SDoug Rabson cd->mreq = m; 701dfdcada3SDoug Rabson while (m) { 702dfdcada3SDoug Rabson cd->resid -= m->m_len; 703dfdcada3SDoug Rabson m = m->m_next; 704dfdcada3SDoug Rabson } 705dfdcada3SDoug Rabson } 706dfdcada3SDoug Rabson 7074a240f6cSAlexander Motin /* 7084a240f6cSAlexander Motin * Block receive upcalls if we have more data pending, 7094a240f6cSAlexander Motin * otherwise report our need. 7104a240f6cSAlexander Motin */ 7114a240f6cSAlexander Motin if (cd->mpending) 7124a240f6cSAlexander Motin so->so_rcv.sb_lowat = INT_MAX; 7134a240f6cSAlexander Motin else 7144a240f6cSAlexander Motin so->so_rcv.sb_lowat = 7154a240f6cSAlexander Motin imax(1, imin(cd->resid, so->so_rcv.sb_hiwat / 2)); 716679659adSAlexander Motin return (TRUE); 7177455eb71SAlexander Motin } 7187455eb71SAlexander Motin 7197455eb71SAlexander Motin static bool_t 7207455eb71SAlexander Motin svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg, 7217455eb71SAlexander Motin struct sockaddr **addrp, struct mbuf **mp) 7227455eb71SAlexander Motin { 7237455eb71SAlexander Motin struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1; 7247455eb71SAlexander Motin struct uio uio; 725ab0c29afSRick Macklem struct mbuf *m, *ctrl; 7267455eb71SAlexander Motin struct socket* so = xprt->xp_socket; 7277455eb71SAlexander Motin XDR xdrs; 7287455eb71SAlexander Motin int error, rcvflag; 729ab0c29afSRick Macklem uint32_t reterr, xid_plus_direction[2]; 730ab0c29afSRick Macklem struct cmsghdr *cmsg; 731ab0c29afSRick Macklem struct tls_get_record tgr; 732ab0c29afSRick Macklem enum clnt_stat ret; 733dfdcada3SDoug Rabson 734dfdcada3SDoug Rabson /* 7357455eb71SAlexander Motin * Serialise access to the socket and our own record parsing 7367455eb71SAlexander Motin * state. 737dfdcada3SDoug Rabson */ 7387455eb71SAlexander Motin sx_xlock(&xprt->xp_lock); 7397455eb71SAlexander Motin 7407455eb71SAlexander Motin for (;;) { 7417455eb71SAlexander Motin /* If we have no request ready, check pending queue. */ 7427455eb71SAlexander Motin while (cd->mpending && 743679659adSAlexander Motin (cd->mreq == NULL || cd->resid != 0 || !cd->eor)) { 744679659adSAlexander Motin if (!svc_vc_process_pending(xprt)) 745679659adSAlexander Motin break; 746679659adSAlexander Motin } 7477455eb71SAlexander Motin 7487455eb71SAlexander Motin /* Process and return complete request in cd->mreq. */ 7497455eb71SAlexander Motin if (cd->mreq != NULL && cd->resid == 0 && cd->eor) { 7507455eb71SAlexander Motin 751c59e4cc3SRick Macklem /* 752c59e4cc3SRick Macklem * Now, check for a backchannel reply. 753c59e4cc3SRick Macklem * The XID is in the first uint32_t of the reply 754c59e4cc3SRick Macklem * and the message direction is the second one. 755c59e4cc3SRick Macklem */ 756c59e4cc3SRick Macklem if ((cd->mreq->m_len >= sizeof(xid_plus_direction) || 757c59e4cc3SRick Macklem m_length(cd->mreq, NULL) >= 758c59e4cc3SRick Macklem sizeof(xid_plus_direction)) && 759c59e4cc3SRick Macklem xprt->xp_p2 != NULL) { 760c59e4cc3SRick Macklem m_copydata(cd->mreq, 0, 761c59e4cc3SRick Macklem sizeof(xid_plus_direction), 762c59e4cc3SRick Macklem (char *)xid_plus_direction); 763c59e4cc3SRick Macklem xid_plus_direction[0] = 764c59e4cc3SRick Macklem ntohl(xid_plus_direction[0]); 765c59e4cc3SRick Macklem xid_plus_direction[1] = 766c59e4cc3SRick Macklem ntohl(xid_plus_direction[1]); 767c59e4cc3SRick Macklem /* Check message direction. */ 768c59e4cc3SRick Macklem if (xid_plus_direction[1] == REPLY) { 769c59e4cc3SRick Macklem clnt_bck_svccall(xprt->xp_p2, 770c59e4cc3SRick Macklem cd->mreq, 771c59e4cc3SRick Macklem xid_plus_direction[0]); 772c59e4cc3SRick Macklem cd->mreq = NULL; 773c59e4cc3SRick Macklem continue; 774c59e4cc3SRick Macklem } 775c59e4cc3SRick Macklem } 776c59e4cc3SRick Macklem 777a9148abdSDoug Rabson xdrmbuf_create(&xdrs, cd->mreq, XDR_DECODE); 778dfdcada3SDoug Rabson cd->mreq = NULL; 7797455eb71SAlexander Motin 7807455eb71SAlexander Motin /* Check for next request in a pending queue. */ 7817455eb71SAlexander Motin svc_vc_process_pending(xprt); 7827455eb71SAlexander Motin if (cd->mreq == NULL || cd->resid != 0) { 783e205fd31SGleb Smirnoff SOCK_RECVBUF_LOCK(so); 7847455eb71SAlexander Motin if (!soreadable(so)) 7855c42b9dcSAlexander Motin xprt_inactive_self(xprt); 786e205fd31SGleb Smirnoff SOCK_RECVBUF_UNLOCK(so); 7877455eb71SAlexander Motin } 7887455eb71SAlexander Motin 789a9148abdSDoug Rabson sx_xunlock(&xprt->xp_lock); 790a9148abdSDoug Rabson 791a9148abdSDoug Rabson if (! xdr_callmsg(&xdrs, msg)) { 792a9148abdSDoug Rabson XDR_DESTROY(&xdrs); 793dfdcada3SDoug Rabson return (FALSE); 794dfdcada3SDoug Rabson } 795a9148abdSDoug Rabson 796a9148abdSDoug Rabson *addrp = NULL; 797a9148abdSDoug Rabson *mp = xdrmbuf_getall(&xdrs); 798a9148abdSDoug Rabson XDR_DESTROY(&xdrs); 799dfdcada3SDoug Rabson 800dfdcada3SDoug Rabson return (TRUE); 801dfdcada3SDoug Rabson } 802dfdcada3SDoug Rabson 803dfdcada3SDoug Rabson /* 804ab0c29afSRick Macklem * If receiving is disabled so that a TLS handshake can be 805ab0c29afSRick Macklem * done by the rpctlssd daemon, return FALSE here. 806ab0c29afSRick Macklem */ 807ab0c29afSRick Macklem rcvflag = MSG_DONTWAIT; 808ab0c29afSRick Macklem if ((xprt->xp_tls & RPCTLS_FLAGS_HANDSHAKE) != 0) 809ab0c29afSRick Macklem rcvflag |= MSG_TLSAPPDATA; 810ab0c29afSRick Macklem tryagain: 811ab0c29afSRick Macklem if (xprt->xp_dontrcv) { 812ab0c29afSRick Macklem sx_xunlock(&xprt->xp_lock); 813ab0c29afSRick Macklem return (FALSE); 814ab0c29afSRick Macklem } 815ab0c29afSRick Macklem 816ab0c29afSRick Macklem /* 817dfdcada3SDoug Rabson * The socket upcall calls xprt_active() which will eventually 818dfdcada3SDoug Rabson * cause the server to call us here. We attempt to 819dfdcada3SDoug Rabson * read as much as possible from the socket and put 820dfdcada3SDoug Rabson * the result in cd->mpending. If the read fails, 821dfdcada3SDoug Rabson * we have drained both cd->mpending and the socket so 822dfdcada3SDoug Rabson * we can call xprt_inactive(). 823dfdcada3SDoug Rabson */ 824dfdcada3SDoug Rabson uio.uio_resid = 1000000000; 825dfdcada3SDoug Rabson uio.uio_td = curthread; 826ab0c29afSRick Macklem ctrl = m = NULL; 827ab0c29afSRick Macklem error = soreceive(so, NULL, &uio, &m, &ctrl, &rcvflag); 828dfdcada3SDoug Rabson 829dfdcada3SDoug Rabson if (error == EWOULDBLOCK) { 830a9148abdSDoug Rabson /* 831a9148abdSDoug Rabson * We must re-test for readability after 832a9148abdSDoug Rabson * taking the lock to protect us in the case 833a9148abdSDoug Rabson * where a new packet arrives on the socket 834a9148abdSDoug Rabson * after our call to soreceive fails with 8357455eb71SAlexander Motin * EWOULDBLOCK. 836a9148abdSDoug Rabson */ 837e205fd31SGleb Smirnoff SOCK_RECVBUF_LOCK(so); 8387455eb71SAlexander Motin if (!soreadable(so)) 8395c42b9dcSAlexander Motin xprt_inactive_self(xprt); 840e205fd31SGleb Smirnoff SOCK_RECVBUF_UNLOCK(so); 841a9148abdSDoug Rabson sx_xunlock(&xprt->xp_lock); 842dfdcada3SDoug Rabson return (FALSE); 843dfdcada3SDoug Rabson } 844dfdcada3SDoug Rabson 845ab0c29afSRick Macklem /* 8460b4f2ab0SRick Macklem * A return of ENXIO indicates that there is an 8470b4f2ab0SRick Macklem * alert record at the head of the 848ab0c29afSRick Macklem * socket's receive queue, for TLS connections. 849ab0c29afSRick Macklem * This record needs to be handled in userland 850ab0c29afSRick Macklem * via an SSL_read() call, so do an upcall to the daemon. 851ab0c29afSRick Macklem */ 8521a878807SRick Macklem KRPC_CURVNET_SET(so->so_vnet); 853ab0c29afSRick Macklem if ((xprt->xp_tls & RPCTLS_FLAGS_HANDSHAKE) != 0 && 854ab0c29afSRick Macklem error == ENXIO) { 8551a878807SRick Macklem KRPC_VNET(svc_vc_tls_alerts)++; 856ab0c29afSRick Macklem /* Disable reception. */ 857ab0c29afSRick Macklem xprt->xp_dontrcv = TRUE; 858ab0c29afSRick Macklem sx_xunlock(&xprt->xp_lock); 859ab0c29afSRick Macklem ret = rpctls_srv_handlerecord(xprt->xp_sslsec, 860ab0c29afSRick Macklem xprt->xp_sslusec, xprt->xp_sslrefno, 861564ed8e8SRick Macklem xprt->xp_sslproc, &reterr); 862*48866036SGleb Smirnoff KRPC_CURVNET_RESTORE(); 863ab0c29afSRick Macklem sx_xlock(&xprt->xp_lock); 864ab0c29afSRick Macklem xprt->xp_dontrcv = FALSE; 865ab0c29afSRick Macklem if (ret != RPC_SUCCESS || reterr != RPCTLSERR_OK) { 866ab0c29afSRick Macklem /* 867ab0c29afSRick Macklem * All we can do is soreceive() it and 868ab0c29afSRick Macklem * then toss it. 869ab0c29afSRick Macklem */ 870ab0c29afSRick Macklem rcvflag = MSG_DONTWAIT; 871ab0c29afSRick Macklem goto tryagain; 872ab0c29afSRick Macklem } 873ab0c29afSRick Macklem sx_xunlock(&xprt->xp_lock); 874ab0c29afSRick Macklem xprt_active(xprt); /* Harmless if already active. */ 875ab0c29afSRick Macklem return (FALSE); 876ab0c29afSRick Macklem } 877ab0c29afSRick Macklem 878dfdcada3SDoug Rabson if (error) { 8791a878807SRick Macklem KRPC_CURVNET_RESTORE(); 880e205fd31SGleb Smirnoff SOCK_RECVBUF_LOCK(so); 881a4fa5e6dSRick Macklem if (xprt->xp_upcallset) { 882a4fa5e6dSRick Macklem xprt->xp_upcallset = 0; 8837455eb71SAlexander Motin soupcall_clear(so, SO_RCV); 884a4fa5e6dSRick Macklem } 885e205fd31SGleb Smirnoff SOCK_RECVBUF_UNLOCK(so); 8865c42b9dcSAlexander Motin xprt_inactive_self(xprt); 887dfdcada3SDoug Rabson cd->strm_stat = XPRT_DIED; 888a9148abdSDoug Rabson sx_xunlock(&xprt->xp_lock); 889dfdcada3SDoug Rabson return (FALSE); 890dfdcada3SDoug Rabson } 891dfdcada3SDoug Rabson 892dfdcada3SDoug Rabson if (!m) { 8931a878807SRick Macklem KRPC_CURVNET_RESTORE(); 894dfdcada3SDoug Rabson /* 895dfdcada3SDoug Rabson * EOF - the other end has closed the socket. 896dfdcada3SDoug Rabson */ 8975c42b9dcSAlexander Motin xprt_inactive_self(xprt); 898dfdcada3SDoug Rabson cd->strm_stat = XPRT_DIED; 899a9148abdSDoug Rabson sx_xunlock(&xprt->xp_lock); 900dfdcada3SDoug Rabson return (FALSE); 901dfdcada3SDoug Rabson } 902dfdcada3SDoug Rabson 903ab0c29afSRick Macklem /* Process any record header(s). */ 904ab0c29afSRick Macklem if (ctrl != NULL) { 905ab0c29afSRick Macklem cmsg = mtod(ctrl, struct cmsghdr *); 906ab0c29afSRick Macklem if (cmsg->cmsg_type == TLS_GET_RECORD && 907ab0c29afSRick Macklem cmsg->cmsg_len == CMSG_LEN(sizeof(tgr))) { 908ab0c29afSRick Macklem memcpy(&tgr, CMSG_DATA(cmsg), sizeof(tgr)); 909ab0c29afSRick Macklem /* 9100b4f2ab0SRick Macklem * TLS_RLTYPE_ALERT records should be handled 9110b4f2ab0SRick Macklem * since soreceive() would have returned 9120b4f2ab0SRick Macklem * ENXIO. Just throw any other 9130b4f2ab0SRick Macklem * non-TLS_RLTYPE_APP records away. 914ab0c29afSRick Macklem */ 915ab0c29afSRick Macklem if (tgr.tls_type != TLS_RLTYPE_APP) { 916ab0c29afSRick Macklem m_freem(m); 917ab0c29afSRick Macklem m_free(ctrl); 918ab0c29afSRick Macklem rcvflag = MSG_DONTWAIT | MSG_TLSAPPDATA; 9191a878807SRick Macklem KRPC_CURVNET_RESTORE(); 920ab0c29afSRick Macklem goto tryagain; 921ab0c29afSRick Macklem } 9221a878807SRick Macklem KRPC_VNET(svc_vc_tls_rx_msgcnt)++; 9231a878807SRick Macklem KRPC_VNET(svc_vc_tls_rx_msgbytes) += 9241a878807SRick Macklem 1000000000 - uio.uio_resid; 925ab0c29afSRick Macklem } 926ab0c29afSRick Macklem m_free(ctrl); 9271a878807SRick Macklem } else { 9281a878807SRick Macklem KRPC_VNET(svc_vc_rx_msgcnt)++; 9291a878807SRick Macklem KRPC_VNET(svc_vc_rx_msgbytes) += 1000000000 - 9301a878807SRick Macklem uio.uio_resid; 931ab0c29afSRick Macklem } 9321a878807SRick Macklem KRPC_CURVNET_RESTORE(); 933ab0c29afSRick Macklem 934dfdcada3SDoug Rabson if (cd->mpending) 935dfdcada3SDoug Rabson m_last(cd->mpending)->m_next = m; 936dfdcada3SDoug Rabson else 937dfdcada3SDoug Rabson cd->mpending = m; 938dfdcada3SDoug Rabson } 939dfdcada3SDoug Rabson } 940dfdcada3SDoug Rabson 941dfdcada3SDoug Rabson static bool_t 942e2adc47dSRick Macklem svc_vc_backchannel_recv(SVCXPRT *xprt, struct rpc_msg *msg, 943e2adc47dSRick Macklem struct sockaddr **addrp, struct mbuf **mp) 944e2adc47dSRick Macklem { 945e2adc47dSRick Macklem struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1; 946e2adc47dSRick Macklem struct ct_data *ct; 947e2adc47dSRick Macklem struct mbuf *m; 948e2adc47dSRick Macklem XDR xdrs; 949e2adc47dSRick Macklem 950e2adc47dSRick Macklem sx_xlock(&xprt->xp_lock); 951e2adc47dSRick Macklem ct = (struct ct_data *)xprt->xp_p2; 952e2adc47dSRick Macklem if (ct == NULL) { 953e2adc47dSRick Macklem sx_xunlock(&xprt->xp_lock); 954e2adc47dSRick Macklem return (FALSE); 955e2adc47dSRick Macklem } 956e2adc47dSRick Macklem mtx_lock(&ct->ct_lock); 957e2adc47dSRick Macklem m = cd->mreq; 958e2adc47dSRick Macklem if (m == NULL) { 9595c42b9dcSAlexander Motin xprt_inactive_self(xprt); 960e2adc47dSRick Macklem mtx_unlock(&ct->ct_lock); 961e2adc47dSRick Macklem sx_xunlock(&xprt->xp_lock); 962e2adc47dSRick Macklem return (FALSE); 963e2adc47dSRick Macklem } 964e2adc47dSRick Macklem cd->mreq = m->m_nextpkt; 965e2adc47dSRick Macklem mtx_unlock(&ct->ct_lock); 966e2adc47dSRick Macklem sx_xunlock(&xprt->xp_lock); 967e2adc47dSRick Macklem 968e2adc47dSRick Macklem xdrmbuf_create(&xdrs, m, XDR_DECODE); 969e2adc47dSRick Macklem if (! xdr_callmsg(&xdrs, msg)) { 970e2adc47dSRick Macklem XDR_DESTROY(&xdrs); 971e2adc47dSRick Macklem return (FALSE); 972e2adc47dSRick Macklem } 973e2adc47dSRick Macklem *addrp = NULL; 974e2adc47dSRick Macklem *mp = xdrmbuf_getall(&xdrs); 975e2adc47dSRick Macklem XDR_DESTROY(&xdrs); 976e2adc47dSRick Macklem return (TRUE); 977e2adc47dSRick Macklem } 978e2adc47dSRick Macklem 979e2adc47dSRick Macklem static bool_t 980a9148abdSDoug Rabson svc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg, 981d473bac7SAlexander Motin struct sockaddr *addr, struct mbuf *m, uint32_t *seq) 982dfdcada3SDoug Rabson { 983dfdcada3SDoug Rabson XDR xdrs; 984dfdcada3SDoug Rabson struct mbuf *mrep; 985a9148abdSDoug Rabson bool_t stat = TRUE; 986ab0c29afSRick Macklem int error, len, maxextsiz; 987ab0c29afSRick Macklem #ifdef KERN_TLS 988ab0c29afSRick Macklem u_int maxlen; 989ab0c29afSRick Macklem #endif 990dfdcada3SDoug Rabson 991dfdcada3SDoug Rabson /* 992dfdcada3SDoug Rabson * Leave space for record mark. 993dfdcada3SDoug Rabson */ 994bd54830bSGleb Smirnoff mrep = m_gethdr(M_WAITOK, MT_DATA); 995dfdcada3SDoug Rabson mrep->m_data += sizeof(uint32_t); 996dfdcada3SDoug Rabson 997a9148abdSDoug Rabson xdrmbuf_create(&xdrs, mrep, XDR_ENCODE); 998a9148abdSDoug Rabson 999a9148abdSDoug Rabson if (msg->rm_reply.rp_stat == MSG_ACCEPTED && 1000a9148abdSDoug Rabson msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { 1001a9148abdSDoug Rabson if (!xdr_replymsg(&xdrs, msg)) 1002a9148abdSDoug Rabson stat = FALSE; 1003a9148abdSDoug Rabson else 1004a9148abdSDoug Rabson xdrmbuf_append(&xdrs, m); 1005a9148abdSDoug Rabson } else { 1006a9148abdSDoug Rabson stat = xdr_replymsg(&xdrs, msg); 1007a9148abdSDoug Rabson } 1008a9148abdSDoug Rabson 1009a9148abdSDoug Rabson if (stat) { 1010dfdcada3SDoug Rabson m_fixhdr(mrep); 1011dfdcada3SDoug Rabson 1012dfdcada3SDoug Rabson /* 1013dfdcada3SDoug Rabson * Prepend a record marker containing the reply length. 1014dfdcada3SDoug Rabson */ 1015eb1b1807SGleb Smirnoff M_PREPEND(mrep, sizeof(uint32_t), M_WAITOK); 1016d473bac7SAlexander Motin len = mrep->m_pkthdr.len; 1017dfdcada3SDoug Rabson *mtod(mrep, uint32_t *) = 1018d473bac7SAlexander Motin htonl(0x80000000 | (len - sizeof(uint32_t))); 1019ab0c29afSRick Macklem 1020ab0c29afSRick Macklem /* For RPC-over-TLS, copy mrep to a chain of ext_pgs. */ 10211a878807SRick Macklem KRPC_CURVNET_SET(xprt->xp_socket->so_vnet); 1022ab0c29afSRick Macklem if ((xprt->xp_tls & RPCTLS_FLAGS_HANDSHAKE) != 0) { 1023ab0c29afSRick Macklem /* 1024ab0c29afSRick Macklem * Copy the mbuf chain to a chain of 1025ab0c29afSRick Macklem * ext_pgs mbuf(s) as required by KERN_TLS. 1026ab0c29afSRick Macklem */ 1027ab0c29afSRick Macklem maxextsiz = TLS_MAX_MSG_SIZE_V10_2; 1028ab0c29afSRick Macklem #ifdef KERN_TLS 1029ab0c29afSRick Macklem if (rpctls_getinfo(&maxlen, false, false)) 1030ab0c29afSRick Macklem maxextsiz = min(maxextsiz, maxlen); 1031ab0c29afSRick Macklem #endif 1032ab0c29afSRick Macklem mrep = _rpc_copym_into_ext_pgs(mrep, maxextsiz); 10331a878807SRick Macklem KRPC_VNET(svc_vc_tls_tx_msgcnt)++; 10341a878807SRick Macklem KRPC_VNET(svc_vc_tls_tx_msgbytes) += len; 10351a878807SRick Macklem } else { 10361a878807SRick Macklem KRPC_VNET(svc_vc_tx_msgcnt)++; 10371a878807SRick Macklem KRPC_VNET(svc_vc_tx_msgbytes) += len; 1038ab0c29afSRick Macklem } 10391a878807SRick Macklem KRPC_CURVNET_RESTORE(); 1040b4c02146SKonstantin Belousov atomic_add_32(&xprt->xp_snd_cnt, len); 1041ab0c29afSRick Macklem /* 1042ab0c29afSRick Macklem * sosend consumes mreq. 1043ab0c29afSRick Macklem */ 1044dfdcada3SDoug Rabson error = sosend(xprt->xp_socket, NULL, NULL, mrep, NULL, 1045dfdcada3SDoug Rabson 0, curthread); 1046dfdcada3SDoug Rabson if (!error) { 1047c809a67aSAlexander Motin atomic_add_rel_32(&xprt->xp_snt_cnt, len); 1048d473bac7SAlexander Motin if (seq) 1049d473bac7SAlexander Motin *seq = xprt->xp_snd_cnt; 1050dfdcada3SDoug Rabson stat = TRUE; 1051c809a67aSAlexander Motin } else 1052c809a67aSAlexander Motin atomic_subtract_32(&xprt->xp_snd_cnt, len); 1053dfdcada3SDoug Rabson } else { 1054dfdcada3SDoug Rabson m_freem(mrep); 1055dfdcada3SDoug Rabson } 1056dfdcada3SDoug Rabson 1057a9148abdSDoug Rabson XDR_DESTROY(&xdrs); 1058dfdcada3SDoug Rabson 1059dfdcada3SDoug Rabson return (stat); 1060dfdcada3SDoug Rabson } 1061dfdcada3SDoug Rabson 1062dfdcada3SDoug Rabson static bool_t 1063e2adc47dSRick Macklem svc_vc_backchannel_reply(SVCXPRT *xprt, struct rpc_msg *msg, 1064d473bac7SAlexander Motin struct sockaddr *addr, struct mbuf *m, uint32_t *seq) 1065e2adc47dSRick Macklem { 1066e2adc47dSRick Macklem struct ct_data *ct; 1067e2adc47dSRick Macklem XDR xdrs; 1068e2adc47dSRick Macklem struct mbuf *mrep; 1069e2adc47dSRick Macklem bool_t stat = TRUE; 1070ab0c29afSRick Macklem int error, maxextsiz; 1071ab0c29afSRick Macklem #ifdef KERN_TLS 1072ab0c29afSRick Macklem u_int maxlen; 1073ab0c29afSRick Macklem #endif 1074e2adc47dSRick Macklem 1075e2adc47dSRick Macklem /* 1076e2adc47dSRick Macklem * Leave space for record mark. 1077e2adc47dSRick Macklem */ 1078bd54830bSGleb Smirnoff mrep = m_gethdr(M_WAITOK, MT_DATA); 1079e2adc47dSRick Macklem mrep->m_data += sizeof(uint32_t); 1080e2adc47dSRick Macklem 1081e2adc47dSRick Macklem xdrmbuf_create(&xdrs, mrep, XDR_ENCODE); 1082e2adc47dSRick Macklem 1083e2adc47dSRick Macklem if (msg->rm_reply.rp_stat == MSG_ACCEPTED && 1084e2adc47dSRick Macklem msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { 1085e2adc47dSRick Macklem if (!xdr_replymsg(&xdrs, msg)) 1086e2adc47dSRick Macklem stat = FALSE; 1087e2adc47dSRick Macklem else 1088e2adc47dSRick Macklem xdrmbuf_append(&xdrs, m); 1089e2adc47dSRick Macklem } else { 1090e2adc47dSRick Macklem stat = xdr_replymsg(&xdrs, msg); 1091e2adc47dSRick Macklem } 1092e2adc47dSRick Macklem 1093e2adc47dSRick Macklem if (stat) { 1094e2adc47dSRick Macklem m_fixhdr(mrep); 1095e2adc47dSRick Macklem 1096e2adc47dSRick Macklem /* 1097e2adc47dSRick Macklem * Prepend a record marker containing the reply length. 1098e2adc47dSRick Macklem */ 1099e2adc47dSRick Macklem M_PREPEND(mrep, sizeof(uint32_t), M_WAITOK); 1100e2adc47dSRick Macklem *mtod(mrep, uint32_t *) = 1101e2adc47dSRick Macklem htonl(0x80000000 | (mrep->m_pkthdr.len 1102e2adc47dSRick Macklem - sizeof(uint32_t))); 1103ab0c29afSRick Macklem 1104ab0c29afSRick Macklem /* For RPC-over-TLS, copy mrep to a chain of ext_pgs. */ 1105ab0c29afSRick Macklem if ((xprt->xp_tls & RPCTLS_FLAGS_HANDSHAKE) != 0) { 1106ab0c29afSRick Macklem /* 1107ab0c29afSRick Macklem * Copy the mbuf chain to a chain of 1108ab0c29afSRick Macklem * ext_pgs mbuf(s) as required by KERN_TLS. 1109ab0c29afSRick Macklem */ 1110ab0c29afSRick Macklem maxextsiz = TLS_MAX_MSG_SIZE_V10_2; 1111ab0c29afSRick Macklem #ifdef KERN_TLS 1112ab0c29afSRick Macklem if (rpctls_getinfo(&maxlen, false, false)) 1113ab0c29afSRick Macklem maxextsiz = min(maxextsiz, maxlen); 1114ab0c29afSRick Macklem #endif 1115ab0c29afSRick Macklem mrep = _rpc_copym_into_ext_pgs(mrep, maxextsiz); 1116ab0c29afSRick Macklem } 1117e2adc47dSRick Macklem sx_xlock(&xprt->xp_lock); 1118e2adc47dSRick Macklem ct = (struct ct_data *)xprt->xp_p2; 1119e2adc47dSRick Macklem if (ct != NULL) 1120e2adc47dSRick Macklem error = sosend(ct->ct_socket, NULL, NULL, mrep, NULL, 1121e2adc47dSRick Macklem 0, curthread); 1122e2adc47dSRick Macklem else 1123e2adc47dSRick Macklem error = EPIPE; 1124e2adc47dSRick Macklem sx_xunlock(&xprt->xp_lock); 1125e2adc47dSRick Macklem if (!error) { 1126e2adc47dSRick Macklem stat = TRUE; 1127e2adc47dSRick Macklem } 1128e2adc47dSRick Macklem } else { 1129e2adc47dSRick Macklem m_freem(mrep); 1130e2adc47dSRick Macklem } 1131e2adc47dSRick Macklem 1132e2adc47dSRick Macklem XDR_DESTROY(&xdrs); 1133e2adc47dSRick Macklem 1134e2adc47dSRick Macklem return (stat); 1135e2adc47dSRick Macklem } 1136e2adc47dSRick Macklem 1137e2adc47dSRick Macklem static bool_t 113887d18efeSDimitry Andric svc_vc_null(void) 1139dfdcada3SDoug Rabson { 1140dfdcada3SDoug Rabson 1141dfdcada3SDoug Rabson return (FALSE); 1142dfdcada3SDoug Rabson } 1143dfdcada3SDoug Rabson 114474fb0ba7SJohn Baldwin static int 1145dfdcada3SDoug Rabson svc_vc_soupcall(struct socket *so, void *arg, int waitflag) 1146dfdcada3SDoug Rabson { 1147dfdcada3SDoug Rabson SVCXPRT *xprt = (SVCXPRT *) arg; 1148dfdcada3SDoug Rabson 11497455eb71SAlexander Motin if (soreadable(xprt->xp_socket)) 1150dfdcada3SDoug Rabson xprt_active(xprt); 115174fb0ba7SJohn Baldwin return (SU_OK); 1152dfdcada3SDoug Rabson } 1153dfdcada3SDoug Rabson 1154779f106aSGleb Smirnoff static int 1155779f106aSGleb Smirnoff svc_vc_rendezvous_soupcall(struct socket *head, void *arg, int waitflag) 1156779f106aSGleb Smirnoff { 1157779f106aSGleb Smirnoff SVCXPRT *xprt = (SVCXPRT *) arg; 1158779f106aSGleb Smirnoff 1159779f106aSGleb Smirnoff if (!TAILQ_EMPTY(&head->sol_comp)) 1160779f106aSGleb Smirnoff xprt_active(xprt); 1161779f106aSGleb Smirnoff return (SU_OK); 1162779f106aSGleb Smirnoff } 1163779f106aSGleb Smirnoff 1164dfdcada3SDoug Rabson #if 0 1165dfdcada3SDoug Rabson /* 1166dfdcada3SDoug Rabson * Get the effective UID of the sending process. Used by rpcbind, keyserv 1167dfdcada3SDoug Rabson * and rpc.yppasswdd on AF_LOCAL. 1168dfdcada3SDoug Rabson */ 1169dfdcada3SDoug Rabson int 1170dfdcada3SDoug Rabson __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) { 1171dfdcada3SDoug Rabson int sock, ret; 1172dfdcada3SDoug Rabson gid_t egid; 1173dfdcada3SDoug Rabson uid_t euid; 1174dfdcada3SDoug Rabson struct sockaddr *sa; 1175dfdcada3SDoug Rabson 1176dfdcada3SDoug Rabson sock = transp->xp_fd; 1177a9148abdSDoug Rabson sa = (struct sockaddr *)transp->xp_rtaddr; 1178dfdcada3SDoug Rabson if (sa->sa_family == AF_LOCAL) { 1179dfdcada3SDoug Rabson ret = getpeereid(sock, &euid, &egid); 1180dfdcada3SDoug Rabson if (ret == 0) 1181dfdcada3SDoug Rabson *uid = euid; 1182dfdcada3SDoug Rabson return (ret); 1183dfdcada3SDoug Rabson } else 1184dfdcada3SDoug Rabson return (-1); 1185dfdcada3SDoug Rabson } 1186dfdcada3SDoug Rabson #endif 1187