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