]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
Move over src and dst thresholding to use host table. Fix a bug in threshold 'both...
authorVictor Julien <victor@inliniac.net>
Wed, 14 Mar 2012 18:12:59 +0000 (19:12 +0100)
committerVictor Julien <victor@inliniac.net>
Wed, 14 Mar 2012 18:12:59 +0000 (19:12 +0100)
src/detect-detection-filter.c
src/detect-engine-threshold.c
src/detect-engine-threshold.h
src/detect-threshold.c
src/detect-threshold.h
src/detect.h
src/host-timeout.c
src/host.c
src/util-threshold-config.c

index 0bc2e6df5437d03e2e630ff7bc4cdedc7e8590da..6dd47bd535396f6f14a9717a8549a6c2ef9723e8 100644 (file)
@@ -29,6 +29,8 @@
 #include "decode.h"
 #include "detect.h"
 
+#include "host.h"
+
 #include "detect-detection-filter.h"
 #include "detect-threshold.h"
 #include "detect-parse.h"
@@ -404,6 +406,8 @@ static int DetectDetectionFilterTestSig1(void) {
     int result = 0;
     int alerts = 0;
 
+    HostInitConfig(HOST_QUIET);
+
     memset(&th_v, 0, sizeof(th_v));
 
     p = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
@@ -451,6 +455,7 @@ static int DetectDetectionFilterTestSig1(void) {
 
 end:
     UTHFreePackets(&p, 1);
+    HostShutdown();
     return result;
 }
 
@@ -472,6 +477,8 @@ static int DetectDetectionFilterTestSig2(void) {
     int alerts = 0;
     struct timeval ts;
 
+    HostInitConfig(HOST_QUIET);
+
     memset (&ts, 0, sizeof(struct timeval));
     TimeGet(&ts);
 
@@ -525,6 +532,7 @@ static int DetectDetectionFilterTestSig2(void) {
     DetectEngineCtxFree(de_ctx);
 end:
     UTHFreePackets(&p, 1);
+    HostShutdown();
     return result;
 }
 
index f6e4ddbaa51cdacaa890ab6ed7a4de3b5d985b92..bcab9a722e7f9195c4c2e757f41ba284a9be1559 100644 (file)
@@ -39,6 +39,7 @@
 #include "debug.h"
 #include "detect.h"
 #include "flow.h"
+#include "host.h"
 
 #include "detect-parse.h"
 #include "detect-engine-sigorder.h"
@@ -120,43 +121,6 @@ DetectThresholdData *SigGetThresholdType(Signature *sig, Packet *p)
     return SigGetThresholdTypeIter(sig, p, &psm);
 }
 
-/**
- * \brief Search for a threshold data into threshold hash table
- *
- * \param de_ctx Dectection Context
- * \param tsh_ptr Threshold element
- * \param p Packet structure
- *
- * \retval lookup_tsh Return the threshold element
- */
-DetectThresholdEntry *ThresholdHashSearch(DetectEngineCtx *de_ctx, DetectThresholdEntry *tsh_ptr, Packet *p)
-{
-    SCEnter();
-
-    DetectThresholdEntry *lookup_tsh = NULL;
-
-    SCLogDebug("tsh_ptr->track %u", tsh_ptr->track);
-
-    if (tsh_ptr->track == TRACK_DST) {
-        if (PKT_IS_IPV4(p)) {
-            SCLogDebug("ipv4 dst");
-            lookup_tsh = HashListTableLookup(de_ctx->ths_ctx.threshold_hash_table_dst, tsh_ptr, sizeof(DetectThresholdEntry));
-        } else if (PKT_IS_IPV6(p)) {
-            lookup_tsh = HashListTableLookup(de_ctx->ths_ctx.threshold_hash_table_dst_ipv6, tsh_ptr, sizeof(DetectThresholdEntry));
-        }
-    } else if (tsh_ptr->track == TRACK_SRC) {
-        if (PKT_IS_IPV4(p)) {
-            SCLogDebug("ipv4 src");
-            lookup_tsh = HashListTableLookup(de_ctx->ths_ctx.threshold_hash_table_src, tsh_ptr, sizeof(DetectThresholdEntry));
-        } else if (PKT_IS_IPV6(p))
-            lookup_tsh = HashListTableLookup(de_ctx->ths_ctx.threshold_hash_table_src_ipv6, tsh_ptr, sizeof(DetectThresholdEntry));
-    } else {
-        SCLogDebug("no track, weird");
-    }
-
-    SCReturnPtr(lookup_tsh, "DetectThresholdEntry");
-}
-
 /**
  * \brief Remove timeout threshold hash elements
  *
@@ -164,95 +128,50 @@ DetectThresholdEntry *ThresholdHashSearch(DetectEngineCtx *de_ctx, DetectThresho
  *
  */
 
-/** \todo In some conditions HashListtableRemove returns at dt->array = NULL
- *  Must need to check it
- **/
-
-static inline void ThresholdTimeoutRemove(DetectEngineCtx *de_ctx, struct timeval *tv)
+int ThresholdTimeoutCheck(Host *host, struct timeval *tv)
 {
-    HashListTableBucket *next = NULL;
-    HashListTableBucket *buck = HashListTableGetListHead(de_ctx->ths_ctx.threshold_hash_table_src);
-    while (buck != NULL) {
-        /* get the next before we free "buck" */
-        next = HashListTableGetListNext(buck);
-
-        DetectThresholdEntry *tsh = HashListTableGetListData(buck);
-        if (tsh == NULL)
-            goto next;
-
-        if ((tv->tv_sec - tsh->tv_sec1) <= tsh->seconds)
-            goto next;
-
-        switch(tsh->ipv) {
-            case 4:
-                if (tsh->track == TRACK_SRC) {
-                    HashListTableRemove(de_ctx->ths_ctx.threshold_hash_table_src,
-                            tsh, sizeof(DetectThresholdEntry));
-                } else if (tsh->track == TRACK_DST) {
-                    HashListTableRemove(de_ctx->ths_ctx.threshold_hash_table_dst,
-                            tsh, sizeof(DetectThresholdEntry));
-                }
-                break;
-            case 6:
-                if (tsh->track == TRACK_SRC) {
-                    HashListTableRemove(de_ctx->ths_ctx.threshold_hash_table_src_ipv6,
-                            tsh, sizeof(DetectThresholdEntry));
-                } else if (tsh->track == TRACK_DST) {
-                    HashListTableRemove(de_ctx->ths_ctx.threshold_hash_table_dst_ipv6,
-                            tsh, sizeof(DetectThresholdEntry));
-                }
-                break;
+    DetectThresholdEntry *tde = NULL;
+    DetectThresholdEntry *tmp = NULL;
+    DetectThresholdEntry *prev = NULL;
+    int retval = 1;
+
+    if (host->threshold == NULL)
+        return 1;
+
+    tmp = host->threshold;
+
+    prev = NULL;
+    while (tmp != NULL) {
+        if ((tv->tv_sec - tmp->tv_sec1) <= tmp->seconds) {
+            prev = tmp;
+            tmp = tmp->next;
+            retval = 0;
+            continue;
         }
-    next:
-        buck = next;
-    }
 
-    return;
-}
+        /* timed out */
 
-/**
- * \brief Add threshold element into hash table
- *
- * \param de_ctx Dectection Context
- * \param tsh_ptr Threshold element
- * \param p Packet structure
- *
- */
-void ThresholdHashAdd(DetectEngineCtx *de_ctx, DetectThresholdEntry *tsh_ptr, Packet *p)
-{
-    SCEnter();
+        if (prev != NULL) {
+            prev->next = tmp->next;
 
-    int ret = 0;
+            tde = tmp;
+            tmp = tde->next;
 
-    switch(tsh_ptr->ipv) {
-        case 4:
-            if (tsh_ptr->track == TRACK_DST) {
-                ret = HashListTableAdd(de_ctx->ths_ctx.threshold_hash_table_dst,
-                        tsh_ptr, sizeof(DetectThresholdEntry));
-            } else if (tsh_ptr->track == TRACK_SRC) {
-                ret = HashListTableAdd(de_ctx->ths_ctx.threshold_hash_table_src,
-                        tsh_ptr, sizeof(DetectThresholdEntry));
-            }
-            break;
-        case 6:
-            if (tsh_ptr->track == TRACK_DST)
-                ret = HashListTableAdd(de_ctx->ths_ctx.threshold_hash_table_dst_ipv6,
-                        tsh_ptr, sizeof(DetectThresholdEntry));
-            else if (tsh_ptr->track == TRACK_SRC)
-                ret =  HashListTableAdd(de_ctx->ths_ctx.threshold_hash_table_src_ipv6,
-                        tsh_ptr, sizeof(DetectThresholdEntry));
-            break;
-    }
+            SCFree(tde);
+        } else {
+            host->threshold = tmp->next;
+
+            tde = tmp;
+            tmp = tde->next;
 
-    if(ret == -1)   {
-        SCLogError(SC_ERR_THRESHOLD_HASH_ADD,
-                "failed to add element into the hash table");
+            SCFree(tde);
+        }
     }
 
-    SCReturn;
+    return retval;
 }
 
-static inline DetectThresholdEntry *DetectThresholdEntryAlloc(DetectThresholdData *td, Packet *p, Signature *s) {
+static inline DetectThresholdEntry *DetectThresholdEntryAlloc(DetectThresholdData *td, Packet *p, uint32_t sid, uint32_t gid) {
     SCEnter();
 
     DetectThresholdEntry *ste = SCMalloc(sizeof(DetectThresholdEntry));
@@ -260,19 +179,8 @@ static inline DetectThresholdEntry *DetectThresholdEntryAlloc(DetectThresholdDat
         SCReturnPtr(NULL, "DetectThresholdEntry");
     }
 
-    if (PKT_IS_IPV4(p))
-        ste->ipv = 4;
-    else if (PKT_IS_IPV6(p))
-        ste->ipv = 6;
-
-    ste->sid = s->id;
-    ste->gid = s->gid;
-
-    if (td->track == TRACK_DST) {
-        COPY_ADDRESS(&p->dst, &ste->addr);
-    } else if (td->track == TRACK_SRC) {
-        COPY_ADDRESS(&p->src, &ste->addr);
-    }
+    ste->sid = sid;
+    ste->gid = gid;
 
     ste->track = td->track;
     ste->seconds = td->seconds;
@@ -281,66 +189,36 @@ static inline DetectThresholdEntry *DetectThresholdEntryAlloc(DetectThresholdDat
     SCReturnPtr(ste, "DetectThresholdEntry");
 }
 
-/**
- * \brief Make the threshold logic for signatures
- *
- * \param de_ctx Dectection Context
- * \param tsh_ptr Threshold element
- * \param p Packet structure
- * \param s Signature structure
- *
- * \retval 1 alert on this event
- * \retval 0 do not alert on this event
- */
-int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
-        DetectThresholdData *td, Packet *p, Signature *s)
+static DetectThresholdEntry *ThresholdHostLookupEntry(Host *h, uint32_t sid, uint32_t gid)
 {
-    SCEnter();
+    DetectThresholdEntry *e = h->threshold;
 
-    int ret = 0;
-    DetectThresholdEntry *lookup_tsh = NULL;
-    DetectThresholdEntry ste;
-
-    if (td == NULL) {
-        SCReturnInt(0);
-    }
-
-    /* setup the Entry we use to search our hash with */
-    if (PKT_IS_IPV4(p))
-        ste.ipv = 4;
-    else if (PKT_IS_IPV6(p))
-        ste.ipv = 6;
-    else {
-        SCReturnInt(0);
+    for (e = h->threshold; e != NULL; e = e->next) {
+        if (e->sid == sid && e->gid == gid)
+            break;
     }
 
-    ste.sid = s->id;
-    ste.gid = s->gid;
+    return e;
+}
 
-    if (td->track == TRACK_DST) {
-        COPY_ADDRESS(&p->dst, &ste.addr);
-    } else if (td->track == TRACK_SRC) {
-        COPY_ADDRESS(&p->src, &ste.addr);
-    }
+int ThresholdHandlePacketHost(Host *h, Packet *p, DetectThresholdData *td, uint32_t sid, uint32_t gid) {
+    int ret = 0;
 
-    ste.track = td->track;
-    ste.seconds = td->seconds;
+    DetectThresholdEntry *lookup_tsh = ThresholdHostLookupEntry(h, sid, gid);
+    SCLogDebug("lookup_tsh %p sid %u gid %u", lookup_tsh, sid, gid);
 
-    SCMutexLock(&de_ctx->ths_ctx.threshold_table_lock);
     switch(td->type)   {
         case TYPE_LIMIT:
         {
             SCLogDebug("limit");
 
-            lookup_tsh = ThresholdHashSearch(de_ctx, &ste, p);
-            SCLogDebug("lookup_tsh %p", lookup_tsh);
-
             if (lookup_tsh != NULL)  {
                 if ((p->ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) {
-                    if (lookup_tsh->current_count < td->count) {
+                    lookup_tsh->current_count++;
+
+                    if (lookup_tsh->current_count <= td->count) {
                         ret = 1;
                     }
-                    lookup_tsh->current_count++;
                 } else    {
                     lookup_tsh->tv_sec1 = p->ts.tv_sec;
                     lookup_tsh->current_count = 1;
@@ -348,18 +226,18 @@ int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx
                     ret = 1;
                 }
             } else {
-                DetectThresholdEntry *e = DetectThresholdEntryAlloc(td, p, s);
+                DetectThresholdEntry *e = DetectThresholdEntryAlloc(td, p, sid, gid);
                 if (e == NULL) {
                     break;
                 }
 
                 e->tv_sec1 = p->ts.tv_sec;
                 e->current_count = 1;
-                e->ipv = ste.ipv;
 
                 ret = 1;
 
-                ThresholdHashAdd(de_ctx, e, p);
+                e->next = h->threshold;
+                h->threshold = e;
             }
             break;
         }
@@ -367,7 +245,6 @@ int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx
         {
             SCLogDebug("threshold");
 
-            lookup_tsh = ThresholdHashSearch(de_ctx, &ste, p);
             if (lookup_tsh != NULL)  {
                 if ((p->ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) {
                     lookup_tsh->current_count++;
@@ -384,16 +261,16 @@ int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx
                 if (td->count == 1)  {
                     ret = 1;
                 } else {
-                    DetectThresholdEntry *e = DetectThresholdEntryAlloc(td, p, s);
+                    DetectThresholdEntry *e = DetectThresholdEntryAlloc(td, p, sid, gid);
                     if (e == NULL) {
                         break;
                     }
 
                     e->current_count = 1;
                     e->tv_sec1 = p->ts.tv_sec;
-                    e->ipv = ste.ipv;
 
-                    ThresholdHashAdd(de_ctx, e, p);
+                    e->next = h->threshold;
+                    h->threshold = e;
                 }
             }
             break;
@@ -402,28 +279,35 @@ int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx
         {
             SCLogDebug("both");
 
-            lookup_tsh = ThresholdHashSearch(de_ctx, &ste, p);
             if (lookup_tsh != NULL) {
                 if ((p->ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) {
+                    /* within time limit */
+
                     lookup_tsh->current_count++;
                     if (lookup_tsh->current_count == td->count) {
                         ret = 1;
                     }
-                } else    {
+                } else {
+                    /* expired, so reset */
                     lookup_tsh->tv_sec1 = p->ts.tv_sec;
                     lookup_tsh->current_count = 1;
+
+                    /* if we have a limit of 1, this is a match */
+                    if (lookup_tsh->current_count == td->count) {
+                        ret = 1;
+                    }
                 }
             } else {
-                DetectThresholdEntry *e = DetectThresholdEntryAlloc(td, p, s);
+                DetectThresholdEntry *e = DetectThresholdEntryAlloc(td, p, sid, gid);
                 if (e == NULL) {
                     break;
                 }
 
                 e->current_count = 1;
                 e->tv_sec1 = p->ts.tv_sec;
-                e->ipv = ste.ipv;
 
-                ThresholdHashAdd(de_ctx, e, p);
+                e->next = h->threshold;
+                h->threshold = e;
 
                 /* for the first match we return 1 to
                  * indicate we should alert */
@@ -438,32 +322,39 @@ int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx
         {
             SCLogDebug("detection_filter");
 
-            lookup_tsh = ThresholdHashSearch(de_ctx, &ste, p);
             if (lookup_tsh != NULL) {
                 if ((p->ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) {
+                    /* within timeout */
+
                     lookup_tsh->current_count++;
                     if (lookup_tsh->current_count >= td->count) {
                         ret = 1;
                     }
                 } else {
+                    /* expired, reset */
+
                     lookup_tsh->tv_sec1 = p->ts.tv_sec;
                     lookup_tsh->current_count = 1;
+
+                    if (td->count == 1) {
+                        ret = 1;
+                    }
                 }
             } else {
                 if (td->count == 1) {
                     ret = 1;
                 }
 
-                DetectThresholdEntry *e = DetectThresholdEntryAlloc(td, p, s);
+                DetectThresholdEntry *e = DetectThresholdEntryAlloc(td, p, sid, gid);
                 if (e == NULL) {
                     break;
                 }
 
                 e->current_count = 1;
                 e->tv_sec1 = p->ts.tv_sec;
-                e->ipv = ste.ipv;
 
-                ThresholdHashAdd(de_ctx, e, p);
+                e->next = h->threshold;
+                h->threshold = e;
             }
             break;
         }
@@ -472,12 +363,6 @@ int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx
         {
             SCLogDebug("rate_filter");
 
-            /* tracking by src/dst or by rule? */
-            if (td->track != TRACK_RULE)
-                lookup_tsh = ThresholdHashSearch(de_ctx, &ste, p);
-            else
-                lookup_tsh = (DetectThresholdEntry *)de_ctx->ths_ctx.th_entry[s->num];
-
             if (lookup_tsh != NULL) {
                 /* Check if we have a timeout enabled, if so,
                  * we still matching (and enabling the new_action) */
@@ -543,7 +428,7 @@ int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx
                     ret = 1;
                 }
 
-                DetectThresholdEntry *e = DetectThresholdEntryAlloc(td, p, s);
+                DetectThresholdEntry *e = DetectThresholdEntryAlloc(td, p, sid, gid);
                 if (e == NULL) {
                     break;
                 }
@@ -551,13 +436,9 @@ int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx
                 e->current_count = 1;
                 e->tv_sec1 = p->ts.tv_sec;
                 e->tv_timeout = 0;
-                e->ipv = ste.ipv;
 
-                /** The track is by src/dst or by rule? */
-                if (td->track != TRACK_RULE)
-                    ThresholdHashAdd(de_ctx, e, p);
-                else
-                    de_ctx->ths_ctx.th_entry[s->num] = e;
+                e->next = h->threshold;
+                h->threshold = e;
             }
             break;
         }
@@ -585,74 +466,134 @@ int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx
             SCLogError(SC_ERR_INVALID_VALUE, "type %d is not supported", td->type);
     }
 
-    /* handle timing out entries */
-    ThresholdTimeoutRemove(de_ctx, &p->ts);
-
-    SCMutexUnlock(&de_ctx->ths_ctx.threshold_table_lock);
-    SCReturnInt(ret);
+    return ret;
 }
 
-void ThresholdFreeFunc(void *data)
-{
-    if (data != NULL)
-        SCFree(data);
-    return;
-}
+static int ThresholdHandlePacketRule(DetectEngineCtx *de_ctx, Packet *p, DetectThresholdData *td, Signature *s) {
+    int ret = 0;
 
-/**
- * \brief Compare elements into the hash table
- *
- * \param data1 First element to compare
- * \param len1 length of first element
- * \param data2 Second element to compare
- * \param len2 length of second element
- *
- * \retval 1 Match or 0 No Match
- */
-char ThresholdCompareFunc(void *data1, uint16_t len1, void *data2,uint16_t len2)
-{
-    SCEnter();
+    if (td->type != TYPE_RATE)
+        return 1;
+
+    DetectThresholdEntry* lookup_tsh = (DetectThresholdEntry *)de_ctx->ths_ctx.th_entry[s->num];
+    if (lookup_tsh != NULL) {
+        /* Check if we have a timeout enabled, if so,
+         * we still matching (and enabling the new_action) */
+        if ( (p->ts.tv_sec - lookup_tsh->tv_timeout) > td->timeout) {
+            /* Ok, we are done, timeout reached */
+            td->timeout = 0;
+        } else {
+            /* Already matching */
+            /* Take the action to perform */
+            switch (td->new_action) {
+                case TH_ACTION_ALERT:
+                    ALERT_PACKET(p);
+                    break;
+                case TH_ACTION_DROP:
+                    DROP_PACKET(p);
+                    break;
+                case TH_ACTION_REJECT:
+                    REJECT_PACKET(p);
+                    break;
+                case TH_ACTION_PASS:
+                    PASS_PACKET(p);
+                    break;
+                default:
+                    /* Weird, leave the default action */
+                    break;
+            }
+            ret = 1;
+        }
+
+        /* Update the matching state with the timeout interval */
+        if ( (p->ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) {
+            lookup_tsh->current_count++;
+            if (lookup_tsh->current_count >= td->count) {
+                /* Then we must enable the new action by setting a
+                 * timeout */
+                lookup_tsh->tv_timeout = p->ts.tv_sec;
+                /* Take the action to perform */
+                switch (td->new_action) {
+                    case TH_ACTION_ALERT:
+                        ALERT_PACKET(p);
+                        break;
+                    case TH_ACTION_DROP:
+                        DROP_PACKET(p);
+                        break;
+                    case TH_ACTION_REJECT:
+                        REJECT_PACKET(p);
+                        break;
+                    case TH_ACTION_PASS:
+                        PASS_PACKET(p);
+                        break;
+                    default:
+                        /* Weird, leave the default action */
+                        break;
+                }
+                ret = 1;
+            }
+        } else {
+            lookup_tsh->tv_sec1 = p->ts.tv_sec;
+            lookup_tsh->current_count = 1;
+        }
+    } else {
+        if (td->count == 1) {
+            ret = 1;
+        }
 
-    DetectThresholdEntry *a = (DetectThresholdEntry *)data1;
-    DetectThresholdEntry *b = (DetectThresholdEntry *)data2;
+        DetectThresholdEntry *e = DetectThresholdEntryAlloc(td, p, s->id, s->gid);
+        if (e != NULL) {
+            e->current_count = 1;
+            e->tv_sec1 = p->ts.tv_sec;
+            e->tv_timeout = 0;
 
-    if ((a->sid == b->sid) && (a->gid == b->gid) &&
-            (CMP_ADDR(&a->addr,&b->addr)))
-    {
-        SCReturnInt(1);
+            de_ctx->ths_ctx.th_entry[s->num] = e;
+        }
     }
 
-    SCReturnInt(0);
+    return ret;
 }
 
 /**
- * \brief Create the hash for threshold tables
+ * \brief Make the threshold logic for signatures
  *
- * \param ht Hash Table
- * \param data Data that will be used to create the hash
- * \param datalen Data length
+ * \param de_ctx Dectection Context
+ * \param tsh_ptr Threshold element
+ * \param p Packet structure
+ * \param s Signature structure
  *
- * \retval hash the hash
+ * \retval 1 alert on this event
+ * \retval 0 do not alert on this event
  */
-uint32_t ThresholdHashFunc(HashListTable *ht, void *data, uint16_t datalen)
+int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
+        DetectThresholdData *td, Packet *p, Signature *s)
 {
     SCEnter();
 
-    DetectThresholdEntry *dt = (DetectThresholdEntry *)data;
-    uint32_t hash = 0;
-
-    if (dt->ipv == 4)
-        hash = (dt->sid + dt->gid + dt->addr.addr_data32[0]);
-    else if (dt->ipv == 6)
-        hash = (dt->sid + dt->gid + dt->addr.addr_data32[0] +
-                dt->addr.addr_data32[1] +
-                dt->addr.addr_data32[2] +
-                dt->addr.addr_data32[3]);
-    else {
-        SCLogDebug("no dt->ipv");
+    int ret = 0;
+    if (td == NULL) {
+        SCReturnInt(0);
     }
 
-    SCReturnInt(hash % THRESHOLD_HASH_SIZE);
+    if (td->track == TRACK_SRC) {
+        Host *src = HostGetHostFromHash(&p->src);
+        if (src) {
+            ret = ThresholdHandlePacketHost(src,p,td,s->id,s->gid);
+            HostRelease(src);
+        }
+    } else if (td->track == TRACK_DST) {
+        Host *dst = HostGetHostFromHash(&p->dst);
+        if (dst) {
+            ret = ThresholdHandlePacketHost(dst,p,td,s->id,s->gid);
+            HostRelease(dst);
+        }
+    } else if (td->track == TRACK_RULE) {
+        SCMutexLock(&de_ctx->ths_ctx.threshold_table_lock);
+        ret = ThresholdHandlePacketRule(de_ctx,p,td,s);
+        SCMutexUnlock(&de_ctx->ths_ctx.threshold_table_lock);
+    }
+
+    SCReturnInt(ret);
 }
 
 /**
@@ -663,44 +604,10 @@ uint32_t ThresholdHashFunc(HashListTable *ht, void *data, uint16_t datalen)
  */
 void ThresholdHashInit(DetectEngineCtx *de_ctx)
 {
-    if (de_ctx->ths_ctx.threshold_hash_table_dst == NULL ||
-        de_ctx->ths_ctx.threshold_hash_table_src == NULL ||
-        de_ctx->ths_ctx.threshold_hash_table_src_ipv6 == NULL ||
-        de_ctx->ths_ctx.threshold_hash_table_dst_ipv6 == NULL) {
-
-        de_ctx->ths_ctx.threshold_hash_table_dst = HashListTableInit(THRESHOLD_HASH_SIZE, ThresholdHashFunc, ThresholdCompareFunc, ThresholdFreeFunc);
-        if(de_ctx->ths_ctx.threshold_hash_table_dst == NULL)    {
-            SCLogError(SC_ERR_MEM_ALLOC,
-                    "Threshold: Failed to initialize ipv4 dst hash table.");
-            exit(EXIT_FAILURE);
-        }
-
-        de_ctx->ths_ctx.threshold_hash_table_src = HashListTableInit(THRESHOLD_HASH_SIZE, ThresholdHashFunc, ThresholdCompareFunc, ThresholdFreeFunc);
-        if(de_ctx->ths_ctx.threshold_hash_table_dst == NULL)    {
-            SCLogError(SC_ERR_MEM_ALLOC,
-                    "Threshold: Failed to initialize ipv4 src hash table.");
-            exit(EXIT_FAILURE);
-        }
-
-        de_ctx->ths_ctx.threshold_hash_table_src_ipv6 = HashListTableInit(THRESHOLD_HASH_SIZE, ThresholdHashFunc, ThresholdCompareFunc, ThresholdFreeFunc);
-        if(de_ctx->ths_ctx.threshold_hash_table_dst == NULL)    {
-            SCLogError(SC_ERR_MEM_ALLOC,
-                    "Threshold: Failed to initialize ipv6 src hash table.");
-            exit(EXIT_FAILURE);
-        }
-
-        de_ctx->ths_ctx.threshold_hash_table_dst_ipv6 = HashListTableInit(THRESHOLD_HASH_SIZE, ThresholdHashFunc, ThresholdCompareFunc, ThresholdFreeFunc);
-        if(de_ctx->ths_ctx.threshold_hash_table_dst == NULL)    {
-            SCLogError(SC_ERR_MEM_ALLOC,
-                    "Threshold: Failed to initialize ipv6 dst hash table.");
-            exit(EXIT_FAILURE);
-        }
-
-        if (SCMutexInit(&de_ctx->ths_ctx.threshold_table_lock, NULL) != 0) {
-            SCLogError(SC_ERR_MEM_ALLOC,
-                    "Threshold: Failed to initialize hash table mutex.");
-            exit(EXIT_FAILURE);
-        }
+    if (SCMutexInit(&de_ctx->ths_ctx.threshold_table_lock, NULL) != 0) {
+        SCLogError(SC_ERR_MEM_ALLOC,
+                "Threshold: Failed to initialize hash table mutex.");
+        exit(EXIT_FAILURE);
     }
 }
 
@@ -712,12 +619,27 @@ void ThresholdHashInit(DetectEngineCtx *de_ctx)
  */
 void ThresholdContextDestroy(DetectEngineCtx *de_ctx)
 {
-    HashListTableFree(de_ctx->ths_ctx.threshold_hash_table_dst);
-    HashListTableFree(de_ctx->ths_ctx.threshold_hash_table_src);
-    HashListTableFree(de_ctx->ths_ctx.threshold_hash_table_dst_ipv6);
-    HashListTableFree(de_ctx->ths_ctx.threshold_hash_table_src_ipv6);
     if (de_ctx->ths_ctx.th_entry != NULL)
         SCFree(de_ctx->ths_ctx.th_entry);
+    SCMutexDestroy(&de_ctx->ths_ctx.threshold_table_lock);
+}
+
+/**
+ * \brief this function will free all the entries of a list
+ *        DetectTagDataEntry
+ *
+ * \param td pointer to DetectTagDataEntryList
+ */
+void ThresholdListFree(void *ptr) {
+    if (ptr != NULL) {
+        DetectThresholdEntry *entry = ptr;
+
+        while (entry != NULL) {
+            DetectThresholdEntry *next_entry = entry->next;
+            SCFree(entry);
+            entry = next_entry;
+        }
+    }
 }
 
 /**
index b547a636cc64f3bd8a0eb0844f467b26ba62e8d2..cc3df5679260b1c2867f7b1e148b6935631f5076 100644 (file)
 #define __DETECT_ENGINE_THRESHOLD_H__
 
 #include "detect.h"
-
-#define THRESHOLD_HASH_SIZE 0xffff
+#include "host.h"
 
 DetectThresholdData *SigGetThresholdType(Signature *, Packet *);
-DetectThresholdData *SigGetThresholdTypeIter(Signature *sig, Packet *p, SigMatch **psm);
+DetectThresholdData *SigGetThresholdTypeIter(Signature *, Packet *, SigMatch **);
 int PacketAlertThreshold(DetectEngineCtx *, DetectEngineThreadCtx *,
                           DetectThresholdData *, Packet *, Signature *);
-void ThresholdFreeFunc(void *data);
-char ThresholdCompareFunc(void *data1, uint16_t len1, void *data2,uint16_t len2);
-uint32_t ThresholdHashFunc(HashListTable *ht, void *data, uint16_t datalen);
-void ThresholdHashInit(DetectEngineCtx *de_ctx);
-void ThresholdContextDestroy(DetectEngineCtx *de_ctx);
+
+void ThresholdHashInit(DetectEngineCtx *);
+void ThresholdContextDestroy(DetectEngineCtx *);
+
+int ThresholdTimeoutCheck(Host *, struct timeval *);
+void ThresholdListFree(void *ptr);
 
 #endif /* __DETECT_ENGINE_THRESHOLD_H__ */
index d1c181ca3940bb7ab644cb652e98e83262bcd65c..035ee71a5781a6e59b6b025c88ba90bad651cedc 100644 (file)
@@ -35,6 +35,8 @@
 #include "suricata.h"
 #include "decode.h"
 
+#include "host.h"
+
 #include "detect.h"
 #include "detect-parse.h"
 
@@ -401,6 +403,8 @@ static int DetectThresholdTestSig1(void) {
     int result = 0;
     int alerts = 0;
 
+    HostInitConfig(HOST_QUIET);
+
     memset(&th_v, 0, sizeof(th_v));
 
     p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
@@ -428,20 +432,44 @@ static int DetectThresholdTestSig1(void) {
 
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
     alerts = PacketAlertCheck(p, 1);
+    if (alerts != 1) {
+        printf("alerts %"PRIi32", expected 1: ", alerts);
+    }
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
     alerts += PacketAlertCheck(p, 1);
+    if (alerts != 2) {
+        printf("alerts %"PRIi32", expected 2: ", alerts);
+    }
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
     alerts += PacketAlertCheck(p, 1);
+    if (alerts != 3) {
+        printf("alerts %"PRIi32", expected 3: ", alerts);
+    }
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
     alerts += PacketAlertCheck(p, 1);
+    if (alerts != 4) {
+        printf("alerts %"PRIi32", expected 4: ", alerts);
+    }
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
     alerts += PacketAlertCheck(p, 1);
+    if (alerts != 5) {
+        printf("alerts %"PRIi32", expected 5: ", alerts);
+    }
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
     alerts += PacketAlertCheck(p, 1);
+    if (alerts != 5) {
+        printf("alerts %"PRIi32", expected 5: ", alerts);
+    }
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
     alerts += PacketAlertCheck(p, 1);
+    if (alerts != 5) {
+        printf("alerts %"PRIi32", expected 5: ", alerts);
+    }
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
     alerts += PacketAlertCheck(p, 1);
+    if (alerts != 5) {
+        printf("alerts %"PRIi32", expected 5: ", alerts);
+    }
 
     if(alerts == 5)
         result = 1;
@@ -455,6 +483,8 @@ static int DetectThresholdTestSig1(void) {
     DetectEngineCtxFree(de_ctx);
 
     UTHFreePackets(&p, 1);
+
+    HostShutdown();
 end:
     return result;
 }
@@ -476,6 +506,8 @@ static int DetectThresholdTestSig2(void) {
     int result = 0;
     int alerts = 0;
 
+    HostInitConfig(HOST_QUIET);
+
     memset(&th_v, 0, sizeof(th_v));
 
     p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
@@ -530,6 +562,7 @@ cleanup:
 
 end:
     UTHFreePackets(&p, 1);
+    HostShutdown();
     return result;
 }
 
@@ -550,9 +583,9 @@ static int DetectThresholdTestSig3(void) {
     int result = 0;
     int alerts = 0;
     struct timeval ts;
-    DetectThresholdData *td = NULL;
     DetectThresholdEntry *lookup_tsh = NULL;
-    DetectThresholdEntry *ste = NULL;
+
+    HostInitConfig(HOST_QUIET);
 
     memset (&ts, 0, sizeof(struct timeval));
     TimeGet(&ts);
@@ -576,41 +609,25 @@ static int DetectThresholdTestSig3(void) {
     SigGroupBuild(de_ctx);
     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 
-    td = SigGetThresholdType(s,p);
-
-    /* setup the Entry we use to search our hash with */
-    ste = SCMalloc(sizeof(DetectThresholdEntry));
-    if (ste == NULL)
-        goto end;
-    memset(ste, 0x00, sizeof(*ste));
-
-    if (PKT_IS_IPV4(p))
-        ste->ipv = 4;
-    else if (PKT_IS_IPV6(p))
-        ste->ipv = 6;
-
-    ste->sid = s->id;
-    ste->gid = s->gid;
-
-    if (td->track == TRACK_DST) {
-        COPY_ADDRESS(&p->dst, &ste->addr);
-    } else if (td->track == TRACK_SRC) {
-        COPY_ADDRESS(&p->src, &ste->addr);
-    }
-
-    ste->track = td->track;
-
     TimeGet(&p->ts);
 
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
 
-    lookup_tsh = (DetectThresholdEntry *)HashListTableLookup(de_ctx->ths_ctx.threshold_hash_table_dst, ste, sizeof(DetectThresholdEntry));
+    Host *host = HostLookupHostFromHash(&p->dst);
+    if (host == NULL) {
+        printf("host not found: ");
+        goto cleanup;
+    }
+
+    lookup_tsh = (DetectThresholdEntry *)host->threshold;
     if (lookup_tsh == NULL) {
+        HostRelease(host);
         printf("lookup_tsh is NULL: ");
         goto cleanup;
     }
+    HostRelease(host);
 
     TimeSetIncrementTime(200);
     TimeGet(&p->ts);
@@ -619,8 +636,21 @@ static int DetectThresholdTestSig3(void) {
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
 
-    if (lookup_tsh)
-        alerts = lookup_tsh->current_count;
+    host = HostLookupHostFromHash(&p->dst);
+    if (host == NULL) {
+        printf("host not found: ");
+        goto cleanup;
+    }
+    HostRelease(host);
+
+    lookup_tsh = (DetectThresholdEntry *)host->threshold;
+    if (lookup_tsh == NULL) {
+        HostRelease(host);
+        printf("lookup_tsh is NULL: ");
+        goto cleanup;
+    }
+
+    alerts = lookup_tsh->current_count;
 
     if (alerts == 3)
         result = 1;
@@ -637,6 +667,7 @@ cleanup:
     DetectEngineCtxFree(de_ctx);
 end:
     UTHFreePackets(&p, 1);
+    HostShutdown();
     return result;
 }
 
@@ -658,6 +689,8 @@ static int DetectThresholdTestSig4(void) {
     int alerts = 0;
     struct timeval ts;
 
+    HostInitConfig(HOST_QUIET);
+
     memset (&ts, 0, sizeof(struct timeval));
     TimeGet(&ts);
 
@@ -711,6 +744,7 @@ cleanup:
     DetectEngineCtxFree(de_ctx);
 end:
     UTHFreePackets(&p, 1);
+    HostShutdown();
     return result;
 }
 
@@ -731,6 +765,8 @@ static int DetectThresholdTestSig5(void) {
     int result = 0;
     int alerts = 0;
 
+    HostInitConfig(HOST_QUIET);
+
     memset(&th_v, 0, sizeof(th_v));
     p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
 
@@ -793,6 +829,7 @@ cleanup:
 
 end:
     UTHFreePackets(&p, 1);
+    HostShutdown();
     return result;
 }
 
@@ -804,6 +841,8 @@ static int DetectThresholdTestSig6Ticks(void) {
     int result = 0;
     int alerts = 0;
 
+    HostInitConfig(HOST_QUIET);
+
     memset(&th_v, 0, sizeof(th_v));
     p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
 
@@ -872,6 +911,7 @@ cleanup:
 
 end:
     UTHFreePackets(&p, 1);
+    HostShutdown();
     return result;
 }
 #endif /* UNITTESTS */
index 68f485e69f541e27fdf762021814fe97af9931e6..e71bcb9afc4ba481841288b4d0d16a973f27cdb2 100644 (file)
@@ -55,8 +55,6 @@
 typedef struct DetectThresholdData_ {
     uint32_t count;     /**< Event count */
     uint32_t seconds;   /**< Event seconds */
-    uint32_t sid;       /**< Signature id */
-    uint8_t gid;        /**< Signature group id */
     uint8_t type;       /**< Threshold type : limit , threshold, both, detection_filter */
     uint8_t track;      /**< Track type: by_src, by_dst */
     uint8_t new_action; /**< new_action alert|drop|pass|log|sdrop|reject */
@@ -66,16 +64,17 @@ typedef struct DetectThresholdData_ {
 } DetectThresholdData;
 
 typedef struct DetectThresholdEntry_ {
+    uint32_t sid;           /**< Signature id */
+    uint32_t gid;           /**< Signature group id */
+
     uint32_t tv_timeout;    /**< Timeout for new_action (for rate_filter)
                                  its not "seconds", that define the time interval */
     uint32_t seconds;       /**< Event seconds */
-    uint32_t sid;           /**< Signature id */
     uint32_t tv_sec1;       /**< Var for time control */
     uint32_t current_count; /**< Var for count control */
-    Address addr;           /**< Var used to store dst or src addr */
-    uint8_t gid;            /**< Signature group id */
-    uint8_t ipv;            /**< Packet ip version */
-    uint8_t track;          /**< Track type: by_src, by_src */
+    int track;          /**< Track type: by_src, by_src */
+
+    struct DetectThresholdEntry_ *next;
 } DetectThresholdEntry;
 
 
index 62f34aad2da84fe9ed7b3947920d9236b6005475..d2a609e16043a0c75d59004d9e8b5f07791b3000 100644 (file)
@@ -514,10 +514,6 @@ typedef struct MpmPatternIdStore_ {
 
 /** \brief threshold ctx */
 typedef struct ThresholdCtx_    {
-    HashListTable *threshold_hash_table_dst;        /**< Ipv4 dst hash table */
-    HashListTable *threshold_hash_table_src;        /**< Ipv4 src hash table */
-    HashListTable *threshold_hash_table_dst_ipv6;   /**< Ipv6 dst hash table */
-    HashListTable *threshold_hash_table_src_ipv6;   /**< Ipv6 src hash table */
     SCMutex threshold_table_lock;                   /**< Mutex for hash table */
 
     /** to support rate_filter "by_rule" option */
index 991d90f004fbfb219c4c0175a5087978161203f2..21b33c168325de207529adce911892ac45876092 100644 (file)
@@ -23,7 +23,9 @@
 
 #include "suricata-common.h"
 #include "host.h"
+
 #include "detect-engine-tag.h"
+#include "detect-engine-threshold.h"
 
 uint32_t HostGetSpareCount(void) {
     return HostSpareQueueGetSize();
@@ -55,8 +57,8 @@ static int HostHostTimedOut(Host *h, struct timeval *ts) {
     if (h->tag && TagTimeoutCheck(h, ts) == 0) {
         tags = 1;
     }
-    if (h->threshold) {
-        // run threshold cleanup
+    if (h->threshold && ThresholdTimeoutCheck(h, ts) == 0) {
+        thresholds = 1;
     }
 
     if (tags || thresholds)
index 007619b679b5704fb3ad53670d03b7ed5b129e2c..7fbf08d303ab2da78f784e0772e3001cbfc22017 100644 (file)
@@ -36,6 +36,7 @@
 #include "host-queue.h"
 
 #include "detect-tag.h"
+#include "detect-engine-threshold.h"
 
 static Host *HostGetUsedHost(void);
 
@@ -62,6 +63,8 @@ Host *HostAlloc(void) {
     if (h == NULL)
         goto error;
 
+    memset(h, 0x00, sizeof(Host));
+
     SCMutexInit(&h->m, NULL);
     return h;
 
@@ -98,6 +101,10 @@ void HostClearMemory(Host *h) {
         DetectTagDataListFree(h->tag);
         h->tag = NULL;
     }
+    if (h->threshold != NULL) {
+        ThresholdListFree(h->threshold);
+        h->threshold = NULL;
+    }
 }
 
 #define HOST_DEFAULT_HASHSIZE 4096
index 63e5c000ad82ccfdda7c7cf872a170ae1429d230..5df793e554badf6c0015bed464149d882221bb6a 100644 (file)
@@ -31,6 +31,9 @@
  */
 
 #include "suricata-common.h"
+
+#include "host.h"
+
 #include "detect.h"
 #include "detect-engine.h"
 #include "detect-engine-address.h"
@@ -1507,6 +1510,8 @@ int SCThresholdConfTest09(void)
     int result = 0;
     FILE *fd = NULL;
 
+    HostInitConfig(HOST_QUIET);
+
     Packet *p = UTHBuildPacket((uint8_t*)"lalala", 6, IPPROTO_TCP);
     ThreadVars th_v;
     DetectEngineThreadCtx *det_ctx = NULL;
@@ -1583,6 +1588,7 @@ end:
     DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
     DetectEngineCtxFree(de_ctx);
 
+    HostShutdown();
     return result;
 }
 
@@ -1598,6 +1604,8 @@ int SCThresholdConfTest10(void)
     int result = 0;
     FILE *fd = NULL;
 
+    HostInitConfig(HOST_QUIET);
+
     Packet *p = UTHBuildPacket((uint8_t*)"lalala", 6, IPPROTO_TCP);
     Packet *p2 = UTHBuildPacketSrcDst((uint8_t*)"lalala", 6, IPPROTO_TCP, "172.26.0.1", "172.26.0.10");
 
@@ -1680,6 +1688,7 @@ end:
     DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
     DetectEngineCtxFree(de_ctx);
 
+    HostShutdown();
     return result;
 }
 
@@ -1695,6 +1704,8 @@ int SCThresholdConfTest11(void)
     int result = 0;
     FILE *fd = NULL;
 
+    HostInitConfig(HOST_QUIET);
+
     Packet *p = UTHBuildPacket((uint8_t*)"lalala", 6, IPPROTO_TCP);
     ThreadVars th_v;
     DetectEngineThreadCtx *det_ctx = NULL;
@@ -1796,6 +1807,7 @@ end:
     DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
     DetectEngineCtxFree(de_ctx);
 
+    HostShutdown();
     return result;
 }
 
@@ -1811,6 +1823,8 @@ int SCThresholdConfTest12(void)
     int result = 0;
     FILE *fd = NULL;
 
+    HostInitConfig(HOST_QUIET);
+
     Packet *p = UTHBuildPacket((uint8_t*)"lalala", 6, IPPROTO_TCP);
     ThreadVars th_v;
     DetectEngineThreadCtx *det_ctx = NULL;
@@ -1913,6 +1927,7 @@ end:
     DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
     DetectEngineCtxFree(de_ctx);
 
+    HostShutdown();
     return result;
 }
 
@@ -1931,6 +1946,8 @@ int SCThresholdConfTest13(void)
     int result = 0;
     FILE *fd = NULL;
 
+    HostInitConfig(HOST_QUIET);
+
     if (de_ctx == NULL)
         return result;
 
@@ -1958,6 +1975,7 @@ end:
     SigGroupCleanup(de_ctx);
     SigCleanSignatures(de_ctx);
     DetectEngineCtxFree(de_ctx);
+    HostShutdown();
     return result;
 }
 
@@ -1973,6 +1991,8 @@ int SCThresholdConfTest14(void)
     int result = 0;
     FILE *fd = NULL;
 
+    HostInitConfig(HOST_QUIET);
+
     Packet *p = UTHBuildPacketReal((uint8_t*)"lalala", 6, IPPROTO_TCP, "192.168.0.10",
                                     "192.168.0.100", 1234, 24);
     Packet *p1 = UTHBuildPacketReal((uint8_t*)"lalala", 6, IPPROTO_TCP, "192.168.1.1",
@@ -2020,6 +2040,7 @@ end:
     DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
     DetectEngineCtxFree(de_ctx);
 
+    HostShutdown();
     return result;
 }