Coverage Report

Created: 2026-08-14 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/detect-icmpv6-mtu.c
Line
Count
Source
1
/* Copyright (C) 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
 * \file
20
 *
21
 * \author Philippe Antoine <p.antoine@catenacyber.fr>
22
 *
23
 */
24
25
#include "suricata-common.h"
26
27
#include "detect.h"
28
#include "detect-parse.h"
29
30
#include "detect-icmpv6-mtu.h"
31
#include "detect-engine-uint.h"
32
33
/* prototypes */
34
static int DetectICMPv6mtuMatch (DetectEngineThreadCtx *, Packet *,
35
        const Signature *, const SigMatchCtx *);
36
static int DetectICMPv6mtuSetup (DetectEngineCtx *, Signature *, const char *);
37
void DetectICMPv6mtuFree (DetectEngineCtx *de_ctx, void *);
38
#ifdef UNITTESTS
39
void DetectICMPv6mtuRegisterTests (void);
40
#endif
41
static int PrefilterSetupIcmpv6mtu(DetectEngineCtx *de_ctx, SigGroupHead *sgh);
42
static bool PrefilterIcmpv6mtuIsPrefilterable(const Signature *s);
43
44
/**
45
 * \brief Registration function for icmpv6.mtu: keyword
46
 */
47
48
void DetectICMPv6mtuRegister(void)
49
34
{
50
34
    sigmatch_table[DETECT_ICMPV6MTU].name = "icmpv6.mtu";
51
34
    sigmatch_table[DETECT_ICMPV6MTU].desc = "match on ICMPv6 MTU field";
52
34
    sigmatch_table[DETECT_ICMPV6MTU].url = "/rules/header-keywords.html#icmpv6mtu";
53
34
    sigmatch_table[DETECT_ICMPV6MTU].Match = DetectICMPv6mtuMatch;
54
34
    sigmatch_table[DETECT_ICMPV6MTU].Setup = DetectICMPv6mtuSetup;
55
34
    sigmatch_table[DETECT_ICMPV6MTU].Free = DetectICMPv6mtuFree;
56
#ifdef UNITTESTS
57
    sigmatch_table[DETECT_ICMPV6MTU].RegisterTests = DetectICMPv6mtuRegisterTests;
58
#endif
59
34
    sigmatch_table[DETECT_ICMPV6MTU].SupportsPrefilter = PrefilterIcmpv6mtuIsPrefilterable;
60
34
    sigmatch_table[DETECT_ICMPV6MTU].SetupPrefilter = PrefilterSetupIcmpv6mtu;
61
34
    return;
62
34
}
63
64
// returns 0 on no mtu, and 1 if mtu
65
static inline int DetectICMPv6mtuGetValue(Packet *p, uint32_t *picmpv6mtu)
66
6.08k
{
67
6.08k
    if (!(PKT_IS_ICMPV6(p)) || PKT_IS_PSEUDOPKT(p))
68
6.08k
        return 0;
69
0
    if (ICMPV6_GET_CODE(p) != 0)
70
0
        return 0;
71
0
    if (!(ICMPV6_HAS_MTU(p)))
72
0
        return 0;
73
74
0
    *picmpv6mtu = ICMPV6_GET_MTU(p);
75
0
    return 1;
76
0
}
77
78
/**
79
 * \brief This function is used to match ICMPV6 MTU rule option on a packet with those passed via icmpv6.mtu:
80
 *
81
 * \param det_ctx pointer to the pattern matcher thread
82
 * \param p pointer to the current packet
83
 * \param s pointer to the signature unused
84
 * \param ctx pointer to the signature match context
85
 *
86
 * \retval 0 no match
87
 * \retval 1 match
88
 */
89
static int DetectICMPv6mtuMatch (DetectEngineThreadCtx *det_ctx, Packet *p,
90
        const Signature *s, const SigMatchCtx *ctx)
