imap_ssn->mime_ssn= new ImapMime(p, &(config->decode_conf), &(config->log_config));
imap_ssn->mime_ssn->set_mime_stats(&(imapstats.mime_stats));
- if (p->packet_flags & SSNFLAG_MIDSTREAM)
+ if (Stream::is_midstream(p->flow))
imap_ssn->state = STATE_UNKNOWN;
imap_ssn->body_read = imap_ssn->body_len = 0;
pop_ssn->mime_ssn = new PopMime(p, &(config->decode_conf), &(config->log_config));
pop_ssn->mime_ssn->set_mime_stats(&(popstats.mime_stats));
- if (p->packet_flags & SSNFLAG_MIDSTREAM)
- {
+ if (Stream::is_midstream(p->flow))
pop_ssn->state = STATE_UNKNOWN;
- }
return pop_ssn;
}
#define IP_POLICIES \
"first | linux | bsd | bsd_right | last | windows | solaris"
-// sequence must match enum StreamPolicy defines in tcp_defs.h
+// This sequence defines the user configurable options for TCP normalization behavior and
+// TCP overlap resolution behavior. The enums Normalizer::Policy and Overlap::Policy defined
+// in tcp_defs.h must match the order of the policy types defined here.
#define TCP_POLICIES \
"first | last | linux | old_linux | bsd | macos | solaris | irix | " \
- "hpux11 | hpux10 | windows | win_2003 | vista | proxy | asymmetric"
+ "hpux11 | hpux10 | windows | win_2003 | vista"
struct AlertInfo
{
#define MAX_ZERO_WIN_PROBE_LEN 1
#define MAX_KEEP_ALIVE_PROBE_LEN 1
-// target-based policy types - changes to this enum require changes to stream.h::TCP_POLICIES
-enum StreamPolicy : uint8_t
+// The normalizer policy options FIRST thru VISTA are user configurable normalizer polices and this sequence
+// must match with the configuration strings defined by TCP_POLICIES in stream.h. The normalizer policy types
+// defined after VISTA are determined dynamically and assigned to a flow when appropriate, they are not configurable.
+namespace Normalizer
{
- OS_FIRST = 0,
- OS_LAST,
- OS_LINUX,
- OS_OLD_LINUX,
- OS_BSD,
- OS_MACOS,
- OS_SOLARIS,
- OS_IRIX,
- OS_HPUX11,
- OS_HPUX10,
- OS_WINDOWS,
- OS_WINDOWS2K3,
- OS_VISTA,
- OS_PROXY,
- MISSED_3WHS,
- OS_END_OF_LIST,
- OS_DEFAULT = OS_BSD
-};
+ enum Policy : uint8_t
+ {
+ FIRST = 0,
+ LAST,
+ LINUX,
+ OLD_LINUX,
+ BSD,
+ MACOS,
+ SOLARIS,
+ IRIX,
+ HPUX11,
+ HPUX10,
+ WINDOWS,
+ WINDOWS2K3,
+ VISTA,
+ PROXY,
+ MISSED_3WHS,
+ MAX_NORM_POLICY,
+ DEFAULT = BSD
+ };
+}
+
+// increment operator...
+inline Normalizer::Policy& operator++(Normalizer::Policy& c, int)
+{
+ if ( c < Normalizer::Policy::MAX_NORM_POLICY )
+ c = static_cast<Normalizer::Policy>( static_cast<int>(c) + 1 );
+ else
+ c = Normalizer::Policy::MAX_NORM_POLICY;
+
+ return c;
+}
+
+// The overlap policy options FIRST thru VISTA are user configurable normalizer polices and this sequence
+// must match with the configuration strings defined by TCP_POLICIES in stream.h. Note that the FIRST overlap
+// policy is configurable but is also the policy used for all flows when stream is configured to be in IPS mode.
+namespace Overlap
+{
+ enum Policy : uint8_t
+ {
+ FIRST = 0,
+ LAST,
+ LINUX,
+ OLD_LINUX,
+ BSD,
+ MACOS,
+ SOLARIS,
+ IRIX,
+ HPUX11,
+ HPUX10,
+ WINDOWS,
+ WINDOWS2K3,
+ VISTA,
+ MAX_OVERLAP_POLICY,
+ DEFAULT_POLICY = BSD
+ };
+}
// increment operator...
-inline StreamPolicy& operator++(StreamPolicy& c, int)
+inline Overlap::Policy& operator++(Overlap::Policy& c, int)
{
- if ( c < StreamPolicy::OS_END_OF_LIST )
- c = static_cast<StreamPolicy>( static_cast<int>(c) + 1 );
+ if ( c < Overlap::Policy::MAX_OVERLAP_POLICY )
+ c = static_cast<Overlap::Policy>( static_cast<int>(c) + 1 );
else
- c = StreamPolicy::OS_END_OF_LIST;
+ c = Overlap::Policy::MAX_OVERLAP_POLICY;
return c;
}
config->no_ack = v.get_bool();
else if ( v.is("policy") )
- config->policy = static_cast< StreamPolicy >( v.get_uint8() );
+ config->policy = static_cast< Normalizer::Policy >( v.get_uint8() );
else if ( v.is("overlap_limit") )
config->overlap_limit = v.get_uint32();
{
if ( tns.tracker->get_snd_wnd() )
{
- if ( !(tns.session->flow->session_state & STREAM_STATE_MIDSTREAM ) )
+ if ( !Stream::is_midstream(tns.session->flow) )
return tns.tracker->get_snd_wnd();
}
else if ( tns.session->flow->two_way_traffic() )
tns.session->tel.set_tcp_event(EVENT_NO_TIMESTAMP);
/* Ignore the timestamp for this first packet, next one will checked. */
- if ( tns.session->tcp_config->policy == StreamPolicy::OS_SOLARIS )
+ if ( tns.session->tcp_config->policy == Normalizer::Policy::SOLARIS )
tns.tracker->clear_tf_flags(TF_TSTAMP);
packet_dropper(tns, tsd, NORM_TCP_OPT);
TcpStreamTracker* peer_tracker = nullptr;
TcpNormalizer* prev_norm = nullptr;
- StreamPolicy os_policy = StreamPolicy::OS_DEFAULT;
+ Normalizer::Policy norm_policy = Normalizer::Policy::DEFAULT;
int32_t paws_ts_fudge = 0;
int tcp_ts_flags = 0;
#include "tcp_normalizers.h"
+#include "packet_io/packet_tracer.h"
+
#include "tcp_module.h"
#include "tcp_segment_descriptor.h"
#include "tcp_session.h"
return tns.prev_norm->handle_repeated_syn(tns, tsd);
}
-void TcpNormalizerPolicy::init(StreamPolicy os, TcpSession* ssn, TcpStreamTracker* trk, TcpStreamTracker* peer)
+void TcpNormalizerPolicy::init(Normalizer::Policy os, TcpSession* ssn, TcpStreamTracker* trk, TcpStreamTracker* peer)
{
- if ( os == StreamPolicy::MISSED_3WHS and os == tns.os_policy)
- tns.prev_norm = TcpNormalizerFactory::get_instance(StreamPolicy::OS_DEFAULT);
- else
- tns.prev_norm = TcpNormalizerFactory::get_instance(tns.os_policy);
+ if ( os == Normalizer::Policy::MISSED_3WHS )
+ {
+ // missed 3whs may have been set earlier
+ if ( os == tns.norm_policy )
+ return;
+
+ tns.prev_norm = norm;
+ }
- tns.os_policy = os;
+ tns.norm_policy = os;
tns.session = ssn;
tns.tracker = trk;
tns.peer_tracker = peer;
norm = TcpNormalizerFactory::get_instance(os);
norm->init(tns);
+
+ if ( PacketTracer::is_active() )
+ {
+ if ( os == Normalizer::Policy::MISSED_3WHS )
+ PacketTracer::log("stream_tcp: %s tracker normalization policy set to %s. Some normalizations are disabled.\n",
+ trk->client_tracker ? "client" : "server", norm->get_name().c_str());
+ else if ( os == Normalizer::Policy::PROXY )
+ PacketTracer::log("stream_tcp: %s tracker normalization policy set to %s. Normalizations are disabled.\n",
+ trk->client_tracker ? "client" : "server", norm->get_name().c_str());
+ else
+ PacketTracer::log("stream_tcp: %s tracker normalization policy set to %s\n",
+ trk->client_tracker ? "client" : "server", norm->get_name().c_str());
+ }
+
}
-TcpNormalizer* TcpNormalizerFactory::normalizers[StreamPolicy::OS_END_OF_LIST];
+TcpNormalizer* TcpNormalizerFactory::normalizers[Normalizer::Policy::MAX_NORM_POLICY];
void TcpNormalizerFactory::initialize()
{
- normalizers[StreamPolicy::OS_FIRST] = new TcpNormalizerFirst;
- normalizers[StreamPolicy::OS_LAST] = new TcpNormalizerLast;
- normalizers[StreamPolicy::OS_LINUX] = new TcpNormalizerLinux;
- normalizers[StreamPolicy::OS_OLD_LINUX] = new TcpNormalizerOldLinux;
- normalizers[StreamPolicy::OS_BSD] = new TcpNormalizerBSD;
- normalizers[StreamPolicy::OS_MACOS] = new TcpNormalizerMacOS;
- normalizers[StreamPolicy::OS_SOLARIS] = new TcpNormalizerSolaris;
- normalizers[StreamPolicy::OS_IRIX] = new TcpNormalizerIrix;
- normalizers[StreamPolicy::OS_HPUX11] = new TcpNormalizerHpux11;
- normalizers[StreamPolicy::OS_HPUX10] = new TcpNormalizerHpux10;
- normalizers[StreamPolicy::OS_WINDOWS] = new TcpNormalizerWindows;
- normalizers[StreamPolicy::OS_WINDOWS2K3] = new TcpNormalizerWindows2K3;
- normalizers[StreamPolicy::OS_VISTA] = new TcpNormalizerVista;
- normalizers[StreamPolicy::OS_PROXY] = new TcpNormalizerProxy;
- normalizers[StreamPolicy::MISSED_3WHS] = new TcpNormalizerMissed3whs;
+ normalizers[Normalizer::Policy::FIRST] = new TcpNormalizerFirst;
+ normalizers[Normalizer::Policy::LAST] = new TcpNormalizerLast;
+ normalizers[Normalizer::Policy::LINUX] = new TcpNormalizerLinux;
+ normalizers[Normalizer::Policy::OLD_LINUX] = new TcpNormalizerOldLinux;
+ normalizers[Normalizer::Policy::BSD] = new TcpNormalizerBSD;
+ normalizers[Normalizer::Policy::MACOS] = new TcpNormalizerMacOS;
+ normalizers[Normalizer::Policy::SOLARIS] = new TcpNormalizerSolaris;
+ normalizers[Normalizer::Policy::IRIX] = new TcpNormalizerIrix;
+ normalizers[Normalizer::Policy::HPUX11] = new TcpNormalizerHpux11;
+ normalizers[Normalizer::Policy::HPUX10] = new TcpNormalizerHpux10;
+ normalizers[Normalizer::Policy::WINDOWS] = new TcpNormalizerWindows;
+ normalizers[Normalizer::Policy::WINDOWS2K3] = new TcpNormalizerWindows2K3;
+ normalizers[Normalizer::Policy::VISTA] = new TcpNormalizerVista;
+ normalizers[Normalizer::Policy::PROXY] = new TcpNormalizerProxy;
+ normalizers[Normalizer::Policy::MISSED_3WHS] = new TcpNormalizerMissed3whs;
}
void TcpNormalizerFactory::term()
{
- for ( auto sp = StreamPolicy::OS_FIRST; sp < StreamPolicy::OS_END_OF_LIST; sp++ )
+ for ( auto sp = Normalizer::Policy::FIRST; sp < Normalizer::Policy::MAX_NORM_POLICY; sp++ )
delete normalizers[sp];
}
-TcpNormalizer* TcpNormalizerFactory::get_instance(StreamPolicy sp)
+TcpNormalizer* TcpNormalizerFactory::get_instance(Normalizer::Policy sp)
{
- assert( sp < StreamPolicy::OS_END_OF_LIST );
+ assert( sp < Normalizer::Policy::MAX_NORM_POLICY );
return normalizers[sp];
}
public:
static void initialize();
static void term();
- static TcpNormalizer* get_instance(StreamPolicy);
+ static TcpNormalizer* get_instance(Normalizer::Policy);
private:
TcpNormalizerFactory() = delete;
- static TcpNormalizer* normalizers[StreamPolicy::OS_END_OF_LIST];
+ static TcpNormalizer* normalizers[Normalizer::Policy::MAX_NORM_POLICY];
};
class TcpNormalizerPolicy
TcpNormalizerPolicy() = default;
~TcpNormalizerPolicy() = default;
- void init(StreamPolicy os, TcpSession* ssn, TcpStreamTracker* trk, TcpStreamTracker* peer);
- void reset()
- { init(StreamPolicy::OS_DEFAULT, nullptr, nullptr, nullptr); }
+ void init(Normalizer::Policy os, TcpSession* ssn, TcpStreamTracker* trk, TcpStreamTracker* peer);
TcpNormalizer::NormStatus apply_normalizations(TcpSegmentDescriptor& tsd, uint32_t seq, bool stream_is_inorder)
{ return norm->apply_normalizations(tns, tsd, seq, stream_is_inorder); }
uint16_t set_urg_offset(const snort::tcp::TCPHdr* tcph, uint16_t dsize)
{ return norm->set_urg_offset(tns, tcph, dsize); }
- StreamPolicy get_os_policy() const
- { return tns.os_policy; }
+ Normalizer::Policy get_norm_policy() const
+ { return tns.norm_policy; }
bool is_paws_drop_zero_ts() const
{ return tns.paws_drop_zero_ts; }
{
public:
TcpOverlapResolverFirst()
- { overlap_policy = StreamPolicy::OS_FIRST; }
+ { overlap_policy = Overlap::Policy::FIRST; }
private:
void insert_left_overlap(TcpOverlapState& tos) override
{
public:
TcpOverlapResolverLast()
- { overlap_policy = StreamPolicy::OS_LAST; }
+ { overlap_policy = Overlap::Policy::LAST; }
private:
void right_overlap_truncate_existing(TcpOverlapState& tos) override
{
public:
TcpOverlapResolverLinux()
- { overlap_policy = StreamPolicy::OS_LINUX; }
+ { overlap_policy = Overlap::Policy::LINUX; }
private:
void insert_left_overlap(TcpOverlapState& tos) override
{
public:
TcpOverlapResolverOldLinux()
- { overlap_policy = StreamPolicy::OS_OLD_LINUX; }
+ { overlap_policy = Overlap::Policy::OLD_LINUX; }
private:
void insert_left_overlap(TcpOverlapState& tos) override
{
public:
TcpOverlapResolverBSD()
- { overlap_policy = StreamPolicy::OS_BSD; }
+ { overlap_policy = Overlap::Policy::BSD; }
private:
void insert_left_overlap(TcpOverlapState& tos) override
{
public:
TcpOverlapResolverMacOS()
- { overlap_policy = StreamPolicy::OS_MACOS; }
+ { overlap_policy = Overlap::Policy::MACOS; }
private:
void insert_left_overlap(TcpOverlapState& tos) override
{
public:
TcpOverlapResolverSolaris()
- { overlap_policy = StreamPolicy::OS_SOLARIS; }
+ { overlap_policy = Overlap::Policy::SOLARIS; }
private:
void insert_left_overlap(TcpOverlapState& tos) override
{
public:
TcpOverlapResolverIrix()
- { overlap_policy = StreamPolicy::OS_IRIX; }
+ { overlap_policy = Overlap::Policy::IRIX; }
private:
void insert_left_overlap(TcpOverlapState& tos) override
{
public:
TcpOverlapResolverHpux11()
- { overlap_policy = StreamPolicy::OS_HPUX11; }
+ { overlap_policy = Overlap::Policy::HPUX11; }
private:
void insert_left_overlap(TcpOverlapState& tos) override
{
public:
TcpOverlapResolverHpux10()
- { overlap_policy = StreamPolicy::OS_HPUX10; }
+ { overlap_policy = Overlap::Policy::HPUX10; }
private:
void insert_left_overlap(TcpOverlapState& tos) override
{
public:
TcpOverlapResolverWindows()
- { overlap_policy = StreamPolicy::OS_WINDOWS; }
+ { overlap_policy = Overlap::Policy::WINDOWS; }
private:
void insert_left_overlap(TcpOverlapState& tos) override
{
public:
TcpOverlapResolverWindows2K3()
- { overlap_policy = StreamPolicy::OS_WINDOWS2K3; }
+ { overlap_policy = Overlap::Policy::WINDOWS2K3; }
private:
void insert_left_overlap(TcpOverlapState& tos) override
{
public:
TcpOverlapResolverVista()
- { overlap_policy = StreamPolicy::OS_VISTA; }
+ { overlap_policy = Overlap::Policy::VISTA; }
private:
void insert_left_overlap(TcpOverlapState& tos) override
{ full_right_overlap_os5 (tos); }
};
-class TcpOverlapResolverProxy : public TcpOverlapResolverFirst
-{
-public:
- TcpOverlapResolverProxy()
- { overlap_policy = StreamPolicy::OS_PROXY; }
-
-private:
- void insert_left_overlap(TcpOverlapState& tos) override
- { left_overlap_keep_first(tos); }
-
- void insert_right_overlap(TcpOverlapState& tos) override
- { right_overlap_truncate_new(tos); }
-
- void insert_full_overlap(TcpOverlapState& tos) override
- { full_right_overlap_os5(tos); }
-};
-
-TcpOverlapResolver* TcpOverlapResolverFactory::overlap_resolvers[StreamPolicy::OS_END_OF_LIST];
+TcpOverlapResolver* TcpOverlapResolverFactory::overlap_resolvers[Overlap::Policy::MAX_OVERLAP_POLICY];
void TcpOverlapResolverFactory::initialize()
{
- overlap_resolvers[StreamPolicy::OS_FIRST] = new TcpOverlapResolverFirst;
- overlap_resolvers[StreamPolicy::OS_LAST] = new TcpOverlapResolverLast;
- overlap_resolvers[StreamPolicy::OS_LINUX] = new TcpOverlapResolverLinux;
- overlap_resolvers[StreamPolicy::OS_OLD_LINUX] = new TcpOverlapResolverOldLinux;
- overlap_resolvers[StreamPolicy::OS_BSD] = new TcpOverlapResolverBSD;
- overlap_resolvers[StreamPolicy::OS_MACOS] = new TcpOverlapResolverMacOS;
- overlap_resolvers[StreamPolicy::OS_SOLARIS] = new TcpOverlapResolverSolaris;
- overlap_resolvers[StreamPolicy::OS_IRIX] = new TcpOverlapResolverIrix;
- overlap_resolvers[StreamPolicy::OS_HPUX11] = new TcpOverlapResolverHpux11;
- overlap_resolvers[StreamPolicy::OS_HPUX10] = new TcpOverlapResolverHpux10;
- overlap_resolvers[StreamPolicy::OS_WINDOWS] = new TcpOverlapResolverWindows;
- overlap_resolvers[StreamPolicy::OS_WINDOWS2K3] = new TcpOverlapResolverWindows2K3;
- overlap_resolvers[StreamPolicy::OS_VISTA] = new TcpOverlapResolverVista;
- overlap_resolvers[StreamPolicy::OS_PROXY] = new TcpOverlapResolverProxy;
+ overlap_resolvers[Overlap::Policy::FIRST] = new TcpOverlapResolverFirst;
+ overlap_resolvers[Overlap::Policy::LAST] = new TcpOverlapResolverLast;
+ overlap_resolvers[Overlap::Policy::LINUX] = new TcpOverlapResolverLinux;
+ overlap_resolvers[Overlap::Policy::OLD_LINUX] = new TcpOverlapResolverOldLinux;
+ overlap_resolvers[Overlap::Policy::BSD] = new TcpOverlapResolverBSD;
+ overlap_resolvers[Overlap::Policy::MACOS] = new TcpOverlapResolverMacOS;
+ overlap_resolvers[Overlap::Policy::SOLARIS] = new TcpOverlapResolverSolaris;
+ overlap_resolvers[Overlap::Policy::IRIX] = new TcpOverlapResolverIrix;
+ overlap_resolvers[Overlap::Policy::HPUX11] = new TcpOverlapResolverHpux11;
+ overlap_resolvers[Overlap::Policy::HPUX10] = new TcpOverlapResolverHpux10;
+ overlap_resolvers[Overlap::Policy::WINDOWS] = new TcpOverlapResolverWindows;
+ overlap_resolvers[Overlap::Policy::WINDOWS2K3] = new TcpOverlapResolverWindows2K3;
+ overlap_resolvers[Overlap::Policy::VISTA] = new TcpOverlapResolverVista;
}
void TcpOverlapResolverFactory::term()
{
- for ( auto sp = StreamPolicy::OS_FIRST; sp <= StreamPolicy::OS_PROXY; sp++ )
+ for ( auto sp = Overlap::Policy::FIRST; sp < Overlap::Policy::MAX_OVERLAP_POLICY; sp++ )
delete overlap_resolvers[sp];
}
-TcpOverlapResolver* TcpOverlapResolverFactory::get_instance(StreamPolicy os_policy)
+TcpOverlapResolver* TcpOverlapResolverFactory::get_instance(Overlap::Policy policy)
{
NormMode tcp_ips_data = Normalize_GetMode(NORM_TCP_IPS);
- StreamPolicy sp = (tcp_ips_data == NORM_MODE_ON) ? StreamPolicy::OS_FIRST : os_policy;
+ Overlap::Policy sp = (tcp_ips_data == NORM_MODE_ON) ? Overlap::Policy::FIRST : policy;
- assert( sp <= StreamPolicy::OS_PROXY );
+ assert( sp < Overlap::Policy::MAX_OVERLAP_POLICY );
return overlap_resolvers[sp];
}
void eval_left(TcpOverlapState&);
void eval_right(TcpOverlapState&);
- StreamPolicy get_overlap_policy()
+ Overlap::Policy get_overlap_policy()
{ return overlap_policy; }
protected:
virtual void insert_right_overlap(TcpOverlapState&) = 0;
virtual void insert_full_overlap(TcpOverlapState&) = 0;
- StreamPolicy overlap_policy = StreamPolicy::OS_DEFAULT;
+ Overlap::Policy overlap_policy = Overlap::Policy::DEFAULT_POLICY;
};
class TcpOverlapResolverFactory
public:
static void initialize();
static void term();
- static TcpOverlapResolver* get_instance(StreamPolicy);
+ static TcpOverlapResolver* get_instance(Overlap::Policy);
private:
TcpOverlapResolverFactory() = delete;
- static TcpOverlapResolver* overlap_resolvers[StreamPolicy::OS_END_OF_LIST];
+ static TcpOverlapResolver* overlap_resolvers[Overlap::Policy::MAX_OVERLAP_POLICY];
};
#endif
delete tos;
}
-void TcpReassemblySegments::init(TcpSession* ssn, TcpStreamTracker* trk, StreamPolicy pol)
+void TcpReassemblySegments::init(TcpSession* ssn, TcpStreamTracker* trk, Overlap::Policy pol)
{
session = ssn;
tracker = trk;
tracker->set_order(TcpStreamTracker::OUT_OF_SEQUENCE);
- if (PacketTracer::is_active())
+ if ( PacketTracer::is_active() )
PacketTracer::log("stream_tcp: Skipped %u packets before seglist hole\n", packets_skipped);
}
tsn = head;
}
- while (tsn->next_no_gap())
+ while ( tsn->next_no_gap() )
tsn = tsn->next;
tracker->set_rcv_nxt(tsn->next_seq());
}
bool hole_skipped = false;
- if (SEQ_GT(tsn->seq, seglist_base_seq))
+ if ( SEQ_GT(tsn->seq, seglist_base_seq) )
{
hole_skipped = true;
seglist_base_seq = tsn->seq;
tracker->set_order(TcpStreamTracker::OUT_OF_SEQUENCE);
- if (PacketTracer::is_active())
+ if ( PacketTracer::is_active() )
PacketTracer::log("stream_tcp: Skipped hole at beginning of the seglist\n");
}
{
++num_holes;
total_segs += num_segs;
- if (PacketTracer::is_active())
+ if ( PacketTracer::is_active() )
PacketTracer::log("stream_tcp: Seglist hole(%u): %u-->%u:%u. Segments purged: %u Total purged: %u\n",
tsn->seq, tsn->next->seq, tsn->next->seq - tsn->seq, num_holes, num_segs, total_segs);
tsn = tsn->next;
TcpReassemblySegments() = default;
~TcpReassemblySegments();
- void init(TcpSession* ssn, TcpStreamTracker* trk, StreamPolicy pol);
+ void init(TcpSession* ssn, TcpStreamTracker* trk, Overlap::Policy);
void reset();
void update_next(TcpSegmentNode*);
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_segment.cc author davis mcpherson <davmcphe@cisco.com>
+// tcp_segment_node.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Sep 21, 2015
#ifdef HAVE_CONFIG_H
: Session(f), client(true), server(false)
{
tsm = TcpStateMachine::get_instance();
- client.init_tcp_state(this);
- server.init_tcp_state(this);
-
tcpStats.instantiated++;
}
TcpStreamTracker* talker;
TcpStreamTracker* listener;
- if (p->is_from_server())
+ if ( p->is_from_server() )
{
talker = &server;
listener = &client;
talker->reassembler->eval_flush_policy_on_data(p);
}
- if (p->dsize > 0)
+ if ( p->dsize > 0 )
listener->reassembler->eval_flush_policy_on_data(p);
- if (p->ptrs.tcph->is_ack())
+ if ( p->ptrs.tcph->is_ack() )
talker->reassembler->eval_flush_policy_on_ack(p);
tcpStats.restarts++;
if ( flow->two_way_traffic() )
return;
- if ( PacketTracer::is_active() )
- PacketTracer::log("stream_tcp: TCP did not see the complete 3-Way Handshake. "
- "Not all normalizations will be in effect\n");
-
- client.normalizer.init(StreamPolicy::MISSED_3WHS, this, &client, &server);
- server.normalizer.init(StreamPolicy::MISSED_3WHS, this, &server, &client);
+ client.normalizer.init(Normalizer::Policy::MISSED_3WHS, this, &client, &server);
+ server.normalizer.init(Normalizer::Policy::MISSED_3WHS, this, &server, &client);
}
void TcpSession::set_os_policy()
{
- assert(tcp_config->policy <= StreamPolicy::OS_VISTA);
+ assert(tcp_config->policy <= Normalizer::Policy::VISTA);
+
+ Normalizer::Policy client_norm_policy = flow->ssn_policy ?
+ static_cast<Normalizer::Policy>( flow->ssn_policy ) : tcp_config->policy;
- StreamPolicy client_os_policy = flow->ssn_policy ?
- static_cast<StreamPolicy>( flow->ssn_policy ) : tcp_config->policy;
+ Normalizer::Policy server_norm_policy = flow->ssn_policy ?
+ static_cast<Normalizer::Policy>( flow->ssn_policy ) : tcp_config->policy;
- StreamPolicy server_os_policy = flow->ssn_policy ?
- static_cast<StreamPolicy>( flow->ssn_policy ) : tcp_config->policy;
+ client.normalizer.init(client_norm_policy, this, &client, &server);
+ server.normalizer.init(server_norm_policy, this, &server, &client);
- client.normalizer.init(client_os_policy, this, &client, &server);
- server.normalizer.init(server_os_policy, this, &server, &client);
+ Overlap::Policy client_overlap_policy;
+ Overlap::Policy server_overlap_policy;
- if (Normalize_GetMode(NORM_TCP_IPS) == NORM_MODE_ON)
+ if ( Normalize_GetMode(NORM_TCP_IPS) == NORM_MODE_ON )
{
- client_os_policy = StreamPolicy::OS_FIRST;
- server_os_policy = StreamPolicy::OS_FIRST;
+ client_overlap_policy = Overlap::Policy::FIRST;
+ server_overlap_policy = Overlap::Policy::FIRST;
+ }
+ else
+ {
+ client_overlap_policy = static_cast<Overlap::Policy>( client_norm_policy );
+ server_overlap_policy = static_cast<Overlap::Policy>( server_norm_policy );
}
- client.seglist.init(this, &client, client_os_policy);
- server.seglist.init(this, &server, server_os_policy);
+ client.seglist.init(this, &client, client_overlap_policy);
+ server.seglist.init(this, &server, server_overlap_policy);
}
// FIXIT-M this is no longer called (but should be)
TcpStreamTracker* talker = tsd.get_talker();
talker->set_tf_flags(listener->normalizer.get_timestamp_flags());
- if (listener->normalizer.handling_timestamps()
- && SEQ_EQ(listener->rcv_nxt, tsd.get_seq()))
+ if ( listener->normalizer.handling_timestamps()
+ && SEQ_EQ(listener->rcv_nxt, tsd.get_seq()) )
{
talker->set_ts_last_packet(tsd.get_packet_timestamp());
talker->set_ts_last(tsd.get_timestamp());
bool TcpSession::check_for_window_slam(TcpSegmentDescriptor& tsd)
{
- if (Stream::is_midstream(tsd.get_flow()) or !flow->two_way_traffic())
+ if ( Stream::is_midstream(tsd.get_flow()) or !flow->two_way_traffic() )
return false;
TcpStreamTracker* listener = tsd.get_listener();
}
else if ( tsd.is_packet_from_client() && (tsd.get_wnd() <= SLAM_MAX)
&& (tsd.get_ack() == listener->get_iss() + 1)
- && !(tsd.get_tcph()->is_fin() || tsd.get_tcph()->is_rst()))
+ && !(tsd.get_tcph()->is_fin() || tsd.get_tcph()->is_rst()) )
{
/* got a window slam alert! */
tel.set_tcp_event(EVENT_WINDOW_SLAM);
else
space_left = 0;
- if ( inline_mode || listener->normalizer.get_trim_win() == NORM_MODE_ON)
+ if ( inline_mode || listener->normalizer.get_trim_win() == NORM_MODE_ON )
{
// FIXIT-M - only alert once per threshold exceeded event
tel.set_tcp_event(EVENT_MAX_QUEUED_BYTES_EXCEEDED);
void TcpSession::check_small_segment_threshold(const TcpSegmentDescriptor &tsd, TcpStreamTracker *listener)
{
// alert if small segments threshold is exceeded
- if (tcp_config->max_consec_small_segs)
+ if ( tcp_config->max_consec_small_segs )
{
- if (tsd.get_len() >= tcp_config->max_consec_small_seg_size)
+ if ( tsd.get_len() >= tcp_config->max_consec_small_seg_size )
listener->small_seg_count = 0;
- else if (++listener->small_seg_count == tcp_config->max_consec_small_segs)
+ else if ( ++listener->small_seg_count == tcp_config->max_consec_small_segs )
tel.set_tcp_event(EVENT_MAX_SMALL_SEGS_EXCEEDED);
}
}
action = listener->normalizer.handle_repeated_syn(tsd);
}
- if (action != ACTION_NOTHING)
+ if ( action != ACTION_NOTHING )
{
tel.set_tcp_event(EVENT_SYN_ON_EST);
pkt_action_mask |= action;
void TcpSession::start_proxy()
{
- if ( PacketTracer::is_active() )
- PacketTracer::log("stream_tcp: TCP normalization policy set to Proxy mode. Normalizations will be skipped\n");
-
- client.normalizer.init(StreamPolicy::OS_PROXY, this, &client, &server);
- server.normalizer.init(StreamPolicy::OS_PROXY, this, &server, &client);
+ client.normalizer.init(Normalizer::Policy::PROXY, this, &client, &server);
+ server.normalizer.init(Normalizer::Policy::PROXY, this, &server, &client);
++tcpStats.proxy_mode_flows;
}
update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
flow->session_state |= STREAM_STATE_ESTABLISHED;
flow->set_idle_timeout(this->tcp_config->idle_timeout);
- if (SSNFLAG_ESTABLISHED != (SSNFLAG_ESTABLISHED & flow->get_session_flags()))
+ if ( SSNFLAG_ESTABLISHED != (SSNFLAG_ESTABLISHED & flow->get_session_flags()) )
{
flow->set_session_flags(SSNFLAG_ESTABLISHED);
// Only send 1 event
- if (SSNFLAG_TCP_PSEUDO_EST != (SSNFLAG_TCP_PSEUDO_EST & flow->get_session_flags()))
+ if ( SSNFLAG_TCP_PSEUDO_EST != (SSNFLAG_TCP_PSEUDO_EST & flow->get_session_flags()) )
DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_ESTABLISHED, tsd.get_pkt());
}
}
{
uint64_t initiator_packets;
uint64_t responder_packets;
- if (flow.flags.client_initiated)
+ if ( flow.flags.client_initiated )
{
initiator_packets = flow.flowstats.client_pkts;
responder_packets = flow.flowstats.server_pkts;
{
if ( SEQ_EQ(tsd.get_ack(), trk.get_snd_nxt() ) )
{
- if ( (trk.normalizer.get_os_policy() == StreamPolicy::OS_WINDOWS)
+ if ( (trk.normalizer.get_norm_policy() == Normalizer::Policy::WINDOWS)
&& (tsd.get_wnd() == 0))
{
trk.session->tel.set_tcp_event(EVENT_WINDOW_SLAM);
TcpStateListen::TcpStateListen(TcpStateMachine& tsm) :
TcpStateHandler(TcpStreamTracker::TCP_LISTEN, tsm)
-{
-}
+{ }
bool TcpStateListen::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
Flow* flow = tsd.get_flow();
flow->session_state |= STREAM_STATE_MIDSTREAM;
- if ( !Stream::is_midstream(flow) )
- {
- TcpStreamTracker* listener = tsd.get_listener();
- TcpStreamTracker* talker = tsd.get_talker();
-
- talker->normalizer.init(StreamPolicy::MISSED_3WHS, trk.session, talker, listener);
- listener->normalizer.init(StreamPolicy::MISSED_3WHS, trk.session, listener, talker);
- flow->set_session_flags(SSNFLAG_MIDSTREAM);
+ assert ( !Stream::is_midstream(flow) );
- if ( PacketTracer::is_active() )
- PacketTracer::log("stream_tcp: TCP did not see the complete 3-Way Handshake. "
- "Not all normalizations will be in effect\n");
-
- DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_MIDSTREAM, tsd.get_pkt());
- }
+ trk.normalizer.init(Normalizer::Policy::MISSED_3WHS, trk.session, &trk, tsd.get_listener());
+ flow->set_session_flags(SSNFLAG_MIDSTREAM);
+ DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_MIDSTREAM, tsd.get_pkt());
trk.init_on_data_seg_sent(tsd);
trk.session->init_new_tcp_session(tsd);
bool TcpStateListen::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- Flow* flow = tsd.get_flow();
- flow->session_state |= STREAM_STATE_MIDSTREAM;
+ trk.normalizer.init(Normalizer::Policy::MISSED_3WHS, trk.session, &trk, tsd.get_talker());
trk.init_on_data_seg_recv(tsd);
trk.normalizer.ecn_tracker(tsd.get_tcph());
trk.session->handle_data_segment(tsd, !trk.normalizer.is_tcp_ips_enabled());
TcpStateMidStreamRecv::TcpStateMidStreamRecv(TcpStateMachine& tsm) :
TcpStateHandler(TcpStreamTracker::TCP_MID_STREAM_RECV, tsm)
-{
-}
+{ }
bool TcpStateMidStreamRecv::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
{
if ( SEQ_EQ(tsd.get_ack(), trk.get_snd_nxt() ) )
{
- if ( (trk.normalizer.get_os_policy() == StreamPolicy::OS_WINDOWS)
+ if ( (trk.normalizer.get_norm_policy() == Normalizer::Policy::WINDOWS)
&& (tsd.get_wnd() == 0))
{
trk.session->tel.set_tcp_event(EVENT_WINDOW_SLAM);
Flow* flow = tsd.get_flow();
flow->session_state |= STREAM_STATE_MIDSTREAM;
- if ( !Stream::is_midstream(flow) )
- {
- TcpStreamTracker* listener = tsd.get_listener();
- TcpStreamTracker* talker = tsd.get_talker();
-
- talker->normalizer.init(StreamPolicy::MISSED_3WHS, trk.session, talker, listener);
- listener->normalizer.init(StreamPolicy::MISSED_3WHS, trk.session, listener, talker);
- flow->set_session_flags(SSNFLAG_MIDSTREAM);
-
- if ( PacketTracer::is_active() )
- PacketTracer::log("stream_tcp: TCP did not see the complete 3-Way Handshake. "
- "Not all normalizations will be in effect\n");
+ assert ( !Stream::is_midstream(flow) );
- DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_MIDSTREAM, tsd.get_pkt());
- }
+ trk.normalizer.init(Normalizer::Policy::MISSED_3WHS, trk.session, &trk, tsd.get_listener());
+ flow->set_session_flags(SSNFLAG_MIDSTREAM);
+ DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_MIDSTREAM, tsd.get_pkt());
trk.init_on_data_seg_sent(tsd);
trk.session->init_new_tcp_session(tsd);
bool TcpStateNone::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- Flow* flow = tsd.get_flow();
- flow->session_state |= STREAM_STATE_MIDSTREAM;
+ trk.normalizer.init(Normalizer::Policy::MISSED_3WHS, trk.session, &trk, tsd.get_talker());
trk.init_on_data_seg_recv(tsd);
trk.normalizer.ecn_tracker(tsd.get_tcph());
trk.session->handle_data_segment(tsd, !trk.normalizer.is_tcp_ips_enabled());
{
if ( trk.is_ack_valid(tsd.get_ack()) )
{
- trk.irs = tsd.get_seq();
+ trk.set_irs(tsd.get_seq());
trk.update_tracker_ack_recv(tsd);
trk.normalizer.ecn_tracker(tsd.get_tcph());
trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
bool TcpStateSynSent::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- trk.irs = tsd.get_seq();
+ trk.set_irs(tsd.get_seq());
trk.finish_client_init(tsd);
if ( tsd.is_data_segment() )
trk.session->handle_data_on_syn(tsd);
{
trk.session->check_for_repeated_syn(tsd);
trk.update_tracker_ack_sent(tsd);
- trk.iss = tsd.get_seq();
+ trk.set_iss(tsd.get_seq());
trk.session->update_timestamp_tracking(tsd);
}
return true;
void show() const;
- StreamPolicy policy = StreamPolicy::OS_DEFAULT;
+ Normalizer::Policy policy = Normalizer::Policy::DEFAULT;
uint16_t flags = 0;
uint16_t flush_factor = 0;
};
TcpStreamTracker::TcpStreamTracker(bool client) :
- tcp_state(client ? TCP_STATE_NONE : TCP_LISTEN), client_tracker(client),
+ client_tracker(client), tcp_state(client ? TCP_STATE_NONE : TCP_LISTEN),
held_packet(null_iterator)
-{ }
+{
+ flush_policy = STREAM_FLPOLICY_IGNORE;
+ update_flush_policy(nullptr);
+}
TcpStreamTracker::~TcpStreamTracker()
{
- if ( reassembler->get_flush_policy() != STREAM_FLPOLICY_IGNORE )
+ if ( reassembler and (reassembler->get_flush_policy() != STREAM_FLPOLICY_IGNORE) )
delete reassembler;
if( oaitw_reassembler )
void TcpStreamTracker::reset()
{
tcp_alerts.clear();
- normalizer.reset();
seglist.reset();
reassembler->reset_paf();
}
flush_policy = STREAM_FLPOLICY_IGNORE;
update_flush_policy(nullptr);
- normalizer.reset();
seglist.reset();
tcp_alerts.clear();
}
if ( seglist.data_was_queued() )
return; // we already have state, don't mess it up
- if ( !( flow->session_state & STREAM_STATE_MIDSTREAM ) )
+ if ( !Stream::is_midstream(flow) )
{
if ( tsd.get_tcph()->is_syn() )
seglist.set_seglist_base_seq(tsd.get_seq() + 1);
static void thread_term();
public:
- uint32_t snd_una = 0; // SND.UNA - send unacknowledged
- uint32_t snd_nxt = 0; // SND.NXT - send next
- uint32_t snd_wnd = 0; // SND.WND - send window
- uint32_t snd_wl1 = 0; // SND.WL1 - segment sequence number used for last window update
- uint32_t snd_wl2 = 0; // SND.WL2 - segment acknowledgment number used for last window update
- uint32_t iss = 0; // ISS - initial send sequence number
-
uint32_t rcv_nxt = 0; // RCV.NXT - receive next
uint32_t rcv_wnd = 0; // RCV.WND - receive window
- uint32_t irs = 0; // IRS - initial receive sequence number
-
- uint16_t snd_up = 0; // SND.UP - send urgent pointer
- uint16_t rcv_up = 0; // RCV.UP - receive urgent pointer
uint32_t held_pkt_seq = 0;
- TcpState tcp_state;
- TcpEvent tcp_event = TCP_MAX_EVENTS;
-
bool client_tracker;
- bool rst_pkt_sent = false;
bool midstream_initial_ack_flush = false;
// FIXIT-L make these non-public
-public:
TcpNormalizerPolicy normalizer;
TcpReassemblySegments seglist;
TcpReassembler* reassembler = nullptr;
private:
void update_flush_policy(snort::StreamSplitter*);
+ TcpState tcp_state;
+ TcpEvent tcp_event = TCP_MAX_EVENTS;
+
snort::StreamSplitter* splitter = nullptr;
static const std::list<HeldPacket>::iterator null_iterator;
std::list<HeldPacket>::iterator held_packet;
FlushPolicy flush_policy = STREAM_FLPOLICY_IGNORE;
bool mac_addr_valid = false;
bool fin_seq_set = false; // FIXIT-M should be obviated by tcp state
+ bool rst_pkt_sent = false;
uint8_t order = IN_SEQUENCE;
uint32_t hole_left_edge = 0; // First left hole
uint32_t hole_right_edge = 0;
+
+ uint32_t snd_una = 0; // SND.UNA - send unacknowledged
+ uint32_t snd_nxt = 0; // SND.NXT - send next
+ uint32_t snd_wnd = 0; // SND.WND - send window
+ uint32_t snd_wl1 = 0; // SND.WL1 - segment sequence number used for last window update
+ uint32_t snd_wl2 = 0; // SND.WL2 - segment acknowledgment number used for last window update
+ uint32_t iss = 0; // ISS - initial send sequence number
+ uint32_t irs = 0; // IRS - initial receive sequence number
+ uint16_t snd_up = 0; // SND.UP - send urgent pointer
+ uint16_t rcv_up = 0; // RCV.UP - receive urgent pointer
};
// <--- note -- the 'state' parameter must be a reference
{
};
-TEST(tcp_normalizers, os_policy)
+TEST(tcp_normalizers, norm_policy)
{
- StreamPolicy os_policy;
+ Normalizer::Policy norm_policy;
Flow* flow = new Flow;
TcpSession* session = new TcpSessionMock( flow );
TcpNormalizerState tns;
- for( os_policy = StreamPolicy::OS_FIRST; os_policy <= StreamPolicy::OS_PROXY; ++os_policy )
+ for( norm_policy = Normalizer::Policy::OS_FIRST; norm_policy < Normalizer::Policy::MAX_NORM_POLICY; ++norm_policy )
{
TcpNormalizer* normalizer = TcpNormalizerFactory::create(
- tns, os_policy, session, session->client, session->server);
+ tns, norm_policy, session, session->client, session->server);
- CHECK( normalizer.get_os_policy(tns) == os_policy );
+ CHECK( normalizer.get_norm_policy(tns) == norm_policy );
}
delete flow;
TEST(tcp_normalizers, paws_fudge_config)
{
- StreamPolicy os_policy;
+ Normalizer::Policy norm_policy;
Flow* flow = new Flow;
TcpSession* session = new TcpSessionMock( flow );
TcpNormalizerState tns;
- for( os_policy = StreamPolicy::OS_FIRST; os_policy <= StreamPolicy::OS_PROXY; ++os_policy )
+ for( norm_policy = Normalizer::Policy::OS_FIRST; norm_policy < Normalizer::Policy::MAX_NORM_POLICY; ++norm_policy )
{
TcpNormalizer* normalizer = TcpNormalizerFactory::create(
- tns, os_policy, session, session->client, session->server);
+ tns, norm_policy, session, session->client, session->server);
- switch ( os_policy )
+ switch ( norm_policy )
{
- case StreamPolicy::OS_LINUX:
+ case Normalizer::Policy::LINUX:
CHECK( normalizer.get_paws_ts_fudge(tns) == 1 );
break;
TEST(tcp_normalizers, paws_drop_zero_ts_config)
{
- StreamPolicy os_policy;
+ Normalizer::Policy norm_policy;
Flow* flow = new Flow;
TcpSession* session = new TcpSessionMock( flow );
TcpNormalizerState tns;
- for( os_policy = StreamPolicy::OS_FIRST; os_policy <= StreamPolicy::OS_PROXY; ++os_policy )
+ for( norm_policy = Normalizer::Policy::OS_FIRST; norm_policy < Normalizer::Policy::MAX_NORM_POLICY; ++norm_policy )
{
TcpNormalizer* normalizer = TcpNormalizerFactory::create(
- tns, os_policy, session, session->client, session->server );
+ tns, norm_policy, session, session->client, session->server );
- switch ( os_policy )
+ switch ( norm_policy )
{
- case StreamPolicy::OS_OLD_LINUX:
- case StreamPolicy::OS_SOLARIS:
- case StreamPolicy::OS_WINDOWS:
- case StreamPolicy::OS_WINDOWS2K3:
- case StreamPolicy::OS_VISTA:
+ case Normalizer::Policy::OLD_LINUX:
+ case Normalizer::Policy::SOLARIS:
+ case Normalizer::Policy::WINDOWS:
+ case Normalizer::Policy::WINDOWS2K3:
+ case Normalizer::Policy::VISTA:
CHECK( !normalizer.is_paws_drop_zero_ts(tns) );
break;
TEST(tcp_normalizers, norm_options_enabled)
{
- StreamPolicy os_policy;
+ Normalizer::Policy norm_policy;
Flow* flow = new Flow;
TcpSession* session = new TcpSessionMock( flow );
norm_enabled = true;
- for( os_policy = StreamPolicy::OS_FIRST; os_policy <= StreamPolicy::OS_PROXY; ++os_policy )
+ for( norm_policy = Normalizer::Policy::OS_FIRST; norm_policy < Normalizer::Policy::MAX_NORM_POLICY; ++norm_policy )
{
TcpNormalizerState tns;
TcpNormalizer* normalizer = TcpNormalizerFactory::create(
- tns, os_policy, session, session->client, session->server);
+ tns, norm_policy, session, session->client, session->server);
CHECK( normalizer.get_opt_block(tns) == NORM_MODE_ON );
CHECK( normalizer.get_strip_ecn(tns) == NORM_MODE_ON );
}
norm_enabled = false;
- for( os_policy = StreamPolicy::OS_FIRST; os_policy <= StreamPolicy::OS_PROXY; ++os_policy )
+ for( norm_policy = Normalizer::Policy::OS_FIRST; norm_policy < Normalizer::Policy::MAX_NORM_POLICY; ++norm_policy )
{
TcpNormalizerState tns;
TcpNormalizer* normalizer = TcpNormalizerFactory::create(
- tns, os_policy, session, session->client, session->server);
+ tns, norm_policy, session, session->client, session->server);
CHECK( normalizer.get_opt_block(tns) == NORM_MODE_TEST );
CHECK( normalizer.get_strip_ecn(tns) == NORM_MODE_TEST );