Coverage Report

Created: 2026-06-30 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata/src/decode-gre.c
Line
Count
Source
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
45.9k
{
49
45.9k
    DEBUG_VALIDATE_BUG_ON(pkt == NULL);
50
51
45.9k
    uint32_t header_len = GRE_HDR_LEN;
52
45.9k
    GRESreHdr *gsre = NULL;
53
45.9k
    GREPPtPHd *gre_pptp_h = NULL;
54
55
45.9k
    StatsCounterIncr(&tv->stats, dtv->counter_gre);
56
57
45.9k
    if(len < GRE_HDR_LEN)    {
58
479
        ENGINE_SET_INVALID_EVENT(p, GRE_PKT_TOO_SMALL);
59
479
        return TM_ECODE_FAILED;
60
479
    }
61
45.4k
    if (!PacketIncreaseCheckLayers(p)) {
62
36
        return TM_ECODE_FAILED;
63
36
    }
64
65
45.4k
    GREHdr *greh = PacketSetGRE(p, pkt);
66
67
45.4k
    SCLogDebug("p %p pkt %p GRE protocol %04x Len: %d GRE version %x", p, pkt, GRE_GET_PROTO(greh),
68
45.4k
            len, GRE_GET_VERSION(greh));
69
70
45.4k
    switch (GRE_GET_VERSION(greh)) {
71
36.8k
        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
36.8k
            if (GRE_FLAG_ISSET_RECUR(greh)) {
83
2.55k
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_RECUR);
84
2.55k
                return TM_ECODE_OK;
85
2.55k
            }
86
87
34.3k
            if (GREV1_FLAG_ISSET_FLAGS(greh)) {
88
926
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_FLAGS);
89
926
                return TM_ECODE_OK;
90
926
            }
91
92
            /* Adjust header length based on content */
93
94
33.3k
            if (GRE_FLAG_ISSET_KY(greh))
95
6.71k
                header_len += GRE_KEY_LEN;
96
97
33.3k
            if (GRE_FLAG_ISSET_SQ(greh))
98
4.96k
                header_len += GRE_SEQ_LEN;
99
100
33.3k
            if (GRE_FLAG_ISSET_CHKSUM(greh) || GRE_FLAG_ISSET_ROUTE(greh))
101
7.46k
                header_len += GRE_CHKSUM_LEN + GRE_OFFSET_LEN;
102
103
33.3k
            if (header_len > len)   {
104
1.79k
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_HDR_TOO_BIG);
105
1.79k
                return TM_ECODE_OK;
106
1.79k
            }
107
108
31.5k
            if (GRE_FLAG_ISSET_ROUTE(greh)) {
109
9.17k
                while (1)
110
9.17k
                {
111
9.17k
                    if ((header_len + GRE_SRE_HDR_LEN) > len) {
112
1.55k
                        ENGINE_SET_INVALID_EVENT(p,
113
1.55k
                                                 GRE_VERSION0_MALFORMED_SRE_HDR);
114
1.55k
                        return TM_ECODE_OK;
115
1.55k
                    }
116
117
7.62k
                    gsre = (GRESreHdr *)(pkt + header_len);
118
119
7.62k
                    header_len += GRE_SRE_HDR_LEN;
120
121
7.62k
                    if ((SCNtohs(gsre->af) == 0) && (gsre->sre_length == 0))
122
2.39k
                        break;
123
124
5.22k
                    header_len += gsre->sre_length;
125
5.22k
                    if (header_len > len) {
126
1.59k
                        ENGINE_SET_INVALID_EVENT(p,
127
1.59k
                                                 GRE_VERSION0_MALFORMED_SRE_HDR);
128
1.59k
                        return TM_ECODE_OK;
129
1.59k
                    }
130
5.22k
                }
131
5.54k
            }
132
28.4k
            break;
133
134
28.4k
        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
6.55k
            if (GRE_FLAG_ISSET_CHKSUM(greh)) {
146
290
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_CHKSUM);
147
290
                return TM_ECODE_OK;
