Coverage Report

Created: 2026-02-14 06:42

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
38.5k
{
49
38.5k
    DEBUG_VALIDATE_BUG_ON(pkt == NULL);
50
51
38.5k
    uint32_t header_len = GRE_HDR_LEN;
52
38.5k
    GRESreHdr *gsre = NULL;
53
38.5k
    GREPPtPHd *gre_pptp_h = NULL;
54
55
38.5k
    StatsCounterIncr(&tv->stats, dtv->counter_gre);
56
57
38.5k
    if(len < GRE_HDR_LEN)    {
58
576
        ENGINE_SET_INVALID_EVENT(p, GRE_PKT_TOO_SMALL);
59
576
        return TM_ECODE_FAILED;
60
576
    }
61
37.9k
    if (!PacketIncreaseCheckLayers(p)) {
62
34
        return TM_ECODE_FAILED;
63
34
    }
64
65
37.9k
    GREHdr *greh = PacketSetGRE(p, pkt);
66
67
37.9k
    SCLogDebug("p %p pkt %p GRE protocol %04x Len: %d GRE version %x", p, pkt, GRE_GET_PROTO(greh),
68
37.9k
            len, GRE_GET_VERSION(greh));
69
70
37.9k
    switch (GRE_GET_VERSION(greh)) {
71
30.9k
        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
30.9k
            if (GRE_FLAG_ISSET_RECUR(greh)) {
83
1.02k
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_RECUR);
84
1.02k
                return TM_ECODE_OK;
85
1.02k
            }
86
87
29.9k
            if (GREV1_FLAG_ISSET_FLAGS(greh)) {
88
876
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_FLAGS);
89
876
                return TM_ECODE_OK;
90
876
            }
91
92
            /* Adjust header length based on content */
93
94
29.0k
            if (GRE_FLAG_ISSET_KY(greh))
95
5.48k
                header_len += GRE_KEY_LEN;
96
97
29.0k
            if (GRE_FLAG_ISSET_SQ(greh))
98
5.17k
                header_len += GRE_SEQ_LEN;
99
100
29.0k
            if (GRE_FLAG_ISSET_CHKSUM(greh) || GRE_FLAG_ISSET_ROUTE(greh))
101
5.86k
                header_len += GRE_CHKSUM_LEN + GRE_OFFSET_LEN;
102
103
29.0k
            if (header_len > len)   {
104
1.35k
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_HDR_TOO_BIG);
105
1.35k
                return TM_ECODE_OK;
106
1.35k
            }
107
108
27.7k
            if (GRE_FLAG_ISSET_ROUTE(greh)) {
109
7.65k
                while (1)
110
7.65k
                {
111
7.65k
                    if ((header_len + GRE_SRE_HDR_LEN) > len) {
112
1.02k
                        ENGINE_SET_INVALID_EVENT(p,
113
1.02k
                                                 GRE_VERSION0_MALFORMED_SRE_HDR);
114
1.02k
                        return TM_ECODE_OK;
115
1.02k
                    }
116
117
6.63k
                    gsre = (GRESreHdr *)(pkt + header_len);
118
119
6.63k
                    header_len += GRE_SRE_HDR_LEN;
120
121
6.63k
                    if ((SCNtohs(gsre->af) == 0) && (gsre->sre_length == 0))
122
1.76k
                        break;
123
124
4.87k
                    header_len += gsre->sre_length;
125
4.87k
                    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
4.87k
                }
131
4.38k
            }
132
25.0k
            break;
133
134
25.0k
        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
5.25k
            if (GRE_FLAG_ISSET_CHKSUM(greh)) {
146
365
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_CHKSUM);
147
365
                return TM_ECODE_OK;
148
365
            }
149
150
4.88k
            if (GRE_FLAG_ISSET_ROUTE(greh)) {
151
159
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_ROUTE);
152
159
                return TM_ECODE_OK;
153
159
            }
154
155
4.72k
            if (GRE_FLAG_ISSET_SSR(greh)) {
156
280
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_SSR);
157
280
                return TM_ECODE_OK;
158
280
            }
159
160
4.44k
            if (GRE_FLAG_ISSET_RECUR(greh)) {
161
341
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_RECUR);
162
341
                return TM_ECODE_OK;
163
341
            }
164
165
4.10k
            if (GREV1_FLAG_ISSET_FLAGS(greh)) {
166
636
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_FLAGS);
167
636
                return TM_ECODE_OK;
168
636
            }
169
170
3.47k
            if (GRE_GET_PROTO(greh) != GRE_PROTO_PPP) {
171
402
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_WRONG_PROTOCOL);
172
402
                return TM_ECODE_OK;
