@ -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 DetectFlowPkts Free( 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 DetectFlowPktsTo Server Setup( 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 PrefilterPacketFlowPkts ToServer Match(
static void PrefilterPacketFlowPkts Match(
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 PrefilterSetupFlowPkts ToServer ( 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 , PrefilterPacketU32 Compare,
PrefilterPacketFlowPkts ToServer Match) ;
return PrefilterSetupPacketHeader ( de_ctx , sgh , DETECT_FLOW_PKTS , SIG_MASK_REQUIRE_FLOW ,
PrefilterPacketFlowPktsSet, PrefilterPacketFlowPkts Compare,
PrefilterPacketFlowPkts Match) ;
}
static bool PrefilterFlowPkts ToServer IsPrefilterable( const Signature * s )
static bool PrefilterFlowPkts IsPrefilterable( 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 DetectFlowBytes Match(
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 DetectFlowBytes Free( 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 DetectFlowBytesTo Server Setup( 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 DetectFlowBytes Setup( 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 = DetectFlowBytes Match;
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 ;
}