您的位置:首页 > 其它

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

2016-10-09 14:34 281 查看
由于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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  源码