snort配置文件中的IP解析

簡介

        結合前面對snort中解析IP的細節處理,從總體上分析snort讀取規則是如何管理解析到的IP,以及是如何經過直接複製副原本提升效率的.
node

預備資源

     前面對處理細節的分析 http://my.oschina.net/u/572632/blog/289745
ide

        snort 規則中的IP介紹
源碼分析

流程圖

        部分代碼片斷結合流程圖說明
ui

/* Used by the "list" mode.  A doubly linked list of sfip_t objects. */
typedef struct _ip_node {   /*構成一個鏈表明一個IP集合,存放在sfip_var_t中的head或neg_head中*/
    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 {   /**每個被解析的IP串對應該結構*/
    /* 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;     /**解析出的通常IP*/
    sfip_node_t *neg_head; /**被 !取反的IP*/

    /* 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;           /**IP串的ID*/
    char *name;            /**IP串的名字*/
    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 { /**管理全部被解析出的IP串*/
    sfip_var_t *head;
    uint32_t id;
} vartable_t;


  1. 當從配置文件中得到一個IP串時就交給解析器解析器this

  2. 解析器首先查看是否已解析過相同的串,若是有直接拷貝一個副本做爲該次解析結果spa

  3. 若是該串沒有解析過,則解析器開始解析該串.net

  4. 解析完成後將該串解析後的集合放入管理器中,向用戶返回該次解析結果code

代碼分析

代碼取自snort-2.9.6.0對象

static int ProcessIP(SnortConfig *sc, char *addr, RuleTreeNode *rtn, int mode, int neg_list)
{
    /**獲取存放全部IP信息的表*/
    vartable_t *ip_vartable = sc->targeted_policies[getParserPolicy(sc)]->ip_vartable;

    DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Got address string: %s\n",
                addr););
    assert(rtn);
    /* If a rule has a variable in it, we want to copy that variable's
     * contents to the IP variable (IP list) stored with the rtn.
     * This code tries to look up the variable, and if found, will copy it
     * to the rtn->{sip,dip} */
    if(mode == SRC)                 /**區分解析對象是源IP仍是目地IP*/
    {
        int ret;

        if (rtn->sip == NULL)       /**源IP是否已解析*/
        {
                                    /**查看是否解析過相同的IP結合*/
            sfip_var_t *tmp = sfvt_lookup_var(ip_vartable, addr);
            if (tmp != NULL)
            {    /**若是出現過相同的集合直接拷貝上次解析後的數據*/
                rtn->sip = sfvar_create_alias(tmp, tmp->name);
                if (rtn->sip == NULL)
                    ret = SFIP_FAILURE;
                else
                    ret = SFIP_SUCCESS;
            }
            else
            {
                /**不然建立解析該串並放入ip_varTable中*/
                rtn->sip = (sfip_var_t *)SnortAlloc(sizeof(sfip_var_t));
                ret = sfvt_add_to_var(ip_vartable, rtn->sip, addr);
            }
        }
        else
        {
            /** 解析串,並將解析出的IP集合添加到rtn->sip中, 並放入ip_vartable中*/
            ret = sfvt_add_to_var(ip_vartable, rtn->sip, addr);
        }

        /* The function sfvt_add_to_var adds 'addr' to the variable 'rtn->sip' */
        if (ret != SFIP_SUCCESS)
        {
            if(ret == SFIP_LOOKUP_FAILURE)
            {
                ParseError("Undefined variable in the string: %s.", addr);
            }
            else if(ret == SFIP_CONFLICT)
            {
                ParseError("Negated IP ranges that are more general than "
                           "non-negated ranges are not allowed. Consider "
                           "inverting the logic: %s.", addr);
            }
            else if(ret == SFIP_NOT_ANY)
            {
                ParseError("!any is not allowed: %s.", addr);
            }
            else
            {
                ParseError("Unable to process the IP address: %s.", addr);
            }
        }
        /**該節點中出現一個any 標記,則將rtn中標註ANY*/
        if(rtn->sip->head && rtn->sip->head->flags & SFIP_ANY)
        {
            rtn->flags |= ANY_SRC_IP;
        }
    }
    /* mode == DST */   /**與源IP相對*/
    else
    {
        int ret;

        if (rtn->dip == NULL)
        {
            sfip_var_t *tmp = sfvt_lookup_var(ip_vartable, addr);
            if (tmp != NULL)
            {
                rtn->dip = sfvar_create_alias(tmp, tmp->name);
                if (rtn->dip == NULL)
                    ret = SFIP_FAILURE;
                else
                    ret = SFIP_SUCCESS;
            }
            else
            {
                rtn->dip = (sfip_var_t *)SnortAlloc(sizeof(sfip_var_t));
                ret = sfvt_add_to_var(ip_vartable, rtn->dip, addr);
            }
        }
        else
        {
            ret = sfvt_add_to_var(ip_vartable, rtn->dip, addr);
        }

        if (ret != SFIP_SUCCESS)
        {
            if(ret == SFIP_LOOKUP_FAILURE)
            {
                ParseError("Undefined variable in the string: %s.", addr);
            }
            else if(ret == SFIP_CONFLICT)
            {
                ParseError("Negated IP ranges that are more general than "
                           "non-negated ranges are not allowed. Consider "
                           "inverting the logic: %s.", addr);
            }
            else if(ret == SFIP_NOT_ANY)
            {
                ParseError("!any is not allowed: %s.", addr);
            }
            else
            {
                ParseError("Unable to process the IP address: %s.", addr);
            }
        }

        if(rtn->dip->head && rtn->dip->head->flags & SFIP_ANY)
        {
            rtn->flags |= ANY_DST_IP;
        }
    }

    /* Make sure the IP lists provided by the user are valid */
    if (mode == SRC)
        ValidateIPList(rtn->sip, addr);
    else
        ValidateIPList(rtn->dip, addr);

    return 0;
}


總結

  1. 該部分代碼的對括號以及取反的方式有很大的參考價值blog

  2. 每次解析前先嚐試查找被解析過的相同的串得到副原本減小解析的思路減小了不少開銷

參考資料

  1. 獨孤九劍的<snort入侵檢測系統源碼分析>

相關文章
相關標籤/搜索