Coverage Report

Created: 2026-09-06 07:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata8/src/decode-icmpv6.c
Line
Count
Source
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 ICMPv6
31
 */
32
33
#include "suricata-common.h"
34
#include "decode-icmpv6.h"
35
#include "decode.h"
36
#include "flow.h"
37
#include "util-print.h"
38
#include "util-validate.h"
39
40
#if defined(DEBUG) || defined(UNITTESTS)
41
static inline const IPV6Hdr *PacketGetICMPv6EmbIPv6(const Packet *p)
42
{
43
    BUG_ON(p->l4.type != PACKET_L4_ICMPV6);
44
    const uint8_t *start = (const uint8_t *)PacketGetICMPv6(p);
45
    const uint8_t *ip = start + p->l4.vars.icmpv6.emb_ip6h_offset;
46
    return (const IPV6Hdr *)ip;
47
}
48
#endif
49
50
/**
51
 * \brief Get variables and do some checks of the embedded IPV6 packet
52
 *
53
 * \param p Pointer to the packet we are filling
54
 * \param partial_packet  Pointer to the raw packet buffer
55
 * \param len the len of the rest of the packet not processed yet
56
 *
57
 * \retval void No return value
58
 */
59
static void DecodePartialIPV6(Packet *p, uint8_t *partial_packet, uint16_t len )
60
26.0k
{
61
    /** Check the sizes, the header must fit at least */
62
26.0k
    if (len < IPV6_HEADER_LEN) {
63
15.2k
        SCLogDebug("ICMPV6_IPV6_TRUNC_PKT");
64
15.2k
        ENGINE_SET_INVALID_EVENT(p, ICMPV6_IPV6_TRUNC_PKT);
65
15.2k
        return;
66
15.2k
    }
67
68
10.8k
    IPV6Hdr *icmp6_ip6h = (IPV6Hdr*)partial_packet;
69
70
    /** Check the embedded version */
71
10.8k
    if(((icmp6_ip6h->s_ip6_vfc & 0xf0) >> 4) != 6)
72
1.26k
    {
73
1.26k
        SCLogDebug("ICMPv6 contains Unknown IPV6 version "
74
1.26k
                "ICMPV6_IPV6_UNKNOWN_VER");
75
1.26k
        ENGINE_SET_INVALID_EVENT(p, ICMPV6_IPV6_UNKNOWN_VER);
76
1.26k
        return;
77
1.26k
    }
78
79
    /** We need to fill l4.vars.icmpv6 */
80
9.60k
    const uint8_t *icmpv6_ptr = (const uint8_t *)p->l4.hdrs.icmpv6h;
81
9.60k
    DEBUG_VALIDATE_BUG_ON((ptrdiff_t)(partial_packet - icmpv6_ptr) > (ptrdiff_t)UINT16_MAX);
82
9.60k
    p->l4.vars.icmpv6.emb_ip6h_offset = (uint16_t)(partial_packet - icmpv6_ptr);
83
    /** Get protocol and ports inside the embedded ipv6 packet and set the pointers */
84
9.60k
    p->l4.vars.icmpv6.emb_ip6_proto_next = icmp6_ip6h->s_ip6_nxt;
85
86
9.60k
    switch (icmp6_ip6h->s_ip6_nxt) {
87
4.08k
        case IPPROTO_TCP:
88
4.08k
            if (len >= IPV6_HEADER_LEN + TCP_HEADER_LEN ) {
89
3.97k
                TCPHdr *emb_tcph = (TCPHdr *)(partial_packet + IPV6_HEADER_LEN);
90
3.97k
                p->l4.vars.icmpv6.emb_sport = emb_tcph->th_sport;
91
3.97k
                p->l4.vars.icmpv6.emb_dport = emb_tcph->th_dport;
92
3.97k
                p->l4.vars.icmpv6.emb_ports_set = true;
93
94
3.97k
                SCLogDebug("ICMPV6->IPV6->TCP header sport: "
95
3.97k
                           "%" PRIu16 " dport %" PRIu16 "",
96
3.97k
                        p->l4.vars.icmpv6.emb_sport, p->l4.vars.icmpv6.emb_dport);
97
3.97k
            } else {
98
104
                SCLogDebug("Warning, ICMPV6->IPV6->TCP "
99
104
                           "header Didn't fit in the packet!");
100
104
                p->l4.vars.icmpv6.emb_sport = 0;
101
104
                p->l4.vars.icmpv6.emb_dport = 0;
102
104
            }
103
104
4.08k
            break;
105
1.73k
        case IPPROTO_UDP:
106
1.73k
            if (len >= IPV6_HEADER_LEN + UDP_HEADER_LEN ) {
107
1.65k
                UDPHdr *emb_udph = (UDPHdr *)(partial_packet + IPV6_HEADER_LEN);
108
1.65k
                p->l4.vars.icmpv6.emb_sport = emb_udph->uh_sport;
109
1.65k
                p->l4.vars.icmpv6.emb_dport = emb_udph->uh_dport;
110
1.65k
                p->l4.vars.icmpv6.emb_ports_set = true;
111
112
1.65k
                SCLogDebug("ICMPV6->IPV6->UDP header sport: "
113
1.65k
                           "%" PRIu16 " dport %" PRIu16 "",
114
1.65k
                        p->l4.vars.icmpv6.emb_sport, p->l4.vars.icmpv6.emb_dport);
115
1.65k
            } else {
116
79
                SCLogDebug("Warning, ICMPV6->IPV6->UDP "
117
79
                           "header Didn't fit in the packet!");
118
79
                p->l4.vars.icmpv6.emb_sport = 0;
119
79
                p->l4.vars.icmpv6.emb_dport = 0;
120
79
            }
121
122
1.73k
            break;
123
238
        case IPPROTO_ICMPV6:
124
238
            p->l4.vars.icmpv6.emb_sport = 0;
125
238
            p->l4.vars.icmpv6.emb_dport = 0;
126
127
238
            SCLogDebug("ICMPV6->IPV6->ICMP header");
128
129
238
            break;
130
9.60k
    }
131
132
    /* debug print */
133
#ifdef DEBUG
134
    char s[46], d[46];
135
    PrintInet(AF_INET6, (const void *)PacketGetICMPv6EmbIPv6(p)->s_ip6_src, s, sizeof(s));
136
    PrintInet(AF_INET6, (const void *)PacketGetICMPv6EmbIPv6(p)->s_ip6_dst, d, sizeof(d));
137
    SCLogDebug("ICMPv6 embedding IPV6 %s->%s - CLASS: %" PRIu32 " FLOW: "
138
               "%" PRIu32 " NH: %" PRIu32 " PLEN: %" PRIu32 " HLIM: %" PRIu32,
139
               s, d, IPV6_GET_RAW_CLASS(icmp6_ip6h), IPV6_GET_RAW_FLOW(icmp6_ip6h),
140
               IPV6_GET_RAW_NH(icmp6_ip6h), IPV6_GET_RAW_PLEN(icmp6_ip6h), IPV6_GET_RAW_HLIM(icmp6_ip6h));
141
#endif
142
9.60k
}
143
144
/** \retval type counterpart type or -1 */
145
int ICMPv6GetCounterpart(uint8_t type)
146
331k
{
147
331k
#define CASE_CODE(t,r) case (t): return r; case (r): return t;
148
331k
    switch (type) {
149
66.3k
        CASE_CODE(ICMP6_ECHO_REQUEST,   ICMP6_ECHO_REPLY);
150
12.3k
        CASE_CODE(ND_NEIGHBOR_SOLICIT,  ND_NEIGHBOR_ADVERT);
151
22.1k
        CASE_CODE(ND_ROUTER_SOLICIT,    ND_ROUTER_ADVERT);
152
737
        CASE_CODE(MLD_LISTENER_QUERY,   MLD_LISTENER_REPORT);
153
982
        CASE_CODE(ICMP6_NI_QUERY,       ICMP6_NI_REPLY);
154
1.38k
        CASE_CODE(HOME_AGENT_AD_REQUEST,HOME_AGENT_AD_REPLY);
155
156
709
        CASE_CODE(MOBILE_PREFIX_SOLICIT,MOBILE_PREFIX_ADVERT);
157
2.12k
        CASE_CODE(CERT_PATH_SOLICIT,    CERT_PATH_ADVERT);
158
521
        CASE_CODE(MC_ROUTER_ADVERT,     MC_ROUTER_SOLICIT);
159
2.15k
        CASE_CODE(DUPL_ADDR_REQUEST,    DUPL_ADDR_CONFIRM);
160
188k
        default:
161
188k
            return -1;
162
331k
    }
163
331k
#undef CASE_CODE
164
331k
}
165
166
/**
167
 * \brief Decode ICMPV6 packets and fill the Packet with the decoded info
168
 *
169
 * \param tv Pointer to the thread variables
170
 * \param dtv Pointer to the decode thread variables
171
 * \param p Pointer to the packet we are filling
172
 * \param pkt Pointer to the raw packet buffer
173
 * \param len the len of the rest of the packet not processed yet
174
 *
175
 * \retval void No return value
176
 */
