suricata
detect-flow-pkts.c
Go to the documentation of this file.
1 /* Copyright (C) 2023 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-pkts.h"
21 #include "detect-engine.h"
23 #include "detect-engine-uint.h"
24 #include "detect-parse.h"
25 
26 static int DetectFlowPktsToClientMatch(
27  DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx)
28 {
29  if (p->flow == NULL) {
30  return 0;
31  }
32  uint32_t nb = p->flow->tosrcpktcnt;
33 
34  const DetectU32Data *du32 = (const DetectU32Data *)ctx;
35  return DetectU32Match(nb, du32);
36 }
37 
38 static void DetectFlowPktsToClientFree(DetectEngineCtx *de_ctx, void *ptr)
39 {
40  rs_detect_u32_free(ptr);
41 }
42 
43 static int DetectFlowPktsToClientSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
44 {
45  DetectU32Data *du32 = DetectU32Parse(rawstr);
46  if (du32 == NULL)
47  return -1;
48 
50  DETECT_SM_LIST_MATCH) == NULL) {
51  DetectFlowPktsToClientFree(de_ctx, du32);
52  return -1;
53  }
55 
56  return 0;
57 }
58 
59 static void PrefilterPacketFlowPktsToClientMatch(
60  DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
61 {
62  const PrefilterPacketHeaderCtx *ctx = pectx;
63  if (!PrefilterPacketHeaderExtraMatch(ctx, p))
64  return;
65 
66  DetectU32Data du32;
67  du32.mode = ctx->v1.u8[0];
68  du32.arg1 = ctx->v1.u32[1];
69  du32.arg2 = ctx->v1.u32[2];
70  if (DetectFlowPktsToClientMatch(det_ctx, p, NULL, (const SigMatchCtx *)&du32)) {
71  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
72  }
73 }
74 
75 static int PrefilterSetupFlowPktsToClient(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
76 {
78  PrefilterPacketU32Set, PrefilterPacketU32Compare, PrefilterPacketFlowPktsToClientMatch);
79 }
80 
81 static bool PrefilterFlowPktsToClientIsPrefilterable(const Signature *s)
82 {
83  return PrefilterIsPrefilterableById(s, DETECT_FLOW_PKTS_TO_CLIENT);
84 }
85 
87 {
88  sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].name = "flow.pkts_toclient";
89  sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].desc = "match flow number of packets to client";
90  sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].url = "/rules/flow-keywords.html#flow-pkts_toclient";
91  sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].Match = DetectFlowPktsToClientMatch;
92  sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].Setup = DetectFlowPktsToClientSetup;
93  sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].Free = DetectFlowPktsToClientFree;
95  PrefilterFlowPktsToClientIsPrefilterable;
96  sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].SetupPrefilter = PrefilterSetupFlowPktsToClient;
97 }
98 
99 static int DetectFlowPktsToServerMatch(
100  DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx)
101 {
102  if (p->flow == NULL) {
103  return 0;
104  }
105  uint32_t nb = p->flow->todstpktcnt;
106 
107  const DetectU32Data *du32 = (const DetectU32Data *)ctx;
108  return DetectU32Match(nb, du32);
109 }
110 
111 static void DetectFlowPktsToServerFree(DetectEngineCtx *de_ctx, void *ptr)
112 {
113  rs_detect_u32_free(ptr);
114 }
115 
116 static int DetectFlowPktsToServerSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
117 {
118  DetectU32Data *du32 = DetectU32Parse(rawstr);
119  if (du32 == NULL)
120  return -1;
121 
123  DETECT_SM_LIST_MATCH) == NULL) {
124  DetectFlowPktsToServerFree(de_ctx, du32);
125  return -1;
126  }
128 
129  return 0;
130 }
131 
132 static void PrefilterPacketFlowPktsToServerMatch(
133  DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
134 {
135  const PrefilterPacketHeaderCtx *ctx = pectx;
136  if (!PrefilterPacketHeaderExtraMatch(ctx, p))
137  return;
138 
139  DetectU32Data du32;
140  du32.mode = ctx->v1.u8[0];
141  du32.arg1 = ctx->v1.u32[1];
142  du32.arg2 = ctx->v1.u32[2];
143  if (DetectFlowPktsToServerMatch(det_ctx, p, NULL, (const SigMatchCtx *)&du32)) {
144  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
145  }
146 }
147 
148 static int PrefilterSetupFlowPktsToServer(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
149 {
151  PrefilterPacketU32Set, PrefilterPacketU32Compare, PrefilterPacketFlowPktsToServerMatch);
152 }
153 
154 static bool PrefilterFlowPktsToServerIsPrefilterable(const Signature *s)
155 {
156  return PrefilterIsPrefilterableById(s, DETECT_FLOW_PKTS_TO_SERVER);
157 }
158 
160 {
161  sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].name = "flow.pkts_toserver";
162  sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].desc = "match flow number of packets to server";
163  sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].url = "/rules/flow-keywords.html#flow-pkts_toserver";
164  sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].Match = DetectFlowPktsToServerMatch;
165  sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].Setup = DetectFlowPktsToServerSetup;
166  sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].Free = DetectFlowPktsToServerFree;
168  PrefilterFlowPktsToServerIsPrefilterable;
169  sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].SetupPrefilter = PrefilterSetupFlowPktsToServer;
170 }
171 
172 static int DetectFlowBytesToClientMatch(
173  DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx)
174 {
175  if (p->flow == NULL) {
176  return 0;
177  }
178  uint64_t nb = p->flow->tosrcbytecnt;
179 
180  const DetectU64Data *du64 = (const DetectU64Data *)ctx;
181  return DetectU64Match(nb, du64);
182 }
183 
184 static void DetectFlowBytesToClientFree(DetectEngineCtx *de_ctx, void *ptr)
185 {
186  rs_detect_u64_free(ptr);
187 }
188 
189 static int DetectFlowBytesToClientSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
190 {
191  DetectU64Data *du64 = DetectU64Parse(rawstr);
192  if (du64 == NULL)
193  return -1;
194 
196  DETECT_SM_LIST_MATCH) == NULL) {
197  DetectFlowBytesToClientFree(de_ctx, du64);
198  return -1;
199  }
201 
202  return 0;
203 }
204 
206 {
207  sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].name = "flow.bytes_toclient";
208  sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].desc = "match flow number of bytes to client";
210  "/rules/flow-keywords.html#flow-bytes_toclient";
211  sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].Match = DetectFlowBytesToClientMatch;
212  sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].Setup = DetectFlowBytesToClientSetup;
213  sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].Free = DetectFlowBytesToClientFree;
214 }
215 
216 static int DetectFlowBytesToServerMatch(
217  DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx)
218 {
219  if (p->flow == NULL) {
220  return 0;
221  }
222  uint64_t nb = p->flow->todstbytecnt;
223 
224  const DetectU64Data *du64 = (const DetectU64Data *)ctx;
225  return DetectU64Match(nb, du64);
226 }
227 
228 static void DetectFlowBytesToServerFree(DetectEngineCtx *de_ctx, void *ptr)
229 {
230  rs_detect_u64_free(ptr);
231 }
232 
233 static int DetectFlowBytesToServerSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
234 {
235  DetectU64Data *du64 = DetectU64Parse(rawstr);
236  if (du64 == NULL)
237  return -1;
238 
240  DETECT_SM_LIST_MATCH) == NULL) {
241  DetectFlowBytesToServerFree(de_ctx, du64);
242  return -1;
243  }
245 
246  return 0;
247 }
248 
250 {
251  sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].name = "flow.bytes_toserver";
252  sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].desc = "match flow number of bytes to server";
254  "/rules/flow-keywords.html#flow-bytes_toserver";
255  sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].Match = DetectFlowBytesToServerMatch;
256  sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].Setup = DetectFlowBytesToServerSetup;
257  sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].Free = DetectFlowBytesToServerFree;
258 }
detect-engine-uint.h
SigTableElmt_::url
const char * url
Definition: detect.h:1299
detect-engine.h
DetectU32Match
int DetectU32Match(const uint32_t parg, const DetectUintData_u32 *du32)
Definition: detect-engine-uint.c:31
SigTableElmt_::desc
const char * desc
Definition: detect.h:1298
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1286
SigTableElmt_::name
const char * name
Definition: detect.h:1296
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1448
DetectU32Parse
DetectUintData_u32 * DetectU32Parse(const char *u32str)
This function is used to parse u32 options passed via some u32 keyword.
Definition: detect-engine-uint.c:45
PrefilterPacketU32Set
void PrefilterPacketU32Set(PrefilterPacketHeaderValue *v, void *smctx)
Definition: detect-engine-uint.c:51
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1204
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:839
PrefilterPacketHeaderCtx_::sigs_array
SigIntId * sigs_array
Definition: detect-engine-prefilter-common.h:43
PrefilterPacketHeaderValue::u8
uint8_t u8[16]
Definition: detect-engine-prefilter-common.h:24
rust.h
DetectFlowBytesToClientRegister
void DetectFlowBytesToClientRegister(void)
Definition: detect-flow-pkts.c:205
DetectFlowBytesToServerRegister
void DetectFlowBytesToServerRegister(void)
Definition: detect-flow-pkts.c:249
PrefilterPacketHeaderCtx_::sigs_cnt
uint32_t sigs_cnt
Definition: detect-engine-prefilter-common.h:42
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1281
detect-engine-prefilter.h
SigTableElmt_::SetupPrefilter
int(* SetupPrefilter)(DetectEngineCtx *de_ctx, struct SigGroupHead_ *sgh)
Definition: detect.h:1284
DETECT_FLOW_BYTES_TO_SERVER
@ DETECT_FLOW_BYTES_TO_SERVER
Definition: detect-engine-register.h:116
Flow_::tosrcbytecnt
uint64_t tosrcbytecnt
Definition: flow.h:499
DetectFlowPktsToClientRegister
void DetectFlowPktsToClientRegister(void)
Definition: detect-flow-pkts.c:86
PrefilterPacketHeaderCtx_
Definition: detect-engine-prefilter-common.h:35
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEngineThreadCtx_
Definition: detect.h:1095
Flow_::todstpktcnt
uint32_t todstpktcnt
Definition: flow.h:496
PrefilterPacketHeaderValue::u32
uint32_t u32[4]
Definition: detect-engine-prefilter-common.h:26
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:114
DETECT_FLOW_BYTES_TO_CLIENT
@ DETECT_FLOW_BYTES_TO_CLIENT
Definition: detect-engine-register.h:115
Flow_::todstbytecnt
uint64_t todstbytecnt
Definition: flow.h:498
DetectFlowPktsToServerRegister
void DetectFlowPktsToServerRegister(void)
Definition: detect-flow-pkts.c:159
Signature_::flags
uint32_t flags
Definition: detect.h:597
Packet_
Definition: decode.h:488
PrefilterPacketU32Compare
bool PrefilterPacketU32Compare(PrefilterPacketHeaderValue v, void *smctx)
Definition: detect-engine-uint.c:60
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1264
PrefilterPacketHeaderCtx_::v1
PrefilterPacketHeaderValue v1
Definition: detect-engine-prefilter-common.h:36
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:345
Packet_::flow
struct Flow_ * flow
Definition: decode.h:527
suricata-common.h
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:127
DetectU32Data
DetectUintData_u32 DetectU32Data
Definition: detect-engine-uint.h:41
DETECT_FLOW_PKTS_TO_SERVER
@ DETECT_FLOW_PKTS_TO_SERVER
Definition: detect-engine-register.h:114
DetectU64Parse
DetectUintData_u64 * DetectU64Parse(const char *u64str)
Definition: detect-engine-uint.c:147
PrefilterSetupPacketHeader
int PrefilterSetupPacketHeader(DetectEngineCtx *de_ctx, SigGroupHead *sgh, int sm_type, void(*Set)(PrefilterPacketHeaderValue *v, void *), bool(*Compare)(PrefilterPacketHeaderValue v, void *), void(*Match)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx))
Definition: detect-engine-prefilter-common.c:417
DetectU64Data
DetectUintData_u64 DetectU64Data
Definition: detect-engine-uint.h:40
SigTableElmt_::SupportsPrefilter
bool(* SupportsPrefilter)(const Signature *s)
Definition: detect.h:1283
detect-parse.h
Signature_
Signature container.
Definition: detect.h:596
DetectU64Match
int DetectU64Match(const uint64_t parg, const DetectUintData_u64 *du64)
Definition: detect-engine-uint.c:142
detect-flow-pkts.h
SigMatchAppendSMToList
SigMatch * SigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:447
DETECT_FLOW_PKTS_TO_CLIENT
@ DETECT_FLOW_PKTS_TO_CLIENT
Definition: detect-engine-register.h:113
Flow_::tosrcpktcnt
uint32_t tosrcpktcnt
Definition: flow.h:497
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:249