2 * (c) Copyright 1992 by Panagiotis Tsirigotis
3 * (c) Sections Copyright 1998-2001 by Rob Braun
4 * All rights reserved. The file named COPYRIGHT specifies the terms
5 * and conditions for redistribution.
10 #include <sys/types.h>
11 #include <sys/socket.h>
20 #ifdef HAVE_SYS_SELECT_H
21 #include <sys/select.h>
25 #include "intcommon.h"
31 typedef enum { S_OK, S_SERVER_ERR, S_CLIENT_ERR } stream_status_e ;
33 struct istream_private
35 unsigned accepted_connections ;
38 #define SIP( p ) ((struct istream_private *)(p))
40 static struct istream_private istream ;
41 static struct intercept_s stream_intercept_state ;
42 static void si_mux(void) ;
45 static struct intercept_ops istream_ops =
53 struct intercept_s *si_init( struct server *serp )
55 struct intercept_s *ip = &stream_intercept_state ;
57 ip->int_socket_type = SOCK_STREAM ;
58 ip->int_priv = (void *) &istream ;
59 ip->int_ops = &istream_ops ;
60 int_init( ip, serp ) ;
61 if ( signal( SIGPIPE, SIG_IGN ) == SIG_ERR )
62 int_fail( ip, "signal" ) ;
66 static status_e handle_io( psi_h iter, channel_s *chp, fd_set *maskp, stream_status_e (*iofunc)() );
67 static stream_status_e tcp_local_to_remote( channel_s *chp );
68 static stream_status_e tcp_remote_to_local( channel_s *chp );
69 static void connection_request( struct intercept_s *ip, channel_s **chpp );
71 /* Unfortunatly, this can't be private... */
74 struct intercept_s *ip = &stream_intercept_state ;
76 if ( SIP( ip->int_priv )->accepted_connections == 0 )
77 (void) accept( INT_REMOTE( ip ), SA( NULL ), NULL ) ;
82 static void si_mux(void)
84 struct intercept_s *ip = &stream_intercept_state ;
88 const char *func = "si_mux" ;
90 FD_ZERO( &socket_mask ) ;
91 FD_SET( INT_REMOTE( ip ), &socket_mask ) ;
92 mask_max = INT_REMOTE( ip ) ;
94 iter = psi_create( INT_CONNECTIONS( ip ) ) ;
97 msg( LOG_ERR, func, ES_NOMEM ) ;
107 read_mask = socket_mask ;
108 n_ready = int_select( mask_max+1, &read_mask ) ;
113 if ( FD_ISSET( INT_REMOTE( ip ), &read_mask ) )
115 connection_request( ip, &chp ) ;
118 FD_SET( chp->ch_local_socket, &socket_mask ) ;
119 if ( chp->ch_local_socket > mask_max )
120 mask_max = chp->ch_local_socket ;
121 FD_SET( chp->ch_remote_socket, &socket_mask ) ;
122 if ( chp->ch_remote_socket > mask_max )
123 mask_max = chp->ch_remote_socket ;
125 if ( --n_ready == 0 )
129 for ( chp = CHP( psi_start(iter) ) ; chp ; chp = CHP( psi_next(iter) ) )
131 if ( FD_ISSET( chp->ch_local_socket, &read_mask ) )
135 msg( LOG_DEBUG, func, "Input available on local socket %d",
136 chp->ch_local_socket ) ;
138 if ( handle_io( iter, chp, &socket_mask, tcp_local_to_remote ) == FAILED )
140 if ( --n_ready == 0 )
144 if ( FD_ISSET( chp->ch_remote_socket, &read_mask ) )
147 msg( LOG_DEBUG, func, "Input available on remote socket %d",
148 chp->ch_remote_socket ) ;
150 if ( handle_io( iter, chp,
151 &socket_mask, tcp_remote_to_local ) == FAILED )
153 if ( --n_ready == 0 )
161 static status_e handle_io( psi_h iter,
164 stream_status_e (*iofunc)() )
166 const char *func = "handle_io" ;
168 switch ( (*iofunc)( chp ) )
176 msg( LOG_DEBUG, func,
177 "Closing channel to %s,%d using sockets %d(l),%d(r)",
178 xaddrname( &chp->ch_from ), ntohs(xaddrport( &chp->ch_from )),
179 chp->ch_local_socket, chp->ch_remote_socket ) ;
181 FD_CLR( chp->ch_local_socket, maskp ) ;
182 FD_CLR( chp->ch_remote_socket, maskp ) ;
183 (void) Sclose( chp->ch_remote_socket ) ;
184 (void) Sclose( chp->ch_local_socket ) ;
186 FREE_CHANNEL( chp ) ;
195 static void connection_request( struct intercept_s *ip, channel_s **chpp )
197 union xsockaddr csin ;
198 socklen_t sin_len = 0;
201 bool_int addr_checked ;
202 const char *func = "connection_request" ;
205 if( SC_IPV4( SVC_CONF( SERVER_SERVICE( INT_SERVER( ip ) ) ) ) )
206 sin_len = sizeof(struct sockaddr_in);
207 if( SC_IPV6( SVC_CONF( SERVER_SERVICE( INT_SERVER( ip ) ) ) ) )
208 sin_len = sizeof(struct sockaddr_in6);
210 if ( ( sd = accept( INT_REMOTE( ip ), SA( &csin ), &sin_len ) ) == -1 )
213 SIP( ip->int_priv )->accepted_connections++ ;
216 msg( LOG_DEBUG, func, "connection request from %s,%d",
217 xaddrname( &csin ), ntohs( xaddrport( &csin ) ) ) ;
219 chp = int_lookupconn( ip, &csin, &addr_checked ) ;
222 struct server *serp = INT_SERVER( ip ) ;
223 struct service *sp = SERVER_SERVICE( serp ) ;
224 connection_s *cop = SERVER_CONNECTION( serp ) ;
226 CONN_SETADDR( cop, &csin ) ;
228 if ( INTERCEPT( ip ) )
233 M_OR( check_mask, XMASK( CF_ADDRESS ), XMASK( CF_TIME ) ) ;
234 result = access_control( sp, cop, &check_mask ) ;
236 if ( result != AC_OK )
238 svc_log_failure( sp, cop, result ) ;
239 (void) Sclose( sd ) ;
244 if ( ( chp = int_newconn( ip, &csin, sd ) ) == NULL )
246 (void) Sclose( sd ) ;
250 if ( ! addr_checked )
251 svc_log_success( sp, cop, SERVER_PID( serp ) ) ;
253 #if defined( TCP_NODELAY )
257 (void) setsockopt( chp->ch_local_socket, IPPROTO_TCP,
258 TCP_NODELAY, (char *) &on, sizeof( on ) ) ;
259 (void) setsockopt( chp->ch_remote_socket, IPPROTO_TCP,
260 TCP_NODELAY, (char *) &on, sizeof( on ) ) ;
262 #endif /* TCP_NODELAY */
268 "Received another connection request from %s,%d",
269 xaddrname( &csin ), ntohs( xaddrport( &csin ) ) ) ;
273 static stream_status_e tcp_local_to_remote( channel_s *chp )
275 char buf[ DATAGRAM_SIZE ] ;
279 const char *func = "tcp_local_to_remote" ;
283 rcc = recv( chp->ch_local_socket, buf, sizeof( buf ), 0 ) ;
285 return( S_SERVER_ERR ) ;
286 else if ( rcc == -1 )
288 if ( errno != EINTR )
290 msg( LOG_ERR, func, "recv: %m" ) ;
291 return( S_SERVER_ERR ) ;
298 for ( p = buf, left = rcc ; left ; p += wcc, left -= wcc )
300 wcc = send( chp->ch_remote_socket, p, left, 0 ) ;
302 return( S_CLIENT_ERR ) ;
303 else if ( wcc == -1 )
305 if ( errno == EINTR )
309 msg( LOG_ERR, func, "send: %m" ) ;
310 return( S_CLIENT_ERR ) ;
317 msg( LOG_DEBUG, func,
318 "Transferred %d bytes from local socket %d to remote socket %d",
319 rcc, chp->ch_local_socket, chp->ch_remote_socket ) ;
326 static stream_status_e tcp_remote_to_local( channel_s *chp )
328 char buf[ DATAGRAM_SIZE ] ;
332 const char *func = "tcp_remote_to_local" ;
336 rcc = recv( chp->ch_remote_socket, buf, sizeof( buf ), 0 ) ;
338 return( S_CLIENT_ERR ) ;
339 else if ( rcc == -1 )
341 if ( errno != EINTR )
343 msg( LOG_ERR, func, "recv: %m" ) ;
344 return( S_CLIENT_ERR ) ;
351 for ( p = buf, left = rcc ; left ; p += wcc, left -= wcc )
353 wcc = send( chp->ch_local_socket, p, left, 0 ) ;
355 return( S_SERVER_ERR ) ;
356 } else if ( wcc == -1 ) {
357 if ( errno == EINTR ) {
360 msg( LOG_ERR, func, "send: %m" ) ;
361 return( S_SERVER_ERR ) ;
368 msg( LOG_DEBUG, func,
369 "Transferred %d bytes from remote socket %d to local socket %d",
370 rcc, chp->ch_remote_socket, chp->ch_local_socket ) ;