Suricata之源代码(二)

    在前面的代码主要是运行模式的一些初始化工作。接下来Suricata中的代码主要是完成对命令行的命令
  1. <span style="font-size:18px;">    ConfInit();  
  2.     struct option long_opts[] = {  
  3.         {"dump-config", 0, &dump_config, 1},  
  4.         {"pfring", optional_argument, 0, 0},  
  5.         {"pfring-int", required_argument, 0, 0},  
  6.         {"pfring-cluster-id", required_argument, 0, 0},  
  7.         {"pfring-cluster-type", required_argument, 0, 0},  
  8.         {"af-packet", optional_argument, 0, 0},  
  9.         {"pcap", optional_argument, 0, 0},  
  10. #ifdef BUILD_UNIX_SOCKET  
  11.         {"unix-socket", optional_argument, 0, 0},  
  12. #endif  
  13.         {"pcap-buffer-size", required_argument, 0, 0},  
  14.         {"unittest-filter", required_argument, 0, 'U'},  
  15.         {"list-app-layer-protos", 0, &list_app_layer_protocols, 1},  
  16.         {"list-unittests", 0, &list_unittests, 1},  
  17.         {"list-cuda-cards", 0, &list_cuda_cards, 1},  
  18.         {"list-runmodes", 0, &list_runmodes, 1},  
  19.         {"list-keywords", optional_argument, &list_keywords, 1},  
  20.         {"runmode", required_argument, NULL, 0},  
  21.         {"engine-analysis", 0, &engine_analysis, 1},  
  22. #ifdef OS_WIN32  
  23.         {"service-install", 0, 0, 0},  
  24.         {"service-remove", 0, 0, 0},  
  25.         {"service-change-params", 0, 0, 0},  
  26. #endif /* OS_WIN32 */  
  27.         {"pidfile", required_argument, 0, 0},  
  28.         {"init-errors-fatal", 0, 0, 0},  
  29.         {"fatal-unittests", 0, 0, 0},  
  30.         {"user", required_argument, 0, 0},  
  31.         {"group", required_argument, 0, 0},  
  32.         {"erf-in", required_argument, 0, 0},  
  33.         {"dag", required_argument, 0, 0},  
  34.         {"napatech", 0, 0, 0},  
  35.         {"build-info", 0, &build_info, 1},  
  36.         {NULL, 0, NULL, 0}  
  37.     };  
  38. </span>  
<span style="font-size:18px;">    ConfInit();
    struct option long_opts[] = {
        {"dump-config", 0, &dump_config, 1},
        {"pfring", optional_argument, 0, 0},
        {"pfring-int", required_argument, 0, 0},
        {"pfring-cluster-id", required_argument, 0, 0},
        {"pfring-cluster-type", required_argument, 0, 0},
        {"af-packet", optional_argument, 0, 0},
        {"pcap", optional_argument, 0, 0},
#ifdef BUILD_UNIX_SOCKET
        {"unix-socket", optional_argument, 0, 0},
#endif
        {"pcap-buffer-size", required_argument, 0, 0},
        {"unittest-filter", required_argument, 0, 'U'},
        {"list-app-layer-protos", 0, &list_app_layer_protocols, 1},
        {"list-unittests", 0, &list_unittests, 1},
        {"list-cuda-cards", 0, &list_cuda_cards, 1},
        {"list-runmodes", 0, &list_runmodes, 1},
        {"list-keywords", optional_argument, &list_keywords, 1},
        {"runmode", required_argument, NULL, 0},
        {"engine-analysis", 0, &engine_analysis, 1},
#ifdef OS_WIN32
		{"service-install", 0, 0, 0},
		{"service-remove", 0, 0, 0},
		{"service-change-params", 0, 0, 0},
#endif /* OS_WIN32 */
        {"pidfile", required_argument, 0, 0},
        {"init-errors-fatal", 0, 0, 0},
        {"fatal-unittests", 0, 0, 0},
        {"user", required_argument, 0, 0},
        {"group", required_argument, 0, 0},
        {"erf-in", required_argument, 0, 0},
        {"dag", required_argument, 0, 0},
        {"napatech", 0, 0, 0},
        {"build-info", 0, &build_info, 1},
        {NULL, 0, NULL, 0}
    };
</span>
ConfInit()的主要工作是初始化配置文件系统,主要是声明并初始化root,root = ConfNodeNew()。代码中使用了struct option结构体。该结构体主要是映射段命令和长命令的关系以及后面是否一定要跟参数。
  1. <span style="font-size:18px;">#define no_argument        0  
  2. #define required_argument  1  
  3. #define optional_argument  2  
  4.   
  5. struct option {  
  6.    const char *name;  
  7.    int has_arg;  
  8.    int *flag;  
  9.    int val;  
  10. };</span>  
<span style="font-size:18px;">#define no_argument        0
#define required_argument  1
#define optional_argument  2

