]> git.ipfire.org Git - people/ms/suricata.git/commitdiff
flow: take vlan_id's into account in the flow hash
authorVictor Julien <victor@inliniac.net>
Thu, 11 Oct 2012 18:35:17 +0000 (20:35 +0200)
committerVictor Julien <victor@inliniac.net>
Wed, 24 Jul 2013 09:06:17 +0000 (11:06 +0200)
In VLAN we can have 2 layers of encapsulation. In this patch both
layers are used in the flow hash to distinguish between encapsulated
traffic.

src/decode-events.h
src/decode-vlan.c
src/decode.h
src/detect-engine-event.h
src/flow-hash.c
src/flow-util.c
src/flow.h

index 93cf8bc605c4062964508e875f415589f73958f2..06c9291a613eb248461a72e3c1dfa1c36966f6a3 100644 (file)
@@ -132,6 +132,7 @@ enum {
     /* VLAN EVENTS */
     VLAN_HEADER_TOO_SMALL,          /**< vlan header smaller than minimum size */
     VLAN_UNKNOWN_TYPE,              /**< vlan unknown type */
+    VLAN_HEADER_TOO_MANY_LAYERS,
 
     /* RAW EVENTS */
     IPRAW_INVALID_IPV,              /**< invalid ip version in ip raw */
index f49c316eea2a6e81f31a88cf69ac84dea7d68531..7130ed3a0cea4659e903c99e5016f5f3e227ef0d 100644 (file)
  */
 void DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
 {
+    uint32_t proto;
+
     SCPerfCounterIncr(dtv->counter_vlan, tv->sc_perf_pca);
 
     if(len < VLAN_HEADER_LEN)    {
         ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_SMALL);
         return;
     }
+    if (p->vlan_idx >= 2) {
+        ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS);
+        return;
+    }
 
-    p->vlanh = (VLANHdr *)pkt;
-    if(p->vlanh == NULL)
+    p->vlanh[p->vlan_idx] = (VLANHdr *)pkt;
+    if(p->vlanh[p->vlan_idx] == NULL)
         return;
 
+    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, GET_VLAN_PROTO(p->vlanh), GET_VLAN_PRIORITY(p->vlanh), GET_VLAN_CFI(p->vlanh), GET_VLAN_ID(p->vlanh), len);
+            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);
+
+    p->vlan_id[p->vlan_idx] = (uint16_t)GET_VLAN_ID(p->vlanh[p->vlan_idx]);
+    p->vlan_idx++;
 
-    switch (GET_VLAN_PROTO(p->vlanh))   {
+    switch (proto)   {
         case ETHERNET_TYPE_IP:
             DecodeIPV4(tv, dtv, p, pkt + VLAN_HEADER_LEN,
                        len - VLAN_HEADER_LEN, pq);
@@ -86,11 +98,16 @@ void DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt,
                                  len - VLAN_HEADER_LEN, pq);
             break;
         case ETHERNET_TYPE_VLAN:
-            DecodeVLAN(tv, dtv, p, pkt + VLAN_HEADER_LEN,
-                                 len - VLAN_HEADER_LEN, pq);
+            if (p->vlan_idx >= 2) {
+                ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS);
+                return;
+            } else {
+                DecodeVLAN(tv, dtv, p, pkt + VLAN_HEADER_LEN,
+                        len - VLAN_HEADER_LEN, pq);
+            }
             break;
         default:
-            SCLogDebug("unknown VLAN type: %" PRIx32 "",GET_VLAN_PROTO(p->vlanh));
+            SCLogDebug("unknown VLAN type: %" PRIx32 "", proto);
             ENGINE_SET_EVENT(p,VLAN_UNKNOWN_TYPE);
             return;
     }
index e3c2e61a39bdbe673971a32777d5df0626d5de65..3d96df622b3780a99ee8582381c6fa8dc4d58af0 100644 (file)
@@ -367,6 +367,9 @@ typedef struct Packet_
      * has the exact same tuple as the lower levels */
     uint8_t recursion_level;
 
+    uint16_t vlan_id[2];
+    uint8_t vlan_idx;
+
     /* Pkt Flags */
     uint32_t flags;
 
@@ -442,7 +445,7 @@ typedef struct Packet_
 
     GREHdr *greh;
 