177
int DecodeICMPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
178
                 const uint8_t *pkt, uint32_t len)
179
315k
{
180
315k
    const IPV6Hdr *ip6h = PacketGetIPv6(p);
181
315k
    int full_hdr = 0;
182
315k
    StatsIncr(tv, dtv->counter_icmpv6);
183
184
315k
    if (len < ICMPV6_HEADER_LEN) {
185
1.23k
        SCLogDebug("ICMPV6_PKT_TOO_SMALL");
186
1.23k
        ENGINE_SET_INVALID_EVENT(p, ICMPV6_PKT_TOO_SMALL);
187
1.23k
        return TM_ECODE_FAILED;
188
1.23k
    }
189
190
314k
    ICMPV6Hdr *icmpv6h = PacketSetICMPv6(p, pkt);
191
314k
    p->proto = IPPROTO_ICMPV6;
192
314k
    const uint8_t type = p->icmp_s.type = icmpv6h->type;
193
314k
    const uint8_t code = p->icmp_s.code = icmpv6h->code;
194
314k
    DEBUG_VALIDATE_BUG_ON(len - ICMPV6_HEADER_LEN > UINT16_MAX);
195
314k
    p->payload_len = (uint16_t)(len - ICMPV6_HEADER_LEN);
196
314k
    p->payload = (uint8_t *)pkt + ICMPV6_HEADER_LEN;
197
198
314k
    int ctype = ICMPv6GetCounterpart(p->icmp_s.type);
199
314k
    if (ctype != -1) {
200
136k
        p->icmp_d.type = (uint8_t)ctype;
201
136k
    }
202
203
314k
    SCLogDebug("ICMPV6 TYPE %u CODE %u", type, code);
204
205
314k
    switch (type) {
206
16.1k
        case ICMP6_DST_UNREACH:
207
16.1k
            SCLogDebug("ICMP6_DST_UNREACH");
208
209
16.1k
            if (code > ICMP6_DST_UNREACH_REJECTROUTE) {
210
4.00k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
211
12.1k
            } else {
212
12.1k
                if (unlikely(len > ICMPV6_HEADER_LEN + USHRT_MAX)) {
213
0
                    return TM_ECODE_FAILED;
214
0
                }
215
12.1k
                DecodePartialIPV6(p, (uint8_t *)(pkt + ICMPV6_HEADER_LEN),
216
12.1k
                        (uint16_t)(len - ICMPV6_HEADER_LEN));
217
12.1k
                full_hdr = 1;
218
12.1k
            }
219
220
16.1k
            break;
221
16.1k
        case ICMP6_PACKET_TOO_BIG:
222
12.3k
            SCLogDebug("ICMP6_PACKET_TOO_BIG");
223
224
12.3k
            if (code != 0) {
225
3.49k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
226
8.88k
            } else {
227
8.88k
                if (unlikely(len > ICMPV6_HEADER_LEN + USHRT_MAX)) {
228
0
                    return TM_ECODE_FAILED;
229
0
                }
230
8.88k
                p->l4.vars.icmpv6.mtu = ICMPV6_GET_MTU(icmpv6h);
231
8.88k
                DecodePartialIPV6(p, (uint8_t *)(pkt + ICMPV6_HEADER_LEN),
232
8.88k
                        (uint16_t)(len - ICMPV6_HEADER_LEN));
233
8.88k
                full_hdr = 1;
234
8.88k
            }
235
236
12.3k
            break;
237
12.3k
        case ICMP6_TIME_EXCEEDED:
238
1.31k
            SCLogDebug("ICMP6_TIME_EXCEEDED");
239
240
1.31k
            if (code > ICMP6_TIME_EXCEED_REASSEMBLY) {
241
749
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
242
749
            } else {
243
567
                if (unlikely(len > ICMPV6_HEADER_LEN + USHRT_MAX)) {
244
0
                    return TM_ECODE_FAILED;
245
0
                }
246
567
                DecodePartialIPV6(p, (uint8_t *)(pkt + ICMPV6_HEADER_LEN),
247
567
                        (uint16_t)(len - ICMPV6_HEADER_LEN));
248
567
                full_hdr = 1;
249
567
            }
250
251
1.31k
            break;
252
5.90k
        case ICMP6_PARAM_PROB:
253
5.90k
            SCLogDebug("ICMP6_PARAM_PROB");
254
255
5.90k
            if (code > ICMP6_PARAMPROB_OPTION) {
256
1.40k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
257
4.49k
            } else {
258
4.49k
                if (unlikely(len > ICMPV6_HEADER_LEN + USHRT_MAX)) {
259
0
                    return TM_ECODE_FAILED;
260
0
                }
261
4.49k
                DecodePartialIPV6(p, (uint8_t *)(pkt + ICMPV6_HEADER_LEN),
262
4.49k
                        (uint16_t)(len - ICMPV6_HEADER_LEN));
263
4.49k
                full_hdr = 1;
264
4.49k
            }
265
266
5.90k
            break;
267
65.5k
        case ICMP6_ECHO_REQUEST:
268
65.5k
            SCLogDebug("ICMP6_ECHO_REQUEST id: %u seq: %u", icmpv6h->icmpv6b.icmpv6i.id,
269
65.5k
                    icmpv6h->icmpv6b.icmpv6i.seq);
270
271
65.5k
            if (code != 0) {
272
2.63k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
273
62.9k
            } else {
274
62.9k
                p->l4.vars.icmpv6.id = icmpv6h->icmpv6b.icmpv6i.id;
275
62.9k
                p->l4.vars.icmpv6.seq = icmpv6h->icmpv6b.icmpv6i.seq;
276
62.9k
                full_hdr = 1;
277
62.9k
            }
278
279
65.5k
            break;
280
10.4k
        case ICMP6_ECHO_REPLY:
281
10.4k
            SCLogDebug("ICMP6_ECHO_REPLY id: %u seq: %u", icmpv6h->icmpv6b.icmpv6i.id,
282
10.4k
                    icmpv6h->icmpv6b.icmpv6i.seq);
283
284
10.4k
            if (code != 0) {
285
1.03k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
286
9.45k
            } else {
287
9.45k
                p->l4.vars.icmpv6.id = icmpv6h->icmpv6b.icmpv6i.id;
288
9.45k
                p->l4.vars.icmpv6.seq = icmpv6h->icmpv6b.icmpv6i.seq;
289
9.45k
                full_hdr = 1;
290
9.45k
            }
291
292
10.4k
            break;
293
20.2k
        case ND_ROUTER_SOLICIT:
294
20.2k
            SCLogDebug("ND_ROUTER_SOLICIT");
295
20.2k
            if (code != 0) {
296
913
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
297
913
            }
298
20.2k
            break;
299
3.56k
        case ND_ROUTER_ADVERT:
300
3.56k
            SCLogDebug("ND_ROUTER_ADVERT");
301
3.56k
            if (code != 0) {
302
571
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
303
571
            }
304
3.56k
            break;
305
10.9k
        case ND_NEIGHBOR_SOLICIT:
306
10.9k
            SCLogDebug("ND_NEIGHBOR_SOLICIT");
307
10.9k
            if (code != 0) {
308
868
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
309
868
            }
310
10.9k
            break;
311
7.18k
        case ND_NEIGHBOR_ADVERT:
312
7.18k
            SCLogDebug("ND_NEIGHBOR_ADVERT");
313
7.18k
            if (code != 0) {
314
260
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
315
260
            }
316
7.18k
            break;
317
975
        case ND_REDIRECT:
318
975
            SCLogDebug("ND_REDIRECT");
319
975
            if (code != 0) {
320
700
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
321
700
            }
322
975
            break;
323
695
        case MLD_LISTENER_QUERY:
324
695
            SCLogDebug("MLD_LISTENER_QUERY");
325
695
            if (code != 0) {
326
428
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
327
428
            }
328
695
            if (IPV6_GET_RAW_HLIM(ip6h) != 1) {
329
478
                ENGINE_SET_EVENT(p, ICMPV6_MLD_MESSAGE_WITH_INVALID_HL);
330
478
            }
331
695
            break;
332
3.27k
        case MLD_LISTENER_REPORT:
333
3.27k
            SCLogDebug("MLD_LISTENER_REPORT");
334
3.27k
            if (code != 0) {
335
2.41k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
336
2.41k
            }
337
3.27k
            if (IPV6_GET_RAW_HLIM(ip6h) != 1) {
338
2.40k
                ENGINE_SET_EVENT(p, ICMPV6_MLD_MESSAGE_WITH_INVALID_HL);
339
2.40k
            }
340
3.27k
            break;
341
2.24k
        case MLD_LISTENER_REDUCTION:
342
2.24k
            SCLogDebug("MLD_LISTENER_REDUCTION");
343
2.24k
            if (code != 0) {
344
1.70k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
345
1.70k
            }
346
2.24k
            if (IPV6_GET_RAW_HLIM(ip6h) != 1) {
347
1.06k
                ENGINE_SET_EVENT(p, ICMPV6_MLD_MESSAGE_WITH_INVALID_HL);
348
1.06k
            }
349
2.24k
            break;
350
3.18k
        case ICMP6_RR:
351
3.18k
            SCLogDebug("ICMP6_RR");
352
3.18k
            if (code > 2 && code != 255) {
353
1.15k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
354
1.15k
            }
355
3.18k
            break;
356
897
        case ICMP6_NI_QUERY:
357
897
            SCLogDebug("ICMP6_NI_QUERY");
358
897
            if (code > 2) {
359
585
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
360
585
            }
361
897
            break;
362
2.15k
        case ICMP6_NI_REPLY:
363
2.15k
            SCLogDebug("ICMP6_NI_REPLY");
364
2.15k
            if (code > 2) {
365
1.64k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
366
1.64k
            }
367
2.15k
            break;
368
659
        case ND_INVERSE_SOLICIT:
369
659
            SCLogDebug("ND_INVERSE_SOLICIT");
370
659
            if (code != 0) {
371
395
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
372
395
            }
373
659
            break;
374
942
        case ND_INVERSE_ADVERT:
375
942
            SCLogDebug("ND_INVERSE_ADVERT");
376
942
            if (code != 0) {
377
554
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
378
554
            }
379
942
            break;
380
40.8k
        case MLD_V2_LIST_REPORT:
381
40.8k
            SCLogDebug("MLD_V2_LIST_REPORT");
382
40.8k
            if (code != 0) {
383
1.38k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
384
1.38k
            }
385
40.8k
            break;
386
1.32k
        case HOME_AGENT_AD_REQUEST:
387
1.32k
            SCLogDebug("HOME_AGENT_AD_REQUEST");
388
1.32k
            if (code != 0) {
389
912
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
390
912
            }
391
1.32k
            break;
392
960
        case HOME_AGENT_AD_REPLY:
393
960
            SCLogDebug("HOME_AGENT_AD_REPLY");
394
960
            if (code != 0) {
395
635
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
396
635
            }
397
960
            break;
398
680
        case MOBILE_PREFIX_SOLICIT:
399
680
            SCLogDebug("MOBILE_PREFIX_SOLICIT");
400
680
            if (code != 0) {
401
584
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
402
584
            }
403
680
            break;
404
651
        case MOBILE_PREFIX_ADVERT:
405
651
            SCLogDebug("MOBILE_PREFIX_ADVERT");
406
651
            if (code != 0) {
407
365
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
408
365
            }
409
651
            break;
410
2.02k
        case CERT_PATH_SOLICIT:
411
2.02k
            SCLogDebug("CERT_PATH_SOLICIT");
412
2.02k
            if (code != 0) {
413
1.78k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
414
1.78k
            }
415
2.02k
            break;
416
662
        case CERT_PATH_ADVERT:
417
662
            SCLogDebug("CERT_PATH_ADVERT");
418
662
            if (code != 0) {
419
375
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
420
375
            }
421
662
            break;
422
6.47k
        case ICMP6_MOBILE_EXPERIMENTAL:
423
6.47k
            SCLogDebug("ICMP6_MOBILE_EXPERIMENTAL");
424
6.47k
            break;
425
470
        case MC_ROUTER_ADVERT:
426
470
            SCLogDebug("MC_ROUTER_ADVERT");
427
470
            break;
428
509
        case MC_ROUTER_SOLICIT:
429
509
            SCLogDebug("MC_ROUTER_SOLICIT");
430
509
            break;
431
1.29k
        case MC_ROUTER_TERMINATE:
432
1.29k
            SCLogDebug("MC_ROUTER_TERMINATE");
433
1.29k
            break;
434
1.36k
        case FMIPV6_MSG:
435
1.36k
            SCLogDebug("FMIPV6_MSG");
436
1.36k
            if (code != 0) {
437
1.04k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
438
1.04k
            }
439
1.36k
            break;
440
15.2k
        case RPL_CONTROL_MSG:
441
15.2k
            SCLogDebug("RPL_CONTROL_MSG");
442
15.2k
            if (code > 3 && code < 128) {
443
808
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
444
808
            }
445
15.2k
            if (code > 132) {
446
493
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
447
493
            }
448
15.2k
            break;
449
482
        case LOCATOR_UDATE_MSG:
450
482
            SCLogDebug("LOCATOR_UDATE_MSG");
451
482
            if (code != 0) {
452
367
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
453
367
            }
454
482
            break;
455
2.02k
        case DUPL_ADDR_REQUEST:
456
2.02k
            SCLogDebug("DUPL_ADDR_REQUEST");
457
2.02k
            if (code != 0) {
458
1.63k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
459
1.63k
            }
460
2.02k
            break;
461
1.88k
        case DUPL_ADDR_CONFIRM:
462
1.88k
            SCLogDebug("DUPL_ADDR_CONFIRM");
463
1.88k
            if (code != 0) {
464
1.13k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
465
1.13k
            }
466
1.88k
            break;
467
720
        case MPL_CONTROL_MSG:
468
720
            SCLogDebug("MPL_CONTROL_MSG");
469
720
            if (code != 0) {
470
416
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
471
416
            }
472
720
            break;
473
68.2k
        default:
474
            /* Various range taken from:
475
             *   http://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml#icmpv6-parameters-2
476
             */
477
68.2k
            if (type > 4 && type < 100) {
478
7.51k
                ENGINE_SET_EVENT(p, ICMPV6_UNASSIGNED_TYPE);
479
60.6k
            } else if (type >= 100 && type < 102) {
480
1.66k
                ENGINE_SET_EVENT(p, ICMPV6_EXPERIMENTATION_TYPE);
481
59.0k
            } else if (type >= 102 && type < 127) {
482
3.76k
                ENGINE_SET_EVENT(p, ICMPV6_UNASSIGNED_TYPE);
483
55.2k
            } else if (type >= 160 && type < 200) {
484
1.58k
                ENGINE_SET_EVENT(p, ICMPV6_UNASSIGNED_TYPE);
485
53.6k
            } else if (type >= 200 && type < 202) {
486
839
                ENGINE_SET_EVENT(p, ICMPV6_EXPERIMENTATION_TYPE);
487
52.8k
            } else if (type >= 202) {
488
5.00k
                ENGINE_SET_EVENT(p, ICMPV6_UNASSIGNED_TYPE);
489
47.8k
            } else {
490
47.8k
                SCLogDebug("ICMPV6 Message type %u not "
491
47.8k
                           "implemented yet",
492
47.8k
                        type);
493
47.8k
                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_TYPE);
494
47.8k
            }
495
314k
    }
