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-debug.h"
41 
42 /**
43  * \brief Function to decode GRE packets
44  */
45 
46 int DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
47 {
48  DEBUG_VALIDATE_BUG_ON(pkt == NULL);
49 
50  uint32_t header_len = GRE_HDR_LEN;
51  GRESreHdr *gsre = NULL;
52  GREPPtPHd *gre_pptp_h = 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  GREHdr *greh = PacketSetGRE(p, pkt);
65 
66  SCLogDebug("p %p pkt %p GRE protocol %04x Len: %d GRE version %x", p, pkt, GRE_GET_PROTO(greh),
68 
69  switch (GRE_GET_VERSION(greh)) {
70  case GRE_VERSION_0:
71 
72  /* GRE version 0 doesn't support the fields below RFC 1701 */
73 
74  /**
75  * \todo We need to make sure this does not allow bypassing
76  * inspection. A server may just ignore these and
77  * continue processing the packet, but we will not look
78  * further into it.
79  */
80 
83  return TM_ECODE_OK;
84  }
85 
88  return TM_ECODE_OK;
89  }
90 
91  /* Adjust header length based on content */
92 
94  header_len += GRE_KEY_LEN;
95 
97  header_len += GRE_SEQ_LEN;
98 
100  header_len += GRE_CHKSUM_LEN + GRE_OFFSET_LEN;
101 
102  if (header_len > len) {
104  return TM_ECODE_OK;
105  }
106 
107  if (GRE_FLAG_ISSET_ROUTE(greh)) {
108  while (1)
109  {
110  if ((header_len + GRE_SRE_HDR_LEN) > len) {
113  return TM_ECODE_OK;
114  }
115 
116  gsre = (GRESreHdr *)(pkt + header_len);
117 
118  header_len += GRE_SRE_HDR_LEN;
119 
120  if ((SCNtohs(gsre->af) == 0) && (gsre->sre_length == 0))
121  break;
122 
123  header_len += gsre->sre_length;
124  if (header_len > len) {
127  return TM_ECODE_OK;
128  }
129  }
130  }
131  break;
132 
133  case GRE_VERSION_1:
134 
135  /* GRE version 1 doesn't support the fields below RFC 1701 */
136 
137  /**
138  * \todo We need to make sure this does not allow bypassing
139  * inspection. A server may just ignore these and
140  * continue processing the packet, but we will not look
141  * further into it.
142  */
143 
146  return TM_ECODE_OK;
147  }
148 
149  if (GRE_FLAG_ISSET_ROUTE(greh)) {
151  return TM_ECODE_OK;
152  }
153 
154  if (GRE_FLAG_ISSET_SSR(greh)) {
156  return TM_ECODE_OK;
157  }
158 
159  if (GRE_FLAG_ISSET_RECUR(greh)) {
161  return TM_ECODE_OK;
162  }
163 
166  return TM_ECODE_OK;
167  }
168 
169  if (GRE_GET_PROTO(greh) != GRE_PROTO_PPP) {
171  return TM_ECODE_OK;
172  }
173 
174  if (!(GRE_FLAG_ISSET_KY(greh))) {
176  return TM_ECODE_OK;
177  }
178 
179  header_len += GRE_KEY_LEN;
180  /* key is set and proto == PPP */
181  gre_pptp_h = (GREPPtPHd *)pkt;
182 
183  /* Adjust header length based on content */
184 
185  if (GRE_FLAG_ISSET_SQ(greh))
186  header_len += GRE_SEQ_LEN;
187 
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(greh)) {
203  case ETHERNET_TYPE_IP:
204  {
205  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
206  len - header_len, DECODE_TUNNEL_IPV4);
207  if (tp != NULL) {
210  }
211  break;
212  }
213 
214  case GRE_PROTO_PPP:
215  {
216  if (gre_pptp_h && !gre_pptp_h->payload_length)
217  return TM_ECODE_OK;
218 
219  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
220  len - header_len, DECODE_TUNNEL_PPP);
221  if (tp != NULL) {
224  }
225  break;
226  }
227 
228  case ETHERNET_TYPE_IPV6:
229  {
230  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
231  len - header_len, DECODE_TUNNEL_IPV6);
232  if (tp != NULL) {
235  }
236  break;
237  }
238 
239  case ETHERNET_TYPE_VLAN:
240  {
241  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
242  len - header_len, DECODE_TUNNEL_VLAN);
243  if (tp != NULL) {
246  }
247  break;
248  }
249 
251  {
252  // Determine if it's Type I or Type II based on the flags in the GRE header.
253  // Type I: 0|0|0|0|0|00000|000000000|00000
254  // Type II: 0|0|0|1|0|00000|000000000|00000
255  // Seq
256  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len, len - header_len,
258  if (tp != NULL) {
261  }
262  break;
263  }
264 
266  {
267  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
268  len - header_len, DECODE_TUNNEL_ETHERNET);
269  if (tp != NULL) {
272  }
273  break;
274  }
275 
276  case ETHERNET_TYPE_ARP: {
278  tv, dtv, p, pkt + header_len, len - header_len, DECODE_TUNNEL_ARP);
279  if (tp != NULL) {
282  }
283  break;
284  }
285 
286  default:
287  return TM_ECODE_OK;
288  }
289  return TM_ECODE_OK;
290 }
291 
292 
293 #ifdef UNITTESTS
294 /**
295  * \test DecodeGRETest01 is a test for small gre packet
296  */
297 
298 static int DecodeGREtest01 (void)
299 {
300  uint8_t raw_gre[] = { 0x00 ,0x6e ,0x62 };
302  FAIL_IF_NULL(p);
303  ThreadVars tv;
305 
306  memset(&tv, 0, sizeof(ThreadVars));
307  memset(&dtv, 0, sizeof(DecodeThreadVars));
308 
309  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
311 
312  PacketFree(p);
313  PASS;
314 }
315 
316 /**
317  * \test DecodeGRETest02 is a test for wrong gre version
318  */
319 
320 static int DecodeGREtest02 (void)
321 {
322  uint8_t raw_gre[] = {
323  0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
324  0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
325  0x00, 0x8a, 0x30, 0x01, 0x0b, 0x00, 0x4e, 0x00,
326  0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03, 0x00,
327  0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x40,
328  0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e, 0x2b,
329  0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e, 0x00,
330  0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4, 0x01,
331  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
332  0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73, 0x69,
333  0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x03,
334  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
335  0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00,
336  0x00, 0x00, 0x00 };
338  FAIL_IF_NULL(p);
339  ThreadVars tv;
341 
342  memset(&tv, 0, sizeof(ThreadVars));
343  memset(&dtv, 0, sizeof(DecodeThreadVars));
344 
345  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
347 
348  PacketFree(p);
349  PASS;
350 }
351 
352 
353 /**
354  * \test DecodeGRETest03 is a test for valid gre packet
355  */
356 
357 static int DecodeGREtest03 (void)
358 {
359  uint8_t raw_gre[] = {
360  0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
361  0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
362  0x00, 0x8a, 0x30, 0x01, 0x88, 0x0b, 0x00, 0x4e,
363  0x00, 0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03,
364  0x00, 0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00,
365  0x40, 0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e,
366  0x2b, 0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e,
367  0x00, 0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4,
368  0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
369  0x00, 0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73,
370  0x69, 0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72,
371  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
372  0x01, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00,
373  0x00, 0x00, 0x00, 0x00 };
375  FAIL_IF_NULL(p);
376  ThreadVars tv;
378 
379  memset(&tv, 0, sizeof(ThreadVars));
380  memset(&dtv, 0, sizeof(DecodeThreadVars));
381 
382  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
383  FAIL_IF_NOT(PacketIsGRE(p));
384 
385  PacketFree(p);
386  PASS;
387 }
388 #endif /* UNITTESTS */
389 
390 /**
391  * \brief this function registers unit tests for GRE decoder
392  */
393 
395 {
396 #ifdef UNITTESTS
397  UtRegisterTest("DecodeGREtest01", DecodeGREtest01);
398  UtRegisterTest("DecodeGREtest02", DecodeGREtest02);
399  UtRegisterTest("DecodeGREtest03", DecodeGREtest03);
400 #endif /* UNITTESTS */
401 }
402 /**
403  * @}
404  */
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:70
GRE_VERSION1_FLAGS
@ GRE_VERSION1_FLAGS
Definition: decode-events.h:146
GRE_FLAG_ISSET_ROUTE
#define GRE_FLAG_ISSET_ROUTE(r)
Definition: decode-gre.h:71
len
uint8_t len
Definition: app-layer-dnp3.h:2
DECODE_TUNNEL_IPV6
@ DECODE_TUNNEL_IPV6
Definition: decode.h:1150
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
GREV1_ACK_LEN
#define GREV1_ACK_LEN
Definition: decode-gre.h:81
GRE_FLAG_ISSET_RECUR
#define GRE_FLAG_ISSET_RECUR(r)
Definition: decode-gre.h:75
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:101
ENGINE_ISSET_EVENT
#define ENGINE_ISSET_EVENT(p, e)
Definition: decode.h:1244
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
DecodeThreadVars_::counter_gre
StatsCounterId counter_gre
Definition: decode.h:1038
ETHERNET_TYPE_IPV6
#define ETHERNET_TYPE_IPV6
Definition: decode-ethernet.h:39
GRE_HDR_LEN
#define GRE_HDR_LEN
Definition: decode-gre.h:62
GRE_VERSION1_WRONG_PROTOCOL
@ GRE_VERSION1_WRONG_PROTOCOL
Definition: decode-events.h:148
GRE_VERSION1_ROUTE
@ GRE_VERSION1_ROUTE
Definition: decode-events.h:143
DECODE_TUNNEL_ERSPANI
@ DECODE_TUNNEL_ERSPANI
Definition: decode.h:1146
p
Packet * p
Definition: fuzz_dataset.c:30
ETHERNET_TYPE_ERSPAN
#define ETHERNET_TYPE_ERSPAN
Definition: decode-ethernet.h:48
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
GRE_VERSION1_SSR
@ GRE_VERSION1_SSR
Definition: decode-events.h:144
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
GRE_WRONG_VERSION
@ GRE_WRONG_VERSION
Definition: decode-events.h:137
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1366
GREV1_FLAG_ISSET_FLAGS
#define GREV1_FLAG_ISSET_FLAGS(r)
Definition: decode-gre.h:82
decode-gre.h
DECODE_TUNNEL_ERSPANII
@ DECODE_TUNNEL_ERSPANII
Definition: decode.h:1145
decode.h
GRE_VERSION1_RECUR
@ GRE_VERSION1_RECUR
Definition: decode-events.h:145
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:73
GRE_VERSION1_CHKSUM
@ GRE_VERSION1_CHKSUM
Definition: decode-events.h:142
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
DECODE_TUNNEL_PPP
@ DECODE_TUNNEL_PPP
Definition: decode.h:1152
StatsCounterIncr
void StatsCounterIncr(StatsThreadContext *stats, StatsCounterId id)
Increments the local counter.
Definition: counters.c:163
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:46
PacketFree
void PacketFree(Packet *p)
Return a malloced packet.
Definition: decode.c:221
GRE_VERSION_0
#define GRE_VERSION_0
Definition: decode-gre.h:59
GRE_KEY_LEN
#define GRE_KEY_LEN
Definition: decode-gre.h:65
DECODE_TUNNEL_VLAN
@ DECODE_TUNNEL_VLAN
Definition: decode.h:1148
Packet_
Definition: decode.h:516
DECODE_TUNNEL_IPV4
@ DECODE_TUNNEL_IPV4
Definition: decode.h:1149
DECODE_TUNNEL_ETHERNET
@ DECODE_TUNNEL_ETHERNET
Definition: decode.h:1144
GRE_OFFSET_LEN
#define GRE_OFFSET_LEN
Definition: decode-gre.h:64
decode-events.h
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:35
GRE_VERSION1_HDR_TOO_BIG
@ GRE_VERSION1_HDR_TOO_BIG
Definition: decode-events.h:150
GRE_VERSION1_NO_KEY
@ GRE_VERSION1_NO_KEY
Definition: decode-events.h:147
GRE_CHKSUM_LEN
#define GRE_CHKSUM_LEN
Definition: decode-gre.h:63
PacketEnqueueNoLock
void PacketEnqueueNoLock(PacketQueueNoLock *qnl, Packet *p)
Definition: packet-queue.c:168
SCNtohs
#define SCNtohs(x)
Definition: suricata-common.h:436
suricata-common.h
GREV1_FLAG_ISSET_ACK
#define GREV1_FLAG_ISSET_ACK(r)
Definition: decode-gre.h:83
GRE_VERSION0_HDR_TOO_BIG
@ GRE_VERSION0_HDR_TOO_BIG
Definition: decode-events.h:140
GRE_SRE_HDR_LEN
#define GRE_SRE_HDR_LEN
Definition: decode-gre.h:67
GRE_PROTO_PPP
#define GRE_PROTO_PPP
Definition: decode-gre.h:68
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:34
util-validate.h
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:260
GRE_VERSION0_MALFORMED_SRE_HDR
@ GRE_VERSION0_MALFORMED_SRE_HDR
Definition: decode-events.h:141
GRE_VERSION0_FLAGS
@ GRE_VERSION0_FLAGS
Definition: decode-events.h:139
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:995
DecodeGRERegisterTests
void DecodeGRERegisterTests(void)
this function registers unit tests for GRE decoder
Definition: decode-gre.c:394
GRE_GET_PROTO
#define GRE_GET_PROTO(r)
Definition: decode-gre.h:78
greh
GREHdr greh
Definition: decode-gre.h:0
GRE_PKT_TOO_SMALL
@ GRE_PKT_TOO_SMALL
Definition: decode-events.h:136
ETHERNET_TYPE_ARP
#define ETHERNET_TYPE_ARP
Definition: decode-ethernet.h:35
ThreadVars_::decode_pq
PacketQueueNoLock decode_pq
Definition: threadvars.h:110
GRE_FLAG_ISSET_KY
#define GRE_FLAG_ISSET_KY(r)
Definition: decode-gre.h:72
GRE_FLAG_ISSET_SSR
#define GRE_FLAG_ISSET_SSR(r)
Definition: decode-gre.h:74
suricata.h
PKT_SRC_DECODER_GRE
@ PKT_SRC_DECODER_GRE
Definition: decode.h:53
ENGINE_SET_INVALID_EVENT
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:1239
GRE_VERSION0_RECUR
@ GRE_VERSION0_RECUR
Definition: decode-events.h:138
ETHERNET_TYPE_VLAN
#define ETHERNET_TYPE_VLAN
Definition: decode-vlan.h:31
DECODE_TUNNEL_ARP
@ DECODE_TUNNEL_ARP
Definition: decode.h:1154
GRE_SEQ_LEN
#define GRE_SEQ_LEN
Definition: decode-gre.h:66
GRE_GET_VERSION
#define GRE_GET_VERSION(r)
Definition: decode-gre.h:76
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:402
GRE_VERSION_1
#define GRE_VERSION_1
Definition: decode-gre.h:60
ThreadVars_::stats
StatsThreadContext stats
Definition: threadvars.h:120
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:109