Understanding the Initialization Process for Suricata: From Atomic Variables to Detection Engine

Initial Module

Initialization Process

  1. Initialize the Suricata instance to maintain the current state, flags, and context environment of the program. This instance is typically passed as a parameter to the sub-functions of various modules.
memset(suri, 0x00, sizeof(*suri));
// pointer to argv[0] 
suri->progname = progname;
// Operating mode
suri->run_mode = RUNMODE_UNKNOWN;
memset(suri->pcap_dev, 0, sizeof(suri->pcap_dev));
// Signature file
suri->sig_file = NULL;
suri->sig_file_exclusive = FALSE;
suri->pid_filename = NULL;
// Regular expression argument
suri->regex_arg = NULL;
// Delayed detection switch
suri->delayed_detect = 0;
// Daemon
suri->daemon = 0;
// Offline mode
suri->offline = 0;
// Verbose mode
suri->verbose = 0;
/* use -1 as unknown */
suri->checksum_validation = -1;
// Disable detection
g_detect_disabled = suri->disabled_detect = 1;

2. Initialize atomic variable engine_stage to record the current operating stage of the program: SURICATA_INIT, SURICATA_RUNTIME, SURICATA_FINALIZE

suricata_context initialization
// Log message output to console or file and level 
suricata_context.SCLogMessage = SCLogMessage;
// File io-related functions
suricata_context.FileOpenFileWithId = FileOpenFileWithId;
suricata_context.FileCloseFileById = FileCloseFileById;
suricata_context.FileAppendDataById = FileAppendDataById;
suricata_context.FileAppendGAPById = FileAppendGAPById;
suricata_context.FileContainerRecycle = FileContainerRecycle;
suricata_context.FilePrune = FilePrune;
suricata_context.FileSetTx = FileContainerSetTx;

3. Initialize the logging module using environment variables or default values

op_iface log output interface: console or file or syslog
File pointer
File lock
Log format and level
op_filter_regex filters log output by matching filenames with this regex

4. Set the current main thread name to “Suricata-Main”. When debugging with gdb, the thread names can be observed using the info threads

5. Initialize the ParserSize module and perform regular expression pre-compilation for parsing size parameters like “10Mb”

#define PARSE_REGEX "^\\s*(\\d+(?:.\\d+)?)\\s*([a-zA-Z]{2})?\\s*$"

6. Register various running modes. Suricata encapsulates the concept of “running mode”, which is stored in the runmodes array as RunModes runmodes[RUNMODE_USER_MAX]

enum RunModes {
 RUNMODE_UNKNOWN = 0,
 RUNMODE_PCAP_DEV,
 RUNMODE_PCAP_FILE,
 RUNMODE_PFRING,
 RUNMODE_NFQ,
 RUNMODE_NFLOG,
 RUNMODE_IPFW,
 RUNMODE_ERF_FILE,
 RUNMODE_DAG,
 RUNMODE_AFP_DEV,
 RUNMODE_NETMAP,
 RUNMODE_UNITTEST,
 RUNMODE_NAPATECH,
 RUNMODE_UNIX_SOCKET,
 RUNMODE_WINDIVERT,
 RUNMODE_PLUGIN,
    }
​
typedef struct RunModes_ {
 int cnt;
 RunMode *runmodes;
} RunModes;

7. Register various operating modes Using IDS Pcap mode as an example, it consists of three sub-modes implemented by reallocating space: IDS Pcap Mode = RunModeIdsPcapSingle (single-threaded pcap processing) + RunModeIdsPcapAutoFp (default sub-mode) + RunModeIdsPcapWorkers (Workers version of the PCAP LIVE processing). After subsequent initialization stages the specific operating mode is determined, these three registered initialization functions will be called to further configure the operating environment for that mode

/*
Current sub-mode: RunMode *mode = &runmodes[runmode].runmodes[runmodes[runmode].cnt];
*/
RunModeIdsPcapRegister();
RunModeFilePcapRegister();
RunModeIdsPfringRegister();
RunModeIpsNFQRegister();
RunModeIpsIPFWRegister();
RunModeErfFileRegister();
RunModeErfDagRegister();
RunModeNapatechRegister();
RunModeIdsAFPRegister();
RunModeIdsNetmapRegister();
RunModeIdsNflogRegister();
RunModeUnixSocketRegister();
RunModeIpsWinDivertRegister();

