suricata
decode-mpls.c
Go to the documentation of this file.
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
33#define MPLS_PW_LEN 4
34#define MPLS_MAX_RESERVED_LABEL 15
35
36#define MPLS_LABEL_IPV4 0
37#define MPLS_LABEL_ROUTER_ALERT 1
38#define MPLS_LABEL_IPV6 2
39#define MPLS_LABEL_NULL 3
40
41#define MPLS_LABEL(shim) SCNtohl(shim) >> 12
42#define MPLS_BOTTOM(shim) ((SCNtohl(shim) >> 8) & 0x1)
43
44/* Inner protocol guessing values. */
45#define MPLS_PROTO_ETHERNET_PW 0
46#define MPLS_PROTO_IPV4 4
47#define MPLS_PROTO_IPV6 6
48
50 const uint8_t *pkt, uint32_t len)
51{
52 DEBUG_VALIDATE_BUG_ON(pkt == NULL);
53
54 uint32_t shim;
55 int label;
56 uint8_t event = 0;
57
59
60 if (!PacketIncreaseCheckLayers(p)) {
61 return TM_ECODE_FAILED;
62 }
63 do {
64 if (len < MPLS_HEADER_LEN) {
66 return TM_ECODE_FAILED;
67 }
68 memcpy(&shim, pkt, sizeof(shim));
69 pkt += MPLS_HEADER_LEN;
71 } while (MPLS_BOTTOM(shim) == 0);
72
73 label = MPLS_LABEL(shim);
74 if (label == MPLS_LABEL_IPV4) {
75 if (len > USHRT_MAX) {
76 return TM_ECODE_FAILED;
77 }
78 return DecodeIPV4(tv, dtv, p, pkt, (uint16_t)len);
79 }
80 else if (label == MPLS_LABEL_ROUTER_ALERT) {
81 /* Not valid at the bottom of the stack. */
83 }
84 else if (label == MPLS_LABEL_IPV6) {
85 if (len > USHRT_MAX) {
86 return TM_ECODE_FAILED;
87 }
88 return DecodeIPV6(tv, dtv, p, pkt, (uint16_t)len);
89 }
90 else if (label == MPLS_LABEL_NULL) {
91 /* Shouldn't appear on the wire. */
93 }
94 else if (label < MPLS_MAX_RESERVED_LABEL) {
96 }
97
98 if (event) {
99 goto end;
100 }
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) {
106 return TM_ECODE_FAILED;
107 }
108
109 /* Best guess at inner packet. */
110 switch (pkt[0] >> 4) {
111 case MPLS_PROTO_IPV4:
112 if (len > USHRT_MAX) {
113 return TM_ECODE_FAILED;
114 }
115 DecodeIPV4(tv, dtv, p, pkt, (uint16_t)len);
116 break;
117 case MPLS_PROTO_IPV6:
118 if (len > USHRT_MAX) {
119 return TM_ECODE_FAILED;
120 }
121 DecodeIPV6(tv, dtv, p, pkt, (uint16_t)len);
122 break;
125 break;
126 default:
128 return TM_ECODE_OK;
129 }
130
131end:
132 if (event) {
133 ENGINE_SET_EVENT(p, event);
134 }
135 return TM_ECODE_OK;
136}
137
138#ifdef UNITTESTS
139
140static 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
148 FAIL_IF_NULL(p);
151 memset(&dtv, 0, sizeof(DecodeThreadVars));
152 memset(&tv, 0, sizeof(ThreadVars));
153
154 DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
156
157 PacketFree(p);
158 PASS;
159}
160
161static int DecodeMPLSTestPacketTooSmall(void)
162{
165 memset(&dtv, 0, sizeof(DecodeThreadVars));
166 memset(&tv, 0, sizeof(ThreadVars));
167
169 FAIL_IF_NULL(p);
170 uint8_t pkt0[] = { 0x00, 0x01, 0x51, 0xff };
171 DecodeMPLS(&tv, &dtv, p, pkt0, sizeof(pkt0));
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));
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));
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));
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));
203 PacketFree(p);
204
205 PASS;
206}
207
208static 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
227 FAIL_IF_NULL(p);
230
231 memset(&dtv, 0, sizeof(DecodeThreadVars));
232 memset(&tv, 0, sizeof(ThreadVars));
233
234 DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
236
237 PacketFree(p);
238 PASS;
239}
240
241static 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
260 FAIL_IF_NULL(p);
263 memset(&dtv, 0, sizeof(DecodeThreadVars));
264 memset(&tv, 0, sizeof(ThreadVars));
265
266 DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
268
269 PacketFree(p);
270 PASS;
271}
272
273static 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
292 FAIL_IF_NULL(p);
295 memset(&dtv, 0, sizeof(DecodeThreadVars));
296 memset(&tv, 0, sizeof(ThreadVars));
297
298 DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
300
301 PacketFree(p);
302 PASS;
303}
304
305static 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
327 FAIL_IF_NULL(p);
330 memset(&dtv, 0, sizeof(DecodeThreadVars));
331 memset(&tv, 0, sizeof(ThreadVars));
332
333 DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
335
336 PacketFree(p);
337 PASS;
338}
339
340#endif /* UNITTESTS */
341
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 */
358}
uint8_t len
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition counters.c:166
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
@ MPLS_BAD_LABEL_IMPLICIT_NULL
@ MPLS_BAD_LABEL_ROUTER_ALERT
@ MPLS_UNKNOWN_PAYLOAD_TYPE
@ MPLS_BAD_LABEL_RESERVED
@ MPLS_PKT_TOO_SMALL
@ MPLS_HEADER_TOO_SMALL
int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
void DecodeMPLSRegisterTests(void)
#define MPLS_PROTO_ETHERNET_PW
Definition decode-mpls.c:45
#define MPLS_PROTO_IPV6
Definition decode-mpls.c:47
#define MPLS_PROTO_IPV4
Definition decode-mpls.c:46
#define MPLS_LABEL_IPV4
Definition decode-mpls.c:36
#define MPLS_LABEL_IPV6
Definition decode-mpls.c:38
#define MPLS_LABEL_NULL
Definition decode-mpls.c:39
#define MPLS_BOTTOM(shim)
Definition decode-mpls.c:42
#define MPLS_PW_LEN
Definition decode-mpls.c:33
#define MPLS_MAX_RESERVED_LABEL
Definition decode-mpls.c:34
#define MPLS_HEADER_LEN
Definition decode-mpls.c:32
#define MPLS_LABEL(shim)
Definition decode-mpls.c:41
int DecodeMPLS(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition decode-mpls.c:49
#define MPLS_LABEL_ROUTER_ALERT
Definition decode-mpls.c:37
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition decode.h:1194
#define ENGINE_ISSET_EVENT(p, e)
Definition decode.h:1199
#define ENGINE_SET_EVENT(p, e)
Definition decode.h:1186
DecodeThreadVars * dtv
ThreadVars * tv
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition decode.c:258
void PacketFree(Packet *p)
Return a malloced packet.
Definition decode.c:219
Structure to hold thread specific data for all decode modules.
Definition decode.h:963
uint16_t counter_mpls
Definition decode.h:1009
Per thread variable structure.
Definition threadvars.h:58
@ TM_ECODE_FAILED
@ TM_ECODE_OK
#define DEBUG_VALIDATE_BUG_ON(exp)