496
497
    /* for a info message the header is just 4 bytes */
498
314k
    if (!full_hdr) {
499
216k
        if (p->payload_len >= 4) {
500
194k
            p->payload_len -= 4;
501
194k
            p->payload = (uint8_t *)pkt + 4;
502
194k
        } else {
503
21.6k
            p->payload_len = 0;
504
21.6k
            p->payload = NULL;
505
21.6k
        }
506
216k
    }
507
508
#ifdef DEBUG
509
    if (ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_CODE))
510
        SCLogDebug("Unknown Code, ICMPV6_UNKNOWN_CODE");
511
512
    if (ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_TYPE))
513
        SCLogDebug("Unknown Type, ICMPV6_UNKNOWN_TYPE");
514
#endif
515
516
314k
    FlowSetupPacket(p);
517
518
314k
    return TM_ECODE_OK;
519
314k
}
520
521
#ifdef UNITTESTS
522
#include "packet.h"
523
#include "util-unittest-helper.h"
524
525
static int ICMPV6CalculateValidChecksumtest01(void)
526
{
527
    uint16_t csum = 0;
528
529
    uint8_t raw_ipv6[] = {
530
        0x00, 0x00, 0x86, 0x05, 0x80, 0xda, 0x00, 0x60,
531
        0x97, 0x07, 0x69, 0xea, 0x86, 0xdd, 0x60, 0x00,
532
        0x00, 0x00, 0x00, 0x44, 0x3a, 0x40, 0x3f, 0xfe,
533
        0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x60,
534
        0x97, 0xff, 0xfe, 0x07, 0x69, 0xea, 0x3f, 0xfe,
535
        0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
536
        0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x03, 0x00,
537
        0xf7, 0x52, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00,
538
        0x00, 0x00, 0x00, 0x14, 0x11, 0x01, 0x3f, 0xfe,
539
        0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
540
        0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe,
541
        0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0,
542
        0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75,
543
        0x82, 0x9b, 0x00, 0x14, 0x82, 0x8b, 0x01, 0x01,
544
        0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0xf5, 0xed,
545
        0x08, 0x00};
546
547
    csum = *( ((uint16_t *)(raw_ipv6 + 56)));
548
549
    FAIL_IF(csum != ICMPV6CalculateChecksum((uint16_t *)(raw_ipv6 + 14 + 8),
550
                                            (uint16_t *)(raw_ipv6 + 54), 68));
551
    PASS;
552
}
553
554
static int ICMPV6CalculateInvalidChecksumtest02(void)
555
{
556
    uint16_t csum = 0;
557
558
    uint8_t raw_ipv6[] = {
559
        0x00, 0x00, 0x86, 0x05, 0x80, 0xda, 0x00, 0x60,
560
        0x97, 0x07, 0x69, 0xea, 0x86, 0xdd, 0x60, 0x00,
561
        0x00, 0x00, 0x00, 0x44, 0x3a, 0x40, 0x3f, 0xfe,
562
        0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x60,
563
        0x97, 0xff, 0xfe, 0x07, 0x69, 0xea, 0x3f, 0xfe,
564
        0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
565
        0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x03, 0x00,
566
        0xf7, 0x52, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00,
567
        0x00, 0x00, 0x00, 0x14, 0x11, 0x01, 0x3f, 0xfe,
568
        0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
569
        0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe,
570
        0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0,
571
        0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75,
572
        0x82, 0x9b, 0x00, 0x14, 0x82, 0x8b, 0x01, 0x01,
573
        0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0xf5, 0xed,
574
        0x08, 0x01};
575
576
    csum = *( ((uint16_t *)(raw_ipv6 + 56)));
577
578
    FAIL_IF(csum == ICMPV6CalculateChecksum((uint16_t *)(raw_ipv6 + 14 + 8),
579
                                            (uint16_t *)(raw_ipv6 + 54), 68));
580
    PASS;
581
}
582
583
/** \test icmpv6 message type: parameter problem, valid packet
584
 *
585
 * \retval retval 0 = Error ; 1 = ok
586
 */