8. Initialize the configuration module, create the root node of the configuration tree by calling alloc, to later parse the Suricata.yaml

typedef struct ConfNode_ {
 // filename: fast.log   name:val
 char *name;
 char *val;
 /**< Flag that sets this node's value as final */
 int final;
 // Parent node
 struct ConfNode_ *parent;
 // Head node, next node
 TAILQ_HEAD(, ConfNode_) head;
 TAILQ_ENTRY(ConfNode_) next;
} ConfNode;
​

9. Command line argument parsing

// Monitor device registration
typedef struct LiveDeviceName_ {
 char *dev;  /**< the device (e.g. "eth0") */
 TAILQ_ENTRY(LiveDeviceName_) next;
} LiveDeviceName;
pd = SCCalloc(1, sizeof(LiveDeviceName));
TAILQ_INSERT_TAIL(&pre_live_devices, pd, next);
​
g_engine_mode defaults to IDS, IPS can drop packets (--simulate-ips)
EngineModeSetIPS();
​
Parse short command line arguments and add them to the configuration tree: ConfGetNodeOrCreate + setVal
​
The "-v" option can be used multiple times, each instance elevating the current log level by one
suri->verbose++;
Set the global run_mode variable, validate if the daemon mode is compatible with the run_mode (neither Pcap file mode nor unit test mode can operate with daemon enabled)

10. GlobalsInitPreConfig
Acquire the current time using a spin lock, and set the time zone (by calling tzset()). Maintain a multi-mode quick match list sorted by priority, using SC_Malloc for memory allocation, and pre-compile regex for matching threshold keywords.

11. LoadYamlConfig
Read the YAML format configuration file using LoadYamlConfig. YAML parsing is completed through the libyaml library, with the parsed results stored in the configuration tree (see conf.c)

12. SCLogLoadConfig
Initialize some global configurations of the log module based on the previously transformed configuration tree

SCLogDebug("sc_log_global_log_level: %d", sc_log_global_log_level);
SCLogDebug("sc_lc->log_format: %s", sc_log_config->log_format); 
SCLogDebug("SCLogSetOPFilter: filter: %s", sc_log_config->op_filter);
typedef struct SCLogConfig_ 
{    
 char *startup_message;    
 SCLogLevel log_level;    
 char *log_format;      
 char *op_filter;    
 /* compiled pcre filter expression */     
 pcre *op_filter_regex;     
 pcre_extra *op_filter_regex_study;     
 /* op ifaces used */    
 SCLogOPIfaceCtx *op_ifaces;     
 /* number of op ifaces */    
 uint8_t op_ifaces_cnt; 
} SCLogConfig;

13. PostConfLoadedSetup
After configuration becomes effective, module setup

  • MpmTableSetup: Set up multi-pattern matching table. Each entry in this table implements a specific multi-pattern matching algorithm (like WuManber, AC), including ac, ac-ks, ac-bs, hs
  • SpmTableSetup: Set up single-pattern matching table, bm, hs
  typedef struct MpmTableElmt_ {
    const char *name;
    void (*InitCtx)(struct MpmCtx_ *);
    void (*InitThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *);
    void (*DestroyCtx)(struct MpmCtx_ *);
    void (*DestroyThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *);

    /** function pointers for adding patterns to the mpm ctx.
     *
     *  \param mpm_ctx Mpm context to add the pattern to
     *  \param pattern pointer to the pattern
     *  \param pattern_len length of the pattern in bytes
     *  \param offset pattern offset setting
     *  \param depth pattern depth setting
     *  \param pid pattern id
     *  \param sid signature _internal_ id
     *  \param flags pattern flags
     */
    int  (*AddPattern)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, SigIntId, uint8_t);
    int  (*AddPatternNocase)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, SigIntId, uint8_t);
    int  (*Prepare)(struct MpmCtx_ *);
    uint32_t (*Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t);
    void (*PrintCtx)(struct MpmCtx_ *);
    void (*PrintThreadCtx)(struct MpmThreadCtx_ *);
    void (*RegisterUnittests)(void);
    uint8_t flags;
} MpmTableElmt;

extern MpmTableElmt mpm_table[MPM_TABLE_SIZE];

