Coverage Report

Created: 2026-11-12 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata8/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
201k
{
49
201k
    DEBUG_VALIDATE_BUG_ON(pkt == NULL);
50
51
201k
    uint32_t header_len = GRE_HDR_LEN;
52
201k
    GRESreHdr *gsre = NULL;
53
201k
    GREPPtPHd *gre_pptp_h = NULL;
54
55
201k
    StatsIncr(tv, dtv->counter_gre);
56
57
201k
    if(len < GRE_HDR_LEN)    {
58
834
        ENGINE_SET_INVALID_EVENT(p, GRE_PKT_TOO_SMALL);
59
834
        return TM_ECODE_FAILED;
60
834
    }
61
200k
    if (!PacketIncreaseCheckLayers(p)) {
62
65
        return TM_ECODE_FAILED;
63
65
    }
64
65
200k
    GREHdr *greh = PacketSetGRE(p, pkt);
66
67
200k
    SCLogDebug("p %p pkt %p GRE protocol %04x Len: %d GRE version %x", p, pkt, GRE_GET_PROTO(greh),
68
200k
            len, GRE_GET_VERSION(greh));
69
70
200k
    switch (GRE_GET_VERSION(greh)) {
71
152k
        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
152k
            if (GRE_FLAG_ISSET_RECUR(greh)) {
83
1.69k
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_RECUR);
84
1.69k
                return TM_ECODE_OK;
85
1.69k
            }
86
87
150k
            if (GREV1_FLAG_ISSET_FLAGS(greh)) {
88
2.24k
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_FLAGS);
89
2.24k
                return TM_ECODE_OK;
90
2.24k
            }
91
92
            /* Adjust header length based on content */
93
94
148k
            if (GRE_FLAG_ISSET_KY(greh))
95
7.25k
                header_len += GRE_KEY_LEN;
96
97
148k
            if (GRE_FLAG_ISSET_SQ(greh))
98
5.92k
                header_len += GRE_SEQ_LEN;
99
100
148k
            if (GRE_FLAG_ISSET_CHKSUM(greh) || GRE_FLAG_ISSET_ROUTE(greh))
101
8.01k
                header_len += GRE_CHKSUM_LEN + GRE_OFFSET_LEN;
102
103
148k
            if (header_len > len)   {
104
1.76k
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_HDR_TOO_BIG);
105
1.76k
                return TM_ECODE_OK;
106
1.76k
            }
107
108
146k
            if (GRE_FLAG_ISSET_ROUTE(greh)) {
109
10.7k
                while (1)
110
10.7k
                {
111
10.7k
                    if ((header_len + GRE_SRE_HDR_LEN) > len) {
112
1.42k
                        ENGINE_SET_INVALID_EVENT(p,
113
1.42k
                                                 GRE_VERSION0_MALFORMED_SRE_HDR);
114
1.42k
                        return TM_ECODE_OK;
115
1.42k
                    }
116
117
9.29k
                    gsre = (GRESreHdr *)(pkt + header_len);
118
119
9.29k
                    header_len += GRE_SRE_HDR_LEN;
120
121
9.29k
                    if ((SCNtohs(gsre->af) == 0) && (gsre->sre_length == 0))
122
2.82k
                        break;
123
124
6.47k
                    header_len += gsre->sre_length;
125
6.47k
                    if (header_len > len) {
126
1.75k
                        ENGINE_SET_INVALID_EVENT(p,
127
1.75k
                                                 GRE_VERSION0_MALFORMED_SRE_HDR);
128
1.75k
                        return TM_ECODE_OK;
129
1.75k
                    }
130
6.47k
                }
131
6.00k
            }
132
143k
            break;
133
134
143k
        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
9.28k
            if (GRE_FLAG_ISSET_CHKSUM(greh)) {
146
602
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_CHKSUM);
147
602
                return TM_ECODE_OK;
148
602
            }
149
150
8.68k
            if (GRE_FLAG_ISSET_ROUTE(greh)) {
151
964
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_ROUTE);
152
964
                return TM_ECODE_OK;
153
964
            }
154
155
7.72k
            if (GRE_FLAG_ISSET_SSR(greh)) {
156
1.60k
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_SSR);
157
1.60k
                return TM_ECODE_OK;
158
1.60k
            }
159
160
6.12k
            if (GRE_FLAG_ISSET_RECUR(greh)) {
161
637
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_RECUR);
162
637
                return TM_ECODE_OK;
163
637
            }
164
165
5.48k
            if (GREV1_FLAG_ISSET_FLAGS(greh)) {
166
1.19k
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_FLAGS);
167
1.19k
                return TM_ECODE_OK;
168
1.19k
            }
