From 7a8eb28caeb232d321b6e42c9fa2786f7b06d6b0 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Thu, 16 Oct 2025 10:39:24 +0200 Subject: [PATCH] detect: id is now a generic integer Ticket: 7889 --- doc/userguide/rules/header-keywords.rst | 2 + src/detect-id.c | 126 ++++-------------------- src/detect-id.h | 7 -- 3 files changed, 20 insertions(+), 115 deletions(-) diff --git a/doc/userguide/rules/header-keywords.rst b/doc/userguide/rules/header-keywords.rst index b940372768..117a8f391d 100644 --- a/doc/userguide/rules/header-keywords.rst +++ b/doc/userguide/rules/header-keywords.rst @@ -153,6 +153,8 @@ this way, the receiver of the packet knows which fragments belong to the same packet. (IP ID does not take care of the order, in that case offset is used. It clarifies the order of the fragments.) +id uses an :ref:`unsigned 16-bits integer `. + Format of id:: id:; diff --git a/src/detect-id.c b/src/detect-id.c index fd10300f55..82a8bf21f8 100644 --- a/src/detect-id.c +++ b/src/detect-id.c @@ -31,6 +31,7 @@ #include "detect-engine.h" #include "detect-engine-mpm.h" #include "detect-engine-prefilter-common.h" +#include "detect-engine-uint.h" #include "detect-id.h" #include "flow.h" @@ -44,9 +45,6 @@ /** * \brief Regex for parsing "id" option, matching number or "number" */ -#define PARSE_REGEX "^\\s*([0-9]{1,5}|\"[0-9]{1,5}\")\\s*$" - -static DetectParseRegex parse_regex; static int DetectIdMatch (DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *); @@ -70,13 +68,12 @@ void DetectIdRegister (void) sigmatch_table[DETECT_ID].Match = DetectIdMatch; sigmatch_table[DETECT_ID].Setup = DetectIdSetup; sigmatch_table[DETECT_ID].Free = DetectIdFree; + sigmatch_table[DETECT_ID].flags = SIGMATCH_INFO_UINT16; #ifdef UNITTESTS sigmatch_table[DETECT_ID].RegisterTests = DetectIdRegisterTests; #endif sigmatch_table[DETECT_ID].SupportsPrefilter = PrefilterIdIsPrefilterable; sigmatch_table[DETECT_ID].SetupPrefilter = PrefilterSetupId; - - DetectSetupParseRegexes(PARSE_REGEX, &parse_regex); } /** @@ -94,7 +91,7 @@ static int DetectIdMatch (DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx) { DEBUG_VALIDATE_BUG_ON(PKT_IS_PSEUDOPKT(p)); - const DetectIdData *id_d = (const DetectIdData *)ctx; + const DetectU16Data *id_d = (const DetectU16Data *)ctx; /** * To match a ipv4 packet with a "id" rule @@ -104,79 +101,7 @@ static int DetectIdMatch (DetectEngineThreadCtx *det_ctx, Packet *p, } const IPV4Hdr *ip4h = PacketGetIPv4(p); - if (id_d->id == IPV4_GET_RAW_IPID(ip4h)) { - SCLogDebug("IPV4 Proto and matched with ip_id: %u.\n", - id_d->id); - return 1; - } - - return 0; -} - -/** - * \brief This function is used to parse IPV4 ip_id passed via keyword: "id" - * - * \param idstr Pointer to the user provided id option - * - * \retval id_d pointer to DetectIdData on success - * \retval NULL on failure - */ -static DetectIdData *DetectIdParse (const char *idstr) -{ - uint16_t temp; - DetectIdData *id_d = NULL; - int res = 0; - size_t pcre2len; - pcre2_match_data *match = NULL; - - int ret = DetectParsePcreExec(&parse_regex, &match, idstr, 0, 0); - - if (ret < 1 || ret > 3) { - SCLogError("invalid id option '%s'. The id option " - "value must be in the range %u - %u", - idstr, DETECT_IPID_MIN, DETECT_IPID_MAX); - goto error; - } - - char copy_str[128] = ""; - char *tmp_str; - pcre2len = sizeof(copy_str); - res = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)copy_str, &pcre2len); - if (res < 0) { - SCLogError("pcre2_substring_copy_bynumber failed"); - goto error; - } - tmp_str = copy_str; - - /* Let's see if we need to scape "'s */ - if (tmp_str[0] == '"') - { - tmp_str[strlen(tmp_str) - 1] = '\0'; - tmp_str += 1; - } - - /* ok, fill the id data */ - if (StringParseUint16(&temp, 10, 0, (const char *)tmp_str) <= 0) { - SCLogError("invalid id option '%s'", tmp_str); - goto error; - } - - /* We have a correct id option */ - id_d = SCMalloc(sizeof(DetectIdData)); - if (unlikely(id_d == NULL)) - goto error; - - id_d->id = temp; - - SCLogDebug("detect-id: will look for ip_id: %u\n", id_d->id); - pcre2_match_data_free(match); - return id_d; - -error: - if (match) { - pcre2_match_data_free(match); - } - return NULL; + return DetectU16Match(IPV4_GET_RAW_IPID(ip4h), id_d); } /** @@ -192,9 +117,7 @@ error: */ int DetectIdSetup (DetectEngineCtx *de_ctx, Signature *s, const char *idstr) { - DetectIdData *id_d = NULL; - - id_d = DetectIdParse(idstr); + DetectU16Data *id_d = SCDetectU16UnquoteParse(idstr); if (id_d == NULL) return -1; @@ -216,8 +139,7 @@ int DetectIdSetup (DetectEngineCtx *de_ctx, Signature *s, const char *idstr) */ void DetectIdFree(DetectEngineCtx *de_ctx, void *ptr) { - DetectIdData *id_d = (DetectIdData *)ptr; - SCFree(id_d); + SCDetectU16Free(ptr); } /* prefilter code */ @@ -237,32 +159,20 @@ PrefilterPacketIdMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pe return; const IPV4Hdr *ip4h = PacketGetIPv4(p); - if (ctx->v1.u16[0] == IPV4_GET_RAW_IPID(ip4h)) { + DetectU16Data du16; + du16.mode = ctx->v1.u8[0]; + du16.arg1 = ctx->v1.u16[1]; + du16.arg2 = ctx->v1.u16[2]; + if (DetectU16Match(IPV4_GET_RAW_IPID(ip4h), &du16)) { SCLogDebug("packet matches IP id %u", ctx->v1.u16[0]); PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt); } } -static void -PrefilterPacketIdSet(PrefilterPacketHeaderValue *v, void *smctx) -{ - const DetectIdData *a = smctx; - v->u16[0] = a->id; -} - -static bool -PrefilterPacketIdCompare(PrefilterPacketHeaderValue v, void *smctx) -{ - const DetectIdData *a = smctx; - if (v.u16[0] == a->id) - return true; - return false; -} - static int PrefilterSetupId(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_ID, SIG_MASK_REQUIRE_REAL_PKT, - PrefilterPacketIdSet, PrefilterPacketIdCompare, PrefilterPacketIdMatch); + PrefilterPacketU16Set, PrefilterPacketU16Compare, PrefilterPacketIdMatch); } static bool PrefilterIdIsPrefilterable(const Signature *s) @@ -285,10 +195,10 @@ static bool PrefilterIdIsPrefilterable(const Signature *s) */ static int DetectIdTestParse01 (void) { - DetectIdData *id_d = DetectIdParse(" 35402 "); + DetectU16Data *id_d = SCDetectU16UnquoteParse(" 35402 "); FAIL_IF_NULL(id_d); - FAIL_IF_NOT(id_d->id == 35402); + FAIL_IF_NOT(id_d->arg1 == 35402); DetectIdFree(NULL, id_d); @@ -302,7 +212,7 @@ static int DetectIdTestParse01 (void) */ static int DetectIdTestParse02 (void) { - DetectIdData *id_d = DetectIdParse("65537"); + DetectU16Data *id_d = SCDetectU16UnquoteParse("65537"); FAIL_IF_NOT_NULL(id_d); @@ -316,7 +226,7 @@ static int DetectIdTestParse02 (void) */ static int DetectIdTestParse03 (void) { - DetectIdData *id_d = DetectIdParse("12what?"); + DetectU16Data *id_d = SCDetectU16UnquoteParse("12what?"); FAIL_IF_NOT_NULL(id_d); @@ -330,10 +240,10 @@ static int DetectIdTestParse03 (void) static int DetectIdTestParse04 (void) { /* yep, look if we trim blank spaces correctly and ignore "'s */ - DetectIdData *id_d = DetectIdParse(" \"35402\" "); + DetectU16Data *id_d = SCDetectU16UnquoteParse(" \"35402\" "); FAIL_IF_NULL(id_d); - FAIL_IF_NOT(id_d->id == 35402); + FAIL_IF_NOT(id_d->arg1 == 35402); DetectIdFree(NULL, id_d); diff --git a/src/detect-id.h b/src/detect-id.h index 9fb9156670..771dc2c2b7 100644 --- a/src/detect-id.h +++ b/src/detect-id.h @@ -24,13 +24,6 @@ #ifndef SURICATA_DETECT_ID_H #define SURICATA_DETECT_ID_H -#define DETECT_IPID_MIN 0 -#define DETECT_IPID_MAX 65536 - -typedef struct DetectIdData_ { - uint16_t id; /** ip->id to match */ -} DetectIdData; - /* prototypes */ void DetectIdRegister (void);