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; }
相关文章推荐
- suricata 3.1 源码分析25 (数据包以太层解码)
- suricata 3.1 源码分析26 (数据包VLAN解码)
- suricata 3.1 源码分析23 (数据包解码模块注册及初始化)
- suricata 3.1 源码分析24 (数据包解码模块执行)
- suricata 3.1 源码分析28 (数据包TCP解码)
- suricata 3.1 源码分析22 (数据包处理2)
- suricata 3.1 源码分析19 (数据包获取)
- suricata 3.1 源码分析29 (数据包队列)
- suricata 3.1 源码分析20 (数据包封装)
- suricata 3.1 源码分析21 (数据包处理1)
- suricata 3.1 源码分析7
- suricata 3.1 源码分析30 (packet_pool处理流程)
- suricata 3.1 源码分析32 (FlowWorker处理流程1)
- suricata 3.1 源码分析1
- suricata 3.1 源码分析11
- suricata 3.1 源码分析18 (模块注册及初始化)
- suricata 3.2 源码分析(IP数据包分片重组流程)
- suricata 3.1 源码分析12
- suricata 3.1 源码分析31 (RespondReject)
- suricata 3.1 源码分析5