suricata
flow-util.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2013 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  * Flow utility functions
24  */
25 
26 #include "suricata-common.h"
27 #include "threads.h"
28 
29 #include "flow.h"
30 #include "flow-private.h"
31 #include "flow-util.h"
32 #include "flow-callbacks.h"
33 #include "flow-var.h"
34 #include "app-layer.h"
35 
36 #include "util-var.h"
37 #include "util-debug.h"
38 #include "util-macset.h"
39 #include "util-flow-rate.h"
40 #include "flow-storage.h"
41 
42 #include "detect.h"
43 #include "detect-engine-state.h"
44 
45 #include "decode-icmpv4.h"
46 
47 #include "util-device-private.h"
48 #include "util-validate.h"
49 
50 /** \brief allocate a flow
51  *
52  * We check against the memuse counter. If it passes that check we increment
53  * the counter first, then we try to alloc.
54  *
55  * \retval f the flow or NULL on out of memory
56  */
58 {
59  Flow *f;
60  size_t size = sizeof(Flow) + SCFlowStorageSize();
61 
62  if (!(FLOW_CHECK_MEMCAP(size))) {
63  return NULL;
64  }
65 
66  (void) SC_ATOMIC_ADD(flow_memuse, size);
67 
68  f = SCCalloc(1, size);
69  if (unlikely(f == NULL)) {
70  (void)SC_ATOMIC_SUB(flow_memuse, size);
71  return NULL;
72  }
73 
74  /* coverity[missing_lock] */
76  return f;
77 }
78 
79 
80 /**
81  * \brief cleanup & free the memory of a flow
82  *
83  * \param f flow to clear & destroy
84  */
85 void FlowFree(Flow *f)
86 {
87  FLOW_DESTROY(f);
88  SCFree(f);
89 
90  size_t size = sizeof(Flow) + SCFlowStorageSize();
91  (void) SC_ATOMIC_SUB(flow_memuse, size);
92 }
93 
94 /**
95  * \brief Function to map the protocol to the defined FLOW_PROTO_* enumeration.
96  *
97  * \param proto protocol which is needed to be mapped
98  */
99 
100 uint8_t FlowGetProtoMapping(uint8_t proto)
101 {
102  switch (proto) {
103  case IPPROTO_TCP:
104  return FLOW_PROTO_TCP;
105  case IPPROTO_UDP:
106  return FLOW_PROTO_UDP;
107  case IPPROTO_ICMP:
108  return FLOW_PROTO_ICMP;
109  default:
110  return FLOW_PROTO_DEFAULT;
111  }
112 }
113 
114 uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
115 {
116  switch (rproto) {
117  case FLOW_PROTO_TCP:
118  return IPPROTO_TCP;
119  case FLOW_PROTO_UDP:
120  return IPPROTO_UDP;
121  case FLOW_PROTO_ICMP:
122  return IPPROTO_ICMP;
123  default:
124  exit(EXIT_FAILURE);
125  }
126 }
127 
128 static inline void FlowSetICMPv4CounterPart(Flow *f)
129 {
130  int ctype = ICMPv4GetCounterpart(f->icmp_s.type);
131  if (ctype == -1)
132  return;
133 
134  f->icmp_d.type = (uint8_t)ctype;
135 }
136 
137 static inline void FlowSetICMPv6CounterPart(Flow *f)
138 {
139  int ctype = ICMPv6GetCounterpart(f->icmp_s.type);
140  if (ctype == -1)
141  return;
142 
143  f->icmp_d.type = (uint8_t)ctype;
144 }
145 
146 /* initialize the flow from the first packet
147  * we see from it. */
148 void FlowInit(ThreadVars *tv, Flow *f, const Packet *p)
149 {
150  SCEnter();
151  SCLogDebug("flow %p", f);
152 
153  f->proto = p->proto;
155  f->tunnel_id = p->tunnel_id;
156  memcpy(&f->vlan_id[0], &p->vlan_id[0], sizeof(f->vlan_id));
157  f->vlan_idx = p->vlan_idx;
158 
159  f->thread_id[0] = (FlowThreadId)tv->id;
160 
161  f->livedev_id = p->livedev_id;
162 
163  if (PacketIsIPv4(p)) {
164  const IPV4Hdr *ip4h = PacketGetIPv4(p);
168  f->flags |= FLOW_IPV4;
169  } else if (PacketIsIPv6(p)) {
170  const IPV6Hdr *ip6h = PacketGetIPv6(p);
174  f->flags |= FLOW_IPV6;
175  } else {
176  SCLogDebug("neither IPv4 or IPv6, weird");
178  }
179 
180  if (PacketIsTCP(p) || PacketIsUDP(p)) {
181  f->sp = p->sp;
182  f->dp = p->dp;
183  } else if (PacketIsICMPv4(p)) {
184  f->icmp_s.type = p->icmp_s.type;
185  f->icmp_s.code = p->icmp_s.code;
186  FlowSetICMPv4CounterPart(f);
187  } else if (PacketIsICMPv6(p)) {
188  f->icmp_s.type = p->icmp_s.type;
189  f->icmp_s.code = p->icmp_s.code;
190  FlowSetICMPv6CounterPart(f);
191  } else if (PacketIsSCTP(p)) {
192  f->sp = p->sp;
193  f->dp = p->dp;
194  } else if (PacketIsESP(p)) {
195  f->esp.spi = ESP_GET_SPI(PacketGetESP(p));
196  } else {
197  /* nothing to do for this IP proto. */
198  SCLogDebug("no special setup for IP proto %u", p->proto);
199  }
200  f->startts = p->ts;
201 
203  f->timeout_policy = FlowGetTimeoutPolicy(f);
204 
205  if (MacSetFlowStorageEnabled()) {
207  MacSet *ms = MacSetInit(10);
209  }
210 
211  if (FlowRateStorageEnabled()) {
215  }
216 
218 
219  SCReturn;
220 }
221 
223 
225 {
226  return g_bypass_info_id;
227 }
228 
229 static void FlowBypassFree(void *x)
230 {
231  FlowBypassInfo *fb = (FlowBypassInfo *) x;
232 
233  if (fb == NULL)
234  return;
235 
236  if (fb->bypass_data && fb->BypassFree) {
237  fb->BypassFree(fb->bypass_data);
238  }
239  SCFree(fb);
240 }
241 
243 {
244  g_bypass_info_id = SCFlowStorageRegister("bypass_counters", FlowBypassFree);
245 }
246 
248 {
249  for (int i = 0; i < FLOW_STATE_SIZE; i++) {
250  const char *name = NULL;
251  if (i == FLOW_STATE_NEW) {
252  name = "flow.end.state.new";
253  } else if (i == FLOW_STATE_ESTABLISHED) {
254  name = "flow.end.state.established";
255  } else if (i == FLOW_STATE_CLOSED) {
256  name = "flow.end.state.closed";
257  } else if (i == FLOW_STATE_LOCAL_BYPASSED) {
258  name = "flow.end.state.local_bypassed";
259 #ifdef CAPTURE_OFFLOAD
260  } else if (i == FLOW_STATE_CAPTURE_BYPASSED) {
261  name = "flow.end.state.capture_bypassed";
262 #endif
263  }
264  if (name) {
265  fec->flow_state[i] = StatsRegisterCounter(name, &t->stats);
266  }
267  }
268 
269  for (enum TcpState i = TCP_NONE; i <= TCP_CLOSED; i++) {
270  const char *name = NULL;
271  switch (i) {
272  case TCP_NONE:
273  name = "flow.end.tcp_state.none";
274  break;
275  case TCP_SYN_SENT:
276  name = "flow.end.tcp_state.syn_sent";
277  break;
278  case TCP_SYN_RECV:
279  name = "flow.end.tcp_state.syn_recv";
280  break;
281  case TCP_ESTABLISHED:
282  name = "flow.end.tcp_state.established";
283  break;
284  case TCP_FIN_WAIT1:
285  name = "flow.end.tcp_state.fin_wait1";
286  break;
287  case TCP_FIN_WAIT2:
288  name = "flow.end.tcp_state.fin_wait2";
289  break;
290  case TCP_TIME_WAIT:
291  name = "flow.end.tcp_state.time_wait";
292  break;
293  case TCP_LAST_ACK:
294  name = "flow.end.tcp_state.last_ack";
295  break;
296  case TCP_CLOSE_WAIT:
297  name = "flow.end.tcp_state.close_wait";
298  break;
299  case TCP_CLOSING:
300  name = "flow.end.tcp_state.closing";
301  break;
302  case TCP_CLOSED:
303  name = "flow.end.tcp_state.closed";
304  break;
305  }
306 
308  }
309  fec->flow_tcp_liberal = StatsRegisterCounter("flow.end.tcp_liberal", &t->stats);
310 }
ESP_GET_SPI
#define ESP_GET_SPI(esph)
Get the spi field off a packet.
Definition: decode-esp.h:29
util-device-private.h
TCP_SYN_RECV
@ TCP_SYN_RECV
Definition: stream-tcp-private.h:154
Packet_::proto
uint8_t proto
Definition: decode.h:556
Flow_::recursion_level
uint8_t recursion_level
Definition: flow.h:383
Flow_::flags
uint64_t flags
Definition: flow.h:410
IPV6_GET_RAW_HLIM
#define IPV6_GET_RAW_HLIM(ip6h)
Definition: decode-ipv6.h:67
FLOW_STATE_ESTABLISHED
@ FLOW_STATE_ESTABLISHED
Definition: flow.h:512
TCP_SYN_SENT
@ TCP_SYN_SENT
Definition: stream-tcp-private.h:153
flow-util.h
Flow_::startts
SCTime_t startts
Definition: flow.h:500
FlowBypassInfo_
Definition: flow.h:536
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
SCFlowGetStorageById
void * SCFlowGetStorageById(const Flow *f, SCFlowStorageId id)
Definition: flow-storage.c:37
ICMPv6GetCounterpart
int ICMPv6GetCounterpart(uint8_t type)
Definition: decode-icmpv6.c:145
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
StatsRegisterCounter
StatsCounterId StatsRegisterCounter(const char *name, StatsThreadContext *stats)
Registers a normal, unqualified counter.
Definition: counters.c:1038
TCP_FIN_WAIT2
@ TCP_FIN_WAIT2
Definition: stream-tcp-private.h:157
name
const char * name
Definition: detect-engine-proto.c:47
Flow_::proto
uint8_t proto
Definition: flow.h:382
threads.h
FLOW_SET_IPV6_SRC_ADDR_FROM_PACKET
#define FLOW_SET_IPV6_SRC_ADDR_FROM_PACKET(ip6h, a)
Definition: flow.h:219
util-macset.h
Packet_::vlan_idx
uint8_t vlan_idx
Definition: decode.h:567
flow-private.h
Flow_
Flow data structure.
Definition: flow.h:360
FLOW_PROTO_DEFAULT
@ FLOW_PROTO_DEFAULT
Definition: flow-private.h:67
RegisterFlowBypassInfo
void RegisterFlowBypassInfo(void)
Definition: flow-util.c:242
Flow_::esp
struct Flow_::@126::@133 esp
SCFlowStorageSize
unsigned int SCFlowStorageSize(void)
Definition: flow-storage.c:32
Flow_::protomap
uint8_t protomap
Definition: flow.h:452
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:332
SCFlowStorageId
Definition: flow-storage.h:33
TCP_FIN_WAIT1
@ TCP_FIN_WAIT1
Definition: stream-tcp-private.h:156
TCP_LAST_ACK
@ TCP_LAST_ACK
Definition: stream-tcp-private.h:159
FlowRateGetStorageID
SCFlowStorageId FlowRateGetStorageID(void)
Definition: util-flow-rate.c:132
TCP_ESTABLISHED
@ TCP_ESTABLISHED
Definition: stream-tcp-private.h:155
p
Packet * p
Definition: fuzz_dataset.c:30
Flow_::max_ttl_toserver
uint8_t max_ttl_toserver
Definition: flow.h:475
proto
uint8_t proto
Definition: decode-template.h:0
Flow_::livedev_id
uint16_t livedev_id
Definition: flow.h:406
Flow_::dp
Port dp
Definition: flow.h:376
g_bypass_info_id
SCFlowStorageId g_bypass_info_id
Definition: flow-util.c:222
FLOW_SET_IPV6_DST_ADDR_FROM_PACKET
#define FLOW_SET_IPV6_DST_ADDR_FROM_PACKET(ip6h, a)
Definition: flow.h:227
util-var.h
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:99
GetFlowBypassInfoID
SCFlowStorageId GetFlowBypassInfoID(void)
Definition: flow-util.c:224
FlowEndCounters_::flow_tcp_state
StatsCounterId flow_tcp_state[TCP_CLOSED+1]
Definition: flow-util.h:148
FlowGetReverseProtoMapping
uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
Definition: flow-util.c:114
TcpState
TcpState
Definition: stream-tcp-private.h:150
SCFlowStorageRegister
SCFlowStorageId SCFlowStorageRegister(const char *name, void(*Free)(void *))
Definition: flow-storage.c:58
Packet_::icmp_s
struct Packet_::@32::@39 icmp_s
Flow_::icmp_d
struct Flow_::@128::@134 icmp_d
FLOW_CHECK_MEMCAP
#define FLOW_CHECK_MEMCAP(size)
check if a memory alloc would fit in the memcap
Definition: flow-util.h:134
Flow_::dst
FlowAddress dst
Definition: flow.h:363
TCP_NONE
@ TCP_NONE
Definition: stream-tcp-private.h:151
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:38
util-flow-rate.h
FLOW_STATE_LOCAL_BYPASSED
@ FLOW_STATE_LOCAL_BYPASSED
Definition: flow.h:514
Flow_::min_ttl_toserver
uint8_t min_ttl_toserver
Definition: flow.h:474
TCP_CLOSE_WAIT
@ TCP_CLOSE_WAIT
Definition: stream-tcp-private.h:160
util-debug.h
FlowBypassInfo_::BypassFree
void(* BypassFree)(void *data)
Definition: flow.h:538
Packet_::ts
SCTime_t ts
Definition: decode.h:596
FlowEndCounters_::flow_tcp_liberal
StatsCounterId flow_tcp_liberal
Definition: flow-util.h:149
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
SCFlowSetStorageById
int SCFlowSetStorageById(Flow *f, SCFlowStorageId id, void *ptr)
Definition: flow-storage.c:42
Packet_::sp
Port sp
Definition: decode.h:541
Packet_::tunnel_id
uint16_t tunnel_id
Definition: decode.h:564
FlowBypassInfo_::bypass_data
void * bypass_data
Definition: flow.h:539
FLOW_PROTO_TCP
@ FLOW_PROTO_TCP
Definition: flow-private.h:64
ThreadVars_::id
int id
Definition: threadvars.h:85
MacSetFlowStorageEnabled
bool MacSetFlowStorageEnabled(void)
Definition: util-macset.c:84
Flow_::tunnel_id
uint16_t tunnel_id
Definition: flow.h:384
SC_ATOMIC_SUB
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:341
FlowThreadId
uint16_t FlowThreadId
Definition: flow.h:337
SCReturn
#define SCReturn
Definition: util-debug.h:286
IPV6Hdr_
Definition: decode-ipv6.h:32
FlowGetProtoMapping
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition: flow-util.c:100
Packet_
Definition: decode.h:534
IPV4_GET_RAW_IPTTL
#define IPV4_GET_RAW_IPTTL(ip4h)
Definition: decode-ipv4.h:102
decode-icmpv4.h
MacSet_
Definition: util-macset.c:44
Flow_::vlan_idx
uint8_t vlan_idx
Definition: flow.h:387
ICMPv4GetCounterpart
int ICMPv4GetCounterpart(uint8_t type)
Definition: decode-icmpv4.c:344
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
FLOW_SET_IPV4_SRC_ADDR_FROM_PACKET
#define FLOW_SET_IPV4_SRC_ADDR_FROM_PACKET(ip4h, a)
Definition: flow.h:201
FLOW_STATE_SIZE
#define FLOW_STATE_SIZE
Definition: flow.h:522
Flow_::src
FlowAddress src
Definition: flow.h:363
IPV4Hdr_
Definition: decode-ipv4.h:72
TCP_CLOSED
@ TCP_CLOSED
Definition: stream-tcp-private.h:162
flow-storage.h
Flow_::icmp_s
struct Flow_::@126::@132 icmp_s
FLOW_STATE_NEW
@ FLOW_STATE_NEW
Definition: flow.h:511
SCFlowRunInitCallbacks
void SCFlowRunInitCallbacks(ThreadVars *tv, Flow *f, const Packet *p)
Definition: flow-callbacks.c:64
suricata-common.h
FlowFree
void FlowFree(Flow *f)
cleanup & free the memory of a flow
Definition: flow-util.c:85
FLOW_IPV6
#define FLOW_IPV6
Definition: flow.h:101
FlowRateStoreInit
FlowRateStore * FlowRateStoreInit(void)
Definition: util-flow-rate.c:100
Packet_::livedev_id
uint16_t livedev_id
Definition: decode.h:659
Flow
struct Flow_ Flow
Definition: app-layer-detect-proto.h:29
MacSetInit
MacSet * MacSetInit(int size)
Definition: util-macset.c:89
Flow_::timeout_policy
uint32_t timeout_policy
Definition: flow.h:420
TCP_CLOSING
@ TCP_CLOSING
Definition: stream-tcp-private.h:161
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:34
FLOW_PROTO_ICMP
@ FLOW_PROTO_ICMP
Definition: flow-private.h:66
util-validate.h
FLOW_STATE_CLOSED
@ FLOW_STATE_CLOSED
Definition: flow.h:513
flow-callbacks.h
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Packet_::recursion_level
uint8_t recursion_level
Definition: decode.h:559
FLOW_PROTO_UDP
@ FLOW_PROTO_UDP
Definition: flow-private.h:65
FlowInit
void FlowInit(ThreadVars *tv, Flow *f, const Packet *p)
Definition: flow-util.c:148
TCP_TIME_WAIT
@ TCP_TIME_WAIT
Definition: stream-tcp-private.h:158
FlowRateStorageEnabled
bool FlowRateStorageEnabled(void)
Definition: util-flow-rate.c:95
Flow_::vlan_id
uint16_t vlan_id[VLAN_MAX_LAYERS]
Definition: flow.h:385
FLOW_SET_IPV4_DST_ADDR_FROM_PACKET
#define FLOW_SET_IPV4_DST_ADDR_FROM_PACKET(ip4h, a)
Definition: flow.h:209
FlowEndCounters_::flow_state
StatsCounterId flow_state[FLOW_STATE_SIZE]
Definition: flow-util.h:147
SCFlowStorageId::id
int id
Definition: flow-storage.h:34
Packet_::vlan_id
uint16_t vlan_id[VLAN_MAX_LAYERS]
Definition: decode.h:566
Flow_::sp
Port sp
Definition: flow.h:365
flow.h
FlowAlloc
Flow * FlowAlloc(void)
allocate a flow
Definition: flow-util.c:57
FlowEndCountersRegister
void FlowEndCountersRegister(ThreadVars *t, FlowEndCounters *fec)
Definition: flow-util.c:247
Packet_::dp
Port dp
Definition: decode.h:549
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
ThreadVars_::stats
StatsThreadContext stats
Definition: threadvars.h:120
FlowEndCounters_
Definition: flow-util.h:146
flow-var.h
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:119
FlowRateStore_
Definition: util-flow-rate.h:47
Flow_::thread_id
FlowThreadId thread_id[2]
Definition: flow.h:399
app-layer.h
f
Flow f
Definition: fuzz_dataset.c:32
MacSetGetFlowStorageID
SCFlowStorageId MacSetGetFlowStorageID(void)
Definition: util-macset.c:112