-    VLANHdr *vlanh;
+    VLANHdr *vlanh[2];
 
     /* ptr to the payload of the packet
      * with it's length. */
@@ -634,6 +637,9 @@ typedef struct DecodeThreadVars_
         (p)->flags = (p)->flags & PKT_ALLOC;    \
         (p)->flowflags = 0;                     \
         (p)->pkt_src = 0;                       \
+        (p)->vlan_id[0] = 0;                    \
+        (p)->vlan_id[1] = 0;                    \
+        (p)->vlan_idx = 0;                      \
         FlowDeReference(&((p)->flow));          \
         (p)->ts.tv_sec = 0;                     \
         (p)->ts.tv_usec = 0;                    \
@@ -669,7 +675,8 @@ typedef struct DecodeThreadVars_
         (p)->pppoesh = NULL;                    \
         (p)->pppoedh = NULL;                    \
         (p)->greh = NULL;                       \
-        (p)->vlanh = NULL;                      \
+        (p)->vlanh[0] = NULL;                   \
+        (p)->vlanh[1] = NULL;                   \
         (p)->payload = NULL;                    \
         (p)->payload_len = 0;                   \
         (p)->pktlen = 0;                        \
index 4517de56ced0425eb70cbc246a041b74814d43f1..93bab8a936f64351bde57c58c8c28777df6d5ba8 100644 (file)
@@ -117,6 +117,7 @@ struct DetectEngineEvents_ {
     { "ipraw.invalid_ip_version",IPRAW_INVALID_IPV, },
     { "vlan.header_too_small",VLAN_HEADER_TOO_SMALL, },
     { "vlan.unknown_type",VLAN_UNKNOWN_TYPE, },
+    { "vlan.too_many_layers", VLAN_HEADER_TOO_MANY_LAYERS, },
     { "ipv4.frag_too_large", IPV4_FRAG_PKT_TOO_LARGE, },
     { "ipv4.frag_overlap", IPV4_FRAG_OVERLAP, },
     { "ipv6.frag_too_large", IPV6_FRAG_PKT_TOO_LARGE, },
index 0747633b89b4b6ec3c2c0fec0adb6626f7774903..1a80a30f0db01e024a70b45a140c8b3ab425b1c3 100644 (file)
@@ -172,8 +172,9 @@ typedef struct FlowHashKey4_ {
             uint16_t sp, dp;
             uint16_t proto; /**< u16 so proto and recur add up to u32 */
             uint16_t recur; /**< u16 so proto and recur add up to u32 */
+            uint16_t vlan_id[2];
         };
-        uint32_t u32[4];
+        const uint32_t u32[5];
     };
 } FlowHashKey4;
 
@@ -184,8 +185,9 @@ typedef struct FlowHashKey6_ {
             uint16_t sp, dp;
             uint16_t proto; /**< u16 so proto and recur add up to u32 */
             uint16_t recur; /**< u16 so proto and recur add up to u32 */
+            uint16_t vlan_id[2];
         };
-        uint32_t u32[10];
+        const uint32_t u32[11];
     };
 } FlowHashKey6;
 
@@ -224,8 +226,10 @@ static inline uint32_t FlowGetKey(Packet *p) {
             }
             fhk.proto = (uint16_t)p->proto;
             fhk.recur = (uint16_t)p->recursion_level;
+            fhk.vlan_id[0] = p->vlan_id[0];
+            fhk.vlan_id[1] = p->vlan_id[1];
 
