Go to the documentation of this file.
75 static inline int FlowHashRawAddressIPv6GtU32(
const uint32_t *a,
const uint32_t *b)
77 for (uint8_t i = 0; i < 4; i++) {
98 const uint32_t
u32[6];
120 if (PacketIsIPv4(p)) {
125 int ai = (p->
src.addr_data32[0] > p->
dst.addr_data32[0]);
126 fhk.
addrs[1 - ai] = p->
src.addr_data32[0];
127 fhk.
addrs[ai] = p->
dst.addr_data32[0];
129 fhk.
ports[0] = 0xfedc;
130 fhk.
ports[1] = 0xba98;
141 }
else if (PacketIsIPv6(p)) {
145 if (FlowHashRawAddressIPv6GtU32(p->
src.addr_data32, p->
dst.addr_data32)) {
146 fhk.
src[0] = p->
src.addr_data32[0];
147 fhk.
src[1] = p->
src.addr_data32[1];
148 fhk.
src[2] = p->
src.addr_data32[2];
149 fhk.
src[3] = p->
src.addr_data32[3];
150 fhk.
dst[0] = p->
dst.addr_data32[0];
151 fhk.
dst[1] = p->
dst.addr_data32[1];
152 fhk.
dst[2] = p->
dst.addr_data32[2];
153 fhk.
dst[3] = p->
dst.addr_data32[3];
155 fhk.
src[0] = p->
dst.addr_data32[0];
156 fhk.
src[1] = p->
dst.addr_data32[1];
157 fhk.
src[2] = p->
dst.addr_data32[2];
158 fhk.
src[3] = p->
dst.addr_data32[3];
159 fhk.
dst[0] = p->
src.addr_data32[0];
160 fhk.
dst[1] = p->
src.addr_data32[1];
161 fhk.
dst[2] = p->
src.addr_data32[2];
162 fhk.
dst[3] = p->
src.addr_data32[3];
165 fhk.
ports[0] = 0xfedc;
166 fhk.
ports[1] = 0xba98;
191 static inline uint32_t FlowGetHash(
const Packet *p)
195 if (PacketIsIPv4(p)) {
196 if (PacketIsTCP(p) || PacketIsUDP(p)) {
199 int ai = (p->
src.addr_data32[0] > p->
dst.addr_data32[0]);
200 fhk.
addrs[1-ai] = p->
src.addr_data32[0];
201 fhk.
addrs[ai] = p->
dst.addr_data32[0];
203 const int pi = (p->
sp > p->
dp);
226 const int ai = (psrc > pdst);
227 fhk.
addrs[1-ai] = psrc;
228 fhk.
addrs[ai] = pdst;
246 const int ai = (p->
src.addr_data32[0] > p->
dst.addr_data32[0]);
247 fhk.
addrs[1-ai] = p->
src.addr_data32[0];
248 fhk.
addrs[ai] = p->
dst.addr_data32[0];
249 fhk.
ports[0] = 0xfeed;
250 fhk.
ports[1] = 0xbeef;
261 }
else if (PacketIsIPv6(p)) {
263 if (FlowHashRawAddressIPv6GtU32(p->
src.addr_data32, p->
dst.addr_data32)) {
264 fhk.
src[0] = p->
src.addr_data32[0];
265 fhk.
src[1] = p->
src.addr_data32[1];
266 fhk.
src[2] = p->
src.addr_data32[2];
267 fhk.
src[3] = p->
src.addr_data32[3];
268 fhk.
dst[0] = p->
dst.addr_data32[0];
269 fhk.
dst[1] = p->
dst.addr_data32[1];
270 fhk.
dst[2] = p->
dst.addr_data32[2];
271 fhk.
dst[3] = p->
dst.addr_data32[3];
273 fhk.
src[0] = p->
dst.addr_data32[0];
274 fhk.
src[1] = p->
dst.addr_data32[1];
275 fhk.
src[2] = p->
dst.addr_data32[2];
276 fhk.
src[3] = p->
dst.addr_data32[3];
277 fhk.
dst[0] = p->
src.addr_data32[0];
278 fhk.
dst[1] = p->
src.addr_data32[1];
279 fhk.
dst[2] = p->
src.addr_data32[2];
280 fhk.
dst[3] = p->
src.addr_data32[3];
283 const int pi = (p->
sp > p->
dp);
320 const int pi = (fk->
sp > fk->
dp);
357 const int pi = (fk->
sp > fk->
dp);
372 static inline bool CmpAddrs(
const uint32_t addr1[4],
const uint32_t addr2[4])
374 return addr1[0] == addr2[0] && addr1[1] == addr2[1] &&
375 addr1[2] == addr2[2] && addr1[3] == addr2[3];
378 static inline bool CmpAddrsAndPorts(
const uint32_t src1[4],
379 const uint32_t dst1[4],
Port src_port1,
Port dst_port1,
380 const uint32_t src2[4],
const uint32_t dst2[4],
Port src_port2,
386 return (CmpAddrs(src1, src2) && CmpAddrs(dst1, dst2) &&
387 src_port1 == src_port2 && dst_port1 == dst_port2) ||
388 (CmpAddrs(src1, dst2) && CmpAddrs(dst1, src2) &&
389 src_port1 == dst_port2 && dst_port1 == src_port2);
392 static inline bool CmpVlanIds(
395 return ((vlan_id1[0] ^ vlan_id2[0]) &
g_vlan_mask) == 0 &&
396 ((vlan_id1[1] ^ vlan_id2[1]) &
g_vlan_mask) == 0 &&
400 static inline bool CmpLiveDevIds(
const LiveDevice *livedev,
const uint16_t
id)
402 uint16_t devid = livedev ? livedev->
id : 0;
408 static inline bool CmpFlowPacket(
const Flow *f,
const Packet *p)
414 return CmpAddrsAndPorts(f_src, f_dst, f->
sp, f->
dp, p_src, p_dst, p->
sp, p->
dp) &&
419 static inline bool CmpFlowKey(
const Flow *f,
const FlowKey *k)
425 return CmpAddrsAndPorts(f_src, f_dst, f->
sp, f->
dp, k_src, k_dst, k->
sp, k->
dp) &&
430 static inline bool CmpAddrsAndICMPTypes(
const uint32_t src1[4],
431 const uint32_t dst1[4], uint8_t icmp_s_type1, uint8_t icmp_d_type1,
432 const uint32_t src2[4],
const uint32_t dst2[4], uint8_t icmp_s_type2,
433 uint8_t icmp_d_type2)
438 return (CmpAddrs(src1, src2) && CmpAddrs(dst1, dst2) &&
439 icmp_s_type1 == icmp_s_type2 && icmp_d_type1 == icmp_d_type2) ||
440 (CmpAddrs(src1, dst2) && CmpAddrs(dst1, src2) &&
441 icmp_s_type1 == icmp_d_type2 && icmp_d_type1 == icmp_s_type2);
444 static inline bool CmpFlowICMPPacket(
const Flow *f,
const Packet *p)
450 return CmpAddrsAndICMPTypes(f_src, f_dst, f->
icmp_s.type, f->
icmp_d.type, p_src, p_dst,
466 static inline int FlowCompareICMPv4(
Flow *f,
const Packet *p)
494 return CmpFlowICMPPacket(f, p);
509 static inline int FlowCompareESP(
Flow *f,
const Packet *p)
516 return CmpAddrs(f_src, p_src) && CmpAddrs(f_dst, p_dst) && f->
proto == p->
proto &&
528 static inline int FlowCompare(
Flow *f,
const Packet *p)
530 if (p->
proto == IPPROTO_ICMP) {
531 return FlowCompareICMPv4(f, p);
532 }
else if (PacketIsESP(p)) {
533 return FlowCompareESP(f, p);
535 return CmpFlowPacket(f, p);
549 static inline bool FlowCreateCheck(
const Packet *p,
const bool emerg)
554 if (PacketIsTCP(p)) {
555 const TCPHdr *tcph = PacketGetTCP(p);
565 if (PacketIsICMPv4(p)) {
607 const Packet *p,
const bool emerg)
610 bool spare_sync =
false;
627 if (
tv && fls->
dtv) {
646 static void FlowExceptionPolicyStatsIncr(
682 if (g_eps_flow_memcap != UINT64_MAX && g_eps_flow_memcap == p->
pcap_cnt) {
683 NoFlowHandleIPS(
tv, fls, p);
688 if (!FlowCreateCheck(p, emerg)) {
695 f = FlowSpareSync(
tv, fls, p, emerg);
707 f = FlowGetUsedFlow(
tv, fls->
dtv, p->
ts);
709 NoFlowHandleIPS(
tv, fls, p);
711 if (
tv != NULL && fls->
dtv != NULL) {
720 if (
tv != NULL && fls->
dtv != NULL) {
735 if (
tv != NULL && fls->
dtv != NULL) {
741 NoFlowHandleIPS(
tv, fls, p);
758 const uint32_t hash,
Packet *p)
761 if (
tv != NULL && fls->
dtv != NULL) {
775 Flow *f = FlowGetNew(
tv, fls, p);
808 FlowBucket *fb,
Flow *f,
Flow *prev_f)
820 if (f->
proto != IPPROTO_TCP || FlowBelongsToUs(
tv, f)) {
827 f->
next = fb->evicted;
835 static inline bool FlowIsTimedOut(
const Flow *f,
const uint32_t sec,
const bool emerg)
844 if ((int64_t)sec >= timeout_at)
876 SCLogDebug(
"fb %p fb->head %p", fb, fb->head);
879 if (fb->head == NULL) {
880 f = FlowGetNew(
tv, fls, p);
895 FlowReference(dest, f);
902 const uint32_t fb_nextts = !emerg ?
SC_ATOMIC_GET(fb->next_ts) : 0;
908 const bool timedout = (fb_nextts < (uint32_t)
SCTIME_SECS(p->
ts) &&
913 MoveToWorkQueue(
tv, fls, fb, f, prev_f);
916 }
else if (FlowCompare(f, p) != 0) {
920 Flow *new_f = TcpReuseReplace(
tv, fls, fb, f, hash, p);
923 MoveToWorkQueue(
tv, fls, fb, f, prev_f);
932 FlowReference(dest, f);
942 if (next_f == NULL) {
943 f = FlowGetNew(
tv, fls, p);
959 FlowReference(dest, f);
976 static inline bool FlowCompareKey(
Flow *f,
FlowKey *key)
978 if ((f->
proto != IPPROTO_TCP) && (f->
proto != IPPROTO_UDP))
980 return CmpFlowKey(f, key);
994 uint32_t hash = flow_id & 0x0000FFFF;
997 SCLogDebug(
"fb %p fb->head %p", fb, fb->head);
999 for (
Flow *f = fb->head; f != NULL; f = f->
next) {
1000 if (FlowGetId(f) == flow_id) {
1021 static Flow *FlowGetExistingFlowFromHash(
FlowKey *key,
const uint32_t hash)
1026 SCLogDebug(
"fb %p fb->head %p", fb, fb->head);
1028 for (
Flow *f = fb->head; f != NULL; f = f->
next) {
1030 if (FlowCompareKey(f, key)) {
1058 Flow *f = FlowGetExistingFlowFromHash(key, hash);
1067 SCLogDebug(
"Can't get a spare flow at start");
1073 f->
src.addr_data32[0] = key->
src.addr_data32[0];
1074 f->
src.addr_data32[1] = key->
src.addr_data32[1];
1075 f->
src.addr_data32[2] = key->
src.addr_data32[2];
1076 f->
src.addr_data32[3] = key->
src.addr_data32[3];
1077 f->
dst.addr_data32[0] = key->
dst.addr_data32[0];
1078 f->
dst.addr_data32[1] = key->
dst.addr_data32[1];
1079 f->
dst.addr_data32[2] = key->
dst.addr_data32[2];
1080 f->
dst.addr_data32[3] = key->
dst.addr_data32[3];
1088 }
else if (key->
src.
family == AF_INET6) {
1107 #define FLOW_GET_NEW_TRIES 5
1111 static inline int GetUsedTryLockBucket(FlowBucket *fb)
1116 static inline int GetUsedTryLockFlow(
Flow *f)
1121 static inline uint32_t GetUsedAtomicUpdate(
const uint32_t val)
1158 #define STATSADDUI64(cnt, value) \
1160 StatsAddUI64(tv, dtv->cnt, (value)); \
1163 #define STATSADDUI64(cnt, value) \
1164 StatsAddUI64(tv, dtv->cnt, (value));
1200 if (GetUsedTryLockBucket(fb) != 0) {
1211 if (GetUsedTryLockFlow(f) != 0) {
1217 if (StillAlive(f,
ts)) {
#define ESP_GET_SPI(esph)
Get the spi field off a packet.
FlowQueuePrivate work_queue
TmEcode OutputFlowLog(ThreadVars *tv, void *thread_data, Flow *f)
Run flow logger(s)
uint16_t counter_flow_udp
void ExceptionPolicyApply(Packet *p, enum ExceptionPolicy policy, enum PacketDropReason drop_reason)
uint16_t counter_flow_active
#define ICMPV4_GET_EMB_PROTO(p)
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
#define IPV4_GET_RAW_IPDST_U32(ip4h)
uint32_t hashword(const uint32_t *k, size_t length, uint32_t initval)
uint16_t counter_flow_icmp4
bool TcpSessionPacketSsnReuse(const Packet *p, const Flow *f, const void *tcp_ssn)
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
@ PKT_DROP_REASON_FLOW_MEMCAP
uint32_t address_un_data32[4]
FlowQueuePrivate FlowSpareGetFromPool(void)
uint16_t counter_flow_spare_sync_avg
uint32_t FlowKeyGetHash(FlowKey *fk)
#define ICMPV4_DEST_UNREACH_IS_VALID(p)
uint16_t vlan_id[VLAN_MAX_LAYERS]
union Address_::@26 address
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
#define FLOWLOCK_TRYWRLOCK(fb)
struct FlowHashKey4_ FlowHashKey4
#define FBLOCK_TRYLOCK(fb)
struct Flow_::@116::@122 icmp_d
uint16_t counter_flow_tcp
struct Packet_::@29::@36 icmp_s
uint32_t address_un_data32[4]
struct Packet_::@31::@37 icmp_d
TcpStreamCnf stream_config
struct Flow_::@114::@120 icmp_s
uint16_t counter_flow_get_used
#define FLOWLOCK_UNLOCK(fb)
uint16_t counter_flow_spare_sync_empty
uint16_t counter_flow_tcp_reuse
uint16_t counter_flow_total
void FlowWakeupFlowManagerThread(void)
#define FLOW_CHECK_MEMCAP(size)
check if a memory alloc would fit in the memcap
uint32_t emerg_spare_sync_stamp
uint16_t counter_flow_spare_sync
struct Flow_::@114::@121 esp
#define STREAM_PKT_FLAG_TCP_PORT_REUSE
void SCFlowRunFinishCallbacks(ThreadVars *tv, Flow *f)
#define FLOW_GET_NEW_TRIES
#define STATSADDUI64(cnt, value)
#define SCTIME_FROM_TIMESPEC(ts)
#define FLOWLOCK_WRLOCK(fb)
SC_ATOMIC_EXTERN(unsigned int, flow_prune_idx)
uint16_t eps_id[EXCEPTION_POLICY_MAX]
Per thread variable structure.
unsigned int FlowStorageSize(void)
struct FlowHashKey6_ FlowHashKey6
Flow * FlowQueuePrivateGetFromTop(FlowQueuePrivate *fqc)
void FlowTimeoutsEmergency(void)
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Flow * FlowGetExistingFlowFromFlowId(int64_t flow_id)
Look for existing Flow using a flow id value.
#define FLOW_END_FLAG_EMERGENCY
#define FBLOCK_UNLOCK(fb)
struct LiveDevice_ * livedev
int FlowClearMemory(Flow *f, uint8_t proto_map)
Function clear the flow memory before queueing it to spare flow queue.
FlowProtoTimeout flow_timeouts_delta[FLOW_PROTO_MAX]
Data structures and function prototypes for keeping state for the detection engine.
int RunmodeIsUnittests(void)
void FlowUpdateState(Flow *f, const enum FlowState s)
FlowQueuePrivate spare_queue
uint32_t FlowGetIpPairProtoHash(const Packet *p)
uint16_t counter_flow_spare_sync_incomplete
#define IPV4_GET_RAW_IPSRC_U32(ip4h)
uint16_t counter_flow_icmp6
ExceptionPolicyCounters counter_flow_memcap_eps
Flow * FlowGetFlowFromHash(ThreadVars *tv, FlowLookupStruct *fls, Packet *p, Flow **dest)
Get Flow for packet.
struct LiveDevice_ * livedev
enum ExceptionPolicy memcap_policy
void StatsAddUI64(ThreadVars *tv, uint16_t id, uint64_t x)
Adds a value of type uint64_t to the local counter.
Structure to hold thread specific data for all decode modules.
Flow * FlowGetFromFlowKey(FlowKey *key, struct timespec *ttime, const uint32_t hash)
Get or create a Flow using a FlowKey.
void * output_flow_thread_data
void FlowInit(ThreadVars *tv, Flow *f, const Packet *p)
uint16_t vlan_id[VLAN_MAX_LAYERS]
#define STREAM_PKT_FLAG_SET(p, f)
uint16_t vlan_id[VLAN_MAX_LAYERS]
uint16_t counter_flow_memcap
#define FLOW_END_FLAG_TIMEOUT
uint16_t vlan_id[VLAN_MAX_LAYERS]
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
uint16_t vlan_id[VLAN_MAX_LAYERS]
void FlowQueuePrivateAppendFlow(FlowQueuePrivate *fqc, Flow *f)
Flow * FlowAlloc(void)
allocate a flow
#define FLOW_END_FLAG_FORCED
#define ICMPV4_IS_ERROR_MSG(type)
void FlowSetupPacket(Packet *p)
prepare packet for a life with flow Set PKT_WANTS_FLOW flag to indicate workers should do a flow look...
union FlowAddress_::@113 address
union PacketL4::L4Vars vars
FlowThreadId thread_id[2]
#define SC_ATOMIC_OR(name, val)
Bitwise OR a value to our atomic variable.