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 /**
48  * \internal
49  * \brief this function is used to decode IEEE802.1q packets
50  *
51  * \param tv pointer to the thread vars
52  * \param dtv pointer code thread vars
53  * \param p pointer to the packet struct
54  * \param pkt pointer to the raw packet
55  * \param len packet len
56  * \param pq pointer to the packet queue
57  *
58  */
60  const uint8_t *pkt, uint32_t len)
61 {
62  uint32_t proto;
63 
64  if (p->vlan_idx == 0)
66  else if (p->vlan_idx == 1)
68 
69  if(len < VLAN_HEADER_LEN) {
71  return TM_ECODE_FAILED;
72  }
73  if (p->vlan_idx >= 2) {
75  return TM_ECODE_FAILED;
76  }
77 
78  VLANHdr *vlan_hdr = (VLANHdr *)pkt;
79  if(vlan_hdr == NULL)
80  return TM_ECODE_FAILED;
81 
82  proto = GET_VLAN_PROTO(vlan_hdr);
83 
84  SCLogDebug("p %p pkt %p VLAN protocol %04x VLAN PRI %d VLAN CFI %d VLAN ID %d Len: %" PRIu32 "",
85  p, pkt, proto, GET_VLAN_PRIORITY(vlan_hdr), GET_VLAN_CFI(vlan_hdr),
86  GET_VLAN_ID(vlan_hdr), len);
87 
88  p->vlan_id[p->vlan_idx++] = (uint16_t)GET_VLAN_ID(vlan_hdr);
89 
90  if (DecodeNetworkLayer(tv, dtv, proto, p,
91  pkt + VLAN_HEADER_LEN, len - VLAN_HEADER_LEN) == false) {
93  return TM_ECODE_FAILED;
94  }
95  return TM_ECODE_OK;
96 }
97 
98 uint16_t DecodeVLANGetId(const Packet *p, uint8_t layer)
99 {
100  if (unlikely(layer > 1))
101  return 0;
102  if (p->vlan_idx > layer) {
103  return p->vlan_id[layer];
104  }
105  return 0;
106 }
107 
108 typedef struct IEEE8021ahHdr_ {
109  uint32_t flags;
110  uint8_t c_destination[6];
111  uint8_t c_source[6];
112  uint16_t type; /**< next protocol */
113 } __attribute__((__packed__)) IEEE8021ahHdr;
114 
115 #define IEEE8021AH_HEADER_LEN sizeof(IEEE8021ahHdr)
116 
118  const uint8_t *pkt, uint32_t len)
119 {
121 
122  if (len < IEEE8021AH_HEADER_LEN) {
124  return TM_ECODE_FAILED;
125  }
126 
127  IEEE8021ahHdr *hdr = (IEEE8021ahHdr *)pkt;
128  const uint16_t next_proto = SCNtohs(hdr->type);
129 
130  DecodeNetworkLayer(tv, dtv, next_proto, p,
132 
133  return TM_ECODE_OK;
134 }
135 
136 #ifdef UNITTESTS
137 /** \todo Must GRE+VLAN and Multi-Vlan packets to
138  * create more tests
139  */
140 
141 /**
142  * \test DecodeVLANTest01 test if vlan header is too small.
143  *
144  * \retval 1 on success
145  * \retval 0 on failure
146  */
147 static int DecodeVLANtest01 (void)
148 {
149  uint8_t raw_vlan[] = { 0x00, 0x20, 0x08 };
150  Packet *p = PacketGetFromAlloc();
151  if (unlikely(p == NULL))
152  return 0;
153  ThreadVars tv;
155 
156  memset(&tv, 0, sizeof(ThreadVars));
157  memset(&dtv, 0, sizeof(DecodeThreadVars));
158 
159  DecodeVLAN(&tv, &dtv, p, raw_vlan, sizeof(raw_vlan));
160 
162  SCFree(p);
163  return 1;
164  }
165 
166  SCFree(p);
167  return 0;
168 }
169 
170 /**
171  * \test DecodeVLANTest02 test if vlan header has unknown type.
172  *
173  * \retval 1 on success
174  * \retval 0 on failure
175  */
176 static int DecodeVLANtest02 (void)
177 {
178  uint8_t raw_vlan[] = {
179  0x00, 0x20, 0x01, 0x00, 0x45, 0x00, 0x00, 0x34,
180  0x3b, 0x36, 0x40, 0x00, 0x40, 0x06, 0xb7, 0xc9,
181  0x83, 0x97, 0x20, 0x81, 0x83, 0x97, 0x20, 0x15,
182  0x04, 0x8a, 0x17, 0x70, 0x4e, 0x14, 0xdf, 0x55,
183  0x4d, 0x3d, 0x5a, 0x61, 0x80, 0x10, 0x6b, 0x50,
184  0x3c, 0x4c, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a,
185  0x00, 0x04, 0xf0, 0xc8, 0x01, 0x99, 0xa3, 0xf3};
186  Packet *p = PacketGetFromAlloc();
187  if (unlikely(p == NULL))
188  return 0;
189  ThreadVars tv;
191 
192  memset(&tv, 0, sizeof(ThreadVars));
193  memset(&dtv, 0, sizeof(DecodeThreadVars));
194 
195  DecodeVLAN(&tv, &dtv, p, raw_vlan, sizeof(raw_vlan));
196 
197 
199  SCFree(p);
200  return 1;
201  }
202 
203  SCFree(p);
204  return 0;
205 }
206 
207 /**
208  * \test DecodeVLANTest02 test a good vlan header.
209  *
210  * \retval 1 on success
211  * \retval 0 on failure
212  */
213 static int DecodeVLANtest03 (void)
214 {
215  uint8_t raw_vlan[] = {
216  0x00, 0x20, 0x08, 0x00, 0x45, 0x00, 0x00, 0x34,
217  0x3b, 0x36, 0x40, 0x00, 0x40, 0x06, 0xb7, 0xc9,
218  0x83, 0x97, 0x20, 0x81, 0x83, 0x97, 0x20, 0x15,
219  0x04, 0x8a, 0x17, 0x70, 0x4e, 0x14, 0xdf, 0x55,
220  0x4d, 0x3d, 0x5a, 0x61, 0x80, 0x10, 0x6b, 0x50,
221  0x3c, 0x4c, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a,
222  0x00, 0x04, 0xf0, 0xc8, 0x01, 0x99, 0xa3, 0xf3};
223  Packet *p = PacketGetFromAlloc();
224  if (unlikely(p == NULL))
225  return 0;
226  ThreadVars tv;
228 
229  memset(&tv, 0, sizeof(ThreadVars));
230  memset(&dtv, 0, sizeof(DecodeThreadVars));
231 
233 
234  DecodeVLAN(&tv, &dtv, p, raw_vlan, sizeof(raw_vlan));
235 
236 
237  if(p->vlan_id[0] == 0) {
238  goto error;
239  }
240 
242  goto error;
243  }
244 
246  goto error;
247  }
248 
249  PACKET_RECYCLE(p);
250  FlowShutdown();
251  SCFree(p);
252  return 1;
253 
254 error:
255  PACKET_RECYCLE(p);
256  FlowShutdown();
257  SCFree(p);
258  return 0;
259 }
260 #endif /* UNITTESTS */
261 
263 {
264 #ifdef UNITTESTS
265  UtRegisterTest("DecodeVLANtest01", DecodeVLANtest01);
266  UtRegisterTest("DecodeVLANtest02", DecodeVLANtest02);
267  UtRegisterTest("DecodeVLANtest03", DecodeVLANtest03);
268 #endif /* UNITTESTS */
269 }
270 
271 /**
272  * @}
273  */
ENGINE_SET_EVENT
#define ENGINE_SET_EVENT(p, e)
Definition: decode.h:981
host.h
len
uint8_t len
Definition: app-layer-dnp3.h:2
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:169
Packet_::vlan_id
uint16_t vlan_id[2]
Definition: decode.h:438
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:996
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
Packet_::vlan_idx
uint8_t vlan_idx
Definition: decode.h:439
FlowInitConfig
void FlowInitConfig(char quiet)
initialize the configuration
Definition: flow.c:530
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:0
IEEE8021ahHdr_
Definition: decode-vlan.c:108
DecodeVLANGetId
uint16_t DecodeVLANGetId(const Packet *p, uint8_t layer)
Definition: decode-vlan.c:98
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:79
util-unittest.h
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:78
__attribute__
struct IEEE8021ahHdr_ __attribute__((__packed__))
DNP3 link header.
Definition: decode-vlan.c:113
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
IEEE8021ahHdr_::type
uint16_t type
Definition: decode-vlan.c:112
IEEE8021ahHdr_::flags
uint32_t flags
Definition: decode-vlan.c:109
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
VLAN_UNKNOWN_TYPE
@ VLAN_UNKNOWN_TYPE
Definition: decode-events.h:145
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:653
util-profiling.h
Packet_
Definition: decode.h:411
DecodeThreadVars_::counter_ieee8021ah
uint16_t counter_ieee8021ah
Definition: decode.h:655
DecodeThreadVars_::counter_vlan
uint16_t counter_vlan
Definition: decode.h:652
decode-events.h
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:30
decode-vlan.h
DecodeVLANRegisterTests
void DecodeVLANRegisterTests(void)
Definition: decode-vlan.c:262
SCNtohs
#define SCNtohs(x)
Definition: suricata-common.h:398
suricata-common.h
FlowShutdown
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:685
VLAN_HEADER_TOO_SMALL
@ VLAN_HEADER_TOO_SMALL
Definition: decode-events.h:144
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:144
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:625
IEEE8021ahHdr_::c_source
uint8_t c_source[6]
Definition: decode-vlan.c:111
ENGINE_SET_INVALID_EVENT
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:989
FLOW_QUIET
#define FLOW_QUIET
Definition: flow.h:38
GET_VLAN_ID
#define GET_VLAN_ID(vlanh)
Definition: decode-vlan.h:36
DecodeIEEE8021ah
int DecodeIEEE8021ah(ThreadVars *, DecodeThreadVars *, Packet *, const uint8_t *, uint32_t)
VLAN_HEADER_TOO_MANY_LAYERS
@ VLAN_HEADER_TOO_MANY_LAYERS
Definition: decode-events.h:146
IEEE8021AH_HEADER_TOO_SMALL
@ IEEE8021AH_HEADER_TOO_SMALL
Definition: decode-events.h:148
flow.h
DecodeVLAN
int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-vlan.c:59
PACKET_RECYCLE
#define PACKET_RECYCLE(p)
Definition: decode.h:807
IEEE8021ahHdr_::c_destination
uint8_t c_destination[6]
Definition: decode-vlan.c:110