• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 23374838686

21 Mar 2026 07:29AM UTC coverage: 59.341% (-20.0%) from 79.315%
23374838686

Pull #15075

github

web-flow
Merge 90b4e834f into 6587e363a
Pull Request #15075: Stack 8001 v16.4

38 of 70 new or added lines in 10 files covered. (54.29%)

34165 existing lines in 563 files now uncovered.

119621 of 201584 relevant lines covered (59.34%)

650666.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

55.8
/src/flow-var.c
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
 * \file
20
 *
21
 * \author Victor Julien <victor@inliniac.net>
22
 * \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
23
 *
24
 * Flow level variable support for complex detection rules
25
 * Supported types atm are String and Integers
26
 */
27

28
#include "suricata-common.h"
29
#include "threads.h"
30
#include "flow-var.h"
31
#include "flow.h"
32
#include "detect.h"
33
#include "util-debug.h"
34

35
/* puts a new value into a flowvar */
36
static void FlowVarUpdateStr(FlowVar *fv, uint8_t *value, uint16_t size)
37
{
1✔
38
    if (fv->data.fv_str.value)
1✔
39
        SCFree(fv->data.fv_str.value);
1✔
40
    fv->data.fv_str.value = value;
1✔
41
    fv->data.fv_str.value_len = size;
1✔
42
}
1✔
43

44
/* puts a new value into a flowvar */
45
static void FlowVarUpdateInt(FlowVar *fv, uint32_t value)
46
{
917✔
47
    fv->data.fv_int.value = value;
917✔
48
}
917✔
49

50
/* puts a new value into a flowvar */
51
static void FlowVarUpdateFloat(FlowVar *fv, double value)
52
{
133✔
53
    fv->data.fv_float.value = value;
133✔
54
}
133✔
55

56
/** \brief get the flowvar with index 'idx' from the flow
57
 *  \note flow is not locked by this function, caller is
58
 *        responsible
59
 */
60
FlowVar *FlowVarGetByKey(Flow *f, const uint8_t *key, FlowVarKeyLenType keylen)
61
{
×
62
    if (f == NULL)
×
63
        return NULL;
×
64

65
    GenericVar *gv = f->flowvar;
×
66

67
    for ( ; gv != NULL; gv = gv->next) {
×
68
        if (gv->type == DETECT_FLOWVAR && gv->idx == 0) {
×
69

70
            FlowVar *fv = (FlowVar *)gv;
×
71
            if (fv->keylen == keylen && memcmp(key, fv->key, keylen) == 0) {
×
72
                return fv;
×
73
            }
×
74
        }
×
75
    }
×
76

77
    return NULL;
×
78
}
×
79

80
/** \brief get the flowvar with index 'idx' from the flow
81
 *  \note flow is not locked by this function, caller is
82
 *        responsible
83
 */
84
FlowVar *FlowVarGet(Flow *f, uint32_t idx)
85
{
5,773✔
86
    if (f == NULL)
5,773✔
87
        return NULL;
8✔
88

89
    GenericVar *gv = f->flowvar;
5,765✔
90

91
    for ( ; gv != NULL; gv = gv->next) {
8,445✔
92
        if (gv->type == DETECT_FLOWVAR && gv->idx == idx)
4,995✔
93
            return (FlowVar *)gv;
2,315✔
94
    }
4,995✔
95

96
    return NULL;
3,450✔
97
}
5,765✔
98

99
/* add a flowvar to the flow, or update it */
100
void FlowVarAddKeyValue(
101
        Flow *f, uint8_t *key, FlowVarKeyLenType keylen, uint8_t *value, uint16_t size)
102
{
×
103
    FlowVar *fv = SCCalloc(1, sizeof(FlowVar));
×
104
    if (unlikely(fv == NULL))
×
105
        return;
×
106

107
    fv->type = DETECT_FLOWVAR;
×
108
    fv->datatype = FLOWVAR_TYPE_STR;
×
109
    fv->idx = 0;
×
110
    fv->data.fv_str.value = value;
×
111
    fv->data.fv_str.value_len = size;
×
112
    fv->key = key;
×
113
    fv->keylen = keylen;
×
114
    fv->next = NULL;
×
115

116
    GenericVarAppend(&f->flowvar, (GenericVar *)fv);
×
117
}
×
118

