2018-02-27 19:20:58 +00:00
/*-
2015-02-24 18:19:20 +00:00
* SSLsplit - transparent SSL / TLS interception
2018-02-27 19:20:58 +00:00
* 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 > .
2012-04-13 12:47:30 +00:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
2018-02-27 19:20:58 +00:00
* 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 .
2012-04-13 12:47:30 +00:00
*
2018-02-27 19:20:58 +00:00
* 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 .
2012-04-13 12:47:30 +00:00
*/
# include "pxyconn.h"
2018-10-15 22:51:07 +00:00
# include "prototcp.h"
2018-10-16 00:37:07 +00:00
# include "protossl.h"
2018-10-08 18:42:49 +00:00
# include "protohttp.h"
2018-10-11 21:07:30 +00:00
# include "protoautossl.h"
2018-10-15 16:22:27 +00:00
# include "protopassthrough.h"
2018-10-08 18:42:49 +00:00
2017-07-15 18:51:20 +00:00
# include "privsep.h"
2012-04-13 12:47:30 +00:00
# include "sys.h"
# include "log.h"
# include "attrib.h"
2014-11-13 23:41:27 +00:00
# include "proc.h"
2012-04-13 12:47:30 +00:00
# include <string.h>
2018-10-17 13:28:21 +00:00
# include <arpa/inet.h>
# include <sys/param.h>
# include <assert.h>
2012-04-13 12:47:30 +00:00
# include <event2/listener.h>
2018-02-20 17:46:08 +00:00
# ifdef HAVE_NETFILTER
# include <glob.h>
# endif /* HAVE_NETFILTER */
2012-04-13 12:47:30 +00:00
/*
* Maximum size of data to buffer per connection direction before
* temporarily stopping to read data from the other end .
*/
# define OUTBUF_LIMIT (128*1024)
2018-10-20 21:25:01 +00:00
// @attention The order of names should match the order in protocol enum
char * protocol_names [ ] = {
// ERROR = -1
" PASSTHROUGH " , // = 0
" HTTP " ,
" HTTPS " ,
" POP3 " ,
" POP3S " ,
" SMTP " ,
" SMTPS " ,
" AUTOSSL " ,
" TCP " ,
" SSL " ,
} ;
2018-10-17 23:00:49 +00:00
static protocol_t NONNULL ( 1 )
2018-10-16 00:37:07 +00:00
pxy_setup_proto ( pxy_conn_ctx_t * ctx )
2018-10-06 00:24:14 +00:00
{
2018-10-15 10:42:40 +00:00
ctx - > protoctx = malloc ( sizeof ( proto_ctx_t ) ) ;
if ( ! ctx - > protoctx ) {
2018-10-11 21:07:30 +00:00
return PROTO_ERROR ;
}
2018-10-15 10:42:40 +00:00
memset ( ctx - > protoctx , 0 , sizeof ( proto_ctx_t ) ) ;
2018-10-11 21:07:30 +00:00
// Default to tcp
prototcp_setup ( ctx ) ;
2018-11-10 20:33:12 +00:00
protocol_t proto ;
2018-10-06 00:24:14 +00:00
if ( ctx - > spec - > upgrade ) {
2018-11-10 20:33:12 +00:00
proto = protoautossl_setup ( ctx ) ;
2018-10-06 00:24:14 +00:00
} else if ( ctx - > spec - > http ) {
if ( ctx - > spec - > ssl ) {
2018-11-10 20:33:12 +00:00
proto = protohttps_setup ( ctx ) ;
2018-10-06 00:24:14 +00:00
} else {
2018-11-10 20:33:12 +00:00
proto = protohttp_setup ( ctx ) ;
2018-10-06 00:24:14 +00:00
}
} else if ( ctx - > spec - > pop3 ) {
if ( ctx - > spec - > ssl ) {
2018-11-10 20:33:12 +00:00
proto = ( protossl_setup ( ctx ) ! = PROTO_ERROR ) ? PROTO_POP3S : PROTO_ERROR ;
2018-10-06 00:24:14 +00:00
} else {
2018-11-10 20:33:12 +00:00
proto = PROTO_POP3 ;
2018-10-06 00:24:14 +00:00
}
} else if ( ctx - > spec - > smtp ) {
if ( ctx - > spec - > ssl ) {
2018-11-10 20:33:12 +00:00
proto = ( protossl_setup ( ctx ) ! = PROTO_ERROR ) ? PROTO_SMTPS : PROTO_ERROR ;
2018-10-06 00:24:14 +00:00
} else {
2018-11-10 20:33:12 +00:00
proto = PROTO_SMTP ;
2018-10-06 00:24:14 +00:00
}
} else if ( ctx - > spec - > ssl ) {
2018-11-10 20:33:12 +00:00
proto = protossl_setup ( ctx ) ;
2018-10-06 00:24:14 +00:00
} else {
2018-11-10 20:33:12 +00:00
proto = PROTO_TCP ;
2018-10-06 00:24:14 +00:00
}
2018-11-10 17:46:39 +00:00
2018-11-10 20:33:12 +00:00
if ( proto = = PROTO_ERROR ) {
2018-11-10 17:46:39 +00:00
free ( ctx - > protoctx ) ;
}
2018-11-10 20:33:12 +00:00
return proto ;
2018-10-06 00:24:14 +00:00
}
2018-10-05 01:55:24 +00:00
2018-10-17 23:00:49 +00:00
static protocol_t NONNULL ( 1 )
2018-10-16 00:37:07 +00:00
pxy_setup_proto_child ( pxy_conn_child_ctx_t * ctx )
2018-10-08 18:42:49 +00:00
{
2018-10-15 10:42:40 +00:00
ctx - > protoctx = malloc ( sizeof ( proto_child_ctx_t ) ) ;
if ( ! ctx - > protoctx ) {
2018-10-11 21:07:30 +00:00
return PROTO_ERROR ;
}
2018-10-15 10:42:40 +00:00
memset ( ctx - > protoctx , 0 , sizeof ( proto_child_ctx_t ) ) ;
2018-10-11 21:07:30 +00:00
// Default to tcp
prototcp_setup_child ( ctx ) ;
2018-11-10 20:33:12 +00:00
protocol_t proto ;
2018-10-08 18:42:49 +00:00
if ( ctx - > conn - > spec - > upgrade ) {
2018-11-10 20:33:12 +00:00
proto = protoautossl_setup_child ( ctx ) ;
2018-10-08 18:42:49 +00:00
} else if ( ctx - > conn - > spec - > http ) {
if ( ctx - > conn - > spec - > ssl ) {
2018-11-10 20:33:12 +00:00
proto = protohttps_setup_child ( ctx ) ;
2018-10-08 18:42:49 +00:00
} else {
2018-11-10 20:33:12 +00:00
proto = protohttp_setup_child ( ctx ) ;
2018-10-08 18:42:49 +00:00
}
} else if ( ctx - > conn - > spec - > pop3 ) {
if ( ctx - > conn - > spec - > ssl ) {
2018-11-10 20:33:12 +00:00
proto = ( protossl_setup_child ( ctx ) ! = PROTO_ERROR ) ? PROTO_POP3S : PROTO_ERROR ;
2018-10-08 18:42:49 +00:00
} else {
2018-11-10 20:33:12 +00:00
proto = PROTO_POP3 ;
2018-10-08 18:42:49 +00:00
}
} else if ( ctx - > conn - > spec - > smtp ) {
if ( ctx - > conn - > spec - > ssl ) {
2018-11-10 20:33:12 +00:00
proto = ( protossl_setup_child ( ctx ) ! = PROTO_ERROR ) ? PROTO_SMTPS : PROTO_ERROR ;
2018-10-08 18:42:49 +00:00
} else {
2018-11-10 20:33:12 +00:00
proto = PROTO_SMTP ;
2018-10-08 18:42:49 +00:00
}
} else if ( ctx - > conn - > spec - > ssl ) {
2018-11-10 20:33:12 +00:00
proto = protossl_setup_child ( ctx ) ;
2018-10-08 18:42:49 +00:00
} else {
2018-11-10 20:33:12 +00:00
proto = PROTO_TCP ;
2018-10-08 18:42:49 +00:00
}
2018-11-10 17:46:39 +00:00
2018-11-10 20:33:12 +00:00
if ( proto = = PROTO_ERROR ) {
2018-11-10 17:46:39 +00:00
free ( ctx - > protoctx ) ;
}
2018-11-10 20:33:12 +00:00
return proto ;
2018-10-08 18:42:49 +00:00
}
2017-07-15 10:04:13 +00:00
static pxy_conn_ctx_t * MALLOC NONNULL ( 2 , 3 , 4 )
2017-07-14 19:34:15 +00:00
pxy_conn_ctx_new ( evutil_socket_t fd ,
pxy_thrmgr_ctx_t * thrmgr ,
proxyspec_t * spec , opts_t * opts ,
evutil_socket_t clisock )
2012-04-13 12:47:30 +00:00
{
2017-08-13 01:36:33 +00:00
# ifdef DEBUG_PROXY
2018-10-17 13:28:21 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_conn_ctx_new: ENTER, fd=%d \n " , fd ) ;
2017-08-13 01:36:33 +00:00
# endif /* DEBUG_PROXY */
2017-07-14 19:34:15 +00:00
2012-04-13 12:47:30 +00:00
pxy_conn_ctx_t * ctx = malloc ( sizeof ( pxy_conn_ctx_t ) ) ;
2017-07-12 13:46:51 +00:00
if ( ! ctx ) {
2017-10-14 22:39:30 +00:00
log_err_level_printf ( LOG_CRIT , " Error allocating memory \n " ) ;
2017-07-14 19:34:15 +00:00
evutil_closesocket ( fd ) ;
2012-04-13 12:47:30 +00:00
return NULL ;
2017-07-12 13:46:51 +00:00
}
2012-04-13 12:47:30 +00:00
memset ( ctx , 0 , sizeof ( pxy_conn_ctx_t ) ) ;
2017-07-15 01:07:42 +00:00
2018-11-09 09:32:16 +00:00
ctx - > id = thrmgr - > conn_count + + ;
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_conn_ctx_new: id=%llu, fd=%d \n " , ctx - > id , fd ) ;
# endif /* DEBUG_PROXY */
2018-10-12 18:59:16 +00:00
ctx - > type = CONN_TYPE_PARENT ;
2017-07-15 01:07:42 +00:00
ctx - > fd = fd ;
2018-09-22 23:02:15 +00:00
ctx - > conn = ctx ;
2017-07-15 01:07:42 +00:00
ctx - > thrmgr = thrmgr ;
ctx - > spec = spec ;
2018-10-11 21:07:30 +00:00
2018-10-16 00:37:07 +00:00
ctx - > proto = pxy_setup_proto ( ctx ) ;
2018-10-08 18:42:49 +00:00
if ( ctx - > proto = = PROTO_ERROR ) {
log_err_level_printf ( LOG_CRIT , " Error allocating memory \n " ) ;
evutil_closesocket ( fd ) ;
free ( ctx ) ;
return NULL ;
}
2018-10-11 21:07:30 +00:00
2017-07-15 01:07:42 +00:00
ctx - > opts = opts ;
ctx - > clisock = clisock ;
2017-07-15 10:04:13 +00:00
ctx - > ctime = time ( NULL ) ;
ctx - > atime = ctx - > ctime ;
2018-11-08 23:10:08 +00:00
2017-07-15 01:07:42 +00:00
ctx - > next = NULL ;
pxy_thrmgr_attach ( ctx ) ;
2018-11-08 23:10:08 +00:00
2014-11-14 14:36:16 +00:00
# ifdef HAVE_LOCAL_PROCINFO
2014-11-14 14:31:30 +00:00
ctx - > lproc . pid = - 1 ;
2014-11-14 14:36:16 +00:00
# endif /* HAVE_LOCAL_PROCINFO */
2017-05-29 09:22:23 +00:00
return ctx ;
}
2017-07-15 10:04:13 +00:00
static pxy_conn_child_ctx_t * MALLOC NONNULL ( 2 )
2018-09-22 23:02:15 +00:00
pxy_conn_ctx_new_child ( evutil_socket_t fd , pxy_conn_ctx_t * conn )
2017-06-25 11:21:32 +00:00
{
2018-09-22 23:02:15 +00:00
assert ( conn ! = NULL ) ;
2017-06-27 14:09:01 +00:00
2017-08-13 01:36:33 +00:00
# ifdef DEBUG_PROXY
2018-10-22 20:13:42 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_conn_ctx_new_child: ENTER, child fd=%d, fd=%d \n " , fd , conn - > fd ) ;
2017-08-13 01:36:33 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2017-07-11 22:45:15 +00:00
pxy_conn_child_ctx_t * ctx = malloc ( sizeof ( pxy_conn_child_ctx_t ) ) ;
2017-07-12 13:46:51 +00:00
if ( ! ctx ) {
2017-06-25 11:21:32 +00:00
return NULL ;
2017-07-12 13:46:51 +00:00
}
2017-07-11 22:45:15 +00:00
memset ( ctx , 0 , sizeof ( pxy_conn_child_ctx_t ) ) ;
2018-10-12 18:59:16 +00:00
ctx - > type = CONN_TYPE_CHILD ;
2017-06-25 11:21:32 +00:00
ctx - > fd = fd ;
2018-09-22 23:02:15 +00:00
ctx - > conn = conn ;
2018-10-11 21:07:30 +00:00
2018-10-16 00:37:07 +00:00
ctx - > proto = pxy_setup_proto_child ( ctx ) ;
2018-10-08 18:42:49 +00:00
if ( ctx - > proto = = PROTO_ERROR ) {
log_err_level_printf ( LOG_CRIT , " Error allocating memory \n " ) ;
evutil_closesocket ( fd ) ;
free ( ctx ) ;
return NULL ;
}
2018-10-11 21:07:30 +00:00
2018-09-22 23:02:15 +00:00
// @attention Child connections use the parent's event bases, otherwise we would get multithreading issues
pxy_thrmgr_attach_child ( conn ) ;
2017-06-25 11:21:32 +00:00
return ctx ;
}
2017-07-14 19:34:15 +00:00
static void NONNULL ( 1 )
pxy_conn_ctx_free_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 , " pxy_conn_ctx_free_child: ENTER, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2017-07-14 19:34:15 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-09-22 23:02:15 +00:00
pxy_thrmgr_detach_child ( ctx - > conn ) ;
2018-10-11 21:07:30 +00:00
// If the proto doesn't have special args, proto_free() callback is NULL
2018-10-15 10:42:40 +00:00
if ( ctx - > protoctx - > proto_free ) {
ctx - > protoctx - > proto_free ( ctx ) ;
2017-07-14 19:34:15 +00:00
}
2018-10-15 10:42:40 +00:00
free ( ctx - > protoctx ) ;
2017-07-14 19:34:15 +00:00
free ( ctx ) ;
}
2017-07-15 10:04:13 +00:00
static void NONNULL ( 1 , 2 )
2017-08-13 01:36:33 +00:00
pxy_conn_remove_child ( pxy_conn_child_ctx_t * child , pxy_conn_child_ctx_t * * head )
{
# ifdef DEBUG_PROXY
2018-10-22 20:13:42 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_conn_remove_child: ENTER, child fd=%d, fd=%d \n " , child - > fd , child - > conn - > fd ) ;
2017-08-13 01:36:33 +00:00
# endif /* DEBUG_PROXY */
2017-07-14 19:34:15 +00:00
if ( child - > fd = = ( * head ) - > fd ) {
* head = ( * head ) - > next ;
return ;
}
pxy_conn_child_ctx_t * current = ( * head ) - > next ;
pxy_conn_child_ctx_t * previous = * head ;
while ( current ! = NULL & & previous ! = NULL ) {
if ( child - > fd = = current - > fd ) {
previous - > next = current - > next ;
return ;
}
previous = current ;
current = current - > next ;
}
return ;
}
2018-10-22 20:13:42 +00:00
static void
2017-07-14 19:34:15 +00:00
pxy_conn_free_child ( pxy_conn_child_ctx_t * ctx )
{
2018-09-22 23:02:15 +00:00
assert ( ctx - > conn ! = NULL ) ;
2017-07-14 19:34:15 +00:00
2017-08-13 01:36:33 +00:00
# ifdef DEBUG_PROXY
2018-10-22 20:13:42 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_conn_free_child: ENTER, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2017-08-13 01:36:33 +00:00
# endif /* DEBUG_PROXY */
2017-07-14 19:34:15 +00:00
2018-10-29 18:38:42 +00:00
if ( ctx - > dst . bev ) {
ctx - > dst . free ( ctx - > dst . bev , ctx - > conn ) ;
ctx - > dst . bev = NULL ;
2017-07-14 19:34:15 +00:00
}
2018-10-29 18:38:42 +00:00
if ( ctx - > src . bev ) {
ctx - > src . free ( ctx - > src . bev , ctx - > conn ) ;
ctx - > src . bev = NULL ;
2017-07-14 19:34:15 +00:00
}
2018-09-22 23:02:15 +00:00
pxy_conn_remove_child ( ctx , & ctx - > conn - > children ) ;
2017-07-14 19:34:15 +00:00
pxy_conn_ctx_free_child ( ctx ) ;
}
2018-10-22 20:13:42 +00:00
void
pxy_conn_term_child ( pxy_conn_child_ctx_t * ctx )
{
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_conn_term_child: ENTER, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
# endif /* DEBUG_PROXY */
ctx - > term = 1 ;
}
2018-10-23 01:02:00 +00:00
void
pxy_conn_free_children ( pxy_conn_ctx_t * ctx )
{
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_conn_free_children: ENTER, fd=%d \n " , ctx - > fd ) ;
# endif /* DEBUG_PROXY */
// @attention Free the child ctxs asap, we need their fds
while ( ctx - > children ) {
pxy_conn_free_child ( ctx - > children ) ;
}
// @attention Parent may be closing before there was any child at all nor was child_evcl ever created
if ( ctx - > child_evcl ) {
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINER , " pxy_conn_free_children: Freeing child_evcl, child fd=%d, children->fd=%d, fd=%d \n " ,
ctx - > child_fd , ctx - > children ? ctx - > children - > fd : - 1 , ctx - > fd ) ;
# endif /* DEBUG_PROXY */
// @attention child_evcl was created with LEV_OPT_CLOSE_ON_FREE, so do not close ctx->child_fd
evconnlistener_free ( ctx - > child_evcl ) ;
ctx - > child_evcl = NULL ;
}
}
2018-10-15 10:42:40 +00:00
void
2017-07-25 13:07:39 +00:00
pxy_conn_ctx_free ( pxy_conn_ctx_t * ctx , int by_requestor )
2012-04-13 12:47:30 +00:00
{
# ifdef DEBUG_PROXY
2018-10-17 13:28:21 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_conn_ctx_free: ENTER, fd=%d \n " , ctx - > fd ) ;
2012-04-13 12:47:30 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-11-03 15:23:31 +00:00
if ( WANT_CONTENT_LOG ( ctx ) ) {
2017-07-25 13:07:39 +00:00
if ( log_content_close ( & ctx - > logctx , by_requestor ) = = - 1 ) {
2017-10-14 22:39:30 +00:00
log_err_level_printf ( LOG_WARNING , " Content log close failed \n " ) ;
2017-07-25 13:07:39 +00:00
}
}
2017-07-15 23:22:35 +00:00
pxy_thrmgr_detach ( ctx ) ;
2015-03-15 16:10:25 +00:00
if ( ctx - > srchost_str ) {
free ( ctx - > srchost_str ) ;
2012-04-13 12:47:30 +00:00
}
2015-03-15 16:10:25 +00:00
if ( ctx - > srcport_str ) {
free ( ctx - > srcport_str ) ;
}
if ( ctx - > dsthost_str ) {
free ( ctx - > dsthost_str ) ;
}
if ( ctx - > dstport_str ) {
free ( ctx - > dstport_str ) ;
2012-04-13 12:47:30 +00:00
}
2014-11-14 14:36:16 +00:00
# ifdef HAVE_LOCAL_PROCINFO
2014-11-14 14:31:30 +00:00
if ( ctx - > lproc . exec_path ) {
free ( ctx - > lproc . exec_path ) ;
2014-10-18 20:16:50 +00:00
}
2014-11-14 14:31:30 +00:00
if ( ctx - > lproc . user ) {
free ( ctx - > lproc . user ) ;
2014-10-18 20:16:50 +00:00
}
2014-11-14 14:31:30 +00:00
if ( ctx - > lproc . group ) {
free ( ctx - > lproc . group ) ;
2014-10-18 20:16:50 +00:00
}
2014-11-14 14:36:16 +00:00
# endif /* HAVE_LOCAL_PROCINFO */
2012-04-13 12:47:30 +00:00
if ( ctx - > ev ) {
event_free ( ctx - > ev ) ;
}
2018-10-20 21:25:01 +00:00
if ( ctx - > sslproxy_header ) {
free ( ctx - > sslproxy_header ) ;
2017-08-03 11:55:57 +00:00
}
2018-10-11 21:07:30 +00:00
// If the proto doesn't have special args, proto_free() callback is NULL
2018-10-15 10:42:40 +00:00
if ( ctx - > protoctx - > proto_free ) {
ctx - > protoctx - > proto_free ( ctx ) ;
2018-10-11 21:07:30 +00:00
}
2018-10-15 10:42:40 +00:00
free ( ctx - > protoctx ) ;
2017-07-15 01:07:42 +00:00
free ( ctx ) ;
2017-06-25 11:21:32 +00:00
}
2012-04-13 12:47:30 +00:00
2018-10-15 22:51:07 +00:00
void
2017-07-25 13:07:39 +00:00
pxy_conn_free ( pxy_conn_ctx_t * ctx , int by_requestor )
2017-07-01 15:08:28 +00:00
{
2017-08-13 01:36:33 +00:00
# ifdef DEBUG_PROXY
2018-10-22 20:13:42 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_conn_free: ENTER, fd=%d \n " , ctx - > fd ) ;
2017-08-13 01:36:33 +00:00
# endif /* DEBUG_PROXY */
2017-07-14 19:34:15 +00:00
2018-10-29 18:38:42 +00:00
if ( ! ctx - > src . closed ) {
if ( ctx - > src . bev ) {
ctx - > src . free ( ctx - > src . bev , ctx ) ;
ctx - > src . bev = NULL ;
2017-07-14 19:34:15 +00:00
} else {
2017-08-13 01:36:33 +00:00
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " pxy_conn_free: evutil_closesocket on NULL src->bev, fd=%d \n " , ctx - > fd ) ;
2017-08-13 01:36:33 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2017-07-14 19:34:15 +00:00
// @todo src fd may be open, although src.bev is NULL, where do we close the src fd?
2018-10-20 21:25:01 +00:00
evutil_closesocket ( ctx - > fd ) ;
2017-07-14 19:34:15 +00:00
}
2017-07-01 15:08:28 +00:00
}
2017-07-14 19:34:15 +00:00
2018-10-29 18:38:42 +00:00
if ( ctx - > srvdst . bev ) {
ctx - > srvdst . free ( ctx - > srvdst . bev , ctx ) ;
ctx - > srvdst . bev = NULL ;
2017-07-01 15:08:28 +00:00
}
2017-07-14 19:34:15 +00:00
2018-10-29 18:38:42 +00:00
if ( ctx - > dst . bev ) {
ctx - > dst . free ( ctx - > dst . bev , ctx ) ;
ctx - > dst . bev = NULL ;
2017-07-05 19:32:10 +00:00
}
2017-07-14 19:34:15 +00:00
2018-10-23 01:02:00 +00:00
pxy_conn_free_children ( ctx ) ;
2017-07-25 13:07:39 +00:00
pxy_conn_ctx_free ( ctx , by_requestor ) ;
2017-07-01 15:08:28 +00:00
}
2018-10-22 20:13:42 +00:00
void
pxy_conn_term ( pxy_conn_ctx_t * ctx , int by_requestor )
{
# ifdef DEBUG_PROXY
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_conn_term: ENTER, fd=%d \n " , ctx - > fd ) ;
# endif /* DEBUG_PROXY */
ctx - > term = 1 ;
ctx - > term_requestor = by_requestor ;
}
2018-10-11 21:07:30 +00:00
void
2018-10-15 22:51:07 +00:00
pxy_log_connect_nonhttp ( pxy_conn_ctx_t * ctx )
2018-10-11 21:07:30 +00:00
{
2018-10-15 22:51:07 +00:00
char * msg ;
# ifdef HAVE_LOCAL_PROCINFO
char * lpi = NULL ;
# endif /* HAVE_LOCAL_PROCINFO */
int rv ;
2018-10-11 21:07:30 +00:00
2018-10-15 22:51:07 +00:00
# ifdef HAVE_LOCAL_PROCINFO
if ( ctx - > opts - > lprocinfo ) {
rv = asprintf ( & lpi , " lproc:%i:%s:%s:%s " ,
ctx - > lproc . pid ,
STRORDASH ( ctx - > lproc . user ) ,
STRORDASH ( ctx - > lproc . group ) ,
STRORDASH ( ctx - > lproc . exec_path ) ) ;
if ( ( rv < 0 ) | | ! lpi ) {
ctx - > enomem = 1 ;
goto out ;
}
} else {
lpi = " " ;
2018-10-11 21:07:30 +00:00
}
2018-10-15 22:51:07 +00:00
# endif /* HAVE_LOCAL_PROCINFO */
2018-10-01 22:46:12 +00:00
2018-10-15 22:51:07 +00:00
/*
* The following ifdef ' s within asprintf arguments list generates
* warnings with - Wembedded - directive on some compilers .
* Not fixing the code in order to avoid more code duplication .
*/
2018-10-01 22:46:12 +00:00
2018-10-15 22:51:07 +00:00
if ( ! ctx - > src . ssl ) {
rv = asprintf ( & msg , " CONN: %s %s %s %s %s "
# ifdef HAVE_LOCAL_PROCINFO
" %s "
# endif /* HAVE_LOCAL_PROCINFO */
" \n " ,
2018-10-16 00:37:07 +00:00
ctx - > proto = = PROTO_PASSTHROUGH ? " passthrough " : ( ctx - > proto = = PROTO_POP3 ? " pop3 " : ( ctx - > proto = = PROTO_SMTP ? " smtp " : " tcp " ) ) ,
2018-10-15 22:51:07 +00:00
STRORDASH ( ctx - > srchost_str ) ,
STRORDASH ( ctx - > srcport_str ) ,
STRORDASH ( ctx - > dsthost_str ) ,
STRORDASH ( ctx - > dstport_str )
# ifdef HAVE_LOCAL_PROCINFO
, lpi
# endif /* HAVE_LOCAL_PROCINFO */
) ;
} else {
rv = asprintf ( & msg , " CONN: %s %s %s %s %s "
" sni:%s names:%s "
" sproto:%s:%s dproto:%s:%s "
" origcrt:%s usedcrt:%s "
# ifdef HAVE_LOCAL_PROCINFO
" %s "
# endif /* HAVE_LOCAL_PROCINFO */
" \n " ,
2018-10-16 00:37:07 +00:00
ctx - > proto = = PROTO_AUTOSSL ? " autossl " : ( ctx - > proto = = PROTO_POP3S ? " pop3s " : ( ctx - > proto = = PROTO_SMTPS ? " smtps " : " ssl " ) ) ,
2018-10-15 22:51:07 +00:00
STRORDASH ( ctx - > srchost_str ) ,
STRORDASH ( ctx - > srcport_str ) ,
STRORDASH ( ctx - > dsthost_str ) ,
STRORDASH ( ctx - > dstport_str ) ,
STRORDASH ( ctx - > sslctx - > sni ) ,
STRORDASH ( ctx - > sslctx - > ssl_names ) ,
SSL_get_version ( ctx - > src . ssl ) ,
SSL_get_cipher ( ctx - > src . ssl ) ,
2018-10-22 13:12:07 +00:00
! ctx - > srvdst . closed & & ctx - > srvdst . ssl ? SSL_get_version ( ctx - > srvdst . ssl ) : ctx - > sslctx - > srvdst_ssl_version ,
! ctx - > srvdst . closed & & ctx - > srvdst . ssl ? SSL_get_cipher ( ctx - > srvdst . ssl ) : ctx - > sslctx - > srvdst_ssl_cipher ,
2018-10-15 22:51:07 +00:00
STRORDASH ( ctx - > sslctx - > origcrtfpr ) ,
STRORDASH ( ctx - > sslctx - > usedcrtfpr )
# ifdef HAVE_LOCAL_PROCINFO
, lpi
# endif /* HAVE_LOCAL_PROCINFO */
) ;
2018-10-01 22:46:12 +00:00
}
2018-10-15 22:51:07 +00:00
if ( ( rv < 0 ) | | ! msg ) {
ctx - > enomem = 1 ;
goto out ;
2018-10-01 22:46:12 +00:00
}
2018-10-15 22:51:07 +00:00
if ( ! ctx - > opts - > detach ) {
log_err_printf ( " %s " , msg ) ;
} else if ( ctx - > opts - > statslog ) {
if ( log_conn ( msg ) = = - 1 ) {
log_err_level_printf ( LOG_WARNING , " Conn logging failed \n " ) ;
}
2018-10-01 22:46:12 +00:00
}
2018-10-15 22:51:07 +00:00
if ( ctx - > opts - > connectlog ) {
if ( log_connect_print_free ( msg ) = = - 1 ) {
free ( msg ) ;
log_err_level_printf ( LOG_WARNING , " Connection logging failed \n " ) ;
2018-10-01 22:46:12 +00:00
}
2018-10-15 22:51:07 +00:00
} else {
free ( msg ) ;
2018-10-01 22:46:12 +00:00
}
2018-10-15 22:51:07 +00:00
out :
# ifdef HAVE_LOCAL_PROCINFO
if ( lpi & & ctx - > opts - > lprocinfo ) {
free ( lpi ) ;
}
# endif /* HAVE_LOCAL_PROCINFO */
return ;
2018-10-01 22:46:12 +00:00
}
2018-10-15 22:51:07 +00:00
int
pxy_log_content_inbuf ( pxy_conn_ctx_t * ctx , struct evbuffer * inbuf , int req )
2018-10-11 21:07:30 +00:00
{
2018-11-30 11:28:51 +00:00
size_t sz = evbuffer_get_length ( inbuf ) ;
unsigned char * buf = malloc ( sz ) ;
if ( ! buf ) {
ctx - > conn - > enomem = 1 ;
return - 1 ;
}
if ( evbuffer_copyout ( inbuf , buf , sz ) = = - 1 ) {
free ( buf ) ;
return - 1 ;
}
logbuf_t * lb = logbuf_new_alloc ( sz , NULL ) ;
if ( ! lb ) {
free ( buf ) ;
ctx - > conn - > enomem = 1 ;
return - 1 ;
}
memcpy ( lb - > buf , buf , lb - > sz ) ;
free ( buf ) ;
if ( log_content_submit ( & ctx - > conn - > logctx , lb , req ) = = - 1 ) {
logbuf_free ( lb ) ;
log_err_level_printf ( LOG_WARNING , " Content log submission failed \n " ) ;
return - 1 ;
2018-10-15 22:51:07 +00:00
}
return 0 ;
2017-05-29 09:22:23 +00:00
}
2018-11-30 11:28:51 +00:00
# ifdef HAVE_LOCAL_PROCINFO
2018-10-15 16:22:27 +00:00
int
2018-11-30 21:36:03 +00:00
pxy_prepare_logging_local_procinfo ( pxy_conn_ctx_t * ctx )
2018-09-29 20:47:18 +00:00
{
2018-10-03 23:56:02 +00:00
if ( ctx - > opts - > lprocinfo ) {
/* fetch process info */
if ( proc_pid_for_addr ( & ctx - > lproc . pid ,
( struct sockaddr * ) & ctx - > lproc . srcaddr ,
ctx - > lproc . srcaddrlen ) = = 0 & &
ctx - > lproc . pid ! = - 1 & &
proc_get_info ( ctx - > lproc . pid ,
& ctx - > lproc . exec_path ,
& ctx - > lproc . uid ,
& ctx - > lproc . gid ) = = 0 ) {
/* fetch user/group names */
ctx - > lproc . user = sys_user_str (
ctx - > lproc . uid ) ;
ctx - > lproc . group = sys_group_str (
ctx - > lproc . gid ) ;
if ( ! ctx - > lproc . user | |
! ctx - > lproc . group ) {
ctx - > enomem = 1 ;
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 1 ) ;
2018-10-03 23:56:02 +00:00
return - 1 ;
2018-09-29 20:47:18 +00:00
}
}
2018-10-03 23:56:02 +00:00
}
return 0 ;
}
2018-11-30 11:28:51 +00:00
# endif /* HAVE_LOCAL_PROCINFO */
2018-10-03 23:56:02 +00:00
2018-11-30 11:28:51 +00:00
static int
2018-10-05 13:55:02 +00:00
pxy_prepare_logging ( pxy_conn_ctx_t * ctx )
2018-10-03 23:56:02 +00:00
{
/* prepare logging, part 2 */
2018-11-30 11:28:51 +00:00
# ifdef HAVE_LOCAL_PROCINFO
2018-10-03 23:56:02 +00:00
if ( WANT_CONNECT_LOG ( ctx ) | | WANT_CONTENT_LOG ( ctx ) ) {
2018-11-03 15:23:31 +00:00
if ( pxy_prepare_logging_local_procinfo ( ctx ) = = - 1 ) {
return - 1 ;
}
2018-09-29 20:47:18 +00:00
}
2018-11-30 11:28:51 +00:00
# endif /* HAVE_LOCAL_PROCINFO */
2018-09-29 20:47:18 +00:00
if ( WANT_CONTENT_LOG ( ctx ) ) {
if ( log_content_open ( & ctx - > logctx , ctx - > opts ,
2018-11-03 15:23:31 +00:00
( struct sockaddr * ) & ctx - > srcaddr ,
ctx - > srcaddrlen ,
( struct sockaddr * ) & ctx - > dstaddr ,
ctx - > dstaddrlen ,
2018-09-29 20:47:18 +00:00
STRORDASH ( ctx - > srchost_str ) , STRORDASH ( ctx - > srcport_str ) ,
STRORDASH ( ctx - > dsthost_str ) , STRORDASH ( ctx - > dstport_str ) ,
# ifdef HAVE_LOCAL_PROCINFO
ctx - > lproc . exec_path ,
ctx - > lproc . user ,
ctx - > lproc . group
# else /* HAVE_LOCAL_PROCINFO */
NULL , NULL , NULL
# endif /* HAVE_LOCAL_PROCINFO */
) = = - 1 ) {
if ( errno = = ENOMEM )
ctx - > enomem = 1 ;
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 1 ) ;
2018-09-29 20:47:18 +00:00
return - 1 ;
}
}
return 0 ;
}
2018-10-17 23:00:49 +00:00
static void NONNULL ( 1 , 2 )
2018-10-03 23:56:02 +00:00
pxy_log_dbg_connect_type ( pxy_conn_ctx_t * ctx , pxy_conn_desc_t * this )
2018-09-29 20:47:18 +00:00
{
2018-09-29 23:43:48 +00:00
if ( OPTS_DEBUG ( ctx - > opts ) ) {
if ( this - > ssl ) {
char * keystr ;
/* for SSL, we get two connect events */
2018-10-20 21:25:01 +00:00
log_dbg_printf ( " %s connected to [%s]:%s %s %s \n " ,
protocol_names [ ctx - > proto ] ,
2018-09-29 23:43:48 +00:00
STRORDASH ( ctx - > dsthost_str ) , STRORDASH ( ctx - > dstport_str ) ,
SSL_get_version ( this - > ssl ) , SSL_get_cipher ( this - > ssl ) ) ;
keystr = ssl_ssl_masterkey_to_str ( this - > ssl ) ;
if ( keystr ) {
log_dbg_print_free ( keystr ) ;
}
} else {
/* for TCP, we get only a dst connect event,
* since src was already connected from the
* beginning ; mirror SSL debug output anyway
* in order not to confuse anyone who might be
* looking closely at the output */
2018-10-20 21:25:01 +00:00
log_dbg_printf ( " %s connected to [%s]:%s \n " ,
protocol_names [ ctx - > proto ] ,
2018-09-29 23:43:48 +00:00
STRORDASH ( ctx - > dsthost_str ) , STRORDASH ( ctx - > dstport_str ) ) ;
2018-10-20 21:25:01 +00:00
log_dbg_printf ( " %s connected from [%s]:%s \n " ,
protocol_names [ ctx - > proto ] ,
2018-09-29 23:43:48 +00:00
STRORDASH ( ctx - > srchost_str ) , STRORDASH ( ctx - > srcport_str ) ) ;
}
}
}
2017-07-28 09:52:53 +00:00
2018-10-11 21:07:30 +00:00
void
2018-09-29 23:43:48 +00:00
pxy_log_connect_src ( pxy_conn_ctx_t * ctx )
{
/* log connection if we don't analyze any headers */
if ( ! ctx - > spec - > http & & ( WANT_CONNECT_LOG ( ctx ) | | ctx - > opts - > statslog ) ) {
pxy_log_connect_nonhttp ( ctx ) ;
}
2018-09-29 20:47:18 +00:00
2018-09-29 23:43:48 +00:00
if ( ctx - > src . ssl & & ctx - > opts - > certgendir ) {
/* write SSL certificates to gendir */
2018-10-16 00:37:07 +00:00
protossl_srccert_write ( ctx ) ;
2018-09-29 23:43:48 +00:00
}
2018-09-29 20:47:18 +00:00
2018-10-16 00:37:07 +00:00
if ( protossl_log_masterkey ( ctx , & ctx - > src ) = = - 1 ) {
2018-09-29 23:43:48 +00:00
return ;
2018-09-24 00:09:05 +00:00
}
2018-10-03 23:56:02 +00:00
pxy_log_dbg_connect_type ( ctx , & ctx - > src ) ;
2018-09-29 23:43:48 +00:00
}
2018-10-11 21:07:30 +00:00
void
2018-10-22 13:12:07 +00:00
pxy_log_connect_srvdst ( pxy_conn_ctx_t * ctx )
2018-09-29 23:43:48 +00:00
{
2018-10-22 13:12:07 +00:00
// @attention srvdst.bev may be NULL, if its writecb fires first
if ( ctx - > srvdst . bev ) {
2018-09-29 23:43:48 +00:00
/* log connection if we don't analyze any headers */
2018-10-22 13:12:07 +00:00
if ( ! ctx - > srvdst . ssl & & ! ctx - > spec - > http & & ( WANT_CONNECT_LOG ( ctx ) | | ctx - > opts - > statslog ) ) {
2018-09-29 23:43:48 +00:00
pxy_log_connect_nonhttp ( ctx ) ;
2018-10-15 22:51:07 +00:00
}
2018-09-29 23:43:48 +00:00
2018-10-22 13:12:07 +00:00
if ( protossl_log_masterkey ( ctx , & ctx - > srvdst ) = = - 1 ) {
2018-10-05 13:55:02 +00:00
return ;
}
2018-10-03 23:56:02 +00:00
2018-10-22 13:12:07 +00:00
pxy_log_dbg_connect_type ( ctx , & ctx - > srvdst ) ;
2018-10-15 10:42:40 +00:00
}
2018-09-29 23:43:48 +00:00
}
2018-10-20 12:29:51 +00:00
static void
2018-10-03 23:56:02 +00:00
pxy_log_dbg_disconnect ( pxy_conn_ctx_t * ctx )
2018-09-29 20:47:18 +00:00
{
2017-07-21 21:44:12 +00:00
/* we only get a single disconnect event here for both connections */
if ( OPTS_DEBUG ( ctx - > opts ) ) {
2018-10-20 21:25:01 +00:00
log_dbg_printf ( " %s disconnected to [%s]:%s, fd=%d \n " ,
protocol_names [ ctx - > proto ] ,
2017-10-26 15:57:46 +00:00
STRORDASH ( ctx - > dsthost_str ) , STRORDASH ( ctx - > dstport_str ) , ctx - > fd ) ;
2018-10-20 21:25:01 +00:00
log_dbg_printf ( " %s disconnected from [%s]:%s, fd=%d \n " ,
protocol_names [ ctx - > proto ] ,
2017-10-26 15:57:46 +00:00
STRORDASH ( ctx - > srchost_str ) , STRORDASH ( ctx - > srcport_str ) , ctx - > fd ) ;
2017-07-21 21:44:12 +00:00
}
2018-09-29 20:47:18 +00:00
}
2017-07-21 21:44:12 +00:00
2018-10-20 12:29:51 +00:00
static void
2018-10-15 22:51:07 +00:00
pxy_log_dbg_disconnect_child ( pxy_conn_child_ctx_t * ctx )
2018-09-29 20:47:18 +00:00
{
2018-10-15 22:51:07 +00:00
/* we only get a single disconnect event here for both connections */
if ( OPTS_DEBUG ( ctx - > conn - > opts ) ) {
2018-10-20 21:25:01 +00:00
log_dbg_printf ( " Child %s disconnected to [%s]:%s, child fd=%d, fd=%d \n " ,
protocol_names [ ctx - > proto ] ,
2018-10-15 22:51:07 +00:00
STRORDASH ( ctx - > conn - > dsthost_str ) , STRORDASH ( ctx - > conn - > dstport_str ) , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-20 21:25:01 +00:00
log_dbg_printf ( " Child %s disconnected from [%s]:%s, child fd=%d, fd=%d \n " ,
protocol_names [ ctx - > proto ] ,
2018-10-15 22:51:07 +00:00
STRORDASH ( ctx - > conn - > srchost_str ) , STRORDASH ( ctx - > conn - > srcport_str ) , ctx - > fd , ctx - > conn - > fd ) ;
}
}
2018-11-30 11:28:51 +00:00
# ifdef DEBUG_PROXY
void
2018-11-30 21:36:03 +00:00
pxy_log_dbg_evbuf_info ( pxy_conn_ctx_t * ctx , pxy_conn_desc_t * this , pxy_conn_desc_t * other )
2018-11-30 11:28:51 +00:00
{
// Use ctx->conn, because this function is used by child conns too
if ( OPTS_DEBUG ( ctx - > conn - > opts ) ) {
log_dbg_printf ( " evbuffer size at EOF: i:%zu o:%zu i:%zu o:%zu \n " ,
evbuffer_get_length ( bufferevent_get_input ( this - > bev ) ) ,
evbuffer_get_length ( bufferevent_get_output ( this - > bev ) ) ,
other - > closed ? 0 : evbuffer_get_length ( bufferevent_get_input ( other - > bev ) ) ,
other - > closed ? 0 : evbuffer_get_length ( bufferevent_get_output ( other - > bev ) ) ) ;
}
}
# endif /* DEBUG_PROXY */
2018-10-15 22:51:07 +00:00
unsigned char *
pxy_malloc_packet ( size_t sz , pxy_conn_ctx_t * ctx )
{
unsigned char * packet = malloc ( sz ) ;
if ( ! packet ) {
ctx - > enomem = 1 ;
return NULL ;
}
return packet ;
}
2017-08-13 01:36:33 +00:00
# ifdef DEBUG_PROXY
2018-10-15 22:51:07 +00:00
char * bev_names [ ] = {
" src " ,
" dst " ,
2018-10-22 13:12:07 +00:00
" srvdst " ,
2018-10-15 22:51:07 +00:00
" NULL " ,
" UNKWN "
2018-10-20 21:25:01 +00:00
} ;
2018-10-15 22:51:07 +00:00
static char *
pxy_get_event_name ( struct bufferevent * bev , pxy_conn_ctx_t * ctx )
{
// XXX: Used by watermark functions only, remove
if ( bev = = ctx - > src . bev ) {
return bev_names [ 0 ] ;
} else if ( bev = = ctx - > dst . bev ) {
return bev_names [ 1 ] ;
2018-10-22 13:12:07 +00:00
} else if ( bev = = ctx - > srvdst . bev ) {
2018-10-15 22:51:07 +00:00
return bev_names [ 2 ] ;
} else if ( bev = = NULL ) {
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " pxy_get_event_name: event_name=NULL \n " ) ;
return bev_names [ 3 ] ;
} else {
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " pxy_get_event_name: event_name=UNKWN \n " ) ;
return bev_names [ 4 ] ;
}
}
2017-08-13 01:36:33 +00:00
# endif /* DEBUG_PROXY */
2018-10-15 22:51:07 +00:00
void
2018-10-20 12:29:51 +00:00
pxy_try_set_watermark ( struct bufferevent * bev , pxy_conn_ctx_t * ctx , struct bufferevent * other )
2018-10-15 22:51:07 +00:00
{
if ( evbuffer_get_length ( bufferevent_get_output ( other ) ) > = OUTBUF_LIMIT ) {
# ifdef DEBUG_PROXY
2018-10-20 12:29:51 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " pxy_try_set_watermark: %s, fd=%d \n " , pxy_get_event_name ( bev , ctx ) , 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
/* temporarily disable data source;
* set an appropriate watermark . */
bufferevent_setwatermark ( other , EV_WRITE , OUTBUF_LIMIT / 2 , OUTBUF_LIMIT ) ;
bufferevent_disable ( bev , EV_READ ) ;
ctx - > thr - > set_watermarks + + ;
}
}
void
2018-10-20 12:29:51 +00:00
pxy_try_unset_watermark ( struct bufferevent * bev , pxy_conn_ctx_t * ctx , pxy_conn_desc_t * other )
2018-10-15 22:51:07 +00:00
{
if ( other - > bev & & ! ( bufferevent_get_enabled ( other - > bev ) & EV_READ ) ) {
# ifdef DEBUG_PROXY
2018-10-20 12:29:51 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " pxy_try_unset_watermark: %s, fd=%d \n " , pxy_get_event_name ( bev , ctx ) , 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
/* data source temporarily disabled;
* re - enable and reset watermark to 0. */
bufferevent_setwatermark ( bev , EV_WRITE , 0 , 0 ) ;
bufferevent_enable ( other - > bev , EV_READ ) ;
ctx - > thr - > unset_watermarks + + ;
}
}
void
pxy_discard_inbuf ( struct bufferevent * bev )
{
struct evbuffer * inbuf = bufferevent_get_input ( bev ) ;
size_t inbuf_size = evbuffer_get_length ( inbuf ) ;
log_dbg_printf ( " Warning: Drained %zu bytes (conn closed) \n " , inbuf_size ) ;
evbuffer_drain ( inbuf , inbuf_size ) ;
}
void
pxy_insert_sslproxy_header ( pxy_conn_ctx_t * ctx , unsigned char * packet , size_t * packet_size )
{
2018-10-19 12:03:36 +00:00
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINER , " pxy_insert_sslproxy_header: INSERT, fd=%d \n " , ctx - > fd ) ;
2018-10-19 12:03:36 +00:00
# endif /* DEBUG_PROXY */
2018-10-20 12:29:51 +00:00
// @attention Cannot use string manipulation functions; we are dealing with binary arrays here, not NULL-terminated strings
2018-10-20 21:25:01 +00:00
memmove ( packet + ctx - > sslproxy_header_len + 2 , packet , * packet_size ) ;
memcpy ( packet , ctx - > sslproxy_header , ctx - > sslproxy_header_len ) ;
memcpy ( packet + ctx - > sslproxy_header_len , " \r \n " , 2 ) ;
2018-11-10 20:33:12 +00:00
* packet_size + = ctx - > sslproxy_header_len + 2 ;
2018-10-20 21:25:01 +00:00
ctx - > sent_sslproxy_header = 1 ;
2018-10-15 22:51:07 +00:00
}
void
2018-10-20 12:29:51 +00:00
pxy_try_remove_sslproxy_header ( pxy_conn_child_ctx_t * ctx , unsigned char * packet , size_t * packet_size )
2018-10-15 22:51:07 +00:00
{
2018-10-20 21:25:01 +00:00
// @attention Cannot use string manipulation functions; we are dealing with binary arrays here, not NULL-terminated strings
unsigned char * pos = memmem ( packet , * packet_size , ctx - > conn - > sslproxy_header , ctx - > conn - > sslproxy_header_len ) ;
2018-10-15 22:51:07 +00:00
if ( pos ) {
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINER , " pxy_try_remove_sslproxy_header: REMOVE, 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-20 21:25:01 +00:00
memmove ( pos , pos + ctx - > conn - > sslproxy_header_len + 2 , * packet_size - ( pos - packet ) - ( ctx - > conn - > sslproxy_header_len + 2 ) ) ;
2018-11-10 20:33:12 +00:00
* packet_size - = ctx - > conn - > sslproxy_header_len + 2 ;
2018-10-20 21:25:01 +00:00
ctx - > removed_sslproxy_header = 1 ;
2018-10-15 22:51:07 +00:00
}
}
/*
* Callback for accept events on the socket listener bufferevent .
*/
static void
2018-10-16 00:37:07 +00:00
pxy_listener_acceptcb_child ( UNUSED struct evconnlistener * listener , evutil_socket_t fd ,
2018-10-15 22:51:07 +00:00
UNUSED struct sockaddr * peeraddr , UNUSED int peeraddrlen , void * arg )
{
pxy_conn_ctx_t * conn = arg ;
conn - > atime = time ( NULL ) ;
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_listener_acceptcb_child: ENTER, child fd=%d, conn->child_fd=%d, fd=%d \n " , fd , conn - > child_fd , conn - > fd ) ;
2018-10-15 22:51:07 +00:00
char * host , * port ;
if ( sys_sockaddr_str ( peeraddr , peeraddrlen , & host , & port ) = = 0 ) {
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_listener_acceptcb_child: peer addr=[%s]:%s, child fd=%d, fd=%d \n " , host , port , fd , conn - > fd ) ;
2018-10-15 22:51:07 +00:00
free ( host ) ;
free ( port ) ;
}
# endif /* DEBUG_PROXY */
2018-11-03 15:23:31 +00:00
if ( ! conn - > dstaddrlen ) {
2018-10-17 13:28:21 +00:00
log_err_level_printf ( LOG_CRIT , " Child no target address; aborting connection \n " ) ;
evutil_closesocket ( fd ) ;
2018-10-22 20:13:42 +00:00
pxy_conn_term ( conn , 1 ) ;
goto out ;
2018-10-17 13:28:21 +00:00
}
2018-10-15 22:51:07 +00:00
pxy_conn_child_ctx_t * ctx = pxy_conn_ctx_new_child ( fd , conn ) ;
if ( ! ctx ) {
log_err_level_printf ( LOG_CRIT , " Error allocating memory \n " ) ;
evutil_closesocket ( fd ) ;
2018-10-22 20:13:42 +00:00
pxy_conn_term ( conn , 1 ) ;
goto out ;
2018-10-15 22:51:07 +00:00
}
// Prepend child ctx to conn ctx child list
// @attention If the last child is deleted, the children list may become null again
ctx - > next = conn - > children ;
conn - > children = ctx ;
conn - > child_count + + ;
ctx - > idx = conn - > child_count ;
2018-10-19 12:03:36 +00:00
// @attention Do not enable src events here yet, they will be enabled after dst connects
2018-10-17 13:28:21 +00:00
if ( prototcp_setup_src_child ( ctx ) = = - 1 ) {
2018-10-22 20:13:42 +00:00
goto out ;
2018-10-15 22:51:07 +00:00
}
2018-10-21 19:01:46 +00:00
// src_fd is different from fd
2018-10-15 22:51:07 +00:00
ctx - > src_fd = bufferevent_getfd ( ctx - > src . bev ) ;
ctx - > conn - > child_src_fd = ctx - > src_fd ;
ctx - > conn - > thr - > max_fd = MAX ( ctx - > conn - > thr - > max_fd , ctx - > src_fd ) ;
/* create server-side socket and eventbuffer */
// Children rely on the findings of parent
ctx - > protoctx - > connectcb ( ctx ) ;
2018-10-22 20:13:42 +00:00
if ( ctx - > conn - > term | | ctx - > conn - > enomem ) {
goto out ;
}
2018-10-15 22:51:07 +00:00
bufferevent_enable ( ctx - > dst . bev , EV_READ | EV_WRITE ) ;
if ( OPTS_DEBUG ( ctx - > conn - > opts ) ) {
char * host , * port ;
2018-11-03 15:23:31 +00:00
if ( sys_sockaddr_str ( ( struct sockaddr * ) & ctx - > conn - > dstaddr , ctx - > conn - > dstaddrlen , & host , & port ) = = 0 ) {
2018-10-20 21:25:01 +00:00
log_dbg_printf ( " Child connecting to [%s]:%s \n " , host , port ) ;
2018-10-15 22:51:07 +00:00
free ( host ) ;
free ( port ) ;
2018-10-19 12:03:36 +00:00
} else {
2018-10-20 21:25:01 +00:00
log_dbg_printf ( " Child connecting to [?]:? \n " ) ;
2018-10-15 22:51:07 +00:00
}
2017-07-21 21:44:12 +00:00
}
2018-10-15 22:51:07 +00:00
/* initiate connection */
2018-11-29 23:49:37 +00:00
if ( bufferevent_socket_connect ( ctx - > dst . bev , ( struct sockaddr * ) & ctx - > conn - > dstaddr , ctx - > conn - > dstaddrlen ) = = - 1 ) {
pxy_conn_term ( conn , 1 ) ;
goto out ;
}
2018-10-15 22:51:07 +00:00
ctx - > dst_fd = bufferevent_getfd ( ctx - > dst . bev ) ;
ctx - > conn - > child_dst_fd = ctx - > dst_fd ;
ctx - > conn - > thr - > max_fd = MAX ( ctx - > conn - > thr - > max_fd , ctx - > dst_fd ) ;
2018-10-22 20:13:42 +00:00
out :
// @attention Do not use ctx->conn here, ctx may be uninitialized
// @attention Call pxy_conn_free() directly, not term functions here
// This is our last chance to close and free the conn
2018-10-28 22:59:26 +00:00
if ( conn - > term | | conn - > enomem ) {
pxy_conn_free ( conn , conn - > term ? conn - > term_requestor : 1 ) ;
2018-10-22 20:13:42 +00:00
}
2017-05-29 09:22:23 +00:00
}
2012-04-13 12:47:30 +00:00
2018-10-15 22:51:07 +00:00
int
pxy_setup_child_listener ( pxy_conn_ctx_t * ctx )
2018-09-29 20:47:18 +00:00
{
2018-10-15 22:51:07 +00:00
// @attention Defer child setup and evcl creation until after parent init is complete, otherwise (1) causes multithreading issues (proxy_listener_acceptcb is
// running on a different thread from the conn, and we only have thrmgr mutex), and (2) we need to clean up less upon errors.
// Child evcls use the evbase of the parent thread, otherwise we would get multithreading issues.
if ( ( ctx - > child_fd = privsep_client_opensock_child ( ctx - > clisock , ctx - > spec ) ) = = - 1 ) {
log_err_level_printf ( LOG_CRIT , " Error opening child socket: %s (%i) \n " , strerror ( errno ) , errno ) ;
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 1 ) ;
2018-10-15 22:51:07 +00:00
return - 1 ;
}
ctx - > thr - > max_fd = MAX ( ctx - > thr - > max_fd , ctx - > child_fd ) ;
2018-09-29 20:47:18 +00:00
2018-10-15 22:51:07 +00:00
// @attention Do not pass NULL as user-supplied pointer
2018-10-16 00:37:07 +00:00
struct evconnlistener * child_evcl = evconnlistener_new ( ctx - > thr - > evbase , pxy_listener_acceptcb_child , ctx , LEV_OPT_CLOSE_ON_FREE , 1024 , ctx - > child_fd ) ;
2018-10-15 22:51:07 +00:00
if ( ! child_evcl ) {
log_err_level_printf ( LOG_CRIT , " Error creating child evconnlistener: %s \n " , strerror ( errno ) ) ;
2018-09-29 20:47:18 +00:00
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " pxy_setup_child_listener: Error creating child evconnlistener: %s, fd=%d, child_fd=%d \n " , strerror ( errno ) , ctx - > fd , ctx - > child_fd ) ;
2018-09-29 20:47:18 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-15 22:51:07 +00:00
// @attention Cannot call proxy_listener_ctx_free() on child_evcl, child_evcl does not have any ctx with next listener
// @attention Close child fd separately, because child evcl does not exist yet, hence fd would not be closed by calling pxy_conn_free()
evutil_closesocket ( ctx - > child_fd ) ;
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 1 ) ;
2018-10-15 22:51:07 +00:00
return - 1 ;
2018-09-29 20:47:18 +00:00
}
2018-10-15 22:51:07 +00:00
ctx - > child_evcl = child_evcl ;
2018-09-29 20:47:18 +00:00
2018-10-15 22:51:07 +00:00
evconnlistener_set_error_cb ( child_evcl , proxy_listener_errorcb ) ;
2018-10-19 12:03:36 +00:00
2018-09-29 20:47:18 +00:00
# ifdef DEBUG_PROXY
2018-10-21 19:01:46 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINER , " pxy_setup_child_listener: Finished setting up child, NEW child_fd=%d, fd=%d \n " , ctx - > child_fd , ctx - > fd ) ;
2018-09-29 20:47:18 +00:00
# endif /* DEBUG_PROXY */
2018-10-15 22:51:07 +00:00
struct sockaddr_in child_listener_addr ;
socklen_t child_listener_len = sizeof ( child_listener_addr ) ;
2018-09-29 20:47:18 +00:00
2018-10-15 22:51:07 +00:00
if ( getsockname ( ctx - > child_fd , ( struct sockaddr * ) & child_listener_addr , & child_listener_len ) < 0 ) {
log_err_level_printf ( LOG_CRIT , " Error in getsockname: %s \n " , strerror ( errno ) ) ;
// @todo If getsockname() fails, should we really terminate the connection?
// @attention Do not close the child fd here, because child evcl exists now, hence pxy_conn_free() will close it while freeing child_evcl
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 1 ) ;
2018-10-15 22:51:07 +00:00
return - 1 ;
2018-09-29 20:47:18 +00:00
}
2018-10-15 22:51:07 +00:00
// @attention Children are always listening on an IPv4 loopback address
char addr [ INET_ADDRSTRLEN ] ;
if ( ! inet_ntop ( AF_INET , & child_listener_addr . sin_addr , addr , INET_ADDRSTRLEN ) ) {
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 1 ) ;
2018-10-15 22:51:07 +00:00
return - 1 ;
}
2018-10-03 23:56:02 +00:00
2018-10-19 23:03:21 +00:00
if ( pxy_set_dstaddr ( ctx ) = = - 1 ) {
return - 1 ;
}
2018-10-15 22:51:07 +00:00
// SSLproxy: [127.0.0.1]:34649,[192.168.3.24]:47286,[74.125.206.108]:465,s
// @todo Port may be less than 5 chars
// SSLproxy: + + [ + addr + ] + : + p + , + [ + srchost_str + ] + : + srcport_str + , + [ + dsthost_str + ] + : + dstport_str + , + s
// SSLPROXY_KEY_LEN + 1 + 1 + strlen(addr) + 1 + 1 + 5 + 1 + 1 + strlen(ctx->srchost_str) + 1 + 1 + strlen(ctx->srcport_str) + 1 + 1 + strlen(ctx->dsthost_str) + 1 + 1 + strlen(ctx->dstport_str) + 1 + 1
2018-10-20 21:25:01 +00:00
ctx - > sslproxy_header_len = SSLPROXY_KEY_LEN + strlen ( addr ) + strlen ( ctx - > srchost_str ) + strlen ( ctx - > srcport_str ) + strlen ( ctx - > dsthost_str ) + strlen ( ctx - > dstport_str ) + 19 ;
2018-10-19 12:03:36 +00:00
2018-10-15 22:51:07 +00:00
// @todo Always check malloc retvals. Should we close the conn if malloc fails?
// +1 for NULL
2018-10-20 21:25:01 +00:00
ctx - > sslproxy_header = malloc ( ctx - > sslproxy_header_len + 1 ) ;
if ( ! ctx - > sslproxy_header ) {
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 1 ) ;
2018-10-15 22:51:07 +00:00
return - 1 ;
}
2018-10-19 12:03:36 +00:00
2018-10-15 22:51:07 +00:00
// printf(3): "snprintf() will write at most size-1 of the characters (the size'th character then gets the terminating NULL)"
// So, +1 for NULL
2018-10-20 21:25:01 +00:00
snprintf ( ctx - > sslproxy_header , ctx - > sslproxy_header_len + 1 , " %s [%s]:%u,[%s]:%s,[%s]:%s,%s " ,
2018-10-15 22:51:07 +00:00
SSLPROXY_KEY , addr , ntohs ( child_listener_addr . sin_port ) , STRORNONE ( ctx - > srchost_str ) , STRORNONE ( ctx - > srcport_str ) ,
STRORNONE ( ctx - > dsthost_str ) , STRORNONE ( ctx - > dstport_str ) , ctx - > spec - > ssl ? " s " : " p " ) ;
return 0 ;
2018-09-29 20:47:18 +00:00
}
2018-10-15 22:51:07 +00:00
int
2018-10-29 18:38:42 +00:00
pxy_try_close_conn_end ( pxy_conn_desc_t * conn_end , pxy_conn_ctx_t * ctx )
2018-09-29 20:47:18 +00:00
{
2018-10-15 22:51:07 +00:00
/* 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 */
if ( evbuffer_get_length ( bufferevent_get_output ( conn_end - > bev ) ) = = 0 ) {
2018-09-29 20:47:18 +00:00
# ifdef DEBUG_PROXY
2018-10-17 13:28:21 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_try_close_conn_end: evbuffer_get_length(outbuf) == 0, terminate conn, fd=%d \n " , ctx - > fd ) ;
2018-09-29 20:47:18 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-29 18:38:42 +00:00
conn_end - > free ( conn_end - > bev , ctx ) ;
2018-10-15 22:51:07 +00:00
conn_end - > bev = NULL ;
conn_end - > closed = 1 ;
return 1 ;
}
return 0 ;
2018-09-29 20:47:18 +00:00
}
2018-10-28 20:51:22 +00:00
int
2018-10-22 13:12:07 +00:00
pxy_connect_srvdst ( struct bufferevent * bev , pxy_conn_ctx_t * ctx )
2018-10-11 21:07:30 +00:00
{
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 , " pxy_connect_srvdst: 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-11 21:07:30 +00:00
}
void
2018-10-29 18:38:42 +00:00
pxy_try_disconnect ( pxy_conn_ctx_t * ctx , pxy_conn_desc_t * this , pxy_conn_desc_t * other , int is_requestor )
2018-10-11 21:07:30 +00:00
{
2018-10-22 13:12:07 +00:00
// @attention srvdst should never reach here unless in passthrough mode, its bev may be NULL
2018-10-11 21:07:30 +00:00
this - > closed = 1 ;
2018-10-29 18:38:42 +00:00
this - > free ( this - > bev , ctx ) ;
2018-10-11 21:07:30 +00:00
this - > bev = NULL ;
if ( other - > closed ) {
# ifdef DEBUG_PROXY
2018-10-20 12:29:51 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_try_disconnect: other->closed, terminate conn, fd=%d \n " , ctx - > fd ) ;
2018-10-11 21:07:30 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-20 12:29:51 +00:00
// Uses only ctx to log disconnect, never any of the bevs
pxy_log_dbg_disconnect ( ctx ) ;
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , is_requestor ) ;
2018-10-11 21:07:30 +00:00
}
}
2018-10-15 22:51:07 +00:00
void
2018-10-29 18:38:42 +00:00
pxy_try_disconnect_child ( pxy_conn_child_ctx_t * ctx , pxy_conn_desc_t * this , pxy_conn_desc_t * other )
2018-10-11 21:07:30 +00:00
{
2018-10-15 22:51:07 +00:00
this - > closed = 1 ;
2018-10-29 18:38:42 +00:00
this - > free ( this - > bev , ctx - > conn ) ;
2018-10-15 22:51:07 +00:00
this - > bev = NULL ;
if ( other - > closed ) {
2018-10-11 21:07:30 +00:00
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_try_disconnect_child: other->closed, terminate conn, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2018-10-11 21:07:30 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-20 12:29:51 +00:00
// Uses only ctx to log disconnect, never any of the bevs
pxy_log_dbg_disconnect_child ( ctx ) ;
2018-10-22 20:13:42 +00:00
pxy_conn_term_child ( ctx ) ;
2018-10-11 21:07:30 +00:00
}
}
2018-10-28 20:51:22 +00:00
int
2018-10-20 12:29:51 +00:00
pxy_try_consume_last_input ( struct bufferevent * bev , pxy_conn_ctx_t * ctx )
2018-10-11 21:07:30 +00:00
{
2018-10-15 22:51:07 +00:00
/* if there is data pending in the closed connection,
* handle it here , otherwise it will be lost . */
if ( evbuffer_get_length ( bufferevent_get_input ( bev ) ) ) {
2018-10-11 21:07:30 +00:00
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " pxy_try_consume_last_input: evbuffer_get_length(inbuf) > 0, terminate conn, fd=%d \n " , ctx - > fd ) ;
2018-10-11 21:07:30 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-28 20:51:22 +00:00
if ( pxy_bev_readcb_preexec_logging_and_stats ( bev , ctx ) = = - 1 ) {
return - 1 ;
}
2018-10-15 22:51:07 +00:00
ctx - > protoctx - > bev_readcb ( bev , ctx ) ;
2018-10-11 21:07:30 +00:00
}
2018-10-28 20:51:22 +00:00
return 0 ;
2018-10-11 21:07:30 +00:00
}
2018-10-28 20:51:22 +00:00
int
2018-10-20 12:29:51 +00:00
pxy_try_consume_last_input_child ( struct bufferevent * bev , pxy_conn_child_ctx_t * ctx )
2017-05-29 09:22:23 +00:00
{
2018-10-15 22:51:07 +00:00
/* if there is data pending in the closed connection,
* handle it here , otherwise it will be lost . */
if ( evbuffer_get_length ( bufferevent_get_input ( bev ) ) ) {
2017-08-13 01:36:33 +00:00
# ifdef DEBUG_PROXY
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINE , " pxy_try_consume_last_input_child: evbuffer_get_length(inbuf) > 0, terminate conn, child fd=%d, fd=%d \n " , ctx - > fd , ctx - > conn - > fd ) ;
2017-08-13 01:36:33 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-10-28 20:51:22 +00:00
if ( pxy_bev_readcb_preexec_logging_and_stats_child ( bev , ctx ) = = - 1 ) {
return - 1 ;
}
2018-10-15 22:51:07 +00:00
ctx - > protoctx - > bev_readcb ( bev , ctx ) ;
2018-10-11 21:07:30 +00:00
}
2018-10-28 20:51:22 +00:00
return 0 ;
2018-10-11 21:07:30 +00:00
}
2018-09-24 00:09:05 +00:00
2018-10-15 22:51:07 +00:00
int
pxy_set_dstaddr ( pxy_conn_ctx_t * ctx )
2018-10-11 21:07:30 +00:00
{
2018-11-03 15:23:31 +00:00
if ( sys_sockaddr_str ( ( struct sockaddr * ) & ctx - > dstaddr , ctx - > dstaddrlen , & ctx - > dsthost_str , & ctx - > dstport_str ) ! = 0 ) {
2018-10-25 11:58:18 +00:00
// sys_sockaddr_str() may fail due to either malloc() or getnameinfo()
2018-10-15 22:51:07 +00:00
ctx - > enomem = 1 ;
2018-10-22 20:13:42 +00:00
pxy_conn_term ( ctx , 1 ) ;
2018-10-15 22:51:07 +00:00
return - 1 ;
}
return 0 ;
2012-04-13 12:47:30 +00:00
}
2018-10-28 20:51:22 +00:00
int
pxy_bev_readcb_preexec_logging_and_stats ( struct bufferevent * bev , pxy_conn_ctx_t * ctx )
2018-10-06 00:24:14 +00:00
{
2018-10-18 22:31:10 +00:00
if ( bev = = ctx - > src . bev | | bev = = ctx - > dst . bev ) {
struct evbuffer * inbuf = bufferevent_get_input ( bev ) ;
size_t inbuf_size = evbuffer_get_length ( inbuf ) ;
if ( bev = = ctx - > src . bev ) {
ctx - > thr - > intif_in_bytes + = inbuf_size ;
} else {
ctx - > thr - > intif_out_bytes + = inbuf_size ;
}
2018-11-30 11:28:51 +00:00
if ( WANT_CONTENT_LOG ( ctx - > conn ) ) {
if ( ctx - > proto ! = PROTO_PASSTHROUGH ) {
// HTTP content logging at this point may record certain header lines twice, if we have not seen all headers yet
return pxy_log_content_inbuf ( ctx , inbuf , ( bev = = ctx - > src . bev ) ) ;
}
2018-10-18 22:31:10 +00:00
}
}
2018-10-28 20:51:22 +00:00
return 0 ;
}
/*
* Callback for read events on the up - and downstream connection bufferevents .
* Called when there is data ready in the input evbuffer .
*/
void
pxy_bev_readcb ( struct bufferevent * bev , void * arg )
{
pxy_conn_ctx_t * ctx = arg ;
if ( pxy_bev_readcb_preexec_logging_and_stats ( bev , ctx ) = = - 1 ) {
2018-11-10 20:33:12 +00:00
goto out ;
2018-10-28 20:51:22 +00:00
}
2018-10-06 00:24:14 +00:00
2018-10-15 22:51:07 +00:00
if ( ! ctx - > connected ) {
2018-10-18 22:31:10 +00:00
log_err_level_printf ( LOG_CRIT , " pxy_bev_readcb: readcb called when not connected - aborting. \n " ) ;
2018-10-15 22:51:07 +00:00
log_exceptcb ( ) ;
2018-10-06 00:24:14 +00:00
return ;
}
2018-10-18 22:31:10 +00:00
ctx - > atime = time ( NULL ) ;
2018-10-15 22:51:07 +00:00
ctx - > protoctx - > bev_readcb ( bev , ctx ) ;
2018-10-21 21:18:27 +00:00
2018-11-10 20:33:12 +00:00
out :
2018-10-28 22:59:26 +00:00
if ( ctx - > term | | ctx - > enomem ) {
pxy_conn_free ( ctx , ctx - > term ? ctx - > term_requestor : ( bev = = ctx - > src . bev ) ) ;
2018-10-21 21:18:27 +00:00
}
2018-10-15 22:51:07 +00:00
}
2018-10-06 00:24:14 +00:00
2018-10-28 20:51:22 +00:00
int
pxy_bev_readcb_preexec_logging_and_stats_child ( struct bufferevent * bev , pxy_conn_child_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
2018-10-18 22:31:10 +00:00
struct evbuffer * inbuf = bufferevent_get_input ( bev ) ;
size_t inbuf_size = evbuffer_get_length ( inbuf ) ;
if ( bev = = ctx - > src . bev ) {
ctx - > conn - > thr - > extif_out_bytes + = inbuf_size ;
} else {
ctx - > conn - > thr - > extif_in_bytes + = inbuf_size ;
}
2018-11-30 11:28:51 +00:00
if ( WANT_CONTENT_LOG ( ctx - > conn ) ) {
if ( ctx - > proto ! = PROTO_PASSTHROUGH ) {
return pxy_log_content_inbuf ( ( pxy_conn_ctx_t * ) ctx , inbuf , ( bev = = ctx - > src . bev ) ) ;
}
2018-10-18 22:31:10 +00:00
}
2018-10-28 20:51:22 +00:00
return 0 ;
}
void
pxy_bev_readcb_child ( struct bufferevent * bev , void * arg )
{
pxy_conn_child_ctx_t * ctx = arg ;
if ( pxy_bev_readcb_preexec_logging_and_stats_child ( bev , ctx ) = = - 1 ) {
2018-11-10 20:33:12 +00:00
goto out ;
2018-10-28 20:51:22 +00:00
}
2018-10-15 22:51:07 +00:00
if ( ! ctx - > connected ) {
2018-10-18 22:31:10 +00:00
log_err_level_printf ( LOG_CRIT , " pxy_bev_readcb_child: readcb called when not connected - aborting. \n " ) ;
2018-10-15 22:51:07 +00:00
log_exceptcb ( ) ;
2018-10-06 00:24:14 +00:00
return ;
2013-05-26 22:03:05 +00:00
}
2018-10-18 22:31:10 +00:00
ctx - > conn - > atime = time ( NULL ) ;
2018-10-15 22:51:07 +00:00
ctx - > protoctx - > bev_readcb ( bev , ctx ) ;
2018-10-21 21:18:27 +00:00
2018-11-10 20:33:12 +00:00
out :
2018-10-28 22:59:26 +00:00
if ( ctx - > conn - > term | | ctx - > conn - > enomem ) {
pxy_conn_free ( ctx - > conn , ctx - > conn - > term ? ctx - > conn - > term_requestor : ( bev = = ctx - > src . bev ) ) ;
2018-10-22 20:13:42 +00:00
return ;
}
if ( ctx - > term ) {
pxy_conn_free_child ( ctx ) ;
2018-10-21 21:18:27 +00:00
}
2018-10-15 22:51:07 +00:00
}
/*
* Callback for write events on the up - and downstream connection bufferevents .
* Called when either all data from the output evbuffer has been written ,
* or if the outbuf is only half full again after having been full .
*/
void
pxy_bev_writecb ( struct bufferevent * bev , void * arg )
{
pxy_conn_ctx_t * ctx = arg ;
2018-10-18 22:31:10 +00:00
2018-10-15 22:51:07 +00:00
ctx - > atime = time ( NULL ) ;
ctx - > protoctx - > bev_writecb ( bev , ctx ) ;
2018-10-22 20:13:42 +00:00
2018-10-28 22:59:26 +00:00
if ( ctx - > term | | ctx - > enomem ) {
pxy_conn_free ( ctx , ctx - > term ? ctx - > term_requestor : ( bev = = ctx - > src . bev ) ) ;
2018-10-22 20:13:42 +00:00
}
2018-10-15 22:51:07 +00:00
}
void
pxy_bev_writecb_child ( struct bufferevent * bev , void * arg )
{
pxy_conn_child_ctx_t * ctx = arg ;
2018-10-18 22:31:10 +00:00
2018-10-15 22:51:07 +00:00
ctx - > conn - > atime = time ( NULL ) ;
ctx - > protoctx - > bev_writecb ( bev , ctx ) ;
2018-10-22 20:13:42 +00:00
2018-10-28 22:59:26 +00:00
if ( ctx - > conn - > term | | ctx - > conn - > enomem ) {
pxy_conn_free ( ctx - > conn , ctx - > conn - > term ? ctx - > conn - > term_requestor : ( bev = = ctx - > src . bev ) ) ;
2018-10-22 20:13:42 +00:00
return ;
}
if ( ctx - > term ) {
pxy_conn_free_child ( ctx ) ;
}
2018-10-15 22:51:07 +00:00
}
2018-10-28 20:51:22 +00:00
int
pxy_bev_eventcb_postexec_logging_and_stats ( struct bufferevent * bev , short events , pxy_conn_ctx_t * ctx )
2018-10-15 22:51:07 +00:00
{
2018-10-22 20:13:42 +00:00
if ( ctx - > term | | ctx - > enomem ) {
2018-10-28 20:51:22 +00:00
return - 1 ;
2018-10-22 12:30:18 +00:00
}
2018-10-20 12:29:51 +00:00
if ( events & BEV_EVENT_CONNECTED ) {
// Passthrough proto does its own connect logging
if ( ctx - > proto ! = PROTO_PASSTHROUGH ) {
if ( bev = = ctx - > src . bev ) {
2018-10-20 21:25:01 +00:00
// @todo When do we reach here? If proto is autossl? Otherwise, src is connected in acceptcb.
2018-10-20 12:29:51 +00:00
pxy_log_connect_src ( ctx ) ;
} else if ( ctx - > connected ) {
if ( pxy_prepare_logging ( ctx ) = = - 1 ) {
2018-10-28 20:51:22 +00:00
return - 1 ;
2018-10-20 12:29:51 +00:00
}
// Doesn't log connect if proto is http, http proto does its own connect logging
2018-10-22 13:12:07 +00:00
pxy_log_connect_srvdst ( ctx ) ;
2018-10-20 12:29:51 +00:00
}
}
2018-10-22 13:12:07 +00:00
if ( bev = = ctx - > srvdst . bev ) {
2018-10-20 12:29:51 +00:00
// src and other fd stats are collected in acceptcb functions
2018-10-22 13:12:07 +00:00
ctx - > srvdst_fd = bufferevent_getfd ( ctx - > srvdst . bev ) ;
ctx - > thr - > max_fd = MAX ( ctx - > thr - > max_fd , ctx - > srvdst_fd ) ;
2018-10-20 12:29:51 +00:00
// Passthrough proto may have a NULL dst.bev
if ( ctx - > dst . bev ) {
ctx - > dst_fd = bufferevent_getfd ( ctx - > dst . bev ) ;
ctx - > thr - > max_fd = MAX ( ctx - > thr - > max_fd , ctx - > dst_fd ) ;
}
}
}
2018-10-28 20:51:22 +00:00
return 0 ;
}
/*
* Callback for meta events on the up - and downstream connection bufferevents .
* Called when EOF has been reached , a connection has been made , and on errors .
*/
void
pxy_bev_eventcb ( struct bufferevent * bev , short events , void * arg )
{
pxy_conn_ctx_t * ctx = arg ;
ctx - > atime = time ( NULL ) ;
if ( events & BEV_EVENT_ERROR ) {
log_err_printf ( " Client-side BEV_EVENT_ERROR \n " ) ;
ctx - > thr - > errors + + ;
}
ctx - > protoctx - > bev_eventcb ( bev , events , arg ) ;
pxy_bev_eventcb_postexec_logging_and_stats ( bev , events , ctx ) ;
2018-10-22 20:13:42 +00:00
// Logging functions may set term or enomem too
// EOF eventcb may call readcb possibly causing enomem
2018-10-28 22:59:26 +00:00
if ( ctx - > term | | ctx - > enomem ) {
pxy_conn_free ( ctx , ctx - > term ? ctx - > term_requestor : ( bev = = ctx - > src . bev ) ) ;
2018-10-22 20:13:42 +00:00
}
2018-10-15 22:51:07 +00:00
}
2018-10-28 20:51:22 +00:00
void
pxy_bev_eventcb_postexec_stats_child ( short events , pxy_conn_child_ctx_t * ctx )
{
if ( events & BEV_EVENT_CONNECTED ) {
ctx - > conn - > thr - > max_fd = MAX ( ctx - > conn - > thr - > max_fd , MAX ( bufferevent_getfd ( ctx - > src . bev ) , bufferevent_getfd ( ctx - > dst . bev ) ) ) ;
}
}
2018-10-15 22:51:07 +00:00
void
pxy_bev_eventcb_child ( struct bufferevent * bev , short events , void * arg )
{
pxy_conn_child_ctx_t * ctx = arg ;
2018-10-18 22:31:10 +00:00
2018-10-15 22:51:07 +00:00
ctx - > conn - > atime = time ( NULL ) ;
2018-10-18 22:31:10 +00:00
if ( events & BEV_EVENT_ERROR ) {
log_err_printf ( " Server-side BEV_EVENT_ERROR \n " ) ;
ctx - > conn - > thr - > errors + + ;
}
2018-10-15 22:51:07 +00:00
ctx - > protoctx - > bev_eventcb ( bev , events , arg ) ;
2018-10-20 12:29:51 +00:00
2018-10-22 12:30:18 +00:00
// EOF eventcb may call readcb possibly causing enomem
2018-10-28 22:59:26 +00:00
if ( ctx - > conn - > term | | ctx - > conn - > enomem ) {
pxy_conn_free ( ctx - > conn , ctx - > conn - > term ? ctx - > conn - > term_requestor : ( bev = = ctx - > src . bev ) ) ;
2018-10-22 20:13:42 +00:00
return ;
}
if ( ctx - > term ) {
pxy_conn_free_child ( ctx ) ;
return ;
2018-10-22 12:30:18 +00:00
}
2018-10-28 20:51:22 +00:00
pxy_bev_eventcb_postexec_stats_child ( events , ctx ) ;
2018-10-06 00:24:14 +00:00
}
2017-05-29 09:22:23 +00:00
2018-10-06 00:24:14 +00:00
/*
* Complete the connection . This gets called after finding out where to
* connect to .
*/
2018-10-15 22:51:07 +00:00
void
2018-10-06 00:24:14 +00:00
pxy_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 , " pxy_conn_connect: ENTER, fd=%d \n " , ctx - > fd ) ;
2018-10-06 00:24:14 +00:00
# endif /* DEBUG_PROXY */
2018-10-19 12:03:36 +00:00
2018-11-03 15:23:31 +00:00
if ( ! ctx - > dstaddrlen ) {
2018-10-06 00:24:14 +00:00
log_err_level_printf ( LOG_CRIT , " No target address; aborting connection \n " ) ;
evutil_closesocket ( ctx - > fd ) ;
pxy_conn_ctx_free ( ctx , 1 ) ;
return ;
}
if ( OPTS_DEBUG ( ctx - > opts ) ) {
char * host , * port ;
2018-11-03 15:23:31 +00:00
if ( sys_sockaddr_str ( ( struct sockaddr * ) & ctx - > dstaddr , ctx - > dstaddrlen , & host , & port ) = = 0 ) {
2018-10-06 00:24:14 +00:00
log_dbg_printf ( " Connecting to [%s]:%s \n " , host , port ) ;
free ( host ) ;
free ( port ) ;
2018-10-19 12:03:36 +00:00
} else {
log_dbg_printf ( " Connecting to [?]:? \n " ) ;
2018-10-06 00:24:14 +00:00
}
}
2018-10-15 10:42:40 +00:00
ctx - > protoctx - > connectcb ( ctx ) ;
2018-10-22 20:13:42 +00:00
2018-10-28 22:59:26 +00:00
if ( ctx - > term | | ctx - > enomem ) {
pxy_conn_free ( ctx , ctx - > term ? ctx - > term_requestor : 1 ) ;
2018-10-22 20:13:42 +00:00
}
2017-07-16 14:10:18 +00:00
// @attention Do not do anything else with the ctx after connecting socket, otherwise if pxy_bev_eventcb fires on error, such as due to "No route to host",
// the conn is closed and freed up, and we get multithreading issues, e.g. signal 11. We are on the thrmgr thread. So, just return.
2017-06-27 14:09:01 +00:00
}
2012-04-13 12:47:30 +00:00
/*
* The src fd is readable . This is used to sneak - preview the SNI on SSL
* connections . If ctx - > ev is NULL , it was called manually for a non - SSL
* connection . If ctx - > passthrough is set , it was called a second time
* after the first ssl callout failed because of client cert auth .
*/
2018-10-15 16:22:27 +00:00
void
2018-10-06 00:24:14 +00:00
pxy_fd_readcb ( evutil_socket_t fd , UNUSED short what , void * arg )
{
pxy_conn_ctx_t * ctx = arg ;
2018-10-18 22:31:10 +00:00
2018-10-06 00:24:14 +00:00
# ifdef DEBUG_PROXY
2018-10-17 13:28:21 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_fd_readcb: ENTER, fd=%d \n " , ctx - > fd ) ;
2018-10-06 00:24:14 +00:00
# endif /* DEBUG_PROXY */
ctx - > atime = time ( NULL ) ;
2018-10-15 10:42:40 +00:00
ctx - > protoctx - > fd_readcb ( fd , what , arg ) ;
2018-10-06 00:24:14 +00:00
}
2012-04-13 12:47:30 +00:00
/*
* Callback for accept events on the socket listener bufferevent .
* Called when a new incoming connection has been accepted .
* Initiates the connection to the server . The incoming connection
* from the client is not being activated until we have a successful
* connection to the server , because we need the server ' s certificate
* in order to set up the SSL session to the client .
* For consistency , plain TCP works the same way , even if we could
* start reading from the client while waiting on the connection to
* the server to connect .
*/
2017-07-11 22:45:15 +00:00
void
2012-04-13 12:47:30 +00:00
pxy_conn_setup ( evutil_socket_t fd ,
struct sockaddr * peeraddr , int peeraddrlen ,
2017-07-11 22:45:15 +00:00
pxy_thrmgr_ctx_t * thrmgr ,
proxyspec_t * spec , opts_t * opts ,
evutil_socket_t clisock )
2012-04-13 12:47:30 +00:00
{
2017-08-13 01:36:33 +00:00
# ifdef DEBUG_PROXY
2018-10-17 13:28:21 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_conn_setup: ENTER, fd=%d \n " , fd ) ;
2017-05-29 09:22:23 +00:00
2017-07-11 22:45:15 +00:00
char * host , * port ;
2017-08-13 01:36:33 +00:00
if ( sys_sockaddr_str ( peeraddr , peeraddrlen , & host , & port ) = = 0 ) {
2018-10-20 21:25:01 +00:00
log_dbg_level_printf ( LOG_DBG_MODE_FINEST , " pxy_conn_setup: peer addr=[%s]:%s, fd=%d \n " , host , port , fd ) ;
2017-07-11 22:45:15 +00:00
free ( host ) ;
free ( port ) ;
}
2017-08-13 01:36:33 +00:00
# endif /* DEBUG_PROXY */
2017-07-11 22:45:15 +00:00
2017-07-14 19:34:15 +00:00
/* create per connection state and attach to thread */
pxy_conn_ctx_t * ctx = pxy_conn_ctx_new ( fd , thrmgr , spec , opts , clisock ) ;
2012-04-13 12:47:30 +00:00
if ( ! ctx ) {
2017-10-14 22:39:30 +00:00
log_err_level_printf ( LOG_CRIT , " Error allocating memory \n " ) ;
2017-07-25 13:07:39 +00:00
evutil_closesocket ( fd ) ;
2017-07-11 22:45:15 +00:00
return ;
2012-04-13 12:47:30 +00:00
}
2017-07-29 21:34:46 +00:00
2012-04-13 12:47:30 +00:00
ctx - > af = peeraddr - > sa_family ;
2017-07-29 21:34:46 +00:00
ctx - > thr - > max_fd = MAX ( ctx - > thr - > max_fd , ctx - > fd ) ;
2012-04-13 12:47:30 +00:00
/* determine original destination of connection */
if ( spec - > natlookup ) {
/* NAT engine lookup */
2018-11-03 15:23:31 +00:00
ctx - > dstaddrlen = sizeof ( struct sockaddr_storage ) ;
if ( spec - > natlookup ( ( struct sockaddr * ) & ctx - > dstaddr , & ctx - > dstaddrlen , fd , peeraddr , peeraddrlen ) = = - 1 ) {
2018-09-27 14:36:52 +00:00
log_err_printf ( " Connection not found in NAT state table, aborting connection \n " ) ;
2012-04-13 12:47:30 +00:00
evutil_closesocket ( fd ) ;
2017-07-25 13:07:39 +00:00
pxy_conn_ctx_free ( ctx , 1 ) ;
2017-07-11 22:45:15 +00:00
return ;
2012-04-13 12:47:30 +00:00
}
} else if ( spec - > connect_addrlen > 0 ) {
/* static forwarding */
2018-11-03 15:23:31 +00:00
ctx - > dstaddrlen = spec - > connect_addrlen ;
memcpy ( & ctx - > dstaddr , & spec - > connect_addr , ctx - > dstaddrlen ) ;
2012-04-13 12:47:30 +00:00
} else {
/* SNI mode */
2017-07-15 01:07:42 +00:00
if ( ! ctx - > spec - > ssl ) {
2012-04-13 12:47:30 +00:00
/* if this happens, the proxyspec parser is broken */
2018-09-27 14:36:52 +00:00
log_err_printf ( " SNI mode used for non-SSL connection; aborting connection \n " ) ;
2012-04-13 12:47:30 +00:00
evutil_closesocket ( fd ) ;
2017-07-25 13:07:39 +00:00
pxy_conn_ctx_free ( ctx , 1 ) ;
2017-07-11 22:45:15 +00:00
return ;
2012-04-13 12:47:30 +00:00
}
}
2018-09-27 14:36:52 +00:00
if ( sys_sockaddr_str ( peeraddr , peeraddrlen , & ctx - > srchost_str , & ctx - > srcport_str ) ! = 0 ) {
2017-08-11 13:53:46 +00:00
goto memout ;
}
2017-07-11 22:45:15 +00:00
/* prepare logging, part 1 */
2018-11-03 15:23:31 +00:00
if ( opts - > pcaplog
# ifndef WITHOUT_MIRROR
| | opts - > mirrorif
# endif /* !WITHOUT_MIRROR */
2017-07-11 22:45:15 +00:00
# ifdef HAVE_LOCAL_PROCINFO
2018-11-03 15:23:31 +00:00
| | opts - > lprocinfo
2017-07-11 22:45:15 +00:00
# endif /* HAVE_LOCAL_PROCINFO */
2018-11-03 15:23:31 +00:00
) {
ctx - > srcaddrlen = peeraddrlen ;
memcpy ( & ctx - > srcaddr , peeraddr , ctx - > srcaddrlen ) ;
2017-07-11 22:45:15 +00:00
}
2017-06-10 18:50:03 +00:00
/* for SSL, defer dst connection setup to initial_readcb */
2017-07-15 01:07:42 +00:00
if ( ctx - > spec - > ssl ) {
2018-10-15 10:42:40 +00:00
ctx - > ev = event_new ( ctx - > evbase , fd , EV_READ , ctx - > protoctx - > fd_readcb , ctx ) ;
2017-06-27 14:09:01 +00:00
if ( ! ctx - > ev )
2017-07-11 22:45:15 +00:00
goto memout ;
2017-06-10 18:50:03 +00:00
event_add ( ctx - > ev , NULL ) ;
} else {
2018-10-15 10:42:40 +00:00
ctx - > protoctx - > fd_readcb ( fd , 0 , ctx ) ;
2017-06-10 18:50:03 +00:00
}
2017-07-12 13:46:51 +00:00
return ;
2017-06-27 14:09:01 +00:00
2017-07-11 22:45:15 +00:00
memout :
2017-10-14 22:39:30 +00:00
log_err_level_printf ( LOG_CRIT , " Aborting connection setup (out of memory)! \n " ) ;
2017-07-11 22:45:15 +00:00
evutil_closesocket ( fd ) ;
2017-07-25 13:07:39 +00:00
pxy_conn_ctx_free ( ctx , 1 ) ;
2017-05-29 09:22:23 +00:00
}
2017-07-07 14:18:01 +00:00
2012-04-13 12:47:30 +00:00
/* vim: set noet ft=c: */