struct option {
   const char *name;
   int has_arg;
   int *flag;
   int val;
};</span>

const char *name是不带短横线的选项名,前面没有短横线。譬如“help”、“verbose”之类。

int has_arg描述了选项是否有选项参数。如果有,是哪种类型的参数,此时,它的值一定是下表中的一个。符号常量数值含义

no_argument 

0 选项没有参数
required_argument  1 选项需要参数
optional_argument  2 选项参数可选
int *flag  如果这个指针为NULL,那么getopt_long()返回该结构val字段中的数值。如果该指针不为NULL,getopt_long()会使得它所指向的变量中填入val字段中的数值,并且getopt_long()返回0。如果flag不是NULL,但未发现长选项,那么它所指向的变量的数值不变。
int val 这个值是发现了长选项时的返回值,或者flag不是NULL时载入*flag中的值。典型情况下,若flag不是NULL,那么val是个真/假值,譬如1或0;另一方面,如果flag是NULL,那么val通常是字符常量,若长选项与短选项一致,那么该字符常量应该与optstring中出现的这个选项的参数相同。

接下来就是对命令的解析工作:

  1. <span style="font-size:18px;"int option_index = 0;  
  2.   
  3.     char short_opts[] = "c:TDhi:l:q:d:r:us:S:U:VF:";  
  4.   
  5.     while ((opt = getopt_long(argc, argv, short_opts, long_opts, &option_index)) != -1) {  
  6.         switch (opt) {  
  7.         case 0:  
  8.             if (strcmp((long_opts[option_index]).name , "pfring") == 0 ||  
  9.                 strcmp((long_opts[option_index]).name , "pfring-int") == 0) {  
  10. #ifdef HAVE_PFRING  
  11.                 run_mode = RUNMODE_PFRING;</span>  
<span style="font-size:18px;"> int option_index = 0;

    char short_opts[] = "c:TDhi:l:q:d:r:us:S:U:VF:";

    while ((opt = getopt_long(argc, argv, short_opts, long_opts, &option_index)) != -1) {
        switch (opt) {
        case 0:
            if (strcmp((long_opts[option_index]).name , "pfring") == 0 ||
                strcmp((long_opts[option_index]).name , "pfring-int") == 0) {
#ifdef HAVE_PFRING
                run_mode = RUNMODE_PFRING;</span>
代码中使用了getopt_long()函数解析了来自命令行的参数。

我们要看的部分也就是NFQ,看看NFQ在解析的时候主要是做了什么事情。

  1. <span style="font-size:18px;">#ifdef NFQ  
  2.             if (run_mode == RUNMODE_UNKNOWN) {  
  3.                 run_mode = RUNMODE_NFQ;  
  4.                 SET_ENGINE_MODE_IPS(engine_mode);  
  5.                 if (NFQRegisterQueue(optarg) == -1)  
  6.                     exit(EXIT_FAILURE);  
  7.             } else if (run_mode == RUNMODE_NFQ) {  
  8.                 if (NFQRegisterQueue(optarg) == -1)  
  9.                     exit(EXIT_FAILURE);  
  10.             } else {  
  11.                 SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "  
  12.                                                      "has been specified");  
  13.                 usage(argv[0]);  
  14.                 exit(EXIT_FAILURE);  
  15.             }  
  16. #else  
  17.             SCLogError(SC_ERR_NFQ_NOSUPPORT,"NFQUEUE not enabled. Make sure to pass --enable-nfqueue to configure when building.");  
  18.             exit(EXIT_FAILURE);  
  19. #endif /* NFQ */  
  20.             break;  
  21.         case 'd':</span>  
<span style="font-size:18px;">#ifdef NFQ
            if (run_mode == RUNMODE_UNKNOWN) {
                run_mode = RUNMODE_NFQ;
                SET_ENGINE_MODE_IPS(engine_mode);
                if (NFQRegisterQueue(optarg) == -1)
                    exit(EXIT_FAILURE);
            } else if (run_mode == RUNMODE_NFQ) {
                if (NFQRegisterQueue(optarg) == -1)
                    exit(EXIT_FAILURE);
            } else {
                SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
                                                     "has been specified");
                usage(argv[0]);
                exit(EXIT_FAILURE);
            }
#else
            SCLogError(SC_ERR_NFQ_NOSUPPORT,"NFQUEUE not enabled. Make sure to pass --enable-nfqueue to configure when building.");
            exit(EXIT_FAILURE);
#endif /* NFQ */
            break;
        case 'd':</span>

run_mode = RUNMODE_NFQ;//设置运行模式

SET_ENGINE_MODE_IPS(engine_mode);//设置为IPS

解析完这部分的代码之后可要对全局的数据进行初始化:

  1. <span style="font-size:18px;"/* Initializations for global vars, queues, etc (memsets, mutex init..) */  
  2.     GlobalInits();  
  3.     TimeInit();  
  4.     SupportFastPatternForSigMatchTypes();<span style="font-family:Microsoft YaHei;">  
  5.  </span> /* load the pattern matchers */  
  6.     MpmTableSetup();</span>  
<span style="font-size:18px;"> /* Initializations for global vars, queues, etc (memsets, mutex init..) */
    GlobalInits();
    TimeInit();
    SupportFastPatternForSigMatchTypes();<span style="font-family:Microsoft YaHei;">
 </span> /* load the pattern matchers */
    MpmTableSetup();</span>

 SupportFastPatternForSigMatchTypes();//这里是比较重要的一个部分,主要是针对快速匹配的。快速匹配的规则在rule中的体现是标记为fast的。这个在后面讲。反正这里就是对各种快速匹配链表进行初始化

MpmTableSetup();//主要是对各种匹配算法进行注册。也即装载模式匹配

SupportFastPatternForSigMatchTypes函数的主要功能如下:

  1. <span style="font-size:18px;">/** 
  2.  * \brief Registers the keywords(SMs) that should be given fp support. 
  3.  */  
  4. void SupportFastPatternForSigMatchTypes(void)  
  5. {  
  6.     SupportFastPatternForSigMatchList(DETECT_SM_LIST_PMATCH);  
  7.     SupportFastPatternForSigMatchList(DETECT_SM_LIST_UMATCH);  
  8.     SupportFastPatternForSigMatchList(DETECT_SM_LIST_HCBDMATCH);  
  9.     SupportFastPatternForSigMatchList(DETECT_SM_LIST_HSBDMATCH);  
  10.     SupportFastPatternForSigMatchList(DETECT_SM_LIST_HHDMATCH);  
  11.     SupportFastPatternForSigMatchList(DETECT_SM_LIST_HRHDMATCH);  
  12.     SupportFastPatternForSigMatchList(DETECT_SM_LIST_HMDMATCH);  
  13.     SupportFastPatternForSigMatchList(DETECT_SM_LIST_HCDMATCH);  
  14.     SupportFastPatternForSigMatchList(DETECT_SM_LIST_HRUDMATCH);  
  15.     SupportFastPatternForSigMatchList(DETECT_SM_LIST_HSMDMATCH);  
  16.     SupportFastPatternForSigMatchList(DETECT_SM_LIST_HSCDMATCH);  
  17.     SupportFastPatternForSigMatchList(DETECT_SM_LIST_HUADMATCH);  
  18.     SupportFastPatternForSigMatchList(DETECT_SM_LIST_HHHDMATCH);  
  19.     SupportFastPatternForSigMatchList(DETECT_SM_LIST_HRHHDMATCH);  
  20.   
  21.     return;  
  22. }  
  23. </span>  
<span style="font-size:18px;">/**
 * \brief Registers the keywords(SMs) that should be given fp support.
 */
void SupportFastPatternForSigMatchTypes(void)
{
    SupportFastPatternForSigMatchList(DETECT_SM_LIST_PMATCH);
    SupportFastPatternForSigMatchList(DETECT_SM_LIST_UMATCH);
    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HCBDMATCH);
    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HSBDMATCH);
    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HHDMATCH);
    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HRHDMATCH);
    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HMDMATCH);
    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HCDMATCH);
    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HRUDMATCH);
    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HSMDMATCH);
    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HSCDMATCH);
    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HUADMATCH);
    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HHHDMATCH);
    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HRHHDMATCH);

    return;
}
</span>
MpmTableSetup函数功能主要是:
  1. <span style="font-size:18px;">void MpmTableSetup(void) {  
  2.     memset(mpm_table, 0, sizeof(mpm_table));  
  3.   
  4.     MpmWuManberRegister();  
  5.     MpmB2gRegister();  
  6. #ifdef __SC_CUDA_SUPPORT__  
  7.     MpmB2gCudaRegister();  
  8. #endif  
  9.     MpmB3gRegister();  
  10.     MpmB2gcRegister();  
  11.     MpmB2gmRegister();  
  12.     MpmACRegister();  
  13.     MpmACBSRegister();  
  14.     MpmACGfbsRegister();  
  15. }</span>  
<span style="font-size:18px;">void MpmTableSetup(void) {
    memset(mpm_table, 0, sizeof(mpm_table));

    MpmWuManberRegister();
    MpmB2gRegister();
#ifdef __SC_CUDA_SUPPORT__
    MpmB2gCudaRegister();
#endif
    MpmB3gRegister();
    MpmB2gcRegister();
    MpmB2gmRegister();
    MpmACRegister();
    MpmACBSRegister();
    MpmACGfbsRegister();
}</span>
接下来的工作就是对yaml文件的加载以及解析工作,这个我会在下个博客给出一定的分析,希望能够达到抛砖引玉的功能。希望对看开源Suricata源代码的人有一定的帮助。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值