]> git.ipfire.org Git - people/ms/suricata.git/blame - src/decode-icmpv4.c
core: Remove unneeded consts
[people/ms/suricata.git] / src / decode-icmpv4.c
CommitLineData
988bb268 1/* Copyright (C) 2007-2020 Open Information Security Foundation
ce019275
WM
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
acf10525
EL
18/**
19 * \ingroup decode
20 *
21 * @{
22 */
23
24
ce019275
WM
25/**
26 * \file
27 *
28 * \author Victor Julien <victor@inliniac.net>
29 *
30 * Decode ICMPv4
31 */
bab4b623 32
ecf86f9c 33#include "suricata-common.h"
97c991f7 34
bab4b623 35#include "decode.h"
a2972251 36#include "decode-events.h"
97c991f7 37#include "decode-ipv4.h"
bab4b623 38#include "decode-icmpv4.h"
97c991f7 39
10cc9d5b
VJ
40#include "flow.h"
41
afa8a676 42#include "util-unittest.h"
e0afe969 43#include "util-unittest-helper.h"
91bc83e5 44#include "util-debug.h"
6b9d1012 45#include "util-print.h"
bab4b623 46
a2972251 47/**
a2972251
J
48 * Note, this is the IP header, plus a bit of the original packet, not the whole thing!
49 */
ab1200fb 50static int DecodePartialIPV4(Packet* p, uint8_t* partial_packet, uint16_t len)
a2972251 51{
0dc471db
J
52 /** Check the sizes, the header must fit at least */
53 if (len < IPV4_HEADER_LEN) {
54 SCLogDebug("DecodePartialIPV4: ICMPV4_IPV4_TRUNC_PKT");
b2c58b8d 55 ENGINE_SET_INVALID_EVENT(p, ICMPV4_IPV4_TRUNC_PKT);
ed1cc1ee 56 return -1;
0dc471db
J
57 }
58
59 IPV4Hdr *icmp4_ip4h = (IPV4Hdr*)partial_packet;
60
0dc471db 61 /** Check the embedded version */
97c991f7 62 if (IPV4_GET_RAW_VER(icmp4_ip4h) != 4) {
0dc471db
J
63 /** Check the embedded version */
64 SCLogDebug("DecodePartialIPV4: ICMPv4 contains Unknown IPV4 version "
65 "ICMPV4_IPV4_UNKNOWN_VER");
b2c58b8d 66 ENGINE_SET_INVALID_EVENT(p, ICMPV4_IPV4_UNKNOWN_VER);
ed1cc1ee 67 return -1;
0dc471db
J
68 }
69
70 /** We need to fill icmpv4vars */
71 p->icmpv4vars.emb_ipv4h = icmp4_ip4h;
72
73 /** Get the IP address from the contained packet */
74 p->icmpv4vars.emb_ip4_src = IPV4_GET_RAW_IPSRC(icmp4_ip4h);
75 p->icmpv4vars.emb_ip4_dst = IPV4_GET_RAW_IPDST(icmp4_ip4h);
76
77 p->icmpv4vars.emb_ip4_hlen=IPV4_GET_RAW_HLEN(icmp4_ip4h) << 2;
78
79 switch (IPV4_GET_RAW_IPPROTO(icmp4_ip4h)) {
80 case IPPROTO_TCP:
81 if (len >= IPV4_HEADER_LEN + TCP_HEADER_LEN ) {
82 p->icmpv4vars.emb_tcph = (TCPHdr*)(partial_packet + IPV4_HEADER_LEN);
11be9bd9
VJ
83 p->icmpv4vars.emb_sport = SCNtohs(p->icmpv4vars.emb_tcph->th_sport);
84 p->icmpv4vars.emb_dport = SCNtohs(p->icmpv4vars.emb_tcph->th_dport);
548a3b2c 85 p->icmpv4vars.emb_ip4_proto = IPPROTO_TCP;
0dc471db
J
86
87 SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->TCP header sport: "
248f9c66 88 "%"PRIu16" dport %"PRIu16"", p->icmpv4vars.emb_sport,
0dc471db 89 p->icmpv4vars.emb_dport);
619414c5 90 } else if (len >= IPV4_HEADER_LEN + 4) {
38e7d944
VJ
91 /* only access th_sport and th_dport */
92 TCPHdr *emb_tcph = (TCPHdr*)(partial_packet + IPV4_HEADER_LEN);
93
94 p->icmpv4vars.emb_tcph = NULL;
11be9bd9
VJ
95 p->icmpv4vars.emb_sport = SCNtohs(emb_tcph->th_sport);
96 p->icmpv4vars.emb_dport = SCNtohs(emb_tcph->th_dport);
38e7d944
VJ
97 p->icmpv4vars.emb_ip4_proto = IPPROTO_TCP;
98 SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->TCP partial header sport: "
248f9c66 99 "%"PRIu16" dport %"PRIu16"", p->icmpv4vars.emb_sport,
38e7d944 100 p->icmpv4vars.emb_dport);
0dc471db
J
101 } else {
102 SCLogDebug("DecodePartialIPV4: Warning, ICMPV4->IPV4->TCP "
103 "header Didn't fit in the packet!");
104 p->icmpv4vars.emb_sport = 0;
105 p->icmpv4vars.emb_dport = 0;
106 }
107
108 break;
109 case IPPROTO_UDP:
110 if (len >= IPV4_HEADER_LEN + UDP_HEADER_LEN ) {
111 p->icmpv4vars.emb_udph = (UDPHdr*)(partial_packet + IPV4_HEADER_LEN);
11be9bd9
VJ
112 p->icmpv4vars.emb_sport = SCNtohs(p->icmpv4vars.emb_udph->uh_sport);
113 p->icmpv4vars.emb_dport = SCNtohs(p->icmpv4vars.emb_udph->uh_dport);
548a3b2c 114 p->icmpv4vars.emb_ip4_proto = IPPROTO_UDP;
0dc471db
J
115
116 SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->UDP header sport: "
248f9c66 117 "%"PRIu16" dport %"PRIu16"", p->icmpv4vars.emb_sport,
0dc471db
J
118 p->icmpv4vars.emb_dport);
119 } else {
120 SCLogDebug("DecodePartialIPV4: Warning, ICMPV4->IPV4->UDP "
121 "header Didn't fit in the packet!");
122 p->icmpv4vars.emb_sport = 0;
123 p->icmpv4vars.emb_dport = 0;
124 }
125
126 break;
127 case IPPROTO_ICMP:
ed1cc1ee
VJ
128 if (len >= IPV4_HEADER_LEN + ICMPV4_HEADER_LEN ) {
129 p->icmpv4vars.emb_icmpv4h = (ICMPV4Hdr*)(partial_packet + IPV4_HEADER_LEN);
130 p->icmpv4vars.emb_sport = 0;
131 p->icmpv4vars.emb_dport = 0;
132 p->icmpv4vars.emb_ip4_proto = IPPROTO_ICMP;
0dc471db 133
ed1cc1ee
VJ
134 SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->ICMP header");
135 }
0dc471db
J
136
137 break;
138 }
139
140 /* debug print */
141#ifdef DEBUG
142 char s[16], d[16];
6b9d1012
EL
143 PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_src), s, sizeof(s));
144 PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_dst), d, sizeof(d));
97c991f7
VJ
145 SCLogDebug("ICMPv4 embedding IPV4 %s->%s - PROTO: %" PRIu32 " ID: %" PRIu32 "", s,d,
146 IPV4_GET_RAW_IPPROTO(icmp4_ip4h), IPV4_GET_RAW_IPID(icmp4_ip4h));
0dc471db
J
147#endif
148
ed1cc1ee 149 return 0;
a2972251
J
150}
151
698e9c06
J
152/** DecodeICMPV4
153 * \brief Main ICMPv4 decoding function
154 */
f8aed4ce 155int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
bab4b623 156{
1c0b4ee0 157 StatsIncr(tv, dtv->counter_icmpv4);
d0e70309 158
bab4b623 159 if (len < ICMPV4_HEADER_LEN) {
b2c58b8d 160 ENGINE_SET_INVALID_EVENT(p, ICMPV4_PKT_TOO_SMALL);
d4b7ecfb 161 return TM_ECODE_FAILED;
bab4b623
VJ
162 }
163
57f71f7e
VJ
164 p->icmpv4h = (ICMPV4Hdr *)pkt;
165
91bc83e5 166 SCLogDebug("ICMPV4 TYPE %" PRIu32 " CODE %" PRIu32 "", p->icmpv4h->type, p->icmpv4h->code);
bab4b623 167
3df4b7da 168 p->proto = IPPROTO_ICMP;
c662383b
VJ
169 p->icmp_s.type = p->icmpv4h->type;
170 p->icmp_s.code = p->icmpv4h->code;
22c0ec2b 171
c662383b
VJ
172 int ctype = ICMPv4GetCounterpart(p->icmp_s.type);
173 if (ctype != -1) {
174 p->icmp_d.type = (uint8_t)ctype;
175 }
176
a2972251 177 ICMPV4ExtHdr* icmp4eh = (ICMPV4ExtHdr*) p->icmpv4h;
988bb268 178 p->icmpv4vars.hlen = ICMPV4_HEADER_LEN;
a2972251
J
179
180 switch (p->icmpv4h->type)
10cc9d5b 181 {
a2972251
J
182 case ICMP_ECHOREPLY:
183 p->icmpv4vars.id=icmp4eh->id;
184 p->icmpv4vars.seq=icmp4eh->seq;
185 if (p->icmpv4h->code!=0) {
7425bf5c 186 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
a2972251
J
187 }
188 break;
189
190 case ICMP_DEST_UNREACH:
548a3b2c 191 if (p->icmpv4h->code > NR_ICMP_UNREACH) {
7425bf5c 192 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
a2972251 193 } else {
548a3b2c 194 /* parse IP header plus 64 bytes */
cdba2f50 195 if (len > ICMPV4_HEADER_PKT_OFFSET) {
c662383b
VJ
196 (void)DecodePartialIPV4(p, (uint8_t *)(pkt + ICMPV4_HEADER_PKT_OFFSET),
197 len - ICMPV4_HEADER_PKT_OFFSET );
548a3b2c 198 }
a2972251
J
199 }
200 break;
201
202 case ICMP_SOURCE_QUENCH:
203 if (p->icmpv4h->code!=0) {
7425bf5c 204 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
a2972251
J
205 } else {
206 // parse IP header plus 64 bytes
55b14f37
MA
207 if (len >= ICMPV4_HEADER_PKT_OFFSET) {
208 if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) {
209 return TM_ECODE_FAILED;
210 }
0dc471db 211 DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
55b14f37 212 }
a2972251
J
213 }
214 break;
215
216 case ICMP_REDIRECT:
217 if (p->icmpv4h->code>ICMP_REDIR_HOSTTOS) {
7425bf5c 218 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
a2972251
J
219 } else {
220 // parse IP header plus 64 bytes
55b14f37
MA
221 if (len > ICMPV4_HEADER_PKT_OFFSET) {
222 if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) {
223 return TM_ECODE_FAILED;
224 }
0dc471db 225 DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
55b14f37 226 }
a2972251
J
227 }
228 break;
229
230 case ICMP_ECHO:
231 p->icmpv4vars.id=icmp4eh->id;
232 p->icmpv4vars.seq=icmp4eh->seq;
233 if (p->icmpv4h->code!=0) {
7425bf5c 234 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
a2972251
J
235 }
236 break;
237
238 case ICMP_TIME_EXCEEDED:
239 if (p->icmpv4h->code>ICMP_EXC_FRAGTIME) {
7425bf5c 240 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
a2972251
J
241 } else {
242 // parse IP header plus 64 bytes
55b14f37
MA
243 if (len > ICMPV4_HEADER_PKT_OFFSET) {
244 if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) {
245 return TM_ECODE_FAILED;
246 }
0dc471db 247 DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
55b14f37 248 }
a2972251
J
249 }
250 break;
251
252 case ICMP_PARAMETERPROB:
253 if (p->icmpv4h->code!=0) {
7425bf5c 254 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
a2972251
J
255 } else {
256 // parse IP header plus 64 bytes
55b14f37
MA
257 if (len > ICMPV4_HEADER_PKT_OFFSET) {
258 if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) {
259 return TM_ECODE_FAILED;
260 }
0dc471db 261 DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
55b14f37 262 }
a2972251
J
263 }
264 break;
265
266 case ICMP_TIMESTAMP:
267 p->icmpv4vars.id=icmp4eh->id;
268 p->icmpv4vars.seq=icmp4eh->seq;
269 if (p->icmpv4h->code!=0) {
7425bf5c 270 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
a2972251 271 }
988bb268
JL
272
273 if (len < (sizeof(ICMPV4Timestamp) + ICMPV4_HEADER_LEN)) {
274 ENGINE_SET_EVENT(p, ICMPV4_IPV4_TRUNC_PKT);
275 } else {
276 p->icmpv4vars.hlen += sizeof(ICMPV4Timestamp);
277 }
a2972251
J
278 break;
279
280 case ICMP_TIMESTAMPREPLY:
281 p->icmpv4vars.id=icmp4eh->id;
282 p->icmpv4vars.seq=icmp4eh->seq;
283 if (p->icmpv4h->code!=0) {
7425bf5c 284 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
a2972251 285 }
988bb268
JL
286
287 if (len < (sizeof(ICMPV4Timestamp) + ICMPV4_HEADER_LEN)) {
288 ENGINE_SET_EVENT(p, ICMPV4_IPV4_TRUNC_PKT);
289 } else {
290 p->icmpv4vars.hlen += sizeof(ICMPV4Timestamp);
291 }
a2972251
J
292 break;
293
294 case ICMP_INFO_REQUEST:
295 p->icmpv4vars.id=icmp4eh->id;
296 p->icmpv4vars.seq=icmp4eh->seq;
297 if (p->icmpv4h->code!=0) {
7425bf5c 298 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
a2972251
J
299 }
300 break;
301
302 case ICMP_INFO_REPLY:
303 p->icmpv4vars.id=icmp4eh->id;
304 p->icmpv4vars.seq=icmp4eh->seq;
305 if (p->icmpv4h->code!=0) {
7425bf5c 306 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
a2972251
J
307 }
308 break;
309
988bb268
JL
310 case ICMP_ROUTERADVERT: {
311 /* pkt points to beginning of icmp message */
312 ICMPV4RtrAdvert *icmpv4_router_advert = (ICMPV4RtrAdvert *)(pkt + sizeof(ICMPV4Hdr));
313 uint32_t advert_len = icmpv4_router_advert->naddr *
314 (icmpv4_router_advert->addr_sz * sizeof(uint32_t));
315 if (len < (advert_len + ICMPV4_HEADER_LEN)) {
316 ENGINE_SET_EVENT(p, ICMPV4_IPV4_TRUNC_PKT);
317 } else {
318 p->icmpv4vars.hlen += advert_len;
319 }
320 } break;
321
a2972251
J
322 case ICMP_ADDRESS:
323 p->icmpv4vars.id=icmp4eh->id;
324 p->icmpv4vars.seq=icmp4eh->seq;
325 if (p->icmpv4h->code!=0) {
7425bf5c 326 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
a2972251
J
327 }
328 break;
329
330 case ICMP_ADDRESSREPLY:
331 p->icmpv4vars.id=icmp4eh->id;
332 p->icmpv4vars.seq=icmp4eh->seq;
333 if (p->icmpv4h->code!=0) {
7425bf5c 334 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
a2972251
J
335 }
336 break;
337
338 default:
7425bf5c 339 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_TYPE);
a2972251 340
10cc9d5b
VJ
341 }
342
988bb268
JL
343 p->payload = (uint8_t *)pkt + p->icmpv4vars.hlen;
344 p->payload_len = len - p->icmpv4vars.hlen;
345
c662383b 346 FlowSetupPacket(p);
d4b7ecfb 347 return TM_ECODE_OK;
bab4b623
VJ
348}
349
c662383b
VJ
350/** \retval type counterpart type or -1 */
351int ICMPv4GetCounterpart(uint8_t type)
352{
353#define CASE_CODE(t,r) case (t): return r; case (r): return t;
354 switch (type) {
355 CASE_CODE(ICMP_ECHO, ICMP_ECHOREPLY);
356 CASE_CODE(ICMP_TIMESTAMP, ICMP_TIMESTAMPREPLY);
357 CASE_CODE(ICMP_INFO_REQUEST, ICMP_INFO_REPLY);
358 CASE_CODE(ICMP_ROUTERSOLICIT, ICMP_ROUTERADVERT);
359 CASE_CODE(ICMP_ADDRESS, ICMP_ADDRESSREPLY);
360 default:
361 return -1;
362 }
363#undef CASE_CODE
364}
365
afa8a676
J
366#ifdef UNITTESTS
367
368/** DecodeICMPV4test01
369 * \brief
a2972251 370 * \retval 1 Expected test value
afa8a676 371 */
8f1d7503
KS
372static int DecodeICMPV4test01(void)
373{
f6a84542
VJ
374 uint8_t raw_icmpv4[] = {
375 0x08, 0x00, 0x78, 0x47, 0xfc, 0x55, 0x00, 0x04,
376 0x52, 0xab, 0x86, 0x4a, 0x84, 0x50, 0x0e, 0x00,
377 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
378 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
379 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
380 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
381 0xab };
1db4aadd 382 Packet *p = SCMalloc(SIZE_OF_PACKET);
e176be6f 383 if (unlikely(p == NULL))
1db4aadd 384 return 0;
afa8a676 385 ThreadVars tv;
244f5d54 386 DecodeThreadVars dtv;
10cc9d5b
VJ
387 int ret = 0;
388 IPV4Hdr ip4h;
afa8a676 389
10cc9d5b 390 memset(&ip4h, 0, sizeof(IPV4Hdr));
afa8a676 391 memset(&tv, 0, sizeof(ThreadVars));
1db4aadd 392 memset(p, 0, SIZE_OF_PACKET);
10cc9d5b 393 memset(&ip4h, 0, sizeof(IPV4Hdr));
244f5d54 394 memset(&dtv, 0, sizeof(DecodeThreadVars));
afa8a676 395
10cc9d5b
VJ
396 FlowInitConfig(FLOW_QUIET);
397
1db4aadd
EL
398 p->src.family = AF_INET;
399 p->dst.family = AF_INET;
e0afe969
VJ
400 p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");;
401 p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");;
10cc9d5b 402
cdba2f50
VJ
403 ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
404 ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
1db4aadd 405 p->ip4h = &ip4h;
10cc9d5b 406
f8aed4ce 407 DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4));
a2972251 408
1db4aadd
EL
409 if (NULL!=p->icmpv4h) {
410 if (p->icmpv4h->type==8 && p->icmpv4h->code==0) {
10cc9d5b 411 ret = 1;
a2972251
J
412 }
413 }
414
10cc9d5b 415 FlowShutdown();
1db4aadd 416 SCFree(p);
10cc9d5b 417 return ret;
afa8a676
J
418}
419
420/** DecodeICMPV4test02
421 * \brief
a2972251 422 * \retval 1 Expected test value
afa8a676 423 */
8f1d7503
KS
424static int DecodeICMPV4test02(void)
425{
f6a84542
VJ
426 uint8_t raw_icmpv4[] = {
427 0x00, 0x00, 0x57, 0x64, 0xfb, 0x55, 0x00, 0x03,
428 0x43, 0xab, 0x86, 0x4a, 0xf6, 0x49, 0x02, 0x00,
429 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
430 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
431 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
432 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
433 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f };
1db4aadd 434 Packet *p = SCMalloc(SIZE_OF_PACKET);
e176be6f 435 if (unlikely(p == NULL))
1db4aadd 436 return 0;
afa8a676 437 ThreadVars tv;
244f5d54 438 DecodeThreadVars dtv;
10cc9d5b
VJ
439 int ret = 0;
440 IPV4Hdr ip4h;
afa8a676 441
10cc9d5b 442 memset(&ip4h, 0, sizeof(IPV4Hdr));
afa8a676 443 memset(&tv, 0, sizeof(ThreadVars));
1db4aadd 444 memset(p, 0, SIZE_OF_PACKET);
244f5d54 445 memset(&dtv, 0, sizeof(DecodeThreadVars));
afa8a676 446
10cc9d5b
VJ
447 FlowInitConfig(FLOW_QUIET);
448
1db4aadd
EL
449 p->src.family = AF_INET;
450 p->dst.family = AF_INET;
e0afe969
VJ
451 p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");;
452 p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");;
10cc9d5b 453
cdba2f50
VJ
454 ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
455 ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
1db4aadd 456 p->ip4h = &ip4h;
10cc9d5b 457
f8aed4ce 458 DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4));
a2972251 459
1db4aadd
EL
460 if (NULL!=p->icmpv4h) {
461 if (p->icmpv4h->type==0 && p->icmpv4h->code==0) {
10cc9d5b 462 ret = 1;
a2972251
J
463 }
464 }
465
10cc9d5b 466 FlowShutdown();
1db4aadd 467 SCFree(p);
10cc9d5b 468 return ret;
afa8a676
J
469}
470
471/** DecodeICMPV4test03
472 * \brief TTL exceeded
a2972251 473 * \retval Expected test value: 1
afa8a676 474 */
8f1d7503
KS
475static int DecodeICMPV4test03(void)
476{
f6a84542
VJ
477 uint8_t raw_icmpv4[] = {
478 0x0b, 0x00, 0x6a, 0x3d, 0x00, 0x00, 0x00, 0x00,
479 0x45, 0x00, 0x00, 0x3c, 0x64, 0x15, 0x00, 0x00,
480 0x01, 0x11, 0xde, 0xfd, 0xc0, 0xa8, 0x01, 0x0d,
481 0xd1, 0x55, 0xe3, 0x93, 0x8b, 0x12, 0x82, 0xaa,
482 0x00, 0x28, 0x7c, 0xdd };
1db4aadd 483 Packet *p = SCMalloc(SIZE_OF_PACKET);
e176be6f 484 if (unlikely(p == NULL))
1db4aadd 485 return 0;
afa8a676 486 ThreadVars tv;
244f5d54 487 DecodeThreadVars dtv;
10cc9d5b
VJ
488 int ret = 0;
489 IPV4Hdr ip4h;
afa8a676 490
10cc9d5b 491 memset(&ip4h, 0, sizeof(IPV4Hdr));
afa8a676 492 memset(&tv, 0, sizeof(ThreadVars));
1db4aadd 493 memset(p, 0, SIZE_OF_PACKET);
244f5d54 494 memset(&dtv, 0, sizeof(DecodeThreadVars));
afa8a676 495
10cc9d5b
VJ
496 FlowInitConfig(FLOW_QUIET);
497
1db4aadd
EL
498 p->src.family = AF_INET;
499 p->dst.family = AF_INET;
e0afe969
VJ
500 p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");;
501 p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");;
10cc9d5b 502
cdba2f50
VJ
503 ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
504 ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
1db4aadd 505 p->ip4h = &ip4h;
10cc9d5b 506
f8aed4ce 507 DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4));
a2972251 508
1db4aadd 509 if (NULL == p->icmpv4h) {
38e7d944 510 printf("NULL == p->icmpv4h: ");
10cc9d5b 511 goto end;
a2972251
J
512 }
513
f4812586 514 /* check it's type 11 code 0 */
1db4aadd 515 if (p->icmpv4h->type != 11 || p->icmpv4h->code != 0) {
38e7d944
VJ
516 printf("p->icmpv4h->type %u, p->icmpv4h->code %u: ",
517 p->icmpv4h->type, p->icmpv4h->code);
10cc9d5b 518 goto end;
0dc471db
J
519 }
520
38e7d944
VJ
521 /* check it's source port 35602 to port 33450 */
522 if (p->icmpv4vars.emb_sport != 35602 ||
523 p->icmpv4vars.emb_dport != 33450) {
524 printf("p->icmpv4vars.emb_sport %u, p->icmpv4vars.emb_dport %u: ",
525 p->icmpv4vars.emb_sport, p->icmpv4vars.emb_dport);
10cc9d5b 526 goto end;
0dc471db
J
527 }
528
f4812586 529 /* check the src,dst IPs contained inside */
0dc471db
J
530 char s[16], d[16];
531
6b9d1012
EL
532 PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_src), s, sizeof(s));
533 PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_dst), d, sizeof(d));
0dc471db 534
f4812586 535 /* ICMPv4 embedding IPV4 192.168.1.13->209.85.227.147 pass */
10cc9d5b
VJ
536 if (strcmp(s, "192.168.1.13") == 0 && strcmp(d, "209.85.227.147") == 0) {
537 ret = 1;
0dc471db 538 }
38e7d944
VJ
539 else {
540 printf("s %s, d %s: ", s, d);
541 }
0dc471db 542
10cc9d5b
VJ
543end:
544 FlowShutdown();
1db4aadd 545 SCFree(p);
10cc9d5b 546 return ret;
afa8a676
J
547}
548
549/** DecodeICMPV4test04
550 * \brief dest. unreachable, administratively prohibited
a2972251 551 * \retval 1 Expected test value
afa8a676 552 */
8f1d7503
KS
553static int DecodeICMPV4test04(void)
554{
f6a84542
VJ
555 uint8_t raw_icmpv4[] = {
556 0x03, 0x0a, 0x36, 0xc3, 0x00, 0x00, 0x00, 0x00,
557 0x45, 0x00, 0x00, 0x3c, 0x62, 0xee, 0x40, 0x00,
558 0x33, 0x06, 0xb4, 0x8f, 0xc0, 0xa8, 0x01, 0x0d,
559 0x58, 0x60, 0x16, 0x29, 0xb1, 0x0a, 0x00, 0x32,
560 0x3e, 0x36, 0x38, 0x7c, 0x00, 0x00, 0x00, 0x00,
561 0xa0, 0x02, 0x16, 0xd0, 0x72, 0x04, 0x00, 0x00,
562 0x02, 0x04, 0x05, 0x8a, 0x04, 0x02, 0x08, 0x0a };
1db4aadd 563 Packet *p = SCMalloc(SIZE_OF_PACKET);
e176be6f 564 if (unlikely(p == NULL))
1db4aadd 565 return 0;
afa8a676 566 ThreadVars tv;
244f5d54 567 DecodeThreadVars dtv;
10cc9d5b
VJ
568 int ret = 0;
569 IPV4Hdr ip4h;
afa8a676 570
10cc9d5b 571 memset(&ip4h, 0, sizeof(IPV4Hdr));
afa8a676 572 memset(&tv, 0, sizeof(ThreadVars));
1db4aadd 573 memset(p, 0, SIZE_OF_PACKET);
244f5d54 574 memset(&dtv, 0, sizeof(DecodeThreadVars));
afa8a676 575
10cc9d5b
VJ
576 FlowInitConfig(FLOW_QUIET);
577
1db4aadd
EL
578 p->src.family = AF_INET;
579 p->dst.family = AF_INET;
e0afe969
VJ
580 p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");;
581 p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");;
10cc9d5b 582
cdba2f50
VJ
583 ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
584 ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
1db4aadd 585 p->ip4h = &ip4h;
10cc9d5b 586
f8aed4ce 587 DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4));
a2972251 588
1db4aadd 589 if (NULL == p->icmpv4h) {
10cc9d5b 590 goto end;
a2972251
J
591 }
592
f4812586 593 /* check the type,code pair is correct - type 3, code 10 */
1db4aadd 594 if (p->icmpv4h->type != 3 || p->icmpv4h->code != 10) {
10cc9d5b 595 goto end;
0dc471db
J
596 }
597
38e7d944
VJ
598 /* check it's src port 45322 to dst port 50 */
599 if (p->icmpv4vars.emb_sport != 45322 ||
600 p->icmpv4vars.emb_dport != 50) {
10cc9d5b 601 goto end;
0dc471db
J
602 }
603
604 // check the src,dst IPs contained inside
605 char s[16], d[16];
606
6b9d1012
EL
607 PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_src), s, sizeof(s));
608 PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_dst), d, sizeof(d));
0dc471db
J
609
610 // ICMPv4 embedding IPV4 192.168.1.13->88.96.22.41
10cc9d5b
VJ
611 if (strcmp(s, "192.168.1.13") == 0 && strcmp(d, "88.96.22.41") == 0) {
612 ret = 1;
0dc471db
J
613 }
614
10cc9d5b
VJ
615end:
616 FlowShutdown();
1db4aadd 617 SCFree(p);
10cc9d5b 618 return ret;
afa8a676
J
619}
620
38e7d944
VJ
621/** DecodeICMPV4test05
622 * \brief dest. unreachable, administratively prohibited
623 * \retval 1 Expected test value
624 */
8f1d7503
KS
625static int DecodeICMPV4test05(void)
626{
38e7d944
VJ
627 uint8_t raw_icmpv4[] = {
628 0x0b, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x00, 0x00, 0x45,
629 0x00, 0x00, 0x30, 0x02, 0x17, 0x40, 0x00, 0x01, 0x06,
630 0xd6, 0xbd, 0xc0, 0xa8, 0x02, 0x05, 0x3d, 0x23, 0xa1,
631 0x23, 0x04, 0x18, 0x00, 0x50, 0xd2, 0x08, 0xc2, 0x48,
632 };
633 Packet *p = SCMalloc(SIZE_OF_PACKET);
e176be6f 634 if (unlikely(p == NULL))
38e7d944
VJ
635 return 0;
636 ThreadVars tv;
637 DecodeThreadVars dtv;
638 int ret = 0;
639 IPV4Hdr ip4h;
640
641 memset(&ip4h, 0, sizeof(IPV4Hdr));
642 memset(&tv, 0, sizeof(ThreadVars));
643 memset(p, 0, SIZE_OF_PACKET);
38e7d944
VJ
644 memset(&dtv, 0, sizeof(DecodeThreadVars));
645
646 FlowInitConfig(FLOW_QUIET);
647
648 p->src.family = AF_INET;
649 p->dst.family = AF_INET;
650 p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");;
651 p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");;
652
cdba2f50
VJ
653 ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
654 ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
38e7d944
VJ
655 p->ip4h = &ip4h;
656
f8aed4ce 657 DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4));
38e7d944
VJ
658
659 if (NULL == p->icmpv4h) {
660 goto end;
661 }
662
663 /* check the type,code pair is correct - type 11, code 0 */
664 if (p->icmpv4h->type != 11 || p->icmpv4h->code != 0) {
665 goto end;
666 }
667
668 /* check it's src port 1048 to dst port 80 */
669 if (p->icmpv4vars.emb_sport != 1048 ||
670 p->icmpv4vars.emb_dport != 80) {
671 goto end;
672 }
673
674 // check the src,dst IPs contained inside
675 char s[16], d[16];
676
6b9d1012
EL
677 PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_src), s, sizeof(s));
678 PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_dst), d, sizeof(d));
38e7d944
VJ
679
680 // ICMPv4 embedding IPV4 192.168.2.5->61.35.161.35
681 if (strcmp(s, "192.168.2.5") == 0 && strcmp(d, "61.35.161.35") == 0) {
682 ret = 1;
683 }
684
685end:
686 FlowShutdown();
687 SCFree(p);
688 return ret;
689}
690
8f1d7503
KS
691static int ICMPV4CalculateValidChecksumtest05(void)
692{
41dd0f8e
AS
693 uint16_t csum = 0;
694
695 uint8_t raw_icmpv4[] = {
696 0x08, 0x00, 0xab, 0x9b, 0x7f, 0x2b, 0x05, 0x2c,
697 0x3f, 0x72, 0x93, 0x4a, 0x00, 0x4d, 0x0a, 0x00,
698 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
699 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
700 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
701 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
702 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
703 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37};
704
705 csum = *( ((uint16_t *)raw_icmpv4) + 1);
706 return (csum == ICMPV4CalculateChecksum((uint16_t *)raw_icmpv4, sizeof(raw_icmpv4)));
707}
708
8f1d7503
KS
709static int ICMPV4CalculateInvalidChecksumtest06(void)
710{
41dd0f8e
AS
711 uint16_t csum = 0;
712
713 uint8_t raw_icmpv4[] = {
714 0x08, 0x00, 0xab, 0x9b, 0x7f, 0x2b, 0x05, 0x2c,
715 0x3f, 0x72, 0x93, 0x4a, 0x00, 0x4d, 0x0a, 0x00,
716 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
717 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
718 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
719 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
720 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
721 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38};
722
723 csum = *( ((uint16_t *)raw_icmpv4) + 1);
52983bf3 724 return (csum != ICMPV4CalculateChecksum((uint16_t *)raw_icmpv4, sizeof(raw_icmpv4)));
41dd0f8e
AS
725}
726
8f1d7503
KS
727static int ICMPV4InvalidType07(void)
728{
a2972251
J
729
730 uint8_t raw_icmpv4[] = {
731 0xff, 0x00, 0xab, 0x9b, 0x7f, 0x2b, 0x05, 0x2c,
732 0x3f, 0x72, 0x93, 0x4a, 0x00, 0x4d, 0x0a, 0x00,
733 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
734 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
735 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
736 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
737 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
738 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38};
739
1db4aadd 740 Packet *p = SCMalloc(SIZE_OF_PACKET);
e176be6f 741 if (unlikely(p == NULL))
1db4aadd 742 return 0;
a2972251
J
743 ThreadVars tv;
744 DecodeThreadVars dtv;
10cc9d5b
VJ
745 int ret = 0;
746 IPV4Hdr ip4h;
a2972251 747
10cc9d5b 748 memset(&ip4h, 0, sizeof(IPV4Hdr));
a2972251 749 memset(&tv, 0, sizeof(ThreadVars));
1db4aadd 750 memset(p, 0, SIZE_OF_PACKET);
a2972251
J
751 memset(&dtv, 0, sizeof(DecodeThreadVars));
752
10cc9d5b
VJ
753 FlowInitConfig(FLOW_QUIET);
754
1db4aadd
EL
755 p->src.family = AF_INET;
756 p->dst.family = AF_INET;
e0afe969
VJ
757 p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");;
758 p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");;
10cc9d5b 759
cdba2f50
VJ
760 ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
761 ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
1db4aadd 762 p->ip4h = &ip4h;
10cc9d5b 763
f8aed4ce 764 DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4));
a2972251 765
7425bf5c 766 if(ENGINE_ISSET_EVENT(p,ICMPV4_UNKNOWN_TYPE)) {
10cc9d5b 767 ret = 1;
a2972251
J
768 }
769
10cc9d5b 770 FlowShutdown();
1db4aadd 771 SCFree(p);
10cc9d5b 772 return ret;
a2972251
J
773}
774
775/** DecodeICMPV4test08
776 * \brief
777 * \retval 1 Expected test value - what we really want is not to segfault
778 */
8f1d7503
KS
779static int DecodeICMPV4test08(void)
780{
a2972251
J
781 uint8_t raw_icmpv4[] = {
782 0x08, 0x00, 0x78, 0x47, 0xfc, 0x55, 0x00, 0x00
783 };
1db4aadd 784 Packet *p = SCMalloc(SIZE_OF_PACKET);
e176be6f 785 if (unlikely(p == NULL))
1db4aadd 786 return 0;
a2972251
J
787 ThreadVars tv;
788 DecodeThreadVars dtv;
10cc9d5b
VJ
789 int ret = 0;
790 IPV4Hdr ip4h;
a2972251 791
10cc9d5b 792 memset(&ip4h, 0, sizeof(IPV4Hdr));
a2972251 793 memset(&tv, 0, sizeof(ThreadVars));
1db4aadd 794 memset(p, 0, SIZE_OF_PACKET);
a2972251
J
795 memset(&dtv, 0, sizeof(DecodeThreadVars));
796
10cc9d5b
VJ
797 FlowInitConfig(FLOW_QUIET);
798
1db4aadd
EL
799 p->src.family = AF_INET;
800 p->dst.family = AF_INET;
e0afe969
VJ
801 p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");;
802 p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");;
10cc9d5b 803
cdba2f50
VJ
804 ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
805 ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
1db4aadd 806 p->ip4h = &ip4h;
10cc9d5b 807
f8aed4ce 808 DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4));
a2972251 809
1db4aadd
EL
810 if (NULL!=p->icmpv4h) {
811 if (p->icmpv4h->type==8 && p->icmpv4h->code==0) {
10cc9d5b 812 ret = 1;
a2972251
J
813 }
814 }
815
10cc9d5b 816 FlowShutdown();
1db4aadd 817 SCFree(p);
10cc9d5b 818 return ret;
a2972251 819}
c43319c3 820#endif /* UNITTESTS */
a2972251 821
afa8a676
J
822/**
823 * \brief Registers ICMPV4 unit test
afa8a676 824 */
8f1d7503
KS
825void DecodeICMPV4RegisterTests(void)
826{
c43319c3 827#ifdef UNITTESTS
796dd522
JI
828 UtRegisterTest("DecodeICMPV4test01", DecodeICMPV4test01);
829 UtRegisterTest("DecodeICMPV4test02", DecodeICMPV4test02);
830 UtRegisterTest("DecodeICMPV4test03", DecodeICMPV4test03);
831 UtRegisterTest("DecodeICMPV4test04", DecodeICMPV4test04);
832 UtRegisterTest("DecodeICMPV4test05", DecodeICMPV4test05);
41dd0f8e 833 UtRegisterTest("ICMPV4CalculateValidChecksumtest05",
796dd522 834 ICMPV4CalculateValidChecksumtest05);
41dd0f8e 835 UtRegisterTest("ICMPV4CalculateInvalidChecksumtest06",
796dd522
JI
836 ICMPV4CalculateInvalidChecksumtest06);
837 UtRegisterTest("DecodeICMPV4InvalidType", ICMPV4InvalidType07);
838 UtRegisterTest("DecodeICMPV4test08", DecodeICMPV4test08);
afa8a676 839#endif /* UNITTESTS */
c43319c3 840}
acf10525
EL
841/**
842 * @}
843 */