suricata
decode-icmpv4.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2010 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:
81  if (len >= IPV4_HEADER_LEN + TCP_HEADER_LEN ) {
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:
128  if (len >= IPV4_HEADER_LEN + ICMPV4_HEADER_LEN ) {
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, uint8_t *pkt, uint32_t len, PacketQueue *pq)
156 {
157  StatsIncr(tv, dtv->counter_icmpv4);
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  p->payload = pkt + ICMPV4_HEADER_LEN;
172  p->payload_len = len - ICMPV4_HEADER_LEN;
173 
174  int ctype = ICMPv4GetCounterpart(p->icmp_s.type);
175  if (ctype != -1) {
176  p->icmp_d.type = (uint8_t)ctype;
177  }
178 
179  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 */
196  if (len > ICMPV4_HEADER_PKT_OFFSET) {
197  (void)DecodePartialIPV4(p, (uint8_t *)(pkt + ICMPV4_HEADER_PKT_OFFSET),
198  len - ICMPV4_HEADER_PKT_OFFSET );
199  }
200  }
201  break;
202 
203  case ICMP_SOURCE_QUENCH:
204  if (p->icmpv4h->code!=0) {
206  } else {
207  // parse IP header plus 64 bytes
208  if (len >= ICMPV4_HEADER_PKT_OFFSET) {
209  if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) {
210  return TM_ECODE_FAILED;
211  }
212  DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
213  }
214  }
215  break;
216 
217  case ICMP_REDIRECT:
218  if (p->icmpv4h->code>ICMP_REDIR_HOSTTOS) {
220  } else {
221  // parse IP header plus 64 bytes
222  if (len > ICMPV4_HEADER_PKT_OFFSET) {
223  if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) {
224  return TM_ECODE_FAILED;
225  }
226  DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
227  }
228  }
229  break;
230 
231  case ICMP_ECHO:
232  p->icmpv4vars.id=icmp4eh->id;
233  p->icmpv4vars.seq=icmp4eh->seq;
234  if (p->icmpv4h->code!=0) {
236  }
237  break;
238 
239  case ICMP_TIME_EXCEEDED:
240  if (p->icmpv4h->code>ICMP_EXC_FRAGTIME) {
242  } else {
243  // parse IP header plus 64 bytes
244  if (len > ICMPV4_HEADER_PKT_OFFSET) {
245  if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) {
246  return TM_ECODE_FAILED;
247  }
248  DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
249  }
250  }
251  break;
252 
253  case ICMP_PARAMETERPROB:
254  if (p->icmpv4h->code!=0) {
256  } else {
257  // parse IP header plus 64 bytes
258  if (len > ICMPV4_HEADER_PKT_OFFSET) {
259  if (unlikely(len > ICMPV4_HEADER_PKT_OFFSET + USHRT_MAX)) {
260  return TM_ECODE_FAILED;
261  }
262  DecodePartialIPV4( p, (uint8_t*) (pkt + ICMPV4_HEADER_PKT_OFFSET), len - ICMPV4_HEADER_PKT_OFFSET );
263  }
264  }
265  break;
266 
267  case ICMP_TIMESTAMP:
268  p->icmpv4vars.id=icmp4eh->id;
269  p->icmpv4vars.seq=icmp4eh->seq;
270  if (p->icmpv4h->code!=0) {
272  }
273  break;
274 
275  case ICMP_TIMESTAMPREPLY:
276  p->icmpv4vars.id=icmp4eh->id;
277  p->icmpv4vars.seq=icmp4eh->seq;
278  if (p->icmpv4h->code!=0) {
280  }
281  break;
282 
283  case ICMP_INFO_REQUEST:
284  p->icmpv4vars.id=icmp4eh->id;
285  p->icmpv4vars.seq=icmp4eh->seq;
286  if (p->icmpv4h->code!=0) {
288  }
289  break;
290 
291  case ICMP_INFO_REPLY:
292  p->icmpv4vars.id=icmp4eh->id;
293  p->icmpv4vars.seq=icmp4eh->seq;
294  if (p->icmpv4h->code!=0) {
296  }
297  break;
298 
299  case ICMP_ADDRESS:
300  p->icmpv4vars.id=icmp4eh->id;
301  p->icmpv4vars.seq=icmp4eh->seq;
302  if (p->icmpv4h->code!=0) {
304  }
305  break;
306 
307  case ICMP_ADDRESSREPLY:
308  p->icmpv4vars.id=icmp4eh->id;
309  p->icmpv4vars.seq=icmp4eh->seq;
310  if (p->icmpv4h->code!=0) {
312  }
313  break;
314 
315  default:
317 
318  }
319 
320  FlowSetupPacket(p);
321  return TM_ECODE_OK;
322 }
323 
324 /** \retval type counterpart type or -1 */
326 {
327 #define CASE_CODE(t,r) case (t): return r; case (r): return t;
328  switch (type) {
329  CASE_CODE(ICMP_ECHO, ICMP_ECHOREPLY);
330  CASE_CODE(ICMP_TIMESTAMP, ICMP_TIMESTAMPREPLY);
331  CASE_CODE(ICMP_INFO_REQUEST, ICMP_INFO_REPLY);
332  CASE_CODE(ICMP_ROUTERSOLICIT, ICMP_ROUTERADVERT);
333  CASE_CODE(ICMP_ADDRESS, ICMP_ADDRESSREPLY);
334  default:
335  return -1;
336  }
337 #undef CASE_CODE
338 }
339 
340 #ifdef UNITTESTS
341 
342 /** DecodeICMPV4test01
343  * \brief
344  * \retval 1 Expected test value
345  */
346 static int DecodeICMPV4test01(void)
347 {
348  uint8_t raw_icmpv4[] = {
349  0x08, 0x00, 0x78, 0x47, 0xfc, 0x55, 0x00, 0x04,
350  0x52, 0xab, 0x86, 0x4a, 0x84, 0x50, 0x0e, 0x00,
351  0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
352  0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
353  0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
354  0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
355  0xab };
357  if (unlikely(p == NULL))
358  return 0;
359  ThreadVars tv;
360  DecodeThreadVars dtv;
361  int ret = 0;
362  IPV4Hdr ip4h;
363 
364  memset(&ip4h, 0, sizeof(IPV4Hdr));
365  memset(&tv, 0, sizeof(ThreadVars));
366  memset(p, 0, SIZE_OF_PACKET);
367  memset(&ip4h, 0, sizeof(IPV4Hdr));
368  memset(&dtv, 0, sizeof(DecodeThreadVars));
369 
371 
372  p->src.family = AF_INET;
373  p->dst.family = AF_INET;
374  p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");;
375  p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");;
376 
377  ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
378  ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
379  p->ip4h = &ip4h;
380 
381  DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
382 
383  if (NULL!=p->icmpv4h) {
384  if (p->icmpv4h->type==8 && p->icmpv4h->code==0) {
385  ret = 1;
386  }
387  }
388 
389  FlowShutdown();
390  SCFree(p);
391  return ret;
392 }
393 
394 /** DecodeICMPV4test02
395  * \brief
396  * \retval 1 Expected test value
397  */
398 static int DecodeICMPV4test02(void)
399 {
400  uint8_t raw_icmpv4[] = {
401  0x00, 0x00, 0x57, 0x64, 0xfb, 0x55, 0x00, 0x03,
402  0x43, 0xab, 0x86, 0x4a, 0xf6, 0x49, 0x02, 0x00,
403  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
404  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
405  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
406  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
407  0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f };
409  if (unlikely(p == NULL))
410  return 0;
411  ThreadVars tv;
412  DecodeThreadVars dtv;
413  int ret = 0;
414  IPV4Hdr ip4h;
415 
416  memset(&ip4h, 0, sizeof(IPV4Hdr));
417  memset(&tv, 0, sizeof(ThreadVars));
418  memset(p, 0, SIZE_OF_PACKET);
419  memset(&dtv, 0, sizeof(DecodeThreadVars));
420 
422 
423  p->src.family = AF_INET;
424  p->dst.family = AF_INET;
425  p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");;
426  p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");;
427 
428  ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
429  ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
430  p->ip4h = &ip4h;
431 
432  DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
433 
434  if (NULL!=p->icmpv4h) {
435  if (p->icmpv4h->type==0 && p->icmpv4h->code==0) {
436  ret = 1;
437  }
438  }
439 
440  FlowShutdown();
441  SCFree(p);
442  return ret;
443 }
444 
445 /** DecodeICMPV4test03
446  * \brief TTL exceeded
447  * \retval Expected test value: 1
448  */
449 static int DecodeICMPV4test03(void)
450 {
451  uint8_t raw_icmpv4[] = {
452  0x0b, 0x00, 0x6a, 0x3d, 0x00, 0x00, 0x00, 0x00,
453  0x45, 0x00, 0x00, 0x3c, 0x64, 0x15, 0x00, 0x00,
454  0x01, 0x11, 0xde, 0xfd, 0xc0, 0xa8, 0x01, 0x0d,
455  0xd1, 0x55, 0xe3, 0x93, 0x8b, 0x12, 0x82, 0xaa,
456  0x00, 0x28, 0x7c, 0xdd };
458  if (unlikely(p == NULL))
459  return 0;
460  ThreadVars tv;
461  DecodeThreadVars dtv;
462  int ret = 0;
463  IPV4Hdr ip4h;
464 
465  memset(&ip4h, 0, sizeof(IPV4Hdr));
466  memset(&tv, 0, sizeof(ThreadVars));
467  memset(p, 0, SIZE_OF_PACKET);
468  memset(&dtv, 0, sizeof(DecodeThreadVars));
469 
471 
472  p->src.family = AF_INET;
473  p->dst.family = AF_INET;
474  p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");;
475  p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");;
476 
477  ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
478  ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
479  p->ip4h = &ip4h;
480 
481  DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
482 
483  if (NULL == p->icmpv4h) {
484  printf("NULL == p->icmpv4h: ");
485  goto end;
486  }
487 
488  /* check it's type 11 code 0 */
489  if (p->icmpv4h->type != 11 || p->icmpv4h->code != 0) {
490  printf("p->icmpv4h->type %u, p->icmpv4h->code %u: ",
491  p->icmpv4h->type, p->icmpv4h->code);
492  goto end;
493  }
494 
495  /* check it's source port 35602 to port 33450 */
496  if (p->icmpv4vars.emb_sport != 35602 ||
497  p->icmpv4vars.emb_dport != 33450) {
498  printf("p->icmpv4vars.emb_sport %u, p->icmpv4vars.emb_dport %u: ",
500  goto end;
501  }
502 
503  /* check the src,dst IPs contained inside */
504  char s[16], d[16];
505 
506  PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_src), s, sizeof(s));
507  PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_dst), d, sizeof(d));
508 
509  /* ICMPv4 embedding IPV4 192.168.1.13->209.85.227.147 pass */
510  if (strcmp(s, "192.168.1.13") == 0 && strcmp(d, "209.85.227.147") == 0) {
511  ret = 1;
512  }
513  else {
514  printf("s %s, d %s: ", s, d);
515  }
516 
517 end:
518  FlowShutdown();
519  SCFree(p);
520  return ret;
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;
541  DecodeThreadVars dtv;
542  int ret = 0;
543  IPV4Hdr ip4h;
544 
545  memset(&ip4h, 0, sizeof(IPV4Hdr));
546  memset(&tv, 0, sizeof(ThreadVars));
547  memset(p, 0, SIZE_OF_PACKET);
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  p->ip4h = &ip4h;
560 
561  DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
562 
563  if (NULL == p->icmpv4h) {
564  goto end;
565  }
566 
567  /* check the type,code pair is correct - type 3, code 10 */
568  if (p->icmpv4h->type != 3 || p->icmpv4h->code != 10) {
569  goto end;
570  }
571 
572  /* check it's src port 45322 to dst port 50 */
573  if (p->icmpv4vars.emb_sport != 45322 ||
574  p->icmpv4vars.emb_dport != 50) {
575  goto end;
576  }
577 
578  // check the src,dst IPs contained inside
579  char s[16], d[16];
580 
581  PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_src), s, sizeof(s));
582  PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_dst), d, sizeof(d));
583 
584  // ICMPv4 embedding IPV4 192.168.1.13->88.96.22.41
585  if (strcmp(s, "192.168.1.13") == 0 && strcmp(d, "88.96.22.41") == 0) {
586  ret = 1;
587  }
588 
589 end:
590  FlowShutdown();
591  SCFree(p);
592  return ret;
593 }
594 
595 /** DecodeICMPV4test05
596  * \brief dest. unreachable, administratively prohibited
597  * \retval 1 Expected test value
598  */
599 static int DecodeICMPV4test05(void)
600 {
601  uint8_t raw_icmpv4[] = {
602  0x0b, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x00, 0x00, 0x45,
603  0x00, 0x00, 0x30, 0x02, 0x17, 0x40, 0x00, 0x01, 0x06,
604  0xd6, 0xbd, 0xc0, 0xa8, 0x02, 0x05, 0x3d, 0x23, 0xa1,
605  0x23, 0x04, 0x18, 0x00, 0x50, 0xd2, 0x08, 0xc2, 0x48,
606  };
608  if (unlikely(p == NULL))
609  return 0;
610  ThreadVars tv;
611  DecodeThreadVars dtv;
612  int ret = 0;
613  IPV4Hdr ip4h;
614 
615  memset(&ip4h, 0, sizeof(IPV4Hdr));
616  memset(&tv, 0, sizeof(ThreadVars));
617  memset(p, 0, SIZE_OF_PACKET);
618  memset(&dtv, 0, sizeof(DecodeThreadVars));
619 
621 
622  p->src.family = AF_INET;
623  p->dst.family = AF_INET;
624  p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");;
625  p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");;
626 
627  ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
628  ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
629  p->ip4h = &ip4h;
630 
631  DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
632 
633  if (NULL == p->icmpv4h) {
634  goto end;
635  }
636 
637  /* check the type,code pair is correct - type 11, code 0 */
638  if (p->icmpv4h->type != 11 || p->icmpv4h->code != 0) {
639  goto end;
640  }
641 
642  /* check it's src port 1048 to dst port 80 */
643  if (p->icmpv4vars.emb_sport != 1048 ||
644  p->icmpv4vars.emb_dport != 80) {
645  goto end;
646  }
647 
648  // check the src,dst IPs contained inside
649  char s[16], d[16];
650 
651  PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_src), s, sizeof(s));
652  PrintInet(AF_INET, &(p->icmpv4vars.emb_ip4_dst), d, sizeof(d));
653 
654  // ICMPv4 embedding IPV4 192.168.2.5->61.35.161.35
655  if (strcmp(s, "192.168.2.5") == 0 && strcmp(d, "61.35.161.35") == 0) {
656  ret = 1;
657  }
658 
659 end:
660  FlowShutdown();
661  SCFree(p);
662  return ret;
663 }
664 
665 static int ICMPV4CalculateValidChecksumtest05(void)
666 {
667  uint16_t csum = 0;
668 
669  uint8_t raw_icmpv4[] = {
670  0x08, 0x00, 0xab, 0x9b, 0x7f, 0x2b, 0x05, 0x2c,
671  0x3f, 0x72, 0x93, 0x4a, 0x00, 0x4d, 0x0a, 0x00,
672  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
673  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
674  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
675  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
676  0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
677  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37};
678 
679  csum = *( ((uint16_t *)raw_icmpv4) + 1);
680  return (csum == ICMPV4CalculateChecksum((uint16_t *)raw_icmpv4, sizeof(raw_icmpv4)));
681 }
682 
683 static int ICMPV4CalculateInvalidChecksumtest06(void)
684 {
685  uint16_t csum = 0;
686 
687  uint8_t raw_icmpv4[] = {
688  0x08, 0x00, 0xab, 0x9b, 0x7f, 0x2b, 0x05, 0x2c,
689  0x3f, 0x72, 0x93, 0x4a, 0x00, 0x4d, 0x0a, 0x00,
690  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
691  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
692  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
693  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
694  0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
695  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38};
696 
697  csum = *( ((uint16_t *)raw_icmpv4) + 1);
698  return (csum != ICMPV4CalculateChecksum((uint16_t *)raw_icmpv4, sizeof(raw_icmpv4)));
699 }
700 
701 static int ICMPV4InvalidType07(void)
702 {
703 
704  uint8_t raw_icmpv4[] = {
705  0xff, 0x00, 0xab, 0x9b, 0x7f, 0x2b, 0x05, 0x2c,
706  0x3f, 0x72, 0x93, 0x4a, 0x00, 0x4d, 0x0a, 0x00,
707  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
708  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
709  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
710  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
711  0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
712  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38};
713 
715  if (unlikely(p == NULL))
716  return 0;
717  ThreadVars tv;
718  DecodeThreadVars dtv;
719  int ret = 0;
720  IPV4Hdr ip4h;
721 
722  memset(&ip4h, 0, sizeof(IPV4Hdr));
723  memset(&tv, 0, sizeof(ThreadVars));
724  memset(p, 0, SIZE_OF_PACKET);
725  memset(&dtv, 0, sizeof(DecodeThreadVars));
726 
728 
729  p->src.family = AF_INET;
730  p->dst.family = AF_INET;
731  p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");;
732  p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");;
733 
734  ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
735  ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
736  p->ip4h = &ip4h;
737 
738  DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
739 
741  ret = 1;
742  }
743 
744  FlowShutdown();
745  SCFree(p);
746  return ret;
747 }
748 
749 /** DecodeICMPV4test08
750  * \brief
751  * \retval 1 Expected test value - what we really want is not to segfault
752  */
753 static int DecodeICMPV4test08(void)
754 {
755  uint8_t raw_icmpv4[] = {
756  0x08, 0x00, 0x78, 0x47, 0xfc, 0x55, 0x00, 0x00
757  };
759  if (unlikely(p == NULL))
760  return 0;
761  ThreadVars tv;
762  DecodeThreadVars dtv;
763  int ret = 0;
764  IPV4Hdr ip4h;
765 
766  memset(&ip4h, 0, sizeof(IPV4Hdr));
767  memset(&tv, 0, sizeof(ThreadVars));
768  memset(p, 0, SIZE_OF_PACKET);
769  memset(&dtv, 0, sizeof(DecodeThreadVars));
770 
772 
773  p->src.family = AF_INET;
774  p->dst.family = AF_INET;
775  p->src.addr_data32[0] = UTHSetIPv4Address("4.3.2.1");;
776  p->dst.addr_data32[0] = UTHSetIPv4Address("1.2.3.4");;
777 
778  ip4h.s_ip_src.s_addr = p->src.addr_data32[0];
779  ip4h.s_ip_dst.s_addr = p->dst.addr_data32[0];
780  p->ip4h = &ip4h;
781 
782  DecodeICMPV4(&tv, &dtv, p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
783 
784  if (NULL!=p->icmpv4h) {
785  if (p->icmpv4h->type==8 && p->icmpv4h->code==0) {
786  ret = 1;
787  }
788  }
789 
790  FlowShutdown();
791  SCFree(p);
792  return ret;
793 }
794 #endif /* UNITTESTS */
795 
796 /**
797  * \brief Registers ICMPV4 unit test
798  */
800 {
801 #ifdef UNITTESTS
802  UtRegisterTest("DecodeICMPV4test01", DecodeICMPV4test01);
803  UtRegisterTest("DecodeICMPV4test02", DecodeICMPV4test02);
804  UtRegisterTest("DecodeICMPV4test03", DecodeICMPV4test03);
805  UtRegisterTest("DecodeICMPV4test04", DecodeICMPV4test04);
806  UtRegisterTest("DecodeICMPV4test05", DecodeICMPV4test05);
807  UtRegisterTest("ICMPV4CalculateValidChecksumtest05",
808  ICMPV4CalculateValidChecksumtest05);
809  UtRegisterTest("ICMPV4CalculateInvalidChecksumtest06",
810  ICMPV4CalculateInvalidChecksumtest06);
811  UtRegisterTest("DecodeICMPV4InvalidType", ICMPV4InvalidType07);
812  UtRegisterTest("DecodeICMPV4test08", DecodeICMPV4test08);
813 #endif /* UNITTESTS */
814 }
815 /**
816  * @}
817  */
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:288
#define ENGINE_SET_EVENT(p, e)
Definition: decode.h:991
#define SCLogDebug(...)
Definition: util-debug.h:335
#define ICMPV4_HEADER_PKT_OFFSET
#define ENGINE_ISSET_EVENT(p, e)
Definition: decode.h:1006
uint16_t emb_sport
#define unlikely(expr)
Definition: util-optimize.h:35
struct in_addr emb_ip4_dst
uint32_t UTHSetIPv4Address(const char *str)
return the uint32_t for a ipv4 address string
ICMPV4Hdr * icmpv4h
Definition: decode.h:526
TCPHdr * emb_tcph
#define FLOW_QUIET
Definition: flow.h:38
Address dst
Definition: decode.h:411
uint8_t emb_ip4_hlen
#define TCP_HEADER_LEN
Definition: decode-tcp.h:28
#define IPV4_GET_RAW_VER(ip4h)
Definition: decode-ipv4.h:94
int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
Main ICMPv4 decoding function.
#define SIZE_OF_PACKET
Definition: decode.h:618
ICMPV4Hdr * emb_icmpv4h
char family
Definition: decode.h:109
uint8_t proto
Definition: decode.h:428
uint8_t type
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Structure to hold thread specific data for all decode modules.
Definition: decode.h:632
#define IPV4_GET_RAW_IPID(ip4h)
Definition: decode-ipv4.h:98
uint16_t counter_icmpv4
Definition: decode.h:652
#define IPV4_GET_RAW_IPPROTO(ip4h)
Definition: decode-ipv4.h:101
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:163
struct Packet_::@43::@51 icmp_d
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition: util-print.c:267
struct in_addr emb_ip4_src
#define ICMPV4_HEADER_LEN
Definition: decode-icmpv4.h:32
IPV4Hdr * ip4h
Definition: decode.h:498
uint8_t emb_ip4_proto
int ICMPv4GetCounterpart(uint8_t type)
#define IPV4_GET_RAW_HLEN(ip4h)
Definition: decode-ipv4.h:95
#define SCMalloc(a)
Definition: util-mem.h:166
#define CASE_CODE(t, r)
struct Packet_::@41::@50 icmp_s
#define SCFree(a)
Definition: util-mem.h:228
#define SCNtohs(x)
#define IPV4_GET_RAW_IPDST(ip4h)
Definition: decode-ipv4.h:103
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:667
uint16_t emb_dport
uint16_t id
uint8_t len
Per thread variable structure.
Definition: threadvars.h:57
uint16_t payload_len
Definition: decode.h:541
uint16_t seq
IPV4Hdr * emb_ipv4h
#define IPV4_GET_RAW_IPSRC(ip4h)
Definition: decode-ipv4.h:102
#define IPV4_HEADER_LEN
Definition: decode-ipv4.h:28
uint8_t * payload
Definition: decode.h:540
void DecodeICMPV4RegisterTests(void)
Registers ICMPV4 unit test.
ICMPV4Vars icmpv4vars
Definition: decode.h:513
UDPHdr * emb_udph
#define UDP_HEADER_LEN
Definition: decode-udp.h:27
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:999
Address src
Definition: decode.h:410
void FlowInitConfig(char quiet)
initialize the configuration
Definition: flow.c:512