snort_stream_tcp.c (snort-2.9.16.1) | : | snort_stream_tcp.c (snort-2.9.17) | ||
---|---|---|---|---|
skipping to change at line 1266 | skipping to change at line 1266 | |||
scb->ha_state.session_flags &= ~( SSNFLAG_SEEN_CLIENT | SSNFLAG_SEEN_SERVER ); | scb->ha_state.session_flags &= ~( SSNFLAG_SEEN_CLIENT | SSNFLAG_SEEN_SERVER ); | |||
} | } | |||
static int StreamTCPDeleteSession( const SessionKey *key ) | static int StreamTCPDeleteSession( const SessionKey *key ) | |||
{ | { | |||
SessionControlBlock *scb = session_api->get_session_by_key( tcp_lws_cache, k ey ); | SessionControlBlock *scb = session_api->get_session_by_key( tcp_lws_cache, k ey ); | |||
if( scb != NULL ) | if( scb != NULL ) | |||
{ | { | |||
if( StreamSetRuntimeConfiguration( scb, scb->protocol ) == 0 ) | if( StreamSetRuntimeConfiguration( scb, scb->protocol ) == 0 ) | |||
session_api->delete_session( tcp_lws_cache, scb, "ha sync", false ); | { | |||
if (!session_api->delete_session( tcp_lws_cache, scb, "ha sync", fal | ||||
se )) | ||||
s5stats.active_tcp_sessions--; | ||||
} | ||||
else | else | |||
WarningMessage(" WARNING: Attempt to delete a TCP Session when no va lid runtime configuration.\n" ); | WarningMessage(" WARNING: Attempt to delete a TCP Session when no va lid runtime configuration.\n" ); | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
#endif | #endif | |||
SessionControlBlock *GetLWTcpSession( const SessionKey *key ) | SessionControlBlock *GetLWTcpSession( const SessionKey *key ) | |||
{ | { | |||
skipping to change at line 3485 | skipping to change at line 3488 | |||
#if !defined(SFLINUX) && defined(DAQ_CAPA_VRF) | #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF) | |||
pkth->address_space_id_dst = tcpssn->address_space_id_dst; | pkth->address_space_id_dst = tcpssn->address_space_id_dst; | |||
pkth->address_space_id_src = tcpssn->address_space_id_src; | pkth->address_space_id_src = tcpssn->address_space_id_src; | |||
#else | #else | |||
pkth->address_space_id = tcpssn->address_space_id; | pkth->address_space_id = tcpssn->address_space_id; | |||
#endif | #endif | |||
#if defined(DAQ_VERSION) && DAQ_VERSION > 8 | #if defined(DAQ_VERSION) && DAQ_VERSION > 8 | |||
pkth->proto = phdr->proto; | pkth->proto = phdr->proto; | |||
#endif | #endif | |||
#if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID) | ||||
pkth->carrier_id = phdr->carrier_id; | ||||
#endif | ||||
#ifdef HAVE_DAQ_REAL_ADDRESSES | #ifdef HAVE_DAQ_REAL_ADDRESSES | |||
if (phdr->flags & DAQ_PKT_FLAG_REAL_ADDRESSES) | if (phdr->flags & DAQ_PKT_FLAG_REAL_ADDRESSES) | |||
{ | { | |||
pkth->flags &= ~(DAQ_PKT_FLAG_REAL_SIP_V6 | DAQ_PKT_FLAG_REAL_DIP_V6); | pkth->flags &= ~(DAQ_PKT_FLAG_REAL_SIP_V6 | DAQ_PKT_FLAG_REAL_DIP_V6); | |||
if (fwd) | if (fwd) | |||
{ | { | |||
pkth->flags |= phdr->flags & (DAQ_PKT_FLAG_REAL_SIP_V6 | DAQ_PKT_FLA G_REAL_DIP_V6); | pkth->flags |= phdr->flags & (DAQ_PKT_FLAG_REAL_SIP_V6 | DAQ_PKT_FLA G_REAL_DIP_V6); | |||
pkth->n_real_sPort = phdr->n_real_sPort; | pkth->n_real_sPort = phdr->n_real_sPort; | |||
pkth->n_real_dPort = phdr->n_real_dPort; | pkth->n_real_dPort = phdr->n_real_dPort; | |||
pkth->real_sIP = phdr->real_sIP; | pkth->real_sIP = phdr->real_sIP; | |||
skipping to change at line 5268 | skipping to change at line 5275 | |||
{ | { | |||
STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE, | STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE, | |||
"In TcpSessionClear, %lu bytes in use\n", session_mem_in_use);); | "In TcpSessionClear, %lu bytes in use\n", session_mem_in_use);); | |||
STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE, | STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE, | |||
"client has %d segs queued\n", tcpssn->client.seg_count);); | "client has %d segs queued\n", tcpssn->client.seg_count);); | |||
STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE, | STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE, | |||
"server has %d segs queued\n", tcpssn->server.seg_count);); | "server has %d segs queued\n", tcpssn->server.seg_count);); | |||
// update stats | // update stats | |||
s5stats.tcp_streamtrackers_released++; | s5stats.tcp_streamtrackers_released++; | |||
if (s5stats.active_tcp_sessions > 0 ) | ||||
s5stats.active_tcp_sessions--; | ||||
StreamUpdatePerfBaseState(&sfBase, tcpssn->scb, TCP_STATE_CLOSED); | StreamUpdatePerfBaseState(&sfBase, tcpssn->scb, TCP_STATE_CLOSED); | |||
RemoveStreamSession(&sfBase); | RemoveStreamSession(&sfBase); | |||
if (scb->ha_state.session_flags & SSNFLAG_PRUNED) | if (scb->ha_state.session_flags & SSNFLAG_PRUNED) | |||
CloseStreamSession(&sfBase, SESSION_CLOSED_PRUNED); | CloseStreamSession(&sfBase, SESSION_CLOSED_PRUNED); | |||
else if (scb->ha_state.session_flags & SSNFLAG_TIMEDOUT) | else if (scb->ha_state.session_flags & SSNFLAG_TIMEDOUT) | |||
CloseStreamSession(&sfBase, SESSION_CLOSED_PRUNED | SESSION_CLOSED_TIMED OUT); | CloseStreamSession(&sfBase, SESSION_CLOSED_PRUNED | SESSION_CLOSED_TIMED OUT); | |||
else | else | |||
CloseStreamSession(&sfBase, SESSION_CLOSED_NORMALLY); | CloseStreamSession(&sfBase, SESSION_CLOSED_NORMALLY); | |||
skipping to change at line 5952 | skipping to change at line 5961 | |||
if( s5TcpPolicy->flags & STREAM_CONFIG_REQUIRE_3WHS ) | if( s5TcpPolicy->flags & STREAM_CONFIG_REQUIRE_3WHS ) | |||
{ | { | |||
/* if require 3WHS, set session state to SYN rx'ed if we got one */ | /* if require 3WHS, set session state to SYN rx'ed if we got one */ | |||
if( TCP_ISFLAGSET( p->tcph, TH_SYN ) && !TCP_ISFLAGSET( p->tcph, TH_ ACK ) ) | if( TCP_ISFLAGSET( p->tcph, TH_SYN ) && !TCP_ISFLAGSET( p->tcph, TH_ ACK ) ) | |||
{ | { | |||
/* SYN only */ | /* SYN only */ | |||
scb->session_state = STREAM_STATE_SYN; | scb->session_state = STREAM_STATE_SYN; | |||
scb->session_established = true; | scb->session_established = true; | |||
scb->proto_policy = s5TcpPolicy; | scb->proto_policy = s5TcpPolicy; | |||
s5stats.total_tcp_sessions++; | s5stats.total_tcp_sessions++; | |||
s5stats.active_tcp_sessions++; | ||||
} | } | |||
else | else | |||
{ | { | |||
/* If we're within the "startup" window, try to handle | /* If we're within the "startup" window, try to handle | |||
* this packet as midstream pickup -- allows for | * this packet as midstream pickup -- allows for | |||
* connections that already existed before snort started. | * connections that already existed before snort started. | |||
*/ | */ | |||
if (p->pkth->ts.tv_sec - firstPacketTime < s5TcpPolicy->hs_timeo ut) | if (p->pkth->ts.tv_sec - firstPacketTime < s5TcpPolicy->hs_timeo ut) | |||
{ | { | |||
midstream_allowed = 1; | midstream_allowed = 1; | |||
skipping to change at line 5991 | skipping to change at line 6001 | |||
} | } | |||
else | else | |||
{ | { | |||
midstream_pickup_allowed: | midstream_pickup_allowed: | |||
if (TCP_ISFLAGSET(p->tcph, (TH_SYN|TH_ACK))) | if (TCP_ISFLAGSET(p->tcph, (TH_SYN|TH_ACK))) | |||
{ | { | |||
/* If we have a SYN/ACK */ | /* If we have a SYN/ACK */ | |||
scb->session_established = true; | scb->session_established = true; | |||
scb->proto_policy = s5TcpPolicy; | scb->proto_policy = s5TcpPolicy; | |||
s5stats.total_tcp_sessions++; | s5stats.total_tcp_sessions++; | |||
s5stats.active_tcp_sessions++; | ||||
} | } | |||
else if (p->dsize > 0) | else if (p->dsize > 0) | |||
{ | { | |||
/* If we have data -- missed the SYN/ACK | /* If we have data -- missed the SYN/ACK | |||
* somehow -- maybe just an incomplete PCAP. | * somehow -- maybe just an incomplete PCAP. | |||
* This handles data on SYN situations | * This handles data on SYN situations | |||
*/ | */ | |||
scb->session_established = true; | scb->session_established = true; | |||
scb->proto_policy = s5TcpPolicy; | scb->proto_policy = s5TcpPolicy; | |||
s5stats.total_tcp_sessions++; | s5stats.total_tcp_sessions++; | |||
s5stats.active_tcp_sessions++; | ||||
} | } | |||
else if( ( ( ( ( StreamConfig * ) scb->stream_config )->tcp_config-> session_on_syn || | else if( ( ( ( ( StreamConfig * ) scb->stream_config )->tcp_config-> session_on_syn || | |||
( StreamPacketHasWscale(p) & TF_WSCALE ) ) | ( StreamPacketHasWscale(p) & TF_WSCALE ) ) | |||
&& TCP_ISFLAGSET(p->tcph, TH_SYN) ) || StreamExpectIsExpecte d( p, &hash_node ) ) | && TCP_ISFLAGSET(p->tcph, TH_SYN) ) || StreamExpectIsExpecte d( p, &hash_node ) ) | |||
{ | { | |||
/* If we have a wscale option or this is an expected connection, need to save the | /* If we have a wscale option or this is an expected connection, need to save the | |||
* option if its the first SYN from client or continue to get th e expected session | * option if its the first SYN from client or continue to get th e expected session | |||
* data. */ | * data. */ | |||
scb->session_state = STREAM_STATE_SYN; | scb->session_state = STREAM_STATE_SYN; | |||
scb->session_established = true; | scb->session_established = true; | |||
scb->proto_policy = s5TcpPolicy; | scb->proto_policy = s5TcpPolicy; | |||
s5stats.total_tcp_sessions++; | s5stats.total_tcp_sessions++; | |||
s5stats.active_tcp_sessions++; | ||||
} | } | |||
else | else | |||
{ | { | |||
/* No data, no need to create session yet */ | /* No data, no need to create session yet */ | |||
/* This is done to handle SYN flood DoS attacks */ | /* This is done to handle SYN flood DoS attacks */ | |||
#ifdef STREAM_DEBUG_ENABLED | #ifdef STREAM_DEBUG_ENABLED | |||
if (TCP_ISFLAGSET(p->tcph, TH_SYN)) | if (TCP_ISFLAGSET(p->tcph, TH_SYN)) | |||
{ | { | |||
STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | |||
"Stream: no data in packet (SYN only), no need t o" | "Stream: no data in packet (SYN only), no need t o" | |||
skipping to change at line 6435 | skipping to change at line 6448 | |||
/* Check if we should not insert a large packet */ | /* Check if we should not insert a large packet */ | |||
if (IgnoreLargePkt(st, p, tdb)) | if (IgnoreLargePkt(st, p, tdb)) | |||
{ | { | |||
return; | return; | |||
} | } | |||
if ( p->tcph->th_flags & TH_SYN ) | if ( p->tcph->th_flags & TH_SYN ) | |||
seq++; | seq++; | |||
/* new packet seq is below the last ack... */ | /* new packet seq is below the last ack... */ | |||
if ( SEQ_GT(st->r_win_base, seq) ) | if ( SEQ_GT(st->r_win_base, seq) ) | |||
{ | { | |||
//Received data segment whose seq no is less than already | STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | |||
ACKed bytes | "segment overlaps ack'd data...\n");); | |||
if(SEQ_GT(st->r_nxt_ack, seq)) | overlap = st->r_win_base - tdb->seq; | |||
{ | if (overlap >= p->dsize) | |||
//We have already seen the data and this is a ret | { | |||
ransmission with different packet size | STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | |||
//Add the delta to seglist if the size is more th | "full overlap on ack'd data, dropping segment\n");); | |||
an overlap | PREPROC_PROFILE_END(s5TcpInsertPerfStats); | |||
STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE | return; | |||
, | } | |||
"segment overlaps ack'd d | } | |||
ata...\n");); | ||||
overlap = st->r_win_base - seq; | ||||
if(overlap >= p->dsize) | ||||
{ | ||||
STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STRE | ||||
AM_STATE, | ||||
"full overlap on | ||||
ack'd data, dropping segment\n");); | ||||
PREPROC_PROFILE_END(s5TcpInsertPerfStats) | ||||
; | ||||
return; | ||||
} | ||||
} | ||||
} | ||||
AddStreamNode(st, p, tdb, tcpssn, p->dsize, overlap, 0, tdb->seq+overlap , NULL, &ss); | AddStreamNode(st, p, tdb, tcpssn, p->dsize, overlap, 0, tdb->seq+overlap , NULL, &ss); | |||
STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | |||
"Attached new queue to seglist, %d bytes queued, " | "Attached new queue to seglist, %d bytes queued, " | |||
"base_seq 0x%X\n", | "base_seq 0x%X\n", | |||
ss->size, st->seglist_base_seq);); | ss->size, st->seglist_base_seq);); | |||
} | } | |||
PREPROC_PROFILE_END(s5TcpInsertPerfStats); | PREPROC_PROFILE_END(s5TcpInsertPerfStats); | |||
skipping to change at line 6562 | skipping to change at line 6569 | |||
if (session_mem_in_use > stream_session_config->memcap) | if (session_mem_in_use > stream_session_config->memcap) | |||
{ | { | |||
pc.str_mem_faults++; | pc.str_mem_faults++; | |||
sfBase.iStreamFaults++; | sfBase.iStreamFaults++; | |||
if ( !p ) | if ( !p ) | |||
{ | { | |||
session_mem_in_use -= size; | session_mem_in_use -= size; | |||
return NULL; | return NULL; | |||
} | } | |||
/* Smack the older time'd out sessions */ | /* Smack the older time'd out sessions */ | |||
if ( !session_api->prune_session_cache( tcp_lws_cache, p->pkth->ts.tv_se c, | if ( !session_api->prune_session_cache( tcp_lws_cache, p->pkth->ts.tv_se c, | |||
( SessionControlBlock * ) p->ssnptr, 0 ) ) | ( SessionControlBlock * ) p->ssnptr, 0 ) ) | |||
{ | { | |||
/* Try the memcap - last parameter (1) specifies check | /* Try the memcap - last parameter (1) specifies check | |||
* based on memory cap. */ | * based on memory cap. */ | |||
session_api->prune_session_cache(tcp_lws_cache, 0, (SessionControlBl ock*) p->ssnptr, 1); | session_api->prune_session_cache(tcp_lws_cache, 0, (SessionControlBl ock*) p->ssnptr, 1); | |||
} | } | |||
} | } | |||
if (session_mem_in_use > stream_session_config->memcap) | ||||
{ | ||||
session_mem_in_use -= size; | ||||
return NULL; | ||||
} | ||||
ss = SnortAlloc(size); | ss = SnortAlloc(size); | |||
ss->tv.tv_sec = tv->tv_sec; | ss->tv.tv_sec = tv->tv_sec; | |||
ss->tv.tv_usec = tv->tv_usec; | ss->tv.tv_usec = tv->tv_usec; | |||
ss->caplen = caplen; | ss->caplen = caplen; | |||
ss->pktlen = pktlen; | ss->pktlen = pktlen; | |||
memcpy(ss->pkt, pkt, caplen); | memcpy(ss->pkt, pkt, caplen); | |||
skipping to change at line 6655 | skipping to change at line 6668 | |||
FatalError("Circular list, WTF?\n"); | FatalError("Circular list, WTF?\n"); | |||
idx = idx->next; | idx = idx->next; | |||
} | } | |||
} | } | |||
#endif | #endif | |||
return STREAM_INSERT_ANOMALY; | return STREAM_INSERT_ANOMALY; | |||
} | } | |||
ss = SegmentAlloc(p, &p->pkth->ts, p->pkth->caplen, p->pkth->pktlen, p->pkt) ; | ss = SegmentAlloc(p, &p->pkth->ts, p->pkth->caplen, p->pkth->pktlen, p->pkt) ; | |||
if (!ss) | ||||
return STREAM_INSERT_ANOMALY; | ||||
ss->data = ss->pkt + (p->data - p->pkt); | ss->data = ss->pkt + (p->data - p->pkt); | |||
ss->orig_dsize = p->dsize; | ss->orig_dsize = p->dsize; | |||
ss->payload = ss->data + slide; | ss->payload = ss->data + slide; | |||
ss->size = (uint16_t)newSize; | ss->size = (uint16_t)newSize; | |||
ss->seq = seq; | ss->seq = seq; | |||
ss->ts = tdb->ts; | ss->ts = tdb->ts; | |||
/* handle the urg ptr */ | /* handle the urg ptr */ | |||
skipping to change at line 6825 | skipping to change at line 6840 | |||
if (held_seg == NULL) | if (held_seg == NULL) | |||
return FALSE; | return FALSE; | |||
if (held_seg->seq == tdb->seq) | if (held_seg->seq == tdb->seq) | |||
return TRUE; | return TRUE; | |||
return FALSE; | return FALSE; | |||
} | } | |||
static bool IsTCPFastOpenPkt (Packet *p) | ||||
{ | ||||
uint8_t opt_count = 0; | ||||
while (opt_count < p->tcp_option_count) | ||||
{ | ||||
if (p->tcp_options[opt_count].code == TCPOPT_TFO) | ||||
{ | ||||
return TRUE; | ||||
} | ||||
opt_count++; | ||||
} | ||||
return FALSE; | ||||
} | ||||
static int StreamQueue(StreamTracker *st, Packet *p, TcpDataBlock *tdb, | static int StreamQueue(StreamTracker *st, Packet *p, TcpDataBlock *tdb, | |||
TcpSession *tcpssn) | TcpSession *tcpssn) | |||
{ | { | |||
StreamSegment *ss = NULL; | StreamSegment *ss = NULL; | |||
StreamSegment *left = NULL; | StreamSegment *left = NULL; | |||
StreamSegment *right = NULL; | StreamSegment *right = NULL; | |||
StreamSegment *dump_me = NULL; | StreamSegment *dump_me = NULL; | |||
uint32_t seq = tdb->seq; | uint32_t seq = tdb->seq; | |||
uint32_t seq_end = tdb->end_seq; | uint32_t seq_end = tdb->end_seq; | |||
uint16_t len = p->dsize; | uint16_t len = p->dsize; | |||
skipping to change at line 7709 | skipping to change at line 7739 | |||
"Ignoring segment due to IGNORE flush_policy\n");); | "Ignoring segment due to IGNORE flush_policy\n");); | |||
return; | return; | |||
} | } | |||
else | else | |||
{ | { | |||
STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | |||
"queuing segment\n");); | "queuing segment\n");); | |||
if ( SEQ_GT(rcv->r_win_base, tdb->seq) ) | if ( SEQ_GT(rcv->r_win_base, tdb->seq) ) | |||
{ | { | |||
//Received data segment whose seq no is less than already ACKed | uint32_t offset = rcv->r_win_base - tdb->seq; | |||
bytes | ||||
if(SEQ_GT(rcv->r_nxt_ack, tdb->seq)) | if ( offset < p->dsize ) | |||
{ | ||||
//We have already seen the data and this is a retransmission | ||||
with different packet size | ||||
//Add the packet to seglist if the size is more than offset | ||||
uint32_t offset = rcv->r_win_base - tdb-> | ||||
seq; | ||||
if ( offset < p->dsize ) | ||||
{ | ||||
tdb->seq += offset; | ||||
p->data += offset; | ||||
p->dsize -= (uint16_t)offset; | ||||
StreamQueue(rcv, p, tdb, tcpssn); | ||||
//Restore the original seq and dsize before the packet i | ||||
s egressed | ||||
p->dsize += (uint16_t)offset; | ||||
p->data -= offset; | ||||
tdb->seq -= offset; | ||||
} | ||||
} | ||||
else | ||||
{ | { | |||
//We have NOT seen the data. Add it to stream queue | tdb->seq += offset; | |||
p->data += offset; | ||||
p->dsize -= (uint16_t)offset; | ||||
StreamQueue(rcv, p, tdb, tcpssn); | StreamQueue(rcv, p, tdb, tcpssn); | |||
p->dsize += (uint16_t)offset; | ||||
p->data -= offset; | ||||
tdb->seq -= offset; | ||||
} | } | |||
} | } | |||
else | else | |||
StreamQueue(rcv, p, tdb, tcpssn); | StreamQueue(rcv, p, tdb, tcpssn); | |||
if ((rcv->tcp_policy->overlap_limit) && | if ((rcv->tcp_policy->overlap_limit) && | |||
(rcv->overlap_count > rcv->tcp_policy->overlap_limit)) | (rcv->overlap_count > rcv->tcp_policy->overlap_limit)) | |||
{ | { | |||
STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | |||
"Reached the overlap limit. Flush the data " | "Reached the overlap limit. Flush the data " | |||
skipping to change at line 7808 | skipping to change at line 7828 | |||
static int ProcessTcpData(Packet *p, StreamTracker *listener, TcpSession *tcpssn , | static int ProcessTcpData(Packet *p, StreamTracker *listener, TcpSession *tcpssn , | |||
TcpDataBlock *tdb, StreamTcpPolicy *s5TcpPolicy) | TcpDataBlock *tdb, StreamTcpPolicy *s5TcpPolicy) | |||
{ | { | |||
PROFILE_VARS; | PROFILE_VARS; | |||
STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | |||
"In ProcessTcpData()\n");); | "In ProcessTcpData()\n");); | |||
PREPROC_PROFILE_START(s5TcpDataPerfStats); | PREPROC_PROFILE_START(s5TcpDataPerfStats); | |||
if ((p->tcph->th_flags & TH_SYN) && (listener->os_policy != STREAM_POLICY_MA COS)) | if (!IsTCPFastOpenPkt(p) && (p->tcph->th_flags & TH_SYN) && (listener->os_po licy != STREAM_POLICY_MACOS)) | |||
{ | { | |||
STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | |||
"Bailing, data on SYN, not MAC Policy!\n");); | "Bailing, data on SYN, not MAC Policy!\n");); | |||
NormalTrimPayloadIfSyn(p, 0, tdb); | NormalTrimPayloadIfSyn(p, 0, tdb); | |||
PREPROC_PROFILE_END(s5TcpDataPerfStats); | PREPROC_PROFILE_END(s5TcpDataPerfStats); | |||
return STREAM_UNALIGNED; | return STREAM_UNALIGNED; | |||
} | } | |||
/* we're aligned, so that's nice anyway */ | /* we're aligned, so that's nice anyway */ | |||
if((tdb->seq == listener->r_nxt_ack) || (p->tcph->th_flags & TH_SYN)) | if((tdb->seq == listener->r_nxt_ack) || (p->tcph->th_flags & TH_SYN)) | |||
skipping to change at line 9186 | skipping to change at line 9206 | |||
ignore = StreamExpectCheck(p, scb); | ignore = StreamExpectCheck(p, scb); | |||
if (ignore) | if (ignore) | |||
{ | { | |||
DisableInspection(scb, p, ignore); | DisableInspection(scb, p, ignore); | |||
PREPROC_PROFILE_END(s5TcpStatePerfStats); | PREPROC_PROFILE_END(s5TcpStatePerfStats); | |||
return retcode; | return retcode; | |||
} | } | |||
} | } | |||
/* Handle data on SYN */ | /* Handle data on SYN */ | |||
if ((p->dsize) && TCP_ISFLAGSET(p->tcph, TH_SYN)) | if (!IsTCPFastOpenPkt(p) && p->dsize && TCP_ISFLAGSET(p->tcph, TH_SYN)) | |||
{ | { | |||
/* MacOS accepts data on SYN, so don't alert if policy is MACOS */ | /* MacOS accepts data on SYN, so don't alert if policy is MACOS */ | |||
if (StreamGetPolicy(scb, s5TcpPolicy, FROM_CLIENT) != | if (StreamGetPolicy(scb, s5TcpPolicy, FROM_CLIENT) != | |||
STREAM_POLICY_MACOS) | STREAM_POLICY_MACOS) | |||
{ | { | |||
#ifdef NORMALIZER | #ifdef NORMALIZER | |||
NormalTrimPayloadIfSyn(p, 0, tdb); // remove data on SYN | NormalTrimPayloadIfSyn(p, 0, tdb); // remove data on SYN | |||
if ( Normalize_GetMode(snort_conf, NORM_TCP_TRIM_SYN) == NORM_MODE_O FF) | if ( Normalize_GetMode(snort_conf, NORM_TCP_TRIM_SYN) == NORM_MODE_O FF) | |||
#endif | #endif | |||
{ | { | |||
skipping to change at line 9599 | skipping to change at line 9619 | |||
talker->flags |= got_ts; | talker->flags |= got_ts; | |||
if(got_ts && SEQ_EQ(listener->r_nxt_ack, tdb->seq)) | if(got_ts && SEQ_EQ(listener->r_nxt_ack, tdb->seq)) | |||
{ | { | |||
talker->ts_last_pkt = p->pkth->ts.tv_sec; | talker->ts_last_pkt = p->pkth->ts.tv_sec; | |||
talker->ts_last = tdb->ts; | talker->ts_last = tdb->ts; | |||
} | } | |||
break; | break; | |||
case TCP_STATE_ESTABLISHED: | case TCP_STATE_ESTABLISHED: | |||
case TCP_STATE_CLOSE_WAIT: | /* Handle out-of-order/OOO ACK */ | |||
if ((Normalize_GetMode(snort_conf, NORM_TCP_IPS) == NORM_MODE_ON | ||||
) && | ||||
(SEQ_GT(tdb->ack, listener->l_nxt_seq))) | ||||
{ | ||||
NormalDropPacket(p); | ||||
PREPROC_PROFILE_END(s5TcpStatePerfStats); | ||||
return retcode | ACTION_BAD_PKT; | ||||
} | ||||
UpdateSsn(p, listener, talker, tdb); | UpdateSsn(p, listener, talker, tdb); | |||
break; | break; | |||
case TCP_STATE_FIN_WAIT_1: | case TCP_STATE_CLOSE_WAIT: | |||
UpdateSsn(p, listener, talker, tdb); | UpdateSsn(p, listener, talker, tdb); | |||
break; | ||||
case TCP_STATE_FIN_WAIT_1: | ||||
STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | |||
"tdb->ack %X >= talker->r_nxt_ack %X\n", | "tdb->ack %X >= talker->r_nxt_ack %X\n", | |||
tdb->ack, talker->r_nxt_ack);); | tdb->ack, talker->r_nxt_ack);); | |||
if ( SEQ_EQ(tdb->ack, listener->l_nxt_seq) ) | if ( SEQ_EQ(tdb->ack, listener->l_nxt_seq) ) | |||
{ | { | |||
if ( (listener->os_policy == STREAM_POLICY_WINDOWS) && (tdb- >win == 0) ) | if ( (listener->os_policy == STREAM_POLICY_WINDOWS) && (tdb- >win == 0) ) | |||
{ | { | |||
eventcode |= EVENT_WINDOW_SLAM; | eventcode |= EVENT_WINDOW_SLAM; | |||
Discard(); | Discard(); | |||
skipping to change at line 9627 | skipping to change at line 9656 | |||
#ifdef NORMALIZER | #ifdef NORMALIZER | |||
if ( NormalDropPacket(p) ) | if ( NormalDropPacket(p) ) | |||
{ | { | |||
LogTcpEvents(listener->tcp_policy, eventcode); | LogTcpEvents(listener->tcp_policy, eventcode); | |||
PREPROC_PROFILE_END(s5TcpStatePerfStats); | PREPROC_PROFILE_END(s5TcpStatePerfStats); | |||
return retcode | ACTION_BAD_PKT; | return retcode | ACTION_BAD_PKT; | |||
} | } | |||
#endif | #endif | |||
} | } | |||
UpdateSsn(p, listener, talker, tdb); | ||||
listener->s_mgr.state = TCP_STATE_FIN_WAIT_2; | listener->s_mgr.state = TCP_STATE_FIN_WAIT_2; | |||
if ( (p->tcph->th_flags & TH_FIN) ) | if ( (p->tcph->th_flags & TH_FIN) ) | |||
{ | { | |||
STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | |||
"seq ok, setting state!\n");); | "seq ok, setting state!\n");); | |||
if (talker->s_mgr.state_queue == TCP_STATE_NONE) | if (talker->s_mgr.state_queue == TCP_STATE_NONE) | |||
{ | { | |||
talker->s_mgr.state = TCP_STATE_LAST_ACK; | talker->s_mgr.state = TCP_STATE_LAST_ACK; | |||
skipping to change at line 9657 | skipping to change at line 9687 | |||
} | } | |||
else if (listener->s_mgr.state_queue == TCP_STATE_CLOSING) | else if (listener->s_mgr.state_queue == TCP_STATE_CLOSING) | |||
{ | { | |||
listener->s_mgr.state_queue = TCP_STATE_TIME_WAIT; | listener->s_mgr.state_queue = TCP_STATE_TIME_WAIT; | |||
listener->s_mgr.transition_seq = tdb->end_seq; | listener->s_mgr.transition_seq = tdb->end_seq; | |||
listener->s_mgr.expected_flags = TH_ACK; | listener->s_mgr.expected_flags = TH_ACK; | |||
} | } | |||
} | } | |||
else | else | |||
{ | { | |||
UpdateSsn(p, listener, talker, tdb); | ||||
STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, | |||
"bad ack!\n");); | "bad ack!\n");); | |||
} | } | |||
break; | break; | |||
case TCP_STATE_FIN_WAIT_2: | case TCP_STATE_FIN_WAIT_2: | |||
UpdateSsn(p, listener, talker, tdb); | ||||
if ( SEQ_GT(tdb->ack, listener->l_nxt_seq) ) | if ( SEQ_GT(tdb->ack, listener->l_nxt_seq) ) | |||
{ | { | |||
eventcode |= EVENT_BAD_ACK; | eventcode |= EVENT_BAD_ACK; | |||
LogTcpEvents(talker->tcp_policy, eventcode); | LogTcpEvents(talker->tcp_policy, eventcode); | |||
NormalDropPacket(p); | NormalDropPacket(p); | |||
PREPROC_PROFILE_END(s5TcpStatePerfStats); | PREPROC_PROFILE_END(s5TcpStatePerfStats); | |||
return retcode | ACTION_BAD_PKT; | return retcode | ACTION_BAD_PKT; | |||
} | } | |||
UpdateSsn(p, listener, talker, tdb); | ||||
break; | break; | |||
case TCP_STATE_CLOSING: | case TCP_STATE_CLOSING: | |||
UpdateSsn(p, listener, talker, tdb); | UpdateSsn(p, listener, talker, tdb); | |||
if(SEQ_GEQ(tdb->end_seq, listener->r_nxt_ack)) | if(SEQ_GEQ(tdb->end_seq, listener->r_nxt_ack)) | |||
{ | { | |||
listener->s_mgr.state = TCP_STATE_TIME_WAIT; | listener->s_mgr.state = TCP_STATE_TIME_WAIT; | |||
} | } | |||
break; | break; | |||
skipping to change at line 12215 | skipping to change at line 12246 | |||
{ | { | |||
NetworkReassemblyPorts *nrp = ( NetworkReassemblyPorts * ) data; | NetworkReassemblyPorts *nrp = ( NetworkReassemblyPorts * ) data; | |||
if( nrp->ip != NULL ) | if( nrp->ip != NULL ) | |||
free( nrp->ip ); | free( nrp->ip ); | |||
free( data ); | free( data ); | |||
} | } | |||
} | } | |||
static void StreamCreateReassemblyPortList( void ) | static void StreamCreateReassemblyPortList( void ) | |||
{ | { | |||
//In SnortInit, we call ConfigurePreprocessors twice. The allocations done f | ||||
irst need to be freed | ||||
if(targeted_nrps.size > 0) | ||||
StreamDestoryReassemblyPortList(); | ||||
sf_sdlist_init( &targeted_nrps, &freeNrpNode ); | sf_sdlist_init( &targeted_nrps, &freeNrpNode ); | |||
} | } | |||
static void StreamDestoryReassemblyPortList( void ) | static void StreamDestoryReassemblyPortList( void ) | |||
{ | { | |||
sf_sdlist_purge( &targeted_nrps ); | sf_sdlist_purge( &targeted_nrps ); | |||
} | } | |||
static NetworkReassemblyPorts *initNetworkPortReassembly( sfcidr_t *ip, unsigned short port, int ra_dir ) | static NetworkReassemblyPorts *initNetworkPortReassembly( sfcidr_t *ip, unsigned short port, int ra_dir ) | |||
{ | { | |||
skipping to change at line 12543 | skipping to change at line 12578 | |||
talker = &tcpssn->client; | talker = &tcpssn->client; | |||
listener = &tcpssn->server; | listener = &tcpssn->server; | |||
} | } | |||
talker->l_unackd += tcp_payload_len; | talker->l_unackd += tcp_payload_len; | |||
listener->r_win_base += tcp_payload_len; | listener->r_win_base += tcp_payload_len; | |||
purge_flushed_ackd(tcpssn, listener); | purge_flushed_ackd(tcpssn, listener); | |||
return 0; | return 0; | |||
} | } | |||
#endif | #endif | |||
size_t get_tcp_used_mempool() | ||||
{ | ||||
if (tcp_lws_cache && tcp_lws_cache->protocol_session_pool) | ||||
return tcp_lws_cache->protocol_session_pool->used_memory; | ||||
return 0; | ||||
} | ||||
End of changes. 27 change blocks. | ||||
58 lines changed or deleted | 84 lines changed or added |