Coverage Report

Created: 2025-07-23 07:29

/src/suricata7/src/detect-flow-age.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2022 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
#include "suricata-common.h"
19
#include "rust.h"
20
#include "detect-flow-age.h"
21
#include "detect-engine.h"
22
#include "detect-engine-prefilter.h"
23
#include "detect-engine-uint.h"
24
#include "detect-parse.h"
25
26
static int DetectFlowAgeMatch(
27
        DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx)
28
2.83k
{
29
2.83k
    if (p->flow == NULL) {
30
51
        return 0;
31
51
    }
32
2.78k
    uint32_t age = SCTIME_SECS(p->flow->lastts) - SCTIME_SECS(p->flow->startts);
33
34
2.78k
    const DetectU32Data *du32 = (const DetectU32Data *)ctx;
35
2.78k
    return DetectU32Match(age, du32);
36
2.83k
}
37
38
static void DetectFlowAgeFree(DetectEngineCtx *de_ctx, void *ptr)
39
6.94k
{
40
6.94k
    rs_detect_u32_free(ptr);
41
6.94k
}
42
43
static int DetectFlowAgeSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
44
7.14k
{
45
7.14k
    DetectU32Data *du32 = DetectU32Parse(rawstr);
46
7.14k
    if (du32 == NULL)
47
202
        return -1;
48
49
6.94k
    SigMatch *sm = SigMatchAlloc();
50
6.94k
    if (sm == NULL) {
51
0
        DetectFlowAgeFree(de_ctx, du32);
52
0
        return -1;
53
0
    }
54
55
6.94k
    sm->type = DETECT_FLOW_AGE;
56
6.94k
    sm->ctx = (SigMatchCtx *)du32;
57
58
6.94k
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
59
6.94k
    s->flags |= SIG_FLAG_REQUIRE_PACKET;
60
61
6.94k
    return 0;
62
6.94k
}
63
64
static void PrefilterPacketFlowAgeMatch(
65
        DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
66
0
{
67
0
    const PrefilterPacketHeaderCtx *ctx = pectx;
68
0
    if (!PrefilterPacketHeaderExtraMatch(ctx, p))
69
0
        return;
70
71
0
    DetectU32Data du32;
72
0
    du32.mode = ctx->v1.u8[0];
73
0
    du32.arg1 = ctx->v1.u32[1];
74
0
    du32.arg2 = ctx->v1.u32[2];
75
0
    if (DetectFlowAgeMatch(det_ctx, p, NULL, (const SigMatchCtx *)&du32)) {
76
0
        PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
77
0
    }
78
0
}
79
80
static int PrefilterSetupFlowAge(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
81
0
{
82
0
    return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_FLOW_AGE, PrefilterPacketU32Set,
83
0
            PrefilterPacketU32Compare, PrefilterPacketFlowAgeMatch);
84
0
}
85
86
static bool PrefilterFlowAgeIsPrefilterable(const Signature *s)
87
0
{
88
0
    return PrefilterIsPrefilterableById(s, DETECT_FLOW_AGE);
89
0
}
90
91
void DetectFlowAgeRegister(void)
92
73
{
93
73
    sigmatch_table[DETECT_FLOW_AGE].name = "flow.age";
94
73
    sigmatch_table[DETECT_FLOW_AGE].desc = "match flow age";
95
73
    sigmatch_table[DETECT_FLOW_AGE].url = "/rules/flow-keywords.html#flow-age";
96
73
    sigmatch_table[DETECT_FLOW_AGE].Match = DetectFlowAgeMatch;
97
73
    sigmatch_table[DETECT_FLOW_AGE].Setup = DetectFlowAgeSetup;
98
73
    sigmatch_table[DETECT_FLOW_AGE].Free = DetectFlowAgeFree;
99
73
    sigmatch_table[DETECT_FLOW_AGE].SupportsPrefilter = PrefilterFlowAgeIsPrefilterable;
100
73
    sigmatch_table[DETECT_FLOW_AGE].SetupPrefilter = PrefilterSetupFlowAge;
101
73
}