119
/* add a flowvar to the flow, or update it */
120
void FlowVarAddIdValue(Flow *f, uint32_t idx, uint8_t *value, uint16_t size)
121
{
27✔
122
    FlowVar *fv = FlowVarGet(f, idx);
27✔
123
    if (fv == NULL) {
27✔
124
        fv = SCCalloc(1, sizeof(FlowVar));
26✔
125
        if (unlikely(fv == NULL))
26✔
126
            return;
×
127

128
        fv->type = DETECT_FLOWVAR;
26✔
129
        fv->datatype = FLOWVAR_TYPE_STR;
26✔
130
        fv->idx = idx;
26✔
131
        fv->data.fv_str.value = value;
26✔
132
        fv->data.fv_str.value_len = size;
26✔
133
        fv->next = NULL;
26✔
134

135
        GenericVarAppend(&f->flowvar, (GenericVar *)fv);
26✔
136
    } else {
26✔
137
        FlowVarUpdateStr(fv, value, size);
1✔
138
    }
1✔
139
}
27✔
140

141
/* add a flowvar to the flow, or update it */
142
void FlowVarAddFloat(Flow *f, uint32_t idx, double value)
143
{
135✔
144
    FlowVar *fv = FlowVarGet(f, idx);
135✔
145
    if (fv == NULL) {
135✔
146
        fv = SCMalloc(sizeof(FlowVar));
2✔
147
        if (unlikely(fv == NULL))
2✔
148
            return;
×
149

150
        fv->type = DETECT_FLOWVAR;
2✔
151
        fv->datatype = FLOWVAR_TYPE_FLOAT;
2✔
152
        fv->idx = idx;
2✔
153
        fv->data.fv_float.value = value;
2✔
154
        fv->next = NULL;
2✔
155

156
        GenericVarAppend(&f->flowvar, (GenericVar *)fv);
2✔
157
    } else {
133✔
158
        FlowVarUpdateFloat(fv, value);
133✔
159
    }
133✔
160
}
135✔
161
/* add a flowvar to the flow, or update it */
162
void FlowVarAddIntNoLock(Flow *f, uint32_t idx, uint32_t value)
163
{
1,106✔
164
    FlowVar *fv = FlowVarGet(f, idx);
1,106✔
165
    if (fv == NULL) {
1,106✔
166
        fv = SCMalloc(sizeof(FlowVar));
189✔
167
        if (unlikely(fv == NULL))
189✔
168
            return;
×
169

170
        fv->type = DETECT_FLOWVAR;
189✔
171
        fv->datatype = FLOWVAR_TYPE_INT;
189✔
172
        fv->idx = idx;
189✔
173
        fv->data.fv_int.value= value;
189✔
174
        fv->next = NULL;
189✔
175

176
        GenericVarAppend(&f->flowvar, (GenericVar *)fv);
189✔
177
    } else {
917✔
178
        FlowVarUpdateInt(fv, value);
917✔
179
    }
917✔
180
}
1,106✔
181

182
/* add a flowvar to the flow, or update it */
183
void FlowVarAddInt(Flow *f, uint32_t idx, uint32_t value)
UNCOV
184
{
×
UNCOV
185
    FlowVarAddIntNoLock(f, idx, value);
×
UNCOV
186
}
×
187

188
void FlowVarFree(FlowVar *fv)
189
{
217✔
190
    if (fv == NULL)
217✔
191
        return;
×
192

193
    if (fv->datatype == FLOWVAR_TYPE_STR) {
217✔
194
        if (fv->data.fv_str.value != NULL)
26✔
195
            SCFree(fv->data.fv_str.value);
26✔
196
        SCFree(fv->key);
26✔
197
    }
26✔
198
    SCFree(fv);
217✔
199
}
217✔
200

201
void FlowVarPrint(GenericVar *gv)
202
{
×
203
    uint16_t u;
×
204

205
    if (!SCLogDebugEnabled())
×
206
        return;
×
207

208
    if (gv == NULL)
×
209
        return;
×
210

211
    if (gv->type == DETECT_FLOWVAR || gv->type == DETECT_FLOWINT) {
×
212
        FlowVar *fv = (FlowVar *)gv;
×
213

214
        if (fv->datatype == FLOWVAR_TYPE_STR) {
×
215
            SCLogDebug("Name idx \"%" PRIu32 "\", Value \"", fv->idx);
×
216
            for (u = 0; u < fv->data.fv_str.value_len; u++) {
×
217
                if (isprint(fv->data.fv_str.value[u]))
×
218
                    SCLogDebug("%c", fv->data.fv_str.value[u]);
×
219
                else
×
220
                    SCLogDebug("\\%02X", fv->data.fv_str.value[u]);
×
221
            }
×
222
            SCLogDebug("\", Len \"%" PRIu16 "\"\n", fv->data.fv_str.value_len);
×
223
        } else if (fv->datatype == FLOWVAR_TYPE_INT) {
×
224
            SCLogDebug("Name idx \"%" PRIu32 "\", Value \"%" PRIu32 "\"", fv->idx,
×
225
                    fv->data.fv_int.value);
×
226
        } else {
×
227
            SCLogDebug("Unknown data type at flowvars\n");
×
228
        }
×
229
    }
×
230
    FlowVarPrint(gv->next);
×
231
}
×
232

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc