* `duration` - connection duration in seconds
* `proto` - transport layer protocol of the connection
* `service` - connection's application protocol
-* `orig_pkts` - number of packets originator sent
-* `resp_pkts` - number of packets responder sent
+* `orig_pkts` - number of packets client sent
+* `resp_pkts` - number of packets server sent
+* `orig_bytes` - tcp/udp payload bytes client sent
+* `resp_bytes` - tcp/udp payload bytes server sent
+
+For TCP orig_bytes and resp_bytes are calculated using first seen sequence number and next expected sequence number.
+These are reset during TCP flow restart. For this case only bytes seen following the restart will be reported.
==== Example
#include "profiler/profiler.h"
#include "pub_sub/intrinsic_event_ids.h"
#include "sfip/sf_ip.h"
+#include "stream/tcp/tcp_session.h"
+#include "stream/udp/udp_session.h"
#include "utils/util.h"
#include "utils/util_net.h"
return f->last_data_seen - f->flowstats.start_time.tv_sec;
}
+static uint64_t get_orig_bytes_tcp(const TcpSession* tcpssn)
+{
+ uint32_t client_bytes = tcpssn->client.get_snd_nxt() - tcpssn->client.get_iss();
+ // get_snd_nxt is the next expected sequence number (last seen + 1)
+ if (client_bytes != 0)
+ client_bytes -= 1;
+ return client_bytes;
+}
+
+static uint64_t get_orig_bytes(const DataEvent*, const Flow* f)
+{
+ if (f->session == nullptr)
+ return 0;
+ if (f->pkt_type == PktType::TCP)
+ return get_orig_bytes_tcp((const TcpSession*)f->session);
+ else if (f->pkt_type == PktType::UDP)
+ return ((UdpSession*)(f->session))->payload_bytes_seen_client;
+
+ return 0;
+}
+
+static uint64_t get_resp_bytes_tcp(const TcpSession* tcpssn)
+{
+ uint32_t server_bytes = tcpssn->server.get_snd_nxt() - tcpssn->server.get_iss();
+ if (server_bytes != 0)
+ server_bytes -= 1;
+ return server_bytes;
+}
+
+static uint64_t get_resp_bytes(const DataEvent*, const Flow* f)
+{
+ if (f->session == nullptr)
+ return 0;
+
+ if (f->pkt_type == PktType::TCP)
+ return get_resp_bytes_tcp((const TcpSession*)f->session);
+ else if (f->pkt_type == PktType::UDP)
+ return ((UdpSession*)(f->session))->payload_bytes_seen_server;
+
+ return 0;
+}
+
static const map<string, ExtractorEvent::NumGetFn> sub_num_getters =
{
{"orig_pkts", get_orig_pkts},
{"resp_pkts", get_resp_pkts},
- {"duration", get_duration}
+ {"duration", get_duration},
+ {"orig_bytes", get_orig_bytes},
+ {"resp_bytes", get_resp_bytes}
};
static const char* get_service(const DataEvent*, const Flow* f)
delete flow;
}
+TEST_CASE("Conn payload bytes", "[extractor]")
+{
+ Flow* flow = new Flow;
+ InspectionPolicy ins;
+ set_inspection_policy(&ins);
+ NetworkPolicy net;
+ set_network_policy(&net);
+
+ SECTION("no session")
+ {
+ uint64_t bytes = get_orig_bytes(nullptr, flow);
+ CHECK(bytes == 0);
+ bytes = get_resp_bytes(nullptr, flow);
+ CHECK(bytes == 0);
+ }
+
+ delete flow;
+}
+
#endif
"service",
"orig_pkts",
"resp_pkts",
- "duration"
+ "duration",
+ "orig_bytes",
+ "resp_bytes"
},
};
}
static const SfIp& get_ip_src(const DataEvent*, const Flow* flow)
- { return flow->flags.client_initiated ? flow->client_ip : flow->server_ip; }
+ { return flow->client_ip; }
static const SfIp& get_ip_dst(const DataEvent*, const Flow* flow)
- { return flow->flags.client_initiated ? flow->server_ip : flow->client_ip; }
+ { return flow->server_ip; }
static uint64_t get_ip_src_port(const DataEvent*, const Flow* flow)
{ return flow->client_port; }
udpStats.released++;
}
-static int ProcessUdp(Flow* lwssn, Packet* p, StreamUdpConfig*)
-{
- assert(lwssn->pkt_type == PktType::UDP);
-
- if ( Stream::blocked_flow(p) )
- return 0;
-
- if ( Stream::ignored_flow(lwssn, p) )
- {
- udpStats.ignored++;
- return 0;
- }
- udpStats.total_bytes += p->dsize;
- /* if both seen, mark established */
- if (p->is_from_server())
- {
- lwssn->ssn_state.session_flags |= SSNFLAG_SEEN_RESPONDER;
- lwssn->set_ttl(p, false);
- }
- else
- {
- lwssn->ssn_state.session_flags |= SSNFLAG_SEEN_SENDER;
- lwssn->set_ttl(p, true);
- }
-
- if (!(lwssn->ssn_state.session_flags & SSNFLAG_ESTABLISHED))
- {
- if ((lwssn->ssn_state.session_flags & SSNFLAG_SEEN_SENDER) &&
- (lwssn->ssn_state.session_flags & SSNFLAG_SEEN_RESPONDER))
- {
- lwssn->ssn_state.session_flags |= SSNFLAG_ESTABLISHED;
- DataBus::publish(Stream::get_pub_id(), StreamEventIds::UDP_BIDIRECTIONAL, p);
- }
- }
-
- if ( lwssn->clouseau )
- lwssn->clouseau->eval(p);
-
- return 0;
-}
-
//-------------------------------------------------------------------------
// UdpSession methods
//-------------------------------------------------------------------------
flow->swap_roles();
}
+int UdpSession::process_udp(Flow* lwssn, Packet* p)
+{
+ assert(lwssn->pkt_type == PktType::UDP);
+
+ if ( Stream::blocked_flow(p) )
+ return 0;
+
+ if ( Stream::ignored_flow(lwssn, p) )
+ {
+ udpStats.ignored++;
+ return 0;
+ }
+ udpStats.total_bytes += p->dsize;
+ /* if both seen, mark established */
+ if (p->is_from_server())
+ {
+ lwssn->ssn_state.session_flags |= SSNFLAG_SEEN_RESPONDER;
+ lwssn->set_ttl(p, false);
+ payload_bytes_seen_server += p->dsize;
+ }
+ else
+ {
+ lwssn->ssn_state.session_flags |= SSNFLAG_SEEN_SENDER;
+ lwssn->set_ttl(p, true);
+ payload_bytes_seen_client += p->dsize;
+ }
+
+ if (!(lwssn->ssn_state.session_flags & SSNFLAG_ESTABLISHED))
+ {
+ if ((lwssn->ssn_state.session_flags & SSNFLAG_SEEN_SENDER) &&
+ (lwssn->ssn_state.session_flags & SSNFLAG_SEEN_RESPONDER))
+ {
+ lwssn->ssn_state.session_flags |= SSNFLAG_ESTABLISHED;
+ DataBus::publish(Stream::get_pub_id(), StreamEventIds::UDP_BIDIRECTIONAL, p);
+ }
+ }
+
+ if ( lwssn->clouseau )
+ lwssn->clouseau->eval(p);
+
+ return 0;
+}
+
int UdpSession::process(Packet* p)
{
Profile profile(udp_perf_stats); // cppcheck-suppress unreadVariable
- StreamUdpConfig* pc = get_udp_cfg(flow->ssn_server);
// Check if the session is expired.
// Should be done before we do something with the packet...
if ( Stream::expired_flow(flow, p) )
UdpHAManager::process_deletion(*flow);
}
- ProcessUdp(flow, p, pc);
+ process_udp(flow, p);
flow->markup_packet_flags(p);
flow->set_expire(p, flow->default_session_timeout);
public:
struct timeval ssn_time = {};
+ uint64_t payload_bytes_seen_client = 0;
+ uint64_t payload_bytes_seen_server = 0;
+
+private:
+ int process_udp(snort::Flow*, snort::Packet*);
};
#endif