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  return DecodeIPV6(tv, dtv, p, pkt, len);
86  }
87  else if (label == MPLS_LABEL_NULL) {
88  /* Shouldn't appear on the wire. */
90  }
91  else if (label < MPLS_MAX_RESERVED_LABEL) {
93  }
94 
95  if (event) {
96  goto end;
97  }
98 
99  // Make sure we still have enough data. While we only need 1 byte to test
100  // for IPv4 and IPv4, we need for to check for ethernet.
101  if (len < MPLS_PW_LEN) {
103  return TM_ECODE_FAILED;
104  }
105 
106  /* Best guess at inner packet. */
107  switch (pkt[0] >> 4) {
108  case MPLS_PROTO_IPV4:
109  if (len > USHRT_MAX) {
110  return TM_ECODE_FAILED;
111  }
112  DecodeIPV4(tv, dtv, p, pkt, (uint16_t)len);
113  break;
114  case MPLS_PROTO_IPV6:
115  DecodeIPV6(tv, dtv, p, pkt, len);
116  break;
119  break;
120  default:
122  return TM_ECODE_OK;
123  }
124 
125 end:
126  if (event) {
127  ENGINE_SET_EVENT(p, event);
128  }
129  return TM_ECODE_OK;
130 }
131 
132 #ifdef UNITTESTS
133 
134 static int DecodeMPLSTestHeaderTooSmall(void)
135 {
136  /* A packet that is too small to have a complete MPLS header. */
137  uint8_t pkt[] = {
138  0x00, 0x00, 0x11
139  };
140 
142  FAIL_IF_NULL(p);
143  ThreadVars tv;
145  memset(&dtv, 0, sizeof(DecodeThreadVars));
146  memset(&tv, 0, sizeof(ThreadVars));
147 
148  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
150 
151  PacketFree(p);
152  PASS;
153 }
154 
155 static int DecodeMPLSTestPacketTooSmall(void)
156 {
157  ThreadVars tv;
159  memset(&dtv, 0, sizeof(DecodeThreadVars));
160  memset(&tv, 0, sizeof(ThreadVars));
161 
163  FAIL_IF_NULL(p);
164  uint8_t pkt0[] = { 0x00, 0x01, 0x51, 0xff };
165  DecodeMPLS(&tv, &dtv, p, pkt0, sizeof(pkt0));
167  PacketFree(p);
168 
169  p = PacketGetFromAlloc();
170  FAIL_IF_NULL(p);
171  uint8_t pkt1[] = { 0x00, 0x01, 0x51, 0xff, 0x45 };
172  DecodeMPLS(&tv, &dtv, p, pkt1, sizeof(pkt1));
174  PacketFree(p);
175 
176  p = PacketGetFromAlloc();
177  FAIL_IF_NULL(p);
178  uint8_t pkt2[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01 };
179  DecodeMPLS(&tv, &dtv, p, pkt2, sizeof(pkt2));
181  PacketFree(p);
182 
183  p = PacketGetFromAlloc();
184  FAIL_IF_NULL(p);
185  uint8_t pkt3[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01, 0x02 };
186  DecodeMPLS(&tv, &dtv, p, pkt3, sizeof(pkt3));
188  PacketFree(p);
189 
190  // This should not create a too small event is it has one more byte
191  // than required.
192  p = PacketGetFromAlloc();
193  FAIL_IF_NULL(p);
194  uint8_t pkt4[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01, 0x02, 0x03 };
195  DecodeMPLS(&tv, &dtv, p, pkt4, sizeof(pkt4));
197  PacketFree(p);
198 
199  PASS;
200 }
201 
202 static int DecodeMPLSTestBadLabelRouterAlert(void)
203 {
204  uint8_t pkt[] = {
205  0x00, 0x00, 0x11, 0xff, 0x45, 0x00, 0x00, 0x64,
206  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
207  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
208  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
209  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
210  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
211  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
212  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
213  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
214  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
215  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
216  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
217  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
218  };
219 
221  FAIL_IF_NULL(p);
222  ThreadVars tv;
224 
225  memset(&dtv, 0, sizeof(DecodeThreadVars));
226  memset(&tv, 0, sizeof(ThreadVars));
227 
228  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
230 
231  PacketFree(p);
232  PASS;
233 }
234 
235 static int DecodeMPLSTestBadLabelImplicitNull(void)
236 {
237  uint8_t pkt[] = {
238  0x00, 0x00, 0x31, 0xff, 0x45, 0x00, 0x00, 0x64,
239  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
240  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
241  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
242  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
243  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
244  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
245  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
246  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
247  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
248  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
249  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
250  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
251  };
252 
254  FAIL_IF_NULL(p);
255  ThreadVars tv;
257  memset(&dtv, 0, sizeof(DecodeThreadVars));
258  memset(&tv, 0, sizeof(ThreadVars));
259 
260  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
262 
263  PacketFree(p);
264  PASS;
265 }
266 
267 static int DecodeMPLSTestBadLabelReserved(void)
268 {
269  uint8_t pkt[] = {
270  0x00, 0x00, 0x51, 0xff, 0x45, 0x00, 0x00, 0x64,
271  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
272  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
273  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
274  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
275  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
276  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
277  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
278  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
279  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
280  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
281  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
282  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
283  };
284 
286  FAIL_IF_NULL(p);
287  ThreadVars tv;
289  memset(&dtv, 0, sizeof(DecodeThreadVars));
290  memset(&tv, 0, sizeof(ThreadVars));
291 
292  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
294 
295  PacketFree(p);
296  PASS;
297 }
298 
299 static int DecodeMPLSTestUnknownPayloadType(void)
300 {
301  /* Valid label: 21.
302  * Unknown payload type: 1.
303  */
304  uint8_t pkt[] = {
305  0x00, 0x01, 0x51, 0xff, 0x15, 0x00, 0x00, 0x64,
306  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
307  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
308  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
309  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
310  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
311  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
312  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
313  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
314  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
315  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
316  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
317  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
318  };
319 
321  FAIL_IF_NULL(p);
322  ThreadVars tv;
324  memset(&dtv, 0, sizeof(DecodeThreadVars));
325  memset(&tv, 0, sizeof(ThreadVars));
326 
327  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
329 
330  PacketFree(p);
331  PASS;
332 }
333 
334 #endif /* UNITTESTS */
335 
337 {
338 #ifdef UNITTESTS
339  UtRegisterTest("DecodeMPLSTestHeaderTooSmall",
340  DecodeMPLSTestHeaderTooSmall);
341  UtRegisterTest("DecodeMPLSTestPacketTooSmall",
342  DecodeMPLSTestPacketTooSmall);
343  UtRegisterTest("DecodeMPLSTestBadLabelRouterAlert",
344  DecodeMPLSTestBadLabelRouterAlert);
345  UtRegisterTest("DecodeMPLSTestBadLabelImplicitNull",
346  DecodeMPLSTestBadLabelImplicitNull);
347  UtRegisterTest("DecodeMPLSTestBadLabelReserved",
348  DecodeMPLSTestBadLabelReserved);
349  UtRegisterTest("DecodeMPLSTestUnknownPayloadType",
350  DecodeMPLSTestUnknownPayloadType);
351 #endif /* UNITTESTS */
352 }
ENGINE_SET_EVENT
#define ENGINE_SET_EVENT(p, e)
Definition: decode.h:1231
len
uint8_t len
Definition: app-layer-dnp3.h:2
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
ENGINE_ISSET_EVENT
#define ENGINE_ISSET_EVENT(p, e)
Definition: decode.h:1244
MPLS_PROTO_IPV6
#define MPLS_PROTO_IPV6
Definition: decode-mpls.c:47
MPLS_MAX_RESERVED_LABEL
#define MPLS_MAX_RESERVED_LABEL
Definition: decode-mpls.c:34
MPLS_BOTTOM
#define MPLS_BOTTOM(shim)
Definition: decode-mpls.c:42
MPLS_HEADER_LEN
#define MPLS_HEADER_LEN
Definition: decode-mpls.c:32
p
Packet * p
Definition: fuzz_iprep.c:21
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
util-unittest.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
MPLS_LABEL_NULL
#define MPLS_LABEL_NULL
Definition: decode-mpls.c:39
DecodeMPLSRegisterTests
void DecodeMPLSRegisterTests(void)
Definition: decode-mpls.c:336
decode.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
MPLS_UNKNOWN_PAYLOAD_TYPE
@ MPLS_UNKNOWN_PAYLOAD_TYPE
Definition: decode-events.h:212
MPLS_BAD_LABEL_ROUTER_ALERT
@ MPLS_BAD_LABEL_ROUTER_ALERT
Definition: decode-events.h:209
MPLS_PKT_TOO_SMALL
@ MPLS_PKT_TOO_SMALL
Definition: decode-events.h:208
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
MPLS_PROTO_ETHERNET_PW
#define MPLS_PROTO_ETHERNET_PW
Definition: decode-mpls.c:45
StatsCounterIncr
void StatsCounterIncr(StatsThreadContext *stats, StatsCounterId id)
Increments the local counter.
Definition: counters.c:164
PacketFree
void PacketFree(Packet *p)
Return a malloced packet.
Definition: decode.c:221
DecodeMPLS
int DecodeMPLS(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-mpls.c:49
MPLS_BAD_LABEL_IMPLICIT_NULL
@ MPLS_BAD_LABEL_IMPLICIT_NULL
Definition: decode-events.h:210
MPLS_LABEL
#define MPLS_LABEL(shim)
Definition: decode-mpls.c:41
Packet_
Definition: decode.h:516
MPLS_PROTO_IPV4
#define MPLS_PROTO_IPV4
Definition: decode-mpls.c:46
DecodeIPV6
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-ipv6.c:551
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:35
MPLS_LABEL_ROUTER_ALERT
#define MPLS_LABEL_ROUTER_ALERT
Definition: decode-mpls.c:37
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
suricata-common.h
MPLS_LABEL_IPV4
#define MPLS_LABEL_IPV4
Definition: decode-mpls.c:36
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:34
util-validate.h
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:260
MPLS_LABEL_IPV6
#define MPLS_LABEL_IPV6
Definition: decode-mpls.c:38
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:995
DecodeThreadVars_::counter_mpls
StatsCounterId counter_mpls
Definition: decode.h:1048
ENGINE_SET_INVALID_EVENT
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:1239
MPLS_HEADER_TOO_SMALL
@ MPLS_HEADER_TOO_SMALL
Definition: decode-events.h:207
DecodeIPV4
int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
Definition: decode-ipv4.c:515
ThreadVars_::stats
StatsThreadContext stats
Definition: threadvars.h:121
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
DecodeEthernet
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-ethernet.c:42
MPLS_BAD_LABEL_RESERVED
@ MPLS_BAD_LABEL_RESERVED
Definition: decode-events.h:211
MPLS_PW_LEN
#define MPLS_PW_LEN
Definition: decode-mpls.c:33