148
290
            }
149
150
6.26k
            if (GRE_FLAG_ISSET_ROUTE(greh)) {
151
417
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_ROUTE);
152
417
                return TM_ECODE_OK;
153
417
            }
154
155
5.84k
            if (GRE_FLAG_ISSET_SSR(greh)) {
156
996
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_SSR);
157
996
                return TM_ECODE_OK;
158
996
            }
159
160
4.84k
            if (GRE_FLAG_ISSET_RECUR(greh)) {
161
422
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_RECUR);
162
422
                return TM_ECODE_OK;
163
422
            }
164
165
4.42k
            if (GREV1_FLAG_ISSET_FLAGS(greh)) {
166
693
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_FLAGS);
167
693
                return TM_ECODE_OK;
168
693
            }
169
170
3.73k
            if (GRE_GET_PROTO(greh) != GRE_PROTO_PPP) {
171
331
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_WRONG_PROTOCOL);
172
331
                return TM_ECODE_OK;
173
331
            }
174
175
3.40k
            if (!(GRE_FLAG_ISSET_KY(greh))) {
176
275
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_NO_KEY);
177
275
                return TM_ECODE_OK;
178
275
            }
179
180
3.12k
            header_len += GRE_KEY_LEN;
181
            /* key is set and proto == PPP */
182
3.12k
            gre_pptp_h = (GREPPtPHd *)pkt;
183
184
            /* Adjust header length based on content */
185
186
3.12k
            if (GRE_FLAG_ISSET_SQ(greh))
187
184
                header_len += GRE_SEQ_LEN;
188
189
3.12k
            if (GREV1_FLAG_ISSET_ACK(greh))
190
145
                header_len += GREV1_ACK_LEN;
191
192
3.12k
            if (header_len > len)   {
193
454
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION1_HDR_TOO_BIG);
194
454
                return TM_ECODE_OK;
195
454
            }
196
197
2.67k
            break;
198
2.67k
        default:
199
1.99k
            ENGINE_SET_INVALID_EVENT(p, GRE_WRONG_VERSION);
200
1.99k
            return TM_ECODE_OK;
201
45.4k
    }
202
203
31.1k
    switch (GRE_GET_PROTO(greh)) {
204
2.19k
        case ETHERNET_TYPE_IP:
205
2.19k
        {
206
2.19k
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
207
2.19k
                    len - header_len, DECODE_TUNNEL_IPV4);
208
2.19k
            if (tp != NULL) {
209
2.06k
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
210
2.06k
                PacketEnqueueNoLock(&tv->decode_pq,tp);
211
2.06k
            }
212
2.19k
            break;
213
0
        }
214
215
17.8k
        case GRE_PROTO_PPP:
216
17.8k
        {
217
17.8k
            if (gre_pptp_h && !gre_pptp_h->payload_length)
218
869
                return TM_ECODE_OK;
219
220
17.0k
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
221
17.0k
                    len - header_len, DECODE_TUNNEL_PPP);
222
17.0k
            if (tp != NULL) {
223
16.1k
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
224
16.1k
                PacketEnqueueNoLock(&tv->decode_pq,tp);
225
16.1k
            }
226
17.0k
            break;
227
17.8k
        }
228
229
366
        case ETHERNET_TYPE_IPV6:
230
366
        {
231
366
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
232
366
                    len - header_len, DECODE_TUNNEL_IPV6);
233
366
            if (tp != NULL) {
234
69
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
235
69
                PacketEnqueueNoLock(&tv->decode_pq,tp);
236
69
            }
237
366
            break;
238
17.8k
        }
239
240
761
        case ETHERNET_TYPE_VLAN:
241
761
        {
242
761
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
243
761
                    len - header_len, DECODE_TUNNEL_VLAN);
244
761
            if (tp != NULL) {
245
437
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
246
437
                PacketEnqueueNoLock(&tv->decode_pq,tp);
247
437
            }
248
761
            break;
249
17.8k
        }
