/src/suricata7/src/decode-udp.c
Line | Count | Source |
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 | 220k | { |
47 | 220k | if (unlikely(len < UDP_HEADER_LEN)) { |
48 | 841 | ENGINE_SET_INVALID_EVENT(p, UDP_HLEN_TOO_SMALL); |
49 | 841 | return -1; |
50 | 841 | } |
51 | | |
52 | 220k | p->udph = (UDPHdr *)pkt; |
53 | | |
54 | 220k | if (unlikely(len < UDP_GET_LEN(p))) { |
55 | 9.06k | ENGINE_SET_INVALID_EVENT(p, UDP_PKT_TOO_SMALL); |
56 | 9.06k | return -1; |
57 | 9.06k | } |
58 | | |
59 | 211k | if (unlikely(UDP_GET_LEN(p) < UDP_HEADER_LEN)) { |
60 | 1.99k | ENGINE_SET_INVALID_EVENT(p, UDP_LEN_INVALID); |
61 | 1.99k | return -1; |
62 | 1.99k | } |
63 | | |
64 | 209k | SET_UDP_SRC_PORT(p,&p->sp); |
65 | 209k | SET_UDP_DST_PORT(p,&p->dp); |
66 | | |
67 | 209k | p->payload = (uint8_t *)pkt + UDP_HEADER_LEN; |
68 | 209k | p->payload_len = UDP_GET_LEN(p) - UDP_HEADER_LEN; |
69 | | |
70 | 209k | p->proto = IPPROTO_UDP; |
71 | | |
72 | 209k | return 0; |
73 | 211k | } |
74 | | |
75 | | int DecodeUDP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, |
76 | | const uint8_t *pkt, uint16_t len) |
77 | 220k | { |
78 | 220k | StatsIncr(tv, dtv->counter_udp); |
79 | | |
80 | 220k | if (unlikely(DecodeUDPPacket(tv, p, pkt,len) < 0)) { |
81 | 11.9k | CLEAR_UDP_PACKET(p); |
82 | 11.9k | return TM_ECODE_FAILED; |
83 | 11.9k | } |
84 | | |
85 | 209k | SCLogDebug("UDP sp: %" PRIu32 " -> dp: %" PRIu32 " - HLEN: %" PRIu32 " LEN: %" PRIu32 "", |
86 | 209k | UDP_GET_SRC_PORT(p), UDP_GET_DST_PORT(p), UDP_HEADER_LEN, p->payload_len); |
87 | | |
88 | 209k | if (DecodeTeredoEnabledForPort(p->sp, p->dp) && |
89 | 209k | likely(DecodeTeredo(tv, dtv, p, p->payload, p->payload_len) == TM_ECODE_OK)) { |
90 | | /* Here we have a Teredo packet and don't need to handle app |
91 | | * layer */ |
92 | 1.25k | FlowSetupPacket(p); |
93 | 1.25k | return TM_ECODE_OK; |
94 | 1.25k | } |
95 | | |
96 | | /* Handle Geneve if configured */ |
97 | 207k | if (DecodeGeneveEnabledForPort(p->sp, p->dp) && |
98 | 5.10k | unlikely(DecodeGeneve(tv, dtv, p, p->payload, p->payload_len) == TM_ECODE_OK)) { |
99 | | /* Here we have a Geneve packet and don't need to handle app |
100 | | * layer */ |
101 | 2.32k | FlowSetupPacket(p); |
102 | 2.32k | return TM_ECODE_OK; |
103 | 2.32k | } |
104 | | |
105 | | /* Handle VXLAN if configured */ |
106 | 205k | if (DecodeVXLANEnabledForPort(p->sp, p->dp) && |
107 | 5.18k | unlikely(DecodeVXLAN(tv, dtv, p, p->payload, p->payload_len) == TM_ECODE_OK)) { |
108 | | /* Here we have a VXLAN packet and don't need to handle app |
109 | | * layer */ |
110 | 3.26k | FlowSetupPacket(p); |
111 | 3.26k | return TM_ECODE_OK; |
112 | 3.26k | } |
113 | | |
114 | 202k | FlowSetupPacket(p); |
115 | | |
116 | 202k | return TM_ECODE_OK; |
117 | 205k | } |
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 | | |
221 | | void DecodeUDPV4RegisterTests(void) |
222 | 0 | { |
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 | 0 | } |
234 | | /** |
235 | | * @} |
236 | | */ |