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-validate.h"
48
49/** \brief allocate a flow
50 *
51 * We check against the memuse counter. If it passes that check we increment
52 * the counter first, then we try to alloc.
53 *
54 * \retval f the flow or NULL on out of memory
55 */
57{
58 Flow *f;
59 size_t size = sizeof(Flow) + FlowStorageSize();
60
61 if (!(FLOW_CHECK_MEMCAP(size))) {
62 return NULL;
63 }
64
65 (void) SC_ATOMIC_ADD(flow_memuse, size);
66
67 f = SCCalloc(1, size);
68 if (unlikely(f == NULL)) {
69 (void)SC_ATOMIC_SUB(flow_memuse, size);
70 return NULL;
71 }
72
73 /* coverity[missing_lock] */
75 return f;
76}
77
78
79/**
80 * \brief cleanup & free the memory of a flow
81 *
82 * \param f flow to clear & destroy
83 */
84void FlowFree(Flow *f)
85{
86 FLOW_DESTROY(f);
87 SCFree(f);
88
89 size_t size = sizeof(Flow) + FlowStorageSize();
90 (void) SC_ATOMIC_SUB(flow_memuse, size);
91}
92
93/**
94 * \brief Function to map the protocol to the defined FLOW_PROTO_* enumeration.
95 *
96 * \param proto protocol which is needed to be mapped
97 */
98
99uint8_t FlowGetProtoMapping(uint8_t proto)
100{
101 switch (proto) {
102 case IPPROTO_TCP:
103 return FLOW_PROTO_TCP;
104 case IPPROTO_UDP:
105 return FLOW_PROTO_UDP;
106 case IPPROTO_ICMP:
107 return FLOW_PROTO_ICMP;
108 default:
109 return FLOW_PROTO_DEFAULT;
110 }
111}
112
113uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
114{
115 switch (rproto) {
116 case FLOW_PROTO_TCP:
117 return IPPROTO_TCP;
118 case FLOW_PROTO_UDP:
119 return IPPROTO_UDP;
120 case FLOW_PROTO_ICMP:
121 return IPPROTO_ICMP;
122 default:
123 exit(EXIT_FAILURE);
124 }
125}
126
127static inline void FlowSetICMPv4CounterPart(Flow *f)
128{
129 int ctype = ICMPv4GetCounterpart(f->icmp_s.type);
130 if (ctype == -1)
131 return;
132
133 f->icmp_d.type = (uint8_t)ctype;
134}
135
136static inline void FlowSetICMPv6CounterPart(Flow *f)
137{
138 int ctype = ICMPv6GetCounterpart(f->icmp_s.type);
139 if (ctype == -1)
140 return;
141
142 f->icmp_d.type = (uint8_t)ctype;
143}
144
145/* initialize the flow from the first packet
146 * we see from it. */
147void FlowInit(ThreadVars *tv, Flow *f, const Packet *p)
148{
149 SCEnter();
150 SCLogDebug("flow %p", f);
151
152 f->proto = p->proto;
154 memcpy(&f->vlan_id[0], &p->vlan_id[0], sizeof(f->vlan_id));
155 f->vlan_idx = p->vlan_idx;
156
157 f->thread_id[0] = (FlowThreadId)tv->id;
158
159 f->livedev = p->livedev;
160
161 if (PacketIsIPv4(p)) {
162 const IPV4Hdr *ip4h = PacketGetIPv4(p);
166 f->flags |= FLOW_IPV4;
167 } else if (PacketIsIPv6(p)) {
168 const IPV6Hdr *ip6h = PacketGetIPv6(p);
172 f->flags |= FLOW_IPV6;
173 } else {
174 SCLogDebug("neither IPv4 or IPv6, weird");
176 }
177
178 if (PacketIsTCP(p) || PacketIsUDP(p)) {
179 f->sp = p->sp;
180 f->dp = p->dp;
181 } else if (PacketIsICMPv4(p)) {
182 f->icmp_s.type = p->icmp_s.type;
183 f->icmp_s.code = p->icmp_s.code;
184 FlowSetICMPv4CounterPart(f);
185 } else if (PacketIsICMPv6(p)) {
186 f->icmp_s.type = p->icmp_s.type;
187 f->icmp_s.code = p->icmp_s.code;
188 FlowSetICMPv6CounterPart(f);
189 } else if (PacketIsSCTP(p)) {
190 f->sp = p->sp;
191 f->dp = p->dp;
192 } else if (PacketIsESP(p)) {
193 f->esp.spi = ESP_GET_SPI(PacketGetESP(p));
194 } else {
195 /* nothing to do for this IP proto. */
196 SCLogDebug("no special setup for IP proto %u", p->proto);
197 }
198 f->startts = p->ts;
199
201 f->timeout_policy = FlowGetTimeoutPolicy(f);
202
205 MacSet *ms = MacSetInit(10);
207 }
208
213 }
214
216
217 SCReturn;
218}
219
221
226
227static void FlowBypassFree(void *x)
228{
229 FlowBypassInfo *fb = (FlowBypassInfo *) x;
230
231 if (fb == NULL)
232 return;
233
234 if (fb->bypass_data && fb->BypassFree) {
235 fb->BypassFree(fb->bypass_data);
236 }
237 SCFree(fb);
238}
239
241{
242 g_bypass_info_id = FlowStorageRegister("bypass_counters", sizeof(void *),
243 NULL, FlowBypassFree);
244}
245
247{
248 for (int i = 0; i < FLOW_STATE_SIZE; i++) {
249 const char *name = NULL;
250 if (i == FLOW_STATE_NEW) {
251 name = "flow.end.state.new";
252 } else if (i == FLOW_STATE_ESTABLISHED) {
253 name = "flow.end.state.established";
254 } else if (i == FLOW_STATE_CLOSED) {
255 name = "flow.end.state.closed";
256 } else if (i == FLOW_STATE_LOCAL_BYPASSED) {
257 name = "flow.end.state.local_bypassed";
258#ifdef CAPTURE_OFFLOAD
259 } else if (i == FLOW_STATE_CAPTURE_BYPASSED) {
260 name = "flow.end.state.capture_bypassed";
261#endif
262 }
263 if (name) {
265 }
266 }
267
268 for (enum TcpState i = TCP_NONE; i <= TCP_CLOSED; i++) {
269 const char *name = NULL;
270 switch (i) {
271 case TCP_NONE:
272 name = "flow.end.tcp_state.none";
273 break;
274 case TCP_SYN_SENT:
275 name = "flow.end.tcp_state.syn_sent";
276 break;
277 case TCP_SYN_RECV:
278 name = "flow.end.tcp_state.syn_recv";
279 break;
280 case TCP_ESTABLISHED:
281 name = "flow.end.tcp_state.established";
282 break;
283 case TCP_FIN_WAIT1:
284 name = "flow.end.tcp_state.fin_wait1";
285 break;
286 case TCP_FIN_WAIT2:
287 name = "flow.end.tcp_state.fin_wait2";
288 break;
289 case TCP_TIME_WAIT:
290 name = "flow.end.tcp_state.time_wait";
291 break;
292 case TCP_LAST_ACK:
293 name = "flow.end.tcp_state.last_ack";
294 break;
295 case TCP_CLOSE_WAIT:
296 name = "flow.end.tcp_state.close_wait";
297 break;
298 case TCP_CLOSING:
299 name = "flow.end.tcp_state.closing";
300 break;
301 case TCP_CLOSED:
302 name = "flow.end.tcp_state.closed";
303 break;
304 }
305
307 }
308 fec->flow_tcp_liberal = StatsRegisterCounter("flow.end.tcp_liberal", t);
309}
struct Flow_ Flow
uint16_t StatsRegisterCounter(const char *name, struct ThreadVars_ *tv)
Registers a normal, unqualified counter.
Definition counters.c:952
#define ESP_GET_SPI(esph)
Get the spi field off a packet.
Definition decode-esp.h:29
int ICMPv4GetCounterpart(uint8_t type)
int ICMPv6GetCounterpart(uint8_t type)
#define IPV4_GET_RAW_IPTTL(ip4h)
#define IPV6_GET_RAW_HLIM(ip6h)
Definition decode-ipv6.h:67
uint8_t proto
Data structures and function prototypes for keeping state for the detection engine.
void SCFlowRunInitCallbacks(ThreadVars *tv, Flow *f, const Packet *p)
@ FLOW_PROTO_UDP
@ FLOW_PROTO_DEFAULT
@ FLOW_PROTO_TCP
@ FLOW_PROTO_ICMP
void * FlowGetStorageById(const Flow *f, FlowStorageId id)
int FlowSetStorageById(Flow *f, FlowStorageId id, void *ptr)
FlowStorageId FlowStorageRegister(const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void(*Free)(void *))
unsigned int FlowStorageSize(void)
FlowStorageId g_bypass_info_id
Definition flow-util.c:220
uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
Definition flow-util.c:113
Flow * FlowAlloc(void)
allocate a flow
Definition flow-util.c:56
void FlowEndCountersRegister(ThreadVars *t, FlowEndCounters *fec)
Definition flow-util.c:246
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition flow-util.c:99
void RegisterFlowBypassInfo(void)
Definition flow-util.c:240
void FlowInit(ThreadVars *tv, Flow *f, const Packet *p)
Definition flow-util.c:147
FlowStorageId GetFlowBypassInfoID(void)
Definition flow-util.c:222
void FlowFree(Flow *f)
cleanup & free the memory of a flow
Definition flow-util.c:84
#define FLOW_CHECK_MEMCAP(size)
check if a memory alloc would fit in the memcap
Definition flow-util.h:134
#define FLOW_INITIALIZE(f)
Definition flow-util.h:38
#define FLOW_DESTROY(f)
Definition flow-util.h:119
#define FLOW_STATE_SIZE
Definition flow.h:515
#define FLOW_SET_IPV4_SRC_ADDR_FROM_PACKET(ip4h, a)
Definition flow.h:198
@ FLOW_STATE_LOCAL_BYPASSED
Definition flow.h:507
@ FLOW_STATE_NEW
Definition flow.h:504
@ FLOW_STATE_CLOSED
Definition flow.h:506
@ FLOW_STATE_ESTABLISHED
Definition flow.h:505
#define FLOW_SET_IPV6_SRC_ADDR_FROM_PACKET(ip6h, a)
Definition flow.h:216
#define FLOW_SET_IPV4_DST_ADDR_FROM_PACKET(ip4h, a)
Definition flow.h:206
#define FLOW_SET_IPV6_DST_ADDR_FROM_PACKET(ip6h, a)
Definition flow.h:224
uint16_t FlowThreadId
Definition flow.h:333
#define FLOW_IPV6
Definition flow.h:102
#define FLOW_IPV4
Definition flow.h:100
ThreadVars * tv
@ TCP_ESTABLISHED
@ TCP_SYN_RECV
@ TCP_LAST_ACK
@ TCP_CLOSE_WAIT
@ TCP_CLOSING
@ TCP_CLOSED
@ TCP_FIN_WAIT2
@ TCP_TIME_WAIT
@ TCP_SYN_SENT
@ TCP_FIN_WAIT1
void(* BypassFree)(void *data)
Definition flow.h:531
void * bypass_data
Definition flow.h:532
uint16_t flow_tcp_liberal
Definition flow-util.h:149
uint16_t flow_tcp_state[TCP_CLOSED+1]
Definition flow-util.h:148
uint16_t flow_state[FLOW_STATE_SIZE]
Definition flow-util.h:147
Flow data structure.
Definition flow.h:356
struct Flow_::@129::@135 icmp_s
Port dp
Definition flow.h:372
uint8_t proto
Definition flow.h:378
uint32_t flags
Definition flow.h:421
uint8_t min_ttl_toserver
Definition flow.h:467
uint8_t max_ttl_toserver
Definition flow.h:468
uint32_t timeout_policy
Definition flow.h:405
uint8_t vlan_idx
Definition flow.h:382
uint16_t vlan_id[VLAN_MAX_LAYERS]
Definition flow.h:380
struct LiveDevice_ * livedev
Definition flow.h:398
uint8_t protomap
Definition flow.h:445
struct Flow_::@131::@137 icmp_d
uint8_t code
Definition flow.h:364
struct Flow_::@129::@136 esp
FlowThreadId thread_id[2]
Definition flow.h:394
uint32_t spi
Definition flow.h:368
FlowAddress src
Definition flow.h:359
Port sp
Definition flow.h:361
uint8_t recursion_level
Definition flow.h:379
FlowAddress dst
Definition flow.h:359
uint8_t type
Definition flow.h:363
SCTime_t startts
Definition flow.h:493
struct Packet_::@33::@40 icmp_s
SCTime_t ts
Definition decode.h:555
Port sp
Definition decode.h:508
uint8_t code
Definition decode.h:512
uint8_t recursion_level
Definition decode.h:526
uint8_t type
Definition decode.h:511
uint16_t vlan_id[VLAN_MAX_LAYERS]
Definition decode.h:528
struct LiveDevice_ * livedev
Definition decode.h:618
uint8_t vlan_idx
Definition decode.h:529
uint8_t proto
Definition decode.h:523
Port dp
Definition decode.h:516
Per thread variable structure.
Definition threadvars.h:58
const char * name
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
#define SCEnter(...)
Definition util-debug.h:277
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturn
Definition util-debug.h:279
FlowStorageId FlowRateGetStorageID(void)
FlowRateStore * FlowRateStoreInit(void)
bool FlowRateStorageEnabled(void)
FlowStorageId MacSetGetFlowStorageID(void)
MacSet * MacSetInit(int size)
Definition util-macset.c:92
bool MacSetFlowStorageEnabled(void)
Definition util-macset.c:86
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define unlikely(expr)
#define DEBUG_VALIDATE_BUG_ON(exp)