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
47int 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 GREPPtPHd *gre_pptp_h = NULL;
54
56
57 if(len < GRE_HDR_LEN) {
59 return TM_ECODE_FAILED;
60 }
61 if (!PacketIncreaseCheckLayers(p)) {
62 return TM_ECODE_FAILED;
63 }
64
65 GREHdr *greh = PacketSetGRE(p, pkt);
66
67 SCLogDebug("p %p pkt %p GRE protocol %04x Len: %d GRE version %x", p, pkt, GRE_GET_PROTO(greh),
69
70 switch (GRE_GET_VERSION(greh)) {
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
84 return TM_ECODE_OK;
85 }
86
89 return TM_ECODE_OK;
90 }
91
92 /* Adjust header length based on content */
93
95 header_len += GRE_KEY_LEN;
96
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
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
147 return TM_ECODE_OK;
148 }
149
152 return TM_ECODE_OK;
153 }
154
157 return TM_ECODE_OK;
158 }
159
162 return TM_ECODE_OK;
163 }
164
167 return TM_ECODE_OK;
168 }
169
172 return TM_ECODE_OK;
173 }
174
175 if (!(GRE_FLAG_ISSET_KY(greh))) {
177 return TM_ECODE_OK;
178 }
179
180 header_len += GRE_KEY_LEN;
181 /* key is set and proto == PPP */
182 gre_pptp_h = (GREPPtPHd *)pkt;
183
184 /* Adjust header length based on content */
185
187 header_len += GRE_SEQ_LEN;
188
190 header_len += GREV1_ACK_LEN;
191
192 if (header_len > len) {
194 return TM_ECODE_OK;
195 }
196
197 break;
198 default:
200 return TM_ECODE_OK;
201 }
202
203 switch (GRE_GET_PROTO(greh)) {
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 if (gre_pptp_h && !gre_pptp_h->payload_length)
218 return TM_ECODE_OK;
219
220 Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
221 len - header_len, DECODE_TUNNEL_PPP);
222 if (tp != NULL) {
225 }
226 break;
227 }
228
230 {
231 Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
232 len - header_len, DECODE_TUNNEL_IPV6);
233 if (tp != NULL) {
236 }
237 break;
238 }
239
241 {
242 Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
243 len - header_len, DECODE_TUNNEL_VLAN);
244 if (tp != NULL) {
247 }
248 break;
249 }
250
252 {
253 // Determine if it's Type I or Type II based on the flags in the GRE header.
254 // Type I: 0|0|0|0|0|00000|000000000|00000
255 // Type II: 0|0|0|1|0|00000|000000000|00000
256 // Seq
257 Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len, len - header_len,
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 case ETHERNET_TYPE_ARP: {
279 tv, dtv, p, pkt + header_len, len - header_len, DECODE_TUNNEL_ARP);
280 if (tp != NULL) {
283 }
284 break;
285 }
286
287 default:
288 return TM_ECODE_OK;
289 }
290 return TM_ECODE_OK;
291}
292
293
294#ifdef UNITTESTS
295/**
296 * \test DecodeGRETest01 is a test for small gre packet
297 */
298
299static int DecodeGREtest01 (void)
300{
301 uint8_t raw_gre[] = { 0x00 ,0x6e ,0x62 };
303 FAIL_IF_NULL(p);
306
307 memset(&tv, 0, sizeof(ThreadVars));
308 memset(&dtv, 0, sizeof(DecodeThreadVars));
309
310 DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
312
313 SCFree(p);
314 PASS;
315}
316
317/**
318 * \test DecodeGRETest02 is a test for wrong gre version
319 */
320
321static int DecodeGREtest02 (void)
322{
323 uint8_t raw_gre[] = {
324 0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
325 0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
326 0x00, 0x8a, 0x30, 0x01, 0x0b, 0x00, 0x4e, 0x00,
327 0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03, 0x00,
328 0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x40,
329 0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e, 0x2b,
330 0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e, 0x00,
331 0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4, 0x01,
332 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
333 0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73, 0x69,
334 0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x03,
335 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
336 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00,
337 0x00, 0x00, 0x00 };
339 FAIL_IF_NULL(p);
342
343 memset(&tv, 0, sizeof(ThreadVars));
344 memset(&dtv, 0, sizeof(DecodeThreadVars));
345
346 DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
348
349 SCFree(p);
350 PASS;
351}
352
353
354/**
355 * \test DecodeGRETest03 is a test for valid gre packet
356 */
357
358static int DecodeGREtest03 (void)
359{
360 uint8_t raw_gre[] = {
361 0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
362 0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
363 0x00, 0x8a, 0x30, 0x01, 0x88, 0x0b, 0x00, 0x4e,
364 0x00, 0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03,
365 0x00, 0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00,
366 0x40, 0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e,
367 0x2b, 0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e,
368 0x00, 0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4,
369 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
370 0x00, 0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73,
371 0x69, 0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72,
372 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
373 0x01, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00,
374 0x00, 0x00, 0x00, 0x00 };
376 FAIL_IF_NULL(p);
379
380 memset(&tv, 0, sizeof(ThreadVars));
381 memset(&dtv, 0, sizeof(DecodeThreadVars));
382
383 DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
384 FAIL_IF_NOT(PacketIsGRE(p));
385
386 SCFree(p);
387 PASS;
388}
389#endif /* UNITTESTS */
390
391/**
392 * \brief this function registers unit tests for GRE decoder
393 */
394
396{
397#ifdef UNITTESTS
398 UtRegisterTest("DecodeGREtest01", DecodeGREtest01);
399 UtRegisterTest("DecodeGREtest02", DecodeGREtest02);
400 UtRegisterTest("DecodeGREtest03", DecodeGREtest03);
401#endif /* UNITTESTS */
402}
403/**
404 * @}
405 */
uint8_t len
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition counters.c:166
#define ETHERNET_TYPE_IP
#define ETHERNET_TYPE_ARP
#define ETHERNET_TYPE_BRIDGE
#define ETHERNET_TYPE_IPV6
#define ETHERNET_TYPE_ERSPAN
@ GRE_WRONG_VERSION
@ GRE_VERSION1_ROUTE
@ GRE_PKT_TOO_SMALL
@ GRE_VERSION1_CHKSUM
@ GRE_VERSION0_HDR_TOO_BIG
@ GRE_VERSION0_FLAGS
@ GRE_VERSION1_NO_KEY
@ GRE_VERSION1_HDR_TOO_BIG
@ GRE_VERSION1_RECUR
@ GRE_VERSION1_FLAGS
@ GRE_VERSION1_WRONG_PROTOCOL
@ GRE_VERSION1_SSR
@ GRE_VERSION0_MALFORMED_SRE_HDR
@ GRE_VERSION0_RECUR
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
void DecodeGRERegisterTests(void)
this function registers unit tests for GRE decoder
Definition decode-gre.c:395
#define GRE_KEY_LEN
Definition decode-gre.h:65
#define GRE_SEQ_LEN
Definition decode-gre.h:66
#define GRE_VERSION_1
Definition decode-gre.h:60
#define GRE_HDR_LEN
Definition decode-gre.h:62
#define GRE_FLAG_ISSET_SQ(r)
Definition decode-gre.h:73
#define GRE_SRE_HDR_LEN
Definition decode-gre.h:67
GREHdr greh
Definition decode-gre.h:0
#define GREV1_ACK_LEN
Definition decode-gre.h:81
#define GREV1_FLAG_ISSET_ACK(r)
Definition decode-gre.h:83
#define GRE_OFFSET_LEN
Definition decode-gre.h:64
#define GRE_FLAG_ISSET_CHKSUM(r)
Definition decode-gre.h:70
#define GRE_GET_PROTO(r)
Definition decode-gre.h:78
#define GRE_FLAG_ISSET_ROUTE(r)
Definition decode-gre.h:71
#define GRE_FLAG_ISSET_KY(r)
Definition decode-gre.h:72
#define GRE_VERSION_0
Definition decode-gre.h:59
#define GRE_CHKSUM_LEN
Definition decode-gre.h:63
#define GRE_FLAG_ISSET_SSR(r)
Definition decode-gre.h:74
#define GRE_FLAG_ISSET_RECUR(r)
Definition decode-gre.h:75
#define GREV1_FLAG_ISSET_FLAGS(r)
Definition decode-gre.h:82
#define GRE_GET_VERSION(r)
Definition decode-gre.h:76
#define GRE_PROTO_PPP
Definition decode-gre.h:68
#define ETHERNET_TYPE_VLAN
Definition decode-vlan.h:31
#define PKT_SET_SRC(p, src_val)
Definition decode.h:1325
@ DECODE_TUNNEL_ERSPANII
Definition decode.h:1103
@ DECODE_TUNNEL_PPP
Definition decode.h:1109
@ DECODE_TUNNEL_IPV6
Definition decode.h:1107
@ DECODE_TUNNEL_ETHERNET
Definition decode.h:1102
@ DECODE_TUNNEL_ERSPANI
Definition decode.h:1104
@ DECODE_TUNNEL_ARP
Definition decode.h:1111
@ DECODE_TUNNEL_VLAN
Definition decode.h:1105
@ DECODE_TUNNEL_IPV4
Definition decode.h:1106
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition decode.h:1194
#define ENGINE_ISSET_EVENT(p, e)
Definition decode.h:1199
@ PKT_SRC_DECODER_GRE
Definition decode.h:53
DecodeThreadVars * dtv
ThreadVars * tv
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition decode.c:258
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:393
void PacketEnqueueNoLock(PacketQueueNoLock *qnl, Packet *p)
Structure to hold thread specific data for all decode modules.
Definition decode.h:963
uint16_t counter_gre
Definition decode.h:1000
Per thread variable structure.
Definition threadvars.h:58
PacketQueueNoLock decode_pq
Definition threadvars.h:112
#define SCNtohs(x)
@ TM_ECODE_FAILED
@ TM_ECODE_OK
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCFree(p)
Definition util-mem.h:61
#define DEBUG_VALIDATE_BUG_ON(exp)