int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
uint8_t *pkt, uint16_t len, PacketQueue *pq)
{
StatsIncr(tv, dtv->counter_eth);
if (unlikely(len < ETHERNET_HEADER_LEN)) {
ENGINE_SET_INVALID_EVENT(p, ETHERNET_PKT_TOO_SMALL);
return TM_ECODE_FAILED;
/*若包长小于ETHERNET_HEADER_LEN(14),则调用ENGINE_SET_EVENT向
本数据包添加一个ETHERNET_PKT_TOO_SMALL事件,并返回。*/
}
p->ethh = (EthernetHdr *)pkt;
//设置ethh指针(EthernetHdr *类型)
if (unlikely(p->ethh == NULL))
return TM_ECODE_FAILED;
SCLogDebug("p %p pkt %p ether type %04x", p, pkt, ntohs(p->ethh->eth_type));
switch (ntohs(p->ethh->eth_type)) {
case ETHERNET_TYPE_IP:
//printf("DecodeEthernet ip4\n");
DecodeIPV4(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
len - ETHERNET_HEADER_LEN, pq);
//IPv4数据包
break;
case ETHERNET_TYPE_IPV6:
//printf("DecodeEthernet ip6\n");
DecodeIPV6(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
len - ETHERNET_HEADER_LEN, pq);
//IPv6数据包
break;
case ETHERNET_TYPE_PPPOE_SESS:
//printf("DecodeEthernet PPPOE Session\n");
DecodePPPOESession(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
len - ETHERNET_HEADER_LEN, pq);
//PPPoE会话阶段数据包,见:PPPoE - 维基百科
break;
case ETHERNET_TYPE_PPPOE_DISC:
//printf("DecodeEthernet PPPOE Discovery\n");
DecodePPPOEDiscovery(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
len - ETHERNET_HEADER_LEN, pq);
//PPPoE发现阶段数据包
break;
case ETHERNET_TYPE_VLAN:
case ETHERNET_TYPE_8021QINQ:
DecodeVLAN(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
len - ETHERNET_HEADER_LEN, pq);
//VLAN数据包,见:虚拟局域网 - 维基百科
break;
case ETHERNET_TYPE_MPLS_UNICAST:
case ETHERNET_TYPE_MPLS_MULTICAST:
DecodeMPLS(tv, dtv, p, pkt + ETHERNET_HEADER_LEN,
len - ETHERNET_HEADER_LEN, pq);
break;
default:
SCLogDebug("p %p pkt %p ether type %04x not supported", p,
pkt, ntohs(p->ethh->eth_type));
}
return TM_ECODE_OK;
}
PPPoE和VLAN都是夹在Ethernet协议和IP协议之间的,而相比PPPoE来说,VLAN在公司环境中更加普遍,因此下面只记录VLAN解码。