91
{
92
    uint32_t picmpv6mtu;
93
    if (DetectICMPv6mtuGetValue(p, &picmpv6mtu) == 0) {
94
        return 0;
95
    }
96
97
    const DetectU32Data *du32 = (const DetectU32Data *)ctx;
98
    return DetectU32Match(picmpv6mtu, du32);
99
}
100
101
/**
102
 * \brief this function is used to attach the parsed icmpv6.mtu data into the current signature
103
 *
104
 * \param de_ctx pointer to the Detection Engine Context
105
 * \param s pointer to the Current Signature
106
 * \param icmpv6mtustr pointer to the user provided icmpv6.mtu options
107
 *
108
 * \retval 0 on Success
109
 * \retval -1 on Failure
110
 */
111
static int DetectICMPv6mtuSetup (DetectEngineCtx *de_ctx, Signature *s, const char *icmpv6mtustr)
112
2.28k
{
113
2.28k
    DetectU32Data *icmpv6mtud = DetectU32Parse(icmpv6mtustr);
114
2.28k
    if (icmpv6mtud == NULL)
115
498
        return -1;
116
117
1.78k
    SigMatch *sm = SigMatchAlloc();
118
1.78k
    if (sm == NULL) {
119
0
        DetectICMPv6mtuFree(de_ctx, icmpv6mtud);
120
0
        return -1;
121
0
    }
122
123
1.78k
    sm->type = DETECT_ICMPV6MTU;
124
1.78k
    sm->ctx = (SigMatchCtx *)icmpv6mtud;
125
126
1.78k
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
127
1.78k
    s->flags |= SIG_FLAG_REQUIRE_PACKET;
128
1.78k
    s->proto.flags |= DETECT_PROTO_IPV6;
129
130
1.78k
    return 0;
131
1.78k
}
132
133
/**
134
 * \brief this function will free memory associated with DetectU32Data
135
 *
136
 * \param ptr pointer to DetectU32Data
137
 */
138
void DetectICMPv6mtuFree(DetectEngineCtx *de_ctx, void *ptr)
139
1.78k
{
140
1.78k
    rs_detect_u32_free(ptr);
141
1.78k
}
142
143
/* prefilter code */
144
145
static void
146
PrefilterPacketIcmpv6mtuMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
147
6.08k
{
148
6.08k
    uint32_t picmpv6mtu;
149
6.08k
    if (DetectICMPv6mtuGetValue(p, &picmpv6mtu) == 0) {
150
6.08k
        return;
151
6.08k
    }
152
153
    /* during setup Suricata will automatically see if there is another
154
     * check that can be added: alproto, sport or dport */
155
0
    const PrefilterPacketHeaderCtx *ctx = pectx;
156
0
    if (!PrefilterPacketHeaderExtraMatch(ctx, p))
157
0
        return;
158
159
    /* if we match, add all the sigs that use this prefilter. This means
160
     * that these will be inspected further */
161
0
    DetectU32Data du32;
162
0
    du32.mode = ctx->v1.u8[0];
163
0
    du32.arg1 = ctx->v1.u32[1];
164
0
    du32.arg2 = ctx->v1.u32[2];
165
0
    if (DetectU32Match(picmpv6mtu, &du32))
166
0
    {
167
0
        SCLogDebug("packet matches icmpv6.mtu/hl %u", picmpv6mtu);
168
0
        PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
169
0
    }
170
0
}
171
172
static int PrefilterSetupIcmpv6mtu(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
173
7.04k
{
174
7.04k
    return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_ICMPV6MTU,
175
7.04k
            PrefilterPacketU32Set,
176
7.04k
            PrefilterPacketU32Compare,
177
7.04k
            PrefilterPacketIcmpv6mtuMatch);
178
7.04k
}
179
180
static bool PrefilterIcmpv6mtuIsPrefilterable(const Signature *s)
181
0
{
182
0
    return PrefilterIsPrefilterableById(s, DETECT_ICMPV6MTU);
183
0
}
184
185
#ifdef UNITTESTS
186
#include "tests/detect-icmpv6-mtu.c"
187
#endif