587
static int ICMPV6ParamProbTest01(void)
588
{
589
    static uint8_t raw_ipv6[] = {
590
        0x60, 0x00, 0x00, 0x00, 0x00, 0x38, 0x3a, 0xff,
591
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
595
        0x04, 0x00, 0xcc, 0x2a, 0x6d, 0x93, 0x0b, 0xdf,
596
        0x69, 0x70, 0x12, 0xb7, 0x00, 0x08, 0x3a, 0xff,
597
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
601
        0x80, 0x00, 0x08, 0xb5, 0x99, 0xc3, 0xde, 0x40 };
602
603
    Packet *p = PacketGetFromAlloc();
604
    FAIL_IF_NULL(p);
605
    IPV6Hdr ip6h;
606
    ThreadVars tv;
607
    DecodeThreadVars dtv;
608
    uint32_t *ipv6src;
609
    uint32_t *ipv6dst;
610
    ipv6src = (uint32_t*) &raw_ipv6[8];
611
    ipv6dst = (uint32_t*) &raw_ipv6[24];
612
613
    memset(&tv, 0, sizeof(ThreadVars));
614
    memset(&dtv, 0, sizeof(DecodeThreadVars));
615
    memset(&ip6h, 0, sizeof(IPV6Hdr));
616
617
    FlowInitConfig(FLOW_QUIET);
618
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
619
    FAIL_IF(!PacketIsICMPv6(p));
620
621
    /* ICMPv6 not processed at all? */
622
    FAIL_IF(ICMPV6_GET_TYPE(PacketGetICMPv6(p)) != 4);
623
    FAIL_IF(ICMPV6_GET_CODE(PacketGetICMPv6(p)) != 0);
624
    FAIL_IF(ICMPV6_GET_EMB_PROTO(p) != IPPROTO_ICMPV6);
625
626
    /* Let's check if we retrieved the embedded ipv6 addresses correctly */
627
    for (int i = 0; i < 4; i++) {
628
        FAIL_IF(PacketGetICMPv6EmbIPv6(p)->s_ip6_src[i] != ipv6src[i] ||
629
                PacketGetICMPv6EmbIPv6(p)->s_ip6_dst[i] != ipv6dst[i]);
630
    }
631
632
    PacketRecycle(p);
633
    FlowShutdown();
634
    SCFree(p);
635
    PASS;
636
}
637
638
/** \test icmpv6 message type: packet too big, valid packet
639
 *
640
 * \retval retval 0 = Error ; 1 = ok
641
 */
