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