• 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

97.7
/src/decode-mpls.c
1
/* Copyright (C) 2014-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
 * \file
20
 *
21
 * \author Jason Ish <jason.ish@emulex.com>
22
 *
23
 * MPLS decoder.
24
 */
25

26
#include "suricata-common.h"
27
#include "decode.h"
28

29
#include "util-validate.h"
30
#include "util-unittest.h"
31

32
#define MPLS_HEADER_LEN         4
198,971✔
33
#define MPLS_PW_LEN             4
14,731✔
34
#define MPLS_MAX_RESERVED_LABEL 15
6,276✔
35

36
#define MPLS_LABEL_IPV4         0
7,378✔
37
#define MPLS_LABEL_ROUTER_ALERT 1
7,138✔
38
#define MPLS_LABEL_IPV6         2
6,701✔
39
#define MPLS_LABEL_NULL         3
6,471✔
40

41
#define MPLS_LABEL(shim)        SCNtohl(shim) >> 12
7,378✔
42
#define MPLS_BOTTOM(shim)       ((SCNtohl(shim) >> 8) & 0x1)
65,791✔
43

44
/* Inner protocol guessing values. */
45
#define MPLS_PROTO_ETHERNET_PW  0
4,341✔
46
#define MPLS_PROTO_IPV4         4
580✔
47
#define MPLS_PROTO_IPV6         6
423✔
48

49
int DecodeMPLS(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
50
        const uint8_t *pkt, uint32_t len)
51
{
9,172✔
52
    DEBUG_VALIDATE_BUG_ON(pkt == NULL);
9,172✔
53

54
    uint32_t shim;
9,172✔
55
    int label;
9,172✔
56
    uint8_t event = 0;
9,172✔
57

58
    StatsCounterIncr(&tv->stats, dtv->counter_mpls);
9,172✔
59

60
    if (!PacketIncreaseCheckLayers(p)) {
9,172✔
61
        return TM_ECODE_FAILED;
196✔
62
    }
196✔
63
    do {
67,389✔
64
        if (len < MPLS_HEADER_LEN) {
67,389✔
65
            ENGINE_SET_INVALID_EVENT(p, MPLS_HEADER_TOO_SMALL);
1,598✔
66
            return TM_ECODE_FAILED;
1,598✔
67
        }
1,598✔
68
        memcpy(&shim, pkt, sizeof(shim));
65,791✔
69
        pkt += MPLS_HEADER_LEN;
65,791✔
70
        len -= MPLS_HEADER_LEN;
65,791✔
71
    } while (MPLS_BOTTOM(shim) == 0);
65,791✔
72

73
    label = MPLS_LABEL(shim);
7,378✔
74
    if (label == MPLS_LABEL_IPV4) {
7,378✔
75
        if (len > USHRT_MAX) {
240✔
76
            return TM_ECODE_FAILED;
10✔
77
        }
10✔
78
        return DecodeIPV4(tv, dtv, p, pkt, (uint16_t)len);
230✔
79
    }
240✔
80
    else if (label == MPLS_LABEL_ROUTER_ALERT) {
7,138✔
81
        /* Not valid at the bottom of the stack. */
82
        event = MPLS_BAD_LABEL_ROUTER_ALERT;
437✔
83
    }
437✔
84
    else if (label == MPLS_LABEL_IPV6) {
6,701✔
85
        if (len > USHRT_MAX) {
230✔
86
            return TM_ECODE_FAILED;
19✔
87
        }
19✔
88
        return DecodeIPV6(tv, dtv, p, pkt, (uint16_t)len);
211✔
89
    }
230✔
90
    else if (label == MPLS_LABEL_NULL) {
6,471✔
91
        /* Shouldn't appear on the wire. */
92
        event = MPLS_BAD_LABEL_IMPLICIT_NULL;
195✔
93
    }
195✔
94
    else if (label < MPLS_MAX_RESERVED_LABEL) {
6,276✔
95
        event = MPLS_BAD_LABEL_RESERVED;
227✔
96
    }
227✔
97

98
    if (event) {
6,908✔
99
        goto end;
859✔
100
    }
859✔
101

102
    // Make sure we still have enough data. While we only need 1 byte to test
103
    // for IPv4 and IPv4, we need for to check for ethernet.
104
    if (len < MPLS_PW_LEN) {
6,049✔
105
        ENGINE_SET_INVALID_EVENT(p, MPLS_PKT_TOO_SMALL);
426✔
106
        return TM_ECODE_FAILED;
426✔
107
    }
426✔
108

109
    /* Best guess at inner packet. */
110
    switch (pkt[0] >> 4) {
5,623✔
111
    case MPLS_PROTO_IPV4:
580✔
112
        if (len > USHRT_MAX) {
580✔
113
            return TM_ECODE_FAILED;
11✔
114
        }
11✔
115
        DecodeIPV4(tv, dtv, p, pkt, (uint16_t)len);
569✔
116
        break;
569✔
117
    case MPLS_PROTO_IPV6:
423✔
118
        if (len > USHRT_MAX) {
423✔
119
            return TM_ECODE_FAILED;
11✔
120
        }
11✔
121
        DecodeIPV6(tv, dtv, p, pkt, (uint16_t)len);
412✔
122
        break;
412✔
123
    case MPLS_PROTO_ETHERNET_PW:
4,341✔
124
        DecodeEthernet(tv, dtv, p, pkt + MPLS_PW_LEN, len - MPLS_PW_LEN);
4,341✔
125
        break;
4,341✔
126
    default:
279✔
127
        ENGINE_SET_INVALID_EVENT(p, MPLS_UNKNOWN_PAYLOAD_TYPE);
279✔
128
        return TM_ECODE_OK;
279✔
129
    }
5,623✔
130

131
end:
6,181✔
132
    if (event) {
6,181✔
133
        ENGINE_SET_EVENT(p, event);
859✔
134
    }
859✔
135
    return TM_ECODE_OK;
6,181✔
136
}
5,623✔
137

