tcpint.c (xinetd-2.3.15) | : | tcpint.c (xinetd-2.3.15.4.tar.xz) | ||
---|---|---|---|---|
skipping to change at line 18 | skipping to change at line 18 | |||
#include "config.h" | #include "config.h" | |||
#include <sys/types.h> | #include <sys/types.h> | |||
#include <sys/socket.h> | #include <sys/socket.h> | |||
#include <sys/time.h> | #include <sys/time.h> | |||
#include <syslog.h> | #include <syslog.h> | |||
#include <signal.h> | #include <signal.h> | |||
#include <errno.h> | #include <errno.h> | |||
#include <stdio.h> | #include <stdio.h> | |||
#include <stdlib.h> | #include <stdlib.h> | |||
#include <unistd.h> | #include <unistd.h> | |||
#ifdef HAVE_SYS_SELECT_H | ||||
#include <sys/select.h> | #include <sys/select.h> | |||
#endif | ||||
#include "tcpint.h" | #include "tcpint.h" | |||
#include "intcommon.h" | #include "intcommon.h" | |||
#include "msg.h" | #include "msg.h" | |||
#include "log.h" | #include "log.h" | |||
#include "xconfig.h" | #include "xconfig.h" | |||
#include "sconf.h" | #include "sconf.h" | |||
typedef enum { S_OK, S_SERVER_ERR, S_CLIENT_ERR } stream_status_e ; | typedef enum { S_OK, S_SERVER_ERR, S_CLIENT_ERR } stream_status_e ; | |||
skipping to change at line 62 | skipping to change at line 59 | |||
ip->int_socket_type = SOCK_STREAM ; | ip->int_socket_type = SOCK_STREAM ; | |||
ip->int_priv = (void *) &istream ; | ip->int_priv = (void *) &istream ; | |||
ip->int_ops = &istream_ops ; | ip->int_ops = &istream_ops ; | |||
int_init( ip, serp ) ; | int_init( ip, serp ) ; | |||
if ( signal( SIGPIPE, SIG_IGN ) == SIG_ERR ) | if ( signal( SIGPIPE, SIG_IGN ) == SIG_ERR ) | |||
int_fail( ip, "signal" ) ; | int_fail( ip, "signal" ) ; | |||
return( ip ) ; | return( ip ) ; | |||
} | } | |||
#ifdef HAVE_POLL | ||||
static status_e handle_io( psi_h iter, channel_s *chp, | ||||
struct pollfd *pfd_handled, | ||||
struct pollfd *pfd_array, | ||||
int *pfds_last, | ||||
stream_status_e (*iofunc)() ); | ||||
#else | ||||
static status_e handle_io( psi_h iter, channel_s *chp, fd_set *maskp, stream_sta tus_e (*iofunc)() ); | static status_e handle_io( psi_h iter, channel_s *chp, fd_set *maskp, stream_sta tus_e (*iofunc)() ); | |||
#endif | ||||
static stream_status_e tcp_local_to_remote( channel_s *chp ); | static stream_status_e tcp_local_to_remote( channel_s *chp ); | |||
static stream_status_e tcp_remote_to_local( channel_s *chp ); | static stream_status_e tcp_remote_to_local( channel_s *chp ); | |||
static void connection_request( struct intercept_s *ip, channel_s **chpp ); | static void connection_request( struct intercept_s *ip, channel_s **chpp ); | |||
/* Unfortunatly, this can't be private... */ | /* Unfortunatly, this can't be private... */ | |||
void si_exit(void) | void si_exit(void) | |||
{ | { | |||
struct intercept_s *ip = &stream_intercept_state ; | struct intercept_s *ip = &stream_intercept_state ; | |||
if ( SIP( ip->int_priv )->accepted_connections == 0 ) | if ( SIP( ip->int_priv )->accepted_connections == 0 ) | |||
(void) accept( INT_REMOTE( ip ), SA( NULL ), NULL ) ; | (void) accept( INT_REMOTE( ip ), SA( NULL ), NULL ) ; | |||
int_exit( ip ) ; | int_exit( ip ) ; | |||
} | } | |||
static void si_mux(void) | static void si_mux(void) | |||
{ | { | |||
struct intercept_s *ip = &stream_intercept_state ; | struct intercept_s *ip = &stream_intercept_state ; | |||
#ifdef HAVE_POLL | ||||
struct pollfd *pfd_array; | ||||
int pfds_last = 0; | ||||
#else | ||||
fd_set socket_mask ; | fd_set socket_mask ; | |||
int mask_max ; | int mask_max ; | |||
#endif | ||||
psi_h iter ; | psi_h iter ; | |||
const char *func = "si_mux" ; | const char *func = "si_mux" ; | |||
#ifdef HAVE_POLL | ||||
pfd_array = calloc(sizeof(struct pollfd),MAX_FDS); | ||||
pfd_array[ pfds_last ].fd = INT_REMOTE( ip ) ; | ||||
pfd_array[ pfds_last++ ].events = POLLIN | POLLOUT; | ||||
#else | ||||
FD_ZERO( &socket_mask ) ; | FD_ZERO( &socket_mask ) ; | |||
FD_SET( INT_REMOTE( ip ), &socket_mask ) ; | FD_SET( INT_REMOTE( ip ), &socket_mask ) ; | |||
mask_max = INT_REMOTE( ip ) ; | mask_max = INT_REMOTE( ip ) ; | |||
#endif | ||||
iter = psi_create( INT_CONNECTIONS( ip ) ) ; | iter = psi_create( INT_CONNECTIONS( ip ) ) ; | |||
if ( iter == NULL ) | if ( iter == NULL ) | |||
{ | { | |||
msg( LOG_ERR, func, ES_NOMEM ) ; | msg( LOG_ERR, func, ES_NOMEM ) ; | |||
#ifdef HAVE_POLL | ||||
free( pfd_array ) ; | ||||
#endif | ||||
return ; | return ; | |||
} | } | |||
for ( ;; ) | for ( ;; ) | |||
{ | { | |||
channel_s *chp ; | channel_s *chp ; | |||
#ifndef HAVE_POLL | ||||
fd_set read_mask ; | fd_set read_mask ; | |||
#endif | ||||
int n_ready ; | int n_ready ; | |||
#ifdef HAVE_POLL | ||||
n_ready = int_poll( pfds_last, pfd_array ) ; | ||||
#else | ||||
read_mask = socket_mask ; | read_mask = socket_mask ; | |||
n_ready = int_select( mask_max+1, &read_mask ) ; | n_ready = int_select( mask_max+1, &read_mask ) ; | |||
#endif | ||||
if ( n_ready == -1 ) | if ( n_ready == -1 ) | |||
return ; | goto free_iter ; | |||
#ifdef HAVE_POLL | ||||
if ( pfd_array[0].revents & ( POLLIN | POLLOUT ) ) | ||||
#else | ||||
if ( FD_ISSET( INT_REMOTE( ip ), &read_mask ) ) | if ( FD_ISSET( INT_REMOTE( ip ), &read_mask ) ) | |||
#endif | ||||
{ | { | |||
connection_request( ip, &chp ) ; | connection_request( ip, &chp ) ; | |||
if ( chp != NULL ) | if ( chp != NULL ) | |||
{ | { | |||
#ifdef HAVE_POLL | ||||
pfd_array[ pfds_last ].fd = chp->ch_local_socket ; | ||||
pfd_array[ pfds_last++ ].events = POLLIN | POLLOUT ; | ||||
pfd_array[ pfds_last ].fd = chp->ch_remote_socket ; | ||||
pfd_array[ pfds_last++ ].events = POLLIN | POLLOUT ; | ||||
#else | ||||
FD_SET( chp->ch_local_socket, &socket_mask ) ; | FD_SET( chp->ch_local_socket, &socket_mask ) ; | |||
if ( chp->ch_local_socket > mask_max ) | if ( chp->ch_local_socket > mask_max ) | |||
mask_max = chp->ch_local_socket ; | mask_max = chp->ch_local_socket ; | |||
FD_SET( chp->ch_remote_socket, &socket_mask ) ; | FD_SET( chp->ch_remote_socket, &socket_mask ) ; | |||
if ( chp->ch_remote_socket > mask_max ) | if ( chp->ch_remote_socket > mask_max ) | |||
mask_max = chp->ch_remote_socket ; | mask_max = chp->ch_remote_socket ; | |||
#endif | ||||
} | } | |||
if ( --n_ready == 0 ) | if ( --n_ready == 0 ) | |||
continue ; | continue ; | |||
} | } | |||
for ( chp = CHP( psi_start(iter) ) ; chp ; chp = CHP( psi_next(iter) ) ) | for ( chp = CHP( psi_start(iter) ) ; chp ; chp = CHP( psi_next(iter) ) ) | |||
{ | { | |||
#ifdef HAVE_POLL | ||||
int i; | ||||
struct pollfd *local_pfd = NULL, *remote_pfd = NULL; | ||||
/* TODO: detection with O(n)=1 */ | ||||
for (i = 0 ; i < pfds_last ; i++ ) | ||||
if (pfd_array[i].fd == chp->ch_local_socket) | ||||
local_pfd = &pfd_array[i]; | ||||
else if (pfd_array[i] .fd== chp->ch_remote_socket) | ||||
remote_pfd = &pfd_array[i]; | ||||
if ( local_pfd != NULL && | ||||
local_pfd->revents & ( POLLIN | POLLOUT) ) | ||||
#else | ||||
if ( FD_ISSET( chp->ch_local_socket, &read_mask ) ) | if ( FD_ISSET( chp->ch_local_socket, &read_mask ) ) | |||
#endif | ||||
{ | { | |||
#ifdef DEBUG_TCPINT | #ifdef DEBUG_TCPINT | |||
if ( debug.on ) | if ( debug.on ) | |||
msg( LOG_DEBUG, func, "Input available on local socket %d", | msg( LOG_DEBUG, func, "Input available on local socket %d", | |||
chp->ch_local_socket ) ; | chp->ch_local_socket ) ; | |||
#endif | #endif | |||
#ifdef HAVE_POLL | ||||
if ( handle_io( iter, chp, local_pfd, pfd_array, | ||||
&pfds_last, tcp_local_to_remote ) == FAILED ) | ||||
#else | ||||
if ( handle_io( iter, chp, &socket_mask, tcp_local_to_remote ) == FA ILED ) | if ( handle_io( iter, chp, &socket_mask, tcp_local_to_remote ) == FA ILED ) | |||
return ; | #endif | |||
goto free_iter ; | ||||
if ( --n_ready == 0 ) | if ( --n_ready == 0 ) | |||
break ; | goto free_iter ; | |||
} | } | |||
#ifdef HAVE_POLL | ||||
if ( remote_pfd != NULL && | ||||
remote_pfd->revents & ( POLLIN | POLLOUT) ) | ||||
#else | ||||
if ( FD_ISSET( chp->ch_remote_socket, &read_mask ) ) | if ( FD_ISSET( chp->ch_remote_socket, &read_mask ) ) | |||
#endif | ||||
{ | { | |||
#ifdef DEBUG_TCPINT | #ifdef DEBUG_TCPINT | |||
msg( LOG_DEBUG, func, "Input available on remote socket %d", | msg( LOG_DEBUG, func, "Input available on remote socket %d", | |||
chp->ch_remote_socket ) ; | chp->ch_remote_socket ) ; | |||
#endif | #endif | |||
#ifdef HAVE_POLL | ||||
if ( handle_io( iter, chp, remote_pfd, pfd_array, | ||||
&pfds_last, tcp_remote_to_local ) == FAILED ) | ||||
#else | ||||
if ( handle_io( iter, chp, | if ( handle_io( iter, chp, | |||
&socket_mask, tcp_remote_to_local ) == FAILED ) | &socket_mask, tcp_remote_to_local ) == FAILED ) | |||
return ; | #endif | |||
goto free_iter ; | ||||
if ( --n_ready == 0 ) | if ( --n_ready == 0 ) | |||
break ; | goto free_iter ; | |||
} | } | |||
} | } | |||
} | } | |||
free_iter: | ||||
psi_destroy( iter ) ; | ||||
return ; | ||||
} | } | |||
#ifdef HAVE_POLL | ||||
static status_e handle_io( psi_h iter, | ||||
channel_s *chp, | ||||
struct pollfd *pfd_handled, | ||||
struct pollfd *pfd_array, | ||||
int *pfds_last, | ||||
stream_status_e (*iofunc)() ) | ||||
#else | ||||
static status_e handle_io( psi_h iter, | static status_e handle_io( psi_h iter, | |||
channel_s *chp, | channel_s *chp, | |||
fd_set *maskp, | fd_set *maskp, | |||
stream_status_e (*iofunc)() ) | stream_status_e (*iofunc)() ) | |||
#endif | ||||
{ | { | |||
const char *func = "handle_io" ; | const char *func = "handle_io" ; | |||
switch ( (*iofunc)( chp ) ) | switch ( (*iofunc)( chp ) ) | |||
{ | { | |||
case S_SERVER_ERR: | case S_SERVER_ERR: | |||
return( FAILED ) ; | return( FAILED ) ; | |||
case S_CLIENT_ERR: | case S_CLIENT_ERR: | |||
if ( debug.on ) | if ( debug.on ) | |||
msg( LOG_DEBUG, func, | msg( LOG_DEBUG, func, | |||
"Closing channel to %s,%d using sockets %d(l),%d(r)", | "Closing channel to %s,%d using sockets %d(l),%d(r)", | |||
xaddrname( &chp->ch_from ), ntohs(xaddrport( &chp->ch_from )), | xaddrname( &chp->ch_from ), ntohs(xaddrport( &chp->ch_from )), | |||
chp->ch_local_socket, chp->ch_remote_socket ) ; | chp->ch_local_socket, chp->ch_remote_socket ) ; | |||
#ifdef HAVE_POLL | ||||
if ( pfd_handled != NULL) | ||||
*pfd_handled = pfd_array[ --( *pfds_last ) ]; | ||||
#else | ||||
FD_CLR( chp->ch_local_socket, maskp ) ; | FD_CLR( chp->ch_local_socket, maskp ) ; | |||
FD_CLR( chp->ch_remote_socket, maskp ) ; | FD_CLR( chp->ch_remote_socket, maskp ) ; | |||
#endif | ||||
(void) Sclose( chp->ch_remote_socket ) ; | (void) Sclose( chp->ch_remote_socket ) ; | |||
(void) Sclose( chp->ch_local_socket ) ; | (void) Sclose( chp->ch_local_socket ) ; | |||
psi_remove( iter ) ; | psi_remove( iter ) ; | |||
FREE_CHANNEL( chp ) ; | FREE_CHANNEL( chp ) ; | |||
break ; | break ; | |||
case S_OK: | case S_OK: | |||
break ; | break ; | |||
} | } | |||
return( OK ) ; | return( OK ) ; | |||
} | } | |||
skipping to change at line 349 | skipping to change at line 432 | |||
break ; | break ; | |||
} | } | |||
for ( p = buf, left = rcc ; left ; p += wcc, left -= wcc ) | for ( p = buf, left = rcc ; left ; p += wcc, left -= wcc ) | |||
{ | { | |||
wcc = send( chp->ch_local_socket, p, left, 0 ) ; | wcc = send( chp->ch_local_socket, p, left, 0 ) ; | |||
if ( wcc == 0 ) { | if ( wcc == 0 ) { | |||
return( S_SERVER_ERR ) ; | return( S_SERVER_ERR ) ; | |||
} else if ( wcc == (ssize_t)-1 ) { | } else if ( wcc == (ssize_t)-1 ) { | |||
if ( errno == EINTR ) { | if ( errno == EINTR ) { | |||
#ifdef DEBUG_TCPINT | ||||
rcc = 0 ; | rcc = 0 ; | |||
#endif | ||||
} else { | } else { | |||
msg( LOG_ERR, func, "send: %m" ) ; | msg( LOG_ERR, func, "send: %m" ) ; | |||
return( S_SERVER_ERR ) ; | return( S_SERVER_ERR ) ; | |||
} | } | |||
} | } | |||
} | } | |||
#ifdef DEBUG_TCPINT | #ifdef DEBUG_TCPINT | |||
if ( debug.on ) | if ( debug.on ) | |||
msg( LOG_DEBUG, func, | msg( LOG_DEBUG, func, | |||
End of changes. 35 change blocks. | ||||
9 lines changed or deleted | 94 lines changed or added |