• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 23374838686

21 Mar 2026 07:29AM UTC coverage: 59.341% (-20.0%) from 79.315%
23374838686

Pull #15075

github

web-flow
Merge 90b4e834f into 6587e363a
Pull Request #15075: Stack 8001 v16.4

38 of 70 new or added lines in 10 files covered. (54.29%)

34165 existing lines in 563 files now uncovered.

119621 of 201584 relevant lines covered (59.34%)

650666.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.33
/src/decode-gre.c
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
{
20,800✔
49
    DEBUG_VALIDATE_BUG_ON(pkt == NULL);
20,800✔
50

51
    uint32_t header_len = GRE_HDR_LEN;
20,800✔
52
    GRESreHdr *gsre = NULL;
20,800✔
53
    GREPPtPHd *gre_pptp_h = NULL;
20,800✔
54

55
    StatsCounterIncr(&tv->stats, dtv->counter_gre);
20,800✔
56

57
    if(len < GRE_HDR_LEN)    {
20,800✔
58
        ENGINE_SET_INVALID_EVENT(p, GRE_PKT_TOO_SMALL);
331✔
59
        return TM_ECODE_FAILED;
331✔
60
    }
331✔
61
    if (!PacketIncreaseCheckLayers(p)) {
20,469✔
62
        return TM_ECODE_FAILED;
36✔
63
    }
36✔
64

65
    GREHdr *greh = PacketSetGRE(p, pkt);
20,433✔
66

67
    SCLogDebug("p %p pkt %p GRE protocol %04x Len: %d GRE version %x", p, pkt, GRE_GET_PROTO(greh),
20,433✔
68
            len, GRE_GET_VERSION(greh));
20,433✔
69

70
    switch (GRE_GET_VERSION(greh)) {
20,433✔
71
        case GRE_VERSION_0:
14,821✔
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
            if (GRE_FLAG_ISSET_RECUR(greh)) {
14,821✔
83
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_RECUR);
709✔
84
                return TM_ECODE_OK;
709✔
85
            }
709✔
86

87
            if (GREV1_FLAG_ISSET_FLAGS(greh)) {
14,112✔
88
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_FLAGS);
235✔
89
                return TM_ECODE_OK;
235✔
90
            }
235✔
91

92
            /* Adjust header length based on content */
93

94
            if (GRE_FLAG_ISSET_KY(greh))
13,877✔
95
                header_len += GRE_KEY_LEN;
2,816✔
96

97
            if (GRE_FLAG_ISSET_SQ(greh))
13,877✔
98
                header_len += GRE_SEQ_LEN;
4,397✔
99

100
            if (GRE_FLAG_ISSET_CHKSUM(greh) || GRE_FLAG_ISSET_ROUTE(greh))
13,877✔
101
                header_len += GRE_CHKSUM_LEN + GRE_OFFSET_LEN;
2,197✔
102

103
            if (header_len > len)   {
13,877✔
104
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_HDR_TOO_BIG);
379✔
105
                return TM_ECODE_OK;
379✔
106
            }
379✔
107

108
            if (GRE_FLAG_ISSET_ROUTE(greh)) {
13,498✔
109
                while (1)
3,144✔
110
                {
3,144✔
111
                    if ((header_len + GRE_SRE_HDR_LEN) > len) {
3,144✔
112
                        ENGINE_SET_INVALID_EVENT(p,
776✔
113
                                                 GRE_VERSION0_MALFORMED_SRE_HDR);
776✔
114
                        return TM_ECODE_OK;
776✔
115
                    }
776✔
116

117
                    gsre = (GRESreHdr *)(pkt + header_len);
2,368✔
118

119
                    header_len += GRE_SRE_HDR_LEN;
2,368✔
120

121
                    if ((SCNtohs(gsre->af) == 0) && (gsre->sre_length == 0))
2,368✔
122
                        break;
147✔
123

124
                    header_len += gsre->sre_length;
2,221✔
125
                    if (header_len > len) {
2,221✔
126
                        ENGINE_SET_INVALID_EVENT(p,
781✔
127
                                                 GRE_VERSION0_MALFORMED_SRE_HDR);
781✔
128
                        return TM_ECODE_OK;
781✔
129
                    }
781✔
130
                }
2,221✔
131
            }
1,704✔
132
            break;
11,941✔
133

134
        case GRE_VERSION_1:
11,941✔
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(greh)) {
4,777✔
146
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_CHKSUM);
239✔
147
                return TM_ECODE_OK;
239✔
148
            }
239✔
149

150
            if (GRE_FLAG_ISSET_ROUTE(greh)) {
4,538✔
151
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_ROUTE);
136✔
152
                return TM_ECODE_OK;
136✔
153
            }
136✔
154

155
            if (GRE_FLAG_ISSET_SSR(greh)) {
4,402✔
156
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_SSR);
251✔
157
                return TM_ECODE_OK;
251✔
158
            }
251✔
159

160
            if (GRE_FLAG_ISSET_RECUR(greh)) {
4,151✔
161
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_RECUR);
248✔
162
                return TM_ECODE_OK;
248✔
163
            }
248✔
164

165
            if (GREV1_FLAG_ISSET_FLAGS(greh)) {
3,903✔
166
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_FLAGS);
286✔
167
                return TM_ECODE_OK;
286✔
168
            }
286✔
169

170
            if (GRE_GET_PROTO(greh) != GRE_PROTO_PPP) {
3,617✔
171
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_WRONG_PROTOCOL);
376✔
172
                return TM_ECODE_OK;
