博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
snort 中的IP集合解析
阅读量:7144 次
发布时间:2019-06-29

本文共 7831 字,大约阅读时间需要 26 分钟。

hot3.png

简介

    前面总结了snort在读取配置文件时的总体流程,这里选择较为重要且相对有价值的细节部分进行分析,snort的IP串解析方式.

    因为snort支持[ ]形成IP集合并且支持使用'!'取反,因此可能构成如下的串 ![IP, !IP ![IP, !IP]]。

    因此会增加解析的难度.

分析

    snort处理这个问题的思想是,当发现一个 '['符号时便寻找与之对应的']'并将之间的串进行递归的解析,这样就能处理层次问题了.

代码分析

    以下是snort-2.9.6.0中多个代码片段合并而成

typedef struct _ip {    int16_t family;    int16_t bits;    /* see sfip_size(): these address bytes     * must be the last field in this struct */    union    {        u_int8_t  u6_addr8[16];        u_int16_t u6_addr16[8];        u_int32_t u6_addr32[4];//        u_int64_t    u6_addr64[2];    } ip;    #define ip8  ip.u6_addr8    #define ip16 ip.u6_addr16    #define ip32 ip.u6_addr32//    #define ip64 ip.u6_addr64} sfip_t;/***********************************************************************/#ifndef SF_IPVAR_H#define SF_IPVAR_H/* Flags */#define SFIP_NEGATED  1#define SFIP_ANY      2#include 
#include "sf_ip.h"/* Selects which mode a given variable is using to * store and lookup IP addresses */typedef enum _modes {    SFIP_LIST,    SFIP_TABLE} MODES;/* Used by the "list" mode.  A doubly linked list of sfip_t objects. */typedef struct _ip_node {    sfip_t *ip;#define ip_addr ip;   /* To ease porting Snort */    struct _ip_node *next;    int flags;                    // XXX    int addr_flags; /* Flags used exlusively by Snort */                    /* Keeping these variables seperate keeps                     * this from stepping on Snort's toes. */                    /* Should merge them later */} sfip_node_t;/* An IP variable onkect */typedef struct _var_t {    /* Selects whether or not to use the list, the table,     * or any other method added later */    MODES mode;    /* Linked lists.  Switch to something faster later */    sfip_node_t *head;    sfip_node_t *neg_head;    /* The mode above will select whether to use the sfip_node_t linked list     * or the IP routing table *///    sfrt rt;    /* Linked list of IP variables for the variable table */    struct _var_t *next;    uint32_t id;    char *name;    char *value;} sfip_var_t;/* A variable table for storing and looking up variables *//* Expand later to use a faster data structure */typedef struct _vartable_t {    sfip_var_t *head;    uint32_t id;} vartable_t;/***********************************************************************/SFIP_RET sfvar_parse_iplist(vartable_t *table, sfip_var_t *var,                           char *str, int negation){    char *end, *tok;    SFIP_RET ret;    int neg_ip;    if(!var || !table || !str)  /**检查防止段错误*/        return SFIP_ARG_ERR;    while(*str)    {        /* Skip whitespace and leading commas */        /** 跳过IP字符串前面的空指针以及多余的,*/        if(isspace((int)*str) || *str == ',')        {            str++;            continue;        }        /**neg IP标志是为了标志如 !192.168.1.1这样的IP*/        neg_ip = 0;        /* Handle multiple negations */        /**基数个 '!'为真, 偶数个'!'为否*/        for(; *str == '!'; str++)             neg_ip = !neg_ip;        /**提取一个IP串,这里可能会附带少量多余符号*/        /* Find end of this token */        for(end = str+1;           *end && !isspace((int)*end) && *end != LIST_CLOSE && *end != ',';            end++) ;        /**拷贝我们提取出的串*/        tok = SnortStrndup(str, end - str);        /**检查是从[exp1,exp2]中提取出 [exp1 这样的串*/        if(*str == LIST_OPEN)        {            char *list_tok;            /**找到与开头的 '['对应的 ']'*/            if((end = _find_end_token(str)) == NULL)            {                /* No trailing bracket found */                free(tok);                return SFIP_UNMATCHED_BRACKET;            }            str++;            /**从 [exp] 中提取出了整个exp, exp可能是复数个IP条目*/            list_tok = SnortStrndup(str, end - str);            /**递归拆分其中的子串, 注意negtive^neg_ip 完成了多重否定的解析*/            if((ret = sfvar_parse_iplist(table, var, list_tok,                           negation ^ neg_ip)) != SFIP_SUCCESS)            {                free(list_tok);                free(tok);                return ret;            }            free(list_tok);        }        /**这里通过递归已经将整个串拆分到最小单元即$VAR 或 !192.168.1.1这样的结构*/        else if(*str == '$')        {            /**该串是一个变量*/            sfip_var_t *tmp_var;            sfip_var_t *copy_var;            /**查看是否有这个变量*/            if((tmp_var = sfvt_lookup_var(table, tok)) == NULL)            {                /**未知变量,错误*/                free(tok);                return SFIP_LOOKUP_FAILURE;            }            /**将该变量对应的IP串拷贝出来*/            copy_var = sfvar_deep_copy(tmp_var);            /* Apply the negation */            /**确定该串的符号, 1标识为取反*/            if(negation ^ neg_ip)            {                /* Check for a negated "any" */                /**any 取反视为错误*/                if(copy_var->head && copy_var->head->flags & SFIP_ANY)                {                    free(tok);                    sfvar_free(copy_var);                    return SFIP_NOT_ANY;                }                /**对0的IP取反视为错误*/                /* Check if this is a negated, zero'ed IP (equivalent of a "!any") */                if(copy_var->head && !sfip_is_set(copy_var->head->ip))                {                    free(tok);                    sfvar_free(copy_var);                    return SFIP_NOT_ANY;                }                /**反转数据, 即将 IP取反的集合与不取反的交换*/                _negate_lists(copy_var);            }            /**将该集合加入,该改则的IP集合*/            sfvar_add(var, copy_var);            sfvar_free(copy_var);        }        else if(*str == LIST_CLOSE)        {            /* This should be the last character, if not, then this is an             * invalid extra closing bracket */            if(!(*(str+1)))            {                free(tok);                return SFIP_SUCCESS;            }            free(tok);            return SFIP_UNMATCHED_BRACKET;        }        else        {            sfip_node_t *node;            /* Skip leading commas */            for(; *str == ','; str++) ;            /* Check for a negated "any" */            if(negation ^ neg_ip && !strcasecmp(tok, "any"))            {                free(tok);                return SFIP_NOT_ANY;            }            /**普通的IP串,直接解析后添加*/            /* This should be an IP address! */            /* Allocate new node for this string and add it to "ret" */            if((node = sfipnode_alloc(tok, &ret)) == NULL)            {                free(tok);                return ret;            }            if(negation ^ neg_ip)            {                _negate_node(node);            }            /* Check if this is a negated, zero'ed IP (equivalent of a "!any") */            if(!sfip_is_set(node->ip) && (node->flags & SFIP_NEGATED))            {                sfip_node_free(node);                free(tok);                return SFIP_NOT_ANY;            }            ret = sfvar_add_node(var, node, negation ^ neg_ip);            if(ret != SFIP_SUCCESS )            {                free(tok);                return ret;            }        }        free(tok);        /**只要该串解析完后不是末尾就将解析指针指向下一个*/        if(*end)            str = end + 1;        else break;    }    return SFIP_SUCCESS;}/***********************************************************************//* Support function for sfvar_parse_iplist.  Used to * correctly match up end brackets. *  (Can't just do strchr(str, ']') because of the *  [a, [b], c] case, and can't do strrchr because *  of the [a, [b], [c]] case) */ /**改代码非常精妙的找到了与第一个'['对应的 ']',而且同时完成了校验工作*/static char *_find_end_token(char *str){    int stack = 0;    for(; *str; str++)    {        if(*str == LIST_OPEN)            stack++;        else if(*str == LIST_CLOSE)            stack--;        if(!stack)        {            return str;        }    }    return NULL;}

总结

  1. 该段代码在括号处理得技巧上值得学习

  2. 还有一处从这部分代码片段看不太明显地方;是对解析过一次的字符串,再次遇到相同的串就将其解析后的IP集合直接采用深度拷贝过来

  3. 对于第二点的深度拷贝目前原因不明,可能方便后面重新整理构建,但如果不是的话,副本可以使用类似智能指针的思想来创建

转载于:https://my.oschina.net/u/572632/blog/289745

你可能感兴趣的文章
[已解]如何设置xib 中 ipad 的开发模式为横屏
查看>>
Repeater控件使用
查看>>
[Android] 华为荣耀2制作fastboot线刷包[海思平台]
查看>>
慢慢 的变老
查看>>
高效能TCP通讯基础组件Beetle.Express
查看>>
MyEclipse内存不足配置
查看>>
四舍五入网络Java保留两位小数
查看>>
MFC 循环界面假死的解决(MFC 按钮终止循环)
查看>>
详细解说九宫图比较常用的多控件布局
查看>>
程序员的出路在哪里?挣钱的机会来了续-福利来了,仿QQ界面,放出全部源码,打造创业框架及实现思路...
查看>>
C语言中的 (void*)0 与 (void)0
查看>>
DIV固定在页面某个位置,不随鼠标滚动而滚动
查看>>
android 根据SD卡中图片路径读取并显示SD中的图片——源代码
查看>>
浅析Android线程模型一 --- 转
查看>>
Cocos2d-x PluginX (二)增加新的Plugin
查看>>
python-django开发学习笔记四
查看>>
cocos2d-x开发记录:二,基本概念(导演,场景,层和精灵,场景切换,效果)...
查看>>
Binutils工具集中的一些比较常用的工具
查看>>
IoC在ASP.NET Web API中的应用
查看>>
Android手机 Fildder真机抓包
查看>>