typedef struct MpmCtx_ {
    void *ctx;
    uint8_t mpm_type;

    uint8_t flags;

    uint16_t maxdepth;

    /* unique patterns */
    uint32_t pattern_cnt;

    uint16_t minlen;
    uint16_t maxlen;

    uint32_t memory_cnt;
    uint32_t memory_size;

    uint32_t max_pat_id;

    /* hash used during ctx initialization */
    MpmPattern **init_hash;
} MpmCtx;


typedef struct SCACCtx_ {
    /* pattern arrays.  We need this only during the goto table creation phase */
    MpmPattern **parray;

    /* no of states used by ac */
    uint32_t state_count;

    uint32_t pattern_id_bitarray_size;

    /* the all important memory hungry state_table */
    SC_AC_STATE_TYPE_U16 (*state_table_u16)[256];
    /* the all important memory hungry state_table */
    SC_AC_STATE_TYPE_U32 (*state_table_u32)[256];

    /* goto_table, failure table, and output table.  Needed to create state_table.
     * Will be freed, once we have created the state_table */
    int32_t (*goto_table)[256];
    int32_t *failure_table;
    SCACOutputTable *output_table;
    SCACPatternList *pid_pat_list;

    /* the size of each state */
    uint32_t single_state_size;

    uint32_t allocated_state_count;

} SCACCtx;
  • Initialize storage-related settings like tag keywords, which are dependent on rules and appear infrequently, allocate memory accordingly
STORAGE_HOST, STORAGE_FLOW, STORAGE_IPPAIR, STORAGE_DEVICE 
memset(&storage_max_id, 0x00, sizeof(storage_max_id)); 
storage_list = NULL; 
storage_map = NULL; 
storage_registration_closed = 0;  
  • Register RegisterFlowBypassInfo for bypass traffic offloading in STORAGE_FLOW
  • Register protocol parsers
AppLayerParserProtoCtx ctxs[FLOW_PROTO_MAX][ALPROTO_MAX];
enum {
    FLOW_PROTO_TCP = 0,
    FLOW_PROTO_UDP,
    FLOW_PROTO_ICMP,
    FLOW_PROTO_DEFAULT,

    /* should be last */
    FLOW_PROTO_MAX,
};
enum AppProtoEnum {
    ALPROTO_UNKNOWN = 0,
    ALPROTO_HTTP,
    ALPROTO_FTP,
    ALPROTO_SMTP,
    ALPROTO_TLS, /* SSLv2, SSLv3 & TLSv1 */
    ALPROTO_SSH,
    ALPROTO_IMAP,
    ALPROTO_JABBER,
    ALPROTO_SMB,
    ALPROTO_DCERPC,
    ALPROTO_IRC,

    ALPROTO_DNS,
    ALPROTO_MODBUS,
    ALPROTO_ENIP,
    ALPROTO_DNP3,
    ALPROTO_NFS,
    ALPROTO_NTP,
    ALPROTO_FTPDATA,
    ALPROTO_TFTP,
    ALPROTO_IKEV2,
    ALPROTO_KRB5,
    ALPROTO_DHCP,
    ALPROTO_SNMP,
    ALPROTO_SIP,
    ALPROTO_RFB,
    ALPROTO_MQTT,
    ALPROTO_TEMPLATE,
    ALPROTO_TEMPLATE_RUST,
    ALPROTO_RDP,
    ALPROTO_HTTP2,

    /* used by the probing parser when alproto detection fails
     * permanently for that particular stream */
    ALPROTO_FAILED,
#ifdef UNITTESTS
    ALPROTO_TEST,
#endif /* UNITESTS */
    /* keep last */
    ALPROTO_MAX,
};

/**
 * \brief App layer protocol parser context.
 */
