suricata
decode-icmpv4.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 ICMPv4
31 */
32
33#include "suricata-common.h"
34
35#include "decode.h"
36#include "decode-events.h"
37#include "decode-ipv4.h"
38#include "decode-icmpv4.h"
39
40#include "flow.h"
41
42#include "util-unittest.h"
44#include "util-debug.h"
45#include "util-print.h"
46#include "util-validate.h"
47
48/**
49 * Note, this is the IP header, plus a bit of the original packet, not the whole thing!
50 */
51static int DecodePartialIPV4(Packet* p, uint8_t* partial_packet, uint16_t len)
52{
53 /** Check the sizes, the header must fit at least */
54 if (len < IPV4_HEADER_LEN) {
55 SCLogDebug("DecodePartialIPV4: ICMPV4_IPV4_TRUNC_PKT");
57 return -1;
58 }
59
60 IPV4Hdr *icmp4_ip4h = (IPV4Hdr*)partial_packet;
61
62 /** Check the embedded version */
63 if (IPV4_GET_RAW_VER(icmp4_ip4h) != 4) {
64 /** Check the embedded version */
65 SCLogDebug("DecodePartialIPV4: ICMPv4 contains Unknown IPV4 version "
66 "ICMPV4_IPV4_UNKNOWN_VER");
68 return -1;
69 }
70
71 /** We need to fill icmpv4vars */
72 const uint8_t *icmpv4_ptr = (const uint8_t *)p->l4.hdrs.icmpv4h;
73 DEBUG_VALIDATE_BUG_ON((ptrdiff_t)(partial_packet - icmpv4_ptr) > (ptrdiff_t)UINT16_MAX);
74 p->l4.vars.icmpv4.emb_ip4h_offset = (uint16_t)(partial_packet - icmpv4_ptr);
75
76 switch (IPV4_GET_RAW_IPPROTO(icmp4_ip4h)) {
77 case IPPROTO_TCP:
79 TCPHdr *emb_tcph = (TCPHdr *)(partial_packet + IPV4_HEADER_LEN);
80 p->l4.vars.icmpv4.emb_sport = SCNtohs(emb_tcph->th_sport);
81 p->l4.vars.icmpv4.emb_dport = SCNtohs(emb_tcph->th_dport);
82 p->l4.vars.icmpv4.emb_ports_set = true;
83 p->l4.vars.icmpv4.emb_ip4_proto = IPPROTO_TCP;
84
85 SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->TCP header sport: "
86 "%" PRIu16 " dport %" PRIu16 "",
88 } else if (len >= IPV4_HEADER_LEN + 4) {
89 /* only access th_sport and th_dport */
90 TCPHdr *emb_tcph = (TCPHdr *)(partial_packet + IPV4_HEADER_LEN);
91 p->l4.vars.icmpv4.emb_sport = SCNtohs(emb_tcph->th_sport);
92 p->l4.vars.icmpv4.emb_dport = SCNtohs(emb_tcph->th_dport);
93 p->l4.vars.icmpv4.emb_ports_set = true;
94 p->l4.vars.icmpv4.emb_ip4_proto = IPPROTO_TCP;
95 SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->TCP partial header sport: "
96 "%" PRIu16 " dport %" PRIu16 "",
98 } else {
99 SCLogDebug("DecodePartialIPV4: Warning, ICMPV4->IPV4->TCP "
100 "header Didn't fit in the packet!");
101 p->l4.vars.icmpv4.emb_sport = 0;
102 p->l4.vars.icmpv4.emb_dport = 0;
103 }
104
105 break;
106 case IPPROTO_UDP:
108 UDPHdr *emb_udph = (UDPHdr *)(partial_packet + IPV4_HEADER_LEN);
109 p->l4.vars.icmpv4.emb_sport = SCNtohs(emb_udph->uh_sport);
110 p->l4.vars.icmpv4.emb_dport = SCNtohs(emb_udph->uh_dport);
111 p->l4.vars.icmpv4.emb_ports_set = true;
112 p->l4.vars.icmpv4.emb_ip4_proto = IPPROTO_UDP;
113
114 SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->UDP header sport: "
115 "%" PRIu16 " dport %" PRIu16 "",
117 } else {
118 SCLogDebug("DecodePartialIPV4: Warning, ICMPV4->IPV4->UDP "
119 "header Didn't fit in the packet!");
120 p->l4.vars.icmpv4.emb_sport = 0;
121 p->l4.vars.icmpv4.emb_dport = 0;
122 }
123
124 break;
125 case IPPROTO_ICMP:
127 p->l4.vars.icmpv4.emb_sport = 0;
128 p->l4.vars.icmpv4.emb_dport = 0;
129 p->l4.vars.icmpv4.emb_ip4_proto = IPPROTO_ICMP;
130
131 SCLogDebug("DecodePartialIPV4: ICMPV4->IPV4->ICMP header");
132 }
133
134 break;
135 }
136
137 return 0;
138}
139
140/** DecodeICMPV4
141 * \brief Main ICMPv4 decoding function
142 */
143int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
144{
146
147 if (len < ICMPV4_HEADER_LEN) {
149 return TM_ECODE_FAILED;
150 }
151
152 ICMPV4Hdr *icmpv4h = PacketSetICMPv4(p, pkt);
153
154 SCLogDebug("ICMPV4 TYPE %" PRIu32 " CODE %" PRIu32 "", icmpv4h->type, icmpv4h->code);
155
156 p->proto = IPPROTO_ICMP;
157 const uint8_t type = p->icmp_s.type = icmpv4h->type;
158 const uint8_t code = p->icmp_s.code = icmpv4h->code;
159
160 int ctype = ICMPv4GetCounterpart(type);
161 if (ctype != -1) {
162 p->icmp_d.type = (uint8_t)ctype;
163 }
164
165 ICMPV4ExtHdr *icmp4eh = (ICMPV4ExtHdr *)icmpv4h;
167
168 switch (type) {
169 case ICMP_ECHOREPLY:
170 p->l4.vars.icmpv4.id = icmp4eh->id;
171 p->l4.vars.icmpv4.seq = icmp4eh->seq;
172 if (code != 0) {
174 }
175 break;
176
178 if (code > NR_ICMP_UNREACH) {
180 } else {
181 /* parse IP header plus 64 bytes */
183 if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) {
184 return TM_ECODE_FAILED;
185 }
186 (void)DecodePartialIPV4(p, (uint8_t *)(pkt + ICMPV4_HEADER_PKT_OFFSET),
187 (uint16_t)(len - ICMPV4_HEADER_PKT_OFFSET));
188 }
189 }
190 break;
191
193 if (code != 0) {
195 } else {
196 // parse IP header plus 64 bytes
198 if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) {
199 return TM_ECODE_FAILED;
200 }
201 DecodePartialIPV4(p, (uint8_t *)(pkt + ICMPV4_HEADER_PKT_OFFSET),
202 (uint16_t)(len - ICMPV4_HEADER_PKT_OFFSET));
203 }
204 }
205 break;
206
207 case ICMP_REDIRECT:
208 if (code > ICMP_REDIR_HOSTTOS) {
210 } else {
211 // parse IP header plus 64 bytes
213 if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) {
214 return TM_ECODE_FAILED;
215 }
216 DecodePartialIPV4(p, (uint8_t *)(pkt + ICMPV4_HEADER_PKT_OFFSET),
217 (uint16_t)(len - ICMPV4_HEADER_PKT_OFFSET));
218 }
219 }
220 break;
221
222 case ICMP_ECHO:
223 p->l4.vars.icmpv4.id = icmp4eh->id;
224 p->l4.vars.icmpv4.seq = icmp4eh->seq;
225 if (code != 0) {
227 }
228 break;
229
231 if (code > ICMP_EXC_FRAGTIME) {
233 } else {
234 // parse IP header plus 64 bytes
236 if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) {
237 return TM_ECODE_FAILED;
238 }
239 DecodePartialIPV4(p, (uint8_t *)(pkt + ICMPV4_HEADER_PKT_OFFSET),
240 (uint16_t)(len - ICMPV4_HEADER_PKT_OFFSET));
241 }
242 }
243 break;
244
246 if (code != 0) {
248 } else {
249 // parse IP header plus 64 bytes
251 if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) {
252 return TM_ECODE_FAILED;
253 }
254 DecodePartialIPV4(p, (uint8_t *)(pkt + ICMPV4_HEADER_PKT_OFFSET),
255 (uint16_t)(len - ICMPV4_HEADER_PKT_OFFSET));
256 }
257 }
258 break;
259
260 case ICMP_TIMESTAMP:
261 p->l4.vars.icmpv4.id = icmp4eh->id;
262 p->l4.vars.icmpv4.seq = icmp4eh->seq;
263 if (code != 0) {
265 }
266
267 if (len < (sizeof(ICMPV4Timestamp) + ICMPV4_HEADER_LEN)) {
269 } else {
270 p->l4.vars.icmpv4.hlen += sizeof(ICMPV4Timestamp);
271 }
272 break;
273
275 p->l4.vars.icmpv4.id = icmp4eh->id;
276 p->l4.vars.icmpv4.seq = icmp4eh->seq;
277 if (code != 0) {
279 }
280
281 if (len < (sizeof(ICMPV4Timestamp) + ICMPV4_HEADER_LEN)) {
283 } else {
284 p->l4.vars.icmpv4.hlen += sizeof(ICMPV4Timestamp);
285 }
286 break;
287
289 p->l4.vars.icmpv4.id = icmp4eh->id;
290 p->l4.vars.icmpv4.seq = icmp4eh->seq;
291 if (code != 0) {
293 }
294 break;
295
296 case ICMP_INFO_REPLY:
297 p->l4.vars.icmpv4.id = icmp4eh->id;
298 p->l4.vars.icmpv4.seq = icmp4eh->seq;
299 if (code != 0) {
301 }
302 break;
303
304 case ICMP_ROUTERADVERT: {
305 /* pkt points to beginning of icmp message */
306 ICMPV4RtrAdvert *icmpv4_router_advert = (ICMPV4RtrAdvert *)(pkt + sizeof(ICMPV4Hdr));
307 uint32_t advert_len = icmpv4_router_advert->naddr *
308 (icmpv4_router_advert->addr_sz * sizeof(uint32_t));
309 if (len < (advert_len + ICMPV4_HEADER_LEN)) {
311 } else {
312 p->l4.vars.icmpv4.hlen += advert_len;
313 }
314 } break;
315
316 case ICMP_ADDRESS:
317 p->l4.vars.icmpv4.id = icmp4eh->id;
318 p->l4.vars.icmpv4.seq = icmp4eh->seq;
319 if (code != 0) {
321 }
322 break;
323
325 p->l4.vars.icmpv4.id = icmp4eh->id;
326 p->l4.vars.icmpv4.seq = icmp4eh->seq;
327 if (code != 0) {
329 }
330 break;
331
332 default:
334 }
335
336 p->payload = (uint8_t *)pkt + p->l4.vars.icmpv4.hlen;
337 DEBUG_VALIDATE_BUG_ON(len - p->l4.vars.icmpv4.hlen > UINT16_MAX);
338 p->payload_len = (uint16_t)(len - p->l4.vars.icmpv4.hlen);
339
341 return TM_ECODE_OK;
342}
343
344/** \retval type counterpart type or -1 */
346{
347#define CASE_CODE(t,r) case (t): return r; case (r): return t;
348 switch (type) {
354 default:
355 return -1;
356 }
357#undef CASE_CODE
358}
359
360#ifdef UNITTESTS
361
362/** DecodeICMPV4test01
363 * \brief
364 * \retval 1 Expected test value
365 */
366static int DecodeICMPV4test01(void)
367{
368 uint8_t raw_icmpv4[] = {
369 0x08, 0x00, 0x78, 0x47, 0xfc, 0x55, 0x00, 0x04,
370 0x52, 0xab, 0x86, 0x4a, 0x84, 0x50, 0x0e, 0x00,
371 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
372 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
373 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
374 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
375 0xab };
377 FAIL_IF_NULL(p);
380 IPV4Hdr ip4h;
381
382 memset(&ip4h, 0, sizeof(IPV4Hdr));
383 memset(&tv, 0, sizeof(ThreadVars));
384 memset(&ip4h, 0, sizeof(IPV4Hdr));
385 memset(&dtv, 0, sizeof(DecodeThreadVars));
386
388
389 p->src.family = AF_INET;
390 p->dst.family = AF_INET;
391 p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");
392 p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");
393
394 ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
395 ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
396 UTHSetIPV4Hdr(p, &ip4h);
397
398 DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4));
399 FAIL_IF_NOT(PacketIsICMPv4(p));
400
401 const ICMPV4Hdr *icmpv4h = PacketGetICMPv4(p);
402 FAIL_IF_NULL(icmpv4h);
403
404 FAIL_IF_NOT(icmpv4h->type == 8);
405 FAIL_IF_NOT(icmpv4h->code == 0);
406
407 FlowShutdown();
408 SCFree(p);
409 PASS;
410}
411
412/** DecodeICMPV4test02
413 * \brief
414 * \retval 1 Expected test value
415 */
416static int DecodeICMPV4test02(void)
417{
418 uint8_t raw_icmpv4[] = {
419 0x00, 0x00, 0x57, 0x64, 0xfb, 0x55, 0x00, 0x03,
420 0x43, 0xab, 0x86, 0x4a, 0xf6, 0x49, 0x02, 0x00,
421 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
422 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
423 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
424 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
425 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f };
427 FAIL_IF_NULL(p);
430 IPV4Hdr ip4h;
431
432 memset(&ip4h, 0, sizeof(IPV4Hdr));
433 memset(&tv, 0, sizeof(ThreadVars));
434 memset(&dtv, 0, sizeof(DecodeThreadVars));
435
437
438 p->src.family = AF_INET;
439 p->dst.family = AF_INET;
440 p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");
441 p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");
442
443 ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
444 ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
445 UTHSetIPV4Hdr(p, &ip4h);
446
447 DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4));
448 FAIL_IF_NOT(PacketIsICMPv4(p));
449
450 const ICMPV4Hdr *icmpv4h = PacketGetICMPv4(p);
451 FAIL_IF_NULL(icmpv4h);
452
453 FAIL_IF_NOT(icmpv4h->type == 0);
454 FAIL_IF_NOT(icmpv4h->code == 0);
455
456 FlowShutdown();
457 SCFree(p);
458 PASS;
459}
460
461/** DecodeICMPV4test03
462 * \brief TTL exceeded
463 * \retval Expected test value: 1
464 */
465static int DecodeICMPV4test03(void)
466{
467 uint8_t raw_icmpv4[] = {
468 0x0b, 0x00, 0x6a, 0x3d, 0x00, 0x00, 0x00, 0x00,
469 0x45, 0x00, 0x00, 0x3c, 0x64, 0x15, 0x00, 0x00,
470 0x01, 0x11, 0xde, 0xfd, 0xc0, 0xa8, 0x01, 0x0d,
471 0xd1, 0x55, 0xe3, 0x93, 0x8b, 0x12, 0x82, 0xaa,
472 0x00, 0x28, 0x7c, 0xdd };
474 FAIL_IF_NULL(p);
477 IPV4Hdr ip4h;
478
479 memset(&ip4h, 0, sizeof(IPV4Hdr));
480 memset(&tv, 0, sizeof(ThreadVars));
481 memset(&dtv, 0, sizeof(DecodeThreadVars));
482
484
485 p->src.family = AF_INET;
486 p->dst.family = AF_INET;
487 p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");
488 p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");
489
490 ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
491 ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
492 UTHSetIPV4Hdr(p, &ip4h);
493
494 DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4));
495 FAIL_IF_NOT(PacketIsICMPv4(p));
496
497 const ICMPV4Hdr *icmpv4h = PacketGetICMPv4(p);
498 FAIL_IF_NULL(icmpv4h);
499
500 /* check it's type 11 code 0 */
501 FAIL_IF_NOT(icmpv4h->type == 11);
502 FAIL_IF_NOT(icmpv4h->code == 0);
503
504 /* check it's source port 35602 to port 33450 */
505 FAIL_IF(p->l4.vars.icmpv4.emb_sport != 35602);
506 FAIL_IF(p->l4.vars.icmpv4.emb_dport != 33450);
507
508 /* check the src,dst IPs contained inside */
509 uint32_t src_ip = IPV4_GET_RAW_IPSRC_U32(PacketGetICMPv4EmbIPv4(p));
510 uint32_t dst_ip = IPV4_GET_RAW_IPDST_U32(PacketGetICMPv4EmbIPv4(p));
511 char s[16], d[16];
512 PrintInet(AF_INET, &src_ip, s, sizeof(s));
513 PrintInet(AF_INET, &dst_ip, d, sizeof(d));
514
515 /* ICMPv4 embedding IPV4 192.168.1.13->209.85.227.147 pass */
516 FAIL_IF_NOT(strcmp(s, "192.168.1.13") == 0);
517 FAIL_IF_NOT(strcmp(d, "209.85.227.147") == 0);
518
519 FlowShutdown();
520 SCFree(p);
521 PASS;
522}
523
524/** DecodeICMPV4test04
525 * \brief dest. unreachable, administratively prohibited
526 * \retval 1 Expected test value
527 */
528static int DecodeICMPV4test04(void)
529{
530 uint8_t raw_icmpv4[] = {
531 0x03, 0x0a, 0x36, 0xc3, 0x00, 0x00, 0x00, 0x00,
532 0x45, 0x00, 0x00, 0x3c, 0x62, 0xee, 0x40, 0x00,
533 0x33, 0x06, 0xb4, 0x8f, 0xc0, 0xa8, 0x01, 0x0d,
534 0x58, 0x60, 0x16, 0x29, 0xb1, 0x0a, 0x00, 0x32,
535 0x3e, 0x36, 0x38, 0x7c, 0x00, 0x00, 0x00, 0x00,
536 0xa0, 0x02, 0x16, 0xd0, 0x72, 0x04, 0x00, 0x00,
537 0x02, 0x04, 0x05, 0x8a, 0x04, 0x02, 0x08, 0x0a };
539 if (unlikely(p == NULL))
540 return 0;
543 int ret = 0;
544 IPV4Hdr ip4h;
545
546 memset(&ip4h, 0, sizeof(IPV4Hdr));
547 memset(&tv, 0, sizeof(ThreadVars));
548 memset(&dtv, 0, sizeof(DecodeThreadVars));
549
551
552 p->src.family = AF_INET;
553 p->dst.family = AF_INET;
554 p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");
555 p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");
556
557 ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
558 ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
559 UTHSetIPV4Hdr(p, &ip4h);
560
561 DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4));
562 FAIL_IF_NOT(PacketIsICMPv4(p));
563
564 const ICMPV4Hdr *icmpv4h = PacketGetICMPv4(p);
565 FAIL_IF_NULL(icmpv4h);
566
567 /* check the type,code pair is correct - type 3, code 10 */
568 FAIL_IF_NOT(icmpv4h->type == 3);
569 FAIL_IF_NOT(icmpv4h->code == 10);
570
571 /* check it's src port 45322 to dst port 50 */
572 if (p->l4.vars.icmpv4.emb_sport != 45322 || p->l4.vars.icmpv4.emb_dport != 50) {
573 goto end;
574 }
575
576 // check the src,dst IPs contained inside
577 uint32_t src_ip = IPV4_GET_RAW_IPSRC_U32(PacketGetICMPv4EmbIPv4(p));
578 uint32_t dst_ip = IPV4_GET_RAW_IPDST_U32(PacketGetICMPv4EmbIPv4(p));
579 char s[16], d[16];
580 PrintInet(AF_INET, &src_ip, s, sizeof(s));
581 PrintInet(AF_INET, &dst_ip, d, sizeof(d));
582
583 // ICMPv4 embedding IPV4 192.168.1.13->88.96.22.41
584 if (strcmp(s, "192.168.1.13") == 0 && strcmp(d, "88.96.22.41") == 0) {
585 ret = 1;
586 }
587
588end:
589 FlowShutdown();
590 SCFree(p);
591 return ret;
592}
593
594/** DecodeICMPV4test05
595 * \brief dest. unreachable, administratively prohibited
596 * \retval 1 Expected test value
597 */
598static int DecodeICMPV4test05(void)
599{
600 uint8_t raw_icmpv4[] = {
601 0x0b, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x00, 0x00, 0x45,
602 0x00, 0x00, 0x30, 0x02, 0x17, 0x40, 0x00, 0x01, 0x06,
603 0xd6, 0xbd, 0xc0, 0xa8, 0x02, 0x05, 0x3d, 0x23, 0xa1,
604 0x23, 0x04, 0x18, 0x00, 0x50, 0xd2, 0x08, 0xc2, 0x48,
605 };
607 if (unlikely(p == NULL))
608 return 0;
611 int ret = 0;
612 IPV4Hdr ip4h;
613
614 memset(&ip4h, 0, sizeof(IPV4Hdr));
615 memset(&tv, 0, sizeof(ThreadVars));
616 memset(&dtv, 0, sizeof(DecodeThreadVars));
617
619
620 p->src.family = AF_INET;
621 p->dst.family = AF_INET;
622 p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");
623 p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");
624
625 ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
626 ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
627 UTHSetIPV4Hdr(p, &ip4h);
628
629 DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4));
630 FAIL_IF_NOT(PacketIsICMPv4(p));
631
632 const ICMPV4Hdr *icmpv4h = PacketGetICMPv4(p);
633 FAIL_IF_NULL(icmpv4h);
634
635 /* check the type,code pair is correct - type 11, code 0 */
636 FAIL_IF_NOT(icmpv4h->type == 11);
637 FAIL_IF_NOT(icmpv4h->code == 0);
638
639 /* check it's src port 1048 to dst port 80 */
640 if (p->l4.vars.icmpv4.emb_sport != 1048 || p->l4.vars.icmpv4.emb_dport != 80) {
641 goto end;
642 }
643
644 // check the src,dst IPs contained inside
645 uint32_t src_ip = IPV4_GET_RAW_IPSRC_U32(PacketGetICMPv4EmbIPv4(p));
646 uint32_t dst_ip = IPV4_GET_RAW_IPDST_U32(PacketGetICMPv4EmbIPv4(p));
647 char s[16], d[16];
648 PrintInet(AF_INET, &src_ip, s, sizeof(s));
649 PrintInet(AF_INET, &dst_ip, d, sizeof(d));
650
651 // ICMPv4 embedding IPV4 192.168.2.5->61.35.161.35
652 if (strcmp(s, "192.168.2.5") == 0 && strcmp(d, "61.35.161.35") == 0) {
653 ret = 1;
654 }
655
656end:
657 FlowShutdown();
658 SCFree(p);
659 return ret;
660}
661
662static int ICMPV4CalculateValidChecksumtest05(void)
663{
664 uint16_t csum = 0;
665
666 uint8_t raw_icmpv4[] = {
667 0x08, 0x00, 0xab, 0x9b, 0x7f, 0x2b, 0x05, 0x2c,
668 0x3f, 0x72, 0x93, 0x4a, 0x00, 0x4d, 0x0a, 0x00,
669 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
670 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
671 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
672 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
673 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
674 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37};
675
676 csum = *( ((uint16_t *)raw_icmpv4) + 1);
677 return (csum == ICMPV4CalculateChecksum((uint16_t *)raw_icmpv4, sizeof(raw_icmpv4)));
678}
679
680static int ICMPV4CalculateInvalidChecksumtest06(void)
681{
682 uint16_t csum = 0;
683
684 uint8_t raw_icmpv4[] = {
685 0x08, 0x00, 0xab, 0x9b, 0x7f, 0x2b, 0x05, 0x2c,
686 0x3f, 0x72, 0x93, 0x4a, 0x00, 0x4d, 0x0a, 0x00,
687 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
688 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
689 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
690 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
691 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
692 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38};
693
694 csum = *( ((uint16_t *)raw_icmpv4) + 1);
695 return (csum != ICMPV4CalculateChecksum((uint16_t *)raw_icmpv4, sizeof(raw_icmpv4)));
696}
697
698static int ICMPV4InvalidType07(void)
699{
700
701 uint8_t raw_icmpv4[] = {
702 0xff, 0x00, 0xab, 0x9b, 0x7f, 0x2b, 0x05, 0x2c,
703 0x3f, 0x72, 0x93, 0x4a, 0x00, 0x4d, 0x0a, 0x00,
704 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
705 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
706 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
707 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
708 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
709 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38};
710
712 if (unlikely(p == NULL))
713 return 0;
716 int ret = 0;
717 IPV4Hdr ip4h;
718
719 memset(&ip4h, 0, sizeof(IPV4Hdr));
720 memset(&tv, 0, sizeof(ThreadVars));
721 memset(&dtv, 0, sizeof(DecodeThreadVars));
722
724
725 p->src.family = AF_INET;
726 p->dst.family = AF_INET;
727 p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");
728 p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");
729
730 ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
731 ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
732 UTHSetIPV4Hdr(p, &ip4h);
733
734 DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4));
735
737 ret = 1;
738 }
739
740 FlowShutdown();
741 SCFree(p);
742 return ret;
743}
744
745/** DecodeICMPV4test08
746 * \brief
747 * \retval 1 Expected test value - what we really want is not to segfault
748 */
749static int DecodeICMPV4test08(void)
750{
751 uint8_t raw_icmpv4[] = {
752 0x08, 0x00, 0x78, 0x47, 0xfc, 0x55, 0x00, 0x00
753 };
755 FAIL_IF_NULL(p);
758 IPV4Hdr ip4h;
759
760 memset(&ip4h, 0, sizeof(IPV4Hdr));
761 memset(&tv, 0, sizeof(ThreadVars));
762 memset(&dtv, 0, sizeof(DecodeThreadVars));
763
765
766 p->src.family = AF_INET;
767 p->dst.family = AF_INET;
768 p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");
769 p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");
770
771 ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
772 ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
773 UTHSetIPV4Hdr(p, &ip4h);
774
775 DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4));
776 FAIL_IF_NOT(PacketIsICMPv4(p));
777
778 const ICMPV4Hdr *icmpv4h = PacketGetICMPv4(p);
779 FAIL_IF_NULL(icmpv4h);
780
781 FAIL_IF_NOT(icmpv4h->type == 8);
782 FAIL_IF_NOT(icmpv4h->code == 0);
783
784 FlowShutdown();
785 SCFree(p);
786 PASS;
787}
788#endif /* UNITTESTS */
789
790/**
791 * \brief Registers ICMPV4 unit test
792 */
794{
795#ifdef UNITTESTS
796 UtRegisterTest("DecodeICMPV4test01", DecodeICMPV4test01);
797 UtRegisterTest("DecodeICMPV4test02", DecodeICMPV4test02);
798 UtRegisterTest("DecodeICMPV4test03", DecodeICMPV4test03);
799 UtRegisterTest("DecodeICMPV4test04", DecodeICMPV4test04);
800 UtRegisterTest("DecodeICMPV4test05", DecodeICMPV4test05);
801 UtRegisterTest("ICMPV4CalculateValidChecksumtest05",
802 ICMPV4CalculateValidChecksumtest05);
803 UtRegisterTest("ICMPV4CalculateInvalidChecksumtest06",
804 ICMPV4CalculateInvalidChecksumtest06);
805 UtRegisterTest("DecodeICMPV4InvalidType", ICMPV4InvalidType07);
806 UtRegisterTest("DecodeICMPV4test08", DecodeICMPV4test08);
807#endif /* UNITTESTS */
808}
809/**
810 * @}
811 */
uint8_t len
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition counters.c:166
@ ICMPV4_IPV4_UNKNOWN_VER
@ ICMPV4_UNKNOWN_TYPE
@ ICMPV4_PKT_TOO_SMALL
@ ICMPV4_UNKNOWN_CODE
@ ICMPV4_IPV4_TRUNC_PKT
int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Main ICMPv4 decoding function.
#define CASE_CODE(t, r)
int ICMPv4GetCounterpart(uint8_t type)
void DecodeICMPV4RegisterTests(void)
Registers ICMPV4 unit test.
#define ICMP_REDIR_HOSTTOS
#define ICMP_TIMESTAMPREPLY
#define ICMPV4_HEADER_LEN
#define ICMP_SOURCE_QUENCH
#define NR_ICMP_UNREACH
#define ICMP_TIME_EXCEEDED
#define ICMP_ROUTERADVERT
#define ICMP_ROUTERSOLICIT
#define ICMP_PARAMETERPROB
#define ICMP_REDIRECT
#define ICMP_ADDRESSREPLY
#define ICMP_ADDRESS
#define ICMP_TIMESTAMP
#define ICMPV4_HEADER_PKT_OFFSET
#define ICMP_ECHOREPLY
#define ICMP_EXC_FRAGTIME
#define ICMP_INFO_REPLY
#define ICMP_INFO_REQUEST
#define ICMP_DEST_UNREACH
#define ICMP_ECHO
#define IPV4_GET_RAW_IPSRC_U32(ip4h)
#define IPV4_GET_RAW_IPDST_U32(ip4h)
#define IPV4_HEADER_LEN
Definition decode-ipv4.h:28
#define IPV4_GET_RAW_VER(ip4h)
Definition decode-ipv4.h:95
#define IPV4_GET_RAW_IPPROTO(ip4h)
#define TCP_HEADER_LEN
Definition decode-tcp.h:28
#define UDP_HEADER_LEN
Definition decode-udp.h:27
uint16_t type
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition decode.h:1194
#define ENGINE_ISSET_EVENT(p, e)
Definition decode.h:1199
#define ENGINE_SET_EVENT(p, e)
Definition decode.h:1186
void FlowSetupPacket(Packet *p)
prepare packet for a life with flow Set PKT_WANTS_FLOW flag to indicate workers should do a flow look...
Definition flow-hash.c:533
void FlowInitConfig(bool quiet)
initialize the configuration
Definition flow.c:547
void FlowShutdown(void)
shutdown the flow engine
Definition flow.c:691
#define FLOW_QUIET
Definition flow.h:43
DecodeThreadVars * dtv
ThreadVars * tv
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition decode.c:258
char family
Definition decode.h:113
Structure to hold thread specific data for all decode modules.
Definition decode.h:963
uint16_t counter_icmpv4
Definition decode.h:987
uint16_t emb_ip4h_offset
uint8_t emb_ip4_proto
uint16_t emb_dport
uint16_t emb_sport
uint16_t hlen
union PacketL4::L4Vars vars
union PacketL4::L4Hdrs hdrs
struct Packet_::@33::@40 icmp_s
struct PacketL4 l4
Definition decode.h:601
Address src
Definition decode.h:505
uint8_t code
Definition decode.h:512
uint8_t type
Definition decode.h:511
struct Packet_::@35::@41 icmp_d
uint8_t * payload
Definition decode.h:605
uint16_t payload_len
Definition decode.h:606
Address dst
Definition decode.h:506
uint8_t proto
Definition decode.h:523
uint16_t th_dport
Definition decode-tcp.h:151
uint16_t th_sport
Definition decode-tcp.h:150
Per thread variable structure.
Definition threadvars.h:58
uint16_t uh_dport
Definition decode-udp.h:44
uint16_t uh_sport
Definition decode-udp.h:43
#define SCNtohs(x)
@ TM_ECODE_FAILED
@ TM_ECODE_OK
ICMPV4Hdr * icmpv4h
Definition decode.h:471
ICMPV4Vars icmpv4
Definition decode.h:479
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCFree(p)
Definition util-mem.h:61
#define unlikely(expr)
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition util-print.c:231
void UTHSetIPV4Hdr(Packet *p, IPV4Hdr *ip4h)
uint32_t UTHSetIPv4Address(const char *str)
return the uint32_t for a ipv4 address string
#define DEBUG_VALIDATE_BUG_ON(exp)