642
static int ICMPV6PktTooBigTest01(void)
643
{
644
    static uint8_t raw_ipv6[] = {
645
        0x60, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3a, 0xff,
646
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
650
        0x02, 0x00, 0x5c, 0x7a, 0x00, 0x00, 0x05, 0x00,
651
        0x64, 0x14, 0xfd, 0xff, 0x00, 0x00, 0x3b, 0xff,
652
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
656
657
    Packet *p = PacketGetFromAlloc();
658
    FAIL_IF_NULL(p);
659
    IPV6Hdr ip6h;
660
    ThreadVars tv;
661
    DecodeThreadVars dtv;
662
    uint32_t *ipv6src;
663
    uint32_t *ipv6dst;
664
    ipv6src = (uint32_t*) &raw_ipv6[8];
665
    ipv6dst = (uint32_t*) &raw_ipv6[24];
666
667
    memset(&tv, 0, sizeof(ThreadVars));
668
    memset(&dtv, 0, sizeof(DecodeThreadVars));
669
    memset(&ip6h, 0, sizeof(IPV6Hdr));
670
671
    FlowInitConfig(FLOW_QUIET);
672
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
673
    FAIL_IF(!PacketIsICMPv6(p));
674
675
    /* Note: it has an embedded ipv6 packet but no protocol after ipv6
676
     * (IPPROTO_NONE) */
677
    /* Check if ICMPv6 header was processed at all. */
678
    FAIL_IF(ICMPV6_GET_TYPE(PacketGetICMPv6(p)) != 2);
679
    FAIL_IF(ICMPV6_GET_CODE(PacketGetICMPv6(p)) != 0);
680
681
    /* Let's check if we retrieved the embedded ipv6 addresses correctly */
682
    for (int i = 0; i < 4; i++) {
683
        FAIL_IF(PacketGetICMPv6EmbIPv6(p)->s_ip6_src[i] != ipv6src[i] ||
684
                PacketGetICMPv6EmbIPv6(p)->s_ip6_dst[i] != ipv6dst[i]);
685
    }
686
687
    SCLogDebug("ICMPV6 IPV6 src and dst properly set");
688
689
    PacketRecycle(p);
690
    FlowShutdown();
691
    SCFree(p);
692
    PASS;
693
}
694
695
/** \test icmpv6 message type: time exceed, valid packet
696
 *
697
 * \retval retval 0 = Error ; 1 = ok
698
 */
699
static int ICMPV6TimeExceedTest01(void)
700
{
701
    static uint8_t raw_ipv6[] = {
702
        0x60, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3a, 0xff,
703
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
704
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
706
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
707
        0x03, 0x00, 0x56, 0x2d, 0x00, 0x00, 0x00, 0x00,
708
        0x6d, 0x23, 0xff, 0x3d, 0x00, 0x00, 0x3b, 0xff,
709
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
710
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
711
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
712
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
713
714
    Packet *p = PacketGetFromAlloc();
715
    FAIL_IF_NULL(p);
716
    IPV6Hdr ip6h;
717
    ThreadVars tv;
718
    DecodeThreadVars dtv;
719
    uint32_t *ipv6src;
720
    uint32_t *ipv6dst;
721
    ipv6src = (uint32_t*) &raw_ipv6[8];
722
    ipv6dst = (uint32_t*) &raw_ipv6[24];
723
724
    memset(&tv, 0, sizeof(ThreadVars));
725
    memset(&dtv, 0, sizeof(DecodeThreadVars));
726
    memset(&ip6h, 0, sizeof(IPV6Hdr));
727
728
    FlowInitConfig(FLOW_QUIET);
729
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
730
    FAIL_IF(!PacketIsICMPv6(p));
731
732
    /* Note: it has an embedded ipv6 packet but no protocol after ipv6 (IPPROTO_NONE) */
733
    FAIL_IF(ICMPV6_GET_TYPE(PacketGetICMPv6(p)) != 3);
734
    FAIL_IF(ICMPV6_GET_CODE(PacketGetICMPv6(p)) != 0);
735
    FAIL_IF_NULL(PacketGetICMPv6EmbIPv6(p));
736
    FAIL_IF(ICMPV6_GET_EMB_PROTO(p) != IPPROTO_NONE);
737
738
    /* Let's check if we retrieved the embedded ipv6 addresses correctly */
739
    for (int i = 0; i < 4; i++) {
740
        FAIL_IF(PacketGetICMPv6EmbIPv6(p)->s_ip6_src[i] != ipv6src[i] ||
741
                PacketGetICMPv6EmbIPv6(p)->s_ip6_dst[i] != ipv6dst[i]);
742
    }
743
744
    SCLogDebug("ICMPV6 IPV6 src and dst properly set");
745
746
    PacketRecycle(p);
747
    FlowShutdown();
748
    SCFree(p);
749
    PASS;
750
}
751
752
/** \test icmpv6 message type: destination unreach, valid packet
753
 *
754
 * \retval retval 0 = Error ; 1 = ok
755
 */
756
static int ICMPV6DestUnreachTest01(void)
757
{
758
    static uint8_t raw_ipv6[] = {
759
        0x60, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3a, 0xff,
760
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
761
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
762
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
763
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
764
        0x01, 0x00, 0x7b, 0x85, 0x00, 0x00, 0x00, 0x00,
765
        0x60, 0x4b, 0xe8, 0xbd, 0x00, 0x00, 0x3b, 0xff,
766
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
767
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
768
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
770
771
    Packet *p = PacketGetFromAlloc();
772
    FAIL_IF_NULL(p);
773
    IPV6Hdr ip6h;
774
    ThreadVars tv;
775
    DecodeThreadVars dtv;
776
    uint32_t *ipv6src;
777
    uint32_t *ipv6dst;
778
    ipv6src = (uint32_t*) &raw_ipv6[8];
779
    ipv6dst = (uint32_t*) &raw_ipv6[24];
780
781
    memset(&tv, 0, sizeof(ThreadVars));
782
    memset(&dtv, 0, sizeof(DecodeThreadVars));
783
    memset(&ip6h, 0, sizeof(IPV6Hdr));
784
785
    FlowInitConfig(FLOW_QUIET);
786
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
787
    FAIL_IF(!PacketIsICMPv6(p));
788
789
    /* Note: it has an embedded ipv6 packet but no protocol after ipv6 (IPPROTO_NONE) */
790
    FAIL_IF(ICMPV6_GET_TYPE(PacketGetICMPv6(p)) != 1);
791
    FAIL_IF(ICMPV6_GET_CODE(PacketGetICMPv6(p)) != 0);
792
    FAIL_IF_NULL(PacketGetICMPv6EmbIPv6(p));
793
    FAIL_IF(ICMPV6_GET_EMB_PROTO(p) != IPPROTO_NONE);
794
795
    /* Let's check if we retrieved the embedded ipv6 addresses correctly */
796
    for (int i = 0; i < 4; i++) {
797
        FAIL_IF(PacketGetICMPv6EmbIPv6(p)->s_ip6_src[i] != ipv6src[i] ||
798
                PacketGetICMPv6EmbIPv6(p)->s_ip6_dst[i] != ipv6dst[i]);
799
    }
800
801
    PacketRecycle(p);
802
    FlowShutdown();
803
    SCFree(p);
804
    PASS;
805
}
806
807
/**\test icmpv6 message type: echo request, valid packet
808
 * \retval retval 0 = Error ; 1 = ok
809
 */
810
static int ICMPV6EchoReqTest01(void)
811
{
812
    static uint8_t raw_ipv6[] = {
813
        0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0xff,
814
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
815
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
816
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
817
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
818
        0x80, 0x00, 0xe5, 0xa5, 0x25, 0xf0, 0x75, 0x23 };
819
820
    Packet *p = PacketGetFromAlloc();
821
    FAIL_IF_NULL(p);
822
    IPV6Hdr ip6h;
823
    ThreadVars tv;
824
    DecodeThreadVars dtv;
825
826
    memset(&tv, 0, sizeof(ThreadVars));
827
    memset(&dtv, 0, sizeof(DecodeThreadVars));
828
    memset(&ip6h, 0, sizeof(IPV6Hdr));
829
830
    FlowInitConfig(FLOW_QUIET);
831
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
832
    FAIL_IF(!PacketIsICMPv6(p));
833
834
    SCLogDebug("ID: %u seq: %u", ICMPV6_GET_ID(p), ICMPV6_GET_SEQ(p));
835
836
    FAIL_IF(ICMPV6_GET_TYPE(PacketGetICMPv6(p)) != 128);
837
    FAIL_IF(ICMPV6_GET_CODE(PacketGetICMPv6(p)) != 0);
838
    FAIL_IF(SCNtohs(ICMPV6_GET_ID(p)) != 9712);
839
    FAIL_IF(SCNtohs(ICMPV6_GET_SEQ(p)) != 29987);
840
841
    PacketRecycle(p);
842
    FlowShutdown();
843
    SCFree(p);
844
    PASS;
845
}
846
847
/**\test icmpv6 message type: echo reply, valid packet
848
 * \retval retval 0 = Error ; 1 = ok
849
 */
850
static int ICMPV6EchoRepTest01(void)
851
{
852
    static uint8_t raw_ipv6[] = {
853
        0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a,
854
        0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
855
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
856
        0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00,
857
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
858
        0x00, 0x00, 0x00, 0x00, 0x01, 0x81, 0x00,
859
        0xe5, 0xa5, 0x25, 0xf0, 0x75, 0x23 };
860
861
    Packet *p = PacketGetFromAlloc();
862
    FAIL_IF_NULL(p);
863
    IPV6Hdr ip6h;
864
    ThreadVars tv;
865
    DecodeThreadVars dtv;
866
867
    memset(&tv, 0, sizeof(ThreadVars));
868
    memset(&dtv, 0, sizeof(DecodeThreadVars));
869
    memset(&ip6h, 0, sizeof(IPV6Hdr));
870
871
    FlowInitConfig(FLOW_QUIET);
872
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
873
    FAIL_IF(!PacketIsICMPv6(p));
874
875
    FAIL_IF(ICMPV6_GET_TYPE(PacketGetICMPv6(p)) != 129);
876
    FAIL_IF(ICMPV6_GET_CODE(PacketGetICMPv6(p)) != 0);
877
    FAIL_IF(SCNtohs(ICMPV6_GET_ID(p)) != 9712);
878
    FAIL_IF(SCNtohs(ICMPV6_GET_SEQ(p)) != 29987);
879
880
    PacketRecycle(p);
881
    FlowShutdown();
882
    SCFree(p);
883
    PASS;
884
}
885
886
/** \test icmpv6 message type: parameter problem, invalid packet
887
 * \brief set the event ICMPV6_IPV6_UNKNOWN_VER properly when the embedded packet has an unknown version
888
 * \retval retval 0 = Error ; 1 = ok
889
 */
890
static int ICMPV6ParamProbTest02(void)
891
{
892
    static uint8_t raw_ipv6[] = {
893
        0x60, 0x00, 0x00, 0x00, 0x00, 0x38, 0x3a, 0xff,
894
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
895
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
896
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
897
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
898
        0x04, 0x00, 0xcc, 0x2a, 0x6d, 0x93, 0x0b, 0xdf,
899
        0x38, 0x70, 0x12, 0xb7, 0x00, 0x08, 0x3a, 0xff,
900
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
901
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
902
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
903
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
904
        0x80, 0x00, 0x08, 0xb5, 0x99, 0xc3, 0xde, 0x40 };
905
906
    Packet *p = PacketGetFromAlloc();
907
    FAIL_IF_NULL(p);
908
    IPV6Hdr ip6h;
909
    ThreadVars tv;
910
    DecodeThreadVars dtv;
911
912
    memset(&tv, 0, sizeof(ThreadVars));
913
    memset(&dtv, 0, sizeof(DecodeThreadVars));
914
    memset(&ip6h, 0, sizeof(IPV6Hdr));
915
916
    FlowInitConfig(FLOW_QUIET);
917
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
918
    FAIL_IF(!PacketIsICMPv6(p));
919
    FAIL_IF(ICMPV6_GET_TYPE(PacketGetICMPv6(p)) != 4);
920
    FAIL_IF(ICMPV6_GET_CODE(PacketGetICMPv6(p)) != 0);
921
    FAIL_IF(!ENGINE_ISSET_EVENT(p, ICMPV6_IPV6_UNKNOWN_VER));
922
923
    PacketRecycle(p);
924
    FlowShutdown();
925
    SCFree(p);
926
    PASS;
927
}
928
929
/** \test icmpv6 message type: packet too big, invalid packet
930
 *  \brief Set the event ICMPV6_UNKNOWN_CODE if code is invalid for this type
931
 * \retval retval 0 = Error ; 1 = ok
932
 */
933
static int ICMPV6PktTooBigTest02(void)
934
{
935
    static uint8_t raw_ipv6[] = {
936
        0x60, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3a, 0xff,
937
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
938
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
939
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
940
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
941
        0x02, 0x10, 0x5c, 0x7a, 0x00, 0x00, 0x05, 0x00,
942
        0x64, 0x14, 0xfd, 0xff, 0x00, 0x00, 0x3b, 0xff,
943
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
944
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
945
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
946
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
947
948
    Packet *p = PacketGetFromAlloc();
949
    FAIL_IF_NULL(p);
950
    IPV6Hdr ip6h;
951
    ThreadVars tv;
952
    DecodeThreadVars dtv;
953
954
    memset(&tv, 0, sizeof(ThreadVars));
955
    memset(&dtv, 0, sizeof(DecodeThreadVars));
956
    memset(&ip6h, 0, sizeof(IPV6Hdr));
957
958
    FlowInitConfig(FLOW_QUIET);
959
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
960
    FAIL_IF(!PacketIsICMPv6(p));
961
    FAIL_IF(!ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_CODE));
962
963
    PacketRecycle(p);
964
    FlowShutdown();
965
    SCFree(p);
966
    PASS;
967
}
968
969
/** \test icmpv6 message type: time exceed, invalid packet
970
 * \brief set the event ICMPV6_PKT_TOO_SMALL properly
971
 * \retval retval 0 = Error ; 1 = ok
972
 */
973
static int ICMPV6TimeExceedTest02(void)
974
{
975
    static uint8_t raw_ipv6[] = {
976
        0x60, 0x00, 0x00, 0x00, 0x00, 0x03, 0x3a, 0xff,
977
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
978
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
979
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
980
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
981
        0x02, 0x10, 0x5c };
982
983
    /* The icmpv6 header is broken in the checksum (so we dont have a complete header) */
984
985
    Packet *p = PacketGetFromAlloc();
986
    FAIL_IF_NULL(p);
987
    IPV6Hdr ip6h;
988
    ThreadVars tv;
989
    DecodeThreadVars dtv;
990
991
    memset(&tv, 0, sizeof(ThreadVars));
992
    memset(&dtv, 0, sizeof(DecodeThreadVars));
993
    memset(&ip6h, 0, sizeof(IPV6Hdr));
994
995
    FlowInitConfig(FLOW_QUIET);
996
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
997
998
    FAIL_IF(!ENGINE_ISSET_EVENT(p, ICMPV6_PKT_TOO_SMALL));
999
1000
    PacketRecycle(p);
1001
    FlowShutdown();
1002
    SCFree(p);
1003
    PASS;
1004
}
1005
1006
/**\test icmpv6 message type: destination unreach, invalid packet
1007
 * \brief The embedded packet header (ipv6) is truncated
1008
 * \retval retval 0 = Error ; 1 = ok
1009
 */
1010
static int ICMPV6DestUnreachTest02(void)
1011
{
1012
    static uint8_t raw_ipv6[] = {
1013
        0x60, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x3a, 0xff,
1014
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1015
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1016
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1017
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1018
        0x01, 0x00, 0x7b, 0x85, 0x00, 0x00, 0x00, 0x00,
1019
        0x60, 0x4b, 0xe8, 0xbd, 0x00, 0x00, 0x3b, 0xff,
1020
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1021
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1022
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1023
        0x00, 0x00, 0x00, 0x00, 0x00 };
1024
1025
    Packet *p = PacketGetFromAlloc();
1026
    FAIL_IF_NULL(p);
1027
    IPV6Hdr ip6h;
1028
    ThreadVars tv;
1029
    DecodeThreadVars dtv;
1030
1031
    memset(&tv, 0, sizeof(ThreadVars));
1032
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1033
    memset(&ip6h, 0, sizeof(IPV6Hdr));
1034
1035
    FlowInitConfig(FLOW_QUIET);
1036
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1037
1038
    FAIL_IF(!ENGINE_ISSET_EVENT(p, ICMPV6_IPV6_TRUNC_PKT));
1039
1040
    PacketRecycle(p);
1041
    FlowShutdown();
1042
    SCFree(p);
1043
    PASS;
1044
}
1045
1046
/**\test icmpv6 message type: echo request, invalid packet
1047
 * \brief unknown code
1048
 * \retval retval 0 = Error ; 1 = ok
1049
 */
1050
static int ICMPV6EchoReqTest02(void)
1051
{
1052
    static uint8_t raw_ipv6[] = {
1053
        0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a,
1054
        0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1055
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1056
        0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00,
1057
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1058
        0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01,
1059
        0xe5, 0xa5, 0x25, 0xf0, 0x75, 0x23 };
1060
1061
    Packet *p = PacketGetFromAlloc();
1062
    FAIL_IF_NULL(p);
1063
    IPV6Hdr ip6h;
1064
    ThreadVars tv;
1065
    DecodeThreadVars dtv;
1066
1067
    memset(&tv, 0, sizeof(ThreadVars));
1068
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1069
    memset(&ip6h, 0, sizeof(IPV6Hdr));
1070
1071
    FlowInitConfig(FLOW_QUIET);
1072
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1073
1074
    FAIL_IF(!ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_CODE));
1075
1076
    PacketRecycle(p);
1077
    FlowShutdown();
1078
    SCFree(p);
1079
    PASS;
1080
}
1081
1082
/**\test icmpv6 message type: echo reply, invalid packet
1083
 * \brief unknown code
1084
 * \retval retval 0 = Error ; 1 = ok
1085
 */
1086
static int ICMPV6EchoRepTest02(void)
1087
{
1088
    static uint8_t raw_ipv6[] = {
1089
        0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a,
1090
        0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1091
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1092
        0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00,
1093
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1094
        0x00, 0x00, 0x00, 0x00, 0x01, 0x81, 0x01,
1095
        0xe5, 0xa5, 0x25, 0xf0, 0x75, 0x23 };
1096
1097
    Packet *p = PacketGetFromAlloc();
1098
    FAIL_IF_NULL(p);
1099
    IPV6Hdr ip6h;
1100
    ThreadVars tv;
1101
    DecodeThreadVars dtv;
1102
1103
    memset(&tv, 0, sizeof(ThreadVars));
1104
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1105
    memset(&ip6h, 0, sizeof(IPV6Hdr));
1106
1107
    FlowInitConfig(FLOW_QUIET);
1108
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1109
1110
    FAIL_IF(!ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_CODE));
1111
1112
    PacketRecycle(p);
1113
    FlowShutdown();
1114
    SCFree(p);
1115
    PASS;
1116
}
1117
1118
/**\test icmpv6 packet decoding and setting up of payload_len and payload buffer
1119
 * \retval retval 0 = Error ; 1 = ok
1120
 */
1121
static int ICMPV6PayloadTest01(void)
1122
{
1123
    static uint8_t raw_ipv6[] = {
1124
        0x60, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x3a, 0xff,
1125
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1126
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1127
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1128
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1129
        0x01, 0x00, 0x7b, 0x85, 0x00, 0x00, 0x00, 0x00,
1130
        0x60, 0x4b, 0xe8, 0xbd, 0x00, 0x00, 0x3b, 0xff,
1131
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1132
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1133
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1134
        0x00, 0x00, 0x00, 0x00, 0x00 };
1135
1136
    Packet *p = PacketGetFromAlloc();
1137
    FAIL_IF_NULL(p);
1138
    IPV6Hdr ip6h;
1139
    ThreadVars tv;
1140
    DecodeThreadVars dtv;
1141
1142
    memset(&tv, 0, sizeof(ThreadVars));
1143
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1144
    memset(&ip6h, 0, sizeof(IPV6Hdr));
1145
1146
    FlowInitConfig(FLOW_QUIET);
1147
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1148
1149
    FAIL_IF_NULL(p->payload);
1150
    FAIL_IF(p->payload_len != 37);
1151
1152
    PacketRecycle(p);
1153
    FlowShutdown();
1154
    SCFree(p);
1155
    PASS;
1156
}
1157
1158
static int ICMPV6RouterSolicitTestKnownCode(void)
1159
{
1160
    static uint8_t raw_ipv6[] = {
1161
        0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0xff,
1162
        0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1163
        0x02, 0x24, 0x8c, 0xff, 0xfe, 0x0e, 0x31, 0x54,
1164
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1165
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1166
        0x85, 0x00, 0xbe, 0xb0, 0x00, 0x00, 0x00, 0x00
1167
    };
1168
1169
    Packet *p = PacketGetFromAlloc();
1170
    FAIL_IF_NULL(p);
1171
    IPV6Hdr ip6h;
1172
    ThreadVars tv;
1173
    DecodeThreadVars dtv;
1174
1175
    memset(&tv, 0, sizeof(ThreadVars));
1176
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1177
    memset(&ip6h, 0, sizeof(IPV6Hdr));
1178
1179
    FlowInitConfig(FLOW_QUIET);
1180
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1181
1182
    FAIL_IF(ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_CODE));
1183
1184
    PacketRecycle(p);
1185
    FlowShutdown();
1186
    SCFree(p);
1187
    PASS;
1188
}
1189
1190
static int ICMPV6RouterSolicitTestUnknownCode(void)
1191
{
1192
    static uint8_t raw_ipv6[] = {
1193
        0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0xff,
1194
        0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1195
        0x02, 0x24, 0x8c, 0xff, 0xfe, 0x0e, 0x31, 0x54,
1196
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1197
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1198
        0x85, 0x01, 0xbe, 0xaf, 0x00, 0x00, 0x00, 0x00
1199
    };
1200
1201
    Packet *p = PacketGetFromAlloc();
1202
    FAIL_IF_NULL(p);
1203
    IPV6Hdr ip6h;
1204
    ThreadVars tv;
1205
    DecodeThreadVars dtv;
1206
1207
    memset(&tv, 0, sizeof(ThreadVars));
1208
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1209
    memset(&ip6h, 0, sizeof(IPV6Hdr));
1210
1211
    FlowInitConfig(FLOW_QUIET);
1212
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1213
1214
    FAIL_IF(!ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_CODE));
