suricata
decode-mpls.c
Go to the documentation of this file.
1 /* Copyright (C) 2014 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 #include "util-unittest.h"
29 
30 #define MPLS_HEADER_LEN 4
31 #define MPLS_PW_LEN 4
32 #define MPLS_MAX_RESERVED_LABEL 15
33 
34 #define MPLS_LABEL_IPV4 0
35 #define MPLS_LABEL_ROUTER_ALERT 1
36 #define MPLS_LABEL_IPV6 2
37 #define MPLS_LABEL_NULL 3
38 
39 #define MPLS_LABEL(shim) SCNtohl(shim) >> 12
40 #define MPLS_BOTTOM(shim) ((SCNtohl(shim) >> 8) & 0x1)
41 
42 /* Inner protocol guessing values. */
43 #define MPLS_PROTO_ETHERNET_PW 0
44 #define MPLS_PROTO_IPV4 4
45 #define MPLS_PROTO_IPV6 6
46 
47 int DecodeMPLS(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt,
48  uint32_t len, PacketQueue *pq)
49 {
50  uint32_t shim;
51  int label;
52  int event = 0;
53 
54  StatsIncr(tv, dtv->counter_mpls);
55 
56  do {
57  if (len < MPLS_HEADER_LEN) {
59  return TM_ECODE_FAILED;
60  }
61  shim = *(uint32_t *)pkt;
62  pkt += MPLS_HEADER_LEN;
63  len -= MPLS_HEADER_LEN;
64  } while (MPLS_BOTTOM(shim) == 0);
65 
66  label = MPLS_LABEL(shim);
67  if (label == MPLS_LABEL_IPV4) {
68  if (len > USHRT_MAX) {
69  return TM_ECODE_FAILED;
70  }
71  return DecodeIPV4(tv, dtv, p, pkt, len, pq);
72  }
73  else if (label == MPLS_LABEL_ROUTER_ALERT) {
74  /* Not valid at the bottom of the stack. */
76  }
77  else if (label == MPLS_LABEL_IPV6) {
78  if (len > USHRT_MAX) {
79  return TM_ECODE_FAILED;
80  }
81  return DecodeIPV6(tv, dtv, p, pkt, len, pq);
82  }
83  else if (label == MPLS_LABEL_NULL) {
84  /* Shouldn't appear on the wire. */
86  }
87  else if (label < MPLS_MAX_RESERVED_LABEL) {
89  }
90 
91  if (event) {
92  goto end;
93  }
94 
95  /* Best guess at inner packet. */
96  switch (pkt[0] >> 4) {
97  case MPLS_PROTO_IPV4:
98  if (len > USHRT_MAX) {
99  return TM_ECODE_FAILED;
100  }
101  DecodeIPV4(tv, dtv, p, pkt, len, pq);
102  break;
103  case MPLS_PROTO_IPV6:
104  if (len > USHRT_MAX) {
105  return TM_ECODE_FAILED;
106  }
107  DecodeIPV6(tv, dtv, p, pkt, len, pq);
108  break;
110  DecodeEthernet(tv, dtv, p, pkt + MPLS_PW_LEN, len - MPLS_PW_LEN,
111  pq);
112  break;
113  default:
115  return TM_ECODE_OK;
116  }
117 
118 end:
119  if (event) {
120  ENGINE_SET_EVENT(p, event);
121  }
122  return TM_ECODE_OK;
123 }
124 
125 #ifdef UNITTESTS
126 
127 static int DecodeMPLSTestHeaderTooSmall(void)
128 {
129  int ret = 1;
130 
131  /* A packet that is too small to have a complete MPLS header. */
132  uint8_t pkt[] = {
133  0x00, 0x00, 0x11
134  };
135 
137  if (unlikely(p == NULL)) {
138  return 0;
139  }
140  ThreadVars tv;
141  DecodeThreadVars dtv;
142 
143  memset(&dtv, 0, sizeof(DecodeThreadVars));
144  memset(&tv, 0, sizeof(ThreadVars));
145  memset(p, 0, SIZE_OF_PACKET);
146 
147  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt), NULL);
148 
150  ret = 0;
151  }
152 
153  SCFree(p);
154  return ret;
155 }
156 
157 static int DecodeMPLSTestBadLabelRouterAlert(void)
158 {
159  int ret = 1;
160  uint8_t pkt[] = {
161  0x00, 0x00, 0x11, 0xff, 0x45, 0x00, 0x00, 0x64,
162  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
163  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
164  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
165  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
166  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
167  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
168  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
169  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
170  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
171  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
172  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
173  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
174  };
175 
177  if (unlikely(p == NULL)) {
178  return 0;
179  }
180  ThreadVars tv;
181  DecodeThreadVars dtv;
182 
183  memset(&dtv, 0, sizeof(DecodeThreadVars));
184  memset(&tv, 0, sizeof(ThreadVars));
185  memset(p, 0, SIZE_OF_PACKET);
186 
187  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt), NULL);
188 
190  ret = 0;
191  }
192 
193  SCFree(p);
194  return ret;
195 }
196 
197 static int DecodeMPLSTestBadLabelImplicitNull(void)
198 {
199  int ret = 1;
200  uint8_t pkt[] = {
201  0x00, 0x00, 0x31, 0xff, 0x45, 0x00, 0x00, 0x64,
202  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
203  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
204  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
205  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
206  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
207  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
208  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
209  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
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  };
215 
217  if (unlikely(p == NULL)) {
218  return 0;
219  }
220  ThreadVars tv;
221  DecodeThreadVars dtv;
222 
223  memset(&dtv, 0, sizeof(DecodeThreadVars));
224  memset(&tv, 0, sizeof(ThreadVars));
225  memset(p, 0, SIZE_OF_PACKET);
226 
227  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt), NULL);
228 
230  ret = 0;
231  }
232 
233  SCFree(p);
234  return ret;
235 }
236 
237 static int DecodeMPLSTestBadLabelReserved(void)
238 {
239  int ret = 1;
240  uint8_t pkt[] = {
241  0x00, 0x00, 0x51, 0xff, 0x45, 0x00, 0x00, 0x64,
242  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
243  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
244  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
245  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
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  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  };
255 
257  if (unlikely(p == NULL)) {
258  return 0;
259  }
260  ThreadVars tv;
261  DecodeThreadVars dtv;
262 
263  memset(&dtv, 0, sizeof(DecodeThreadVars));
264  memset(&tv, 0, sizeof(ThreadVars));
265  memset(p, 0, SIZE_OF_PACKET);
266 
267  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt), NULL);
268 
270  ret = 0;
271  }
272 
273  SCFree(p);
274  return ret;
275 }
276 
277 static int DecodeMPLSTestUnknownPayloadType(void)
278 {
279  int ret = 1;
280 
281  /* Valid label: 21.
282  * Unknown payload type: 1.
283  */
284  uint8_t pkt[] = {
285  0x00, 0x01, 0x51, 0xff, 0x15, 0x00, 0x00, 0x64,
286  0x00, 0x0a, 0x00, 0x00, 0xff, 0x01, 0xa5, 0x6a,
287  0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01,
288  0x08, 0x00, 0x3a, 0x77, 0x0a, 0x39, 0x06, 0x2b,
289  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x33, 0x50,
290  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
291  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
292  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
293  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
294  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
295  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
296  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
297  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd
298  };
299 
301  if (unlikely(p == NULL)) {
302  return 0;
303  }
304  ThreadVars tv;
305  DecodeThreadVars dtv;
306 
307  memset(&dtv, 0, sizeof(DecodeThreadVars));
308  memset(&tv, 0, sizeof(ThreadVars));
309  memset(p, 0, SIZE_OF_PACKET);
310 
311  DecodeMPLS(&tv, &dtv, p, pkt, sizeof(pkt), NULL);
312 
314  ret = 0;
315  }
316 
317  SCFree(p);
318  return ret;
319 }
320 
321 #endif /* UNITTESTS */
322 
324 {
325 #ifdef UNITTESTS
326  UtRegisterTest("DecodeMPLSTestHeaderTooSmall",
327  DecodeMPLSTestHeaderTooSmall);
328  UtRegisterTest("DecodeMPLSTestBadLabelRouterAlert",
329  DecodeMPLSTestBadLabelRouterAlert);
330  UtRegisterTest("DecodeMPLSTestBadLabelImplicitNull",
331  DecodeMPLSTestBadLabelImplicitNull);
332  UtRegisterTest("DecodeMPLSTestBadLabelReserved",
333  DecodeMPLSTestBadLabelReserved);
334  UtRegisterTest("DecodeMPLSTestUnknownPayloadType",
335  DecodeMPLSTestUnknownPayloadType);
336 #endif /* UNITTESTS */
337 }
#define ENGINE_SET_EVENT(p, e)
Definition: decode.h:1000
#define ENGINE_ISSET_EVENT(p, e)
Definition: decode.h:1015
#define MPLS_LABEL(shim)
Definition: decode-mpls.c:39
#define MPLS_HEADER_LEN
Definition: decode-mpls.c:30
#define unlikely(expr)
Definition: util-optimize.h:35
#define MPLS_PROTO_IPV6
Definition: decode-mpls.c:45
#define MPLS_MAX_RESERVED_LABEL
Definition: decode-mpls.c:32
#define MPLS_LABEL_ROUTER_ALERT
Definition: decode-mpls.c:35
#define MPLS_LABEL_IPV6
Definition: decode-mpls.c:36
int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
Definition: decode-ipv4.c:533
#define SIZE_OF_PACKET
Definition: decode.h:628
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
Definition: decode-ipv6.c:584
int DecodeMPLS(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
Definition: decode-mpls.c:47
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
#define MPLS_LABEL_NULL
Definition: decode-mpls.c:37
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void DecodeMPLSRegisterTests(void)
Definition: decode-mpls.c:323
Structure to hold thread specific data for all decode modules.
Definition: decode.h:642
uint16_t counter_mpls
Definition: decode.h:676
#define MPLS_PROTO_IPV4
Definition: decode-mpls.c:44
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:163
#define MPLS_PW_LEN
Definition: decode-mpls.c:31
#define SCMalloc(a)
Definition: util-mem.h:174
#define SCFree(a)
Definition: util-mem.h:236
#define MPLS_BOTTOM(shim)
Definition: decode-mpls.c:40
uint8_t len
Per thread variable structure.
Definition: threadvars.h:57
#define MPLS_PROTO_ETHERNET_PW
Definition: decode-mpls.c:43
#define MPLS_LABEL_IPV4
Definition: decode-mpls.c:34
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:1008