From 5fad553fa4e5ca37b6968f13e64b74a9995c9903 Mon Sep 17 00:00:00 2001 From: Shivani Bhardwaj Date: Fri, 29 Nov 2024 14:01:12 +0530 Subject: [PATCH] flow/pkts: make syntax cleaner and compact Currently, the syntax includes direction as a part of the keyword which is against how usually keywords are done. By making direction as a mandatory argument, it is possible to make the syntax cleaner and the implementation more compact and easily extendable. Pros: - Registration table sees lesser entries if newer options are added - If the options have to be extended, it can be done trivially - In accordance w existing keyword implementations Note that this commit also retains the existing direction specific keywords. --- src/detect-engine-register.c | 6 +- src/detect-engine-register.h | 6 +- src/detect-flow-pkts.c | 427 ++++++++++++++++++++++++----------- src/detect-flow-pkts.h | 8 +- 4 files changed, 314 insertions(+), 133 deletions(-) diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index 9bddf0fd8437..82153807ad58 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -581,10 +581,12 @@ void SigTableSetup(void) DetectReplaceRegister(); DetectFlowRegister(); DetectFlowAgeRegister(); - DetectFlowPktsToClientRegister(); + DetectFlowPktsRegister(); DetectFlowPktsToServerRegister(); - DetectFlowBytesToClientRegister(); + DetectFlowPktsToClientRegister(); + DetectFlowBytesRegister(); DetectFlowBytesToServerRegister(); + DetectFlowBytesToClientRegister(); DetectRequiresRegister(); DetectWindowRegister(); DetectRpcRegister(); diff --git a/src/detect-engine-register.h b/src/detect-engine-register.h index b7a029998555..f46bf688f0f8 100644 --- a/src/detect-engine-register.h +++ b/src/detect-engine-register.h @@ -127,10 +127,12 @@ enum DetectKeywordId { DETECT_FRAME, DETECT_FLOW_AGE, - DETECT_FLOW_PKTS_TO_CLIENT, + DETECT_FLOW_PKTS, DETECT_FLOW_PKTS_TO_SERVER, - DETECT_FLOW_BYTES_TO_CLIENT, + DETECT_FLOW_PKTS_TO_CLIENT, + DETECT_FLOW_BYTES, DETECT_FLOW_BYTES_TO_SERVER, + DETECT_FLOW_BYTES_TO_CLIENT, DETECT_REQUIRES, diff --git a/src/detect-flow-pkts.c b/src/detect-flow-pkts.c index ef8fed369cd9..884ba2f1cba2 100644 --- a/src/detect-flow-pkts.c +++ b/src/detect-flow-pkts.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Open Information Security Foundation +/* Copyright (C) 2023-2025 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -23,32 +23,64 @@ #include "detect-engine-uint.h" #include "detect-parse.h" -static int DetectFlowPktsToClientMatch( +enum FlowDirection { + DETECT_FLOW_TOSERVER = 1, + DETECT_FLOW_TOCLIENT, +}; + +typedef struct DetectFlowPkts_ { + DetectU32Data *pkt_data; + enum FlowDirection dir; +} DetectFlowPkts; + +typedef struct DetectFlowBytes_ { + DetectU64Data *byte_data; + enum FlowDirection dir; +} DetectFlowBytes; + +static int DetectFlowPktsMatch( DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx) { if (p->flow == NULL) { return 0; } - uint32_t nb = p->flow->tosrcpktcnt; - const DetectU32Data *du32 = (const DetectU32Data *)ctx; - return DetectU32Match(nb, du32); + const DetectFlowPkts *df = (const DetectFlowPkts *)ctx; + if (df->dir == DETECT_FLOW_TOSERVER) { + return DetectU32Match(p->flow->todstpktcnt, df->pkt_data); + } else if (df->dir == DETECT_FLOW_TOCLIENT) { + return DetectU32Match(p->flow->tosrcpktcnt, df->pkt_data); + } + return 0; } -static void DetectFlowPktsToClientFree(DetectEngineCtx *de_ctx, void *ptr) +static void DetectFlowPktsFree(DetectEngineCtx *de_ctx, void *ptr) { - rs_detect_u32_free(ptr); + DetectFlowPkts *df = (DetectFlowPkts *)ptr; + if (df != NULL) { + rs_detect_u32_free(df->pkt_data); + SCFree(df); + } } -static int DetectFlowPktsToClientSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) +static int DetectFlowPktsToServerSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) { DetectU32Data *du32 = DetectU32Parse(rawstr); if (du32 == NULL) return -1; - if (SigMatchAppendSMToList(de_ctx, s, DETECT_FLOW_PKTS_TO_CLIENT, (SigMatchCtx *)du32, - DETECT_SM_LIST_MATCH) == NULL) { - DetectFlowPktsToClientFree(de_ctx, du32); + DetectFlowPkts *df = SCCalloc(1, sizeof(DetectFlowPkts)); + if (df == NULL) { + rs_detect_u32_free(du32); + return -1; + } + + df->pkt_data = du32; + df->dir = DETECT_FLOW_TOSERVER; + + if (SigMatchAppendSMToList( + de_ctx, s, DETECT_FLOW_PKTS, (SigMatchCtx *)df, DETECT_SM_LIST_MATCH) == NULL) { + DetectFlowPktsFree(de_ctx, df); return -1; } s->flags |= SIG_FLAG_REQUIRE_PACKET; @@ -56,147 +88,225 @@ static int DetectFlowPktsToClientSetup(DetectEngineCtx *de_ctx, Signature *s, co return 0; } -static void PrefilterPacketFlowPktsToClientMatch( - DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx) +static int DetectFlowPktsToClientSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) { - const PrefilterPacketHeaderCtx *ctx = pectx; - if (!PrefilterPacketHeaderExtraMatch(ctx, p)) - return; + DetectU32Data *du32 = DetectU32Parse(rawstr); + if (du32 == NULL) + return -1; - DetectU32Data du32; - du32.mode = ctx->v1.u8[0]; - du32.arg1 = ctx->v1.u32[1]; - du32.arg2 = ctx->v1.u32[2]; - if (DetectFlowPktsToClientMatch(det_ctx, p, NULL, (const SigMatchCtx *)&du32)) { - PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt); + DetectFlowPkts *df = SCCalloc(1, sizeof(DetectFlowPkts)); + if (df == NULL) { + rs_detect_u32_free(du32); + return -1; } -} + df->pkt_data = du32; + df->dir = DETECT_FLOW_TOCLIENT; -static int PrefilterSetupFlowPktsToClient(DetectEngineCtx *de_ctx, SigGroupHead *sgh) -{ - return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_FLOW_PKTS_TO_CLIENT, - SIG_MASK_REQUIRE_FLOW, PrefilterPacketU32Set, PrefilterPacketU32Compare, - PrefilterPacketFlowPktsToClientMatch); -} + if (SigMatchAppendSMToList( + de_ctx, s, DETECT_FLOW_PKTS, (SigMatchCtx *)df, DETECT_SM_LIST_MATCH) == NULL) { + DetectFlowPktsFree(de_ctx, df); + return -1; + } + s->flags |= SIG_FLAG_REQUIRE_PACKET; -static bool PrefilterFlowPktsToClientIsPrefilterable(const Signature *s) -{ - return PrefilterIsPrefilterableById(s, DETECT_FLOW_PKTS_TO_CLIENT); + return 0; } -void DetectFlowPktsToClientRegister(void) +static int DetectFlowPktsSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) { - sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].name = "flow.pkts_toclient"; - sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].desc = "match flow number of packets to client"; - sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].url = "/rules/flow-keywords.html#flow-pkts_toclient"; - sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].Match = DetectFlowPktsToClientMatch; - sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].Setup = DetectFlowPktsToClientSetup; - sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].Free = DetectFlowPktsToClientFree; - sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].SupportsPrefilter = - PrefilterFlowPktsToClientIsPrefilterable; - sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].SetupPrefilter = PrefilterSetupFlowPktsToClient; -} + DetectFlowPkts *df = NULL; + char copy[strlen(rawstr) + 1]; + strlcpy(copy, rawstr, sizeof(copy)); + char *context = NULL; + char *token = strtok_r(copy, ",", &context); + uint8_t num_tokens = 0; + uint8_t dir = 0; + char *pkt_data = NULL; + + while (token != NULL) { + if (num_tokens > 1) + return -1; + + while (*token != '\0' && isblank(*token)) { + token++; + } + if (strlen(token) == 0) { + goto next; + } + + num_tokens++; + + if (dir == 0 && num_tokens == 1) { + if (strcmp(token, "toserver") == 0) { + dir = DETECT_FLOW_TOSERVER; + } else if (strcmp(token, "toclient") == 0) { + dir = DETECT_FLOW_TOCLIENT; + } else { + SCLogError("Invalid direction given: %s", token); + return -1; + } + } + + if (dir && num_tokens == 2) { + pkt_data = token; + } + + next: + token = strtok_r(NULL, ",", &context); + } -static int DetectFlowPktsToServerMatch( - DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx) -{ - if (p->flow == NULL) { - return 0; + DetectU32Data *du32 = DetectU32Parse(pkt_data); + if (du32 == NULL) + return -1; + df = SCCalloc(1, sizeof(DetectFlowPkts)); + if (df == NULL) { + rs_detect_u32_free(du32); + return -1; } - uint32_t nb = p->flow->todstpktcnt; + df->dir = dir; + df->pkt_data = du32; + if (SigMatchAppendSMToList( + de_ctx, s, DETECT_FLOW_PKTS, (SigMatchCtx *)df, DETECT_SM_LIST_MATCH) == NULL) { + DetectFlowPktsFree(de_ctx, df); + return -1; + } + + s->flags |= SIG_FLAG_REQUIRE_PACKET; - const DetectU32Data *du32 = (const DetectU32Data *)ctx; - return DetectU32Match(nb, du32); + return 0; } -static void DetectFlowPktsToServerFree(DetectEngineCtx *de_ctx, void *ptr) +static void PrefilterPacketFlowPktsSet(PrefilterPacketHeaderValue *v, void *smctx) { - rs_detect_u32_free(ptr); + const DetectFlowPkts *df = smctx; + const DetectUintData_u32 *data = df->pkt_data; + v->u8[0] = data->mode; + v->u8[1] = (uint8_t)df->dir; + v->u32[1] = data->arg1; + v->u32[2] = data->arg2; } -static int DetectFlowPktsToServerSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) +static bool PrefilterPacketFlowPktsCompare(PrefilterPacketHeaderValue v, void *smctx) { - DetectU32Data *du32 = DetectU32Parse(rawstr); - if (du32 == NULL) - return -1; - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_FLOW_PKTS_TO_SERVER, (SigMatchCtx *)du32, - DETECT_SM_LIST_MATCH) == NULL) { - DetectFlowPktsToServerFree(de_ctx, du32); - return -1; + const DetectFlowPkts *df = smctx; + if (v.u8[0] == df->pkt_data->mode && v.u8[1] == df->dir && v.u32[1] == df->pkt_data->arg1 && + v.u32[2] == df->pkt_data->arg2) { + return true; } - s->flags |= SIG_FLAG_REQUIRE_PACKET; - - return 0; + return false; } -static void PrefilterPacketFlowPktsToServerMatch( +static void PrefilterPacketFlowPktsMatch( DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx) { const PrefilterPacketHeaderCtx *ctx = pectx; if (!PrefilterPacketHeaderExtraMatch(ctx, p)) return; - DetectU32Data du32; - du32.mode = ctx->v1.u8[0]; - du32.arg1 = ctx->v1.u32[1]; - du32.arg2 = ctx->v1.u32[2]; - if (DetectFlowPktsToServerMatch(det_ctx, p, NULL, (const SigMatchCtx *)&du32)) { + DetectFlowPkts df; + DetectUintData_u32 data = { + .mode = ctx->v1.u8[0], .arg1 = ctx->v1.u32[1], .arg2 = ctx->v1.u32[2] + }; + df.pkt_data = &data; + df.dir = ctx->v1.u8[1]; + + if (DetectFlowPktsMatch(det_ctx, p, NULL, (const SigMatchCtx *)&df)) { PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt); } } -static int PrefilterSetupFlowPktsToServer(DetectEngineCtx *de_ctx, SigGroupHead *sgh) +static int PrefilterSetupFlowPkts(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { - return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_FLOW_PKTS_TO_SERVER, - SIG_MASK_REQUIRE_FLOW, PrefilterPacketU32Set, PrefilterPacketU32Compare, - PrefilterPacketFlowPktsToServerMatch); + return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_FLOW_PKTS, SIG_MASK_REQUIRE_FLOW, + PrefilterPacketFlowPktsSet, PrefilterPacketFlowPktsCompare, + PrefilterPacketFlowPktsMatch); } -static bool PrefilterFlowPktsToServerIsPrefilterable(const Signature *s) +static bool PrefilterFlowPktsIsPrefilterable(const Signature *s) { - return PrefilterIsPrefilterableById(s, DETECT_FLOW_PKTS_TO_SERVER); + return PrefilterIsPrefilterableById(s, DETECT_FLOW_PKTS); +} + +void DetectFlowPktsRegister(void) +{ + sigmatch_table[DETECT_FLOW_PKTS].name = "flow.pkts"; + sigmatch_table[DETECT_FLOW_PKTS].desc = "match number of packets in a flow"; + sigmatch_table[DETECT_FLOW_PKTS].url = "/rules/flow-keywords.html#flow-pkts"; + sigmatch_table[DETECT_FLOW_PKTS].Match = DetectFlowPktsMatch; + sigmatch_table[DETECT_FLOW_PKTS].Setup = DetectFlowPktsSetup; + sigmatch_table[DETECT_FLOW_PKTS].Free = DetectFlowPktsFree; + sigmatch_table[DETECT_FLOW_PKTS].SupportsPrefilter = PrefilterFlowPktsIsPrefilterable; + sigmatch_table[DETECT_FLOW_PKTS].SetupPrefilter = PrefilterSetupFlowPkts; } void DetectFlowPktsToServerRegister(void) { sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].name = "flow.pkts_toserver"; - sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].desc = "match flow number of packets to server"; - sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].url = "/rules/flow-keywords.html#flow-pkts_toserver"; - sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].Match = DetectFlowPktsToServerMatch; + sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].desc = + "match number of packets in a flow in to server direction"; + sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].url = "/rules/flow-keywords.html#flow-pkts"; + sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].Match = DetectFlowPktsMatch; sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].Setup = DetectFlowPktsToServerSetup; - sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].Free = DetectFlowPktsToServerFree; - sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].SupportsPrefilter = - PrefilterFlowPktsToServerIsPrefilterable; - sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].SetupPrefilter = PrefilterSetupFlowPktsToServer; + sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].Free = DetectFlowPktsFree; + sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].SupportsPrefilter = PrefilterFlowPktsIsPrefilterable; + sigmatch_table[DETECT_FLOW_PKTS_TO_SERVER].SetupPrefilter = PrefilterSetupFlowPkts; +} + +void DetectFlowPktsToClientRegister(void) +{ + sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].name = "flow.pkts_toclient"; + sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].desc = + "match number of packets in a flow in to client direction"; + sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].url = "/rules/flow-keywords.html#flow-pkts"; + sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].Match = DetectFlowPktsMatch; + sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].Setup = DetectFlowPktsToClientSetup; + sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].Free = DetectFlowPktsFree; + sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].SupportsPrefilter = PrefilterFlowPktsIsPrefilterable; + sigmatch_table[DETECT_FLOW_PKTS_TO_CLIENT].SetupPrefilter = PrefilterSetupFlowPkts; } -static int DetectFlowBytesToClientMatch( +static int DetectFlowBytesMatch( DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx) { if (p->flow == NULL) { return 0; } - uint64_t nb = p->flow->tosrcbytecnt; - const DetectU64Data *du64 = (const DetectU64Data *)ctx; - return DetectU64Match(nb, du64); + const DetectFlowBytes *df = (const DetectFlowBytes *)ctx; + if (df->dir == DETECT_FLOW_TOSERVER) { + return DetectU64Match(p->flow->todstbytecnt, df->byte_data); + } else if (df->dir == DETECT_FLOW_TOCLIENT) { + return DetectU64Match(p->flow->tosrcbytecnt, df->byte_data); + } + return 0; } -static void DetectFlowBytesToClientFree(DetectEngineCtx *de_ctx, void *ptr) +static void DetectFlowBytesFree(DetectEngineCtx *de_ctx, void *ptr) { - rs_detect_u64_free(ptr); + DetectFlowBytes *df = (DetectFlowBytes *)ptr; + if (df != NULL) { + rs_detect_u64_free(df->byte_data); + SCFree(df); + } } -static int DetectFlowBytesToClientSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) +static int DetectFlowBytesToServerSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) { DetectU64Data *du64 = DetectU64Parse(rawstr); if (du64 == NULL) return -1; - if (SigMatchAppendSMToList(de_ctx, s, DETECT_FLOW_BYTES_TO_CLIENT, (SigMatchCtx *)du64, - DETECT_SM_LIST_MATCH) == NULL) { - DetectFlowBytesToClientFree(de_ctx, du64); + DetectFlowBytes *df = SCCalloc(1, sizeof(DetectFlowBytes)); + if (df == NULL) { + rs_detect_u64_free(du64); + return -1; + } + df->byte_data = du64; + df->dir = DETECT_FLOW_TOSERVER; + + if (SigMatchAppendSMToList( + de_ctx, s, DETECT_FLOW_BYTES, (SigMatchCtx *)df, DETECT_SM_LIST_MATCH) == NULL) { + DetectFlowBytesFree(de_ctx, df); return -1; } s->flags |= SIG_FLAG_REQUIRE_PACKET; @@ -204,43 +314,87 @@ static int DetectFlowBytesToClientSetup(DetectEngineCtx *de_ctx, Signature *s, c return 0; } -void DetectFlowBytesToClientRegister(void) +static int DetectFlowBytesToClientSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) { - sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].name = "flow.bytes_toclient"; - sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].desc = "match flow number of bytes to client"; - sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].url = - "/rules/flow-keywords.html#flow-bytes_toclient"; - sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].Match = DetectFlowBytesToClientMatch; - sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].Setup = DetectFlowBytesToClientSetup; - sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].Free = DetectFlowBytesToClientFree; -} + DetectU64Data *du64 = DetectU64Parse(rawstr); + if (du64 == NULL) + return -1; -static int DetectFlowBytesToServerMatch( - DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx) -{ - if (p->flow == NULL) { - return 0; + DetectFlowBytes *df = SCCalloc(1, sizeof(DetectFlowBytes)); + if (df == NULL) { + rs_detect_u64_free(du64); + return -1; } - uint64_t nb = p->flow->todstbytecnt; - const DetectU64Data *du64 = (const DetectU64Data *)ctx; - return DetectU64Match(nb, du64); -} + df->byte_data = du64; + df->dir = DETECT_FLOW_TOCLIENT; -static void DetectFlowBytesToServerFree(DetectEngineCtx *de_ctx, void *ptr) -{ - rs_detect_u64_free(ptr); + if (SigMatchAppendSMToList( + de_ctx, s, DETECT_FLOW_BYTES, (SigMatchCtx *)df, DETECT_SM_LIST_MATCH) == NULL) { + DetectFlowBytesFree(de_ctx, df); + return -1; + } + s->flags |= SIG_FLAG_REQUIRE_PACKET; + + return 0; } -static int DetectFlowBytesToServerSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) +static int DetectFlowBytesSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) { - DetectU64Data *du64 = DetectU64Parse(rawstr); + DetectFlowBytes *df = NULL; + char copy[strlen(rawstr) + 1]; + strlcpy(copy, rawstr, sizeof(copy)); + char *context = NULL; + char *token = strtok_r(copy, ",", &context); + uint8_t num_tokens = 0; + uint8_t dir = 0; + char *byte_data = NULL; + + while (token != NULL) { + if (num_tokens > 1) + return -1; + + while (*token != '\0' && isblank(*token)) { + token++; + } + if (strlen(token) == 0) { + goto next; + } + + num_tokens++; + + if (dir == 0 && num_tokens == 1) { + if (strcmp(token, "toserver") == 0) { + dir = DETECT_FLOW_TOSERVER; + } else if (strcmp(token, "toclient") == 0) { + dir = DETECT_FLOW_TOCLIENT; + } else { + SCLogError("Invalid direction given: %s", token); + return -1; + } + } + + if (dir && num_tokens == 2) { + byte_data = token; + } + + next: + token = strtok_r(NULL, ",", &context); + } + + DetectU64Data *du64 = DetectU64Parse(byte_data); if (du64 == NULL) return -1; - - if (SigMatchAppendSMToList(de_ctx, s, DETECT_FLOW_BYTES_TO_SERVER, (SigMatchCtx *)du64, - DETECT_SM_LIST_MATCH) == NULL) { - DetectFlowBytesToServerFree(de_ctx, du64); + df = SCCalloc(1, sizeof(DetectFlowBytes)); + if (df == NULL) { + rs_detect_u64_free(du64); + return -1; + } + df->dir = dir; + df->byte_data = du64; + if (SigMatchAppendSMToList( + de_ctx, s, DETECT_FLOW_BYTES, (SigMatchCtx *)df, DETECT_SM_LIST_MATCH) == NULL) { + DetectFlowBytesFree(de_ctx, df); return -1; } s->flags |= SIG_FLAG_REQUIRE_PACKET; @@ -248,13 +402,34 @@ static int DetectFlowBytesToServerSetup(DetectEngineCtx *de_ctx, Signature *s, c return 0; } +void DetectFlowBytesRegister(void) +{ + sigmatch_table[DETECT_FLOW_BYTES].name = "flow.bytes"; + sigmatch_table[DETECT_FLOW_BYTES].desc = "match number of bytes in a flow"; + sigmatch_table[DETECT_FLOW_BYTES].url = "/rules/flow-keywords.html#flow-bytes"; + sigmatch_table[DETECT_FLOW_BYTES].Match = DetectFlowBytesMatch; + sigmatch_table[DETECT_FLOW_BYTES].Setup = DetectFlowBytesSetup; + sigmatch_table[DETECT_FLOW_BYTES].Free = DetectFlowBytesFree; +} + void DetectFlowBytesToServerRegister(void) { sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].name = "flow.bytes_toserver"; - sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].desc = "match flow number of bytes to server"; - sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].url = - "/rules/flow-keywords.html#flow-bytes_toserver"; - sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].Match = DetectFlowBytesToServerMatch; + sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].desc = + "match number of bytes in a flow in to server dir"; + sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].url = "/rules/flow-keywords.html#flow-bytes"; + sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].Match = DetectFlowBytesMatch; sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].Setup = DetectFlowBytesToServerSetup; - sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].Free = DetectFlowBytesToServerFree; + sigmatch_table[DETECT_FLOW_BYTES_TO_SERVER].Free = DetectFlowBytesFree; +} + +void DetectFlowBytesToClientRegister(void) +{ + sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].name = "flow.bytes_toclient"; + sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].desc = + "match number of bytes in a flow in to client dir"; + sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].url = "/rules/flow-keywords.html#flow-bytes"; + sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].Match = DetectFlowBytesMatch; + sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].Setup = DetectFlowBytesToClientSetup; + sigmatch_table[DETECT_FLOW_BYTES_TO_CLIENT].Free = DetectFlowBytesFree; } diff --git a/src/detect-flow-pkts.h b/src/detect-flow-pkts.h index da1e0eb5a6aa..076e6ddd7b67 100644 --- a/src/detect-flow-pkts.h +++ b/src/detect-flow-pkts.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Open Information Security Foundation +/* Copyright (C) 2023-2025 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -18,9 +18,11 @@ #ifndef SURICATA_DETECT_FLOW_PKTS_H #define SURICATA_DETECT_FLOW_PKTS_H -void DetectFlowPktsToClientRegister(void); +void DetectFlowPktsRegister(void); void DetectFlowPktsToServerRegister(void); -void DetectFlowBytesToClientRegister(void); +void DetectFlowPktsToClientRegister(void); +void DetectFlowBytesRegister(void); void DetectFlowBytesToServerRegister(void); +void DetectFlowBytesToClientRegister(void); #endif /* SURICATA_DETECT_FLOW_PKTS_H */