From 68255f5e9d92bb88add4a9dacc96568b9c3817be Mon Sep 17 00:00:00 2001 From: William Robinet Date: Fri, 17 Apr 2015 10:59:26 +0200 Subject: [PATCH 1/3] Fix memory leak at connection closing --- base/tcpconn.c | 1 + 1 file changed, 1 insertion(+) diff --git a/base/tcpconn.c b/base/tcpconn.c index cd37753..65f338a 100644 --- a/base/tcpconn.c +++ b/base/tcpconn.c @@ -158,6 +158,7 @@ int tcp_destroy_conn(conn) free_tcp_segment_queue(conn->i2r.oo_queue); free_tcp_segment_queue(conn->r2i.oo_queue); zero_conn(conn); + free(conn); return(0); } From 4310c3f11758aa21c2973d293c3b3e0bfd31afd3 Mon Sep 17 00:00:00 2001 From: William Robinet Date: Wed, 22 Apr 2015 11:23:37 +0200 Subject: [PATCH 2/3] In flight connection pool cleaning --- base/pcap-snoop.c | 29 ++++++++++++++++++++++++++--- base/tcpconn.c | 32 +++++++++++++++++++++++++++++++- base/tcpconn.h | 1 + base/tcppack.c | 5 ++++- ssldump.1 | 6 ++++++ 5 files changed, 68 insertions(+), 5 deletions(-) diff --git a/base/pcap-snoop.c b/base/pcap-snoop.c index 6589718..b1ae251 100644 --- a/base/pcap-snoop.c +++ b/base/pcap-snoop.c @@ -87,6 +87,13 @@ RETSIGTYPE sig_handler PROTO_LIST((void)); void pcap_cb PROTO_LIST((u_char *ptr,struct pcap_pkthdr *hdr,u_char *data)); int main PROTO_LIST((int argc,char **argv)); +int packet_cnt = 0; // Packet counter used for connection pool cleaning +int conn_freq = 100; // Number of packets after which a connection pool + // cleaning is performed +int conn_ttl = 100; // TTL of inactive connections in connection pool +struct timeval last_packet_seen_time; // Timestamp of the last packet of the + // last block of conn_freq packets seen + int err_exit(str,num) char *str; int num; @@ -128,7 +135,7 @@ void pcap_cb(ptr,hdr,data) n_handler *n; int len; struct ether_header *e_hdr=(struct ether_header *)data; - int type; + int type, cleaned_conn; n=(n_handler *)ptr; if(hdr->caplen!=hdr->len) err_exit("Length mismatch",-1); @@ -231,6 +238,15 @@ void pcap_cb(ptr,hdr,data) #endif } network_process_packet(n,&hdr->ts,data,len); + + if(packet_cnt == conn_freq) { + packet_cnt = 0; + memcpy(&last_packet_seen_time,&hdr->ts,sizeof(struct timeval)); + if(cleaned_conn = clean_old_conn()) + printf("%d inactive connection(s) cleaned from connection pool\n", cleaned_conn); + } else { + packet_cnt++; + } } typedef struct module_def_ { @@ -277,7 +293,7 @@ int main(argc,argv) signal(SIGINT,sig_handler); - while((c=getopt(argc,argv,"vr:f:S:yTtai:k:p:nsAxXhHVNdqem:P"))!=EOF){ + while((c=getopt(argc,argv,"vr:F:f:S:yTt:ai:k:p:nsAxXhHVNdqem:P"))!=EOF){ switch(c){ case 'v': print_version(); @@ -319,6 +335,12 @@ int main(argc,argv) case 'n': NET_print_flags |= NET_PRINT_NO_RESOLVE; break; + case 't': + conn_ttl=atoi(optarg); + break; + case 'F': + conn_freq=atoi(optarg); + break; case 'm': for(m=modules;m->name!=0;m++){ if(!strcmp(m->name,optarg)){ @@ -427,7 +449,8 @@ int main(argc,argv) if(NET_print_flags & NET_PRINT_TYPESET) printf("\n.ps\n.fi\n"); - + + printf("Cleaning %d remaining connection(s) from connection pool\n", destroy_all_conn()); exit(0); } diff --git a/base/tcpconn.c b/base/tcpconn.c index 65f338a..1a832a8 100644 --- a/base/tcpconn.c +++ b/base/tcpconn.c @@ -59,6 +59,9 @@ int conn_number=1; static conn_struct *first_conn=0; +extern struct timeval last_packet_seen_time; +extern int conn_ttl; + static int zero_conn PROTO_LIST((tcp_conn *conn)); static int zero_conn(conn) @@ -162,7 +165,34 @@ int tcp_destroy_conn(conn) return(0); } - + +int clean_old_conn() { + conn_struct *conn; + tcp_conn *tcpconn; + struct timeval dt; + int i = 0; + + for(conn=first_conn;conn;conn=conn->next) { + i++; + tcpconn = &conn->conn; + timestamp_diff(&last_packet_seen_time, &tcpconn->last_seen_time, &dt); + if(dt.tv_sec > conn_ttl) { + tcp_destroy_conn(&(first_conn->conn)); + } + } + return i; +} + +int destroy_all_conn() { + conn_struct *conn; + int i = 0,r; + while(first_conn) { + i++; + tcp_destroy_conn(&first_conn->conn); + } + return i; +} + int free_tcp_segment_queue(seg) segment *seg; { diff --git a/base/tcpconn.h b/base/tcpconn.h index d081b01..a0a4a4e 100644 --- a/base/tcpconn.h +++ b/base/tcpconn.h @@ -83,6 +83,7 @@ typedef struct tcp_conn_ { stream_data r2i; /*The stream from responder to initiator*/ struct timeval start_time; + struct timeval last_seen_time; proto_handler *analyzer; /*The analyzer to call with new data*/ struct conn_struct_ *backptr; } tcp_conn; diff --git a/base/tcppack.c b/base/tcppack.c index ed69546..185f73a 100644 --- a/base/tcppack.c +++ b/base/tcppack.c @@ -107,7 +107,9 @@ int process_tcp_packet(handler,ctx,p) } stream=direction==DIR_R2I?&conn->r2i:&conn->i2r; - + + memcpy(&conn->last_seen_time,&p->ts,sizeof(struct timeval)); + switch(conn->state){ case TCP_STATE_SYN1: if(direction != DIR_R2I) @@ -182,6 +184,7 @@ static int new_connection(handler,ctx,p,connp) conn->state=TCP_STATE_SYN1; memcpy(&conn->start_time,&p->ts,sizeof(struct timeval)); + memcpy(&conn->last_seen_time,&p->ts,sizeof(struct timeval)); if(r=create_proto_handler(handler,ctx,&conn->analyzer,conn,&p->ts)) ABORT(r); diff --git a/ssldump.1 b/ssldump.1 index 4c5ff4a..f1f80bf 100644 --- a/ssldump.1 +++ b/ssldump.1 @@ -181,6 +181,12 @@ Print the TCP headers. .B \-v Display version and copyright information. .TP +.B \-t +Specify the TTL for inactive connections referenced in the connection pool (in seconds, default: 100). +.TP +.B \-F +Specify the number of packets after which a connection pool cleaning is performed (in packets, default: 100). +.TP .B \-x Print each record in hex, as well as decoding it. .TP From 3ca46766e449e8fd982e8291e8a741d02d3d570c Mon Sep 17 00:00:00 2001 From: William Robinet Date: Wed, 22 Apr 2015 11:32:42 +0200 Subject: [PATCH 3/3] Fix memory leak if SSL session id is not present --- ssl/ssldecode.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ssl/ssldecode.c b/ssl/ssldecode.c index db0d32c..e373396 100644 --- a/ssl/ssldecode.c +++ b/ssl/ssldecode.c @@ -259,9 +259,10 @@ int ssl_set_client_session_id(d,msg,len) { #ifdef OPENSSL int r; - - if(r=r_data_create(&d->session_id,msg,len)) - ERETURN(r); + + if(len>0) + if(r=r_data_create(&d->session_id,msg,len)) + ERETURN(r); #endif return(0); }