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 
131 end:
132  if (event) {
133  ENGINE_SET_EVENT(p, event);
134  }
135  return TM_ECODE_OK;
136 }
137 
138 #ifdef UNITTESTS
139 
140 static int DecodeMPLSTestHeaderTooSmall(void)
141 {
142  int ret = 1;
143 
144  /* A packet that is too small to have a complete MPLS header. */
145  uint8_t pkt[] = {
146  0x00, 0x00, 0x11
147  };
148 
149  Packet *p = PacketGetFromAlloc();
150  if (unlikely(p == NULL)) {
151  return 0;
152  }
153  ThreadVars tv;
155 
156  memset(&dtv, 0, sizeof(DecodeThreadVars));
157  memset(&tv, 0, sizeof(ThreadVars));
158 
159  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
160 
162  ret = 0;
163  }
164 
165  SCFree(p);
166  return ret;
167 }
168 
169 static int DecodeMPLSTestPacketTooSmall(void)
170 {
171  ThreadVars tv;
173 
174  memset(&dtv, 0, sizeof(DecodeThreadVars));
175  memset(&tv, 0, sizeof(ThreadVars));
176 
177  Packet *p0 = SCCalloc(1, SIZE_OF_PACKET);
178  memset(p0, 0, SIZE_OF_PACKET);
179  uint8_t pkt0[] = { 0x00, 0x01, 0x51, 0xff };
180  DecodeMPLS(&tv, &dtv, p0, pkt0, sizeof(pkt0));
182  SCFree(p0);
183 
184  Packet *p1 = SCCalloc(1, SIZE_OF_PACKET);
185  FAIL_IF_NULL(p1);
186  uint8_t pkt1[] = { 0x00, 0x01, 0x51, 0xff, 0x45 };
187  DecodeMPLS(&tv, &dtv, p1, pkt1, sizeof(pkt1));
189  SCFree(p1);
190 
191  Packet *p2 = SCCalloc(1, SIZE_OF_PACKET);
192  FAIL_IF_NULL(p2);
193  uint8_t pkt2[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01 };
194  DecodeMPLS(&tv, &dtv, p2, pkt2, sizeof(pkt2));
196  SCFree(p2);
197 
198  Packet *p3 = SCCalloc(1, SIZE_OF_PACKET);
199  FAIL_IF_NULL(p3);
200  uint8_t pkt3[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01, 0x02 };
201  DecodeMPLS(&tv, &dtv, p3, pkt3, sizeof(pkt3));
203  SCFree(p3);
204 
205  // This should not create a too small event is it has one more byte
206  // than required.
207  Packet *p4 = SCCalloc(1, SIZE_OF_PACKET);
208  FAIL_IF_NULL(p4);
209  uint8_t pkt4[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01, 0x02, 0x03 };
210  DecodeMPLS(&tv, &dtv, p4, pkt4, sizeof(pkt4));
212  SCFree(p4);
213 
214  PASS;
215 }
216 
217 static int DecodeMPLSTestBadLabelRouterAlert(void)
218 {
219  int ret = 1;
220  uint8_t pkt[] = {
221  0x00, 0x00, 0x11, 0xff, 0x45, 0x00, 0x00, 0x64,
222  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
223  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
224  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
225  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
226  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
227  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
228  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
229  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
230  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
231  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
232  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
233  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
234  };
235 
236  Packet *p = PacketGetFromAlloc();
237  if (unlikely(p == NULL)) {
238  return 0;
239  }
240  ThreadVars tv;
242 
243  memset(&dtv, 0, sizeof(DecodeThreadVars));
244  memset(&tv, 0, sizeof(ThreadVars));
245 
246  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
247 
249  ret = 0;
250  }
251 
252  SCFree(p);
253  return ret;
254 }
255 
256 static int DecodeMPLSTestBadLabelImplicitNull(void)
257 {
258  int ret = 1;
259  uint8_t pkt[] = {
260  0x00, 0x00, 0x31, 0xff, 0x45, 0x00, 0x00, 0x64,
261  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
262  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
263  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
264  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
265  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
266  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
267  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
268  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
269  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
270  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
271  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
272  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
273  };
274 
275  Packet *p = PacketGetFromAlloc();
276  if (unlikely(p == NULL)) {
277  return 0;
278  }
279  ThreadVars tv;
281 
282  memset(&dtv, 0, sizeof(DecodeThreadVars));
283  memset(&tv, 0, sizeof(ThreadVars));
284 
285  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
286 
288  ret = 0;
289  }
290 
291  SCFree(p);
292  return ret;
293 }
294 
295 static int DecodeMPLSTestBadLabelReserved(void)
296 {
297  int ret = 1;
298  uint8_t pkt[] = {
299  0x00, 0x00, 0x51, 0xff, 0x45, 0x00, 0x00, 0x64,
300  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
301  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
302  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
303  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
304  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
305  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
306  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
307  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
308  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
309  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
310  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
311  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
312  };
313 
314  Packet *p = PacketGetFromAlloc();
315  if (unlikely(p == NULL)) {
316  return 0;
317  }
318  ThreadVars tv;
320 
321  memset(&dtv, 0, sizeof(DecodeThreadVars));
322  memset(&tv, 0, sizeof(ThreadVars));
323 
324  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
325 
327  ret = 0;
328  }
329 
330  SCFree(p);
331  return ret;
332 }
333 
334 static int DecodeMPLSTestUnknownPayloadType(void)
335 {
336  int ret = 1;
337 
338  /* Valid label: 21.
339  * Unknown payload type: 1.
340  */
341  uint8_t pkt[] = {
342  0x00, 0x01, 0x51, 0xff, 0x15, 0x00, 0x00, 0x64,
343  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
344  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
345  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
346  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
347  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
348  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
349  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
350  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
351  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
352  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
353  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
354  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
355  };
356 
357  Packet *p = PacketGetFromAlloc();
358  if (unlikely(p == NULL)) {
359  return 0;
360  }
361  ThreadVars tv;
363 
364  memset(&dtv, 0, sizeof(DecodeThreadVars));
365  memset(&tv, 0, sizeof(ThreadVars));
366 
367  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
368 
370  ret = 0;
371  }
372 
373  SCFree(p);
374  return ret;
375 }
376 
377 #endif /* UNITTESTS */
378 
380 {
381 #ifdef UNITTESTS
382  UtRegisterTest("DecodeMPLSTestHeaderTooSmall",
383  DecodeMPLSTestHeaderTooSmall);
384  UtRegisterTest("DecodeMPLSTestPacketTooSmall",
385  DecodeMPLSTestPacketTooSmall);
386  UtRegisterTest("DecodeMPLSTestBadLabelRouterAlert",
387  DecodeMPLSTestBadLabelRouterAlert);
388  UtRegisterTest("DecodeMPLSTestBadLabelImplicitNull",
389  DecodeMPLSTestBadLabelImplicitNull);
390  UtRegisterTest("DecodeMPLSTestBadLabelReserved",
391  DecodeMPLSTestBadLabelReserved);
392  UtRegisterTest("DecodeMPLSTestUnknownPayloadType",
393  DecodeMPLSTestUnknownPayloadType);
394 #endif /* UNITTESTS */
395 }
ENGINE_SET_EVENT
#define ENGINE_SET_EVENT(p, e)
Definition: decode.h:1059
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
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:169
MPLS_BAD_LABEL_ROUTER_ALERT
@ MPLS_BAD_LABEL_ROUTER_ALERT
Definition: decode-events.h:189
MPLS_UNKNOWN_PAYLOAD_TYPE
@ MPLS_UNKNOWN_PAYLOAD_TYPE
Definition: decode-events.h:192
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
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:1074
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
MPLS_PKT_TOO_SMALL
@ MPLS_PKT_TOO_SMALL
Definition: decode-events.h:188
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:83
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:82
MPLS_LABEL_NULL
#define MPLS_LABEL_NULL
Definition: decode-mpls.c:39
DecodeMPLSRegisterTests
void DecodeMPLSRegisterTests(void)
Definition: decode-mpls.c:379
decode.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
MPLS_BAD_LABEL_IMPLICIT_NULL
@ MPLS_BAD_LABEL_IMPLICIT_NULL
Definition: decode-events.h:190
MPLS_PROTO_ETHERNET_PW
#define MPLS_PROTO_ETHERNET_PW
Definition: decode-mpls.c:45
DecodeMPLS
int DecodeMPLS(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-mpls.c:49
SIZE_OF_PACKET
#define SIZE_OF_PACKET
Definition: decode.h:650
MPLS_LABEL
#define MPLS_LABEL(shim)
Definition: decode-mpls.c:41
Packet_
Definition: decode.h:427
DecodeIPV6
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
Definition: decode-ipv6.c:572
MPLS_PROTO_IPV4
#define MPLS_PROTO_IPV4
Definition: decode-mpls.c:46
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:30
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
MPLS_HEADER_TOO_SMALL
@ MPLS_HEADER_TOO_SMALL
Definition: decode-events.h:187
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
util-validate.h
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:173
MPLS_LABEL_IPV6
#define MPLS_LABEL_IPV6
Definition: decode-mpls.c:38
DecodeThreadVars_::counter_mpls
uint16_t counter_mpls
Definition: decode.h:692
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:654
ENGINE_SET_INVALID_EVENT
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:1067
MPLS_BAD_LABEL_RESERVED
@ MPLS_BAD_LABEL_RESERVED
Definition: decode-events.h:191
DecodeIPV4
int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
Definition: decode-ipv4.c:517
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:111
DecodeEthernet
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-ethernet.c:42
MPLS_PW_LEN
#define MPLS_PW_LEN
Definition: decode-mpls.c:33