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-var.h"
33 #include "app-layer.h"
34 
35 #include "util-var.h"
36 #include "util-debug.h"
37 #include "util-macset.h"
38 #include "flow-storage.h"
39 
40 #include "detect.h"
41 #include "detect-engine-state.h"
42 
43 #include "decode-icmpv4.h"
44 
45 #include "util-validate.h"
46 
47 /** \brief allocate a flow
48  *
49  * We check against the memuse counter. If it passes that check we increment
50  * the counter first, then we try to alloc.
51  *
52  * \retval f the flow or NULL on out of memory
53  */
55 {
56  Flow *f;
57  size_t size = sizeof(Flow) + FlowStorageSize();
58 
59  if (!(FLOW_CHECK_MEMCAP(size))) {
60  return NULL;
61  }
62 
63  (void) SC_ATOMIC_ADD(flow_memuse, size);
64 
65  f = SCMalloc(size);
66  if (unlikely(f == NULL)) {
67  (void)SC_ATOMIC_SUB(flow_memuse, size);
68  return NULL;
69  }
70  memset(f, 0, size);
71 
72  /* coverity[missing_lock] */
73  FLOW_INITIALIZE(f);
74  return f;
75 }
76 
77 
78 /**
79  * \brief cleanup & free the memory of a flow
80  *
81  * \param f flow to clear & destroy
82  */
83 void FlowFree(Flow *f)
84 {
85  FLOW_DESTROY(f);
86  SCFree(f);
87 
88  size_t size = sizeof(Flow) + FlowStorageSize();
89  (void) SC_ATOMIC_SUB(flow_memuse, size);
90 }
91 
92 /**
93  * \brief Function to map the protocol to the defined FLOW_PROTO_* enumeration.
94  *
95  * \param proto protocol which is needed to be mapped
96  */
97 
98 uint8_t FlowGetProtoMapping(uint8_t proto)
99 {
100  switch (proto) {
101  case IPPROTO_TCP:
102  return FLOW_PROTO_TCP;
103  case IPPROTO_UDP:
104  return FLOW_PROTO_UDP;
105  case IPPROTO_ICMP:
106  return FLOW_PROTO_ICMP;
107  default:
108  return FLOW_PROTO_DEFAULT;
109  }
110 }
111 
112 uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
113 {
114  switch (rproto) {
115  case FLOW_PROTO_TCP:
116  return IPPROTO_TCP;
117  case FLOW_PROTO_UDP:
118  return IPPROTO_UDP;
119  case FLOW_PROTO_ICMP:
120  return IPPROTO_ICMP;
121  default:
122  exit(EXIT_FAILURE);
123  }
124 }
125 
126 static inline void FlowSetICMPv4CounterPart(Flow *f)
127 {
128  int ctype = ICMPv4GetCounterpart(f->icmp_s.type);
129  if (ctype == -1)
130  return;
131 
132  f->icmp_d.type = (uint8_t)ctype;
133 }
134 
135 static inline void FlowSetICMPv6CounterPart(Flow *f)
136 {
137  int ctype = ICMPv6GetCounterpart(f->icmp_s.type);
138  if (ctype == -1)
139  return;
140 
141  f->icmp_d.type = (uint8_t)ctype;
142 }
143 
144 /* initialize the flow from the first packet
145  * we see from it. */
146 void FlowInit(Flow *f, const Packet *p)
147 {
148  SCEnter();
149  SCLogDebug("flow %p", f);
150 
151  f->proto = p->proto;
153  f->vlan_id[0] = p->vlan_id[0];
154  f->vlan_id[1] = p->vlan_id[1];
155  f->vlan_idx = p->vlan_idx;
156  f->livedev = p->livedev;
157 
158  if (PKT_IS_IPV4(p)) {
162  f->flags |= FLOW_IPV4;
163  } else if (PKT_IS_IPV6(p)) {
167  f->flags |= FLOW_IPV6;
168  } else {
169  SCLogDebug("neither IPv4 or IPv6, weird");
171  }
172 
173  if (p->tcph != NULL) { /* XXX MACRO */
174  SET_TCP_SRC_PORT(p,&f->sp);
175  SET_TCP_DST_PORT(p,&f->dp);
176  } else if (p->udph != NULL) { /* XXX MACRO */
177  SET_UDP_SRC_PORT(p,&f->sp);
178  SET_UDP_DST_PORT(p,&f->dp);
179  } else if (p->icmpv4h != NULL) {
180  f->icmp_s.type = p->icmp_s.type;
181  f->icmp_s.code = p->icmp_s.code;
182  FlowSetICMPv4CounterPart(f);
183  } else if (p->icmpv6h != NULL) {
184  f->icmp_s.type = p->icmp_s.type;
185  f->icmp_s.code = p->icmp_s.code;
186  FlowSetICMPv6CounterPart(f);
187  } else if (p->sctph != NULL) { /* XXX MACRO */
188  SET_SCTP_SRC_PORT(p,&f->sp);
189  SET_SCTP_DST_PORT(p,&f->dp);
190  } else if (p->esph != NULL) {
191  f->esp.spi = ESP_GET_SPI(p);
192  } else {
193  /* nothing to do for this IP proto. */
194  SCLogDebug("no special setup for IP proto %u", p->proto);
195  }
196  COPY_TIMESTAMP(&p->ts, &f->startts);
197 
199  f->timeout_policy = FlowGetTimeoutPolicy(f);
200  const uint32_t timeout_at = (uint32_t)f->startts.tv_sec + f->timeout_policy;
201  f->timeout_at = timeout_at;
202 
203  if (MacSetFlowStorageEnabled()) {
205  if (ms != NULL) {
206  MacSetReset(ms);
207  } else {
208  ms = MacSetInit(10);
210  }
211  }
212 
213  SCReturn;
214 }
215 
217 
219 {
220  return g_bypass_info_id;
221 }
222 
223 static void FlowBypassFree(void *x)
224 {
225  FlowBypassInfo *fb = (FlowBypassInfo *) x;
226 
227  if (fb == NULL)
228  return;
229 
230  if (fb->bypass_data && fb->BypassFree) {
231  fb->BypassFree(fb->bypass_data);
232  }
233  SCFree(fb);
234 }
235 
237 {
238  g_bypass_info_id = FlowStorageRegister("bypass_counters", sizeof(void *),
239  NULL, FlowBypassFree);
240 }
241 
243 {
244  for (int i = 0; i < FLOW_STATE_SIZE; i++) {
245  const char *name = NULL;
246  if (i == FLOW_STATE_NEW) {
247  name = "flow.end.state.new";
248  } else if (i == FLOW_STATE_ESTABLISHED) {
249  name = "flow.end.state.established";
250  } else if (i == FLOW_STATE_CLOSED) {
251  name = "flow.end.state.closed";
252  } else if (i == FLOW_STATE_LOCAL_BYPASSED) {
253  name = "flow.end.state.local_bypassed";
254 #ifdef CAPTURE_OFFLOAD
255  } else if (i == FLOW_STATE_CAPTURE_BYPASSED) {
256  name = "flow.end.state.capture_bypassed";
257 #endif
258  }
259  if (name) {
260  fec->flow_state[i] = StatsRegisterCounter(name, t);
261  }
262  }
263 
264  for (enum TcpState i = TCP_NONE; i <= TCP_CLOSED; i++) {
265  const char *name = NULL;
266  switch (i) {
267  case TCP_NONE:
268  name = "flow.end.tcp_state.none";
269  break;
270  case TCP_SYN_SENT:
271  name = "flow.end.tcp_state.syn_sent";
272  break;
273  case TCP_SYN_RECV:
274  name = "flow.end.tcp_state.syn_recv";
275  break;
276  case TCP_ESTABLISHED:
277  name = "flow.end.tcp_state.established";
278  break;
279  case TCP_FIN_WAIT1:
280  name = "flow.end.tcp_state.fin_wait1";
281  break;
282  case TCP_FIN_WAIT2:
283  name = "flow.end.tcp_state.fin_wait2";
284  break;
285  case TCP_TIME_WAIT:
286  name = "flow.end.tcp_state.time_wait";
287  break;
288  case TCP_LAST_ACK:
289  name = "flow.end.tcp_state.last_ack";
290  break;
291  case TCP_CLOSE_WAIT:
292  name = "flow.end.tcp_state.close_wait";
293  break;
294  case TCP_CLOSING:
295  name = "flow.end.tcp_state.closing";
296  break;
297  case TCP_CLOSED:
298  name = "flow.end.tcp_state.closed";
299  break;
300  }
301 
302  fec->flow_tcp_state[i] = StatsRegisterCounter(name, t);
303  }
304  fec->flow_tcp_liberal = StatsRegisterCounter("flow.end.tcp_liberal", t);
305 }
FlowStorageId
Definition: flow-storage.h:31
TCP_SYN_RECV
@ TCP_SYN_RECV
Definition: stream-tcp-private.h:153
Packet_::proto
uint8_t proto
Definition: decode.h:447
Packet_::icmp_s
struct Packet_::@33::@43 icmp_s
SET_SCTP_DST_PORT
#define SET_SCTP_DST_PORT(pkt, prt)
Definition: decode.h:198
Flow_::recursion_level
uint8_t recursion_level
Definition: flow.h:379
Packet_::sctph
SCTPHdr * sctph
Definition: decode.h:551
FLOW_PROTO_ICMP
@ FLOW_PROTO_ICMP
Definition: flow-private.h:72
FLOW_STATE_ESTABLISHED
@ FLOW_STATE_ESTABLISHED
Definition: flow.h:513
TCP_SYN_SENT
@ TCP_SYN_SENT
Definition: stream-tcp-private.h:152
flow-util.h
Flow_::icmp_d
struct Flow_::@119::@125 icmp_d
Flow_::startts
struct timeval startts
Definition: flow.h:503
Packet_::vlan_id
uint16_t vlan_id[2]
Definition: decode.h:452
PKT_IS_IPV6
#define PKT_IS_IPV6(p)
Definition: decode.h:243
GetFlowBypassInfoID
FlowStorageId GetFlowBypassInfoID(void)
Definition: flow-util.c:218
FlowBypassInfo_
Definition: flow.h:537
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
ICMPv6GetCounterpart
int ICMPv6GetCounterpart(uint8_t type)
Definition: decode-icmpv6.c:146
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:296
TCP_FIN_WAIT2
@ TCP_FIN_WAIT2
Definition: stream-tcp-private.h:156
g_bypass_info_id
FlowStorageId g_bypass_info_id
Definition: flow-util.c:216
Flow_::proto
uint8_t proto
Definition: flow.h:378
threads.h
util-macset.h
Packet_::vlan_idx
uint8_t vlan_idx
Definition: decode.h:453
flow-private.h
Flow_
Flow data structure.
Definition: flow.h:356
RegisterFlowBypassInfo
void RegisterFlowBypassInfo(void)
Definition: flow-util.c:236
Flow_::protomap
uint8_t protomap
Definition: flow.h:458
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:333
TCP_FIN_WAIT1
@ TCP_FIN_WAIT1
Definition: stream-tcp-private.h:155
TCP_LAST_ACK
@ TCP_LAST_ACK
Definition: stream-tcp-private.h:158
Flow_::vlan_id
uint16_t vlan_id[2]
Definition: flow.h:380
Flow
struct Flow_ Flow
Flow data structure.
FlowEndCounters_::flow_tcp_liberal
uint16_t flow_tcp_liberal
Definition: flow-util.h:159
TCP_ESTABLISHED
@ TCP_ESTABLISHED
Definition: stream-tcp-private.h:154
FlowEndCounters_::flow_state
uint16_t flow_state[FLOW_STATE_SIZE]
Definition: flow-util.h:157
Flow_::max_ttl_toserver
uint8_t max_ttl_toserver
Definition: flow.h:481
proto
uint8_t proto
Definition: decode-template.h:0
Flow_::dp
Port dp
Definition: flow.h:372
SET_UDP_DST_PORT
#define SET_UDP_DST_PORT(pkt, prt)
Definition: decode.h:188
util-var.h
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:96
FlowGetReverseProtoMapping
uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
Definition: flow-util.c:112
FLOW_SET_IPV6_DST_ADDR_FROM_PACKET
#define FLOW_SET_IPV6_DST_ADDR_FROM_PACKET(p, a)
Definition: flow.h:218
TcpState
TcpState
Definition: stream-tcp-private.h:149
FLOW_CHECK_MEMCAP
#define FLOW_CHECK_MEMCAP(size)
check if a memory alloc would fit in the memcap
Definition: flow-util.h:144
FLOW_PROTO_UDP
@ FLOW_PROTO_UDP
Definition: flow-private.h:71
Flow_::dst
FlowAddress dst
Definition: flow.h:359
FlowEndCounters_::flow_tcp_state
uint16_t flow_tcp_state[TCP_CLOSED+1]
Definition: flow-util.h:158
TCP_NONE
@ TCP_NONE
Definition: stream-tcp-private.h:150
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
FLOW_STATE_LOCAL_BYPASSED
@ FLOW_STATE_LOCAL_BYPASSED
Definition: flow.h:515
Flow_::min_ttl_toserver
uint8_t min_ttl_toserver
Definition: flow.h:480
TCP_CLOSE_WAIT
@ TCP_CLOSE_WAIT
Definition: stream-tcp-private.h:159
Flow_::esp
struct Flow_::@117::@124 esp
util-debug.h
SET_TCP_SRC_PORT
#define SET_TCP_SRC_PORT(pkt, prt)
Definition: decode.h:175
FlowBypassInfo_::BypassFree
void(* BypassFree)(void *data)
Definition: flow.h:539
SET_UDP_SRC_PORT
#define SET_UDP_SRC_PORT(pkt, prt)
Definition: decode.h:185
FLOW_SET_IPV6_SRC_ADDR_FROM_PACKET
#define FLOW_SET_IPV6_SRC_ADDR_FROM_PACKET(p, a)
Definition: flow.h:211
SCEnter
#define SCEnter(...)
Definition: util-debug.h:298
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
FlowStorageSize
unsigned int FlowStorageSize(void)
Definition: flow-storage.c:35
FlowSetStorageById
int FlowSetStorageById(Flow *f, FlowStorageId id, void *ptr)
Definition: flow-storage.c:45
FlowStorageRegister
FlowStorageId FlowStorageRegister(const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void(*Free)(void *))
Definition: flow-storage.c:66
FlowBypassInfo_::bypass_data
void * bypass_data
Definition: flow.h:540
Flow_::icmp_s
struct Flow_::@117::@123 icmp_s
MacSetFlowStorageEnabled
bool MacSetFlowStorageEnabled(void)
Definition: util-macset.c:84
SC_ATOMIC_SUB
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:342
SCReturn
#define SCReturn
Definition: util-debug.h:300
Packet_::icmpv6h
ICMPV6Hdr * icmpv6h
Definition: decode.h:557
FlowGetProtoMapping
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition: flow-util.c:98
Packet_
Definition: decode.h:425
FLOW_SET_IPV4_DST_ADDR_FROM_PACKET
#define FLOW_SET_IPV4_DST_ADDR_FROM_PACKET(p, a)
Definition: flow.h:194
ESP_GET_SPI
#define ESP_GET_SPI(p)
Get the spi field off a packet.
Definition: decode-esp.h:32
decode-icmpv4.h
MacSet_
Definition: util-macset.c:44
Packet_::livedev
struct LiveDevice_ * livedev
Definition: decode.h:580
Flow_::vlan_idx
uint8_t vlan_idx
Definition: flow.h:388
ICMPv4GetCounterpart
int ICMPv4GetCounterpart(uint8_t type)
Definition: decode-icmpv4.c:360
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
MacSetGetFlowStorageID
FlowStorageId MacSetGetFlowStorageID(void)
Definition: util-macset.c:113
FLOW_STATE_SIZE
#define FLOW_STATE_SIZE
Definition: flow.h:523
FlowGetStorageById
void * FlowGetStorageById(const Flow *f, FlowStorageId id)
Definition: flow-storage.c:40
Flow_::src
FlowAddress src
Definition: flow.h:359
FLOW_SET_IPV4_SRC_ADDR_FROM_PACKET
#define FLOW_SET_IPV4_SRC_ADDR_FROM_PACKET(p, a)
Definition: flow.h:187
SET_SCTP_SRC_PORT
#define SET_SCTP_SRC_PORT(pkt, prt)
Definition: decode.h:194
TCP_CLOSED
@ TCP_CLOSED
Definition: stream-tcp-private.h:161
flow-storage.h
MacSetReset
void MacSetReset(MacSet *ms)
Definition: util-macset.c:262
FLOW_PROTO_TCP
@ FLOW_PROTO_TCP
Definition: flow-private.h:70
FLOW_STATE_NEW
@ FLOW_STATE_NEW
Definition: flow.h:512
Packet_::ts
struct timeval ts
Definition: decode.h:468
suricata-common.h
FlowFree
void FlowFree(Flow *f)
cleanup & free the memory of a flow
Definition: flow-util.c:83
FLOW_IPV6
#define FLOW_IPV6
Definition: flow.h:98
Packet_::tcph
TCPHdr * tcph
Definition: decode.h:547
MacSetInit
MacSet * MacSetInit(int size)
Definition: util-macset.c:90
Packet_::icmpv4h
ICMPV4Hdr * icmpv4h
Definition: decode.h:555
Flow_::timeout_policy
uint32_t timeout_policy
Definition: flow.h:423
TCP_CLOSING
@ TCP_CLOSING
Definition: stream-tcp-private.h:160
Flow_::livedev
struct LiveDevice_ * livedev
Definition: flow.h:409
util-validate.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
FLOW_STATE_CLOSED
@ FLOW_STATE_CLOSED
Definition: flow.h:514
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::flags
uint32_t flags
Definition: flow.h:434
Packet_::recursion_level
uint8_t recursion_level
Definition: decode.h:450
TCP_TIME_WAIT
@ TCP_TIME_WAIT
Definition: stream-tcp-private.h:157
FlowStorageId::id
int id
Definition: flow-storage.h:32
IPV6_GET_HLIM
#define IPV6_GET_HLIM(p)
Definition: decode-ipv6.h:90
Packet_::udph
UDPHdr * udph
Definition: decode.h:549
FLOW_PROTO_DEFAULT
@ FLOW_PROTO_DEFAULT
Definition: flow-private.h:73
COPY_TIMESTAMP
#define COPY_TIMESTAMP(src, dst)
Definition: flow-util.h:30
Flow_::sp
Port sp
Definition: flow.h:361
flow.h
FlowAlloc
Flow * FlowAlloc(void)
allocate a flow
Definition: flow-util.c:54
FlowEndCountersRegister
void FlowEndCountersRegister(ThreadVars *t, FlowEndCounters *fec)
Definition: flow-util.c:242
StatsRegisterCounter
uint16_t StatsRegisterCounter(const char *name, struct ThreadVars_ *tv)
Registers a normal, unqualified counter.
Definition: counters.c:955
Packet_::esph
ESPHdr * esph
Definition: decode.h:553
Flow_::timeout_at
uint32_t timeout_at
Definition: flow.h:402
FlowEndCounters_
Definition: flow-util.h:156
flow-var.h
PKT_IS_IPV4
#define PKT_IS_IPV4(p)
Definition: decode.h:242
SET_TCP_DST_PORT
#define SET_TCP_DST_PORT(pkt, prt)
Definition: decode.h:179
FlowInit
void FlowInit(Flow *f, const Packet *p)
Definition: flow-util.c:146
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:111
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:130
IPV4_GET_IPTTL
#define IPV4_GET_IPTTL(p)
Definition: decode-ipv4.h:146
app-layer.h