snort 中的规则解析框架(二)

六眼飞鱼酱① 提交于 2019-11-30 11:32:15

简介

    snort中配置文件的处理是一个很重要的部分,因为其不仅是数据的读取过程更是snort初始结构的搭建过程

       前面已经对snort解析单个文件做了代码分析.

        链接:http://my.oschina.net/u/572632/blog/289256

        这里从配置文件读取的总入口开始结合前面的分析做更多的记录,目地是整理出现在snort的整理框架图。以2.9.6.0 Ver 为例

代码分析

/****************************************************************************
 * 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;
}

总结

  1. 作为配置文件读取的顶层接口,实际主要是在解析文件前对必要数据做了初始化工作

  2. include的回调操作是在解析到include命令时作为插件触发的

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!