1215
1216
    PacketRecycle(p);
1217
    FlowShutdown();
1218
    SCFree(p);
1219
    PASS;
1220
}
1221
1222
static int ICMPV6RouterAdvertTestKnownCode(void)
1223
{
1224
    static uint8_t raw_ipv6[] = {
1225
        0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0xff,
1226
        0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1227
        0x02, 0x24, 0x8c, 0xff, 0xfe, 0x0e, 0x31, 0x54,
1228
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1229
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1230
        0x86, 0x00, 0xbd, 0xb0, 0x00, 0x00, 0x00, 0x00
1231
    };
1232
1233
    Packet *p = PacketGetFromAlloc();
1234
    FAIL_IF_NULL(p);
1235
    IPV6Hdr ip6h;
1236
    ThreadVars tv;
1237
    DecodeThreadVars dtv;
1238
1239
    memset(&tv, 0, sizeof(ThreadVars));
1240
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1241
    memset(&ip6h, 0, sizeof(IPV6Hdr));
1242
1243
    FlowInitConfig(FLOW_QUIET);
1244
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1245
1246
    FAIL_IF(ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_CODE));
1247
1248
    PacketRecycle(p);
1249
    FlowShutdown();
1250
    SCFree(p);
1251
    PASS;
1252
}
1253
1254
static int ICMPV6RouterAdvertTestUnknownCode(void)
1255
{
1256
    static uint8_t raw_ipv6[] = {
1257
        0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0xff,
1258
        0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1259
        0x02, 0x24, 0x8c, 0xff, 0xfe, 0x0e, 0x31, 0x54,
1260
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1261
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1262
        0x86, 0x01, 0xbd, 0xaf, 0x00, 0x00, 0x00, 0x00
1263
    };
1264
1265
    Packet *p = PacketGetFromAlloc();
1266
    FAIL_IF_NULL(p);
1267
    IPV6Hdr ip6h;
1268
    ThreadVars tv;
1269
    DecodeThreadVars dtv;
1270
1271
    memset(&tv, 0, sizeof(ThreadVars));
1272
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1273
    memset(&ip6h, 0, sizeof(IPV6Hdr));
1274
1275
    FlowInitConfig(FLOW_QUIET);
1276
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1277
1278
    FAIL_IF(!ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_CODE));
