Coverage Report

Created: 2026-08-14 07:34

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