您的位置:首页 > 其它

suricata 3.1 源码分析27 (数据包IPv4解码)

2016-10-10 13:26 453 查看
int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
{
StatsIncr(tv, dtv->counter_ipv4);

SCLogDebug("pkt %p len %"PRIu16"", pkt, len);

/* do the actual decoding */
if (unlikely(DecodeIPV4Packet (p, pkt, len) < 0)) {
/*
DecodeIPV4首先会调用完成实际解码的DecodeIPV4Packet函数,该函数流程为:
1. 若len小于IPV4_HEADER_LEN(20),则添加IPV4_PKT_TOO_SMALL事件。
2. 使用IP_GET_RAW_VER获取版本号,若不为4,则添加IPV4_WRONG_IP_VER事件。
3. 设置ip4h指针(IPV4Hdr *类型)。
4. 使用IPV4_GET_HLEN获取IP头长度,若不等于IPV4_HEADER_LEN,则也添加IPV4_HEADER_LEN事件。
5. 使用IPV4_GET_IPLEN获取IP数据包长度(IP头+IP负载),若小于IP头长度,则添加IPV4_IPLEN_SMALLER_THAN_HLEN事件。
6. 若len小于IP数据包长度,则添加IPV4_TRUNC_PKT事件,表示这是个被截断的包。
7. 设置Packet的src和dst,通过SET_IPV4_SRC_ADDR和SET_IPV4_DST_ADDR实现。
8. 若IPv4选项长度(hlen-20)不为0,则调用DecodeIPV4Options对其进行解码。
*/
SCLogDebug("decoding IPv4 packet failed");
p->ip4h = NULL;
return TM_ECODE_FAILED;
}
p->proto = IPV4_GET_IPPROTO(p);
//调用IPV4_GET_IPPROTO获取下层协议,存储在Packet的proto中

/* If a fragment, pass off for re-assembly. */
if (unlikely(IPV4_GET_IPOFFSET(p) > 0 || IPV4_GET_MF(p) == 1)) {
Packet *rp = Defrag(tv, dtv, p, pq);
if (rp != NULL) {
PacketEnqueue(pq, rp);
}
p->flags |= PKT_IS_FRAGMENT;
return TM_ECODE_OK;
/*分片情况处理:若offset大于0或者MF标志为1,表示这是一个分片包,将会交给重组模块
的Defrag函数去处理。若返回不为NULL,表示已经重组完成了,那么就递归调用DecodeIPV4
重新进行IP层的解码,然后把这个新生成的重组包扔到pre队列中去。接着,给当前数据包打上PKT_IS_FRAGMENT标志,然后返回。*/
}

/* do hdr test, process hdr rules */

#ifdef DEBUG
if (SCLogDebugEnabled()) { /* only convert the addresses if debug is really enabled */
/* debug print */
char s[16], d[16];
PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), s, sizeof(s));
PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), d, sizeof(d));
SCLogDebug("IPV4 %s->%s PROTO: %" PRIu32 " OFFSET: %" PRIu32 " RF: %" PRIu32 " DF: %" PRIu32 " MF: %" PRIu32 " ID: %" PRIu32 "", s,d,
IPV4_GET_IPPROTO(p), IPV4_GET_IPOFFSET(p), IPV4_GET_RF(p),
IPV4_GET_DF(p), IPV4_GET_MF(p), IPV4_GET_IPID(p));
}
#endif /* DEBUG */

/* check what next decoder to invoke */
switch (IPV4_GET_IPPROTO(p)) {
case IPPROTO_TCP:
DecodeTCP(tv, dtv, p, pkt + IPV4_GET_HLEN(p),
IPV4_GET_IPLEN(p) - IPV4_GET_HLEN(p), pq);
break;
case IPPROTO_UDP:
DecodeUDP(tv, dtv, p, pkt + IPV4_GET_HLEN(p),
IPV4_GET_IPLEN(p) - IPV4_GET_HLEN(p), pq);
break;
case IPPROTO_ICMP:
DecodeICMPV4(tv, dtv, p, pkt + IPV4_GET_HLEN(p),
IPV4_GET_IPLEN(p) - IPV4_GET_HLEN(p), pq);
break;
case IPPROTO_GRE:
DecodeGRE(tv, dtv, p, pkt + IPV4_GET_HLEN(p),
IPV4_GET_IPLEN(p) - IPV4_GET_HLEN(p), pq);
break;
case IPPROTO_SCTP:
DecodeSCTP(tv, dtv, p, pkt + IPV4_GET_HLEN(p),
IPV4_GET_IPLEN(p) - IPV4_GET_HLEN(p), pq);
break;
case IPPROTO_IPV6:
{
if (pq != NULL) {
/* spawn off tunnel packet */
Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + IPV4_GET_HLEN(p),
IPV4_GET_IPLEN(p) - IPV4_GET_HLEN(p),
DECODE_TUNNEL_IPV6, pq);
if (tp != NULL) {
PKT_SET_SRC(tp, PKT_SRC_DECODER_IPV4);
PacketEnqueue(pq,tp);
}
}
break;
}
case IPPROTO_IP:
/* check PPP VJ uncompressed packets and decode tcp dummy */
if(p->ppph != NULL && ntohs(p->ppph->protocol) == PPP_VJ_UCOMP)    {
DecodeTCP(tv, dtv, p, pkt + IPV4_GET_HLEN(p),
IPV4_GET_IPLEN(p) -  IPV4_GET_HLEN(p), pq);
}
break;
case IPPROTO_ICMPV6:
ENGINE_SET_INVALID_EVENT(p, IPV4_WITH_ICMPV6);
break;
}

return TM_ECODE_OK;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  源码