suricata
decode-ethernet.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-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  * \ingroup decode
20  *
21  * @{
22  */
23 
24 
25 /**
26  * \file
27  *
28  * \author Victor Julien <victor@inliniac.net>
29  *
30  * Decode Ethernet
31  */
32 
33 #include "suricata-common.h"
34 #include "decode.h"
35 #include "decode-ethernet.h"
36 #include "decode-events.h"
37 
38 #include "util-unittest.h"
39 #include "util-debug.h"
40 
42  uint8_t *pkt, uint32_t len, PacketQueue *pq)
43 {
44  StatsIncr(tv, dtv->counter_eth);
45 
46  if (unlikely(len < ETHERNET_HEADER_LEN)) {
48  return TM_ECODE_FAILED;
49  }
50 
51  if (unlikely(len > ETHERNET_HEADER_LEN + USHRT_MAX)) {
52  return TM_ECODE_FAILED;
53  }
54 
55  p->ethh = (EthernetHdr *)pkt;
56  if (unlikely(p->ethh == NULL))
57  return TM_ECODE_FAILED;
58 
59  SCLogDebug("p %p pkt %p ether type %04x", p, pkt, SCNtohs(p->ethh->eth_type));
60 
61  switch (SCNtohs(p->ethh->eth_type)) {
62  case ETHERNET_TYPE_IP:
63  //printf("DecodeEthernet ip4\n");
64  DecodeIPV4(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
65  len - ETHERNET_HEADER_LEN, pq);
66  break;
67  case ETHERNET_TYPE_IPV6:
68  //printf("DecodeEthernet ip6\n");
69  DecodeIPV6(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
70  len - ETHERNET_HEADER_LEN, pq);
71  break;
73  //printf("DecodeEthernet PPPOE Session\n");
74  DecodePPPOESession(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
75  len - ETHERNET_HEADER_LEN, pq);
76  break;
78  //printf("DecodeEthernet PPPOE Discovery\n");
79  DecodePPPOEDiscovery(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
80  len - ETHERNET_HEADER_LEN, pq);
81  break;
82  case ETHERNET_TYPE_VLAN:
84  DecodeVLAN(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
85  len - ETHERNET_HEADER_LEN, pq);
86  break;
89  DecodeMPLS(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
90  len - ETHERNET_HEADER_LEN, pq);
91  break;
92  case ETHERNET_TYPE_DCE:
93  if (unlikely(len < ETHERNET_DCE_HEADER_LEN)) {
95  } else {
96  DecodeEthernet(tv, dtv, p, pkt + ETHERNET_DCE_HEADER_LEN,
97  len - ETHERNET_DCE_HEADER_LEN, pq);
98  }
99  break;
100  default:
101  SCLogDebug("p %p pkt %p ether type %04x not supported", p,
102  pkt, SCNtohs(p->ethh->eth_type));
103  }
104 
105  return TM_ECODE_OK;
106 }
107 
108 #ifdef UNITTESTS
109 /** DecodeEthernettest01
110  * \brief Valid Ethernet packet
111  * \retval 0 Expected test value
112  */
113 static int DecodeEthernetTest01 (void)
114 {
115  /* ICMP packet wrapped in PPPOE */
116  uint8_t raw_eth[] = {
117  0x00, 0x10, 0x94, 0x55, 0x00, 0x01, 0x00, 0x10,
118  0x94, 0x56, 0x00, 0x01, 0x88, 0x64, 0x11, 0x00,
119  0x00, 0x01, 0x00, 0x68, 0x00, 0x21, 0x45, 0xc0,
120  0x00, 0x64, 0x00, 0x1e, 0x00, 0x00, 0xff, 0x01,
121  0xa7, 0x78, 0x0a, 0x00, 0x00, 0x02, 0x0a, 0x00,
122  0x00, 0x01, 0x08, 0x00, 0x4a, 0x61, 0x00, 0x06,
123  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
124  0x3b, 0xd4, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
125  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
126  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
127  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
128  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
129  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
130  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
131  0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
132  0xab, 0xcd };
133 
135  if (unlikely(p == NULL))
136  return 0;
137  ThreadVars tv;
138  DecodeThreadVars dtv;
139 
140  memset(&dtv, 0, sizeof(DecodeThreadVars));
141  memset(&tv, 0, sizeof(ThreadVars));
142  memset(p, 0, SIZE_OF_PACKET);
143 
144  DecodeEthernet(&tv, &dtv, p, raw_eth, sizeof(raw_eth), NULL);
145 
146  SCFree(p);
147  return 1;
148 }
149 
150 /**
151  * Test a DCE ethernet frame that is too small.
152  */
153 static int DecodeEthernetTestDceTooSmall(void)
154 {
155  uint8_t raw_eth[] = {
156  0x00, 0x10, 0x94, 0x55, 0x00, 0x01, 0x00, 0x10,
157  0x94, 0x56, 0x00, 0x01, 0x89, 0x03,
158  };
159 
161  FAIL_IF_NULL(p);
162  ThreadVars tv;
163  DecodeThreadVars dtv;
164 
165  memset(&dtv, 0, sizeof(DecodeThreadVars));
166  memset(&tv, 0, sizeof(ThreadVars));
167  memset(p, 0, SIZE_OF_PACKET);
168 
169  DecodeEthernet(&tv, &dtv, p, raw_eth, sizeof(raw_eth), NULL);
170 
172 
173  SCFree(p);
174  PASS;
175 }
176 
177 /**
178  * Test that a DCE ethernet frame, followed by data that is too small
179  * for an ethernet header.
180  *
181  * Redmine issue:
182  * https://redmine.openinfosecfoundation.org/issues/2887
183  */
184 static int DecodeEthernetTestDceNextTooSmall(void)
185 {
186  uint8_t raw_eth[] = {
187  0x00, 0x10, 0x94, 0x55, 0x00, 0x01, 0x00, 0x10,
188  0x94, 0x56, 0x00, 0x01, 0x89, 0x03, //0x88, 0x64,
189 
190  0x00, 0x00,
191 
192  0x00, 0x10, 0x94, 0x55, 0x00, 0x01, 0x00, 0x10,
193  0x94, 0x56, 0x00, 0x01,
194  };
195 
197  FAIL_IF_NULL(p);
198  ThreadVars tv;
199  DecodeThreadVars dtv;
200 
201  memset(&dtv, 0, sizeof(DecodeThreadVars));
202  memset(&tv, 0, sizeof(ThreadVars));
203  memset(p, 0, SIZE_OF_PACKET);
204 
205  DecodeEthernet(&tv, &dtv, p, raw_eth, sizeof(raw_eth), NULL);
206 
208 
209  SCFree(p);
210  PASS;
211 }
212 
213 #endif /* UNITTESTS */
214 
215 
216 /**
217  * \brief Registers Ethernet unit tests
218  * \todo More Ethernet tests
219  */
221 {
222 #ifdef UNITTESTS
223  UtRegisterTest("DecodeEthernetTest01", DecodeEthernetTest01);
224  UtRegisterTest("DecodeEthernetTestDceNextTooSmall",
225  DecodeEthernetTestDceNextTooSmall);
226  UtRegisterTest("DecodeEthernetTestDceTooSmall",
227  DecodeEthernetTestDceTooSmall);
228 #endif /* UNITTESTS */
229 }
230 /**
231  * @}
232  */
int DecodePPPOESession(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
Main decoding function for PPPOE Session packets.
Definition: decode-pppoe.c:129
EthernetHdr * ethh
Definition: decode.h:491
#define SCLogDebug(...)
Definition: util-debug.h:335
#define ENGINE_ISSET_EVENT(p, e)
Definition: decode.h:1006
#define PASS
Pass the test.
#define unlikely(expr)
Definition: util-optimize.h:35
uint16_t counter_eth
Definition: decode.h:647
int DecodePPPOEDiscovery(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
Main decoding function for PPPOE Discovery packets.
Definition: decode-pppoe.c:50
#define ETHERNET_TYPE_VLAN
Definition: decode-vlan.h:31
int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
Definition: decode-ipv4.c:532
#define SIZE_OF_PACKET
Definition: decode.h:618
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
#define ETHERNET_TYPE_IP
#define ETHERNET_TYPE_PPPOE_DISC
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
#define ETHERNET_TYPE_DCE
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Structure to hold thread specific data for all decode modules.
Definition: decode.h:632
#define ETHERNET_TYPE_MPLS_MULTICAST
Definition: decode-mpls.h:30
void DecodeEthernetRegisterTests(void)
Registers Ethernet unit tests.
#define ETHERNET_DCE_HEADER_LEN
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:163
int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
Definition: decode-vlan.c:62
#define ETHERNET_HEADER_LEN
#define ETHERNET_TYPE_PPPOE_SESS
#define SCMalloc(a)
Definition: util-mem.h:166
#define SCFree(a)
Definition: util-mem.h:228
#define SCNtohs(x)
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
uint8_t len
Per thread variable structure.
Definition: threadvars.h:57
#define ETHERNET_TYPE_IPV6
#define ETHERNET_TYPE_MPLS_UNICAST
Definition: decode-mpls.h:29
#define ETHERNET_TYPE_8021QINQ
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:999