2018-10-15 22:51:07 +00:00
/*-
* SSLsplit - transparent SSL / TLS interception
* https : //www.roe.ch/SSLsplit
*
* Copyright ( c ) 2009 - 2018 , Daniel Roethlisberger < daniel @ roe . ch > .
2018-10-30 09:42:52 +00:00
* Copyright ( c ) 2018 , Soner Tari < sonertari @ gmail . com > .
2018-10-15 22:51:07 +00:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
* 1. Redistributions of source code must retain the above copyright notice ,
* this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright notice ,
* this list of conditions and the following disclaimer in the documentation
* and / or other materials provided with the distribution .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ` ` AS IS ' '
* AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR
* CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS
* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN
* CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE )
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE .
*/
# include "prototcp.h"
# include "protopassthrough.h"
# include <sys/param.h>
2018-10-17 13:28:21 +00:00
/*
* Set up a bufferevent structure for either a dst or src connection ,
* optionally with or without SSL . Sets all callbacks , enables read
* and write events , but does not call bufferevent_socket_connect ( ) .
*
* For dst connections , pass - 1 as fd . Pass a pointer to an initialized
* SSL struct as ssl if the connection should use SSL .
*
* Returns pointer to initialized bufferevent structure , as returned
* by bufferevent_socket_new ( ) or bufferevent_openssl_socket_new ( ) .
*/
static struct bufferevent * NONNULL ( 1 )
prototcp_bufferevent_setup ( pxy_conn_ctx_t * ctx , evutil_socket_t fd )
{
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bufferevent_setup: ENTER, fd=%d \n " , fd ) ;
# endif /* DEBUG_PROXY */
2018-10-22 13:12:07 +00:00
// @todo Do we really need to defer callbacks? BEV_OPT_DEFER_CALLBACKS seems responsible for the issue with srvdst: We get writecb sometimes, no eventcb for CONNECTED event
2018-10-17 13:28:21 +00:00
struct bufferevent * bev = bufferevent_socket_new ( ctx - > evbase , fd , BEV_OPT_DEFER_CALLBACKS ) ;
if ( ! bev ) {
log_err_level_printf ( LOG_CRIT , " Error creating bufferevent socket \n " ) ;
2018-10-20 21:25:01 +00:00
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bufferevent_setup: bufferevent_socket_connect failed, fd=%d \n " , fd ) ;
# endif /* DEBUG_PROXY */
2018-10-17 13:28:21 +00:00
return NULL ;
}
2018-10-22 13:12:07 +00:00
// @attention Do not set callbacks here, srvdst does not set r cb
2018-10-17 13:28:21 +00:00
//bufferevent_setcb(bev, pxy_bev_readcb, pxy_bev_writecb, pxy_bev_eventcb, ctx);
// @todo Should we enable events here?
//bufferevent_enable(bev, EV_READ|EV_WRITE);
return bev ;
}
2018-10-19 23:03:21 +00:00
static struct bufferevent * NONNULL ( 1 )
2018-10-17 13:28:21 +00:00
prototcp_bufferevent_setup_child ( pxy_conn_child_ctx_t * ctx , evutil_socket_t fd )
{
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bufferevent_setup_child: ENTER, fd=%d \n " , fd ) ;
# endif /* DEBUG_PROXY */
struct bufferevent * bev = bufferevent_socket_new ( ctx - > conn - > evbase , fd , BEV_OPT_DEFER_CALLBACKS ) ;
if ( ! bev ) {
log_err_level_printf ( LOG_CRIT , " Error creating bufferevent socket \n " ) ;
2018-10-20 21:25:01 +00:00
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bufferevent_setup_child: bufferevent_socket_connect failed, fd=%d \n " , fd ) ;
# endif /* DEBUG_PROXY */
2018-10-17 13:28:21 +00:00
return NULL ;
}
bufferevent_setcb ( bev , pxy_bev_readcb_child , pxy_bev_writecb_child , pxy_bev_eventcb_child , ctx ) ;
// @attention We cannot enable events here, because src events will be deferred until after dst is connected
//bufferevent_enable(bev, EV_READ|EV_WRITE);
return bev ;
}
/*
* Free bufferenvent and close underlying socket properly .
*/
2018-10-29 18:38:42 +00:00
static void
2018-10-15 22:51:07 +00:00
prototcp_bufferevent_free_and_close_fd ( struct bufferevent * bev , UNUSED pxy_conn_ctx_t * ctx )
{
evutil_socket_t fd = bufferevent_getfd ( bev ) ;
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINER , " prototcp_bufferevent_free_and_close_fd: in=%zu, out=%zu, fd=%d \n " ,
2018-10-15 22:51:07 +00:00
evbuffer_get_length ( bufferevent_get_input ( bev ) ) , evbuffer_get_length ( bufferevent_get_output ( bev ) ) , fd ) ;
# endif /* DEBUG_PROXY */
bufferevent_free ( bev ) ;
2018-10-19 23:03:21 +00:00
evutil_closesocket ( fd ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-17 13:28:21 +00:00
int
prototcp_setup_src ( pxy_conn_ctx_t * ctx )
{
ctx - > src . ssl = NULL ;
ctx - > src . bev = prototcp_bufferevent_setup ( ctx , ctx - > fd ) ;
if ( ! ctx - > src . bev ) {
log_err_level_printf ( LOG_CRIT , " Error creating src bufferevent \n " ) ;
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 1 ) ;
2018-10-17 13:28:21 +00:00
return - 1 ;
}
2018-10-29 18:38:42 +00:00
ctx - > src . free = prototcp_bufferevent_free_and_close_fd ;
2018-10-17 13:28:21 +00:00
return 0 ;
}
int
prototcp_setup_dst ( pxy_conn_ctx_t * ctx )
{
ctx - > dst . ssl = NULL ;
ctx - > dst . bev = prototcp_bufferevent_setup ( ctx , - 1 ) ;
if ( ! ctx - > dst . bev ) {
log_err_level_printf ( LOG_CRIT , " Error creating parent dst \n " ) ;
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 1 ) ;
2018-10-17 13:28:21 +00:00
return - 1 ;
}
2018-10-29 18:38:42 +00:00
ctx - > dst . free = prototcp_bufferevent_free_and_close_fd ;
2018-10-17 13:28:21 +00:00
return 0 ;
}
int
2018-10-22 13:12:07 +00:00
prototcp_setup_srvdst ( pxy_conn_ctx_t * ctx )
2018-10-17 13:28:21 +00:00
{
2018-10-22 13:12:07 +00:00
ctx - > srvdst . ssl = NULL ;
ctx - > srvdst . bev = prototcp_bufferevent_setup ( ctx , - 1 ) ;
if ( ! ctx - > srvdst . bev ) {
log_err_level_printf ( LOG_CRIT , " Error creating srvdst \n " ) ;
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 1 ) ;
2018-10-17 13:28:21 +00:00
return - 1 ;
}
2018-10-29 18:38:42 +00:00
ctx - > srvdst . free = prototcp_bufferevent_free_and_close_fd ;
2018-10-17 13:28:21 +00:00
return 0 ;
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-15 22:51:07 +00:00
prototcp_conn_connect ( pxy_conn_ctx_t * ctx )
{
# ifdef DEBUG_PROXY
2018-10-17 13:28:21 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_conn_connect: ENTER, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-17 13:28:21 +00:00
if ( prototcp_setup_dst ( ctx ) = = - 1 ) {
2018-10-15 22:51:07 +00:00
return ;
}
bufferevent_setcb ( ctx - > dst . bev , pxy_bev_readcb , pxy_bev_writecb , pxy_bev_eventcb , ctx ) ;
bufferevent_enable ( ctx - > dst . bev , EV_READ | EV_WRITE ) ;
/* create server-side socket and eventbuffer */
2018-10-22 13:12:07 +00:00
if ( prototcp_setup_srvdst ( ctx ) = = - 1 ) {
2018-10-15 22:51:07 +00:00
return ;
}
// @attention Sometimes dst write cb fires but not event cb, especially if this listener cb is not finished yet, so the conn stalls.
// @todo Why does event cb not fire sometimes?
2018-10-22 13:12:07 +00:00
// @attention BEV_OPT_DEFER_CALLBACKS seems responsible for the issue with srvdst, libevent acts as if we call event connect() ourselves.
2018-10-15 22:51:07 +00:00
// @see Launching connections on socket-based bufferevents at http://www.wangafu.net/~nickm/libevent-book/Ref6_bufferevent.html
2018-10-22 13:12:07 +00:00
// Disable and NULL r cb, we do nothing for srvdst in r cb
bufferevent_setcb ( ctx - > srvdst . bev , NULL , pxy_bev_writecb , pxy_bev_eventcb , ctx ) ;
bufferevent_enable ( ctx - > srvdst . bev , EV_WRITE ) ;
2018-10-15 22:51:07 +00:00
/* initiate connection */
2018-11-03 15:23:31 +00:00
if ( bufferevent_socket_connect ( ctx - > srvdst . bev , ( struct sockaddr * ) & ctx - > dstaddr , ctx - > dstaddrlen ) = = - 1 ) {
2018-10-22 13:12:07 +00:00
log_err_level_printf ( LOG_CRIT , " prototcp_conn_connect: bufferevent_socket_connect for srvdst failed \n " ) ;
2018-10-15 22:51:07 +00:00
# ifdef DEBUG_PROXY
2018-10-22 13:12:07 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_conn_connect: bufferevent_socket_connect for srvdst failed, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-15 22:51:07 +00:00
// @attention Do not try to close the conn here, otherwise both pxy_conn_connect() and eventcb try to free the conn using pxy_conn_free(),
// they are running on different threads, causing multithreading issues, e.g. signal 10.
// @todo Should we use thrmgr->mutex? Can we?
2018-11-29 23:49:37 +00:00
pxy_conn_term ( ctx , 1 ) ;
2018-10-15 22:51:07 +00:00
}
}
2018-10-17 13:28:21 +00:00
int
prototcp_setup_src_child ( pxy_conn_child_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
2018-10-17 13:28:21 +00:00
ctx - > src . ssl = NULL ;
ctx - > src . bev = prototcp_bufferevent_setup_child ( ctx , ctx - > fd ) ;
if ( ! ctx - > src . bev ) {
log_err_level_printf ( LOG_CRIT , " Error creating child src \n " ) ;
evutil_closesocket ( ctx - > fd ) ;
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx - > conn , 1 ) ;
2018-10-17 13:28:21 +00:00
return - 1 ;
}
2018-10-29 18:38:42 +00:00
ctx - > src . free = prototcp_bufferevent_free_and_close_fd ;
2018-10-17 13:28:21 +00:00
return 0 ;
}
2018-10-15 22:51:07 +00:00
2018-10-17 13:28:21 +00:00
int
prototcp_setup_dst_child ( pxy_conn_child_ctx_t * ctx )
{
2018-10-15 22:51:07 +00:00
ctx - > dst . ssl = NULL ;
2018-10-17 13:28:21 +00:00
ctx - > dst . bev = prototcp_bufferevent_setup_child ( ctx , - 1 ) ;
2018-10-15 22:51:07 +00:00
if ( ! ctx - > dst . bev ) {
log_err_level_printf ( LOG_CRIT , " Error creating bufferevent \n " ) ;
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx - > conn , 1 ) ;
2018-10-17 13:28:21 +00:00
return - 1 ;
2018-10-15 22:51:07 +00:00
}
2018-10-29 18:38:42 +00:00
ctx - > dst . free = prototcp_bufferevent_free_and_close_fd ;
2018-10-17 13:28:21 +00:00
return 0 ;
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-17 13:28:21 +00:00
prototcp_connect_child ( pxy_conn_child_ctx_t * ctx )
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_connect_child: ENTER, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-17 13:28:21 +00:00
# endif /* DEBUG_PROXY */
/* create server-side socket and eventbuffer */
prototcp_setup_dst_child ( ctx ) ;
2018-10-15 22:51:07 +00:00
}
void
prototcp_fd_readcb ( UNUSED evutil_socket_t fd , UNUSED short what , void * arg )
{
pxy_conn_ctx_t * ctx = arg ;
2018-10-19 12:03:36 +00:00
2018-10-15 22:51:07 +00:00
# ifdef DEBUG_PROXY
2018-10-17 13:28:21 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_fd_readcb: ENTER, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-15 22:51:07 +00:00
pxy_conn_connect ( ctx ) ;
}
2019-03-05 22:09:02 +00:00
int
prototcp_try_send_userauth_msg ( struct bufferevent * bev , pxy_conn_ctx_t * ctx )
{
if ( ctx - > opts - > user_auth & & ! ctx - > user ) {
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_try_send_userauth_msg: Sending userauth message, fd=%d \n " , ctx - > fd ) ;
# endif /* DEBUG_PROXY */
pxy_discard_inbuf ( bev ) ;
evbuffer_add_printf ( bufferevent_get_output ( bev ) , USERAUTH_MSG , ctx - > opts - > user_auth_url ) ;
ctx - > sent_userauth_msg = 1 ;
return 1 ;
}
return 0 ;
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-22 21:18:48 +00:00
prototcp_bev_readcb_src ( struct bufferevent * bev , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_readcb_src: ENTER, size=%zu, fd=%d \n " ,
evbuffer_get_length ( bufferevent_get_input ( bev ) ) , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
if ( ctx - > dst . closed ) {
pxy_discard_inbuf ( bev ) ;
return ;
}
2019-03-05 22:09:02 +00:00
if ( prototcp_try_send_userauth_msg ( bev , ctx ) ) {
return ;
}
2018-10-15 22:51:07 +00:00
struct evbuffer * inbuf = bufferevent_get_input ( bev ) ;
struct evbuffer * outbuf = bufferevent_get_output ( ctx - > dst . bev ) ;
2018-10-20 21:25:01 +00:00
if ( ! ctx - > sent_sslproxy_header ) {
2018-10-20 12:29:51 +00:00
size_t packet_size = evbuffer_get_length ( inbuf ) ;
// +2 is for \r\n
2018-10-20 21:25:01 +00:00
unsigned char * packet = pxy_malloc_packet ( packet_size + ctx - > sslproxy_header_len + 2 , ctx ) ;
2018-10-20 12:29:51 +00:00
if ( ! packet ) {
return ;
}
2018-10-15 22:51:07 +00:00
2018-10-20 12:29:51 +00:00
evbuffer_remove ( inbuf , packet , packet_size ) ;
2018-10-15 22:51:07 +00:00
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_readcb_src: ORIG packet, size=%zu, fd=%d: \n %.*s \n " ,
2018-10-20 12:29:51 +00:00
packet_size , ctx - > fd , ( int ) packet_size , packet ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-20 12:29:51 +00:00
pxy_insert_sslproxy_header ( ctx , packet , & packet_size ) ;
evbuffer_add ( outbuf , packet , packet_size ) ;
2018-10-15 22:51:07 +00:00
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_readcb_src: NEW packet, size=%zu, fd=%d: \n %.*s \n " ,
2018-10-20 12:29:51 +00:00
packet_size , ctx - > fd , ( int ) packet_size , packet ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-18 22:31:10 +00:00
2018-10-20 12:29:51 +00:00
free ( packet ) ;
}
else {
evbuffer_add_buffer ( outbuf , inbuf ) ;
}
pxy_try_set_watermark ( bev , ctx , ctx - > dst . bev ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-22 21:18:48 +00:00
prototcp_bev_readcb_dst ( struct bufferevent * bev , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_readcb_dst: ENTER, size=%zu, fd=%d \n " ,
evbuffer_get_length ( bufferevent_get_input ( bev ) ) , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
if ( ctx - > src . closed ) {
pxy_discard_inbuf ( bev ) ;
return ;
}
struct evbuffer * inbuf = bufferevent_get_input ( bev ) ;
struct evbuffer * outbuf = bufferevent_get_output ( ctx - > src . bev ) ;
evbuffer_add_buffer ( outbuf , inbuf ) ;
2018-10-20 12:29:51 +00:00
pxy_try_set_watermark ( bev , ctx , ctx - > src . bev ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-22 21:18:48 +00:00
prototcp_bev_readcb_srvdst ( UNUSED struct bufferevent * bev , UNUSED pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
2018-10-20 21:25:01 +00:00
# ifdef DEBUG_PROXY
2018-10-22 13:12:07 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bev_readcb_srvdst: readcb called on srvdst, fd=%d \n " , ctx - > fd ) ;
2018-10-20 21:25:01 +00:00
# endif /* DEBUG_PROXY */
2018-10-22 21:18:48 +00:00
log_err_printf ( " prototcp_bev_readcb_srvdst: readcb called on srvdst \n " ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-22 21:18:48 +00:00
prototcp_bev_readcb_src_child ( struct bufferevent * bev , pxy_conn_child_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_readcb_src_child: ENTER, size=%zu, child fd=%d, fd=%d \n " ,
evbuffer_get_length ( bufferevent_get_input ( bev ) ) , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
if ( ctx - > dst . closed ) {
pxy_discard_inbuf ( bev ) ;
return ;
}
struct evbuffer * inbuf = bufferevent_get_input ( bev ) ;
struct evbuffer * outbuf = bufferevent_get_output ( ctx - > dst . bev ) ;
2018-10-20 21:25:01 +00:00
if ( ! ctx - > removed_sslproxy_header ) {
2018-10-20 12:29:51 +00:00
size_t packet_size = evbuffer_get_length ( inbuf ) ;
unsigned char * packet = pxy_malloc_packet ( packet_size , ctx - > conn ) ;
if ( ! packet ) {
return ;
}
2018-10-15 22:51:07 +00:00
2018-10-20 12:29:51 +00:00
evbuffer_remove ( inbuf , packet , packet_size ) ;
pxy_try_remove_sslproxy_header ( ctx , packet , & packet_size ) ;
evbuffer_add ( outbuf , packet , packet_size ) ;
2018-10-15 22:51:07 +00:00
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_readcb_src_child: NEW packet, size=%zu, child fd=%d, fd=%d: \n %.*s \n " ,
2018-10-20 12:29:51 +00:00
packet_size , ctx - > fd , ctx - > conn - > fd , ( int ) packet_size , packet ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-20 12:29:51 +00:00
free ( packet ) ;
} else {
evbuffer_add_buffer ( outbuf , inbuf ) ;
}
pxy_try_set_watermark ( bev , ctx - > conn , ctx - > dst . bev ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-22 21:18:48 +00:00
prototcp_bev_readcb_dst_child ( struct bufferevent * bev , pxy_conn_child_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_readcb_dst_child: ENTER, size=%zu, child fd=%d, fd=%d \n " ,
evbuffer_get_length ( bufferevent_get_input ( bev ) ) , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
if ( ctx - > src . closed ) {
pxy_discard_inbuf ( bev ) ;
return ;
}
struct evbuffer * inbuf = bufferevent_get_input ( bev ) ;
struct evbuffer * outbuf = bufferevent_get_output ( ctx - > src . bev ) ;
evbuffer_add_buffer ( outbuf , inbuf ) ;
2018-10-20 12:29:51 +00:00
pxy_try_set_watermark ( bev , ctx - > conn , ctx - > src . bev ) ;
2018-10-15 22:51:07 +00:00
}
2019-03-05 22:09:02 +00:00
int
prototcp_try_close_unauth_conn ( struct bufferevent * bev , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
2019-03-05 16:01:53 +00:00
if ( ctx - > opts - > user_auth & & ! ctx - > user ) {
size_t outbuflen = evbuffer_get_length ( bufferevent_get_output ( bev ) ) ;
if ( outbuflen > 0 ) {
2019-02-28 23:08:24 +00:00
# ifdef DEBUG_PROXY
2019-03-05 22:09:02 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_try_close_unauth_conn: Not closing unauth conn, outbuflen=%zu, fd=%d \n " , outbuflen , ctx - > fd ) ;
2019-02-28 23:08:24 +00:00
# endif /* DEBUG_PROXY */
2019-03-05 22:09:02 +00:00
} else if ( ctx - > sent_userauth_msg ) {
2019-03-05 16:01:53 +00:00
# ifdef DEBUG_PROXY
2019-03-05 22:09:02 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_try_close_unauth_conn: Closing unauth conn, fd=%d \n " , ctx - > fd ) ;
2019-03-05 16:01:53 +00:00
# endif /* DEBUG_PROXY */
pxy_conn_term ( ctx , 1 ) ;
2019-03-05 22:09:02 +00:00
} else {
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_try_close_unauth_conn: Not sent userauth msg yet, fd=%d \n " , ctx - > fd ) ;
# endif /* DEBUG_PROXY */
2019-03-05 16:01:53 +00:00
}
2019-03-05 22:09:02 +00:00
return 1 ;
}
return 0 ;
}
static void NONNULL ( 1 )
prototcp_bev_writecb_src ( struct bufferevent * bev , pxy_conn_ctx_t * ctx )
{
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_writecb_src: ENTER, fd=%d \n " , ctx - > fd ) ;
# endif /* DEBUG_PROXY */
if ( prototcp_try_close_unauth_conn ( bev , ctx ) ) {
2019-02-28 23:08:24 +00:00
return ;
}
2018-10-15 22:51:07 +00:00
if ( ctx - > dst . closed ) {
2018-10-29 18:38:42 +00:00
if ( pxy_try_close_conn_end ( & ctx - > src , ctx ) = = 1 ) {
2018-10-15 22:51:07 +00:00
# ifdef DEBUG_PROXY
2018-10-17 13:28:21 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_writecb_src: other->closed, terminate conn, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 1 ) ;
2018-10-15 22:51:07 +00:00
}
return ;
}
2018-10-20 12:29:51 +00:00
pxy_try_unset_watermark ( bev , ctx , & ctx - > dst ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-28 20:51:22 +00:00
static int NONNULL ( 1 , 2 )
2018-10-22 12:30:18 +00:00
prototcp_connect_dst ( struct bufferevent * bev , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-22 12:30:18 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_connect_dst: writecb before connected, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-22 12:30:18 +00:00
// @attention Sometimes dst write cb fires but not event cb, especially if the listener cb is not finished yet, so the conn stalls.
// This is a workaround for this error condition, nothing else seems to work.
// @attention Do not try to free the conn here, since the listener cb may not be finished yet, which causes multithreading issues
// XXX: Workaround, should find the real cause: BEV_OPT_DEFER_CALLBACKS?
ctx - > protoctx - > bev_eventcb ( bev , BEV_EVENT_CONNECTED , ctx ) ;
2018-10-28 20:51:22 +00:00
return pxy_bev_eventcb_postexec_logging_and_stats ( bev , BEV_EVENT_CONNECTED , ctx ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-22 21:18:48 +00:00
prototcp_bev_writecb_dst ( struct bufferevent * bev , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-17 13:28:21 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_writecb_dst: ENTER, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-22 12:30:18 +00:00
if ( ! ctx - > dst_connected ) {
2018-10-28 20:51:22 +00:00
if ( prototcp_connect_dst ( bev , ctx ) = = - 1 ) {
return ;
}
2018-10-22 12:30:18 +00:00
}
2018-10-15 22:51:07 +00:00
if ( ctx - > src . closed ) {
2018-10-29 18:38:42 +00:00
if ( pxy_try_close_conn_end ( & ctx - > dst , ctx ) = = 1 ) {
2018-10-15 22:51:07 +00:00
# ifdef DEBUG_PROXY
2018-10-17 13:28:21 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_writecb_dst: other->closed, terminate conn, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 0 ) ;
2018-10-15 22:51:07 +00:00
}
return ;
}
2018-10-20 12:29:51 +00:00
pxy_try_unset_watermark ( bev , ctx , & ctx - > src ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-22 21:18:48 +00:00
prototcp_bev_writecb_srvdst ( struct bufferevent * bev , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-22 13:12:07 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_writecb_srvdst: ENTER, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-18 22:31:10 +00:00
2018-10-22 13:12:07 +00:00
if ( ! ctx - > srvdst_connected ) {
pxy_connect_srvdst ( bev , ctx ) ;
2018-10-22 12:30:18 +00:00
}
2018-10-15 22:51:07 +00:00
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-22 21:18:48 +00:00
prototcp_bev_writecb_src_child ( struct bufferevent * bev , pxy_conn_child_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_writecb_src_child: ENTER, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
if ( ctx - > dst . closed ) {
2018-10-29 18:38:42 +00:00
if ( pxy_try_close_conn_end ( & ctx - > src , ctx - > conn ) = = 1 ) {
2018-10-15 22:51:07 +00:00
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_writecb_src_child: other->closed, terminate conn, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-22 20:13:42 +00:00
pxy_conn_term_child ( ctx ) ;
2018-10-15 22:51:07 +00:00
}
return ;
}
2018-10-20 12:29:51 +00:00
pxy_try_unset_watermark ( bev , ctx - > conn , & ctx - > dst ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 , 2 )
2018-10-22 12:30:18 +00:00
prototcp_connect_dst_child ( struct bufferevent * bev , pxy_conn_child_ctx_t * ctx )
2018-10-17 13:28:21 +00:00
{
# ifdef DEBUG_PROXY
2018-10-22 12:30:18 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_connect_dst_child: writecb before connected, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-17 13:28:21 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-22 12:30:18 +00:00
// @attention Sometimes dst write cb fires but not event cb, especially if the listener cb is not finished yet, so the conn stalls.
// This is a workaround for this error condition, nothing else seems to work.
// @attention Do not try to free the conn here, since the listener cb may not be finished yet, which causes multithreading issues
// XXX: Workaround, should find the real cause: BEV_OPT_DEFER_CALLBACKS?
ctx - > protoctx - > bev_eventcb ( bev , BEV_EVENT_CONNECTED , ctx ) ;
2018-10-28 20:51:22 +00:00
pxy_bev_eventcb_postexec_stats_child ( BEV_EVENT_CONNECTED , ctx ) ;
2018-10-17 13:28:21 +00:00
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-22 21:18:48 +00:00
prototcp_bev_writecb_dst_child ( struct bufferevent * bev , pxy_conn_child_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_writecb_dst_child: ENTER, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-22 12:30:18 +00:00
if ( ! ctx - > connected ) {
prototcp_connect_dst_child ( bev , ctx ) ;
}
2018-10-15 22:51:07 +00:00
if ( ctx - > src . closed ) {
2018-10-29 18:38:42 +00:00
if ( pxy_try_close_conn_end ( & ctx - > dst , ctx - > conn ) = = 1 ) {
2018-10-15 22:51:07 +00:00
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_writecb_dst_child: other->closed, terminate conn, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-22 20:13:42 +00:00
pxy_conn_term_child ( ctx ) ;
2018-10-15 22:51:07 +00:00
}
return ;
}
2018-10-20 12:29:51 +00:00
pxy_try_unset_watermark ( bev , ctx - > conn , & ctx - > src ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-22 13:12:07 +00:00
prototcp_close_srvdst ( pxy_conn_ctx_t * ctx )
2018-10-17 13:28:21 +00:00
{
# ifdef DEBUG_PROXY
2018-10-22 13:12:07 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINER , " prototcp_close_srvdst: Closing srvdst, srvdst fd=%d, fd=%d \n " , bufferevent_getfd ( ctx - > srvdst . bev ) , ctx - > fd ) ;
2018-10-17 13:28:21 +00:00
# endif /* DEBUG_PROXY */
2018-10-22 13:12:07 +00:00
// @attention Free the srvdst of the conn asap, we don't need it anymore, but we need its fd
// @attention When both eventcb and writecb for srvdst are enabled, either eventcb or writecb may get a NULL srvdst bev, causing a crash with signal 10.
// So, from this point on, we should check if srvdst is NULL or not.
2018-10-29 18:38:42 +00:00
ctx - > srvdst . free ( ctx - > srvdst . bev , ctx ) ;
2018-10-22 13:12:07 +00:00
ctx - > srvdst . bev = NULL ;
ctx - > srvdst . closed = 1 ;
2018-10-17 13:28:21 +00:00
}
2018-10-17 23:00:49 +00:00
static int NONNULL ( 1 )
2018-10-15 22:51:07 +00:00
prototcp_enable_src ( pxy_conn_ctx_t * ctx )
{
2018-10-17 13:28:21 +00:00
if ( prototcp_setup_src ( ctx ) = = - 1 ) {
2018-10-15 22:51:07 +00:00
return - 1 ;
}
bufferevent_setcb ( ctx - > src . bev , pxy_bev_readcb , pxy_bev_writecb , pxy_bev_eventcb , ctx ) ;
2018-10-22 13:12:07 +00:00
prototcp_close_srvdst ( ctx ) ;
2018-10-15 22:51:07 +00:00
if ( pxy_setup_child_listener ( ctx ) = = - 1 ) {
return - 1 ;
}
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINER , " prototcp_enable_src: Enabling src, %s, child_fd=%d, fd=%d \n " , ctx - > sslproxy_header , ctx - > child_fd , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-15 22:51:07 +00:00
// Now open the gates
bufferevent_enable ( ctx - > src . bev , EV_READ | EV_WRITE ) ;
return 0 ;
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 , 2 )
2018-10-20 12:29:51 +00:00
prototcp_bev_eventcb_connected_src ( UNUSED struct bufferevent * bev , UNUSED pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-17 13:28:21 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_eventcb_connected_src: ENTER, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 , 2 )
2018-10-15 22:51:07 +00:00
prototcp_bev_eventcb_connected_dst ( UNUSED struct bufferevent * bev , pxy_conn_ctx_t * ctx )
{
# ifdef DEBUG_PROXY
2018-10-17 13:28:21 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_eventcb_connected_dst: ENTER, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
ctx - > dst_connected = 1 ;
2018-10-22 13:12:07 +00:00
if ( ctx - > srvdst_connected & & ctx - > dst_connected & & ! ctx - > connected ) {
2018-10-19 23:03:21 +00:00
ctx - > connected = 1 ;
2018-10-17 13:28:21 +00:00
if ( prototcp_enable_src ( ctx ) = = - 1 ) {
return ;
}
2018-10-15 22:51:07 +00:00
}
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 , 2 )
2018-10-22 13:12:07 +00:00
prototcp_bev_eventcb_connected_srvdst ( UNUSED struct bufferevent * bev , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-22 13:12:07 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_eventcb_connected_srvdst: ENTER, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-22 13:12:07 +00:00
ctx - > srvdst_connected = 1 ;
2018-10-18 22:31:10 +00:00
2018-10-15 22:51:07 +00:00
// @attention Create and enable dst.bev before, but connect here, because we check if dst.bev is NULL elsewhere
if ( bufferevent_socket_connect ( ctx - > dst . bev , ( struct sockaddr * ) & ctx - > spec - > conn_dst_addr , ctx - > spec - > conn_dst_addrlen ) = = - 1 ) {
# ifdef DEBUG_PROXY
2018-10-22 13:12:07 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bev_eventcb_connected_srvdst: FAILED bufferevent_socket_connect for dst, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 23:03:21 +00:00
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 1 ) ;
2018-10-15 22:51:07 +00:00
return ;
}
2018-10-18 22:31:10 +00:00
2018-10-22 13:12:07 +00:00
if ( ctx - > srvdst_connected & & ctx - > dst_connected & & ! ctx - > connected ) {
2018-10-19 23:03:21 +00:00
ctx - > connected = 1 ;
2018-10-15 22:51:07 +00:00
if ( prototcp_enable_src ( ctx ) = = - 1 ) {
return ;
}
}
}
void
prototcp_bev_eventcb_eof_src ( struct bufferevent * bev , pxy_conn_ctx_t * ctx )
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_eventcb_eof_src: ENTER, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
pxy_log_dbg_evbuf_info ( ctx , & ctx - > src , & ctx - > dst ) ;
2018-10-18 22:31:10 +00:00
# endif /* DEBUG_PROXY */
2018-10-15 22:51:07 +00:00
if ( ! ctx - > connected ) {
log_err_level_printf ( LOG_WARNING , " EOF on outbound connection before connection establishment \n " ) ;
2018-10-20 21:25:01 +00:00
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bev_eventcb_eof_src: EOF on outbound connection before connection establishment, fd=%d \n " , ctx - > fd ) ;
# endif /* DEBUG_PROXY */
2018-10-15 22:51:07 +00:00
ctx - > dst . closed = 1 ;
} else if ( ! ctx - > dst . closed ) {
# ifdef DEBUG_PROXY
2018-10-17 13:28:21 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_eventcb_eof_src: !other->closed, terminate conn, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-18 22:31:10 +00:00
2018-10-28 20:51:22 +00:00
if ( pxy_try_consume_last_input ( bev , ctx ) = = - 1 ) {
return ;
}
2018-10-29 18:38:42 +00:00
pxy_try_close_conn_end ( & ctx - > dst , ctx ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-29 18:38:42 +00:00
pxy_try_disconnect ( ctx , & ctx - > src , & ctx - > dst , 1 ) ;
2018-10-15 22:51:07 +00:00
}
void
prototcp_bev_eventcb_eof_dst ( struct bufferevent * bev , pxy_conn_ctx_t * ctx )
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_eventcb_eof_dst: ENTER, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
pxy_log_dbg_evbuf_info ( ctx , & ctx - > dst , & ctx - > src ) ;
2018-10-18 22:31:10 +00:00
# endif /* DEBUG_PROXY */
2018-10-15 22:51:07 +00:00
if ( ! ctx - > connected ) {
log_err_level_printf ( LOG_WARNING , " EOF on outbound connection before connection establishment \n " ) ;
2018-10-20 21:25:01 +00:00
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bev_eventcb_eof_dst: EOF on outbound connection before connection establishment, fd=%d \n " , ctx - > fd ) ;
# endif /* DEBUG_PROXY */
2018-10-15 22:51:07 +00:00
ctx - > src . closed = 1 ;
} else if ( ! ctx - > src . closed ) {
# ifdef DEBUG_PROXY
2018-10-17 13:28:21 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_eventcb_eof_dst: !other->closed, terminate conn, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-18 22:31:10 +00:00
2018-10-28 20:51:22 +00:00
if ( pxy_try_consume_last_input ( bev , ctx ) = = - 1 ) {
return ;
}
2018-10-29 18:38:42 +00:00
pxy_try_close_conn_end ( & ctx - > src , ctx ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-29 18:38:42 +00:00
pxy_try_disconnect ( ctx , & ctx - > dst , & ctx - > src , 0 ) ;
2018-10-15 22:51:07 +00:00
}
void
2018-10-22 13:12:07 +00:00
prototcp_bev_eventcb_eof_srvdst ( UNUSED struct bufferevent * bev , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-22 13:12:07 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bev_eventcb_eof_srvdst: EOF on outbound connection before connection establishment, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-22 20:13:42 +00:00
log_err_level_printf ( LOG_WARNING , " EOF on outbound connection before connection establishment on srvdst \n " ) ;
pxy_conn_term ( ctx , 0 ) ;
2018-10-15 22:51:07 +00:00
}
void
2018-10-17 13:28:21 +00:00
prototcp_bev_eventcb_error_src ( UNUSED struct bufferevent * bev , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bev_eventcb_error_src: BEV_EVENT_ERROR, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
if ( ! ctx - > connected ) {
ctx - > dst . closed = 1 ;
} else if ( ! ctx - > dst . closed ) {
2018-10-29 18:38:42 +00:00
pxy_try_close_conn_end ( & ctx - > dst , ctx ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-29 18:38:42 +00:00
pxy_try_disconnect ( ctx , & ctx - > src , & ctx - > dst , 1 ) ;
2018-10-15 22:51:07 +00:00
}
void
2018-10-17 13:28:21 +00:00
prototcp_bev_eventcb_error_dst ( UNUSED struct bufferevent * bev , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bev_eventcb_error_dst: BEV_EVENT_ERROR, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
if ( ! ctx - > connected ) {
ctx - > src . closed = 1 ;
} else if ( ! ctx - > src . closed ) {
2018-10-29 18:38:42 +00:00
pxy_try_close_conn_end ( & ctx - > src , ctx ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-29 18:38:42 +00:00
pxy_try_disconnect ( ctx , & ctx - > dst , & ctx - > src , 0 ) ;
2018-10-15 22:51:07 +00:00
}
void
2018-10-22 13:12:07 +00:00
prototcp_bev_eventcb_error_srvdst ( UNUSED struct bufferevent * bev , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-22 13:12:07 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bev_eventcb_error_srvdst: BEV_EVENT_ERROR, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
if ( ! ctx - > connected ) {
# ifdef DEBUG_PROXY
2018-10-22 13:12:07 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bev_eventcb_error_srvdst: ERROR !ctx->connected, fd=%d \n " , ctx - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-18 22:31:10 +00:00
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 0 ) ;
2018-10-15 22:51:07 +00:00
}
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 , 2 )
2018-10-20 12:29:51 +00:00
prototcp_bev_eventcb_connected_src_child ( UNUSED struct bufferevent * bev , UNUSED pxy_conn_child_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_eventcb_connected_src_child: ENTER, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 , 2 )
2018-10-18 22:31:10 +00:00
prototcp_bev_eventcb_connected_dst_child ( UNUSED struct bufferevent * bev , pxy_conn_child_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_eventcb_connected_dst_child: ENTER, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
ctx - > connected = 1 ;
// @attention Create and enable src.bev before, but connect here, because we check if dst.bev is NULL elsewhere
bufferevent_enable ( ctx - > src . bev , EV_READ | EV_WRITE ) ;
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 , 2 )
2018-10-15 22:51:07 +00:00
prototcp_bev_eventcb_eof_src_child ( struct bufferevent * bev , pxy_conn_child_ctx_t * ctx )
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_eventcb_eof_src_child: ENTER, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-15 22:51:07 +00:00
pxy_log_dbg_evbuf_info ( ctx - > conn , & ctx - > src , & ctx - > dst ) ;
# endif /* DEBUG_PROXY */
// @todo How to handle the following case?
if ( ! ctx - > connected ) {
log_err_level_printf ( LOG_WARNING , " EOF on outbound connection before connection establishment \n " ) ;
2018-10-20 21:25:01 +00:00
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bev_eventcb_eof_src_child: EOF on outbound connection before connection establishment, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
# endif /* DEBUG_PROXY */
2018-10-15 22:51:07 +00:00
ctx - > dst . closed = 1 ;
} else if ( ! ctx - > dst . closed ) {
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_eventcb_eof_src_child: !other->closed, terminate conn, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-18 22:31:10 +00:00
2018-10-28 20:51:22 +00:00
if ( pxy_try_consume_last_input_child ( bev , ctx ) = = - 1 ) {
return ;
}
2018-10-29 18:38:42 +00:00
pxy_try_close_conn_end ( & ctx - > dst , ctx - > conn ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-18 22:31:10 +00:00
2018-10-29 18:38:42 +00:00
pxy_try_disconnect_child ( ctx , & ctx - > src , & ctx - > dst ) ;
2018-10-15 22:51:07 +00:00
}
void
prototcp_bev_eventcb_eof_dst_child ( struct bufferevent * bev , pxy_conn_child_ctx_t * ctx )
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_eventcb_eof_dst_child: ENTER, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-15 22:51:07 +00:00
pxy_log_dbg_evbuf_info ( ctx - > conn , & ctx - > dst , & ctx - > src ) ;
# endif /* DEBUG_PROXY */
// @todo How to handle the following case?
if ( ! ctx - > connected ) {
log_err_level_printf ( LOG_WARNING , " EOF on outbound connection before connection establishment \n " ) ;
2018-10-20 21:25:01 +00:00
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bev_eventcb_eof_dst_child: EOF on outbound connection before connection establishment, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
# endif /* DEBUG_PROXY */
2018-10-15 22:51:07 +00:00
ctx - > src . closed = 1 ;
} else if ( ! ctx - > src . closed ) {
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " prototcp_bev_eventcb_eof_dst_child: !other->closed, terminate conn, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
2018-10-18 22:31:10 +00:00
2018-10-28 20:51:22 +00:00
if ( pxy_try_consume_last_input_child ( bev , ctx ) = = - 1 ) {
return ;
}
2018-10-29 18:38:42 +00:00
pxy_try_close_conn_end ( & ctx - > src , ctx - > conn ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-18 22:31:10 +00:00
2018-10-29 18:38:42 +00:00
pxy_try_disconnect_child ( ctx , & ctx - > dst , & ctx - > src ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 , 2 )
2018-10-17 13:28:21 +00:00
prototcp_bev_eventcb_error_src_child ( UNUSED struct bufferevent * bev , pxy_conn_child_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bev_eventcb_error_src_child: BEV_EVENT_ERROR, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
if ( ! ctx - > connected ) {
/* the callout to the original destination failed,
* e . g . because it asked for client cert auth , so
* close the accepted socket and clean up */
ctx - > dst . closed = 1 ;
} else if ( ! ctx - > dst . closed ) {
/* if the other end is still open and doesn't have data
* to send , close it , otherwise its writecb will close
* it after writing what ' s left in the output buffer */
2018-10-29 18:38:42 +00:00
pxy_try_close_conn_end ( & ctx - > dst , ctx - > conn ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-18 22:31:10 +00:00
2018-10-29 18:38:42 +00:00
pxy_try_disconnect_child ( ctx , & ctx - > src , & ctx - > dst ) ;
2018-10-15 22:51:07 +00:00
}
void
2018-10-17 13:28:21 +00:00
prototcp_bev_eventcb_error_dst_child ( UNUSED struct bufferevent * bev , pxy_conn_child_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " prototcp_bev_eventcb_error_dst_child: BEV_EVENT_ERROR, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-15 22:51:07 +00:00
# endif /* DEBUG_PROXY */
if ( ! ctx - > connected ) {
/* the callout to the original destination failed,
* e . g . because it asked for client cert auth , so
* close the accepted socket and clean up */
ctx - > src . closed = 1 ;
} else if ( ! ctx - > src . closed ) {
/* if the other end is still open and doesn't have data
* to send , close it , otherwise its writecb will close
* it after writing what ' s left in the output buffer */
2018-10-29 18:38:42 +00:00
pxy_try_close_conn_end ( & ctx - > src , ctx - > conn ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-18 22:31:10 +00:00
2018-10-29 18:38:42 +00:00
pxy_try_disconnect_child ( ctx , & ctx - > dst , & ctx - > src ) ;
2018-10-15 22:51:07 +00:00
}
2018-10-17 13:28:21 +00:00
void
2018-10-22 21:18:48 +00:00
prototcp_bev_eventcb_src ( struct bufferevent * bev , short events , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
if ( events & BEV_EVENT_CONNECTED ) {
prototcp_bev_eventcb_connected_src ( bev , ctx ) ;
} else if ( events & BEV_EVENT_EOF ) {
prototcp_bev_eventcb_eof_src ( bev , ctx ) ;
} else if ( events & BEV_EVENT_ERROR ) {
prototcp_bev_eventcb_error_src ( bev , ctx ) ;
}
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-22 21:18:48 +00:00
prototcp_bev_eventcb_dst ( struct bufferevent * bev , short events , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
if ( events & BEV_EVENT_CONNECTED ) {
prototcp_bev_eventcb_connected_dst ( bev , ctx ) ;
} else if ( events & BEV_EVENT_EOF ) {
prototcp_bev_eventcb_eof_dst ( bev , ctx ) ;
} else if ( events & BEV_EVENT_ERROR ) {
prototcp_bev_eventcb_error_dst ( bev , ctx ) ;
}
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-22 21:18:48 +00:00
prototcp_bev_eventcb_srvdst ( struct bufferevent * bev , short events , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
if ( events & BEV_EVENT_CONNECTED ) {
2018-10-22 13:12:07 +00:00
prototcp_bev_eventcb_connected_srvdst ( bev , ctx ) ;
2018-10-15 22:51:07 +00:00
} else if ( events & BEV_EVENT_EOF ) {
2018-10-22 13:12:07 +00:00
prototcp_bev_eventcb_eof_srvdst ( bev , ctx ) ;
2018-10-15 22:51:07 +00:00
} else if ( events & BEV_EVENT_ERROR ) {
2018-10-22 13:12:07 +00:00
prototcp_bev_eventcb_error_srvdst ( bev , ctx ) ;
2018-10-15 22:51:07 +00:00
}
}
2018-10-19 12:03:36 +00:00
void
2018-10-22 21:18:48 +00:00
prototcp_bev_eventcb_src_child ( struct bufferevent * bev , short events , pxy_conn_child_ctx_t * ctx )
2018-10-19 12:03:36 +00:00
{
if ( events & BEV_EVENT_CONNECTED ) {
prototcp_bev_eventcb_connected_src_child ( bev , ctx ) ;
} else if ( events & BEV_EVENT_EOF ) {
prototcp_bev_eventcb_eof_src_child ( bev , ctx ) ;
} else if ( events & BEV_EVENT_ERROR ) {
prototcp_bev_eventcb_error_src_child ( bev , ctx ) ;
}
}
void
2018-10-22 21:18:48 +00:00
prototcp_bev_eventcb_dst_child ( struct bufferevent * bev , short events , pxy_conn_child_ctx_t * ctx )
2018-10-19 12:03:36 +00:00
{
if ( events & BEV_EVENT_CONNECTED ) {
prototcp_bev_eventcb_connected_dst_child ( bev , ctx ) ;
} else if ( events & BEV_EVENT_EOF ) {
prototcp_bev_eventcb_eof_dst_child ( bev , ctx ) ;
} else if ( events & BEV_EVENT_ERROR ) {
prototcp_bev_eventcb_error_dst_child ( bev , ctx ) ;
}
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-15 22:51:07 +00:00
prototcp_bev_readcb ( struct bufferevent * bev , void * arg )
{
pxy_conn_ctx_t * ctx = arg ;
if ( bev = = ctx - > src . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_readcb_src ( bev , ctx ) ;
2018-10-15 22:51:07 +00:00
} else if ( bev = = ctx - > dst . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_readcb_dst ( bev , ctx ) ;
2018-10-22 13:12:07 +00:00
} else if ( bev = = ctx - > srvdst . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_readcb_srvdst ( bev , ctx ) ;
2018-10-15 22:51:07 +00:00
} else {
2018-10-17 13:28:21 +00:00
log_err_printf ( " prototcp_bev_readcb: UNKWN conn end \n " ) ;
2018-10-15 22:51:07 +00:00
}
}
void
prototcp_bev_writecb ( struct bufferevent * bev , void * arg )
{
pxy_conn_ctx_t * ctx = arg ;
if ( bev = = ctx - > src . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_writecb_src ( bev , ctx ) ;
2018-10-15 22:51:07 +00:00
} else if ( bev = = ctx - > dst . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_writecb_dst ( bev , ctx ) ;
2018-10-22 13:12:07 +00:00
} else if ( bev = = ctx - > srvdst . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_writecb_srvdst ( bev , ctx ) ;
2018-10-15 22:51:07 +00:00
} else {
2018-10-17 13:28:21 +00:00
log_err_printf ( " prototcp_bev_writecb: UNKWN conn end \n " ) ;
2018-10-15 22:51:07 +00:00
}
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-15 22:51:07 +00:00
prototcp_bev_eventcb ( struct bufferevent * bev , short events , void * arg )
{
pxy_conn_ctx_t * ctx = arg ;
2018-10-17 13:28:21 +00:00
2018-10-15 22:51:07 +00:00
if ( bev = = ctx - > src . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_eventcb_src ( bev , events , ctx ) ;
2018-10-15 22:51:07 +00:00
} else if ( bev = = ctx - > dst . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_eventcb_dst ( bev , events , ctx ) ;
2018-10-22 13:12:07 +00:00
} else if ( bev = = ctx - > srvdst . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_eventcb_srvdst ( bev , events , ctx ) ;
2018-10-15 22:51:07 +00:00
} else {
2018-10-17 13:28:21 +00:00
log_err_printf ( " prototcp_bev_eventcb: UNKWN conn end \n " ) ;
2018-10-15 22:51:07 +00:00
}
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-15 22:51:07 +00:00
prototcp_bev_readcb_child ( struct bufferevent * bev , void * arg )
{
pxy_conn_child_ctx_t * ctx = arg ;
if ( bev = = ctx - > src . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_readcb_src_child ( bev , ctx ) ;
2018-10-15 22:51:07 +00:00
} else if ( bev = = ctx - > dst . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_readcb_dst_child ( bev , ctx ) ;
2018-10-15 22:51:07 +00:00
} else {
2018-10-17 13:28:21 +00:00
log_err_printf ( " prototcp_bev_readcb_child: UNKWN conn end \n " ) ;
2018-10-15 22:51:07 +00:00
}
}
void
prototcp_bev_writecb_child ( struct bufferevent * bev , void * arg )
{
pxy_conn_child_ctx_t * ctx = arg ;
if ( bev = = ctx - > src . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_writecb_src_child ( bev , ctx ) ;
2018-10-15 22:51:07 +00:00
} else if ( bev = = ctx - > dst . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_writecb_dst_child ( bev , ctx ) ;
2018-10-15 22:51:07 +00:00
} else {
2018-10-17 13:28:21 +00:00
log_err_printf ( " prototcp_bev_writecb_child: UNKWN conn end \n " ) ;
2018-10-15 22:51:07 +00:00
}
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 )
2018-10-15 22:51:07 +00:00
prototcp_bev_eventcb_child ( struct bufferevent * bev , short events , void * arg )
{
pxy_conn_child_ctx_t * ctx = arg ;
2018-10-17 13:28:21 +00:00
2018-10-15 22:51:07 +00:00
if ( bev = = ctx - > src . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_eventcb_src_child ( bev , events , ctx ) ;
2018-10-15 22:51:07 +00:00
} else if ( bev = = ctx - > dst . bev ) {
2018-10-22 21:18:48 +00:00
prototcp_bev_eventcb_dst_child ( bev , events , ctx ) ;
2018-10-15 22:51:07 +00:00
} else {
2018-10-17 13:28:21 +00:00
log_err_printf ( " prototcp_bev_eventcb_child: UNKWN conn end \n " ) ;
2018-10-15 22:51:07 +00:00
}
}
2018-10-17 23:00:49 +00:00
protocol_t
2018-10-15 22:51:07 +00:00
prototcp_setup ( pxy_conn_ctx_t * ctx )
{
ctx - > protoctx - > proto = PROTO_TCP ;
ctx - > protoctx - > connectcb = prototcp_conn_connect ;
ctx - > protoctx - > fd_readcb = prototcp_fd_readcb ;
ctx - > protoctx - > bev_readcb = prototcp_bev_readcb ;
ctx - > protoctx - > bev_writecb = prototcp_bev_writecb ;
ctx - > protoctx - > bev_eventcb = prototcp_bev_eventcb ;
return PROTO_TCP ;
}
2018-10-17 23:00:49 +00:00
protocol_t
2018-10-15 22:51:07 +00:00
prototcp_setup_child ( pxy_conn_child_ctx_t * ctx )
{
ctx - > protoctx - > proto = PROTO_TCP ;
ctx - > protoctx - > connectcb = prototcp_connect_child ;
ctx - > protoctx - > bev_readcb = prototcp_bev_readcb_child ;
ctx - > protoctx - > bev_writecb = prototcp_bev_writecb_child ;
ctx - > protoctx - > bev_eventcb = prototcp_bev_eventcb_child ;
return PROTO_TCP ;
}
/* vim: set noet ft=c: */