一 概述
snort插件在做协议解析业务时需要知道查询名和相关联的协议ID,以便将协议解析结果和协议名称,协议ID都关联保存起来。总的业务流程如下:
1.snort主进程在启动时调用LoadProtocolAppName从数据库读取所有的appname和appid,调用LoadProtocolReference=》AddProtocolReferenceExtern将appname和appid插入哈希表;
2.snort插件如modbus插件等在启动时调用findProtocolReference从哈希表查询appname和appid。
二 SFTargetProtocolReference结构
存入哈希表的数据是SFTargetProtocolReference结构,name是协议名,ordinal是协议ID,每存入一个SFTargetProtocolReference对象,ordinal都会递增加1,其上限是MAX_PROTOCOL_ORDINAL(8192)。
三 哈希表结构sfghash
sfghash是链式哈希表结构,每个Bucket对应一个双向链表,链表里并不存储实际数据,而是存储数据的指针,如下所示:
这里的key和data都是指针,这样会节省哈希表的存储空间,但需要通过释放函数释放相关结点存储,即:
1.创建哈希表sfghash_new:
(1)创建一个大于等于传入参数最大素数的hash table;
(2)创建哈希函数;
(3)保存user_free等对象
2.加入哈希表sfghash_add
(1)支持传入字符串的key或者二进制的key,在传入二进制的key时,需要带入key的字节数;
(2)通过sfhashfcn→hash_fcn算出key对应的哈希值,并对nrows取模找到bucket位置(index);
(3)从相应的bucket找出key,如果找到,则返回已查询到,否则新生成一个hash node插入bucket最开始位置,方便之后查询。
3.哈希表查询sfghash_find_node
(1)根据key算出哈希值;
(2)找到bucket位置;
(3)从bucket查询key,如果查询到,使用movetofront将key的结点移动到bucket最开始,方便之后查询。
4.哈希表删除sfghash_delete
遍历整个hash table,并调用userfree释放data空间。
四 snort调用sfghash
代码:target-based/sftarget_protocol_reference.c,函数调用链:
AddProtocolReference=>InitializeProtocolReferenceTable=>sfghash_add
AddProtocolReferenceExtern=>InitializeProtocolReferenceTable=>sfghash_find=>sfghash_add
FindProtocolReference=>InitializeProtocolReferenceTable=>sfghash_find