1279
1280
    PacketRecycle(p);
1281
    FlowShutdown();
1282
    SCFree(p);
1283
    PASS;
1284
}
1285
1286
static int ICMPV6NeighbourSolicitTestKnownCode(void)
1287
{
1288
    static uint8_t raw_ipv6[] = {
1289
        0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0xff,
1290
        0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1291
        0x02, 0x24, 0x8c, 0xff, 0xfe, 0x0e, 0x31, 0x54,
1292
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1293
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1294
        0x87, 0x00, 0xbc, 0xb0, 0x00, 0x00, 0x00, 0x00
1295
    };
1296
1297
    Packet *p = PacketGetFromAlloc();
1298
    FAIL_IF_NULL(p);
1299
    IPV6Hdr ip6h;
1300
    ThreadVars tv;
1301
    DecodeThreadVars dtv;
1302
1303
    memset(&tv, 0, sizeof(ThreadVars));
1304
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1305
    memset(&ip6h, 0, sizeof(IPV6Hdr));
1306
1307
    FlowInitConfig(FLOW_QUIET);
1308
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1309
1310
    FAIL_IF(ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_CODE));
1311
1312
    PacketRecycle(p);
1313
    FlowShutdown();
1314
    SCFree(p);
1315
    PASS;
1316
}
1317
1318
static int ICMPV6NeighbourSolicitTestUnknownCode(void)
1319
{
1320
    static uint8_t raw_ipv6[] = {
1321
        0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0xff,
1322
        0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1323
        0x02, 0x24, 0x8c, 0xff, 0xfe, 0x0e, 0x31, 0x54,
1324
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1325
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1326
        0x87, 0x01, 0xbc, 0xaf, 0x00, 0x00, 0x00, 0x00
1327
    };
1328
1329
    Packet *p = PacketGetFromAlloc();
1330
    FAIL_IF_NULL(p);
1331
    IPV6Hdr ip6h;
1332
    ThreadVars tv;
1333
    DecodeThreadVars dtv;
1334
1335
    memset(&tv, 0, sizeof(ThreadVars));
1336
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1337
    memset(&ip6h, 0, sizeof(IPV6Hdr));
1338
1339
    FlowInitConfig(FLOW_QUIET);
1340
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1341
1342
    FAIL_IF(!ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_CODE));
1343
1344
    PacketRecycle(p);
1345
    FlowShutdown();
1346
    SCFree(p);
1347
    PASS;
1348
}
1349
1350
static int ICMPV6NeighbourAdvertTestKnownCode(void)
1351
{
1352
    static uint8_t raw_ipv6[] = {
1353
        0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0xff,
1354
        0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1355
        0x02, 0x24, 0x8c, 0xff, 0xfe, 0x0e, 0x31, 0x54,
1356
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1357
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1358
        0x88, 0x00, 0xbb, 0xb0, 0x00, 0x00, 0x00, 0x00
1359
    };
1360
1361
    Packet *p = PacketGetFromAlloc();
1362
    FAIL_IF_NULL(p);
1363
    IPV6Hdr ip6h;
1364
    ThreadVars tv;
1365
    DecodeThreadVars dtv;
1366
1367
    memset(&tv, 0, sizeof(ThreadVars));
1368
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1369
    memset(&ip6h, 0, sizeof(IPV6Hdr));
1370
1371
    FlowInitConfig(FLOW_QUIET);
1372
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1373
1374
    FAIL_IF(ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_CODE));
1375
1376
    PacketRecycle(p);
1377
    FlowShutdown();
1378
    SCFree(p);
1379
    PASS;
1380
}
1381
1382
static int ICMPV6NeighbourAdvertTestUnknownCode(void)
1383
{
1384
    static uint8_t raw_ipv6[] = {
1385
        0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0xff,
1386
        0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1387
        0x02, 0x24, 0x8c, 0xff, 0xfe, 0x0e, 0x31, 0x54,
1388
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1389
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1390
        0x88, 0x01, 0xbb, 0xaf, 0x00, 0x00, 0x00, 0x00
1391
    };
1392
1393
    Packet *p = PacketGetFromAlloc();
1394
    FAIL_IF_NULL(p);
1395
    IPV6Hdr ip6h;
1396
    ThreadVars tv;
1397
    DecodeThreadVars dtv;
1398
1399
    memset(&tv, 0, sizeof(ThreadVars));
1400
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1401
    memset(&ip6h, 0, sizeof(IPV6Hdr));
1402
1403
    FlowInitConfig(FLOW_QUIET);
1404
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1405
1406
    FAIL_IF(!ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_CODE));
1407
1408
    PacketRecycle(p);
1409
    FlowShutdown();
1410
    SCFree(p);
1411
    PASS;
