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