-            uint32_t hash = hashword(fhk.u32, 4, flow_config.hash_rand);
+            uint32_t hash = hashword(fhk.u32, 5, flow_config.hash_rand);
             key = hash % flow_config.hash_size;
 
         } else if (ICMPV4_DEST_UNREACH_IS_VALID(p)) {
@@ -248,8 +252,10 @@ static inline uint32_t FlowGetKey(Packet *p) {
             }
             fhk.proto = (uint16_t)ICMPV4_GET_EMB_PROTO(p);
             fhk.recur = (uint16_t)p->recursion_level;
+            fhk.vlan_id[0] = p->vlan_id[0];
+            fhk.vlan_id[1] = p->vlan_id[1];
 
-            uint32_t hash = hashword(fhk.u32, 4, flow_config.hash_rand);
+            uint32_t hash = hashword(fhk.u32, 5, flow_config.hash_rand);
             key = hash % flow_config.hash_size;
 
         } else {
@@ -265,8 +271,10 @@ static inline uint32_t FlowGetKey(Packet *p) {
             fhk.dp = 0xbeef;
             fhk.proto = (uint16_t)p->proto;
             fhk.recur = (uint16_t)p->recursion_level;
+            fhk.vlan_id[0] = p->vlan_id[0];
+            fhk.vlan_id[1] = p->vlan_id[1];
 
-            uint32_t hash = hashword(fhk.u32, 4, flow_config.hash_rand);
+            uint32_t hash = hashword(fhk.u32, 5, flow_config.hash_rand);
             key = hash % flow_config.hash_size;
         }
     } else if (p->ip6h != NULL) {
@@ -299,8 +307,10 @@ static inline uint32_t FlowGetKey(Packet *p) {
         }
         fhk.proto = (uint16_t)p->proto;
         fhk.recur = (uint16_t)p->recursion_level;
+        fhk.vlan_id[0] = p->vlan_id[0];
+        fhk.vlan_id[1] = p->vlan_id[1];
 
-        uint32_t hash = hashword(fhk.u32, 10, flow_config.hash_rand);
+        uint32_t hash = hashword(fhk.u32, 11, flow_config.hash_rand);
         key = hash % flow_config.hash_size;
     } else
         key = 0;
@@ -318,7 +328,9 @@ static inline uint32_t FlowGetKey(Packet *p) {
        CMP_ADDR(&(f1)->dst, &(f2)->src) && \
        CMP_PORT((f1)->sp, (f2)->dp) && CMP_PORT((f1)->dp, (f2)->sp))) && \
      (f1)->proto == (f2)->proto && \
-     (f1)->recursion_level == (f2)->recursion_level)
+     (f1)->recursion_level == (f2)->recursion_level && \
+     (f1)->vlan_id[0] == (f2)->vlan_id[0] && \
+     (f1)->vlan_id[1] == (f2)->vlan_id[1])
 
 /**
  *  \brief See if a ICMP packet belongs to a flow by comparing the embedded
@@ -340,7 +352,9 @@ static inline int FlowCompareICMPv4(Flow *f, Packet *p) {
                 f->sp == p->icmpv4vars.emb_sport &&
                 f->dp == p->icmpv4vars.emb_dport &&
                 f->proto == ICMPV4_GET_EMB_PROTO(p) &&
-                f->recursion_level == p->recursion_level)
+                f->recursion_level == p->recursion_level &&
+                f->vlan_id[0] == p->vlan_id[0] &&
+                f->vlan_id[1] == p->vlan_id[1])
         {
             return 1;
 
@@ -351,7 +365,9 @@ static inline int FlowCompareICMPv4(Flow *f, Packet *p) {
                 f->dp == p->icmpv4vars.emb_sport &&
                 f->sp == p->icmpv4vars.emb_dport &&
                 f->proto == ICMPV4_GET_EMB_PROTO(p) &&
-                f->recursion_level == p->recursion_level)
+                f->recursion_level == p->recursion_level &&
+                f->vlan_id[0] == p->vlan_id[0] &&
+                f->vlan_id[1] == p->vlan_id[1])
         {
             return 1;
         }
index 5b4b3a715dcde3815d5f93669b469371ecfa97f1..93b227ad0cfda072860017ee4eb1c21c2f2378e0 100644 (file)
@@ -110,6 +110,8 @@ void FlowInit(Flow *f, Packet *p)
 
     f->proto = p->proto;
     f->recursion_level = p->recursion_level;
+    f->vlan_id[0] = p->vlan_id[0];
+    f->vlan_id[1] = p->vlan_id[1];
 
     if (PKT_IS_IPV4(p)) {
         FLOW_SET_IPV4_SRC_ADDR_FROM_PACKET(p, &f->src);
index 2c5096892aab9ba94e7e001f00666fbe8921590f..aa6311d00b088bed693b6ff73533da3c3cf13adc 100644 (file)
@@ -280,6 +280,7 @@ typedef struct Flow_
     };
     uint8_t proto;
     uint8_t recursion_level;
+    uint16_t vlan_id[2];
 
     /* end of flow "header" */