简介
结合前面对snort中解析IP的细节处理,从整体上分析snort读取规则是如何管理解析到的IP,以及是如何通过直接复制副本来提高效率的.
预备资源
前面对处理细节的分析 http://my.oschina.net/u/572632/blog/289745
snort 规则中的IP介绍
流程图
部分代码片段结合流程图说明
/* 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;
当从配置文件中获得一个IP串时就交给解析器解析器
解析器首先查看是否已解析过相同的串,如果有直接拷贝一个副本作为该次解析结果
如果该串没有解析过,则解析器开始解析该串
解析完成后将该串解析后的集合放入管理器中,向用户返回该次解析结果
代码分析
代码取自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;
}
总结
该部分代码的对括号以及取反的方式有很大的参考价值
每次解析前先尝试查找被解析过的相同的串获得副本来减少解析的思路减少了很多开销
参考资料
独孤九剑的<snort入侵检测系统源码分析>
来源:oschina
链接:https://my.oschina.net/u/572632/blog/289775