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-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, const uint8_t *pkt, uint32_t len)
47 {
48  uint32_t header_len = GRE_HDR_LEN;
49  GRESreHdr *gsre = NULL;
50 
52 
53  if(len < GRE_HDR_LEN) {
55  return TM_ECODE_FAILED;
56  }
57  if (!PacketIncreaseCheckLayers(p)) {
58  return TM_ECODE_FAILED;
59  }
60 
61  p->greh = (GREHdr *)pkt;
62  if(p->greh == NULL)
63  return TM_ECODE_FAILED;
64 
65  SCLogDebug("p %p pkt %p GRE protocol %04x Len: %d GRE version %x",
66  p, pkt, GRE_GET_PROTO(p->greh), len,GRE_GET_VERSION(p->greh));
67 
68  switch (GRE_GET_VERSION(p->greh))
69  {
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 
81  if (GRE_FLAG_ISSET_RECUR(p->greh)) {
83  return TM_ECODE_OK;
84  }
85 
86  if (GREV1_FLAG_ISSET_FLAGS(p->greh)) {
88  return TM_ECODE_OK;
89  }
90 
91  /* Adjust header length based on content */
92 
93  if (GRE_FLAG_ISSET_KY(p->greh))
94  header_len += GRE_KEY_LEN;
95 
96  if (GRE_FLAG_ISSET_SQ(p->greh))
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(p->greh))
108  {
109  while (1)
110  {
111  if ((header_len + GRE_SRE_HDR_LEN) > len) {
114  return TM_ECODE_OK;
115  }
116 
117  gsre = (GRESreHdr *)(pkt + header_len);
118 
119  header_len += GRE_SRE_HDR_LEN;
120 
121  if ((SCNtohs(gsre->af) == 0) && (gsre->sre_length == 0))
122  break;
123 
124  header_len += gsre->sre_length;
125  if (header_len > len) {
128  return TM_ECODE_OK;
129  }
130  }
131  }
132  break;
133 
134  case GRE_VERSION_1:
135 
136  /* GRE version 1 doesn't support the fields below RFC 1701 */
137 
138  /**
139  * \todo We need to make sure this does not allow bypassing
140  * inspection. A server may just ignore these and
141  * continue processing the packet, but we will not look
142  * further into it.
143  */
144 
145  if (GRE_FLAG_ISSET_CHKSUM(p->greh)) {
147  return TM_ECODE_OK;
148  }
149 
150  if (GRE_FLAG_ISSET_ROUTE(p->greh)) {
152  return TM_ECODE_OK;
153  }
154 
155  if (GRE_FLAG_ISSET_SSR(p->greh)) {
157  return TM_ECODE_OK;
158  }
159 
160  if (GRE_FLAG_ISSET_RECUR(p->greh)) {
162  return TM_ECODE_OK;
163  }
164 
165  if (GREV1_FLAG_ISSET_FLAGS(p->greh)) {
167  return TM_ECODE_OK;
168  }
169 
170  if (GRE_GET_PROTO(p->greh) != GRE_PROTO_PPP) {
172  return TM_ECODE_OK;
173  }
174 
175  if (!(GRE_FLAG_ISSET_KY(p->greh))) {
177  return TM_ECODE_OK;
178  }
179 
180  header_len += GRE_KEY_LEN;
181 
182  /* Adjust header length based on content */
183 
184  if (GRE_FLAG_ISSET_SQ(p->greh))
185  header_len += GRE_SEQ_LEN;
186 
187  if (GREV1_FLAG_ISSET_ACK(p->greh))
188  header_len += GREV1_ACK_LEN;
189 
190  if (header_len > len) {
192  return TM_ECODE_OK;
193  }
194 
195  break;
196  default:
198  return TM_ECODE_OK;
199  }
200 
201  switch (GRE_GET_PROTO(p->greh))
202  {
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  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
217  len - header_len, DECODE_TUNNEL_PPP);
218  if (tp != NULL) {
221  }
222  break;
223  }
224 
225  case ETHERNET_TYPE_IPV6:
226  {
227  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
228  len - header_len, DECODE_TUNNEL_IPV6);
229  if (tp != NULL) {
232  }
233  break;
234  }
235 
236  case ETHERNET_TYPE_VLAN:
237  {
238  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
239  len - header_len, DECODE_TUNNEL_VLAN);
240  if (tp != NULL) {
243  }
244  break;
245  }
246 
248  {
249  // Determine if it's Type I or Type II based on the flags in the GRE header.
250  // Type I: 0|0|0|0|0|00000|000000000|00000
251  // Type II: 0|0|0|1|0|00000|000000000|00000
252  // Seq
253  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
254  len - header_len,
255  GRE_FLAG_ISSET_SQ(p->greh) == 0 ?
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  default:
277  return TM_ECODE_OK;
278  }
279  return TM_ECODE_OK;
280 }
281 
282 
283 #ifdef UNITTESTS
284 /**
285  * \test DecodeGRETest01 is a test for small gre packet
286  */
287 
288 static int DecodeGREtest01 (void)
289 {
290  uint8_t raw_gre[] = { 0x00 ,0x6e ,0x62 };
291  Packet *p = PacketGetFromAlloc();
292  FAIL_IF_NULL(p);
293  ThreadVars tv;
295 
296  memset(&tv, 0, sizeof(ThreadVars));
297  memset(&dtv, 0, sizeof(DecodeThreadVars));
298 
299  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
301 
302  SCFree(p);
303  PASS;
304 }
305 
306 /**
307  * \test DecodeGRETest02 is a test for wrong gre version
308  */
309 
310 static int DecodeGREtest02 (void)
311 {
312  uint8_t raw_gre[] = {
313  0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
314  0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
315  0x00, 0x8a, 0x30, 0x01, 0x0b, 0x00, 0x4e, 0x00,
316  0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03, 0x00,
317  0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x40,
318  0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e, 0x2b,
319  0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e, 0x00,
320  0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4, 0x01,
321  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
322  0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73, 0x69,
323  0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x03,
324  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
325  0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00,
326  0x00, 0x00, 0x00 };
327  Packet *p = PacketGetFromAlloc();
328  FAIL_IF_NULL(p);
329  ThreadVars tv;
331 
332  memset(&tv, 0, sizeof(ThreadVars));
333  memset(&dtv, 0, sizeof(DecodeThreadVars));
334 
335  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
337 
338  SCFree(p);
339  PASS;
340 }
341 
342 
343 /**
344  * \test DecodeGRETest03 is a test for valid gre packet
345  */
346 
347 static int DecodeGREtest03 (void)
348 {
349  uint8_t raw_gre[] = {
350  0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
351  0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
352  0x00, 0x8a, 0x30, 0x01, 0x88, 0x0b, 0x00, 0x4e,
353  0x00, 0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03,
354  0x00, 0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00,
355  0x40, 0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e,
356  0x2b, 0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e,
357  0x00, 0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4,
358  0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
359  0x00, 0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73,
360  0x69, 0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72,
361  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
362  0x01, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00,
363  0x00, 0x00, 0x00, 0x00 };
364  Packet *p = PacketGetFromAlloc();
365  FAIL_IF_NULL(p);
366  ThreadVars tv;
368 
369  memset(&tv, 0, sizeof(ThreadVars));
370  memset(&dtv, 0, sizeof(DecodeThreadVars));
371 
372  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
373  FAIL_IF_NULL(p->greh);
374 
375  SCFree(p);
376  PASS;
377 }
378 #endif /* UNITTESTS */
379 
380 /**
381  * \brief this function registers unit tests for GRE decoder
382  */
383 
385 {
386 #ifdef UNITTESTS
387  UtRegisterTest("DecodeGREtest01", DecodeGREtest01);
388  UtRegisterTest("DecodeGREtest02", DecodeGREtest02);
389  UtRegisterTest("DecodeGREtest03", DecodeGREtest03);
390 #endif /* UNITTESTS */
391 }
392 /**
393  * @}
394  */
GRE_PKT_TOO_SMALL
@ GRE_PKT_TOO_SMALL
Definition: decode-events.h:127
Packet_::greh
GREHdr * greh
Definition: decode.h:548
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:923
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
GRE_VERSION0_RECUR
@ GRE_VERSION0_RECUR
Definition: decode-events.h:129
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:169
GREV1_ACK_LEN
#define GREV1_ACK_LEN
Definition: decode-gre.h:76
GRE_FLAG_ISSET_RECUR
#define GRE_FLAG_ISSET_RECUR(r)
Definition: decode-gre.h:70
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:1035
GRE_VERSION1_NO_KEY
@ GRE_VERSION1_NO_KEY
Definition: decode-events.h:138
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:920
GRE_VERSION0_MALFORMED_SRE_HDR
@ GRE_VERSION0_MALFORMED_SRE_HDR
Definition: decode-events.h:132
ETHERNET_TYPE_ERSPAN
#define ETHERNET_TYPE_ERSPAN
Definition: decode-ethernet.h:48
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:81
util-unittest.h
GRE_VERSION1_WRONG_PROTOCOL
@ GRE_VERSION1_WRONG_PROTOCOL
Definition: decode-events.h:139
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
GRE_VERSION0_HDR_TOO_BIG
@ GRE_VERSION0_HDR_TOO_BIG
Definition: decode-events.h:131
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1167
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:919
GRE_VERSION1_FLAGS
@ GRE_VERSION1_FLAGS
Definition: decode-events.h:137
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:925
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
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:921
Packet_
Definition: decode.h:415
DECODE_TUNNEL_IPV4
@ DECODE_TUNNEL_IPV4
Definition: decode.h:922
DECODE_TUNNEL_ETHERNET
@ DECODE_TUNNEL_ETHERNET
Definition: decode.h:918
GRE_OFFSET_LEN
#define GRE_OFFSET_LEN
Definition: decode-gre.h:59
decode-events.h
GRE_VERSION1_RECUR
@ GRE_VERSION1_RECUR
Definition: decode-events.h:136
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:30
GRE_VERSION1_SSR
@ GRE_VERSION1_SSR
Definition: decode-events.h:135
GRE_CHKSUM_LEN
#define GRE_CHKSUM_LEN
Definition: decode-gre.h:58
PacketEnqueueNoLock
void PacketEnqueueNoLock(PacketQueueNoLock *qnl, Packet *p)
Definition: packet-queue.c:167
GRE_VERSION1_HDR_TOO_BIG
@ GRE_VERSION1_HDR_TOO_BIG
Definition: decode-events.h:141
GRE_VERSION1_CHKSUM
@ GRE_VERSION1_CHKSUM
Definition: decode-events.h:133
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:669
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_ROUTE
@ GRE_VERSION1_ROUTE
Definition: decode-events.h:134
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
GRE_VERSION0_FLAGS
@ GRE_VERSION0_FLAGS
Definition: decode-events.h:130
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:150
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:639
DecodeGRERegisterTests
void DecodeGRERegisterTests(void)
this function registers unit tests for GRE decoder
Definition: decode-gre.c:384
GRE_GET_PROTO
#define GRE_GET_PROTO(r)
Definition: decode-gre.h:73
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:1028
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_VERSION_1
#define GRE_VERSION_1
Definition: decode-gre.h:55
ETHERNET_TYPE_IP
#define ETHERNET_TYPE_IP
Definition: decode-ethernet.h:34