typedef struct AppLayerParserProtoCtx_
{
    /* 0 - to_server, 1 - to_client. */
    AppLayerParserFPtr Parser[2];
    bool logger;
    uint32_t logger_bits;   /**< registered loggers for this proto */

    void *(*StateAlloc)(void *, AppProto);
    void (*StateFree)(void *);
    void (*StateTransactionFree)(void *, uint64_t);
    void *(*LocalStorageAlloc)(void);
    void (*LocalStorageFree)(void *);

    void (*Truncate)(void *, uint8_t);
    FileContainer *(*StateGetFiles)(void *, uint8_t);
    AppLayerDecoderEvents *(*StateGetEvents)(void *);

    int (*StateGetProgress)(void *alstate, uint8_t direction);
    uint64_t (*StateGetTxCnt)(void *alstate);
    void *(*StateGetTx)(void *alstate, uint64_t tx_id);
    AppLayerGetTxIteratorFunc StateGetTxIterator;
    int (*StateGetProgressCompletionStatus)(uint8_t direction);
    int (*StateGetEventInfoById)(int event_id, const char **event_name,
                                 AppLayerEventType *event_type);
    int (*StateGetEventInfo)(const char *event_name,
                             int *event_id, AppLayerEventType *event_type);

    DetectEngineState *(*GetTxDetectState)(void *tx);
    int (*SetTxDetectState)(void *tx, DetectEngineState *);

    AppLayerTxData *(*GetTxData)(void *tx);
    bool (*ApplyTxConfig)(void *state, void *tx, int mode, AppLayerTxConfig);

    void (*SetStreamDepthFlag)(void *tx, uint8_t flags);

    /* each app-layer has its own value */
    uint32_t stream_depth;

    /* Indicates the direction the parser is ready to see the data
     * the first time for a flow.  Values accepted -
     * STREAM_TOSERVER, STREAM_TOCLIENT */
    uint8_t first_data_dir;

    /* Option flags such as supporting gaps or not. */
    uint32_t option_flags;
    /* coccinelle: AppLayerParserProtoCtx:option_flags:APP_LAYER_PARSER_OPT_ */

    uint32_t internal_flags;
    /* coccinelle: AppLayerParserProtoCtx:internal_flags:APP_LAYER_PARSER_INT_ */

#ifdef UNITTESTS
    void (*RegisterUnittests)(void);
#endif
} AppLayerParserProtoCtx;

HTTP parser's HTTP state memory
typedef struct HtpState_ {
    /* Connection parser structure for each connection */
    htp_connp_t *connp;
    /* Connection structure for each connection */
    htp_conn_t *conn;
    Flow *f;                /**< Needed to retrieve the original flow when using HTPLib callbacks */
    uint64_t transaction_cnt;
    uint64_t store_tx_id;
    FileContainer *files_ts;
    FileContainer *files_tc;
    const struct HTPCfgRec_ *cfg;
    uint16_t flags;
    uint16_t events;
    uint16_t htp_messages_offset; /**< offset into conn->messages list */
    uint32_t file_track_id;             /**< used to assign file track ids to files */
    uint64_t last_request_data_stamp;
    uint64_t last_response_data_stamp;
} HtpState;

14. SCHInfoLoadFromConfig: Load host OS policy information (host OS strategy) from the configuration file and save all strategy information using a radix tree

15. SigTableSetup: Initialize the detection engine, mainly by registering the rules format supported by the detection engine (which is largely consistent with Snort rules) including keywords like sid, priority, msg, within, distance and others

typedef struct SigTableElmt_ {
    /** Packet match function pointer */
    int (*Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *);

    /** AppLayer TX match function pointer */
    int (*AppLayerTxMatch)(DetectEngineThreadCtx *, Flow *,
            uint8_t flags, void *alstate, void *txv,
            const Signature *, const SigMatchCtx *);

    /** File match function  pointer */
    int (*FileMatch)(DetectEngineThreadCtx *,
        Flow *,                     /**< *LOCKED* flow */
        uint8_t flags, File *, const Signature *, const SigMatchCtx *);

    /** InspectionBuffer transformation callback */
    void (*Transform)(InspectionBuffer *, void *context);
    bool (*TransformValidate)(const uint8_t *content, uint16_t content_len, void *context);

    /** keyword setup function pointer */
    int (*Setup)(DetectEngineCtx *, Signature *, const char *);

    bool (*SupportsPrefilter)(const Signature *s);
    int (*SetupPrefilter)(DetectEngineCtx *de_ctx, struct SigGroupHead_ *sgh);

    void (*Free)(DetectEngineCtx *, void *);
#ifdef UNITTESTS
    void (*RegisterTests)(void);
#endif
    uint16_t flags;
    /* coccinelle: SigTableElmt:flags:SIGMATCH_ */

    /** better keyword to replace the current one */
    uint16_t alternative;

    const char *name;     /**< keyword name alias */
    const char *alias;    /**< name alias */
    const char *desc;
    const char *url;

} SigTableElmt;

16. The Signature Structure

/** \brief Signature container */
typedef struct Signature_ {
    uint32_t flags;
    /* coccinelle: Signature:flags:SIG_FLAG_ */

    AppProto alproto;

    uint16_t dsize_low;
    uint16_t dsize_high;

    SignatureMask mask;
    SigIntId num; /**< signature number, internal id */

    /** inline -- action */
    uint8_t action;
    uint8_t file_flags;

    /** Addresses, ports, and protocol this sig matches on */
    DetectProto proto;

    /** Classification id **/
    uint16_t class_id;

    /** IPv4 match arrays */
    uint16_t addr_dst_match4_cnt;
    uint16_t addr_src_match4_cnt;
    uint16_t addr_dst_match6_cnt;
    uint16_t addr_src_match6_cnt;
    DetectMatchAddressIPv4 *addr_dst_match4;
    DetectMatchAddressIPv4 *addr_src_match4;
    /** IPv6 match arrays */
    DetectMatchAddressIPv6 *addr_dst_match6;
    DetectMatchAddressIPv6 *addr_src_match6;

    uint32_t id;  /**< sid, set by the 'sid' rule keyword */
    uint32_t gid; /**< generator id */
    uint32_t rev;
    int prio;

    /** Port settings for this signature */
    DetectPort *sp, *dp;

#ifdef PROFILING
    uint16_t profiling_id;
#endif

    /** Netblocks and hosts specified at the sid, in CIDR format */
    IPOnlyCIDRItem *CidrSrc, *CidrDst;

    DetectEngineAppInspectionEngine *app_inspect;
    DetectEnginePktInspectionEngine *pkt_inspect;

    /* Matching structures for the built-ins. The others are in
     * their inspect engines. */
    SigMatchData *sm_arrays[DETECT_SM_LIST_MAX];

    /* Memory is still owned by the sm_lists/sm_arrays entry */
    const struct DetectFilestoreData_ *filestore_ctx;

    char *msg;

    /** Classification message */
    char *class_msg;
    /** Reference */
    DetectReference *references;
    /** Metadata */
    DetectMetadataHead *metadata;

    char *sig_str;

    SignatureInitData *init_data;

    /** Pointer to the next sig in the list */
    struct Signature_ *next;
} Signature;

17. TmqhSetup: Tm-queue is a buffer zone for data transmission between various modules (threads)
Initialize queue handlers, a bridge connecting thread modules and data packet queues. There are five types of handlers: simple, nfq, packetpool, flow, and ringbuffer. Each type includes an InHandler and OutHandler, wherein one retrieves packets from the preceding queue and the other places packets into the succeeding queue upon completion.
1) Packetpool
Facilitates enqueue and dequeue operations on the packetpool (ringbuffer) circular queue using the read and write position markers.2) Simple
Execute buffer operations based on FIFO (First In, First Out) principles.

3) Flow
When dequeuing, operations follow FIFO; during enqueuing, packet header information is hashed, and packets with identical hash values are placed into a buffer.

18. RegisterAllModules: Register All Modules
Registers all thread modules supported by Suricata. Taking the pcap-related module as an example, the function TmModuleReceivePcapRegister registers the Pcap capture module, and the function TmModuleDecodePcapRegister registers the Pcap packet decoding module. Registration involves populating all fields of the TmModule structure in the corresponding item in the tmm_modules module array. These fields include: module name, thread initialization function, packet processing or acquisition function, thread exit cleanup function, various flags, etc.

