pfring: fix vlan handling issues

When Suricata was monitoring traffic with a single vlan layer, the stats
and output instead showed 2. This was caused by the raw packets PF_RING
feeds Suricata would hold the vlan header, but the code assumed that
the header was stripped and the vlan_id passed to Suricata through
PF_RING's extended_hdr.parsed_pkt.

This patch adds the following logic: Check vlan id from the parser packet
PF_RING prepared. PF_RING sets the vlan_id based on its own parsing or
based on the hardware offload. It gives no indication on where the vlan_id
came from, so we rely on the vlan_offset field. If it's 0, we assume the
PF_RING parser did not see the vlan header and got it from the hardware
offload. In this case we will use this information directly, as we won't
get a raw vlan header later. If PF_RING did set the offset, we do the
parsing in the Suricata decoder so that we have full control.

PF_RING *should* put back the vlan header in all cases, and also set the
vlan_offset field, but as a extra precaution keep the check described
above.

Bug #2355.
pull/3108/head
Victor Julien 7 years ago
parent 711b6fb389
commit 189b521239

@ -255,11 +255,23 @@ static inline void PfringProcessPacket(void *user, struct pfring_pkthdr *h, Pack
* so that is what we do here. */
p->datalink = LINKTYPE_ETHERNET;
/* get vlan id from header. Check on vlan_id not null even if comment in
* header announce NO_VLAN is used when there is no VLAN. But NO_VLAN
* is not defined nor used in PF_RING code. And vlan_id is set to 0
* in PF_RING kernel code when there is no VLAN. */
if ((!ptv->vlan_disabled) && h->extended_hdr.parsed_pkt.vlan_id) {
/* In the past, we needed this vlan handling in cases
* where the vlan header was stripped from the raw packet.
* With modern (at least >= 6) versions of PF_RING, the
* 'copy_data_to_ring' function (kernel/pf_ring.c) makes
* sure that if the hardware stripped the vlan header,
* it is put back by PF_RING.
*
* PF_RING should put it back in all cases, but as a extra
* precaution keep the check here. If the vlan header is
* part of the raw packet, the vlan_offset will be set.
* So is it is not set, use the parsed info from PF_RING's
* extended header.
*/
if ((!ptv->vlan_disabled) &&
h->extended_hdr.parsed_pkt.offset.vlan_offset == 0 &&
h->extended_hdr.parsed_pkt.vlan_id)
{
p->vlan_id[0] = h->extended_hdr.parsed_pkt.vlan_id & 0x0fff;
p->vlan_idx = 1;
p->vlanh[0] = NULL;

Loading…
Cancel
Save