]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
pfring: fix vlan handling issues
authorVictor Julien <victor@inliniac.net>
Tue, 19 Dec 2017 19:17:39 +0000 (20:17 +0100)
committerVictor Julien <victor@inliniac.net>
Tue, 30 Jan 2018 09:32:16 +0000 (10:32 +0100)
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.

src/source-pfring.c

index ed387583c297780646409d18d18f426844404d71..719b54958b1603e33b3e149e638fb4ce9ff539de 100644 (file)
@@ -247,11 +247,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;