suricata
decode-vlan.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2013 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  * \ingroup decode
20  *
21  * @{
22  */
23 
24 
25 /**
26  * \file
27  *
28  * \author Breno Silva <breno.silva@gmail.com>
29  *
30  * Decode 802.1q
31  */
32 
33 #include "suricata-common.h"
34 #include "decode.h"
35 #include "decode-vlan.h"
36 #include "decode-events.h"
37 
38 #include "flow.h"
39 
40 #include "util-unittest.h"
41 #include "util-debug.h"
42 
43 #include "pkt-var.h"
44 #include "util-profiling.h"
45 #include "host.h"
46 
47 static int DecodeIEEE8021ah(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
48  const uint8_t *pkt, uint16_t len);
49 
50 /**
51  * \internal
52  * \brief this function is used to decode IEEE802.1q packets
53  *
54  * \param tv pointer to the thread vars
55  * \param dtv pointer code thread vars
56  * \param p pointer to the packet struct
57  * \param pkt pointer to the raw packet
58  * \param len packet len
59  * \param pq pointer to the packet queue
60  *
61  */
63  const uint8_t *pkt, uint32_t len)
64 {
65  uint32_t proto;
66 
67  if (p->vlan_idx == 0)
69  else if (p->vlan_idx == 1)
71 
72  if(len < VLAN_HEADER_LEN) {
74  return TM_ECODE_FAILED;
75  }
76  if (p->vlan_idx >= 2) {
78  return TM_ECODE_FAILED;
79  }
80 
81  VLANHdr *vlan_hdr = (VLANHdr *)pkt;
82  if(vlan_hdr == NULL)
83  return TM_ECODE_FAILED;
84 
85  proto = GET_VLAN_PROTO(vlan_hdr);
86 
87  SCLogDebug("p %p pkt %p VLAN protocol %04x VLAN PRI %d VLAN CFI %d VLAN ID %d Len: %" PRIu32 "",
88  p, pkt, proto, GET_VLAN_PRIORITY(vlan_hdr), GET_VLAN_CFI(vlan_hdr),
89  GET_VLAN_ID(vlan_hdr), len);
90 
91  p->vlan_id[p->vlan_idx++] = (uint16_t)GET_VLAN_ID(vlan_hdr);
92 
93  switch (proto) {
94  case ETHERNET_TYPE_IP:
95  if (unlikely(len > VLAN_HEADER_LEN + USHRT_MAX)) {
96  return TM_ECODE_FAILED;
97  }
98 
99  DecodeIPV4(tv, dtv, p, pkt + VLAN_HEADER_LEN,
100  len - VLAN_HEADER_LEN);
101  break;
102  case ETHERNET_TYPE_IPV6:
103  if (unlikely(len > VLAN_HEADER_LEN + USHRT_MAX)) {
104  return TM_ECODE_FAILED;
105  }
106  DecodeIPV6(tv, dtv, p, pkt + VLAN_HEADER_LEN,
107  len - VLAN_HEADER_LEN);
108  break;
111  len - VLAN_HEADER_LEN);
112  break;
115  len - VLAN_HEADER_LEN);
116  break;
117  case ETHERNET_TYPE_VLAN:
119  if (p->vlan_idx >= 2) {
121  return TM_ECODE_OK;
122  } else {
123  DecodeVLAN(tv, dtv, p, pkt + VLAN_HEADER_LEN,
124  len - VLAN_HEADER_LEN);
125  }
126  break;
128  DecodeIEEE8021ah(tv, dtv, p, pkt + VLAN_HEADER_LEN,
129  len - VLAN_HEADER_LEN);
130  break;
131  case ETHERNET_TYPE_ARP:
132  break;
135  DecodeMPLS(tv, dtv, p, pkt + VLAN_HEADER_LEN,
136  len - VLAN_HEADER_LEN);
137  break;
138  default:
139  SCLogDebug("unknown VLAN type: %" PRIx32 "", proto);
141  return TM_ECODE_OK;
142  }
143 
144  return TM_ECODE_OK;
145 }
146 
147 uint16_t DecodeVLANGetId(const Packet *p, uint8_t layer)
148 {
149  if (unlikely(layer > 1))
150  return 0;
151  if (p->vlan_idx > layer) {
152  return p->vlan_id[layer];
153  }
154  return 0;
155 }
156 
157 typedef struct IEEE8021ahHdr_ {
158  uint32_t flags;
159  uint8_t c_destination[6];
160  uint8_t c_source[6];
161  uint16_t type; /**< next protocol */
162 } __attribute__((__packed__)) IEEE8021ahHdr;
163 
164 #define IEEE8021AH_HEADER_LEN sizeof(IEEE8021ahHdr)
165 
166 static int DecodeIEEE8021ah(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
167  const uint8_t *pkt, uint16_t len)
168 {
170 
171  if (len < IEEE8021AH_HEADER_LEN) {
173  return TM_ECODE_FAILED;
174  }
175 
176  IEEE8021ahHdr *hdr = (IEEE8021ahHdr *)pkt;
177  uint16_t next_proto = SCNtohs(hdr->type);
178 
179  switch (next_proto) {
180  case ETHERNET_TYPE_VLAN:
181  case ETHERNET_TYPE_8021QINQ: {
184  break;
185  }
186  }
187  return TM_ECODE_OK;
188 }
189 
190 #ifdef UNITTESTS
191 /** \todo Must GRE+VLAN and Multi-Vlan packets to
192  * create more tests
193  */
194 
195 /**
196  * \test DecodeVLANTest01 test if vlan header is too small.
197  *
198  * \retval 1 on success
199  * \retval 0 on failure
200  */
201 static int DecodeVLANtest01 (void)
202 {
203  uint8_t raw_vlan[] = { 0x00, 0x20, 0x08 };
204  Packet *p = PacketGetFromAlloc();
205  if (unlikely(p == NULL))
206  return 0;
207  ThreadVars tv;
209 
210  memset(&tv, 0, sizeof(ThreadVars));
211  memset(&dtv, 0, sizeof(DecodeThreadVars));
212 
213  DecodeVLAN(&tv, &dtv, p, raw_vlan, sizeof(raw_vlan));
214 
216  SCFree(p);
217  return 1;
218  }
219 
220  SCFree(p);
221  return 0;
222 }
223 
224 /**
225  * \test DecodeVLANTest02 test if vlan header has unknown type.
226  *
227  * \retval 1 on success
228  * \retval 0 on failure
229  */
230 static int DecodeVLANtest02 (void)
231 {
232  uint8_t raw_vlan[] = {
233  0x00, 0x20, 0x01, 0x00, 0x45, 0x00, 0x00, 0x34,
234  0x3b, 0x36, 0x40, 0x00, 0x40, 0x06, 0xb7, 0xc9,
235  0x83, 0x97, 0x20, 0x81, 0x83, 0x97, 0x20, 0x15,
236  0x04, 0x8a, 0x17, 0x70, 0x4e, 0x14, 0xdf, 0x55,
237  0x4d, 0x3d, 0x5a, 0x61, 0x80, 0x10, 0x6b, 0x50,
238  0x3c, 0x4c, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a,
239  0x00, 0x04, 0xf0, 0xc8, 0x01, 0x99, 0xa3, 0xf3};
240  Packet *p = PacketGetFromAlloc();
241  if (unlikely(p == NULL))
242  return 0;
243  ThreadVars tv;
245 
246  memset(&tv, 0, sizeof(ThreadVars));
247  memset(&dtv, 0, sizeof(DecodeThreadVars));
248 
249  DecodeVLAN(&tv, &dtv, p, raw_vlan, sizeof(raw_vlan));
250 
251 
253  SCFree(p);
254  return 1;
255  }
256 
257  SCFree(p);
258  return 0;
259 }
260 
261 /**
262  * \test DecodeVLANTest02 test a good vlan header.
263  *
264  * \retval 1 on success
265  * \retval 0 on failure
266  */
267 static int DecodeVLANtest03 (void)
268 {
269  uint8_t raw_vlan[] = {
270  0x00, 0x20, 0x08, 0x00, 0x45, 0x00, 0x00, 0x34,
271  0x3b, 0x36, 0x40, 0x00, 0x40, 0x06, 0xb7, 0xc9,
272  0x83, 0x97, 0x20, 0x81, 0x83, 0x97, 0x20, 0x15,
273  0x04, 0x8a, 0x17, 0x70, 0x4e, 0x14, 0xdf, 0x55,
274  0x4d, 0x3d, 0x5a, 0x61, 0x80, 0x10, 0x6b, 0x50,
275  0x3c, 0x4c, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a,
276  0x00, 0x04, 0xf0, 0xc8, 0x01, 0x99, 0xa3, 0xf3};
277  Packet *p = PacketGetFromAlloc();
278  if (unlikely(p == NULL))
279  return 0;
280  ThreadVars tv;
282 
283  memset(&tv, 0, sizeof(ThreadVars));
284  memset(&dtv, 0, sizeof(DecodeThreadVars));
285 
287 
288  DecodeVLAN(&tv, &dtv, p, raw_vlan, sizeof(raw_vlan));
289 
290 
291  if(p->vlan_id[0] == 0) {
292  goto error;
293  }
294 
296  goto error;
297  }
298 
300  goto error;
301  }
302 
303  PACKET_RECYCLE(p);
304  FlowShutdown();
305  SCFree(p);
306  return 1;
307 
308 error:
309  PACKET_RECYCLE(p);
310  FlowShutdown();
311  SCFree(p);
312  return 0;
313 }
314 #endif /* UNITTESTS */
315 
317 {
318 #ifdef UNITTESTS
319  UtRegisterTest("DecodeVLANtest01", DecodeVLANtest01);
320  UtRegisterTest("DecodeVLANtest02", DecodeVLANtest02);
321  UtRegisterTest("DecodeVLANtest03", DecodeVLANtest03);
322 #endif /* UNITTESTS */
323 }
324 
325 /**
326  * @}
327  */
ENGINE_SET_EVENT
#define ENGINE_SET_EVENT(p, e)
Definition: decode.h:976
host.h
len
uint8_t len
Definition: app-layer-dnp3.h:4
VLAN_UNKNOWN_TYPE
@ VLAN_UNKNOWN_TYPE
Definition: decode-events.h:145
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:168
Packet_::vlan_id
uint16_t vlan_id[2]
Definition: decode.h:436
SCFree
#define SCFree(a)
Definition: util-mem.h:322
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:991
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:335
ETHERNET_TYPE_IPV6
#define ETHERNET_TYPE_IPV6
Definition: decode-ethernet.h:39
Packet_::vlan_idx
uint8_t vlan_idx
Definition: decode.h:437
FlowInitConfig
void FlowInitConfig(char quiet)
initialize the configuration
Definition: flow.c:529
GET_VLAN_CFI
#define GET_VLAN_CFI(vlanh)
Definition: decode-vlan.h:35
IEEE8021AH_HEADER_LEN
#define IEEE8021AH_HEADER_LEN
proto
uint8_t proto
Definition: decode-template.h:2
IEEE8021ahHdr_
Definition: decode-vlan.c:157
DecodeVLANGetId
uint16_t DecodeVLANGetId(const Packet *p, uint8_t layer)
Definition: decode-vlan.c:147
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:79
util-unittest.h
ETHERNET_TYPE_8021QINQ
#define ETHERNET_TYPE_8021QINQ
Definition: decode-ethernet.h:47
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:78
__attribute__
struct IEEE8021ahHdr_ __attribute__((__packed__))
DNP3 link header.
Definition: decode-vlan.c:162
VLAN_HEADER_TOO_MANY_LAYERS
@ VLAN_HEADER_TOO_MANY_LAYERS
Definition: decode-events.h:146
decode.h
util-debug.h
GET_VLAN_PRIORITY
#define GET_VLAN_PRIORITY(vlanh)
Definition: decode-vlan.h:34
VLAN_HEADER_LEN
#define VLAN_HEADER_LEN
Definition: decode-vlan.h:50
ETHERNET_TYPE_8021AD
#define ETHERNET_TYPE_8021AD
Definition: decode-ethernet.h:43
IEEE8021ahHdr_::type
uint16_t type
Definition: decode-vlan.c:161
IEEE8021ahHdr_::flags
uint32_t flags
Definition: decode-vlan.c:158
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
pkt-var.h
GET_VLAN_PROTO
#define GET_VLAN_PROTO(vlanh)
Definition: decode-vlan.h:37
DecodeThreadVars_::counter_vlan_qinq
uint16_t counter_vlan_qinq
Definition: decode.h:650
DecodeMPLS
int DecodeMPLS(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-mpls.c:47
util-profiling.h
ETHERNET_TYPE_MPLS_UNICAST
#define ETHERNET_TYPE_MPLS_UNICAST
Definition: decode-mpls.h:29
ETHERNET_TYPE_PPPOE_DISC
#define ETHERNET_TYPE_PPPOE_DISC
Definition: decode-ethernet.h:41
Packet_
Definition: decode.h:408
DecodeIPV6
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
Definition: decode-ipv6.c:580
DecodeThreadVars_::counter_ieee8021ah
uint16_t counter_ieee8021ah
Definition: decode.h:652
VLAN_HEADER_TOO_SMALL
@ VLAN_HEADER_TOO_SMALL
Definition: decode-events.h:144
DecodeThreadVars_::counter_vlan
uint16_t counter_vlan
Definition: decode.h:649
decode-events.h
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:33
decode-vlan.h
DecodeVLANRegisterTests
void DecodeVLANRegisterTests(void)
Definition: decode-vlan.c:316
DecodePPPOEDiscovery
int DecodePPPOEDiscovery(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Main decoding function for PPPOE Discovery packets.
Definition: decode-pppoe.c:50
SCNtohs
#define SCNtohs(x)
Definition: suricata-common.h:375
suricata-common.h
ETHERNET_TYPE_8021AH
#define ETHERNET_TYPE_8021AH
Definition: decode-ethernet.h:44
FlowShutdown
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:684
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:144
ETHERNET_TYPE_PPPOE_SESS
#define ETHERNET_TYPE_PPPOE_SESS
Definition: decode-ethernet.h:42
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:622
DecodePPPOESession
int DecodePPPOESession(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Main decoding function for PPPOE Session packets.
Definition: decode-pppoe.c:130
ETHERNET_TYPE_ARP
#define ETHERNET_TYPE_ARP
Definition: decode-ethernet.h:35
IEEE8021ahHdr_::c_source
uint8_t c_source[6]
Definition: decode-vlan.c:160
IEEE8021AH_HEADER_TOO_SMALL
@ IEEE8021AH_HEADER_TOO_SMALL
Definition: decode-events.h:148
ENGINE_SET_INVALID_EVENT
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:984
FLOW_QUIET
#define FLOW_QUIET
Definition: flow.h:38
ETHERNET_TYPE_VLAN
#define ETHERNET_TYPE_VLAN
Definition: decode-vlan.h:31
GET_VLAN_ID
#define GET_VLAN_ID(vlanh)
Definition: decode-vlan.h:36
flow.h
DecodeIPV4
int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
Definition: decode-ipv4.c:517
DecodeVLAN
int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-vlan.c:62
ETHERNET_TYPE_MPLS_MULTICAST
#define ETHERNET_TYPE_MPLS_MULTICAST
Definition: decode-mpls.h:30
ETHERNET_TYPE_IP
#define ETHERNET_TYPE_IP
Definition: decode-ethernet.h:34
PACKET_RECYCLE
#define PACKET_RECYCLE(p)
Definition: decode.h:804
IEEE8021ahHdr_::c_destination
uint8_t c_destination[6]
Definition: decode-vlan.c:159