250
251
3.74k
        case ETHERNET_TYPE_ERSPAN:
252
3.74k
        {
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
3.74k
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len, len - header_len,
258
3.74k
                    GRE_FLAG_ISSET_SQ(greh) == 0 ? DECODE_TUNNEL_ERSPANI : DECODE_TUNNEL_ERSPANII);
259
3.74k
            if (tp != NULL) {
260
1.16k
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
261
1.16k
                PacketEnqueueNoLock(&tv->decode_pq,tp);
262
1.16k
            }
263
3.74k
            break;
264
17.8k
        }
265
266
409
        case ETHERNET_TYPE_BRIDGE:
267
409
        {
268
409
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
269
409
                    len - header_len, DECODE_TUNNEL_ETHERNET);
270
409
            if (tp != NULL) {
271
343
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
272
343
                PacketEnqueueNoLock(&tv->decode_pq,tp);
273
343
            }
274
409
            break;
275
17.8k
        }
276
277
111
        case ETHERNET_TYPE_ARP: {
278
111
            Packet *tp = PacketTunnelPktSetup(
279
111
                    tv, dtv, p, pkt + header_len, len - header_len, DECODE_TUNNEL_ARP);
280
111
            if (tp != NULL) {
281
41
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
282
41
                PacketEnqueueNoLock(&tv->decode_pq, tp);
283
41
            }
284
111
            break;
285
17.8k
        }
286
287
5.64k
        default:
288
5.64k
            return TM_ECODE_OK;
289
31.1k
    }
290
24.5k
    return TM_ECODE_OK;
291
31.1k
}
292
293
294
#ifdef UNITTESTS
295
/**
296
 * \test DecodeGRETest01 is a test for small gre packet
297
 */
298
299
static int DecodeGREtest01 (void)
300
{
301
    uint8_t raw_gre[] = { 0x00 ,0x6e ,0x62 };
302
    Packet *p = PacketGetFromAlloc();
303
    FAIL_IF_NULL(p);
304
    ThreadVars tv;
305
    DecodeThreadVars dtv;
306
307
    memset(&tv, 0, sizeof(ThreadVars));
308
    memset(&dtv, 0, sizeof(DecodeThreadVars));
309
310
    DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
311
    FAIL_IF_NOT(ENGINE_ISSET_EVENT(p, GRE_PKT_TOO_SMALL));
312
313
    PacketFree(p);
314
    PASS;
315
}
316
317
/**
318
 * \test DecodeGRETest02 is a test for wrong gre version
319
 */
320
321
static 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 };
338
    Packet *p = PacketGetFromAlloc();
339
    FAIL_IF_NULL(p);
340
    ThreadVars tv;
341
    DecodeThreadVars dtv;
342
343
    memset(&tv, 0, sizeof(ThreadVars));
344
    memset(&dtv, 0, sizeof(DecodeThreadVars));
345
346
    DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
347
    FAIL_IF_NOT(ENGINE_ISSET_EVENT(p, GRE_WRONG_VERSION));
348
349
    PacketFree(p);
350
    PASS;
351
}
352
353
354
/**
355
 * \test DecodeGRETest03 is a test for valid gre packet
356
 */
357
358
static 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 };
375
    Packet *p = PacketGetFromAlloc();
376
    FAIL_IF_NULL(p);
377
    ThreadVars tv;
378
    DecodeThreadVars dtv;
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
    PacketFree(p);
387
    PASS;
388
}
389
#endif /* UNITTESTS */
390
391
/**
392
 * \brief this function registers unit tests for GRE decoder
393
 */
394
395
void DecodeGRERegisterTests(void)
396
0
{
397
#ifdef UNITTESTS
398
    UtRegisterTest("DecodeGREtest01", DecodeGREtest01);
399
    UtRegisterTest("DecodeGREtest02", DecodeGREtest02);
400
    UtRegisterTest("DecodeGREtest03", DecodeGREtest03);
401
#endif /* UNITTESTS */
402
0
}
403
/**
404
 * @}
405
 */