aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/dissectors/packet-tcp.c111
-rw-r--r--epan/dissectors/packet-tcp.h20
2 files changed, 73 insertions, 58 deletions
diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c
index e43150d897..4e706fc9cf 100644
--- a/epan/dissectors/packet-tcp.c
+++ b/epan/dissectors/packet-tcp.c
@@ -925,6 +925,13 @@ init_tcp_conversation_data(packet_info *pinfo)
tcpd->flow2.username = NULL;
tcpd->flow2.command = NULL;
*/
+
+ /* Only allocate the data if its actually going to be analyzed */
+ if (tcp_analyze_seq)
+ {
+ tcpd->flow1.tcp_analyze_seq_info = wmem_new0(wmem_file_scope(), struct tcp_analyze_seq_flow_info_t);
+ tcpd->flow2.tcp_analyze_seq_info = wmem_new0(wmem_file_scope(), struct tcp_analyze_seq_flow_info_t);
+ }
tcpd->acked_table=wmem_tree_new(wmem_file_scope());
tcpd->ts_first.secs=pinfo->abs_ts.secs;
tcpd->ts_first.nsecs=pinfo->abs_ts.nsecs;
@@ -1395,7 +1402,7 @@ tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint3
* the segment is exactly 1 byte
*/
if( seglen==1
- && seq==tcpd->fwd->nextseq
+ && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
&& tcpd->rev->window==0 ) {
if(!tcpd->ta) {
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
@@ -1425,8 +1432,8 @@ tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint3
* one.
* RST packets are not checked for this.
*/
- if( tcpd->fwd->nextseq
- && GT_SEQ(seq, tcpd->fwd->nextseq)
+ if( tcpd->fwd->tcp_analyze_seq_info->nextseq
+ && GT_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->nextseq)
&& (flags&(TH_RST))==0 ) {
if(!tcpd->ta) {
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
@@ -1444,7 +1451,7 @@ tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint3
* SYN/FIN/RST segments are never keepalives
*/
if( (seglen==0||seglen==1)
- && seq==(tcpd->fwd->nextseq-1)
+ && seq==(tcpd->fwd->tcp_analyze_seq_info->nextseq-1)
&& (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
if(!tcpd->ta) {
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
@@ -1459,8 +1466,8 @@ tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint3
if( seglen==0
&& window
&& window!=tcpd->fwd->window
- && seq==tcpd->fwd->nextseq
- && ack==tcpd->fwd->lastack
+ && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
+ && ack==tcpd->fwd->tcp_analyze_seq_info->lastack
&& (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
if(!tcpd->ta) {
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
@@ -1478,7 +1485,7 @@ tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint3
*/
if( seglen>0
&& tcpd->rev->win_scale!=-1
- && (seq+seglen)==(tcpd->rev->lastack+(tcpd->rev->window<<(tcpd->rev->win_scale==-2?0:tcpd->rev->win_scale)))
+ && (seq+seglen)==(tcpd->rev->tcp_analyze_seq_info->lastack+(tcpd->rev->window<<(tcpd->rev->win_scale==-2?0:tcpd->rev->win_scale)))
&& (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
if(!tcpd->ta) {
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
@@ -1494,8 +1501,8 @@ tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint3
if( seglen==0
&& window
&& window==tcpd->fwd->window
- && seq==tcpd->fwd->nextseq
- && ack==tcpd->fwd->lastack
+ && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
+ && ack==tcpd->fwd->tcp_analyze_seq_info->lastack
&& (tcpd->rev->lastsegmentflags&TCP_A_KEEP_ALIVE)
&& (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
if(!tcpd->ta) {
@@ -1514,8 +1521,8 @@ tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint3
if( seglen==0
&& window==0
&& window==tcpd->fwd->window
- && seq==tcpd->fwd->nextseq
- && ack==tcpd->fwd->lastack
+ && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
+ && ack==tcpd->fwd->tcp_analyze_seq_info->lastack
&& (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE)
&& (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
if(!tcpd->ta) {
@@ -1533,25 +1540,25 @@ tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint3
if( seglen==0
&& window
&& window==tcpd->fwd->window
- && seq==tcpd->fwd->nextseq
- && ack==tcpd->fwd->lastack
+ && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
+ && ack==tcpd->fwd->tcp_analyze_seq_info->lastack
&& (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
- tcpd->fwd->dupacknum++;
+ tcpd->fwd->tcp_analyze_seq_info->dupacknum++;
if(!tcpd->ta) {
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
}
tcpd->ta->flags|=TCP_A_DUPLICATE_ACK;
- tcpd->ta->dupack_num=tcpd->fwd->dupacknum;
- tcpd->ta->dupack_frame=tcpd->fwd->lastnondupack;
+ tcpd->ta->dupack_num=tcpd->fwd->tcp_analyze_seq_info->dupacknum;
+ tcpd->ta->dupack_frame=tcpd->fwd->tcp_analyze_seq_info->lastnondupack;
}
finished_fwd:
/* If the ack number changed we must reset the dupack counters */
- if( ack != tcpd->fwd->lastack ) {
- tcpd->fwd->lastnondupack=pinfo->num;
- tcpd->fwd->dupacknum=0;
+ if( ack != tcpd->fwd->tcp_analyze_seq_info->lastack ) {
+ tcpd->fwd->tcp_analyze_seq_info->lastnondupack=pinfo->num;
+ tcpd->fwd->tcp_analyze_seq_info->dupacknum=0;
}
@@ -1563,8 +1570,8 @@ finished_fwd:
* We only check this if we have actually seen some seq numbers
* in the other direction.
*/
- if( tcpd->rev->maxseqtobeacked
- && GT_SEQ(ack, tcpd->rev->maxseqtobeacked )
+ if( tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked
+ && GT_SEQ(ack, tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked )
&& (flags&(TH_ACK))!=0 ) {
if(!tcpd->ta) {
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
@@ -1573,7 +1580,7 @@ finished_fwd:
/* update 'max seq to be acked' in the other direction so we don't get
* this indication again.
*/
- tcpd->rev->maxseqtobeacked=tcpd->rev->nextseq;
+ tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=tcpd->rev->tcp_analyze_seq_info->nextseq;
}
@@ -1587,8 +1594,8 @@ finished_fwd:
* Note that a simple KeepAlive is not a retransmission
*/
if( (seglen>0 || flags&(TH_SYN|TH_FIN))
- && tcpd->fwd->nextseq
- && (LT_SEQ(seq, tcpd->fwd->nextseq)) ) {
+ && tcpd->fwd->tcp_analyze_seq_info->nextseq
+ && (LT_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->nextseq)) ) {
guint64 t;
guint64 ooo_thres;
if (tcpd->ts_first_rtt.nsecs == 0 && tcpd->ts_first_rtt.secs == 0)
@@ -1607,10 +1614,10 @@ finished_fwd:
* duplicate ack
* then this is a fast retransmission
*/
- t=(pinfo->abs_ts.secs-tcpd->rev->lastacktime.secs)*1000000000;
- t=t+(pinfo->abs_ts.nsecs)-tcpd->rev->lastacktime.nsecs;
- if( tcpd->rev->dupacknum>=2
- && tcpd->rev->lastack==seq
+ t=(pinfo->abs_ts.secs-tcpd->rev->tcp_analyze_seq_info->lastacktime.secs)*1000000000;
+ t=t+(pinfo->abs_ts.nsecs)-tcpd->rev->tcp_analyze_seq_info->lastacktime.nsecs;
+ if( tcpd->rev->tcp_analyze_seq_info->dupacknum>=2
+ && tcpd->rev->tcp_analyze_seq_info->lastack==seq
&& t<20000000 ) {
if(!tcpd->ta) {
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
@@ -1623,10 +1630,10 @@ finished_fwd:
* seen sequence number and it doesn't look like a retransmission
* then it is an OUT-OF-ORDER segment.
*/
- t=(pinfo->abs_ts.secs-tcpd->fwd->nextseqtime.secs)*1000000000;
- t=t+(pinfo->abs_ts.nsecs)-tcpd->fwd->nextseqtime.nsecs;
+ t=(pinfo->abs_ts.secs-tcpd->fwd->tcp_analyze_seq_info->nextseqtime.secs)*1000000000;
+ t=t+(pinfo->abs_ts.nsecs)-tcpd->fwd->tcp_analyze_seq_info->nextseqtime.nsecs;
if( t < ooo_thres
- && tcpd->fwd->nextseq != seq + seglen ) {
+ && tcpd->fwd->tcp_analyze_seq_info->nextseq != seq + seglen ) {
if(!tcpd->ta) {
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
}
@@ -1638,7 +1645,7 @@ finished_fwd:
* is less than or equal to the receiver's lastack, the packet contains
* duplicate data and may be considered spurious.
*/
- if ( seq + seglen <= tcpd->rev->lastack ) {
+ if ( seq + seglen <= tcpd->rev->tcp_analyze_seq_info->lastack ) {
if(!tcpd->ta){
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
}
@@ -1651,21 +1658,21 @@ finished_fwd:
tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
}
tcpd->ta->flags|=TCP_A_RETRANSMISSION;
- nstime_delta(&tcpd->ta->rto_ts, &pinfo->abs_ts, &tcpd->fwd->nextseqtime);
- tcpd->ta->rto_frame=tcpd->fwd->nextseqframe;
+ nstime_delta(&tcpd->ta->rto_ts, &pinfo->abs_ts, &tcpd->fwd->tcp_analyze_seq_info->nextseqtime);
+ tcpd->ta->rto_frame=tcpd->fwd->tcp_analyze_seq_info->nextseqframe;
}
finished_checking_retransmission_type:
nextseq = seq+seglen;
- if ((seglen || flags&(TH_SYN|TH_FIN)) && tcpd->fwd->segment_count < TCP_MAX_UNACKED_SEGMENTS) {
+ if ((seglen || flags&(TH_SYN|TH_FIN)) && tcpd->fwd->tcp_analyze_seq_info->segment_count < TCP_MAX_UNACKED_SEGMENTS) {
/* Add this new sequence number to the fwd list. But only if there
* aren't "too many" unacked segments (e.g., we're not seeing the ACKs).
*/
ual = wmem_new(wmem_file_scope(), tcp_unacked_t);
- ual->next=tcpd->fwd->segments;
- tcpd->fwd->segments=ual;
- tcpd->fwd->segment_count++;
+ ual->next=tcpd->fwd->tcp_analyze_seq_info->segments;
+ tcpd->fwd->tcp_analyze_seq_info->segments=ual;
+ tcpd->fwd->tcp_analyze_seq_info->segment_count++;
ual->frame=pinfo->num;
ual->seq=seq;
ual->ts=pinfo->abs_ts;
@@ -1682,30 +1689,30 @@ finished_checking_retransmission_type:
* If we don't have anything since before, just store what we got.
* ZeroWindowProbes are special and don't really advance the nextseq
*/
- if(GT_SEQ(nextseq, tcpd->fwd->nextseq) || !tcpd->fwd->nextseq) {
+ if(GT_SEQ(nextseq, tcpd->fwd->tcp_analyze_seq_info->nextseq) || !tcpd->fwd->tcp_analyze_seq_info->nextseq) {
if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ) {
- tcpd->fwd->nextseq=nextseq;
- tcpd->fwd->nextseqframe=pinfo->num;
- tcpd->fwd->nextseqtime.secs=pinfo->abs_ts.secs;
- tcpd->fwd->nextseqtime.nsecs=pinfo->abs_ts.nsecs;
+ tcpd->fwd->tcp_analyze_seq_info->nextseq=nextseq;
+ tcpd->fwd->tcp_analyze_seq_info->nextseqframe=pinfo->num;
+ tcpd->fwd->tcp_analyze_seq_info->nextseqtime.secs=pinfo->abs_ts.secs;
+ tcpd->fwd->tcp_analyze_seq_info->nextseqtime.nsecs=pinfo->abs_ts.nsecs;
}
}
/* Store the highest continuous seq number seen so far for 'max seq to be acked',
so we can detect TCP_A_ACK_LOST_PACKET condition
*/
- if(EQ_SEQ(seq, tcpd->fwd->maxseqtobeacked) || !tcpd->fwd->maxseqtobeacked) {
+ if(EQ_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked) || !tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked) {
if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ) {
- tcpd->fwd->maxseqtobeacked=tcpd->fwd->nextseq;
+ tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked=tcpd->fwd->tcp_analyze_seq_info->nextseq;
}
}
/* remember what the ack/window is so we can track window updates and retransmissions */
tcpd->fwd->window=window;
- tcpd->fwd->lastack=ack;
- tcpd->fwd->lastacktime.secs=pinfo->abs_ts.secs;
- tcpd->fwd->lastacktime.nsecs=pinfo->abs_ts.nsecs;
+ tcpd->fwd->tcp_analyze_seq_info->lastack=ack;
+ tcpd->fwd->tcp_analyze_seq_info->lastacktime.secs=pinfo->abs_ts.secs;
+ tcpd->fwd->tcp_analyze_seq_info->lastacktime.nsecs=pinfo->abs_ts.nsecs;
/* if there were any flags set for this segment we need to remember them
@@ -1722,7 +1729,7 @@ finished_checking_retransmission_type:
*/
ackcount=0;
prevual = NULL;
- ual = tcpd->rev->segments;
+ ual = tcpd->rev->tcp_analyze_seq_info->segments;
while(ual) {
tcp_unacked_t *tmpual;
@@ -1756,20 +1763,20 @@ finished_checking_retransmission_type:
}
if (!prevual) {
- tcpd->rev->segments = tmpual;
+ tcpd->rev->tcp_analyze_seq_info->segments = tmpual;
}
else{
prevual->next = tmpual;
}
wmem_free(wmem_file_scope(), ual);
ual = tmpual;
- tcpd->rev->segment_count--;
+ tcpd->rev->tcp_analyze_seq_info->segment_count--;
}
/* how many bytes of data are there in flight after this frame
* was sent
*/
- ual=tcpd->fwd->segments;
+ ual=tcpd->fwd->tcp_analyze_seq_info->segments;
if (tcp_track_bytes_in_flight && seglen!=0 && ual && tcpd->fwd->valid_bif) {
guint32 first_seq, last_seq, in_flight;
diff --git a/epan/dissectors/packet-tcp.h b/epan/dissectors/packet-tcp.h
index 9b4cec40db..a9b25dadcc 100644
--- a/epan/dissectors/packet-tcp.h
+++ b/epan/dissectors/packet-tcp.h
@@ -287,14 +287,12 @@ typedef enum {
#define MPTCP_CHECKSUM_MASK 0x80
-
-typedef struct _tcp_flow_t {
- guint8 static_flags; /* true if base seq set */
- guint32 base_seq; /* base seq number (used by relative sequence numbers)*/
-#define TCP_MAX_UNACKED_SEGMENTS 1000 /* The most unacked segments we'll store */
+/* Information in a flow that is only used when tcp_analyze_seq preference
+ * is enabled, so save the memory when it isn't
+ */
+typedef struct tcp_analyze_seq_flow_info_t {
tcp_unacked_t *segments;/* List of segments for which we haven't seen an ACK */
guint16 segment_count; /* How many unacked segments we're currently storing */
- guint32 fin; /* frame number of the final FIN */
guint32 lastack; /* last seen ack */
nstime_t lastacktime; /* Time of the last ack packet */
guint32 lastnondupack; /* frame number of last seen non dupack */
@@ -310,6 +308,14 @@ typedef struct _tcp_flow_t {
* distinguish between retransmission,
* fast retransmissions and outoforder
*/
+
+} tcp_analyze_seq_flow_info_t;
+
+typedef struct _tcp_flow_t {
+ guint8 static_flags; /* true if base seq set */
+ guint32 base_seq; /* base seq number (used by relative sequence numbers)*/
+#define TCP_MAX_UNACKED_SEGMENTS 1000 /* The most unacked segments we'll store */
+ guint32 fin; /* frame number of the final FIN */
guint32 window; /* last seen window */
gint16 win_scale; /* -1 is we don't know, -2 is window scaling is not used */
gint16 scps_capable; /* flow advertised scps capabilities */
@@ -318,6 +324,8 @@ typedef struct _tcp_flow_t {
guint32 push_bytes_sent; /* bytes since the last PSH flag */
gboolean push_set_last; /* tracking last time PSH flag was set */
+ tcp_analyze_seq_flow_info_t* tcp_analyze_seq_info;
+
/* This tcp flow/session contains only one single PDU and should
* be reassembled until the final FIN segment.
*/