A-A+

suricata 3.1 源码分析26 (数据包VLAN解码)

2018年12月06日 suricata 暂无评论

由于VLAN可能嵌套,因此Packet结构体中使用以下相应字段进行记录:
字段含义vlan_idx当前的vlan层数,初始为0,最多为2,即最多只能嵌套一层VLAN,否则会报错。vlan_id[2]记录每一层的VLAN ID(共12位,可表示4096个VLAN),通过GET_VLAN_ID获得。vlanh[2]记录每一层的VLAN头指针(VLANHdr *类型)。

/**
 * \internal
 * \brief this function is used to decode IEEE802.1q packets
 *
 * \param tv pointer to the thread vars
 * \param dtv pointer code thread vars
 * \param p pointer to the packet struct
 * \param pkt pointer to the raw packet
 * \param len packet len
 * \param pq pointer to the packet queue
 *
 */
int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
{
    uint32_t proto;

    if (p->vlan_idx == 0)
        StatsIncr(tv, dtv->counter_vlan);
    else if (p->vlan_idx == 1)
        StatsIncr(tv, dtv->counter_vlan_qinq);

    if(len < VLAN_HEADER_LEN)    {
        ENGINE_SET_INVALID_EVENT(p, VLAN_HEADER_TOO_SMALL);
        return TM_ECODE_FAILED;
//若len小于VLAN_HEADER_LEN(4),则添加VLAN_HEADER_TOO_SMALL事件。

    }
    if (p->vlan_idx >= 2) {
        ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS);
        return TM_ECODE_FAILED;
//vlan_idx是否大于或等于2,否则添加VLAN_HEADER_TOO_MANY_LAYERS事件。

    }

    p->vlanh[p->vlan_idx] = (VLANHdr *)pkt;
    if(p->vlanh[p->vlan_idx] == NULL)
        return TM_ECODE_FAILED;

    proto = GET_VLAN_PROTO(p->vlanh[p->vlan_idx]);

    SCLogDebug("p %p pkt %p VLAN protocol %04x VLAN PRI %d VLAN CFI %d VLAN ID %d Len: %" PRId32 "",
            p, pkt, proto, GET_VLAN_PRIORITY(p->vlanh[p->vlan_idx]),
            GET_VLAN_CFI(p->vlanh[p->vlan_idx]), GET_VLAN_ID(p->vlanh[p->vlan_idx]), len);

    /* only store the id for flow hashing if it's not disabled. */
    if (dtv->vlan_disabled == 0)
        p->vlan_id[p->vlan_idx] = (uint16_t)GET_VLAN_ID(p->vlanh[p->vlan_idx]);

    p->vlan_idx++;

    switch (proto)   {
        case ETHERNET_TYPE_IP:
            DecodeIPV4(tv, dtv, p, pkt + VLAN_HEADER_LEN,
                       len - VLAN_HEADER_LEN, pq);
            break;
        case ETHERNET_TYPE_IPV6:
            DecodeIPV6(tv, dtv, p, pkt + VLAN_HEADER_LEN,
                       len - VLAN_HEADER_LEN, pq);
            break;
        case ETHERNET_TYPE_PPPOE_SESS:
            DecodePPPOESession(tv, dtv, p, pkt + VLAN_HEADER_LEN,
                               len - VLAN_HEADER_LEN, pq);
            break;
        case ETHERNET_TYPE_PPPOE_DISC:
            DecodePPPOEDiscovery(tv, dtv, p, pkt + VLAN_HEADER_LEN,
                                 len - VLAN_HEADER_LEN, pq);
            break;
        case ETHERNET_TYPE_VLAN:
        case ETHERNET_TYPE_8021AD:
            if (p->vlan_idx >= 2) {
                ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS);
                return TM_ECODE_OK;
            } else {
                DecodeVLAN(tv, dtv, p, pkt + VLAN_HEADER_LEN,
                        len - VLAN_HEADER_LEN, pq);
            }
            break;
        default:
            SCLogDebug("unknown VLAN type: %" PRIx32 "", proto);
            ENGINE_SET_INVALID_EVENT(p, VLAN_UNKNOWN_TYPE);
            return TM_ECODE_OK;
    }

    return TM_ECODE_OK;
}
标签:

给我留言

Copyright © 九毛的官方博客 保留所有权利.   Theme  Ality

用户登录