138
#ifdef UNITTESTS
139

140
static int DecodeMPLSTestHeaderTooSmall(void)
141
{
142
    /* A packet that is too small to have a complete MPLS header. */
143
    uint8_t pkt[] = {
144
        0x00, 0x00, 0x11
145
    };
146

147
    Packet *p = PacketGetFromAlloc();
148
    FAIL_IF_NULL(p);
149
    ThreadVars tv;
150
    DecodeThreadVars dtv;
151
    memset(&dtv, 0, sizeof(DecodeThreadVars));
152
    memset(&tv,  0, sizeof(ThreadVars));
153

154
    DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
155
    FAIL_IF(!ENGINE_ISSET_EVENT(p, MPLS_HEADER_TOO_SMALL));
156

157
    PacketFree(p);
158
    PASS;
159
}
160

161
static int DecodeMPLSTestPacketTooSmall(void)
162
{
163
    ThreadVars tv;
164
    DecodeThreadVars dtv;
165
    memset(&dtv, 0, sizeof(DecodeThreadVars));
166
    memset(&tv,  0, sizeof(ThreadVars));
167

168
    Packet *p = PacketGetFromAlloc();
169
    FAIL_IF_NULL(p);
170
    uint8_t pkt0[] = { 0x00, 0x01, 0x51, 0xff };
171
    DecodeMPLS(&tv, &dtv, p, pkt0, sizeof(pkt0));
172
    FAIL_IF_NOT(ENGINE_ISSET_EVENT(p, MPLS_PKT_TOO_SMALL));
173
    PacketFree(p);
174

175
    p = PacketGetFromAlloc();
176
    FAIL_IF_NULL(p);
177
    uint8_t pkt1[] = { 0x00, 0x01, 0x51, 0xff, 0x45 };
178
    DecodeMPLS(&tv, &dtv, p, pkt1, sizeof(pkt1));
179
    FAIL_IF_NOT(ENGINE_ISSET_EVENT(p, MPLS_PKT_TOO_SMALL));
180
    PacketFree(p);
181

182
    p = PacketGetFromAlloc();
183
    FAIL_IF_NULL(p);
184
    uint8_t pkt2[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01 };
185
    DecodeMPLS(&tv, &dtv, p, pkt2, sizeof(pkt2));
186
    FAIL_IF_NOT(ENGINE_ISSET_EVENT(p, MPLS_PKT_TOO_SMALL));
187
    PacketFree(p);
188

189
    p = PacketGetFromAlloc();
190
    FAIL_IF_NULL(p);
191
    uint8_t pkt3[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01, 0x02 };
192
    DecodeMPLS(&tv, &dtv, p, pkt3, sizeof(pkt3));
193
    FAIL_IF_NOT(ENGINE_ISSET_EVENT(p, MPLS_PKT_TOO_SMALL));
194
    PacketFree(p);
195

196
    // This should not create a too small event is it has one more byte
197
    // than required.
198
    p = PacketGetFromAlloc();
199
    FAIL_IF_NULL(p);
200
    uint8_t pkt4[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01, 0x02, 0x03 };
201
    DecodeMPLS(&tv, &dtv, p, pkt4, sizeof(pkt4));
202
    FAIL_IF(ENGINE_ISSET_EVENT(p, MPLS_PKT_TOO_SMALL));
203
    PacketFree(p);
204

205
    PASS;
206
}
207

