suricata
decode-udp.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2020 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 UDP
31  */
32 
33 #include "suricata-common.h"
34 #include "decode.h"
35 #include "decode-geneve.h"
36 #include "decode-udp.h"
37 #include "decode-teredo.h"
38 #include "decode-vxlan.h"
39 #include "decode-events.h"
40 #include "util-unittest.h"
41 #include "util-debug.h"
42 #include "flow.h"
43 #include "app-layer.h"
44 
45 static int DecodeUDPPacket(ThreadVars *t, Packet *p, const uint8_t *pkt, uint16_t len)
46 {
47  if (unlikely(len < UDP_HEADER_LEN)) {
49  return -1;
50  }
51 
52  p->udph = (UDPHdr *)pkt;
53 
54  if (unlikely(len < UDP_GET_LEN(p))) {
56  return -1;
57  }
58 
59  if (unlikely(len != UDP_GET_LEN(p))) {
61  return -1;
62  }
63 
64  SET_UDP_SRC_PORT(p,&p->sp);
65  SET_UDP_DST_PORT(p,&p->dp);
66 
67  p->payload = (uint8_t *)pkt + UDP_HEADER_LEN;
69 
70  p->proto = IPPROTO_UDP;
71 
72  return 0;
73 }
74 
76  const uint8_t *pkt, uint16_t len)
77 {
79 
80  if (unlikely(DecodeUDPPacket(tv, p, pkt,len) < 0)) {
82  return TM_ECODE_FAILED;
83  }
84 
85  SCLogDebug("UDP sp: %" PRIu32 " -> dp: %" PRIu32 " - HLEN: %" PRIu32 " LEN: %" PRIu32 "",
87 
88  if (DecodeTeredoEnabledForPort(p->sp, p->dp) &&
90  /* Here we have a Teredo packet and don't need to handle app
91  * layer */
92  FlowSetupPacket(p);
93  return TM_ECODE_OK;
94  }
95 
96  /* Handle Geneve if configured */
97  if (DecodeGeneveEnabledForPort(p->sp, p->dp) &&
99  /* Here we have a Geneve packet and don't need to handle app
100  * layer */
101  FlowSetupPacket(p);
102  return TM_ECODE_OK;
103  }
104 
105  /* Handle VXLAN if configured */
106  if (DecodeVXLANEnabledForPort(p->sp, p->dp) &&
108  /* Here we have a VXLAN packet and don't need to handle app
109  * layer */
110  FlowSetupPacket(p);
111  return TM_ECODE_OK;
112  }
113 
114  FlowSetupPacket(p);
115 
116  return TM_ECODE_OK;
117 }
118 
119 #ifdef UNITTESTS
120 static int UDPV4CalculateValidChecksumtest01(void)
121 {
122  uint16_t csum = 0;
123 
124  uint8_t raw_ipshdr[] = {
125  0xd0, 0x43, 0xdc, 0xdc, 0xc0, 0xa8, 0x01, 0x3};
126 
127  uint8_t raw_udp[] = {
128  0x00, 0x35, 0xcf, 0x34, 0x00, 0x55, 0x6c, 0xe0,
129  0x83, 0xfc, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
130  0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x61, 0x67,
131  0x65, 0x61, 0x64, 0x32, 0x11, 0x67, 0x6f, 0x6f,
132  0x67, 0x6c, 0x65, 0x73, 0x79, 0x6e, 0x64, 0x69,
133  0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x03, 0x63,
134  0x6f, 0x6d, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0,
135  0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x4b,
136  0x50, 0x00, 0x12, 0x06, 0x70, 0x61, 0x67, 0x65,
137  0x61, 0x64, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f,
138  0x67, 0x6c, 0x65, 0xc0, 0x26};
139 
140  csum = *( ((uint16_t *)raw_udp) + 3);
141 
142  FAIL_IF(UDPV4Checksum((uint16_t *) raw_ipshdr,
143  (uint16_t *)raw_udp, sizeof(raw_udp), csum) != 0);
144  PASS;
145 }
146 
147 static int UDPV4CalculateInvalidChecksumtest02(void)
148 {
149  uint16_t csum = 0;
150 
151  uint8_t raw_ipshdr[] = {
152  0xd0, 0x43, 0xdc, 0xdc, 0xc0, 0xa8, 0x01, 0x3};
153 
154  uint8_t raw_udp[] = {
155  0x00, 0x35, 0xcf, 0x34, 0x00, 0x55, 0x6c, 0xe0,
156  0x83, 0xfc, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
157  0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x61, 0x67,
158  0x65, 0x61, 0x64, 0x32, 0x11, 0x67, 0x6f, 0x6f,
159  0x67, 0x6c, 0x65, 0x73, 0x79, 0x6e, 0x64, 0x69,
160  0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x03, 0x63,
161  0x6f, 0x6d, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0,
162  0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x4b,
163  0x50, 0x00, 0x12, 0x06, 0x70, 0x61, 0x67, 0x65,
164  0x61, 0x64, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f,
165  0x67, 0x6c, 0x65, 0xc0, 0x27};
166 
167  csum = *( ((uint16_t *)raw_udp) + 3);
168 
169  FAIL_IF(UDPV4Checksum((uint16_t *) raw_ipshdr,
170  (uint16_t *)raw_udp, sizeof(raw_udp), csum) == 0);
171  PASS;
172 }
173 
174 static int UDPV6CalculateValidChecksumtest03(void)
175 {
176  uint16_t csum = 0;
177 
178  static uint8_t raw_ipv6[] = {
179  0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00,
180  0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00,
181  0x00, 0x00, 0x00, 0x14, 0x11, 0x02, 0x3f, 0xfe,
182  0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
183  0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe,
184  0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0,
185  0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75,
186  0x82, 0xa0, 0x00, 0x14, 0x1a, 0xc3, 0x06, 0x02,
187  0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0x57, 0xb0,
188  0x09, 0x00};
189 
190  csum = *( ((uint16_t *)(raw_ipv6 + 60)));
191 
192  FAIL_IF(UDPV6Checksum((uint16_t *)(raw_ipv6 + 14 + 8),
193  (uint16_t *)(raw_ipv6 + 54), 20, csum) != 0);
194  PASS;
195 }
196 
197 static int UDPV6CalculateInvalidChecksumtest04(void)
198 {
199  uint16_t csum = 0;
200 
201  static uint8_t raw_ipv6[] = {
202  0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00,
203  0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00,
204  0x00, 0x00, 0x00, 0x14, 0x11, 0x02, 0x3f, 0xfe,
205  0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
206  0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe,
207  0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0,
208  0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75,
209  0x82, 0xa0, 0x00, 0x14, 0x1a, 0xc3, 0x06, 0x02,
210  0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0x57, 0xb0,
211  0x09, 0x01};
212 
213  csum = *( ((uint16_t *)(raw_ipv6 + 60)));
214 
215  FAIL_IF(UDPV6Checksum((uint16_t *)(raw_ipv6 + 14 + 8),
216  (uint16_t *)(raw_ipv6 + 54), 20, csum) == 0);
217  PASS;
218 }
219 #endif /* UNITTESTS */
220 
222 {
223 #ifdef UNITTESTS
224  UtRegisterTest("UDPV4CalculateValidChecksumtest01",
225  UDPV4CalculateValidChecksumtest01);
226  UtRegisterTest("UDPV4CalculateInvalidChecksumtest02",
227  UDPV4CalculateInvalidChecksumtest02);
228  UtRegisterTest("UDPV6CalculateValidChecksumtest03",
229  UDPV6CalculateValidChecksumtest03);
230  UtRegisterTest("UDPV6CalculateInvalidChecksumtest04",
231  UDPV6CalculateInvalidChecksumtest04);
232 #endif /* UNITTESTS */
233 }
234 /**
235  * @}
236  */
Packet_::proto
uint8_t proto
Definition: decode.h:436
DecodeUDPV4RegisterTests
void DecodeUDPV4RegisterTests(void)
Definition: decode-udp.c:221
len
uint8_t len
Definition: app-layer-dnp3.h:2
decode-vxlan.h
UDP_GET_SRC_PORT
#define UDP_GET_SRC_PORT(p)
Definition: decode-udp.h:36
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:169
DecodeUDP
int DecodeUDP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
Definition: decode-udp.c:75
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
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
Packet_::payload
uint8_t * payload
Definition: decode.h:549
decode-udp.h
DecodeVXLANEnabledForPort
bool DecodeVXLANEnabledForPort(const uint16_t sp, const uint16_t dp)
Definition: decode-vxlan.c:64
SET_UDP_DST_PORT
#define SET_UDP_DST_PORT(pkt, prt)
Definition: decode.h:202
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:81
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:550
util-unittest.h
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:80
DecodeGeneveEnabledForPort
bool DecodeGeneveEnabledForPort(const uint16_t sp, const uint16_t dp)
Definition: decode-geneve.c:89
UDP_HLEN_INVALID
@ UDP_HLEN_INVALID
Definition: decode-events.h:105
decode.h
DecodeGeneve
int DecodeGeneve(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-geneve.c:184
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
DecodeTeredoEnabledForPort
bool DecodeTeredoEnabledForPort(const uint16_t sp, const uint16_t dp)
Definition: decode-teredo.c:53
SET_UDP_SRC_PORT
#define SET_UDP_SRC_PORT(pkt, prt)
Definition: decode.h:199
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
Packet_::sp
Port sp
Definition: decode.h:421
UDP_HLEN_TOO_SMALL
@ UDP_HLEN_TOO_SMALL
Definition: decode-events.h:104
Packet_
Definition: decode.h:414
decode-teredo.h
DecodeVXLAN
int DecodeVXLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-vxlan.c:125
decode-events.h
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:30
UDP_GET_DST_PORT
#define UDP_GET_DST_PORT(p)
Definition: decode-udp.h:37
UDP_GET_LEN
#define UDP_GET_LEN(p)
Definition: decode-udp.h:35
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
suricata-common.h
DecodeThreadVars_::counter_udp
uint16_t counter_udp
Definition: decode.h:650
decode-geneve.h
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:631
Packet_::udph
UDPHdr * udph
Definition: decode.h:533
UDP_HEADER_LEN
#define UDP_HEADER_LEN
Definition: decode-udp.h:27
ENGINE_SET_INVALID_EVENT
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:1011
CLEAR_UDP_PACKET
#define CLEAR_UDP_PACKET(p)
Definition: decode-udp.h:49
UDP_PKT_TOO_SMALL
@ UDP_PKT_TOO_SMALL
Definition: decode-events.h:103
likely
#define likely(expr)
Definition: util-optimize.h:32
flow.h
Packet_::dp
Port dp
Definition: decode.h:429
FlowSetupPacket
void FlowSetupPacket(Packet *p)
prepare packet for a life with flow Set PKT_WANTS_FLOW flag to incidate workers should do a flow look...
Definition: flow-hash.c:410
DecodeTeredo
int DecodeTeredo(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
Function to decode Teredo packets.
Definition: decode-teredo.c:124
app-layer.h