173
402
            }
174
175
3.06k
            if (!(GRE_FLAG_ISSET_KY(greh))) {
176
220
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_NO_KEY);
177
220
                return TM_ECODE_OK;
178
220
            }
179
180
2.84k
            header_len += GRE_KEY_LEN;
181
            /* key is set and proto == PPP */
182
2.84k
            gre_pptp_h = (GREPPtPHd *)pkt;
183
184
            /* Adjust header length based on content */
185
186
2.84k
            if (GRE_FLAG_ISSET_SQ(greh))
187
180
                header_len += GRE_SEQ_LEN;
188
189
2.84k
            if (GREV1_FLAG_ISSET_ACK(greh))
190
187
                header_len += GREV1_ACK_LEN;
191
192
2.84k
            if (header_len > len)   {
193
397
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION1_HDR_TOO_BIG);
194
397
                return TM_ECODE_OK;
195
397
            }
196
197
2.45k
            break;
198
2.45k
        default:
199
1.71k
            ENGINE_SET_INVALID_EVENT(p, GRE_WRONG_VERSION);
200
1.71k
            return TM_ECODE_OK;
201
37.9k
    }
202
203
27.5k
    switch (GRE_GET_PROTO(greh)) {
204
3.61k
        case ETHERNET_TYPE_IP:
205
3.61k
        {
206
3.61k
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
207
3.61k
                    len - header_len, DECODE_TUNNEL_IPV4);
208
3.61k
            if (tp != NULL) {
209
3.33k
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
210
3.33k
                PacketEnqueueNoLock(&tv->decode_pq,tp);
211
3.33k
            }
212
3.61k
            break;
213
0
        }
214
215
12.6k
        case GRE_PROTO_PPP:
216
12.6k
        {
217
12.6k
            if (gre_pptp_h && !gre_pptp_h->payload_length)
218
891
                return TM_ECODE_OK;
219
220
11.7k
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
221
11.7k
                    len - header_len, DECODE_TUNNEL_PPP);
222
11.7k
            if (tp != NULL) {
223
11.1k
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
224
11.1k
                PacketEnqueueNoLock(&tv->decode_pq,tp);
225
11.1k
            }
226
11.7k
            break;
227
12.6k
        }
228
229
393
        case ETHERNET_TYPE_IPV6:
230
393
        {
231
393
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
232
393
                    len - header_len, DECODE_TUNNEL_IPV6);
233
393
            if (tp != NULL) {
234
66
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
235
66
                PacketEnqueueNoLock(&tv->decode_pq,tp);
236
66
            }
237
393
            break;
238
12.6k
        }
239
240
1.55k
        case ETHERNET_TYPE_VLAN:
241
1.55k
        {
242
1.55k
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
243
1.55k
                    len - header_len, DECODE_TUNNEL_VLAN);
244
1.55k
            if (tp != NULL) {
245
668
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
246
668
                PacketEnqueueNoLock(&tv->decode_pq,tp);
247
668
            }
248
1.55k
            break;
249
12.6k
        }
250
251
3.93k
        case ETHERNET_TYPE_ERSPAN:
252
3.93k
        {
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.93k
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len, len - header_len,
258
3.93k
                    GRE_FLAG_ISSET_SQ(greh) == 0 ? DECODE_TUNNEL_ERSPANI : DECODE_TUNNEL_ERSPANII);
259
3.93k
            if (tp != NULL) {
260
1.06k
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
261
1.06k
                PacketEnqueueNoLock(&tv->decode_pq,tp);
262
1.06k
            }
263
3.93k
            break;
264
12.6k
        }
265
266
639
        case ETHERNET_TYPE_BRIDGE:
267
639
        {
268
639
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
269
639
                    len - header_len, DECODE_TUNNEL_ETHERNET);
270
639
            if (tp != NULL) {
271
573
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
272
573
                PacketEnqueueNoLock(&tv->decode_pq,tp);
273
573
            }
274
639
            break;
275
12.6k
        }
276
277
93
        case ETHERNET_TYPE_ARP: {
278
93
            Packet *tp = PacketTunnelPktSetup(
279
93
                    tv, dtv, p, pkt + header_len, len - header_len, DECODE_TUNNEL_ARP);
280
93
            if (tp != NULL) {
281
23
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
282
23
                PacketEnqueueNoLock(&tv->decode_pq, tp);
283
23
            }
284
93
            break;
285
12.6k
        }
286
287
4.68k
        default:
288
4.68k
            return TM_ECODE_OK;
289
27.5k
    }
290
21.9k
    return TM_ECODE_OK;
291
27.5k
}
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
 */