suricata
decode-gre.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  * \ingroup decode
20  *
21  * @{
22  */
23 
24 
25 /**
26  * \file
27  *
28  * \author Breno Silva <breno.silva@gmail.com>
29  *
30  * Decodes GRE
31  */
32 
33 #include "suricata-common.h"
34 #include "suricata.h"
35 #include "decode.h"
36 #include "decode-events.h"
37 #include "decode-gre.h"
38 
39 #include "util-unittest.h"
40 #include "util-debug.h"
41 
42 /**
43  * \brief Function to decode GRE packets
44  */
45 
46 int DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
47 {
48  uint32_t header_len = GRE_HDR_LEN;
49  GRESreHdr *gsre = NULL;
50 
51  StatsIncr(tv, dtv->counter_gre);
52 
53  if(len < GRE_HDR_LEN) {
55  return TM_ECODE_FAILED;
56  }
57 
58  p->greh = (GREHdr *)pkt;
59  if(p->greh == NULL)
60  return TM_ECODE_FAILED;
61 
62  SCLogDebug("p %p pkt %p GRE protocol %04x Len: %d GRE version %x",
63  p, pkt, GRE_GET_PROTO(p->greh), len,GRE_GET_VERSION(p->greh));
64 
65  switch (GRE_GET_VERSION(p->greh))
66  {
67  case GRE_VERSION_0:
68 
69  /* GRE version 0 doenst support the fields below RFC 1701 */
70 
71  /**
72  * \todo We need to make sure this does not allow bypassing
73  * inspection. A server may just ignore these and
74  * continue processing the packet, but we will not look
75  * further into it.
76  */
77 
78  if (GRE_FLAG_ISSET_RECUR(p->greh)) {
80  return TM_ECODE_OK;
81  }
82 
83  if (GREV1_FLAG_ISSET_FLAGS(p->greh)) {
85  return TM_ECODE_OK;
86  }
87 
88  /* Adjust header length based on content */
89 
90  if (GRE_FLAG_ISSET_KY(p->greh))
91  header_len += GRE_KEY_LEN;
92 
93  if (GRE_FLAG_ISSET_SQ(p->greh))
94  header_len += GRE_SEQ_LEN;
95 
97  header_len += GRE_CHKSUM_LEN + GRE_OFFSET_LEN;
98 
99  if (header_len > len) {
101  return TM_ECODE_OK;
102  }
103 
104  if (GRE_FLAG_ISSET_ROUTE(p->greh))
105  {
106  while (1)
107  {
108  if ((header_len + GRE_SRE_HDR_LEN) > len) {
111  return TM_ECODE_OK;
112  }
113 
114  gsre = (GRESreHdr *)(pkt + header_len);
115 
116  header_len += GRE_SRE_HDR_LEN;
117 
118  if ((SCNtohs(gsre->af) == 0) && (gsre->sre_length == 0))
119  break;
120 
121  header_len += gsre->sre_length;
122  if (header_len > len) {
125  return TM_ECODE_OK;
126  }
127  }
128  }
129  break;
130 
131  case GRE_VERSION_1:
132 
133  /* GRE version 1 doenst support the fields below RFC 1701 */
134 
135  /**
136  * \todo We need to make sure this does not allow bypassing
137  * inspection. A server may just ignore these and
138  * continue processing the packet, but we will not look
139  * further into it.
140  */
141 
142  if (GRE_FLAG_ISSET_CHKSUM(p->greh)) {
144  return TM_ECODE_OK;
145  }
146 
147  if (GRE_FLAG_ISSET_ROUTE(p->greh)) {
149  return TM_ECODE_OK;
150  }
151 
152  if (GRE_FLAG_ISSET_SSR(p->greh)) {
154  return TM_ECODE_OK;
155  }
156 
157  if (GRE_FLAG_ISSET_RECUR(p->greh)) {
159  return TM_ECODE_OK;
160  }
161 
162  if (GREV1_FLAG_ISSET_FLAGS(p->greh)) {
164  return TM_ECODE_OK;
165  }
166 
167  if (GRE_GET_PROTO(p->greh) != GRE_PROTO_PPP) {
169  return TM_ECODE_OK;
170  }
171 
172  if (!(GRE_FLAG_ISSET_KY(p->greh))) {
174  return TM_ECODE_OK;
175  }
176 
177  header_len += GRE_KEY_LEN;
178 
179  /* Adjust header length based on content */
180 
181  if (GRE_FLAG_ISSET_SQ(p->greh))
182  header_len += GRE_SEQ_LEN;
183 
184  if (GREV1_FLAG_ISSET_ACK(p->greh))
185  header_len += GREV1_ACK_LEN;
186 
187  if (header_len > len) {
189  return TM_ECODE_OK;
190  }
191 
192  break;
193  default:
195  return TM_ECODE_OK;
196  }
197 
198  switch (GRE_GET_PROTO(p->greh))
199  {
200  case ETHERNET_TYPE_IP:
201  {
202  if (pq != NULL) {
203  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
204  len - header_len, DECODE_TUNNEL_IPV4, pq);
205  if (tp != NULL) {
207  PacketEnqueue(pq,tp);
208  }
209  }
210  break;
211  }
212 
213  case GRE_PROTO_PPP:
214  {
215  if (pq != NULL) {
216  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
217  len - header_len, DECODE_TUNNEL_PPP, pq);
218  if (tp != NULL) {
220  PacketEnqueue(pq,tp);
221  }
222  }
223  break;
224  }
225 
226  case ETHERNET_TYPE_IPV6:
227  {
228  if (pq != NULL) {
229  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
230  len - header_len, DECODE_TUNNEL_IPV6, pq);
231  if (tp != NULL) {
233  PacketEnqueue(pq,tp);
234  }
235  }
236  break;
237  }
238 
239  case ETHERNET_TYPE_VLAN:
240  {
241  if (pq != NULL) {
242  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
243  len - header_len, DECODE_TUNNEL_VLAN, pq);
244  if (tp != NULL) {
246  PacketEnqueue(pq,tp);
247  }
248  }
249  break;
250  }
251 
253  {
254  if (pq != NULL) {
255  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
256  len - header_len, DECODE_TUNNEL_ERSPAN, pq);
257  if (tp != NULL) {
259  PacketEnqueue(pq,tp);
260  }
261  }
262  break;
263  }
264 
266  {
267  if (pq != NULL) {
268  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
269  len - header_len, DECODE_TUNNEL_ETHERNET, pq);
270  if (tp != NULL) {
272  PacketEnqueue(pq,tp);
273  }
274  }
275  break;
276  }
277 
278  default:
279  return TM_ECODE_OK;
280  }
281  return TM_ECODE_OK;
282 }
283 
284 
285 #ifdef UNITTESTS
286 /**
287  * \test DecodeGRETest01 is a test for small gre packet
288  */
289 
290 static int DecodeGREtest01 (void)
291 {
292 
293  uint8_t raw_gre[] = { 0x00 ,0x6e ,0x62 };
294  Packet *p = PacketGetFromAlloc();
295  if (unlikely(p == NULL))
296  return 0;
297  ThreadVars tv;
298  DecodeThreadVars dtv;
299 
300  memset(&tv, 0, sizeof(ThreadVars));
301  memset(&dtv, 0, sizeof(DecodeThreadVars));
302 
303  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre), NULL);
304 
306  SCFree(p);
307  return 1;
308  }
309 
310  SCFree(p);
311  return 0;
312 }
313 
314 /**
315  * \test DecodeGRETest02 is a test for wrong gre version
316  */
317 
318 static int DecodeGREtest02 (void)
319 {
320  uint8_t raw_gre[] = {
321  0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
322  0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
323  0x00, 0x8a, 0x30, 0x01, 0x0b, 0x00, 0x4e, 0x00,
324  0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03, 0x00,
325  0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x40,
326  0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e, 0x2b,
327  0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e, 0x00,
328  0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4, 0x01,
329  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
330  0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73, 0x69,
331  0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x03,
332  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
333  0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00,
334  0x00, 0x00, 0x00 };
335  Packet *p = PacketGetFromAlloc();
336  if (unlikely(p == NULL))
337  return 0;
338  ThreadVars tv;
339  DecodeThreadVars dtv;
340 
341  memset(&tv, 0, sizeof(ThreadVars));
342  memset(&dtv, 0, sizeof(DecodeThreadVars));
343 
344  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre), NULL);
345 
347  SCFree(p);
348  return 1;
349  }
350 
351  SCFree(p);
352  return 0;
353 }
354 
355 
356 /**
357  * \test DecodeGRETest03 is a test for valid gre packet
358  */
359 
360 static int DecodeGREtest03 (void)
361 {
362  uint8_t raw_gre[] = {
363  0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
364  0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
365  0x00, 0x8a, 0x30, 0x01, 0x88, 0x0b, 0x00, 0x4e,
366  0x00, 0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03,
367  0x00, 0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00,
368  0x40, 0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e,
369  0x2b, 0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e,
370  0x00, 0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4,
371  0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
372  0x00, 0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73,
373  0x69, 0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72,
374  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
375  0x01, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00,
376  0x00, 0x00, 0x00, 0x00 };
377  Packet *p = PacketGetFromAlloc();
378  if (unlikely(p == NULL))
379  return 0;
380  ThreadVars tv;
381  DecodeThreadVars dtv;
382 
383  memset(&tv, 0, sizeof(ThreadVars));
384  memset(&dtv, 0, sizeof(DecodeThreadVars));
385 
386  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre), NULL);
387 
388  if(p->greh == NULL) {
389  SCFree(p);
390  return 0;
391  }
392 
393 
394  SCFree(p);
395  return 1;
396 }
397 #endif /* UNITTESTS */
398 
399 /**
400  * \brief this function registers unit tests for GRE decoder
401  */
402 
404 {
405 #ifdef UNITTESTS
406  UtRegisterTest("DecodeGREtest01", DecodeGREtest01);
407  UtRegisterTest("DecodeGREtest02", DecodeGREtest02);
408  UtRegisterTest("DecodeGREtest03", DecodeGREtest03);
409 #endif /* UNITTESTS */
410 }
411 /**
412  * @}
413  */
#define GRE_FLAG_ISSET_ROUTE(r)
Definition: decode-gre.h:66
#define GRE_GET_VERSION(r)
Definition: decode-gre.h:71
#define GRE_VERSION_1
Definition: decode-gre.h:55
#define GREV1_ACK_LEN
Definition: decode-gre.h:76
#define SCLogDebug(...)
Definition: util-debug.h:335
#define ENGINE_ISSET_EVENT(p, e)
Definition: decode.h:1015
int DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
Function to decode GRE packets.
Definition: decode-gre.c:46
#define GRE_FLAG_ISSET_CHKSUM(r)
Definition: decode-gre.h:65
#define unlikely(expr)
Definition: util-optimize.h:35
#define GRE_HDR_LEN
Definition: decode-gre.h:57
#define ETHERNET_TYPE_VLAN
Definition: decode-vlan.h:31
#define ETHERNET_TYPE_BRIDGE
#define ETHERNET_TYPE_ERSPAN
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1143
#define GREV1_FLAG_ISSET_FLAGS(r)
Definition: decode-gre.h:77
#define ETHERNET_TYPE_IP
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Structure to hold thread specific data for all decode modules.
Definition: decode.h:642
#define GRE_OFFSET_LEN
Definition: decode-gre.h:59
#define GRE_KEY_LEN
Definition: decode-gre.h:60
#define GRE_VERSION_0
Definition: decode-gre.h:54
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:163
#define GRE_FLAG_ISSET_SQ(r)
Definition: decode-gre.h:68
#define GRE_SRE_HDR_LEN
Definition: decode-gre.h:62
#define GRE_CHKSUM_LEN
Definition: decode-gre.h:58
void DecodeGRERegisterTests(void)
this function registers unit tests for GRE decoder
Definition: decode-gre.c:403
#define SCFree(a)
Definition: util-mem.h:236
#define SCNtohs(x)
#define GRE_PROTO_PPP
Definition: decode-gre.h:63
#define GRE_SEQ_LEN
Definition: decode-gre.h:61
uint16_t counter_gre
Definition: decode.h:670
#define GREV1_FLAG_ISSET_ACK(r)
Definition: decode-gre.h:78
#define GRE_FLAG_ISSET_KY(r)
Definition: decode-gre.h:67
#define GRE_FLAG_ISSET_SSR(r)
Definition: decode-gre.h:69
uint8_t len
Per thread variable structure.
Definition: threadvars.h:57
#define ETHERNET_TYPE_IPV6
#define GRE_GET_PROTO(r)
Definition: decode-gre.h:73
Packet * PacketTunnelPktSetup(ThreadVars *tv, DecodeThreadVars *dtv, Packet *parent, uint8_t *pkt, uint32_t len, enum DecodeTunnelProto proto, PacketQueue *pq)
Setup a pseudo packet (tunnel)
Definition: decode.c:274
GREHdr * greh
Definition: decode.h:539
void PacketEnqueue(PacketQueue *q, Packet *p)
Definition: packet-queue.c:139
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:1008
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:140
#define GRE_FLAG_ISSET_RECUR(r)
Definition: decode-gre.h:70