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  int 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, 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, 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, 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, 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 
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  memset(p, 0, SIZE_OF_PACKET);
159 
160  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
161 
163  ret = 0;
164  }
165 
166  SCFree(p);
167  return ret;
168 }
169 
170 static int DecodeMPLSTestPacketTooSmall(void)
171 {
172  ThreadVars tv;
174 
175  memset(&dtv, 0, sizeof(DecodeThreadVars));
176  memset(&tv, 0, sizeof(ThreadVars));
177 
178  Packet *p0 = SCCalloc(1, SIZE_OF_PACKET);
179  memset(p0, 0, SIZE_OF_PACKET);
180  uint8_t pkt0[] = { 0x00, 0x01, 0x51, 0xff };
181  DecodeMPLS(&tv, &dtv, p0, pkt0, sizeof(pkt0));
183  SCFree(p0);
184 
185  Packet *p1 = SCCalloc(1, SIZE_OF_PACKET);
186  FAIL_IF_NULL(p1);
187  uint8_t pkt1[] = { 0x00, 0x01, 0x51, 0xff, 0x45 };
188  DecodeMPLS(&tv, &dtv, p1, pkt1, sizeof(pkt1));
190  SCFree(p1);
191 
192  Packet *p2 = SCCalloc(1, SIZE_OF_PACKET);
193  FAIL_IF_NULL(p2);
194  uint8_t pkt2[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01 };
195  DecodeMPLS(&tv, &dtv, p2, pkt2, sizeof(pkt2));
197  SCFree(p2);
198 
199  Packet *p3 = SCCalloc(1, SIZE_OF_PACKET);
200  FAIL_IF_NULL(p3);
201  uint8_t pkt3[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01, 0x02 };
202  DecodeMPLS(&tv, &dtv, p3, pkt3, sizeof(pkt3));
204  SCFree(p3);
205 
206  // This should not create a too small event is it has one more byte
207  // than required.
208  Packet *p4 = SCCalloc(1, SIZE_OF_PACKET);
209  FAIL_IF_NULL(p4);
210  uint8_t pkt4[] = { 0x00, 0x01, 0x51, 0xff, 0x45, 0x01, 0x02, 0x03 };
211  DecodeMPLS(&tv, &dtv, p4, pkt4, sizeof(pkt4));
213  SCFree(p4);
214 
215  PASS;
216 }
217 
218 static int DecodeMPLSTestBadLabelRouterAlert(void)
219 {
220  int ret = 1;
221  uint8_t pkt[] = {
222  0x00, 0x00, 0x11, 0xff, 0x45, 0x00, 0x00, 0x64,
223  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
224  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
225  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
226  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
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  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
235  };
236 
238  if (unlikely(p == NULL)) {
239  return 0;
240  }
241  ThreadVars tv;
243 
244  memset(&dtv, 0, sizeof(DecodeThreadVars));
245  memset(&tv, 0, sizeof(ThreadVars));
246  memset(p, 0, SIZE_OF_PACKET);
247 
248  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
249 
251  ret = 0;
252  }
253 
254  SCFree(p);
255  return ret;
256 }
257 
258 static int DecodeMPLSTestBadLabelImplicitNull(void)
259 {
260  int ret = 1;
261  uint8_t pkt[] = {
262  0x00, 0x00, 0x31, 0xff, 0x45, 0x00, 0x00, 0x64,
263  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
264  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
265  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
266  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
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  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
274  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
275  };
276 
278  if (unlikely(p == NULL)) {
279  return 0;
280  }
281  ThreadVars tv;
283 
284  memset(&dtv, 0, sizeof(DecodeThreadVars));
285  memset(&tv, 0, sizeof(ThreadVars));
286  memset(p, 0, SIZE_OF_PACKET);
287 
288  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
289 
291  ret = 0;
292  }
293 
294  SCFree(p);
295  return ret;
296 }
297 
298 static int DecodeMPLSTestBadLabelReserved(void)
299 {
300  int ret = 1;
301  uint8_t pkt[] = {
302  0x00, 0x00, 0x51, 0xff, 0x45, 0x00, 0x00, 0x64,
303  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
304  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
305  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
306  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
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  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  };
316 
318  if (unlikely(p == NULL)) {
319  return 0;
320  }
321  ThreadVars tv;
323 
324  memset(&dtv, 0, sizeof(DecodeThreadVars));
325  memset(&tv, 0, sizeof(ThreadVars));
326  memset(p, 0, SIZE_OF_PACKET);
327 
328  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
329 
331  ret = 0;
332  }
333 
334  SCFree(p);
335  return ret;
336 }
337 
338 static int DecodeMPLSTestUnknownPayloadType(void)
339 {
340  int ret = 1;
341 
342  /* Valid label: 21.
343  * Unknown payload type: 1.
344  */
345  uint8_t pkt[] = {
346  0x00, 0x01, 0x51, 0xff, 0x15, 0x00, 0x00, 0x64,
347  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
348  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
349  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
350  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
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  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
356  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
357  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
358  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
359  };
360 
362  if (unlikely(p == NULL)) {
363  return 0;
364  }
365  ThreadVars tv;
367 
368  memset(&dtv, 0, sizeof(DecodeThreadVars));
369  memset(&tv, 0, sizeof(ThreadVars));
370  memset(p, 0, SIZE_OF_PACKET);
371 
372  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt));
373 
375  ret = 0;
376  }
377 
378  SCFree(p);
379  return ret;
380 }
381 
382 #endif /* UNITTESTS */
383 
385 {
386 #ifdef UNITTESTS
387  UtRegisterTest("DecodeMPLSTestHeaderTooSmall",
388  DecodeMPLSTestHeaderTooSmall);
389  UtRegisterTest("DecodeMPLSTestPacketTooSmall",
390  DecodeMPLSTestPacketTooSmall);
391  UtRegisterTest("DecodeMPLSTestBadLabelRouterAlert",
392  DecodeMPLSTestBadLabelRouterAlert);
393  UtRegisterTest("DecodeMPLSTestBadLabelImplicitNull",
394  DecodeMPLSTestBadLabelImplicitNull);
395  UtRegisterTest("DecodeMPLSTestBadLabelReserved",
396  DecodeMPLSTestBadLabelReserved);
397  UtRegisterTest("DecodeMPLSTestUnknownPayloadType",
398  DecodeMPLSTestUnknownPayloadType);
399 #endif /* UNITTESTS */
400 }
ENGINE_SET_EVENT
#define ENGINE_SET_EVENT(p, e)
Definition: decode.h:1036
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
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:1051
MPLS_BAD_LABEL_ROUTER_ALERT
@ MPLS_BAD_LABEL_ROUTER_ALERT
Definition: decode-events.h:189
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_HEADER_TOO_SMALL
@ MPLS_HEADER_TOO_SMALL
Definition: decode-events.h:187
MPLS_UNKNOWN_PAYLOAD_TYPE
@ MPLS_UNKNOWN_PAYLOAD_TYPE
Definition: decode-events.h:192
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:81
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:80
MPLS_LABEL_NULL
#define MPLS_LABEL_NULL
Definition: decode-mpls.c:39
DecodeMPLSRegisterTests
void DecodeMPLSRegisterTests(void)
Definition: decode-mpls.c:384
decode.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
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:634
MPLS_LABEL
#define MPLS_LABEL(shim)
Definition: decode-mpls.c:41
Packet_
Definition: decode.h:414
DecodeIPV6
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
Definition: decode-ipv6.c:570
MPLS_PROTO_IPV4
#define MPLS_PROTO_IPV4
Definition: decode-mpls.c:46
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:30
MPLS_PKT_TOO_SMALL
@ MPLS_PKT_TOO_SMALL
Definition: decode-events.h:188
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:29
util-validate.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
MPLS_LABEL_IPV6
#define MPLS_LABEL_IPV6
Definition: decode-mpls.c:38
MPLS_BAD_LABEL_IMPLICIT_NULL
@ MPLS_BAD_LABEL_IMPLICIT_NULL
Definition: decode-events.h:190
DecodeThreadVars_::counter_mpls
uint16_t counter_mpls
Definition: decode.h:676
SCFree
#define SCFree(p)
Definition: util-mem.h:61
MPLS_BAD_LABEL_RESERVED
@ MPLS_BAD_LABEL_RESERVED
Definition: decode-events.h:191
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:638
ENGINE_SET_INVALID_EVENT
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:1044
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