service = new_service;
DataBus::publish(FLOW_SERVICE_CHANGE_EVENT, pkt);
}
+
+void Flow::swap_roles()
+{
+ client_initiated = !client_initiated;
+ std::swap(client_ip, server_ip);
+ std::swap(client_port, server_port);
+ std::swap(flowstats.client_pkts, flowstats.server_pkts);
+ std::swap(flowstats.client_bytes, flowstats.server_bytes);
+}
unsigned id;
};
+struct FlowStats
+{
+ uint64_t client_pkts;
+ uint64_t server_pkts;
+ uint64_t client_bytes;
+ uint64_t server_bytes;
+ struct timeval start_time;
+};
+
struct LwState
{
uint32_t session_flags;
void set_ttl(Packet*, bool client);
void set_mpls_layer_per_dir(Packet*);
Layer get_mpls_layer_per_dir(bool);
+ void swap_roles();
void set_service(Packet* pkt, const char* new_service);
bool get_attr(const std::string& key, int32_t& val);
bool get_attr(const std::string& key, std::string& val);
// everything from here down is zeroed
IpsContextChain context_chain;
FlowData* flow_data;
+ FlowStats flowstats;
+
+ SfIp client_ip;
+ SfIp server_ip;
+
+ LwState ssn_state;
+ LwState previous_ssn_state;
+
Inspector* clouseau; // service identifier
Inspector* gadget; // service handler
Inspector* assistant_gadget;
uint64_t expire_time;
- SfIp client_ip;
- SfIp server_ip;
+ DeferredWhitelist deferred_whitelist = WHITELIST_DEFER_OFF;
- LwState ssn_state;
- LwState previous_ssn_state;
- FlowState flow_state;
unsigned inspection_policy_id;
unsigned ips_policy_id;
unsigned network_policy_id;
bool disable_inspect;
bool trigger_finalize_event;
+ bool client_initiated;
- DeferredWhitelist deferred_whitelist = WHITELIST_DEFER_OFF;
+ FlowState flow_state;
private:
void clean();
flow->set_state(Flow::FlowState::ALLOW);
++news;
+ flow->flowstats.start_time = p->pkth->ts;
+ flow->client_initiated = p->is_from_client();
}
// This requires the packet direction to be set
break;
}
+ update_stats(flow, p);
return news;
}
+void FlowControl::update_stats(Flow* flow, Packet* p)
+{
+ if (p->is_from_client())
+ {
+ flow->flowstats.client_pkts++;
+ flow->flowstats.client_bytes += p->pktlen;
+ }
+ else
+ {
+ flow->flowstats.server_pkts++;
+ flow->flowstats.server_bytes += p->pktlen;
+ }
+}
+
//-------------------------------------------------------------------------
// expected
//-------------------------------------------------------------------------
void set_key(snort::FlowKey*, snort::Packet*);
unsigned process(snort::Flow*, snort::Packet*);
void preemptive_cleanup();
+ void update_stats(snort::Flow*, snort::Packet*);
private:
snort::InspectSsnFunc get_proto_session[to_utype(PktType::MAX)] = {};
TextLog_Putc(csv_log, '"');
}
+static void ff_client_bytes(const Args& a)
+{
+ if (a.pkt->flow)
+ TextLog_Print(csv_log, "%" PRIu64, a.pkt->flow->flowstats.client_bytes);
+}
+
+static void ff_client_pkts(const Args& a)
+{
+ if (a.pkt->flow)
+ TextLog_Print(csv_log, "%" PRIu64, a.pkt->flow->flowstats.client_pkts);
+}
+
static void ff_dir(const Args& a)
{
const char* dir;
TextLog_Print(csv_log, "0x%X", ntohs(eh->ether_type));
}
+static void ff_flowstart_time(const Args& a)
+{
+ if (a.pkt->flow)
+ TextLog_Print(csv_log, "%u", a.pkt->flow->flowstats.start_time.tv_sec);
+}
+
static void ff_gid(const Args& a)
{
TextLog_Print(csv_log, "%u", a.event.sig_info->gid);
TextLog_Print(csv_log, "%u", a.pkt->pkth->ts.tv_sec);
}
+static void ff_server_bytes(const Args& a)
+{
+ if (a.pkt->flow)
+ TextLog_Print(csv_log, "%" PRIu64, a.pkt->flow->flowstats.server_bytes);
+}
+
+static void ff_server_pkts(const Args& a)
+{
+ if (a.pkt->flow)
+ TextLog_Print(csv_log, "%" PRIu64, a.pkt->flow->flowstats.server_pkts);
+}
+
static void ff_service(const Args& a)
{
const char* svc = "unknown";
static const CsvFunc csv_func[] =
{
- ff_action, ff_class, ff_b64_data, ff_dir, ff_dst_addr, ff_dst_ap,
- ff_dst_port, ff_eth_dst, ff_eth_len, ff_eth_src, ff_eth_type, ff_gid,
- ff_icmp_code, ff_icmp_id, ff_icmp_seq, ff_icmp_type, ff_iface, ff_ip_id,
- ff_ip_len, ff_msg, ff_mpls, ff_pkt_gen, ff_pkt_len, ff_pkt_num, ff_priority,
- ff_proto, ff_rev, ff_rule, ff_seconds, ff_service, ff_sid, ff_src_addr, ff_src_ap,
- ff_src_port, ff_target, ff_tcp_ack, ff_tcp_flags, ff_tcp_len, ff_tcp_seq,
- ff_tcp_win, ff_timestamp, ff_tos, ff_ttl, ff_udp_len, ff_vlan
+ ff_action, ff_class, ff_b64_data, ff_client_bytes, ff_client_pkts, ff_dir,
+ ff_dst_addr, ff_dst_ap, ff_dst_port, ff_eth_dst, ff_eth_len, ff_eth_src,
+ ff_eth_type, ff_flowstart_time, ff_gid, ff_icmp_code, ff_icmp_id, ff_icmp_seq,
+ ff_icmp_type, ff_iface, ff_ip_id, ff_ip_len, ff_msg, ff_mpls, ff_pkt_gen, ff_pkt_len,
+ ff_pkt_num, ff_priority, ff_proto, ff_rev, ff_rule, ff_seconds, ff_server_bytes,
+ ff_server_pkts, ff_service, ff_sid, ff_src_addr, ff_src_ap, ff_src_port, ff_target,
+ ff_tcp_ack, ff_tcp_flags,ff_tcp_len, ff_tcp_seq, ff_tcp_win, ff_timestamp, ff_tos,
+ ff_ttl, ff_udp_len, ff_vlan
};
#define csv_range \
- "action | class | b64_data | dir | dst_addr | dst_ap | " \
- "dst_port | eth_dst | eth_len | eth_src | eth_type | gid | " \
- "icmp_code | icmp_id | icmp_seq | icmp_type | iface | ip_id | " \
- "ip_len | msg | mpls | pkt_gen | pkt_len | pkt_num | priority | " \
- "proto | rev | rule | seconds | service | sid | src_addr | src_ap | " \
- "src_port | target | tcp_ack | tcp_flags | tcp_len | tcp_seq | " \
- "tcp_win | timestamp | tos | ttl | udp_len | vlan"
+ "action | class | b64_data | client_bytes | client_pkts | dir | dst_addr | " \
+ "dst_ap | dst_port | eth_dst | eth_len | eth_src | eth_type | flowstart_time | "\
+ "gid | icmp_code | icmp_id | icmp_seq | icmp_type | iface | "\
+ "ip_id | ip_len | msg | mpls | pkt_gen | pkt_len | " \
+ "pkt_num | priority | proto | rev | rule | seconds | server_bytes | " \
+ "server_pkts | service | sid | src_addr | src_ap | src_port | target | " \
+ "tcp_ack | tcp_flags | tcp_len | tcp_seq | tcp_win | timestamp | " \
+ "tos | ttl | udp_len | vlan"
#define csv_deflt \
"timestamp pkt_num proto pkt_gen pkt_len dir src_ap dst_ap rule action"
return true;
}
+static bool ff_client_bytes(const Args& a)
+{
+ if (a.pkt->flow)
+ {
+ print_label(a, "client_bytes");
+ TextLog_Print(json_log, "%" PRIu64, a.pkt->flow->flowstats.client_bytes);
+ return true;
+ }
+ return false;
+}
+
+static bool ff_client_pkts(const Args& a)
+{
+ if (a.pkt->flow)
+ {
+ print_label(a, "client_pkts");
+ TextLog_Print(json_log, "%" PRIu64, a.pkt->flow->flowstats.client_pkts);
+ return true;
+ }
+ return false;
+}
+
static bool ff_dir(const Args& a)
{
const char* dir;
return true;
}
+static bool ff_flowstart_time(const Args& a)
+{
+ if (a.pkt->flow)
+ {
+ print_label(a, "flowstart_time");
+ TextLog_Print(json_log, "%u", a.pkt->flow->flowstats.start_time.tv_sec);
+ return true;
+ }
+ return false;
+}
+
static bool ff_gid(const Args& a)
{
print_label(a, "gid");
return true;
}
+static bool ff_server_bytes(const Args& a)
+{
+ if (a.pkt->flow)
+ {
+ print_label(a, "server_bytes");
+ TextLog_Print(json_log, "%" PRIu64, a.pkt->flow->flowstats.server_bytes);
+ return true;
+ }
+ return false;
+}
+
+static bool ff_server_pkts(const Args& a)
+{
+ if (a.pkt->flow)
+ {
+ print_label(a, "server_pkts");
+ TextLog_Print(json_log, "%" PRIu64, a.pkt->flow->flowstats.server_pkts);
+ return true;
+ }
+ return false;
+}
+
static bool ff_service(const Args& a)
{
const char* svc = "unknown";
static const JsonFunc json_func[] =
{
- ff_action, ff_class, ff_b64_data, ff_dir, ff_dst_addr, ff_dst_ap,
- ff_dst_port, ff_eth_dst, ff_eth_len, ff_eth_src, ff_eth_type, ff_gid,
- ff_icmp_code, ff_icmp_id, ff_icmp_seq, ff_icmp_type, ff_iface, ff_ip_id,
- ff_ip_len, ff_msg, ff_mpls, ff_pkt_gen, ff_pkt_len, ff_pkt_num, ff_priority,
- ff_proto, ff_rev, ff_rule, ff_seconds, ff_service, ff_sid, ff_src_addr, ff_src_ap,
- ff_src_port, ff_target, ff_tcp_ack, ff_tcp_flags, ff_tcp_len, ff_tcp_seq,
- ff_tcp_win, ff_timestamp, ff_tos, ff_ttl, ff_udp_len, ff_vlan
+ ff_action, ff_class, ff_b64_data, ff_client_bytes, ff_client_pkts, ff_dir,
+ ff_dst_addr, ff_dst_ap, ff_dst_port, ff_eth_dst, ff_eth_len, ff_eth_src, ff_eth_type,
+ ff_flowstart_time, ff_gid, ff_icmp_code, ff_icmp_id, ff_icmp_seq, ff_icmp_type,
+ ff_iface, ff_ip_id, ff_ip_len, ff_msg, ff_mpls, ff_pkt_gen, ff_pkt_len,
+ ff_pkt_num, ff_priority, ff_proto, ff_rev, ff_rule, ff_seconds, ff_server_bytes,
+ ff_server_pkts, ff_service, ff_sid, ff_src_addr, ff_src_ap, ff_src_port, ff_target,
+ ff_tcp_ack, ff_tcp_flags, ff_tcp_len, ff_tcp_seq, ff_tcp_win, ff_timestamp, ff_tos,
+ ff_ttl, ff_udp_len, ff_vlan
};
#define json_range \
- "action | class | b64_data | dir | dst_addr | dst_ap | " \
- "dst_port | eth_dst | eth_len | eth_src | eth_type | gid | " \
- "icmp_code | icmp_id | icmp_seq | icmp_type | iface | ip_id | " \
- "ip_len | msg | mpls | pkt_gen | pkt_len | pkt_num | priority | " \
- "proto | rev | rule | seconds | service | sid | src_addr | src_ap | " \
- "src_port | target | tcp_ack | tcp_flags | tcp_len | tcp_seq | " \
- "tcp_win | timestamp | tos | ttl | udp_len | vlan"
+ "action | class | b64_data | client_bytes | client_pkts | dir | dst_addr | dst_ap | " \
+ "dst_port | eth_dst | eth_len | eth_src | eth_type | flowstart_time | " \
+ "gid | icmp_code | icmp_id | icmp_seq | icmp_type | iface | ip_id | ip_len | " \
+ "msg | mpls | pkt_gen | pkt_len | pkt_num | priority | proto | rev | rule | " \
+ "seconds | server_bytes | server_pkts | service | sid | src_addr | src_ap | src_port | target | " \
+ "tcp_ack | tcp_flags | tcp_len | tcp_seq | tcp_win | timestamp | " \
+ "tos | ttl | udp_len | vlan"
#define json_deflt \
"timestamp pkt_num proto pkt_gen pkt_len dir src_ap dst_ap rule action"
void UdpSession::update_direction(
char dir, const SfIp* ip, uint16_t port)
{
- SfIp tmpIp;
- uint16_t tmpPort;
-
if (flow->client_ip.equals(*ip) && (flow->client_port == port))
{
if ((dir == SSN_DIR_FROM_CLIENT) && (flow->ssn_state.direction == FROM_CLIENT))
}
}
- // Swap them -- leave flow->ssn_state.direction the same
- tmpIp = flow->client_ip;
- tmpPort = flow->client_port;
- flow->client_ip = flow->server_ip;
- flow->client_port = flow->server_port;
- flow->server_ip = tmpIp;
- flow->server_port = tmpPort;
+ // Swap client/server ip, ports, and stats -- leave flow->ssn_state.direction the same
+ flow->swap_roles();
}
int UdpSession::process(Packet* p)
if ( (f->ssn_state.session_flags & SSNFLAG_CLIENT_SWAP) &&
!(f->ssn_state.session_flags & SSNFLAG_CLIENT_SWAPPED) )
{
- SfIp ip = f->client_ip;
- uint16_t port = f->client_port;
-
- f->client_ip = f->server_ip;
- f->server_ip = ip;
-
- f->client_port = f->server_port;
- f->server_port = port;
+ f->swap_roles();
if ( !f->two_way_traffic() )
{