376✔
173
            }
376✔
174

175
            if (!(GRE_FLAG_ISSET_KY(greh))) {
3,241✔
176
                ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_NO_KEY);
232✔
177
                return TM_ECODE_OK;
232✔
178
            }
232✔
179

180
            header_len += GRE_KEY_LEN;
3,009✔
181
            /* key is set and proto == PPP */
182
            gre_pptp_h = (GREPPtPHd *)pkt;
3,009✔
183

184
            /* Adjust header length based on content */
185

186
            if (GRE_FLAG_ISSET_SQ(greh))
3,009✔
187
                header_len += GRE_SEQ_LEN;
204✔
188

189
            if (GREV1_FLAG_ISSET_ACK(greh))
3,009✔
190
                header_len += GREV1_ACK_LEN;
224✔
191

192
            if (header_len > len)   {
3,009✔
193
                ENGINE_SET_INVALID_EVENT(p, GRE_VERSION1_HDR_TOO_BIG);
419✔
194
                return TM_ECODE_OK;
419✔
195
            }
419✔
196

197
            break;
2,590✔
198
        default:
2,590✔
199
            ENGINE_SET_INVALID_EVENT(p, GRE_WRONG_VERSION);
835✔
200
            return TM_ECODE_OK;
835✔
201
    }
20,433✔
202

203
    switch (GRE_GET_PROTO(greh)) {
14,531✔
204
        case ETHERNET_TYPE_IP:
2,232✔
205
        {
2,232✔
206
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
2,232✔
207
                    len - header_len, DECODE_TUNNEL_IPV4);
2,232✔
208
            if (tp != NULL) {
2,232✔
209
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
2,029✔
210
                PacketEnqueueNoLock(&tv->decode_pq,tp);
2,029✔
211
            }
2,029✔
212
            break;
2,232✔
213
        }
×
214

215
        case GRE_PROTO_PPP:
5,957✔
216
        {
5,957✔
217
            if (gre_pptp_h && !gre_pptp_h->payload_length)
5,957✔
218
                return TM_ECODE_OK;
886✔
219

220
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
5,071✔
221
                    len - header_len, DECODE_TUNNEL_PPP);
5,071✔
222
            if (tp != NULL) {
5,071✔
223
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
4,401✔
224
                PacketEnqueueNoLock(&tv->decode_pq,tp);
4,401✔
225
            }
4,401✔
226
            break;
5,071✔
227
        }
5,957✔
228

229
        case ETHERNET_TYPE_IPV6:
260✔
230
        {
260✔
231
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
260✔
232
                    len - header_len, DECODE_TUNNEL_IPV6);
260✔
233
            if (tp != NULL) {
260✔
234
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
66✔
235
                PacketEnqueueNoLock(&tv->decode_pq,tp);
66✔
236
            }
66✔
237
            break;
260✔
238
        }
5,957✔
239

240
        case ETHERNET_TYPE_VLAN:
657✔
241
        {
657✔
242
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
657✔
243
                    len - header_len, DECODE_TUNNEL_VLAN);
657✔
244
            if (tp != NULL) {
657✔
245
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
411✔
246
                PacketEnqueueNoLock(&tv->decode_pq,tp);
411✔
247
            }
411✔
248
            break;
657✔
249
        }
5,957✔
250

251
        case ETHERNET_TYPE_ERSPAN:
2,106✔
252
        {
2,106✔
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,
2,106✔
258
                    GRE_FLAG_ISSET_SQ(greh) == 0 ? DECODE_TUNNEL_ERSPANI : DECODE_TUNNEL_ERSPANII);
2,106✔
259
            if (tp != NULL) {
2,106✔
260
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
267✔
261
                PacketEnqueueNoLock(&tv->decode_pq,tp);
267✔
262
            }
267✔
263
            break;
2,106✔
264
        }
5,957✔
265

266
        case ETHERNET_TYPE_BRIDGE:
314✔
267
        {
314✔
268
            Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
314✔
269
                    len - header_len, DECODE_TUNNEL_ETHERNET);
314✔
270
            if (tp != NULL) {
314✔
271
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
248✔
272
                PacketEnqueueNoLock(&tv->decode_pq,tp);
248✔
273
            }
248✔
274
            break;
314✔
275
        }
5,957✔
276

277
        case ETHERNET_TYPE_ARP: {
90✔
278
            Packet *tp = PacketTunnelPktSetup(
90✔
279
                    tv, dtv, p, pkt + header_len, len - header_len, DECODE_TUNNEL_ARP);
90✔
280
            if (tp != NULL) {
90✔
281
                PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
19✔
282
                PacketEnqueueNoLock(&tv->decode_pq, tp);
19✔
283
            }
19✔
284
            break;
90✔
285
        }
5,957✔
286

287
        default:
2,915✔
288
            return TM_ECODE_OK;
2,915✔
289
    }
14,531✔
290
    return TM_ECODE_OK;
10,730✔
291
}
14,531✔
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)
UNCOV
396
{
×
397
#ifdef UNITTESTS
398
    UtRegisterTest("DecodeGREtest01", DecodeGREtest01);
399
    UtRegisterTest("DecodeGREtest02", DecodeGREtest02);
400
    UtRegisterTest("DecodeGREtest03", DecodeGREtest03);
401
#endif /* UNITTESTS */
UNCOV
402
}
×
403
/**
404
 * @}
405
 */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc