snort 中的規則解析框架(二)

簡介

    snort中配置文件的處理是一個很重要的部分,由於其不只是數據的讀取過程更是snort初始結構的搭建過程
node

       前面已經對snort解析單個文件作了代碼分析.react

        連接:http://my.oschina.net/u/572632/blog/289256數組

        這裏從配置文件讀取的總入口開始結合前面的分析作更多的記錄,目地是整理出如今snort的整理框架圖。以2.9.6.0 Ver 爲例
session

代碼分析

/****************************************************************************
 * Function: ParseSnortConf()
 *
 * Read the rules file a line at a time and send each rule to the rule parser
 * This is the first pass of the configuration file.  It parses everything
 * except the rules.
 *
 * Arguments: None
 *
 * Returns:
 *  SnortConfig *
 *      An initialized and configured snort configuration struct.
 *      This struct should be passed on the second pass of the
 *      configuration file to parse the rules.
 *
 ***************************************************************************/


 typedef struct _SnortConfig
{
    RunMode run_mode;
    int run_mode_flags;
    int run_flags;
    int output_flags;
    int logging_flags;
    int log_tcpdump;
    int no_log;
    int no_alert;
    int dirty_pig;

    //used for processing command line arguments, checksum configuration
    //in conf files is maintained at policy level
    int checksum_flags;         /* -k */
    int checksum_flags_modified;
    int checksum_drop_flags;
    int checksum_drop_flags_modified;

    uint32_t event_log_id;      /* -G */
    int pkt_snaplen;
    uint64_t pkt_cnt;           /* -n */
#ifdef REG_TEST
    uint64_t pkt_skip;
#endif

    char *dynamic_rules_path;   /* --dump-dynamic-rules */

    /* --dynamic-engine-lib
     * --dynamic-engine-lib-dir
     * --dynamic-detection-lib
     * --dynamic-detection-lib-dir
     * --dynamic-preprocessor-lib
     * --dynamic-preprocessor-lib-dir
     *
     * See below for struct type
     */
    DynamicLibInfo *dyn_engines;
    DynamicLibInfo *dyn_rules;
    DynamicLibInfo *dyn_preprocs;
#ifdef SIDE_CHANNEL
    DynamicLibInfo *dyn_side_channels;
#endif

    char pid_path[STD_BUF];  /* --pid-path or config pidpath */

#ifdef EXIT_CHECK
    uint64_t exit_check;        /* --exit-check */
#endif

    /* -h and -B */
    sfip_t homenet;
    sfip_t obfuscation_net;

    uint32_t ipv6_frag_timeout;
    uint32_t ipv6_max_frag_sessions;

    uint16_t flowbit_size;

    char pid_filename[STD_BUF];  /* used with pid_path */
    char pidfile_suffix[MAX_PIDFILE_SUFFIX + 1];  /* -R */
    char *log_dir;           /* -l or config log_dir */
    char *orig_log_dir;      /* set in case of chroot */
    char *interface;         /* -i or config interface */
    char *bpf_file;          /* -F or config bpf_file */
    char *pcap_log_file;     /* -L */
    char *chroot_dir;        /* -t or config chroot */
    char *alert_file;
    char *perf_file;         /* -Z */
    char *bpf_filter;        /* last command line arguments */
    char* daq_type;          /* --daq or config daq */
    char* daq_mode;          /* --daq-mode or config daq_mode */
    void* daq_vars;          /* --daq-var or config daq_var */
    void* daq_dirs;          /* --daq-dir or config daq_dir */

    char* event_trace_file;
    uint16_t event_trace_max;

    int thiszone;

    uint8_t ignore_ports[UINT16_MAX];        /* config ignore_ports */
    long int tagged_packet_limit;            /* config tagged_packet_limit */
    long int pcre_match_limit;               /* config pcre_match_limit */
    long int pcre_match_limit_recursion;     /* config pcre_match_limit_recursion */
    int *pcre_ovector;
    int pcre_ovector_size;

#ifdef PERF_PROFILING
    ProfileConfig profile_rules;     /* config profile_rules */
    ProfileConfig profile_preprocs;  /* config profile_preprocs */
#endif

    int user_id;
    int group_id;

    mode_t file_mask;

#ifdef MPLS
    uint8_t mpls_payload_type;  /* --mpls_payload_type */
    long int mpls_stack_depth;  /* --max_mpls_labelchain_len */
#endif

    int default_rule_state;     /* config default_rule_state */

    char* react_page;        /* config react */

#ifdef ACTIVE_RESPONSE
    uint8_t respond_attempts;    /* config respond */
    char* respond_device;
    uint8_t *eth_dst;        /* config destination MAC address */
#endif

#ifdef TARGET_BASED
    uint32_t max_attribute_hosts;    /* config max_attribute_hosts */
    uint32_t max_attribute_services_per_host;    /* config max_attribute_services_per_host */
    uint32_t max_metadata_services;  /* config max_metadata_services */
#endif

    OutputConfig *output_configs;
    OutputConfig *rule_type_output_configs;
    SFGHASH *config_table;   /* table of config keywords and arguments */
    int asn1_mem;

    int active_dynamic_nodes;

    RuleState *rule_state_list;
    ClassType *classifications;
    ReferenceSystemNode *references;
    SFGHASH *so_rule_otn_map;
    SFGHASH *otn_map;

    FastPatternConfig *fast_pattern_config;
    EventQueueConfig *event_queue_config;

    PreprocPostConfigFuncNode *preproc_post_config_funcs;
    PreprocCheckConfigFuncNode *preproc_config_check_funcs;

    /* XXX XXX policy specific? */
    ThresholdConfig *threshold_config;
    RateFilterConfig *rate_filter_config;
    DetectionFilterConfig *detection_filter_config;

    SF_EVENTQ *event_queue[NUM_EVENT_QUEUES];

    SF_LIST **ip_proto_only_lists;
    uint8_t ip_proto_array[NUM_IP_PROTOS];

    int num_rule_types;
    RuleListNode *rule_lists;
    int evalOrder[RULE_TYPE__MAX + 1];

    ListHead Alert;         /* Alert Block Header */
    ListHead Log;           /* Log Block Header */
    ListHead Pass;          /* Pass Block Header */
    ListHead Activation;    /* Activation Block Header */
    ListHead Dynamic;       /* Dynamic Block Header */
    ListHead Drop;
    ListHead SDrop;
    ListHead Reject;

    PostConfigFuncNode *plugin_post_config_funcs;

    OTNX_MATCH_DATA *omd;

    /* Pattern matcher queue statistics */
    unsigned int max_inq;
    uint64_t tot_inq_flush;
    uint64_t tot_inq_inserts;
    uint64_t tot_inq_uinserts;

    /* master port list table */
    rule_port_tables_t *port_tables;

#ifdef PPM_MGR
    ppm_cfg_t ppm_cfg;
#endif

    /* The port-rule-maps map the src-dst ports to rules for
     * udp and tcp, for Ip we map the dst port as the protocol,
     * and for Icmp we map the dst port to the Icmp type. This
     * allows us to use the decode packet information to in O(1)
     * select a group of rules to apply to the packet.  These
     * rules may have uricontent, content, or they may be no content
     * rules, or any combination. We process the uricontent 1st,
     * then the content, and then the no content rules for udp/tcp
     * and icmp, than we process the ip rules. */
    PORT_RULE_MAP *prmIpRTNX;
    PORT_RULE_MAP *prmTcpRTNX;
    PORT_RULE_MAP *prmUdpRTNX;
    PORT_RULE_MAP *prmIcmpRTNX;

#ifdef TARGET_BASED
    srmm_table_t *srmmTable;   /* srvc rule map master table */
    srmm_table_t *spgmmTable;  /* srvc port_group map master table */
    sopg_table_t *sopgTable;   /* service-oridnal to port_group table */
#endif

    SFXHASH *detection_option_hash_table;
    SFXHASH *detection_option_tree_hash_table;

    tSfPolicyConfig *policy_config;
    SnortPolicy **targeted_policies;
    unsigned int num_policies_allocated;

    char *base_version;

    uint8_t enable_teredo; /* config enable_deep_teredo_inspection */
    uint8_t enable_gtp; /* config enable_gtp */
    char *gtp_ports;
    uint8_t enable_esp;
    uint8_t vlan_agnostic; /* config vlan_agnostic */
    uint8_t addressspace_agnostic; /* config addressspace_agnostic */
    uint8_t log_ipv6_extra; /* config log_ipv6_extra_data */
    uint8_t tunnel_mask;

    uint32_t so_rule_memcap;
    uint32_t paf_max;          /* config paf_max */
    char *cs_dir;
    bool ha_peer;
    char *ha_out;
    char *ha_in;
    char *output_dir;
    void *file_config;
    int disable_all_policies;
    uint32_t reenabled_preprocessor_bits; /* flags for preprocessors to check, if all policies are disabled */
#ifdef SIDE_CHANNEL
    SideChannelConfig side_channel_config;
#endif
#ifdef SNORT_RELOAD
    int reloadPolicyFlag;
    PreprocessorSwapData *preprocSwapData;
    void *streamReloadConfig;
#endif
    tSfPolicyId parserPolicyId;

/* Used when a user defines a new rule type (ruletype keyword)
 * It points to the new rule type's ListHead and is used for accessing the
 * rule type's AlertList and LogList.
 * The output plugins used for the rule type need to be attached to the new
 * rule type's list head's AlertList or LogList.  It's set before calling
 * the output plugin's initialization routine, because in that routine,
 * AddFuncToOutputList is called (plugbase.c) and there, the output function
 * is attached to the new rule type's appropriate list.
 * NOTE:  This variable MUST NOT be used during runtime */
    ListHead *head_tmp;
} SnortConfig;


typedef struct _VarNode
{
    char *name;
    char *value;
    char *line;
    struct _VarNode *next;
} VarNode;

 /** 這是snort配置文件讀取的總入口 */
SnortConfig * ParseSnortConf(void)
{
    SnortConfig *sc = SnortConfNew();               /** 建立snortConfig結構*/
    VarNode *tmp = cmd_line_var_list;               /** 全局結構*/
    tSfPolicyId policy_id;                          /** 無符號整形做爲ID 值*/

    file_line = 0;                                  /** 記錄當前的行數*/
                                                    /** 記錄當前解析的文件*/
    file_name = snort_conf_file ? snort_conf_file : NULL_CONF;

    InitParser();
    /**
     * 初始化部分全局數據其中最重要的是初始化了rulemap
     *
     *  typedef struct {
     *       unsigned gid;
     *       unsigned sid;
     *   }rule_number_t;
     *
     * typedef struct {
     *   int  max_rules;
     *   int  num_rules;
     *   rule_number_t * map;
     * }rule_index_map_t;
     *
     *  1. rule_index_map_t 是管理規則id的,
     *  2  每一個規則映射一個rule_number_t對象 保存gid和 sid
     *  3. 全部rule_number_t 以數組的形式放在rule_index_map_t 中
     *  4. 空間時與預分配的大小爲 #define MAX_RULE_COUNT (65535 * 2)
     *
     *
     **/

    /* Setup the default rule action anchor points
     * Need to do this now in case we get a user defined rule type */
     /**
      * 1.這部分邏輯比較簡單但卻很重要,主要是搭建規則管理框架的
      * 2.規則信息的管理採用的是三成鏈表
      * 3.這裏是第一層
      * 4具體見後面該部分的代碼片斷註釋
      **/
    CreateDefaultRules(sc);
    /**
     * 初始化端口規則表,屬於數據管理的輔助結構,不是重點
     *
     */
    sc->port_tables = PortTablesNew();

    /**
     * 用於匹配查找的結構初始化
     */
    mpseInitSummary();

    /**
     * 爲rule和 option管理初始化了兩個hash表
     * 使用得是sfghash
     * 須要說明的是snort中有多個hash結構,而sfghash是帶內存管理功能的
     *
     *
     **/
    OtnInit(sc);

    /** config table 也使用sfghash*/
    /* Used to store "config" configurations */
    sc->config_table = sfghash_new(20, 0, 0, free);
    if (sc->config_table == NULL)
    {
        ParseError("%s(%d) No memory to create config table.\n",
                   __FILE__, __LINE__);
    }

    sc->fast_pattern_config = FastPatternConfigNew();   /** 創建快速匹配配置結構,保存基礎配置信息*/
    sc->event_queue_config = EventQueueConfigNew();     /** 創建事務隊列的配置結構*/
    sc->threshold_config = ThresholdConfigNew();        /** 創建閥值數據的配置結構*/
    sc->rate_filter_config = RateFilter_ConfigNew();    /** 創建頻率過濾配置結構*/
    sc->detection_filter_config = DetectionFilterConfigNew(); /** 創建探測配置結構*/
    /**協議數組,其中每一個單元的索引爲協議號,其中存放了一個鏈表頭*/
    sc->ip_proto_only_lists = (SF_LIST **)SnortAlloc(NUM_IP_PROTOS * sizeof(SF_LIST *));

    /* We're not going to parse rules on the first pass */
    parse_rules = 0;

    /** 初始化策略管理結構*/
    sc->policy_config = sfPolicyInit();
    if (sc->policy_config == NULL)
    {
        ParseError("No memory to create policy configuration.\n");
    }

    /* Add the default policy */
    /**這裏得到策略ID的方式是使用文件名得到的*/
    policy_id = sfPolicyAdd(sc->policy_config, file_name);
    /**賦值,策略默認ID是第一個讀取到的文件的ID*/
    sfSetDefaultPolicy(sc->policy_config, policy_id);
    /**targeted_policies 是一個空指針數組這裏是確保其長度大於default policy id*/
    sfDynArrayCheckBounds((void **)&sc->targeted_policies, policy_id, &sc->num_policies_allocated);
    /**分配一個snort policy 放入 targeted_policies數組中 policy id 的位置*/
    sc->targeted_policies[policy_id] = SnortPolicyNew();
    /**初始化snort policy中的部分輔助結構*/
    InitVarTables(sc->targeted_policies[policy_id]);
    /**根據snort運行模式設置標誌,是嗅探模式仍是在線模式?*/
    InitPolicyMode(sc->targeted_policies[policy_id]);
    /**
     * 下面是將正在使用的策略id放入指向的parsePolicyId中
     * if (sc)
     *      sc->parserPolicyId = id;
     * else
     *       snort_conf->parserPolicyId = id;
     *   }
     */
    setParserPolicy(sc, policy_id);

#ifndef SOURCEFIRE
    /* If snort is not run with root privileges, no interfaces will be defined,
     * so user beware if an iface_ADDRESS variable is used in snort.conf and
     * snort is not run as root (even if just in read mode) */
    DefineAllIfaceVars(sc);
#endif

    /* Add command line defined variables - duplicates will already
     * have been resolved */
     /**
      * 提取得到的追加變量
      */
    while (tmp != NULL)
    {
        AddVarToTable(sc, tmp->name, tmp->value);
        tmp = tmp->next;
    }

    /* Initialize storage space for preprocessor defined rule options */
    /** 也是使用sfghash*/
    sc->targeted_policies[policy_id]->preproc_rule_options = PreprocessorRuleOptionsNew();
    if (sc->targeted_policies[policy_id]->preproc_rule_options == NULL)
    {
        ParseError("Could not allocate storage for preprocessor rule "
                   "options.\n");
    }

    /**解析該文件*/
    if ( strcmp(file_name, NULL_CONF) )
        ParseConfigFile(sc, sc->targeted_policies[policy_id], file_name);

    /* We've picked up any targeted policy configs at this point so
     * it's probably okay to parse them here */
     /**遍歷全部snort policy 每個ID標識一個文件**/
    for (policy_id = 0;
         policy_id < sfPolicyNumAllocated(sc->policy_config);
         policy_id++)
    {
        char *fname = sfPolicyGet(sc->policy_config, policy_id);
        /**若是該id對應首個被解析的文件則忽略*/
        /* Already configured default policy */
        if (policy_id == sfGetDefaultPolicy(sc->policy_config))
            continue;

        if (fname != NULL)
        {
            /**再次確保targed_policies的大小足夠*/
            sfDynArrayCheckBounds(\
                                  (void **)&sc->targeted_policies, policy_id, &sc->num_policies_allocated);
            /**爲該文件的解析申請一個snort policy 結構並完成初始化工做*/
            sc->targeted_policies[policy_id] = SnortPolicyNew();

            InitVarTables(sc->targeted_policies[policy_id]);
            InitPolicyMode(sc->targeted_policies[policy_id]);
            setParserPolicy(sc, policy_id);

            /* Need to reset this for each targeted policy */
            memset(config_opt_configured, 0, sizeof(config_opt_configured));

            /* Add command line defined variables - duplicates will already
             * have been resolved */
            tmp = cmd_line_var_list;
            while (tmp != NULL)
            {
                AddVarToTable(sc, tmp->name, tmp->value);
                tmp = tmp->next;
            }

            /* Initialize storage space for preprocessor defined rule options */
            sc->targeted_policies[policy_id]->preproc_rule_options = PreprocessorRuleOptionsNew();
            if (sc->targeted_policies[policy_id]->preproc_rule_options == NULL)
            {
                ParseError("Could not allocate storage for preprocessor rule "
                           "options.\n");
            }
            /* Parse as include file so if the file is specified relative to
             * the snort conf directory we'll pick it up */
            ParseInclude(sc, sc->targeted_policies[policy_id], fname);
        }
    }

    /* This can be initialized now since we've picked up any user
     * defined rules */
    sc->omd = OtnXMatchDataNew(sc->num_rule_types);

    /* Reset these.  The only issue in not reseting would be if we were
     * parsing a command line again, but do it anyway */
    file_name = NULL;
    file_line = 0;

    return sc;
}
/***************************************************************************************/
/** 規則鏈第一層*/
typedef struct _RuleListNode
{
    ListHead *RuleList;         /* The rule list associated with this node */
    RuleType mode;              /* the rule mode */
    int rval;                   /* 0 == no detection, 1 == detection event */
    int evalIndex;              /* 實際上是記錄該條目是第幾個插入底層鏈表 */
    char *name;                 /* name of this rule list (for debugging)  */
    struct _RuleListNode *next; /* the next RuleListNode */
} RuleListNode;

/** 規則鏈第二層*/
typedef struct _ListHead
{
    struct _OutputFuncNode *LogList;
    struct _OutputFuncNode *AlertList;
    struct _RuleListNode *ruleListNode;
} ListHead;


/* function pointer list for rule head nodes */
typedef struct _RuleFpList
{
    /* context data for this test */
    void *context;

    /* rule check function pointer */
    int (*RuleHeadFunc)(Packet *, struct _RuleTreeNode *, struct _RuleFpList *, int);

    /* pointer to the next rule function node */
    struct _RuleFpList *next;
} RuleFpList;

/**規則鏈第三層*/
typedef struct _RuleTreeNode
{
    RuleFpList *rule_func; /* match functions.. (Bidirectional etc.. ) */
    int head_node_number;
    RuleType type;
    IpAddrSet *sip;
    IpAddrSet *dip;
    int proto;
    PortObject * src_portobject;
    PortObject * dst_portobject;
    uint32_t flags;     /* control flags */
    /* stuff for dynamic rules activation/deactivation */
    int active_flag;
    int activation_counter;
    int countdown;
    ActivateListNode *activate_list;

    /**points to global parent RTN list (Drop/Alert) which contains this
     * RTN.
     */
    struct _ListHead *listhead;

    /**reference count from otn. Multiple OTNs can reference this RTN with the same
     * policy.
     */
    unsigned int otnRefCount;
} RuleTreeNode;


static void CreateDefaultRules(SnortConfig *sc)
{
    if (sc == NULL)
        return;
    /**構建頂層規則鏈表
     * 1. 每一個單元表明一個動做
     * 2.全部單元以鏈式存放,且動做的默認優先級在鏈中的位置決定
     * 3.由於是鏈式存放,於是能靠改變頂層鏈中的單元順序來改變頂層規則的優先級
     */
    CreateRuleType(sc, RULE_LIST_TYPE__ACTIVATION, RULE_TYPE__ACTIVATE, 1, &sc->Activation);
    CreateRuleType(sc, RULE_LIST_TYPE__DYNAMIC, RULE_TYPE__DYNAMIC, 1, &sc->Dynamic);
    CreateRuleType(sc, RULE_LIST_TYPE__PASS, RULE_TYPE__PASS, 0, &sc->Pass); /* changed on Jan 06 */
    CreateRuleType(sc, RULE_LIST_TYPE__DROP, RULE_TYPE__DROP, 1, &sc->Drop);
    CreateRuleType(sc, RULE_LIST_TYPE__SDROP, RULE_TYPE__SDROP, 0, &sc->SDrop);
    CreateRuleType(sc, RULE_LIST_TYPE__REJECT, RULE_TYPE__REJECT, 1, &sc->Reject);
    CreateRuleType(sc, RULE_LIST_TYPE__ALERT, RULE_TYPE__ALERT, 1, &sc->Alert);
    CreateRuleType(sc, RULE_LIST_TYPE__LOG, RULE_TYPE__LOG, 1, &sc->Log);
}



/****************************************************************************
 *
 * Function: CreateRuleType
 *
 * Purpose: Creates a new type of rule and adds it to the end of the rule list
 *
 * Arguments: name = name of this rule type
 *                       mode = the mode for this rule type
 *                   rval = return value for this rule type (for detect events)
 *                       head = list head to use (or NULL to create a new one)
 *
 * Returns: the ListHead for the rule type
 *
 ***************************************************************************/
static ListHead * CreateRuleType(SnortConfig *sc, char *name,
                                 RuleType mode, int rval, ListHead *head)
{
    RuleListNode *node;
    int evalIndex = 0;
    if (sc == NULL)
        return NULL;
    node = (RuleListNode *)SnortAlloc(sizeof(RuleListNode));

    /* If this is the first rule list node, then we need to
     * create a new list. */
    if (sc->rule_lists == NULL)
    {
        sc->rule_lists = node;
    }
    else
    {
        RuleListNode *tmp = sc->rule_lists;
        RuleListNode *last;
        do
        {
            /**從這裏能夠看出snortconfig 中的ruleList 是一個單鏈表,尾部插入的管理方式*/
            /* We do not allow multiple rules types with the same name. */
            if (strcasecmp(tmp->name, name) == 0)
            {
                free(node);
                return NULL;
            }
            /**這裏能夠看出RuleListNode單元中 evalIndex數值的來源,即按照插入順序,遞增獲取*/
            evalIndex++;
            last = tmp;
            tmp = tmp->next;

        } while (tmp != NULL);

        last->next = node;
    }

    /* User defined rule type so we need to create a list head for it */
    /** 將頂層鏈表的RuleList指針指向二層鏈表, 此時二層鏈表只有一個單元*/
    if (head == NULL)
    {
        node->RuleList = (ListHead *)SnortAlloc(sizeof(ListHead));
    }
    else
    {
        /* Our default rules already have list heads */
        node->RuleList = head;
    }
    /** 二層鏈表頭部的ruleListNode指針指向其所屬的node*/
    node->RuleList->ruleListNode = node;
    node->mode = mode;
    node->rval = rval;
    node->name = SnortStrdup(name);
    node->evalIndex = evalIndex;

    /**這裏是創建type與ruleListnode在第一層規則鏈表中的位置序號,方便查找*/
    sc->evalOrder[node->mode] =  evalIndex;
    sc->num_rule_types++;

    return node->RuleList;
}

static void OtnInit(SnortConfig *sc)
{
    if (sc == NULL)
        return;

    /* Don't initialize this more than once */
    if ((sc->so_rule_otn_map != NULL) || (sc->otn_map != NULL))
        return;

    /* Init sid-gid -> otn map */
    sc->so_rule_otn_map = SoRuleOtnLookupNew(); /**分配初始化sfghash*/
    if (sc->so_rule_otn_map == NULL)
         ParseError("ParseRulesFile so_otn_map sfghash_new failed.\n");

    /* Init sid-gid -> otn map */
    sc->otn_map = OtnLookupNew();               /**分配初始化sfghash*/
    if (sc->otn_map == NULL)
        ParseError("ParseRulesFile otn_map sfghash_new failed.\n");
}
/***********************************************************************************/
typedef struct
{
    /** 這句是重點*/
    /**group id assigned to each file name. The groupId is an abstract concept
     * to tie multiple vlans into one group. */
    tSfPolicy **ppPolicies;
    tSfPolicyId defaultPolicyId;
    /**policy id of configuration file or packet being processed. */
    tSfPolicyId numAllocatedPolicies;
    unsigned int numActivePolicies;
    /**vlan to policyId bindings. */
    tSfPolicyId vlanBindings[SF_VLAN_BINDING_MAX];
    /**policyId to policyId bindings. */
    tSfPolicyId policyIdBindings[SF_POLICY_ID_BINDING_MAX];
    /**Network to policyId bindings. */
    table_t *netBindTable;

} tSfPolicyConfig;


tSfPolicyConfig * sfPolicyInit(void)
{
    int i;
    tSfPolicyConfig *new = (tSfPolicyConfig *)calloc(1, sizeof(tSfPolicyConfig));

    if (new == NULL)
        return NULL;

    //initialize vlan bindings
    for (i = 0; i < SF_VLAN_BINDING_MAX; i++)
    {
        new->vlanBindings[i] = SF_POLICY_UNBOUND;
    }

    for (i = 0; i < SF_POLICY_ID_BINDING_MAX; i++)
    {
        new->policyIdBindings[i] = SF_POLICY_UNBOUND;
    }

    //initialize net bindings
    /** 初始化查找結構*/
    new->netBindTable = sfrt_new(DIR_16x7_4x4, IPv6, SF_NETWORK_BINDING_MAX, 20);

    return new;
}
/**********************************************************************************/
SnortPolicy * SnortPolicyNew(void)
{
    SnortPolicy *pPolicy = (SnortPolicy *)SnortAlloc(sizeof(SnortPolicy));

    if (pPolicy)
    {
        // minimum possible (allows all but errors to pass by default)
        pPolicy->min_ttl = 1;

#ifdef NORMALIZER
        pPolicy->new_ttl = 5;
#endif

        /* Turn on all decoder alerts by default except for oversized alert.
         * Useful for bug reports ... */
        pPolicy->decoder_alert_flags |= DECODE_EVENT_FLAG__DEFAULT;
        pPolicy->decoder_alert_flags |= DECODE_EVENT_FLAG__TCP_EXP_OPT;
        pPolicy->decoder_alert_flags |= DECODE_EVENT_FLAG__TCP_OBS_OPT;
        pPolicy->decoder_alert_flags |= DECODE_EVENT_FLAG__TCP_TTCP_OPT;
        pPolicy->decoder_alert_flags |= DECODE_EVENT_FLAG__TCP_OPT_ANOMALY;
        pPolicy->decoder_alert_flags |= DECODE_EVENT_FLAG__IP_OPT_ANOMALY;
        pPolicy->decoder_alert_flags |= DECODE_EVENT_FLAG__IPV6_BAD_FRAG;
        pPolicy->decoder_alert_flags |= DECODE_EVENT_FLAG__IPV6_BSD_ICMP_FRAG;

        pPolicy->decoder_drop_flags |= DECODE_EVENT_FLAG__IPV6_BAD_FRAG;

        pPolicy->checksum_flags = CHECKSUM_FLAG__ALL;
    }

    return pPolicy;
}
#########################################################################################
/**當 ParseConfigFile在配置文件中發現include 規則時會調用下面的回調函數*/
static void ParseInclude(SnortConfig *sc, SnortPolicy *p, char *arg)
{
    struct stat file_stat;  /* for include path testing */
    /* Save place in previous file */
    char *stored_file_name = file_name;
    int stored_file_line = file_line;
    /**任何配置文件不能包含頂層文件,避免出現include迴路*/
    /* Including top level snort conf file */
    if (strcmp(arg, snort_conf_file) == 0)
    {
        ParseError("Cannot include \"%s\" in an include directive.",
                   snort_conf_file);
    }

    /* XXX Maybe not allow an include in an included file to avoid
     * potential recursion issues */

    file_line = 0;
    file_name = SnortStrdup(arg);

    /* Stat the file.  If that fails, stat it relative to the directory
     * that the top level snort configuration file was in */
    if (stat(file_name, &file_stat) == -1)
    {
        int path_len = strlen(snort_conf_dir) + strlen(arg) + 1;

        DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"ParseConfigFile: stat "
                                "on %s failed - going to config_dir\n", file_name););

        free(file_name);

        file_name = (char *)SnortAlloc(path_len);
        snprintf(file_name, path_len, "%s%s", snort_conf_dir, arg);

        DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"ParseConfigFile: Opening "
                                "and parsing %s\n", file_name););
    }
    /**調用parseConfigFile*/
    ParseConfigFile(sc, p, file_name);

    free(file_name);

    file_name = stored_file_name;
    file_line = stored_file_line;
}

總結app

  1. 做爲配置文件讀取的頂層接口,實際主要是在解析文件前對必要數據作了初始化工做框架

  2. include的回調操做是在解析到include命令時做爲插件觸發的tcp

相關文章
相關標籤/搜索