suricata
decode-gre.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2021 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-validate.h"
40 #include "util-unittest.h"
41 #include "util-debug.h"
42 
43 /**
44  * \brief Function to decode GRE packets
45  */
46 
47 int DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
48 {
49  DEBUG_VALIDATE_BUG_ON(pkt == NULL);
50 
51  uint32_t header_len = GRE_HDR_LEN;
52  GRESreHdr *gsre = NULL;
53 
55 
56  if(len < GRE_HDR_LEN) {
58  return TM_ECODE_FAILED;
59  }
60  if (!PacketIncreaseCheckLayers(p)) {
61  return TM_ECODE_FAILED;
62  }
63 
64  p->greh = (GREHdr *)pkt;
65 
66  SCLogDebug("p %p pkt %p GRE protocol %04x Len: %d GRE version %x",
67  p, pkt, GRE_GET_PROTO(p->greh), len,GRE_GET_VERSION(p->greh));
68 
69  switch (GRE_GET_VERSION(p->greh))
70  {
71  case GRE_VERSION_0:
72 
73  /* GRE version 0 doesn't support the fields below RFC 1701 */
74 
75  /**
76  * \todo We need to make sure this does not allow bypassing
77  * inspection. A server may just ignore these and
78  * continue processing the packet, but we will not look
79  * further into it.
80  */
81 
82  if (GRE_FLAG_ISSET_RECUR(p->greh)) {
84  return TM_ECODE_OK;
85  }
86 
87  if (GREV1_FLAG_ISSET_FLAGS(p->greh)) {
89  return TM_ECODE_OK;
90  }
91 
92  /* Adjust header length based on content */
93 
94  if (GRE_FLAG_ISSET_KY(p->greh))
95  header_len += GRE_KEY_LEN;
96 
97  if (GRE_FLAG_ISSET_SQ(p->greh))
98  header_len += GRE_SEQ_LEN;
99 
101  header_len += GRE_CHKSUM_LEN + GRE_OFFSET_LEN;
102 
103  if (header_len > len) {
105  return TM_ECODE_OK;
106  }
107 
108  if (GRE_FLAG_ISSET_ROUTE(p->greh))
109  {
110  while (1)
111  {
112  if ((header_len + GRE_SRE_HDR_LEN) > len) {
115  return TM_ECODE_OK;
116  }
117 
118  gsre = (GRESreHdr *)(pkt + header_len);
119 
120  header_len += GRE_SRE_HDR_LEN;
121 
122  if ((SCNtohs(gsre->af) == 0) && (gsre->sre_length == 0))
123  break;
124 
125  header_len += gsre->sre_length;
126  if (header_len > len) {
129  return TM_ECODE_OK;
130  }
131  }
132  }
133  break;
134 
135  case GRE_VERSION_1:
136 
137  /* GRE version 1 doesn't support the fields below RFC 1701 */
138 
139  /**
140  * \todo We need to make sure this does not allow bypassing
141  * inspection. A server may just ignore these and
142  * continue processing the packet, but we will not look
143  * further into it.
144  */
145 
146  if (GRE_FLAG_ISSET_CHKSUM(p->greh)) {
148  return TM_ECODE_OK;
149  }
150 
151  if (GRE_FLAG_ISSET_ROUTE(p->greh)) {
153  return TM_ECODE_OK;
154  }
155 
156  if (GRE_FLAG_ISSET_SSR(p->greh)) {
158  return TM_ECODE_OK;
159  }
160 
161  if (GRE_FLAG_ISSET_RECUR(p->greh)) {
163  return TM_ECODE_OK;
164  }
165 
166  if (GREV1_FLAG_ISSET_FLAGS(p->greh)) {
168  return TM_ECODE_OK;
169  }
170 
171  if (GRE_GET_PROTO(p->greh) != GRE_PROTO_PPP) {
173  return TM_ECODE_OK;
174  }
175 
176  if (!(GRE_FLAG_ISSET_KY(p->greh))) {
178  return TM_ECODE_OK;
179  }
180 
181  header_len += GRE_KEY_LEN;
182 
183  /* Adjust header length based on content */
184 
185  if (GRE_FLAG_ISSET_SQ(p->greh))
186  header_len += GRE_SEQ_LEN;
187 
188  if (GREV1_FLAG_ISSET_ACK(p->greh))
189  header_len += GREV1_ACK_LEN;
190 
191  if (header_len > len) {
193  return TM_ECODE_OK;
194  }
195 
196  break;
197  default:
199  return TM_ECODE_OK;
200  }
201 
202  switch (GRE_GET_PROTO(p->greh))
203  {
204  case ETHERNET_TYPE_IP:
205  {
206  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
207  len - header_len, DECODE_TUNNEL_IPV4);
208  if (tp != NULL) {
211  }
212  break;
213  }
214 
215  case GRE_PROTO_PPP:
216  {
217  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
218  len - header_len, DECODE_TUNNEL_PPP);
219  if (tp != NULL) {
222  }
223  break;
224  }
225 
226  case ETHERNET_TYPE_IPV6:
227  {
228  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
229  len - header_len, DECODE_TUNNEL_IPV6);
230  if (tp != NULL) {
233  }
234  break;
235  }
236 
237  case ETHERNET_TYPE_VLAN:
238  {
239  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
240  len - header_len, DECODE_TUNNEL_VLAN);
241  if (tp != NULL) {
244  }
245  break;
246  }
247 
249  {
250  // Determine if it's Type I or Type II based on the flags in the GRE header.
251  // Type I: 0|0|0|0|0|00000|000000000|00000
252  // Type II: 0|0|0|1|0|00000|000000000|00000
253  // Seq
254  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
255  len - header_len,
256  GRE_FLAG_ISSET_SQ(p->greh) == 0 ?
259  if (tp != NULL) {
262  }
263  break;
264  }
265 
267  {
268  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
269  len - header_len, DECODE_TUNNEL_ETHERNET);
270  if (tp != NULL) {
273  }
274  break;
275  }
276 
277  default:
278  return TM_ECODE_OK;
279  }
280  return TM_ECODE_OK;
281 }
282 
283 
284 #ifdef UNITTESTS
285 /**
286  * \test DecodeGRETest01 is a test for small gre packet
287  */
288 
289 static int DecodeGREtest01 (void)
290 {
291  uint8_t raw_gre[] = { 0x00 ,0x6e ,0x62 };
292  Packet *p = PacketGetFromAlloc();
293  FAIL_IF_NULL(p);
294  ThreadVars tv;
296 
297  memset(&tv, 0, sizeof(ThreadVars));
298  memset(&dtv, 0, sizeof(DecodeThreadVars));
299 
300  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
302 
303  SCFree(p);
304  PASS;
305 }
306 
307 /**
308  * \test DecodeGRETest02 is a test for wrong gre version
309  */
310 
311 static int DecodeGREtest02 (void)
312 {
313  uint8_t raw_gre[] = {
314  0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
315  0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
316  0x00, 0x8a, 0x30, 0x01, 0x0b, 0x00, 0x4e, 0x00,
317  0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03, 0x00,
318  0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x40,
319  0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e, 0x2b,
320  0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e, 0x00,
321  0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4, 0x01,
322  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
323  0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73, 0x69,
324  0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x03,
325  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
326  0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00,
327  0x00, 0x00, 0x00 };
328  Packet *p = PacketGetFromAlloc();
329  FAIL_IF_NULL(p);
330  ThreadVars tv;
332 
333  memset(&tv, 0, sizeof(ThreadVars));
334  memset(&dtv, 0, sizeof(DecodeThreadVars));
335 
336  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
338 
339  SCFree(p);
340  PASS;
341 }
342 
343 
344 /**
345  * \test DecodeGRETest03 is a test for valid gre packet
346  */
347 
348 static int DecodeGREtest03 (void)
349 {
350  uint8_t raw_gre[] = {
351  0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
352  0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
353  0x00, 0x8a, 0x30, 0x01, 0x88, 0x0b, 0x00, 0x4e,
354  0x00, 0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03,
355  0x00, 0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00,
356  0x40, 0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e,
357  0x2b, 0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e,
358  0x00, 0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4,
359  0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
360  0x00, 0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73,
361  0x69, 0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72,
362  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
363  0x01, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00,
364  0x00, 0x00, 0x00, 0x00 };
365  Packet *p = PacketGetFromAlloc();
366  FAIL_IF_NULL(p);
367  ThreadVars tv;
369 
370  memset(&tv, 0, sizeof(ThreadVars));
371  memset(&dtv, 0, sizeof(DecodeThreadVars));
372 
373  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
374  FAIL_IF_NULL(p->greh);
375 
376  SCFree(p);
377  PASS;
378 }
379 #endif /* UNITTESTS */
380 
381 /**
382  * \brief this function registers unit tests for GRE decoder
383  */
384 
386 {
387 #ifdef UNITTESTS
388  UtRegisterTest("DecodeGREtest01", DecodeGREtest01);
389  UtRegisterTest("DecodeGREtest02", DecodeGREtest02);
390  UtRegisterTest("DecodeGREtest03", DecodeGREtest03);
391 #endif /* UNITTESTS */
392 }
393 /**
394  * @}
395  */
Packet_::greh
GREHdr * greh
Definition: decode.h:549
ETHERNET_TYPE_BRIDGE
#define ETHERNET_TYPE_BRIDGE
Definition: decode-ethernet.h:36
GRE_FLAG_ISSET_CHKSUM
#define GRE_FLAG_ISSET_CHKSUM(r)
Definition: decode-gre.h:65
GRE_FLAG_ISSET_ROUTE
#define GRE_FLAG_ISSET_ROUTE(r)
Definition: decode-gre.h:66
len
uint8_t len
Definition: app-layer-dnp3.h:2
DECODE_TUNNEL_IPV6
@ DECODE_TUNNEL_IPV6
Definition: decode.h:925
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:169
GRE_VERSION1_NO_KEY
@ GRE_VERSION1_NO_KEY
Definition: decode-events.h:138
GREV1_ACK_LEN
#define GREV1_ACK_LEN
Definition: decode-gre.h:76
GRE_VERSION0_HDR_TOO_BIG
@ GRE_VERSION0_HDR_TOO_BIG
Definition: decode-events.h:131
GRE_FLAG_ISSET_RECUR
#define GRE_FLAG_ISSET_RECUR(r)
Definition: decode-gre.h:70
GRE_VERSION1_SSR
@ GRE_VERSION1_SSR
Definition: decode-events.h:135
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
ENGINE_ISSET_EVENT
#define ENGINE_ISSET_EVENT(p, e)
Definition: decode.h:1038
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
GRE_WRONG_VERSION
@ GRE_WRONG_VERSION
Definition: decode-events.h:128
ETHERNET_TYPE_IPV6
#define ETHERNET_TYPE_IPV6
Definition: decode-ethernet.h:39
GRE_HDR_LEN
#define GRE_HDR_LEN
Definition: decode-gre.h:57
DECODE_TUNNEL_ERSPANI
@ DECODE_TUNNEL_ERSPANI
Definition: decode.h:922
ETHERNET_TYPE_ERSPAN
#define ETHERNET_TYPE_ERSPAN
Definition: decode-ethernet.h:48
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:81
GRE_VERSION1_CHKSUM
@ GRE_VERSION1_CHKSUM
Definition: decode-events.h:133
util-unittest.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:80
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1170
GREV1_FLAG_ISSET_FLAGS
#define GREV1_FLAG_ISSET_FLAGS(r)
Definition: decode-gre.h:77
decode-gre.h
DECODE_TUNNEL_ERSPANII
@ DECODE_TUNNEL_ERSPANII
Definition: decode.h:921
decode.h
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
GRE_FLAG_ISSET_SQ
#define GRE_FLAG_ISSET_SQ(r)
Definition: decode-gre.h:68
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
DECODE_TUNNEL_PPP
@ DECODE_TUNNEL_PPP
Definition: decode.h:927
DecodeGRE
int DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Function to decode GRE packets.
Definition: decode-gre.c:47
GRE_VERSION_0
#define GRE_VERSION_0
Definition: decode-gre.h:54
GRE_KEY_LEN
#define GRE_KEY_LEN
Definition: decode-gre.h:60
DECODE_TUNNEL_VLAN
@ DECODE_TUNNEL_VLAN
Definition: decode.h:923
Packet_
Definition: decode.h:416
DECODE_TUNNEL_IPV4
@ DECODE_TUNNEL_IPV4
Definition: decode.h:924
GRE_VERSION1_WRONG_PROTOCOL
@ GRE_VERSION1_WRONG_PROTOCOL
Definition: decode-events.h:139
GRE_VERSION0_MALFORMED_SRE_HDR
@ GRE_VERSION0_MALFORMED_SRE_HDR
Definition: decode-events.h:132
GRE_VERSION1_FLAGS
@ GRE_VERSION1_FLAGS
Definition: decode-events.h:137
DECODE_TUNNEL_ETHERNET
@ DECODE_TUNNEL_ETHERNET
Definition: decode.h:920
GRE_VERSION0_FLAGS
@ GRE_VERSION0_FLAGS
Definition: decode-events.h:130
GRE_OFFSET_LEN
#define GRE_OFFSET_LEN
Definition: decode-gre.h:59
decode-events.h
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:30
GRE_CHKSUM_LEN
#define GRE_CHKSUM_LEN
Definition: decode-gre.h:58
PacketEnqueueNoLock
void PacketEnqueueNoLock(PacketQueueNoLock *qnl, Packet *p)
Definition: packet-queue.c:167
SCNtohs
#define SCNtohs(x)
Definition: suricata-common.h:395
suricata-common.h
GREV1_FLAG_ISSET_ACK
#define GREV1_FLAG_ISSET_ACK(r)
Definition: decode-gre.h:78
DecodeThreadVars_::counter_gre
uint16_t counter_gre
Definition: decode.h:670
GRE_SRE_HDR_LEN
#define GRE_SRE_HDR_LEN
Definition: decode-gre.h:62
GRE_PROTO_PPP
#define GRE_PROTO_PPP
Definition: decode-gre.h:63
GRE_VERSION1_RECUR
@ GRE_VERSION1_RECUR
Definition: decode-events.h:136
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
util-validate.h
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:150
GRE_PKT_TOO_SMALL
@ GRE_PKT_TOO_SMALL
Definition: decode-events.h:127
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:640
DecodeGRERegisterTests
void DecodeGRERegisterTests(void)
this function registers unit tests for GRE decoder
Definition: decode-gre.c:385
GRE_GET_PROTO
#define GRE_GET_PROTO(r)
Definition: decode-gre.h:73
GRE_VERSION0_RECUR
@ GRE_VERSION0_RECUR
Definition: decode-events.h:129
ThreadVars_::decode_pq
PacketQueueNoLock decode_pq
Definition: threadvars.h:110
GRE_FLAG_ISSET_KY
#define GRE_FLAG_ISSET_KY(r)
Definition: decode-gre.h:67
GRE_FLAG_ISSET_SSR
#define GRE_FLAG_ISSET_SSR(r)
Definition: decode-gre.h:69
suricata.h
PKT_SRC_DECODER_GRE
@ PKT_SRC_DECODER_GRE
Definition: decode.h:52
ENGINE_SET_INVALID_EVENT
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:1031
ETHERNET_TYPE_VLAN
#define ETHERNET_TYPE_VLAN
Definition: decode-vlan.h:31
GRE_SEQ_LEN
#define GRE_SEQ_LEN
Definition: decode-gre.h:61
GRE_GET_VERSION
#define GRE_GET_VERSION(r)
Definition: decode-gre.h:71
PacketTunnelPktSetup
Packet * PacketTunnelPktSetup(ThreadVars *tv, DecodeThreadVars *dtv, Packet *parent, const uint8_t *pkt, uint32_t len, enum DecodeTunnelProto proto)
Setup a pseudo packet (tunnel)
Definition: decode.c:285
GRE_VERSION1_HDR_TOO_BIG
@ GRE_VERSION1_HDR_TOO_BIG
Definition: decode-events.h:141
GRE_VERSION_1
#define GRE_VERSION_1
Definition: decode-gre.h:55
ETHERNET_TYPE_IP
#define ETHERNET_TYPE_IP
Definition: decode-ethernet.h:34
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:111
GRE_VERSION1_ROUTE
@ GRE_VERSION1_ROUTE
Definition: decode-events.h:134