typedef struct TmModule_ {
const char *name;

/** thread handling */
TmEcode (*ThreadInit)(ThreadVars *, const void *, void **);
void (*ThreadExitPrintStats)(ThreadVars *, void *);
TmEcode (*ThreadDeinit)(ThreadVars *, void *);

/** the packet processing function */
TmEcode (*Func)(ThreadVars *, Packet *, void *);

TmEcode (*PktAcqLoop)(ThreadVars *, void *, void *);

/** terminates the capture loop in PktAcqLoop */
TmEcode (*PktAcqBreakLoop)(ThreadVars *, void *);

TmEcode (*Management)(ThreadVars *, void *);

/** global Init/DeInit */
TmEcode (*Init)(void);
TmEcode (*DeInit)(void);
#ifdef UNITTESTS
void (*RegisterTests)(void);
#endif
uint8_t cap_flags; /**< Flags to indicate the capability requirement of the given TmModule */ /* Other flags used by the module */ uint8_t flags; } TmModule; extern TmModule tmm_modules[TMM_SIZE] typedef enum { TMM_FLOWWORKER, TMM_DECODENFQ, TMM_VERDICTNFQ, TMM_RECEIVENFQ, TMM_RECEIVEPCAP, TMM_RECEIVEPCAPFILE, TMM_DECODEPCAP, TMM_DECODEPCAPFILE, TMM_RECEIVEPFRING, TMM_DECODEPFRING, TMM_RECEIVEPLUGIN, TMM_DECODEPLUGIN, TMM_RESPONDREJECT, TMM_DECODEIPFW, TMM_VERDICTIPFW, TMM_RECEIVEIPFW, TMM_RECEIVEERFFILE, TMM_DECODEERFFILE, TMM_RECEIVEERFDAG, TMM_DECODEERFDAG, TMM_RECEIVEAFP, TMM_DECODEAFP, TMM_RECEIVENETMAP, TMM_DECODENETMAP, TMM_ALERTPCAPINFO, TMM_RECEIVENAPATECH, TMM_DECODENAPATECH, TMM_STATSLOGGER, TMM_RECEIVENFLOG, TMM_DECODENFLOG, TMM_RECEIVEWINDIVERT, TMM_VERDICTWINDIVERT, TMM_DECODEWINDIVERT, TMM_FLOWMANAGER, TMM_FLOWRECYCLER, TMM_BYPASSEDFLOWMANAGER, TMM_DETECTLOADER, TMM_UNIXMANAGER, TMM_SIZE, } TmmId; 19. Rule Loading LoadSignatures -> Obtain signature list
DetectEngineCtx_ -> sig_list + sig_cnt -> sort by Action, by Flowbits, by Flowvar, by Pktvar, by Hostbits, by IPPairbit, by Priority -> runtime match structure (siggroup), the process of siggroup currently seems to group all previous rules list through IP, port number, and flow into a linked list array (sgh, and maintains a sigMask (which rules match))

$25 = {flags = 1572879, alproto = 0, dsize_low = 0, dsize_high = 0, mask = 0 ‘\000’,
num = 0, action = 1 ‘\001’, file_flags = 0 ‘\000’, proto = {
proto = ‘\377’ , flags = 1 ‘\001’}, class = 26 ‘\032’,
addr_dst_match4_cnt = 1, addr_src_match4_cnt = 1, addr_dst_match6_cnt = 1,
addr_src_match6_cnt = 1, addr_dst_match4 = 0x1867db0, addr_src_match4 = 0x1867df0,
addr_dst_match6 = 0x1867f30, addr_src_match6 = 0x1867f00, id = 2260002, gid = 1,
rev = 1, prio = 3, sp = 0x1867c70, dp = 0x1867ca0, CidrSrc = 0x1867bb0,
CidrDst = 0x1867c40, app_inspect = 0x0, sm_arrays = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0}, filestore_ctx = 0x0,
msg = 0x1867cd0 “SURICATA Applayer Detect protocol only one direction”,
class_msg = 0x1855880 “Generic Protocol Command Decode”, references = 0x0,
metadata = 0x0,
sig_str = 0x1867980 “alert ip any any -> any any (msg:\”SURICATA Applayer Detect protocol only one direction\”; flow:established; app-layer-event:applayer_detect_protocol_only_one_direction; flowint:applayer.anomaly.count,+”…, init_data = 0x1856830,
next = 0x0}
(gdb)

/* Signature flags */
/** \note: additions should be added to the rule analyzer as well */

#define SIG_FLAG_SRC_ANY BIT_U32(0) /**< source is any */ #define SIG_FLAG_DST_ANY BIT_U32(1) /**< destination is any */ #define SIG_FLAG_SP_ANY BIT_U32(2) /**< source port is any */ #define SIG_FLAG_DP_ANY BIT_U32(3) /**< destination port is any */ #define SIG_FLAG_NOALERT BIT_U32(4) /**< no alert flag is set */ #define SIG_FLAG_DSIZE BIT_U32(5) /**< signature has a dsize setting */ #define SIG_FLAG_APPLAYER BIT_U32(6) /**< signature applies to app layer instead of packets */ #define SIG_FLAG_IPONLY BIT_U32(7) /**< ip only signature */ 20. Upon completion of initialization, Suricata will then operate in threads according to the run mode and continuously capture packets. Initialization of Resource Scheduling