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"
43 #include "util-unittest-helper.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  */
51 static 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:
107  if (len >= IPV4_HEADER_LEN + UDP_HEADER_LEN ) {
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  */
143 int 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 
177  case ICMP_DEST_UNREACH:
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 
192  case ICMP_SOURCE_QUENCH:
193  if (code != 0) {
195  } else {
196  // parse IP header plus 64 bytes
197  if (len >= ICMPV4_HEADER_PKT_OFFSET) {
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 
230  case ICMP_TIME_EXCEEDED:
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 
245  case ICMP_PARAMETERPROB:
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 
274  case ICMP_TIMESTAMPREPLY:
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 
288  case ICMP_INFO_REQUEST:
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 
324  case ICMP_ADDRESSREPLY:
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 
340  FlowSetupPacket(p);
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  */
366 static 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 };
376  Packet *p = PacketGetFromAlloc();
377  FAIL_IF_NULL(p);
378  ThreadVars tv;
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  */
416 static 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 };
426  Packet *p = PacketGetFromAlloc();
427  FAIL_IF_NULL(p);
428  ThreadVars tv;
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  */
465 static 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 };
473  Packet *p = PacketGetFromAlloc();
474  FAIL_IF_NULL(p);
475  ThreadVars tv;
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  */
528 static 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 };
538  Packet *p = PacketGetFromAlloc();
539  if (unlikely(p == NULL))
540  return 0;
541  ThreadVars tv;
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 
588 end:
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  */
598 static 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  };
606  Packet *p = PacketGetFromAlloc();
607  if (unlikely(p == NULL))
608  return 0;
609  ThreadVars tv;
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 
656 end:
657  FlowShutdown();
658  SCFree(p);
659  return ret;
660 }
661 
662 static 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 
680 static 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 
698 static 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 
711  Packet *p = PacketGetFromAlloc();
712  if (unlikely(p == NULL))
713  return 0;
714  ThreadVars tv;
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  */
749 static int DecodeICMPV4test08(void)
750 {
751  uint8_t raw_icmpv4[] = {
752  0x08, 0x00, 0x78, 0x47, 0xfc, 0x55, 0x00, 0x00
753  };
754  Packet *p = PacketGetFromAlloc();
755  FAIL_IF_NULL(p);
756  ThreadVars tv;
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  */
ENGINE_SET_EVENT
#define ENGINE_SET_EVENT(p, e)
Definition: decode.h:1159
Packet_::proto
uint8_t proto
Definition: decode.h:504
len
uint8_t len
Definition: app-layer-dnp3.h:2
TCPHdr_::th_dport
uint16_t th_dport
Definition: decode-tcp.h:151
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
UDPHdr_::uh_dport
uint16_t uh_dport
Definition: decode-udp.h:44
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:167
IPV4_GET_RAW_IPDST_U32
#define IPV4_GET_RAW_IPDST_U32(ip4h)
Definition: decode-ipv4.h:110
ICMP_INFO_REQUEST
#define ICMP_INFO_REQUEST
Definition: decode-icmpv4.h:66
IPV4_GET_RAW_IPPROTO
#define IPV4_GET_RAW_IPPROTO(ip4h)
Definition: decode-ipv4.h:103
ICMPV4ExtHdr_
Definition: decode-icmpv4.h:173
ICMP_PARAMETERPROB
#define ICMP_PARAMETERPROB
Definition: decode-icmpv4.h:57
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
ICMPV4_IPV4_UNKNOWN_VER
@ ICMPV4_IPV4_UNKNOWN_VER
Definition: decode-events.h:52
ENGINE_ISSET_EVENT
#define ENGINE_ISSET_EVENT(p, e)
Definition: decode.h:1174
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
TCP_HEADER_LEN
#define TCP_HEADER_LEN
Definition: decode-tcp.h:28
Packet_::payload
uint8_t * payload
Definition: decode.h:588
ICMP_REDIRECT
#define ICMP_REDIRECT
Definition: decode-icmpv4.h:42
UTHSetIPV4Hdr
void UTHSetIPV4Hdr(Packet *p, IPV4Hdr *ip4h)
Definition: util-unittest-helper.c:126
UTHSetIPv4Address
uint32_t UTHSetIPv4Address(const char *str)
return the uint32_t for a ipv4 address string
Definition: util-unittest-helper.c:148
ICMPV4_HEADER_PKT_OFFSET
#define ICMPV4_HEADER_PKT_OFFSET
Definition: decode-icmpv4.h:223
ICMPV4ExtHdr_::seq
uint16_t seq
Definition: decode-icmpv4.h:178
ICMP_REDIR_HOSTTOS
#define ICMP_REDIR_HOSTTOS
Definition: decode-icmpv4.h:147
ICMP_SOURCE_QUENCH
#define ICMP_SOURCE_QUENCH
Definition: decode-icmpv4.h:39
Packet_::icmp_s
struct Packet_::@33::@40 icmp_s
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:85
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:589
util-unittest.h
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
ICMP_ROUTERSOLICIT
#define ICMP_ROUTERSOLICIT
Definition: decode-icmpv4.h:51
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:84
ICMPV4Vars_::emb_ip4h_offset
uint16_t emb_ip4h_offset
Definition: decode-icmpv4.h:184
ICMPV4_IPV4_TRUNC_PKT
@ ICMPV4_IPV4_TRUNC_PKT
Definition: decode-events.h:51
ICMP_ECHO
#define ICMP_ECHO
Definition: decode-icmpv4.h:45
ICMP_ADDRESSREPLY
#define ICMP_ADDRESSREPLY
Definition: decode-icmpv4.h:75
FlowInitConfig
void FlowInitConfig(bool quiet)
initialize the configuration
Definition: flow.c:527
TCPHdr_::th_sport
uint16_t th_sport
Definition: decode-tcp.h:150
ICMP_ADDRESS
#define ICMP_ADDRESS
Definition: decode-icmpv4.h:72
decode.h
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
DecodeThreadVars_::counter_icmpv4
uint16_t counter_icmpv4
Definition: decode.h:969
PacketL4::L4Vars::icmpv4
ICMPV4Vars icmpv4
Definition: decode.h:460
ICMPV4Vars_::hlen
uint16_t hlen
Definition: decode-icmpv4.h:190
ICMPV4Vars_::emb_ip4_proto
uint8_t emb_ip4_proto
Definition: decode-icmpv4.h:192
util-print.h
ICMPV4Vars_::emb_dport
uint16_t emb_dport
Definition: decode-icmpv4.h:197
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
PrintInet
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition: util-print.c:237
ICMPV4_UNKNOWN_CODE
@ ICMPV4_UNKNOWN_CODE
Definition: decode-events.h:50
ICMPV4Vars_::id
uint16_t id
Definition: decode-icmpv4.h:186
ICMPV4Vars_::emb_ports_set
bool emb_ports_set
Definition: decode-icmpv4.h:194
ICMPV4_UNKNOWN_TYPE
@ ICMPV4_UNKNOWN_TYPE
Definition: decode-events.h:49
PacketL4::L4Hdrs::icmpv4h
ICMPV4Hdr * icmpv4h
Definition: decode.h:452
ICMPV4Hdr_::type
uint8_t type
Definition: decode-icmpv4.h:166
ICMP_EXC_FRAGTIME
#define ICMP_EXC_FRAGTIME
Definition: decode-icmpv4.h:155
Packet_
Definition: decode.h:482
type
uint16_t type
Definition: decode-vlan.c:107
ICMP_INFO_REPLY
#define ICMP_INFO_REPLY
Definition: decode-icmpv4.h:69
decode-icmpv4.h
ICMPV4_PKT_TOO_SMALL
@ ICMPV4_PKT_TOO_SMALL
Definition: decode-events.h:48
ICMPV4Hdr_
Definition: decode-icmpv4.h:165
Packet_::l4
struct PacketL4 l4
Definition: decode.h:584
ICMPV4_HEADER_LEN
#define ICMPV4_HEADER_LEN
Definition: decode-icmpv4.h:30
IPV4_GET_RAW_VER
#define IPV4_GET_RAW_VER(ip4h)
Definition: decode-ipv4.h:95
ICMP_TIME_EXCEEDED
#define ICMP_TIME_EXCEEDED
Definition: decode-icmpv4.h:54
ICMPv4GetCounterpart
int ICMPv4GetCounterpart(uint8_t type)
Definition: decode-icmpv4.c:345
ICMP_ECHOREPLY
#define ICMP_ECHOREPLY
Definition: decode-icmpv4.h:33
decode-events.h
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:33
IPV4Hdr_
Definition: decode-ipv4.h:72
decode-ipv4.h
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
NR_ICMP_UNREACH
#define NR_ICMP_UNREACH
Definition: decode-icmpv4.h:133
SCNtohs
#define SCNtohs(x)
Definition: suricata-common.h:414
suricata-common.h
IPV4_GET_RAW_IPSRC_U32
#define IPV4_GET_RAW_IPSRC_U32(ip4h)
Definition: decode-ipv4.h:108
FlowShutdown
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:675
IPV4_HEADER_LEN
#define IPV4_HEADER_LEN
Definition: decode-ipv4.h:28
ICMPV4ExtHdr_::id
uint16_t id
Definition: decode-icmpv4.h:177
ICMP_ROUTERADVERT
#define ICMP_ROUTERADVERT
Definition: decode-icmpv4.h:48
Packet_::icmp_d
struct Packet_::@35::@41 icmp_d
UDPHdr_::uh_sport
uint16_t uh_sport
Definition: decode-udp.h:43
ICMPV4Hdr_::code
uint8_t code
Definition: decode-icmpv4.h:167
UDPHdr_
Definition: decode-udp.h:42
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
util-validate.h
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:232
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:946
ICMP_DEST_UNREACH
#define ICMP_DEST_UNREACH
Definition: decode-icmpv4.h:36
DecodeICMPV4RegisterTests
void DecodeICMPV4RegisterTests(void)
Registers ICMPV4 unit test.
Definition: decode-icmpv4.c:793
CASE_CODE
#define CASE_CODE(t, r)
ICMP_TIMESTAMPREPLY
#define ICMP_TIMESTAMPREPLY
Definition: decode-icmpv4.h:63
PacketL4::hdrs
union PacketL4::L4Hdrs hdrs
UDP_HEADER_LEN
#define UDP_HEADER_LEN
Definition: decode-udp.h:27
Address_::family
char family
Definition: decode.h:118
Packet_::dst
Address dst
Definition: decode.h:487
ENGINE_SET_INVALID_EVENT
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:1167
FLOW_QUIET
#define FLOW_QUIET
Definition: flow.h:43
ICMP_TIMESTAMP
#define ICMP_TIMESTAMP
Definition: decode-icmpv4.h:60
ICMPV4Vars_::emb_sport
uint16_t emb_sport
Definition: decode-icmpv4.h:196
flow.h
ICMPV4Vars_::seq
uint16_t seq
Definition: decode-icmpv4.h:187
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
FlowSetupPacket
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:521
TCPHdr_
Definition: decode-tcp.h:149
Packet_::src
Address src
Definition: decode.h:486
PacketL4::vars
union PacketL4::L4Vars vars
DecodeICMPV4
int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Main ICMPv4 decoding function.
Definition: decode-icmpv4.c:143