1412
}
1413
1414
static int ICMPV6RedirectTestKnownCode(void)
1415
{
1416
    static uint8_t raw_ipv6[] = {
1417
        0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0xff,
1418
        0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1419
        0x02, 0x24, 0x8c, 0xff, 0xfe, 0x0e, 0x31, 0x54,
1420
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1421
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1422
        0x89, 0x00, 0xba, 0xb0, 0x00, 0x00, 0x00, 0x00
1423
    };
1424
1425
    Packet *p = PacketGetFromAlloc();
1426
    FAIL_IF_NULL(p);
1427
    IPV6Hdr ip6h;
1428
    ThreadVars tv;
1429
    DecodeThreadVars dtv;
1430
1431
    memset(&tv, 0, sizeof(ThreadVars));
1432
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1433
    memset(&ip6h, 0, sizeof(IPV6Hdr));
1434
1435
    FlowInitConfig(FLOW_QUIET);
1436
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1437
1438
    FAIL_IF(ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_CODE));
1439
1440
    PacketRecycle(p);
1441
    FlowShutdown();
1442
    SCFree(p);
1443
    PASS;
1444
}
1445
1446
static int ICMPV6RedirectTestUnknownCode(void)
1447
{
1448
    static uint8_t raw_ipv6[] = {
1449
        0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0xff,
1450
        0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1451
        0x02, 0x24, 0x8c, 0xff, 0xfe, 0x0e, 0x31, 0x54,
1452
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1453
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1454
        0x89, 0x01, 0xba, 0xaf, 0x00, 0x00, 0x00, 0x00
1455
    };
1456
1457
    Packet *p = PacketGetFromAlloc();
1458
    FAIL_IF_NULL(p);
1459
    IPV6Hdr ip6h;
1460
    ThreadVars tv;
1461
    DecodeThreadVars dtv;
1462
1463
    memset(&tv, 0, sizeof(ThreadVars));
1464
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1465
    memset(&ip6h, 0, sizeof(IPV6Hdr));
1466
1467
    FlowInitConfig(FLOW_QUIET);
1468
    DecodeIPV6(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1469
1470
    FAIL_IF(!ENGINE_ISSET_EVENT(p, ICMPV6_UNKNOWN_CODE));
1471
1472
    PacketRecycle(p);
1473
    FlowShutdown();
1474
    SCFree(p);
1475
    PASS;
1476
}
1477
1478
/**
1479
 * \test Test for valid ICMPv6 checksum when the FCS is still attached.
1480
 *
1481
 * Tests that the packet is decoded with sufficient info to verify the
1482
 * checksum even if the packet has some trailing data like an ethernet
1483
 * FCS.
1484
 */
1485
static int ICMPV6CalculateValidChecksumWithFCS(void)
1486
{
1487
    /* IPV6/ICMPv6 packet with ethernet header.
1488
     * - IPv6 payload length: 36
1489
     */
1490
    uint8_t raw_ipv6[] = {
1491
        0x33, 0x33, 0x00, 0x00, 0x00, 0x16, 0x00, 0x50,
1492
        0x56, 0xa6, 0x6a, 0x7d, 0x86, 0xdd, 0x60, 0x00,
1493
        0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0xfe, 0x80,
1494
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x09,
1495
        0xad, 0x44, 0x49, 0x38, 0x5f, 0xa9, 0xff, 0x02,
1496
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1497
        0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x3a, 0x00,
1498
        0x05, 0x02, 0x00, 0x00, 0x01, 0x00, 0x8f, 0x00,
1499
        0x24, 0xe0, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, /* Checksum: 0x24e0. */
1500
        0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
1501
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1502
        0x00, 0xfb, 0x1f, 0x34, 0xf6, 0xa4
1503
    };
1504
    uint16_t csum = *(((uint16_t *)(raw_ipv6 + 64)));
1505
1506
    Packet *p = PacketGetFromAlloc();
1507
    FAIL_IF_NULL(p);
1508
    ThreadVars tv;
1509
    DecodeThreadVars dtv;
1510
    memset(&tv, 0, sizeof(ThreadVars));
1511
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1512
1513
    FlowInitConfig(FLOW_QUIET);
1514
    DecodeEthernet(&tv, &dtv, p, raw_ipv6, sizeof(raw_ipv6));
1515
    FAIL_IF(!PacketIsICMPv6(p));
1516
1517
    const ICMPV6Hdr *icmpv6h = PacketGetICMPv6(p);
1518
    const IPV6Hdr *ip6h = PacketGetIPv6(p);
1519
    uint16_t icmpv6_len = IPV6_GET_RAW_PLEN(ip6h) -
1520
                          ((const uint8_t *)icmpv6h - (const uint8_t *)ip6h - IPV6_HEADER_LEN);
1521
    FAIL_IF(icmpv6_len != 28);
1522
    FAIL_IF(ICMPV6CalculateChecksum(ip6h->s_ip6_addrs, (uint16_t *)icmpv6h, icmpv6_len) != csum);
1523
1524
    PacketRecycle(p);
1525
    FlowShutdown();
1526
    SCFree(p);
1527
    PASS;
1528
}
1529
1530
#endif /* UNITTESTS */
1531
/**
1532
 * \brief Registers ICMPV6 unit tests
1533
 * \todo More ICMPv6 tests
1534
 */
1535
void DecodeICMPV6RegisterTests(void)
1536
0
{
1537
#ifdef UNITTESTS
1538
    UtRegisterTest("ICMPV6CalculateValidChecksumtest01",
1539
                   ICMPV6CalculateValidChecksumtest01);
1540
    UtRegisterTest("ICMPV6CalculateInvalidChecksumtest02", ICMPV6CalculateInvalidChecksumtest02);
1541
1542
    UtRegisterTest("ICMPV6ParamProbTest01 (Valid)", ICMPV6ParamProbTest01);
1543
    UtRegisterTest("ICMPV6DestUnreachTest01 (Valid)", ICMPV6DestUnreachTest01);
1544
    UtRegisterTest("ICMPV6PktTooBigTest01 (Valid)", ICMPV6PktTooBigTest01);
1545
    UtRegisterTest("ICMPV6TimeExceedTest01 (Valid)", ICMPV6TimeExceedTest01);
1546
    UtRegisterTest("ICMPV6EchoReqTest01 (Valid)", ICMPV6EchoReqTest01);
1547
    UtRegisterTest("ICMPV6EchoRepTest01 (Valid)", ICMPV6EchoRepTest01);
1548
1549
    UtRegisterTest("ICMPV6ParamProbTest02 (Invalid)", ICMPV6ParamProbTest02);
1550
    UtRegisterTest("ICMPV6DestUnreachTest02 (Invalid)",
1551
                   ICMPV6DestUnreachTest02);
1552
    UtRegisterTest("ICMPV6PktTooBigTest02 (Invalid)", ICMPV6PktTooBigTest02);
1553
    UtRegisterTest("ICMPV6TimeExceedTest02 (Invalid)", ICMPV6TimeExceedTest02);
1554
    UtRegisterTest("ICMPV6EchoReqTest02 (Invalid)", ICMPV6EchoReqTest02);
1555
    UtRegisterTest("ICMPV6EchoRepTest02 (Invalid)", ICMPV6EchoRepTest02);
1556
1557
    UtRegisterTest("ICMPV6PayloadTest01", ICMPV6PayloadTest01);
1558
1559
    UtRegisterTest("ICMPV6RouterSolicitTestKnownCode",
1560
                   ICMPV6RouterSolicitTestKnownCode);
1561
    UtRegisterTest("ICMPV6RouterSolicitTestUnknownCode",
1562
                   ICMPV6RouterSolicitTestUnknownCode);
1563
    UtRegisterTest("ICMPV6RouterAdvertTestKnownCode",
1564
                   ICMPV6RouterAdvertTestKnownCode);
1565
    UtRegisterTest("ICMPV6RouterAdvertTestUnknownCode",
1566
                   ICMPV6RouterAdvertTestUnknownCode);
1567
1568
    UtRegisterTest("ICMPV6NeighbourSolicitTestKnownCode",
1569
                   ICMPV6NeighbourSolicitTestKnownCode);
1570
    UtRegisterTest("ICMPV6NeighbourSolicitTestUnknownCode",
1571
                   ICMPV6NeighbourSolicitTestUnknownCode);
1572
    UtRegisterTest("ICMPV6NeighbourAdvertTestKnownCode",
1573
                   ICMPV6NeighbourAdvertTestKnownCode);
1574
    UtRegisterTest("ICMPV6NeighbourAdvertTestUnknownCode",
1575
                   ICMPV6NeighbourAdvertTestUnknownCode);
1576
1577
    UtRegisterTest("ICMPV6RedirectTestKnownCode", ICMPV6RedirectTestKnownCode);
1578
    UtRegisterTest("ICMPV6RedirectTestUnknownCode",
1579
                   ICMPV6RedirectTestUnknownCode);
1580
    UtRegisterTest("ICMPV6CalculateValidChecksumWithFCS",
1581
                   ICMPV6CalculateValidChecksumWithFCS);
1582
#endif /* UNITTESTS */
1583
0
}
1584
/**
1585
 * @}
1586
 */