#include "protocols/tcp.h"
#include "protocols/tcp_options.h"
#include "sfip/sf_ipvar.h"
+#include "stream/stream.h"
#include "utils/util.h"
#include "checksum.h"
//-------------------------------------------------------------------------
bool TcpCodec::encode(const uint8_t* const raw_in, const uint16_t /*raw_len*/,
- EncState& enc, Buffer& buf, Flow*)
+ EncState& enc, Buffer& buf, Flow* flow)
{
const tcp::TCPHdr* const hi = reinterpret_cast<const tcp::TCPHdr*>(raw_in);
// th_seq depends on whether the data passes or drops
if (enc.flags & ENC_FLAG_INLINE)
- tcph_out->th_seq = hi->th_seq;
+ {
+ uint32_t seq = 0;
+
+ if(Stream::get_held_pkt_seq(flow, seq))
+ tcph_out->th_seq = htonl(seq);
+ else
+ tcph_out->th_seq = hi->th_seq;
+ }
else
tcph_out->th_seq = htonl(ntohl(hi->th_seq) + enc.dsize + ctl);
*/
bool FTPDataDirection(Packet* p, FTP_DATA_SESSION* ftpdata)
{
- uint32_t direction;
- uint32_t pktdir = Stream::get_packet_direction(p);
+ Stream::get_packet_direction(p);
if (ftpdata->mode == FTPP_XFER_ACTIVE)
- direction = ftpdata->direction ? PKT_FROM_SERVER : PKT_FROM_CLIENT;
+ {
+ // download
+ if (!p->is_from_application_client() && p->is_from_client())
+ return true;
+
+ // upload
+ if (p->is_from_application_client() && !p->is_from_client())
+ return true;
+ }
else
- direction = ftpdata->direction ? PKT_FROM_CLIENT : PKT_FROM_SERVER;
+ {
+ // download
+ if (!p->is_from_client() && !p->is_from_application_client())
+ return true;
+
+ // upload
+ if (p->is_from_client() && p->is_from_application_client())
+ return true;
+ }
- return (pktdir == direction);
+ return false;
}
/*
}
}
+bool Stream::get_held_pkt_seq(Flow* flow, uint32_t& seq)
+{
+ if (!flow or !flow->session or !(flow->pkt_type == PktType::TCP))
+ return false;
+
+ TcpStreamSession* tcp_session = (TcpStreamSession*)flow->session;
+
+ if (tcp_session->held_packet_dir == SSN_DIR_NONE)
+ return false;
+
+ if (tcp_session->held_packet_dir == SSN_DIR_FROM_CLIENT)
+ {
+ seq = tcp_session->server.held_pkt_seq;
+ tcp_session->held_packet_dir = SSN_DIR_NONE;
+ return true;
+ }
+
+ if (tcp_session->held_packet_dir == SSN_DIR_FROM_SERVER)
+ {
+ seq = tcp_session->client.held_pkt_seq;
+ tcp_session->held_packet_dir = SSN_DIR_NONE;
+ return true;
+ }
+
+ return false;
+}
+
#ifdef UNIT_TEST
#include "catch/snort_catch.h"
static void set_no_ack_mode(Flow*, bool);
static void partial_flush(Flow*, bool to_server);
+ static bool get_held_pkt_seq(Flow*, uint32_t&);
+
private:
static void set_ip_protocol(Flow*);
};
bool TcpStreamSession::set_packet_action_to_hold(Packet* p)
{
if ( p->is_from_client() )
+ {
+ held_packet_dir = SSN_DIR_FROM_CLIENT;
return server.set_held_packet(p);
+ }
else
+ {
+ held_packet_dir = SSN_DIR_FROM_SERVER;
return client.set_held_packet(p);
+ }
}
void TcpStreamSession::set_packet_header_foo(const TcpSegmentDescriptor& tsd)
TcpStreamConfig* tcp_config = nullptr;
TcpEventLogger tel;
bool cleaning = false;
+ uint8_t held_packet_dir = SSN_DIR_NONE;
private:
bool no_ack = false;
memory::MemoryCap::update_allocations(daq_msg_get_data_len(p->daq_msg));
held_packet = hpq->append(p->daq_msg, p->ptrs.tcph->seq(), *this);
+ held_pkt_seq = p->ptrs.tcph->seq();
tcpStats.total_packets_held++;
if ( ++tcpStats.current_packets_held > tcpStats.max_packets_held )
Analyzer::get_local_analyzer()->finalize_daq_message(msg, DAQ_VERDICT_PASS);
tcpStats.held_packets_passed++;
}
+
+ TcpStreamSession* tcp_session = (TcpStreamSession*)cp->flow->session;
+ tcp_session->held_packet_dir = SSN_DIR_NONE;
}
memory::MemoryCap::update_deallocations(msglen);
}
else
{
+ TcpStreamSession* tcp_session = (TcpStreamSession*)flow->session;
+ tcp_session->held_packet_dir = SSN_DIR_NONE;
Analyzer::get_local_analyzer()->finalize_daq_message(msg, DAQ_VERDICT_PASS);
tcpStats.held_packets_passed++;
}
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;