1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 32*7c478bd9Sstevel@tonic-gate * The Regents of the University of California 33*7c478bd9Sstevel@tonic-gate * All Rights Reserved 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 36*7c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 37*7c478bd9Sstevel@tonic-gate * contributors. 38*7c478bd9Sstevel@tonic-gate */ 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate /* 43*7c478bd9Sstevel@tonic-gate * svc_tcp.c, Server side for TCP/IP based RPC. 44*7c478bd9Sstevel@tonic-gate * 45*7c478bd9Sstevel@tonic-gate * Actually implements two flavors of transporter - 46*7c478bd9Sstevel@tonic-gate * a tcp rendezvouser (a listner and connection establisher) 47*7c478bd9Sstevel@tonic-gate * and a record/tcp stream. 48*7c478bd9Sstevel@tonic-gate */ 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 53*7c478bd9Sstevel@tonic-gate #include <errno.h> 54*7c478bd9Sstevel@tonic-gate #include <syslog.h> 55*7c478bd9Sstevel@tonic-gate #include <malloc.h> 56*7c478bd9Sstevel@tonic-gate #include <stdio.h> 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate extern bool_t abort(); 59*7c478bd9Sstevel@tonic-gate extern int errno; 60*7c478bd9Sstevel@tonic-gate extern SVCXPRT *svc_xprt_alloc(); 61*7c478bd9Sstevel@tonic-gate extern void svc_xprt_free(); 62*7c478bd9Sstevel@tonic-gate extern int _socket(int, int, int); 63*7c478bd9Sstevel@tonic-gate extern int _bind(int, const struct sockaddr *, int); 64*7c478bd9Sstevel@tonic-gate extern int _getsockname(int, struct sockaddr *, int *); 65*7c478bd9Sstevel@tonic-gate extern int _listen(int, int); 66*7c478bd9Sstevel@tonic-gate extern int _accept(int, struct sockaddr *, int *); 67*7c478bd9Sstevel@tonic-gate extern int bindresvport(int, struct sockaddr_in *); 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate static struct xp_ops *svctcp_ops(); 70*7c478bd9Sstevel@tonic-gate static struct xp_ops *svctcp_rendezvous_ops(); 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate static int readtcp(), writetcp(); 73*7c478bd9Sstevel@tonic-gate static SVCXPRT *makefd_xprt(); 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate struct tcp_rendezvous { /* kept in xprt->xp_p1 */ 76*7c478bd9Sstevel@tonic-gate u_int sendsize; 77*7c478bd9Sstevel@tonic-gate u_int recvsize; 78*7c478bd9Sstevel@tonic-gate }; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate struct tcp_conn { /* kept in xprt->xp_p1 */ 81*7c478bd9Sstevel@tonic-gate enum xprt_stat strm_stat; 82*7c478bd9Sstevel@tonic-gate uint32_t x_id; 83*7c478bd9Sstevel@tonic-gate XDR xdrs; 84*7c478bd9Sstevel@tonic-gate char verf_body[MAX_AUTH_BYTES]; 85*7c478bd9Sstevel@tonic-gate }; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate /* 88*7c478bd9Sstevel@tonic-gate * Usage: 89*7c478bd9Sstevel@tonic-gate * xprt = svctcp_create(sock, send_buf_size, recv_buf_size); 90*7c478bd9Sstevel@tonic-gate * 91*7c478bd9Sstevel@tonic-gate * Creates, registers, and returns a (rpc) tcp based transporter. 92*7c478bd9Sstevel@tonic-gate * Once *xprt is initialized, it is registered as a transporter 93*7c478bd9Sstevel@tonic-gate * see (svc.h, xprt_register). This routine returns 94*7c478bd9Sstevel@tonic-gate * a NULL if a problem occurred. 95*7c478bd9Sstevel@tonic-gate * 96*7c478bd9Sstevel@tonic-gate * If sock<0 then a socket is created, else sock is used. 97*7c478bd9Sstevel@tonic-gate * If the socket, sock is not bound to a port then svctcp_create 98*7c478bd9Sstevel@tonic-gate * binds it to an arbitrary port. The routine then starts a tcp 99*7c478bd9Sstevel@tonic-gate * listener on the socket's associated port. In any (successful) case, 100*7c478bd9Sstevel@tonic-gate * xprt->xp_sock is the registered socket number and xprt->xp_port is the 101*7c478bd9Sstevel@tonic-gate * associated port number. 102*7c478bd9Sstevel@tonic-gate * 103*7c478bd9Sstevel@tonic-gate * Since tcp streams do buffered io similar to stdio, the caller can specify 104*7c478bd9Sstevel@tonic-gate * how big the send and receive buffers are via the second and third parms; 105*7c478bd9Sstevel@tonic-gate * 0 => use the system default. 106*7c478bd9Sstevel@tonic-gate */ 107*7c478bd9Sstevel@tonic-gate SVCXPRT * 108*7c478bd9Sstevel@tonic-gate svctcp_create(sock, sendsize, recvsize) 109*7c478bd9Sstevel@tonic-gate register int sock; 110*7c478bd9Sstevel@tonic-gate u_int sendsize; 111*7c478bd9Sstevel@tonic-gate u_int recvsize; 112*7c478bd9Sstevel@tonic-gate { 113*7c478bd9Sstevel@tonic-gate bool_t madesock = FALSE; 114*7c478bd9Sstevel@tonic-gate register SVCXPRT *xprt; 115*7c478bd9Sstevel@tonic-gate register struct tcp_rendezvous *r; 116*7c478bd9Sstevel@tonic-gate struct sockaddr_in addr; 117*7c478bd9Sstevel@tonic-gate int len = sizeof (struct sockaddr_in); 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate if (sock == RPC_ANYSOCK) { 120*7c478bd9Sstevel@tonic-gate if ((sock = _socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 121*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "svctcp_create - tcp", 122*7c478bd9Sstevel@tonic-gate " socket creation problem: %m"); 123*7c478bd9Sstevel@tonic-gate return ((SVCXPRT *)NULL); 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate madesock = TRUE; 126*7c478bd9Sstevel@tonic-gate } 127*7c478bd9Sstevel@tonic-gate memset((char *)&addr, 0, sizeof (addr)); 128*7c478bd9Sstevel@tonic-gate addr.sin_family = AF_INET; 129*7c478bd9Sstevel@tonic-gate if (bindresvport(sock, &addr)) { 130*7c478bd9Sstevel@tonic-gate addr.sin_port = 0; 131*7c478bd9Sstevel@tonic-gate (void) _bind(sock, (struct sockaddr *)&addr, len); 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate if ((_getsockname(sock, (struct sockaddr *)&addr, &len) != 0) || 134*7c478bd9Sstevel@tonic-gate (_listen(sock, 2) != 0)) { 135*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "svctcp_create - cannot", 136*7c478bd9Sstevel@tonic-gate " getsockname or listen: %m"); 137*7c478bd9Sstevel@tonic-gate if (madesock) 138*7c478bd9Sstevel@tonic-gate (void) close(sock); 139*7c478bd9Sstevel@tonic-gate return ((SVCXPRT *)NULL); 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate r = (struct tcp_rendezvous *)mem_alloc(sizeof (*r)); 142*7c478bd9Sstevel@tonic-gate if (r == NULL) { 143*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "svctcp_create: out of memory"); 144*7c478bd9Sstevel@tonic-gate if (madesock) 145*7c478bd9Sstevel@tonic-gate (void) close(sock); 146*7c478bd9Sstevel@tonic-gate return (NULL); 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate r->sendsize = sendsize; 149*7c478bd9Sstevel@tonic-gate r->recvsize = recvsize; 150*7c478bd9Sstevel@tonic-gate xprt = svc_xprt_alloc(); 151*7c478bd9Sstevel@tonic-gate if (xprt == NULL) { 152*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "svctcp_create: out of memory"); 153*7c478bd9Sstevel@tonic-gate mem_free((char *) r, sizeof (*r)); 154*7c478bd9Sstevel@tonic-gate if (madesock) 155*7c478bd9Sstevel@tonic-gate (void) close(sock); 156*7c478bd9Sstevel@tonic-gate return (NULL); 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate xprt->xp_p2 = NULL; 159*7c478bd9Sstevel@tonic-gate xprt->xp_netid = NULL; 160*7c478bd9Sstevel@tonic-gate xprt->xp_p1 = (caddr_t)r; 161*7c478bd9Sstevel@tonic-gate xprt->xp_verf = _null_auth; 162*7c478bd9Sstevel@tonic-gate xprt->xp_ops = svctcp_rendezvous_ops(); 163*7c478bd9Sstevel@tonic-gate xprt->xp_port = ntohs(addr.sin_port); 164*7c478bd9Sstevel@tonic-gate xprt->xp_sock = sock; 165*7c478bd9Sstevel@tonic-gate xprt->xp_rtaddr.buf = xprt->xp_raddr; 166*7c478bd9Sstevel@tonic-gate xprt_register(xprt); 167*7c478bd9Sstevel@tonic-gate return (xprt); 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate /* 171*7c478bd9Sstevel@tonic-gate * Like svtcp_create(), except the routine takes any *open* UNIX file 172*7c478bd9Sstevel@tonic-gate * descriptor as its first input. 173*7c478bd9Sstevel@tonic-gate */ 174*7c478bd9Sstevel@tonic-gate SVCXPRT * 175*7c478bd9Sstevel@tonic-gate svcfd_create(fd, sendsize, recvsize) 176*7c478bd9Sstevel@tonic-gate int fd; 177*7c478bd9Sstevel@tonic-gate u_int sendsize; 178*7c478bd9Sstevel@tonic-gate u_int recvsize; 179*7c478bd9Sstevel@tonic-gate { 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate return (makefd_xprt(fd, sendsize, recvsize)); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate static SVCXPRT * 185*7c478bd9Sstevel@tonic-gate makefd_xprt(fd, sendsize, recvsize) 186*7c478bd9Sstevel@tonic-gate int fd; 187*7c478bd9Sstevel@tonic-gate u_int sendsize; 188*7c478bd9Sstevel@tonic-gate u_int recvsize; 189*7c478bd9Sstevel@tonic-gate { 190*7c478bd9Sstevel@tonic-gate register SVCXPRT *xprt; 191*7c478bd9Sstevel@tonic-gate register struct tcp_conn *cd; 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate xprt = svc_xprt_alloc(); 194*7c478bd9Sstevel@tonic-gate if (xprt == (SVCXPRT *)NULL) { 195*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "svc_tcp: makefd_xprt: out of memory"); 196*7c478bd9Sstevel@tonic-gate goto done; 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate cd = (struct tcp_conn *)mem_alloc(sizeof (struct tcp_conn)); 199*7c478bd9Sstevel@tonic-gate if (cd == (struct tcp_conn *)NULL) { 200*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "svc_tcp: makefd_xprt: out of memory"); 201*7c478bd9Sstevel@tonic-gate svc_xprt_free(xprt); 202*7c478bd9Sstevel@tonic-gate xprt = (SVCXPRT *)NULL; 203*7c478bd9Sstevel@tonic-gate goto done; 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate cd->strm_stat = XPRT_IDLE; 206*7c478bd9Sstevel@tonic-gate xdrrec_create(&(cd->xdrs), sendsize, recvsize, 207*7c478bd9Sstevel@tonic-gate (caddr_t)xprt, readtcp, writetcp); 208*7c478bd9Sstevel@tonic-gate xprt->xp_p2 = NULL; 209*7c478bd9Sstevel@tonic-gate xprt->xp_netid = NULL; 210*7c478bd9Sstevel@tonic-gate xprt->xp_p1 = (caddr_t)cd; 211*7c478bd9Sstevel@tonic-gate xprt->xp_verf.oa_base = cd->verf_body; 212*7c478bd9Sstevel@tonic-gate xprt->xp_addrlen = 0; 213*7c478bd9Sstevel@tonic-gate xprt->xp_ops = svctcp_ops(); /* truely deals with calls */ 214*7c478bd9Sstevel@tonic-gate xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ 215*7c478bd9Sstevel@tonic-gate xprt->xp_sock = fd; 216*7c478bd9Sstevel@tonic-gate /* to handle svc_getcaller() properly */ 217*7c478bd9Sstevel@tonic-gate xprt->xp_rtaddr.buf = xprt->xp_raddr; 218*7c478bd9Sstevel@tonic-gate xprt_register(xprt); 219*7c478bd9Sstevel@tonic-gate done: 220*7c478bd9Sstevel@tonic-gate return (xprt); 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate static bool_t 224*7c478bd9Sstevel@tonic-gate rendezvous_request(xprt, rpc_msg) 225*7c478bd9Sstevel@tonic-gate register SVCXPRT *xprt; 226*7c478bd9Sstevel@tonic-gate struct rpc_msg *rpc_msg; 227*7c478bd9Sstevel@tonic-gate { 228*7c478bd9Sstevel@tonic-gate int sock; 229*7c478bd9Sstevel@tonic-gate struct tcp_rendezvous *r; 230*7c478bd9Sstevel@tonic-gate struct sockaddr_in addr; 231*7c478bd9Sstevel@tonic-gate int len; 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate r = (struct tcp_rendezvous *)xprt->xp_p1; 234*7c478bd9Sstevel@tonic-gate again: 235*7c478bd9Sstevel@tonic-gate len = sizeof (struct sockaddr_in); 236*7c478bd9Sstevel@tonic-gate if ((sock = _accept(xprt->xp_sock, (struct sockaddr *)&addr, 237*7c478bd9Sstevel@tonic-gate &len)) < 0) { 238*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 239*7c478bd9Sstevel@tonic-gate goto again; 240*7c478bd9Sstevel@tonic-gate return (FALSE); 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate /* 243*7c478bd9Sstevel@tonic-gate * make a new transporter (re-uses xprt) 244*7c478bd9Sstevel@tonic-gate */ 245*7c478bd9Sstevel@tonic-gate xprt = makefd_xprt(sock, r->sendsize, r->recvsize); 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate memcpy((char *)&xprt->xp_raddr, (char *)&addr, len); 248*7c478bd9Sstevel@tonic-gate xprt->xp_addrlen = len; 249*7c478bd9Sstevel@tonic-gate return (FALSE); /* there is never an rpc msg to be processed */ 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate static enum xprt_stat 253*7c478bd9Sstevel@tonic-gate rendezvous_stat(xprt) 254*7c478bd9Sstevel@tonic-gate SVCXPRT *xprt; 255*7c478bd9Sstevel@tonic-gate { 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate return (XPRT_IDLE); 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate static void 261*7c478bd9Sstevel@tonic-gate svctcp_destroy(xprt) 262*7c478bd9Sstevel@tonic-gate register SVCXPRT *xprt; 263*7c478bd9Sstevel@tonic-gate { 264*7c478bd9Sstevel@tonic-gate register struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1; 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate xprt_unregister(xprt); 267*7c478bd9Sstevel@tonic-gate (void) close(xprt->xp_sock); 268*7c478bd9Sstevel@tonic-gate if (xprt->xp_port != 0) { 269*7c478bd9Sstevel@tonic-gate /* a rendezvouser socket */ 270*7c478bd9Sstevel@tonic-gate xprt->xp_port = 0; 271*7c478bd9Sstevel@tonic-gate } else { 272*7c478bd9Sstevel@tonic-gate /* an actual connection socket */ 273*7c478bd9Sstevel@tonic-gate XDR_DESTROY(&(cd->xdrs)); 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate mem_free((caddr_t)cd, sizeof (struct tcp_conn)); 276*7c478bd9Sstevel@tonic-gate svc_xprt_free(xprt); 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate /* 280*7c478bd9Sstevel@tonic-gate * All read operations timeout after 35 seconds. 281*7c478bd9Sstevel@tonic-gate * A timeout is fatal for the connection. 282*7c478bd9Sstevel@tonic-gate */ 283*7c478bd9Sstevel@tonic-gate static struct timeval wait_per_try = { 35, 0 }; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate /* 286*7c478bd9Sstevel@tonic-gate * reads data from the tcp conection. 287*7c478bd9Sstevel@tonic-gate * any error is fatal and the connection is closed. 288*7c478bd9Sstevel@tonic-gate * (And a read of zero bytes is a half closed stream => error.) 289*7c478bd9Sstevel@tonic-gate */ 290*7c478bd9Sstevel@tonic-gate static int 291*7c478bd9Sstevel@tonic-gate readtcp(xprt, buf, len) 292*7c478bd9Sstevel@tonic-gate register SVCXPRT *xprt; 293*7c478bd9Sstevel@tonic-gate caddr_t buf; 294*7c478bd9Sstevel@tonic-gate register int len; 295*7c478bd9Sstevel@tonic-gate { 296*7c478bd9Sstevel@tonic-gate register int sock = xprt->xp_sock; 297*7c478bd9Sstevel@tonic-gate fd_set mask; 298*7c478bd9Sstevel@tonic-gate fd_set readfds; 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate FD_ZERO(&mask); 301*7c478bd9Sstevel@tonic-gate FD_SET(sock, &mask); 302*7c478bd9Sstevel@tonic-gate do { 303*7c478bd9Sstevel@tonic-gate readfds = mask; 304*7c478bd9Sstevel@tonic-gate if (select(__rpc_dtbsize(), &readfds, NULL, NULL, 305*7c478bd9Sstevel@tonic-gate &wait_per_try) <= 0) { 306*7c478bd9Sstevel@tonic-gate if (errno == EINTR) { 307*7c478bd9Sstevel@tonic-gate continue; 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate goto fatal_err; 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate } while (!FD_ISSET(sock, &readfds)); 312*7c478bd9Sstevel@tonic-gate if ((len = read(sock, buf, len)) > 0) { 313*7c478bd9Sstevel@tonic-gate return (len); 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate fatal_err: 316*7c478bd9Sstevel@tonic-gate ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; 317*7c478bd9Sstevel@tonic-gate return (-1); 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate /* 321*7c478bd9Sstevel@tonic-gate * writes data to the tcp connection. 322*7c478bd9Sstevel@tonic-gate * Any error is fatal and the connection is closed. 323*7c478bd9Sstevel@tonic-gate */ 324*7c478bd9Sstevel@tonic-gate static int 325*7c478bd9Sstevel@tonic-gate writetcp(xprt, buf, len) 326*7c478bd9Sstevel@tonic-gate register SVCXPRT *xprt; 327*7c478bd9Sstevel@tonic-gate caddr_t buf; 328*7c478bd9Sstevel@tonic-gate int len; 329*7c478bd9Sstevel@tonic-gate { 330*7c478bd9Sstevel@tonic-gate register int i, cnt; 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate for (cnt = len; cnt > 0; cnt -= i, buf += i) { 333*7c478bd9Sstevel@tonic-gate if ((i = write(xprt->xp_sock, buf, cnt)) < 0) { 334*7c478bd9Sstevel@tonic-gate ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = 335*7c478bd9Sstevel@tonic-gate XPRT_DIED; 336*7c478bd9Sstevel@tonic-gate return (-1); 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate return (len); 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate static enum xprt_stat 343*7c478bd9Sstevel@tonic-gate svctcp_stat(xprt) 344*7c478bd9Sstevel@tonic-gate SVCXPRT *xprt; 345*7c478bd9Sstevel@tonic-gate { 346*7c478bd9Sstevel@tonic-gate register struct tcp_conn *cd = 347*7c478bd9Sstevel@tonic-gate (struct tcp_conn *)(xprt->xp_p1); 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate if (cd->strm_stat == XPRT_DIED) 350*7c478bd9Sstevel@tonic-gate return (XPRT_DIED); 351*7c478bd9Sstevel@tonic-gate if (! xdrrec_eof(&(cd->xdrs))) 352*7c478bd9Sstevel@tonic-gate return (XPRT_MOREREQS); 353*7c478bd9Sstevel@tonic-gate return (XPRT_IDLE); 354*7c478bd9Sstevel@tonic-gate } 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate static bool_t 357*7c478bd9Sstevel@tonic-gate svctcp_recv(xprt, msg) 358*7c478bd9Sstevel@tonic-gate SVCXPRT *xprt; 359*7c478bd9Sstevel@tonic-gate register struct rpc_msg *msg; 360*7c478bd9Sstevel@tonic-gate { 361*7c478bd9Sstevel@tonic-gate register struct tcp_conn *cd = 362*7c478bd9Sstevel@tonic-gate (struct tcp_conn *)(xprt->xp_p1); 363*7c478bd9Sstevel@tonic-gate register XDR *xdrs = &(cd->xdrs); 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate xdrs->x_op = XDR_DECODE; 366*7c478bd9Sstevel@tonic-gate (void) xdrrec_skiprecord(xdrs); 367*7c478bd9Sstevel@tonic-gate if (xdr_callmsg(xdrs, msg)) { 368*7c478bd9Sstevel@tonic-gate cd->x_id = msg->rm_xid; 369*7c478bd9Sstevel@tonic-gate return (TRUE); 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate return (FALSE); 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate static bool_t 375*7c478bd9Sstevel@tonic-gate svctcp_getargs(xprt, xdr_args, args_ptr) 376*7c478bd9Sstevel@tonic-gate SVCXPRT *xprt; 377*7c478bd9Sstevel@tonic-gate xdrproc_t xdr_args; 378*7c478bd9Sstevel@tonic-gate caddr_t args_ptr; 379*7c478bd9Sstevel@tonic-gate { 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate return ((*xdr_args)(&(((struct tcp_conn *)(xprt->xp_p1))->xdrs), 382*7c478bd9Sstevel@tonic-gate args_ptr)); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate static bool_t 386*7c478bd9Sstevel@tonic-gate svctcp_freeargs(xprt, xdr_args, args_ptr) 387*7c478bd9Sstevel@tonic-gate SVCXPRT *xprt; 388*7c478bd9Sstevel@tonic-gate xdrproc_t xdr_args; 389*7c478bd9Sstevel@tonic-gate caddr_t args_ptr; 390*7c478bd9Sstevel@tonic-gate { 391*7c478bd9Sstevel@tonic-gate register XDR *xdrs = 392*7c478bd9Sstevel@tonic-gate &(((struct tcp_conn *)(xprt->xp_p1))->xdrs); 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate xdrs->x_op = XDR_FREE; 395*7c478bd9Sstevel@tonic-gate return ((*xdr_args)(xdrs, args_ptr)); 396*7c478bd9Sstevel@tonic-gate } 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate static bool_t 399*7c478bd9Sstevel@tonic-gate svctcp_reply(xprt, msg) 400*7c478bd9Sstevel@tonic-gate SVCXPRT *xprt; 401*7c478bd9Sstevel@tonic-gate register struct rpc_msg *msg; 402*7c478bd9Sstevel@tonic-gate { 403*7c478bd9Sstevel@tonic-gate register struct tcp_conn *cd = 404*7c478bd9Sstevel@tonic-gate (struct tcp_conn *)(xprt->xp_p1); 405*7c478bd9Sstevel@tonic-gate register XDR *xdrs = &(cd->xdrs); 406*7c478bd9Sstevel@tonic-gate register bool_t stat; 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate xdrs->x_op = XDR_ENCODE; 409*7c478bd9Sstevel@tonic-gate msg->rm_xid = cd->x_id; 410*7c478bd9Sstevel@tonic-gate stat = xdr_replymsg(xdrs, msg); 411*7c478bd9Sstevel@tonic-gate (void) xdrrec_endofrecord(xdrs, TRUE); 412*7c478bd9Sstevel@tonic-gate return (stat); 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate static struct xp_ops * 417*7c478bd9Sstevel@tonic-gate svctcp_ops() 418*7c478bd9Sstevel@tonic-gate { 419*7c478bd9Sstevel@tonic-gate static struct xp_ops ops; 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate if (ops.xp_recv == NULL) { 422*7c478bd9Sstevel@tonic-gate ops.xp_recv = svctcp_recv; 423*7c478bd9Sstevel@tonic-gate ops.xp_stat = svctcp_stat; 424*7c478bd9Sstevel@tonic-gate ops.xp_getargs = svctcp_getargs; 425*7c478bd9Sstevel@tonic-gate ops.xp_reply = svctcp_reply; 426*7c478bd9Sstevel@tonic-gate ops.xp_freeargs = svctcp_freeargs; 427*7c478bd9Sstevel@tonic-gate ops.xp_destroy = svctcp_destroy; 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate return (&ops); 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate static struct xp_ops * 434*7c478bd9Sstevel@tonic-gate svctcp_rendezvous_ops() 435*7c478bd9Sstevel@tonic-gate { 436*7c478bd9Sstevel@tonic-gate static struct xp_ops ops; 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate if (ops.xp_recv == NULL) { 439*7c478bd9Sstevel@tonic-gate ops.xp_recv = rendezvous_request; 440*7c478bd9Sstevel@tonic-gate ops.xp_stat = rendezvous_stat; 441*7c478bd9Sstevel@tonic-gate ops.xp_getargs = abort; 442*7c478bd9Sstevel@tonic-gate ops.xp_reply = abort; 443*7c478bd9Sstevel@tonic-gate ops.xp_freeargs = abort, 444*7c478bd9Sstevel@tonic-gate ops.xp_destroy = svctcp_destroy; 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate return (&ops); 447*7c478bd9Sstevel@tonic-gate } 448