208
static int DecodeMPLSTestBadLabelRouterAlert(void)
209
{
210
    uint8_t pkt[] = {
211
        0x00, 0x00, 0x11, 0xff, 0x45, 0x00, 0x00, 0x64,
212
        0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
213
        0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
214
        0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
215
        0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
216
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
217
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
218
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
219
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
220
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
221
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
222
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
223
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
224
    };
225

226
    Packet *p = PacketGetFromAlloc();
227
    FAIL_IF_NULL(p);
228
    ThreadVars tv;
229
    DecodeThreadVars dtv;
230

231
    memset(&dtv, 0, sizeof(DecodeThreadVars));
232
    memset(&tv,  0, sizeof(ThreadVars));
233

234
    DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
235
    FAIL_IF(!ENGINE_ISSET_EVENT(p, MPLS_BAD_LABEL_ROUTER_ALERT));
236

237
    PacketFree(p);
238
    PASS;
239
}
240

241
static int DecodeMPLSTestBadLabelImplicitNull(void)
242
{
243
    uint8_t pkt[] = {
244
        0x00, 0x00, 0x31, 0xff, 0x45, 0x00, 0x00, 0x64,
245
        0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
246
        0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
247
        0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
248
        0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
249
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
250
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
251
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
252
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
253
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
254
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
255
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
256
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
257
    };
258

259
    Packet *p = PacketGetFromAlloc();
260
    FAIL_IF_NULL(p);
261
    ThreadVars tv;
262
    DecodeThreadVars dtv;
263
    memset(&dtv, 0, sizeof(DecodeThreadVars));
264
    memset(&tv,  0, sizeof(ThreadVars));
265

266
    DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
267
    FAIL_IF(!ENGINE_ISSET_EVENT(p, MPLS_BAD_LABEL_IMPLICIT_NULL));
268

269
    PacketFree(p);
270
    PASS;
271
}
272

273
static int DecodeMPLSTestBadLabelReserved(void)
274
{
275
    uint8_t pkt[] = {
276
        0x00, 0x00, 0x51, 0xff, 0x45, 0x00, 0x00, 0x64,
277
        0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
278
        0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
279
        0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
280
        0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
281
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
282
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
283
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
284
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
285
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
286
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
287
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
288
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
289
    };
290

291
    Packet *p = PacketGetFromAlloc();
292
    FAIL_IF_NULL(p);
293
    ThreadVars tv;
294
    DecodeThreadVars dtv;
295
    memset(&dtv, 0, sizeof(DecodeThreadVars));
296
    memset(&tv,  0, sizeof(ThreadVars));
297

298
    DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
299
    FAIL_IF(!ENGINE_ISSET_EVENT(p, MPLS_BAD_LABEL_RESERVED));
300

301
    PacketFree(p);
302
    PASS;
303
}
304

305
static int DecodeMPLSTestUnknownPayloadType(void)
306
{
307
    /* Valid label: 21.
308
     * Unknown payload type: 1.
309
     */
310
    uint8_t pkt[] = {
311
        0x00, 0x01, 0x51, 0xff, 0x15, 0x00, 0x00, 0x64,
312
        0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
313
        0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
314
        0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
315
        0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
316
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
317
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
318
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
319
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
320
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
321
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
322
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
323
        0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
324
    };
325

326
    Packet *p = PacketGetFromAlloc();
327
    FAIL_IF_NULL(p);
328
    ThreadVars tv;
329
    DecodeThreadVars dtv;
330
    memset(&dtv, 0, sizeof(DecodeThreadVars));
331
    memset(&tv,  0, sizeof(ThreadVars));
332

333
    DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
334
    FAIL_IF(!ENGINE_ISSET_EVENT(p, MPLS_UNKNOWN_PAYLOAD_TYPE));
335

336
    PacketFree(p);
337
    PASS;
338
}
339

340
#endif /* UNITTESTS */
341

342
void DecodeMPLSRegisterTests(void)
UNCOV
343
{
×
344
#ifdef UNITTESTS
345
    UtRegisterTest("DecodeMPLSTestHeaderTooSmall",
346
                   DecodeMPLSTestHeaderTooSmall);
347
    UtRegisterTest("DecodeMPLSTestPacketTooSmall",
348
                   DecodeMPLSTestPacketTooSmall);
349
    UtRegisterTest("DecodeMPLSTestBadLabelRouterAlert",
350
                   DecodeMPLSTestBadLabelRouterAlert);
351
    UtRegisterTest("DecodeMPLSTestBadLabelImplicitNull",
352
                   DecodeMPLSTestBadLabelImplicitNull);
353
    UtRegisterTest("DecodeMPLSTestBadLabelReserved",
354
                   DecodeMPLSTestBadLabelReserved);
355
    UtRegisterTest("DecodeMPLSTestUnknownPayloadType",
356
                   DecodeMPLSTestUnknownPayloadType);
357
#endif /* UNITTESTS */
UNCOV
358
}
×
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