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

来源:互联网 发布:linux延时函数头文件 编辑:程序博客网 时间:2024/04/29 06:44
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;}
0 0
原创粉丝点击