From d94aea8331e2d853b56421d9e5d280f17b1ea989 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Thu, 16 Oct 2025 11:15:35 +0200 Subject: [PATCH] detect: tcp.window is now a generic integer Ticket: 7889 --- doc/userguide/rules/header-keywords.rst | 2 + src/detect-engine-analyzer.c | 5 +- src/detect-tcp-window.c | 130 ++++-------------------- src/detect-tcp-window.h | 5 - 4 files changed, 21 insertions(+), 121 deletions(-) diff --git a/doc/userguide/rules/header-keywords.rst b/doc/userguide/rules/header-keywords.rst index 782b10023f..4d52b347b8 100644 --- a/doc/userguide/rules/header-keywords.rst +++ b/doc/userguide/rules/header-keywords.rst @@ -438,6 +438,8 @@ This mechanism is used to prevent the receiver from being overflowed by data. The value of the window size is limited and can be 2 to 65.535 bytes. To make more use of your bandwidth you can use a bigger TCP-window. +window uses an :ref:`unsigned 16-bits integer `. + The format of the window keyword is:: window:[!]; diff --git a/src/detect-engine-analyzer.c b/src/detect-engine-analyzer.c index 7952a24697..bda6fbfcc4 100644 --- a/src/detect-engine-analyzer.c +++ b/src/detect-engine-analyzer.c @@ -967,10 +967,9 @@ static void DumpMatches(RuleAnalyzer *ctx, SCJsonBuilder *js, const SigMatchData break; } case DETECT_WINDOW: { - const DetectWindowData *wd = (const DetectWindowData *)smd->ctx; + const DetectU16Data *cd = (const DetectU16Data *)smd->ctx; SCJbOpenObject(js, "window"); - SCJbSetUint(js, "size", wd->size); - SCJbSetBool(js, "negated", wd->negated); + SCDetectU16ToJson(js, cd); SCJbClose(js); break; } diff --git a/src/detect-tcp-window.c b/src/detect-tcp-window.c index 2571842ce9..991de5d695 100644 --- a/src/detect-tcp-window.c +++ b/src/detect-tcp-window.c @@ -28,6 +28,7 @@ #include "detect.h" #include "detect-parse.h" +#include "detect-engine-uint.h" #include "detect-tcp-window.h" #include "flow.h" @@ -38,13 +39,6 @@ #include "util-unittest-helper.h" #include "util-byte.h" -/** - * \brief Regex for parsing our window option - */ -#define PARSE_REGEX "^\\s*([!])?\\s*([0-9]{1,9}+)\\s*$" - -static DetectParseRegex parse_regex; - static int DetectWindowMatch(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *); static int DetectWindowSetup(DetectEngineCtx *, Signature *, const char *); @@ -65,10 +59,10 @@ void DetectWindowRegister (void) sigmatch_table[DETECT_WINDOW].Match = DetectWindowMatch; sigmatch_table[DETECT_WINDOW].Setup = DetectWindowSetup; sigmatch_table[DETECT_WINDOW].Free = DetectWindowFree; + sigmatch_table[DETECT_WINDOW].flags = SIGMATCH_INFO_UINT16; #ifdef UNITTESTS sigmatch_table[DETECT_WINDOW].RegisterTests = DetectWindowRegisterTests; #endif - DetectSetupParseRegexes(PARSE_REGEX, &parse_regex); } /** @@ -85,7 +79,7 @@ void DetectWindowRegister (void) static int DetectWindowMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx) { - const DetectWindowData *wd = (const DetectWindowData *)ctx; + const DetectU16Data *wd = (const DetectU16Data *)ctx; DEBUG_VALIDATE_BUG_ON(PKT_IS_PSEUDOPKT(p)); if (!(PacketIsTCP(p)) || wd == NULL) { @@ -93,81 +87,7 @@ static int DetectWindowMatch(DetectEngineThreadCtx *det_ctx, Packet *p, } const uint16_t window = TCP_GET_RAW_WINDOW(PacketGetTCP(p)); - if ((!wd->negated && wd->size == window) || (wd->negated && wd->size != window)) { - return 1; - } - - return 0; -} - -/** - * \brief This function is used to parse window options passed via window: keyword - * - * \param de_ctx Pointer to the detection engine context - * \param windowstr Pointer to the user provided window options (negation! and size) - * - * \retval wd pointer to DetectWindowData on success - * \retval NULL on failure - */ -static DetectWindowData *DetectWindowParse(DetectEngineCtx *de_ctx, const char *windowstr) -{ - DetectWindowData *wd = NULL; - int res = 0; - size_t pcre2len; - - pcre2_match_data *match = NULL; - int ret = DetectParsePcreExec(&parse_regex, &match, windowstr, 0, 0); - if (ret < 1 || ret > 3) { - SCLogError("pcre_exec parse error, ret %" PRId32 ", string %s", ret, windowstr); - goto error; - } - - wd = SCMalloc(sizeof(DetectWindowData)); - if (unlikely(wd == NULL)) - goto error; - - if (ret > 1) { - char copy_str[128] = ""; - pcre2len = sizeof(copy_str); - res = SC_Pcre2SubstringCopy(match, 1, (PCRE2_UCHAR8 *)copy_str, &pcre2len); - if (res < 0) { - SCLogError("pcre2_substring_copy_bynumber failed"); - goto error; - } - - /* Detect if it's negated */ - if (copy_str[0] == '!') - wd->negated = 1; - else - wd->negated = 0; - - if (ret > 2) { - pcre2len = sizeof(copy_str); - res = pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)copy_str, &pcre2len); - if (res < 0) { - SCLogError("pcre2_substring_copy_bynumber failed"); - goto error; - } - - /* Get the window size if it's a valid value (in packets, we - * should alert if this doesn't happen from decode) */ - if (StringParseUint16(&wd->size, 10, 0, copy_str) < 0) { - goto error; - } - } - } - - pcre2_match_data_free(match); - return wd; - -error: - if (match) { - pcre2_match_data_free(match); - } - if (wd != NULL) - DetectWindowFree(de_ctx, wd); - return NULL; - + return DetectU16Match(window, wd); } /** @@ -182,27 +102,20 @@ error: */ static int DetectWindowSetup (DetectEngineCtx *de_ctx, Signature *s, const char *windowstr) { - DetectWindowData *wd = NULL; - - wd = DetectWindowParse(de_ctx, windowstr); - if (wd == NULL) goto error; + DetectU16Data *wd = SCDetectU16Parse(windowstr); + if (wd == NULL) + return -1; /* Okay so far so good, lets get this into a SigMatch * and put it in the Signature. */ if (SCSigMatchAppendSMToList( de_ctx, s, DETECT_WINDOW, (SigMatchCtx *)wd, DETECT_SM_LIST_MATCH) == NULL) { - goto error; + DetectWindowFree(de_ctx, wd); + return -1; } s->flags |= SIG_FLAG_REQUIRE_PACKET; - return 0; - -error: - if (wd != NULL) - DetectWindowFree(de_ctx, wd); - return -1; - } /** @@ -212,8 +125,7 @@ error: */ void DetectWindowFree(DetectEngineCtx *de_ctx, void *ptr) { - DetectWindowData *wd = (DetectWindowData *)ptr; - SCFree(wd); + SCDetectU16Free(ptr); } #ifdef UNITTESTS /* UNITTESTS */ @@ -224,10 +136,9 @@ void DetectWindowFree(DetectEngineCtx *de_ctx, void *ptr) */ static int DetectWindowTestParse01 (void) { - DetectWindowData *wd = NULL; - wd = DetectWindowParse(NULL, "35402"); + DetectU16Data *wd = SCDetectU16Parse("35402"); FAIL_IF_NULL(wd); - FAIL_IF_NOT(wd->size == 35402); + FAIL_IF_NOT(wd->arg1 == 35402); DetectWindowFree(NULL, wd); PASS; @@ -238,11 +149,10 @@ static int DetectWindowTestParse01 (void) */ static int DetectWindowTestParse02 (void) { - DetectWindowData *wd = NULL; - wd = DetectWindowParse(NULL, "!35402"); + DetectU16Data *wd = SCDetectU16Parse("!35402"); FAIL_IF_NULL(wd); - FAIL_IF_NOT(wd->negated == 1); - FAIL_IF_NOT(wd->size == 35402); + FAIL_IF_NOT(wd->mode == DetectUintModeNe); + FAIL_IF_NOT(wd->arg1 == 35402); DetectWindowFree(NULL, wd); PASS; @@ -253,11 +163,8 @@ static int DetectWindowTestParse02 (void) */ static int DetectWindowTestParse03 (void) { - DetectWindowData *wd = NULL; - wd = DetectWindowParse(NULL, ""); + DetectU16Data *wd = SCDetectU16Parse(""); FAIL_IF_NOT_NULL(wd); - - DetectWindowFree(NULL, wd); PASS; } @@ -266,11 +173,8 @@ static int DetectWindowTestParse03 (void) */ static int DetectWindowTestParse04 (void) { - DetectWindowData *wd = NULL; - wd = DetectWindowParse(NULL, "1235402"); + DetectU16Data *wd = SCDetectU16Parse("1235402"); FAIL_IF_NOT_NULL(wd); - - DetectWindowFree(NULL, wd); PASS; } diff --git a/src/detect-tcp-window.h b/src/detect-tcp-window.h index 7178f5ea79..a53cd26e6a 100644 --- a/src/detect-tcp-window.h +++ b/src/detect-tcp-window.h @@ -18,11 +18,6 @@ #ifndef SURICATA_DETECT_WINDOW_H #define SURICATA_DETECT_WINDOW_H -typedef struct DetectWindowData_ { - uint8_t negated; /** negated? 1=True : 0=False */ - uint16_t size; /** window size to match */ -} DetectWindowData; - /* prototypes */ void DetectWindowRegister (void);