diff --git a/doc/userguide/rules/flow-keywords.rst b/doc/userguide/rules/flow-keywords.rst index 2ab6128e7207..3ba6bbe06a9a 100644 --- a/doc/userguide/rules/flow-keywords.rst +++ b/doc/userguide/rules/flow-keywords.rst @@ -331,6 +331,8 @@ following directions: * toserver +* either + Syntax:: flow.pkts:,[op] @@ -339,6 +341,7 @@ The number of packets can be matched exactly, or compared using the _op_ setting flow.pkts:toclient,3 # exactly 3 flow.pkts:toserver,<3 # smaller than 3 + flow.pkts:either,>=2 # greater than or equal to 2 Signature example:: @@ -361,6 +364,8 @@ following directions: * toserver +* either + Syntax:: flow.bytes:,[op] @@ -369,6 +374,7 @@ The number of bytes can be matched exactly, or compared using the _op_ setting:: flow.bytes:toclient,3 # exactly 3 flow.bytes:toserver,<3 # smaller than 3 + flow.bytes:either,>=2 # greater than or equal to 2 Signature example:: diff --git a/src/detect-flow-pkts.c b/src/detect-flow-pkts.c index 842c78c993d4..f602260df748 100644 --- a/src/detect-flow-pkts.c +++ b/src/detect-flow-pkts.c @@ -26,6 +26,7 @@ enum FlowDirection { DETECT_FLOW_TOSERVER = 1, DETECT_FLOW_TOCLIENT, + DETECT_FLOW_TOEITHER, }; typedef struct DetectFlow_ { @@ -46,6 +47,11 @@ static int DetectFlowPktsMatch( return DetectU32Match(p->flow->todstpktcnt, df->pkt_data); } else if (df->dir == DETECT_FLOW_TOCLIENT) { return DetectU32Match(p->flow->tosrcpktcnt, df->pkt_data); + } else if (df->dir == DETECT_FLOW_TOEITHER) { + if (DetectU32Match(p->flow->tosrcpktcnt, df->pkt_data)) { + return 1; + } + return DetectU32Match(p->flow->todstpktcnt, df->pkt_data); } return 0; } @@ -133,6 +139,8 @@ static int DetectFlowPktsSetup(DetectEngineCtx *de_ctx, Signature *s, const char dir = DETECT_FLOW_TOSERVER; } else if (strcmp(token, "toclient") == 0) { dir = DETECT_FLOW_TOCLIENT; + } else if (strcmp(token, "either") == 0) { + dir = DETECT_FLOW_TOEITHER; } if (dir) { @@ -267,6 +275,11 @@ static int DetectFlowBytesMatch( return DetectU64Match(p->flow->todstbytecnt, df->byte_data); } else if (df->dir == DETECT_FLOW_TOCLIENT) { return DetectU64Match(p->flow->tosrcbytecnt, df->byte_data); + } else if (df->dir == DETECT_FLOW_TOEITHER) { + if (DetectU64Match(p->flow->tosrcbytecnt, df->byte_data)) { + return 1; + } + return DetectU64Match(p->flow->todstbytecnt, df->byte_data); } return 0; } @@ -354,6 +367,8 @@ static int DetectFlowBytesSetup(DetectEngineCtx *de_ctx, Signature *s, const cha dir = DETECT_FLOW_TOSERVER; } else if (strcmp(token, "toclient") == 0) { dir = DETECT_FLOW_TOCLIENT; + } else if (strcmp(token, "either") == 0) { + dir = DETECT_FLOW_TOEITHER; } if (dir) {