169
170
4.28k
            if (GRE_GET_PROTO(greh) != GRE_PROTO_PPP) {
171
672
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_WRONG_PROTOCOL);
172
672
                return TM_ECODE_OK;
173
672
            }
174
175
3.61k
            if (!(GRE_FLAG_ISSET_KY(greh))) {
176
868
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_NO_KEY);
177
868
                return TM_ECODE_OK;
178
868
            }
179
180
2.74k
            header_len += GRE_KEY_LEN;
181
            /* key is set and proto == PPP */
182
2.74k
            gre_pptp_h = (GREPPtPHd *)pkt;
183
184
            /* Adjust header length based on content */
185
186
2.74k
            if (GRE_FLAG_ISSET_SQ(greh))
187
218
                header_len += GRE_SEQ_LEN;
188
189
2.74k
            if (GREV1_FLAG_ISSET_ACK(greh))
190
202
                header_len += GREV1_ACK_LEN;
191
192
2.74k
            if (header_len > len)   {
193
451
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION1_HDR_TOO_BIG);
194
451
                return TM_ECODE_OK;
195
451
            }
196
197
2.29k
            break;
198
38.9k
        default:
199
38.9k
            ENGINE_SET_INVALID_EVENT(p, GRE_WRONG_VERSION);
200
38.9k
            return TM_ECODE_OK;
201
200k
    }
202
203
145k
    switch (GRE_GET_PROTO(greh)) {
204
3.40k
        case ETHERNET_TYPE_IP:
205
3.40k
        {
206
3.40k
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
207
3.40k
                    len - header_len, DECODE_TUNNEL_IPV4);
208
3.40k
            if (tp != NULL) {
209
3.06k
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
210
3.06k
                PacketEnqueueNoLock(&tv->decode_pq,tp);
211
3.06k
            }
212
3.40k
            break;
213
0
        }
214
215
127k
        case GRE_PROTO_PPP:
216
127k
        {
217
127k
            if (gre_pptp_h && !gre_pptp_h->payload_length)
218
795
                return TM_ECODE_OK;
219
220
127k
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
221
127k
                    len - header_len, DECODE_TUNNEL_PPP);
222
127k
            if (tp != NULL) {
223
123k
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
224
123k
                PacketEnqueueNoLock(&tv->decode_pq,tp);
225
123k
            }
226
127k
            break;
227
127k
        }
228
229
392
        case ETHERNET_TYPE_IPV6:
230
392
        {
231
392
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
232
392
                    len - header_len, DECODE_TUNNEL_IPV6);
233
392
            if (tp != NULL) {
234
84
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
235
84
                PacketEnqueueNoLock(&tv->decode_pq,tp);
236
84
            }
237
392
            break;
238
127k
        }
239
240
998
        case ETHERNET_TYPE_VLAN:
241
998
        {
242
998
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
243
998
                    len - header_len, DECODE_TUNNEL_VLAN);
244
998
            if (tp != NULL) {
245
559
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
246
559
                PacketEnqueueNoLock(&tv->decode_pq,tp);
247
559
            }
248
998
            break;
249
127k
        }
250
251
3.76k
        case ETHERNET_TYPE_ERSPAN:
252
3.76k
        {
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.76k
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len, len - header_len,
258
3.76k
                    GRE_FLAG_ISSET_SQ(greh) == 0 ? DECODE_TUNNEL_ERSPANI : DECODE_TUNNEL_ERSPANII);
259
3.76k
            if (tp != NULL) {
260
1.33k
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
261
1.33k
                PacketEnqueueNoLock(&tv->decode_pq,tp);
262
1.33k
            }
263
3.76k
            break;
264
127k
        }
265
266
803
        case ETHERNET_TYPE_BRIDGE:
267
803
        {
268
803
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
269
803
                    len - header_len, DECODE_TUNNEL_ETHERNET);
270
803
            if (tp != NULL) {
271
575
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
272
575
                PacketEnqueueNoLock(&tv->decode_pq,tp);
273
575
            }
274
803
            break;
275
127k
        }
276
277
1.13k
        case ETHERNET_TYPE_ARP: {
278
1.13k
            Packet *tp = PacketTunnelPktSetup(
279
1.13k
                    tv, dtv, p, pkt + header_len, len - header_len, DECODE_TUNNEL_ARP);
280
1.13k
            if (tp != NULL) {
281
428
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
282
428
                PacketEnqueueNoLock(&tv->decode_pq, tp);
283
428
            }
284
1.13k
            break;
285
127k
        }
286
287
7.27k
        default:
288
7.27k
            return TM_ECODE_OK;
289
145k
    }
290
137k
    return TM_ECODE_OK;
291
145k
}
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
    SCFree(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
    SCFree(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
    SCFree(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
 */