]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
pfring: get vlan id from header
authorEric Leblond <eric@regit.org>
Tue, 4 Feb 2014 15:33:30 +0000 (16:33 +0100)
committerVictor Julien <victor@inliniac.net>
Thu, 6 Mar 2014 08:33:49 +0000 (09:33 +0100)
PF_RING is delivering the packet with VLAN header stripped. This
patch updates the code to get the information from PF_RING extended
header information.

This patch uses the new function SCKernelVersionIsAtLeast to know
that we've got a old kernel that do not strip the VLAN header from
the message before sending it to userspace.

src/source-pfring.c

index 6c966083febc4b9de9849559d7ee3903b12f9690..1085cf0e1e71f221a24c38d26810f41ad05c80e7 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 Open Information Security Foundation
+/* Copyright (C) 2007-2014 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -46,6 +46,7 @@
 #include "util-checksum.h"
 #include "util-privs.h"
 #include "util-device.h"
+#include "util-host-info.h"
 #include "runmodes.h"
 
 #ifdef __SC_CUDA_SUPPORT__
@@ -140,6 +141,8 @@ typedef struct PfringThreadVars_
     ThreadVars *tv;
     TmSlot *slot;
 
+    int vlan_disabled;
+
     /* threads count */
     int threads;
 
@@ -234,6 +237,16 @@ 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) {
+        p->vlan_id[0] = h->extended_hdr.parsed_pkt.vlan_id;
+        p->vlan_idx = 1;
+        p->vlanh[0] = NULL;
+    }
+
     switch (ptv->checksum_mode) {
         case CHECKSUM_VALIDATION_RXONLY:
             if (h->extended_hdr.rx_direction == 0) {
@@ -407,6 +420,12 @@ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) {
 
     opflag = PF_RING_REENTRANT | PF_RING_PROMISC;
 
+    /* if suri uses VLAN and if we have a recent kernel, we need
+     * to use parsed_pkt to get VLAN info */
+    if ((! ptv->vlan_disabled) && SCKernelVersionIsAtLeast(3, 0)) {
+        opflag |= PF_RING_LONG_HEADER;
+    }
+
     if (ptv->checksum_mode == CHECKSUM_VALIDATION_RXONLY) {
         if (strncmp(ptv->interface, "dna", 3) == 0) {
             SCLogWarning(SC_ERR_INVALID_VALUE,
@@ -506,6 +525,20 @@ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) {
     }
 #endif /* HAVE_PFRING_ENABLE */
 
+    /* A bit strange to have this here but we only have vlan information
+     * during reading so we need to know if we want to keep vlan during
+     * the capture phase */
+    int vlanbool = 0;
+    if ((ConfGetBool("vlan.use-for-tracking", &vlanbool)) == 1 && vlanbool == 0) {
+        ptv->vlan_disabled = 1;
+    }
+
+    /* If kernel is older than 3.8, VLAN is not stripped so we don't
+     * get the info from packt extended header but we will use a standard
+     * parsing */
+    if (! SCKernelVersionIsAtLeast(3, 0)) {
+        ptv->vlan_disabled = 1;
+    }
 
     *data = (void *)ptv;
     pfconf->DerefFunc(pfconf);
@@ -589,6 +622,11 @@ TmEcode DecodePfring(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, Pac
     SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p));
     SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p));
 
+    /* If suri has set vlan during reading, we increase vlan counter */
+    if (p->vlan_idx) {
+        SCPerfCounterIncr(dtv->counter_vlan, tv->sc_perf_pca);
+    }
+
     DecodeEthernet(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
 
     PacketDecodeFinalize(tv, dtv, p);