简介
前面的分析已经知道了读取规则时如何处理动作,协议,地址和端口串。因此对于解析像:
log tcp any any-> any any
这样的规则头部已经可以完成,这里就对完整规则头部解析后整理规则头部信息的流程进行分析,从该段代码也可看出规则节点是如何与规则选项节点相关联的.
代码分析
snort-2.9.6.0中取出的代码片段
static RuleTreeNode * ProcessHeadNode(SnortConfig *sc, RuleTreeNode *test_node,
ListHead *list)
{
/**查找所有规则选项节点关联的规则头节点是否与在处理的头节点相同该节点*/
RuleTreeNode *rtn = findHeadNode(sc, test_node, getParserPolicy(sc));
/* if it doesn't match any of the existing nodes, make a new node and
* stick it at the end of the list */
if (rtn == NULL) /**检查是否已有相同的规则节点*/
{
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Building New Chain head node\n"););
/**如果没有申请一个新的rtn节点*/
rtn = (RuleTreeNode *)SnortAlloc(sizeof(RuleTreeNode));
/**将该规则对象的被动作节点引用计数加一*/
rtn->otnRefCount++;
/**将test_node的内容拷贝到rtn中*/
/* copy the prototype header info into the new header block */
XferHeader(test_node, rtn);
/* number of header blocks (chain heads?) */
/**这是个全局递增计数,实际是为节点提供ID的*/
head_count++;
/**为该节点设置ID*/
rtn->head_node_number = head_count;
/**这个过程很简单但却很重要,见后面的代码片段*/
/* initialize the function list for the new RTN */
SetupRTNFuncList(rtn);
/**该规则节点的listHead指向对应的动作链*/
/* add link to parent listhead */
rtn->listhead = list;
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
"New Chain head flags = 0x%X\n", rtn->flags););
}
else
{
/**表明该规则有两个动作节点引用*/
/**注意没有设置listhead指针*/
rtn->otnRefCount++;
FreeRuleTreeNode(test_node);
}
return rtn;
}
/**returns matched header node.
*/
static RuleTreeNode * findHeadNode(SnortConfig *sc, RuleTreeNode *testNode,
tSfPolicyId policyId)
{
RuleTreeNode *rtn;
OptTreeNode *otn;
SFGHASH_NODE *hashNode;
for (hashNode = sfghash_findfirst(sc->otn_map);
hashNode;
hashNode = sfghash_findnext(sc->otn_map))
{
/**遍历其中的所有规则选项节点,获取其关联的规则节点*/
otn = (OptTreeNode *)hashNode->data;
rtn = getRtnFromOtn(otn, policyId);
/**检查该规则选项节点关联的规则节点是否是我们将要添加的节点*/
if (TestHeader(rtn, testNode))
return rtn;
}
return NULL;
}
/****************************************************************************
*
* Function: SetupRTNFuncList(RuleTreeNode *)
*
* Purpose: Configures the function list for the rule header detection
* functions (addrs and ports)
*
* Arguments: rtn => the pointer to the current rules list entry to attach to
*
* Returns: void function
*
***************************************************************************/
static void SetupRTNFuncList(RuleTreeNode * rtn)
{
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Initializing RTN function list!\n"););
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Functions: "););
/**这部分实际是根据规则对象的头部属性对rtn->rule_func回调链中加入对报文的源地址等数据处理的回调函数*/
if(rtn->flags & BIDIRECTIONAL)
{
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"CheckBidirectional->\n"););
AddRuleFuncToList(CheckBidirectional, rtn);
}
else
{
/* Attach the proper port checking function to the function list */
/*
* the in-line "if's" check to see if the "any" or "not" flags have
* been set so the PortToFunc call can determine which port testing
* function to attach to the list
*/
PortToFunc(rtn, (rtn->flags & ANY_DST_PORT ? 1 : 0),
(rtn->flags & EXCEPT_DST_PORT ? 1 : 0), DST);
/* as above */
PortToFunc(rtn, (rtn->flags & ANY_SRC_PORT ? 1 : 0),
(rtn->flags & EXCEPT_SRC_PORT ? 1 : 0), SRC);
/* link in the proper IP address detection function */
AddrToFunc(rtn, SRC);
/* last verse, same as the first (but for dest IP) ;) */
AddrToFunc(rtn, DST);
}
DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"RuleListEnd\n"););
/**这里仅仅是在回调连尾部加入一个空回调做结尾标志*/
/* tack the end (success) function to the list */
AddRuleFuncToList(RuleListEnd, rtn);
}
总结
规则头部对象不会出现重复
一个规则头能被多个规则选项引用
对报文的IP,端口处理的回调函数会在这里加入规则持有的回调链中
参考文章
http://my.oschina.net/u/572632/blog/289803
http://my.oschina.net/u/572632/blog/289775
http://my.oschina.net/u/572632/blog/289471