]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect/ttl: major clean up of ttl code
authorVictor Julien <victor@inliniac.net>
Sat, 29 Sep 2018 07:44:06 +0000 (09:44 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 2 Oct 2018 12:24:16 +0000 (14:24 +0200)
Redo unittests using FAIL/PASS macros
Switch parsing to pcre_copy_substring.
Misc cleanups.

src/detect-ttl.c
src/tests/detect-ttl.c [new file with mode: 0644]

index 6a30679183613bb0dc0d644ab8f5000f9ea000e8..bf0fac7f2de087db2854db382c63076b7aaf805a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2013 Open Information Security Foundation
+/* Copyright (C) 2007-2018 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
  * \file
  *
  * \author Gurvinder Singh <gurvindersighdahiya@gmail.com>
+ * \author Victor Julien <victor@inliniac.net>
  *
- * Implements the ttl keyword
+ * Implements the ttl keyword including prefilter support.
  */
 
 #include "suricata-common.h"
 #include "stream-tcp.h"
-#include "util-unittest.h"
 
 #include "detect.h"
 #include "detect-parse.h"
 #include "util-debug.h"
 
 /**
- * \brief Regex for parsing our flow options
+ * \brief Regex for parsing our ttl options
  */
 #define PARSE_REGEX  "^\\s*([0-9]*)?\\s*([<>=-]+)?\\s*([0-9]+)?\\s*$"
 
 static pcre *parse_regex;
 static pcre_extra *parse_regex_study;
 
-/*prototypes*/
+/* prototypes */
 static int DetectTtlMatch (ThreadVars *, DetectEngineThreadCtx *, Packet *,
         const Signature *, const SigMatchCtx *);
 static int DetectTtlSetup (DetectEngineCtx *, Signature *, const char *);
 void DetectTtlFree (void *);
+#ifdef UNITTESTS
 void DetectTtlRegisterTests (void);
-
+#endif
 static int PrefilterSetupTtl(DetectEngineCtx *de_ctx, SigGroupHead *sgh);
 static _Bool PrefilterTtlIsPrefilterable(const Signature *s);
 
@@ -64,8 +65,9 @@ void DetectTtlRegister(void)
     sigmatch_table[DETECT_TTL].Match = DetectTtlMatch;
     sigmatch_table[DETECT_TTL].Setup = DetectTtlSetup;
     sigmatch_table[DETECT_TTL].Free = DetectTtlFree;
+#ifdef UNITTESTS
     sigmatch_table[DETECT_TTL].RegisterTests = DetectTtlRegisterTests;
-
+#endif
     sigmatch_table[DETECT_TTL].SupportsPrefilter = PrefilterTtlIsPrefilterable;
     sigmatch_table[DETECT_TTL].SetupPrefilter = PrefilterSetupTtl;
 
@@ -86,11 +88,11 @@ static inline int TtlMatch(const uint8_t pttl, const uint8_t mode,
         return 1;
 
     return 0;
-
 }
 
 /**
- * \brief This function is used to match TTL rule option on a packet with those passed via ttl:
+ * \brief This function is used to match TTL rule option on a packet with
+ *        those passed via ttl
  *
  * \param t pointer to thread vars
  * \param det_ctx pointer to the pattern matcher thread
@@ -103,7 +105,6 @@ static inline int TtlMatch(const uint8_t pttl, const uint8_t mode,
 static int DetectTtlMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p,
         const Signature *s, const SigMatchCtx *ctx)
 {
-
     if (PKT_IS_PSEUDOPKT(p))
         return 0;
 
@@ -132,134 +133,122 @@ static int DetectTtlMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet
 
 static DetectTtlData *DetectTtlParse (const char *ttlstr)
 {
-    DetectTtlData *ttld = NULL;
-    char *arg1 = NULL;
-    char *arg2 = NULL;
-    char *arg3 = NULL;
 #define MAX_SUBSTRINGS 30
-    int ret = 0, res = 0;
     int ov[MAX_SUBSTRINGS];
+    char arg1[6] = "";
+    char arg2[6] = "";
+    char arg3[6] = "";
 
-    ret = pcre_exec(parse_regex, parse_regex_study, ttlstr, strlen(ttlstr), 0, 0, ov, MAX_SUBSTRINGS);
+    int ret = pcre_exec(parse_regex, parse_regex_study, ttlstr, strlen(ttlstr), 0, 0, ov, MAX_SUBSTRINGS);
     if (ret < 2 || ret > 4) {
         SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 "", ret);
-        goto error;
+        return NULL;
     }
-    const char *str_ptr;
 
-    res = pcre_get_substring((char *) ttlstr, ov, MAX_SUBSTRINGS, 1, &str_ptr);
+    int res = pcre_copy_substring((char *) ttlstr, ov, MAX_SUBSTRINGS, 1, arg1, sizeof(arg1));
     if (res < 0) {
-        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
-        goto error;
+        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
+        return NULL;
     }
-    arg1 = (char *) str_ptr;
-    SCLogDebug("Arg1 \"%s\"", arg1);
+    SCLogDebug("arg1 \"%s\"", arg1);
 
     if (ret >= 3) {
-        res = pcre_get_substring((char *) ttlstr, ov, MAX_SUBSTRINGS, 2, &str_ptr);
+        res = pcre_copy_substring((char *) ttlstr, ov, MAX_SUBSTRINGS, 2, arg2, sizeof(arg2));
         if (res < 0) {
-            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
-            goto error;
+            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
+            return NULL;
         }
-        arg2 = (char *) str_ptr;
-        SCLogDebug("Arg2 \"%s\"", arg2);
+        SCLogDebug("arg2 \"%s\"", arg2);
 
         if (ret >= 4) {
-            res = pcre_get_substring((char *) ttlstr, ov, MAX_SUBSTRINGS, 3, &str_ptr);
+            res = pcre_copy_substring((char *) ttlstr, ov, MAX_SUBSTRINGS, 3, arg3, sizeof(arg3));
             if (res < 0) {
-                SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
-                goto error;
+                SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
+                return NULL;
             }
-            arg3 = (char *) str_ptr;
-            SCLogDebug("Arg3 \"%s\"", arg3);
+            SCLogDebug("arg3 \"%s\"", arg3);
         }
     }
 
-    ttld = SCMalloc(sizeof (DetectTtlData));
-    if (unlikely(ttld == NULL))
-        goto error;
-    ttld->ttl1 = 0;
-    ttld->ttl2 = 0;
+    int ttl1 = 0;
+    int ttl2 = 0;
+    int mode = 0;
 
-    if (arg2 != NULL) {
-        /*set the values*/
-        switch(arg2[0]) {
+    if (strlen(arg2) > 0) {
+        switch (arg2[0]) {
             case '<':
-                if (arg3 == NULL)
-                    goto error;
+                if (strlen(arg3) == 0)
+                    return NULL;
 
-                ttld->mode = DETECT_TTL_LT;
-                ttld->ttl1 = (uint8_t) atoi(arg3);
+                mode = DETECT_TTL_LT;
+                ttl1 = atoi(arg3);
 
-                SCLogDebug("ttl is %"PRIu8"",ttld->ttl1);
+                SCLogDebug("ttl is %"PRIu8"",ttl1);
                 if (strlen(arg1) > 0)
-                    goto error;
+                    return NULL;
 
                 break;
             case '>':
-                if (arg3 == NULL)
-                    goto error;
+                if (strlen(arg3) == 0)
+                    return NULL;
 
-                ttld->mode = DETECT_TTL_GT;
-                ttld->ttl1 = (uint8_t) atoi(arg3);
+                mode = DETECT_TTL_GT;
+                ttl1 = atoi(arg3);
 
-                SCLogDebug("ttl is %"PRIu8"",ttld->ttl1);
+                SCLogDebug("ttl is %"PRIu8"",ttl1);
                 if (strlen(arg1) > 0)
-                    goto error;
+                    return NULL;
 
                 break;
             case '-':
-                if (arg1 == NULL || strlen(arg1)== 0)
-                    goto error;
-                if (arg3 == NULL || strlen(arg3)== 0)
-                    goto error;
-
-                ttld->mode = DETECT_TTL_RA;
-                ttld->ttl1 = (uint8_t) atoi(arg1);
-
-                ttld->ttl2 = (uint8_t) atoi(arg3);
-                SCLogDebug("ttl is %"PRIu8" to %"PRIu8"",ttld->ttl1, ttld->ttl2);
-                if (ttld->ttl1 >= ttld->ttl2) {
-                    SCLogError(SC_ERR_INVALID_SIGNATURE, "Invalid ttl range. ");
-                    goto error;
+                if (strlen(arg1) == 0 || strlen(arg3) == 0)
+                    return NULL;
+
+                mode = DETECT_TTL_RA;
+                ttl1 = atoi(arg1);
+                ttl2 = atoi(arg3);
+
+                SCLogDebug("ttl is %"PRIu8" to %"PRIu8"",ttl1, ttl2);
+                if (ttl1 >= ttl2) {
+                    SCLogError(SC_ERR_INVALID_SIGNATURE, "invalid ttl range");
+                    return NULL;
                 }
                 break;
             default:
-                ttld->mode = DETECT_TTL_EQ;
+                mode = DETECT_TTL_EQ;
 
-                if ((arg2 != NULL && strlen(arg2) > 0) ||
-                    (arg3 != NULL && strlen(arg3) > 0) ||
-                    (arg1 == NULL ||strlen(arg1) == 0))
-                    goto error;
+                if ((strlen(arg2) > 0) ||
+                    (strlen(arg3) > 0) ||
+                    (strlen(arg1) == 0))
+                    return NULL;
 
-                ttld->ttl1 = (uint8_t) atoi(arg1);
+                ttl1 = atoi(arg1);
                 break;
         }
     } else {
-        ttld->mode = DETECT_TTL_EQ;
+        mode = DETECT_TTL_EQ;
 
-        if ((arg3 != NULL && strlen(arg3) > 0) ||
-            (arg1 == NULL ||strlen(arg1) == 0))
-            goto error;
+        if ((strlen(arg3) > 0) ||
+            (strlen(arg1) == 0))
+            return NULL;
 
-        ttld->ttl1 = (uint8_t) atoi(arg1);
+        ttl1 = atoi(arg1);
     }
 
-    SCFree(arg1);
-    SCFree(arg2);
-    SCFree(arg3);
-    return ttld;
+    if (ttl1 < 0 || ttl1 > UCHAR_MAX ||
+        ttl2 < 0 || ttl2 > UCHAR_MAX) {
+        SCLogError(SC_ERR_INVALID_SIGNATURE, "invalid ttl value(s)");
+        return NULL;
+    }
+
+    DetectTtlData *ttld = SCMalloc(sizeof(DetectTtlData));
+    if (unlikely(ttld == NULL))
+        return NULL;
+    ttld->ttl1 = (uint8_t)ttl1;
+    ttld->ttl2 = (uint8_t)ttl2;
+    ttld->mode = mode;
 
-error:
-    if (ttld)
-        SCFree(ttld);
-    if (arg1)
-        SCFree(arg1);
-    if (arg2)
-        SCFree(arg2);
-    if (arg3)
-        SCFree(arg3);
-    return NULL;
+    return ttld;
 }
 
 /**
@@ -274,29 +263,22 @@ error:
  */
 static int DetectTtlSetup (DetectEngineCtx *de_ctx, Signature *s, const char *ttlstr)
 {
-    DetectTtlData *ttld = NULL;
-    SigMatch *sm = NULL;
-
-    ttld = DetectTtlParse(ttlstr);
+    DetectTtlData *ttld = DetectTtlParse(ttlstr);
     if (ttld == NULL)
-        goto error;
+        return -1;
 
-    sm = SigMatchAlloc();
-    if (sm == NULL)
-        goto error;
+    SigMatch *sm = SigMatchAlloc();
+    if (sm == NULL) {
+        DetectTtlFree(ttld);
+        return -1;
+    }
 
     sm->type = DETECT_TTL;
     sm->ctx = (SigMatchCtx *)ttld;
 
     SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
     s->flags |= SIG_FLAG_REQUIRE_PACKET;
-
     return 0;
-
-error:
-    if (ttld != NULL) DetectTtlFree(ttld);
-    if (sm != NULL) SCFree(sm);
-    return -1;
 }
 
 /**
@@ -381,324 +363,5 @@ static _Bool PrefilterTtlIsPrefilterable(const Signature *s)
 }
 
 #ifdef UNITTESTS
-#include "detect-engine.h"
-#include "detect-engine-mpm.h"
-
-/**
- * \brief this function is used to initialize the detection engine context and
- *        setup the signature with passed values.
- *
- */
-
-static int DetectTtlInitTest(DetectEngineCtx **de_ctx, Signature **sig, DetectTtlData **ttld, const char *str)
-{
-    char fullstr[1024];
-    int result = 0;
-
-    *de_ctx = NULL;
-    *sig = NULL;
-
-    if (snprintf(fullstr, 1024, "alert ip any any -> any any (msg:\"Ttl test\"; ttl:%s; sid:1;)", str) >= 1024) {
-        goto end;
-    }
-
-    *de_ctx = DetectEngineCtxInit();
-    if (*de_ctx == NULL) {
-        goto end;
-    }
-
-    (*de_ctx)->flags |= DE_QUIET;
-
-    (*de_ctx)->sig_list = SigInit(*de_ctx, fullstr);
-    if ((*de_ctx)->sig_list == NULL) {
-        goto end;
-    }
-
-    *sig = (*de_ctx)->sig_list;
-
-    *ttld = DetectTtlParse(str);
-
-    result = 1;
-
-end:
-    return result;
-}
-
-/**
- * \test DetectTtlParseTest01 is a test for setting up an valid ttl value.
- */
-
-static int DetectTtlParseTest01 (void)
-{
-    DetectTtlData *ttld = NULL;
-    uint8_t res = 0;
-
-    ttld = DetectTtlParse("10");
-    if (ttld != NULL) {
-        if (ttld->ttl1 == 10 && ttld->mode == DETECT_TTL_EQ)
-            res = 1;
-
-        DetectTtlFree(ttld);
-    }
-
-    return res;
-}
-
-/**
- * \test DetectTtlParseTest02 is a test for setting up an valid ttl value with
- *       "<" operator.
- */
-
-static int DetectTtlParseTest02 (void)
-{
-    DetectTtlData *ttld = NULL;
-    uint8_t res = 0;
-    ttld = DetectTtlParse("<10");
-    if (ttld != NULL) {
-        if (ttld->ttl1 == 10 && ttld->mode == DETECT_TTL_LT)
-            res = 1;
-        DetectTtlFree(ttld);
-    }
-
-    return res;
-}
-
-/**
- * \test DetectTtlParseTest03 is a test for setting up an valid ttl values with
- *       "-" operator.
- */
-
-static int DetectTtlParseTest03 (void)
-{
-    DetectTtlData *ttld = NULL;
-    uint8_t res = 0;
-    ttld = DetectTtlParse("1-2");
-    if (ttld != NULL) {
-        if (ttld->ttl1 == 1 && ttld->ttl2 == 2 && ttld->mode == DETECT_TTL_RA)
-            res = 1;
-        DetectTtlFree(ttld);
-    }
-
-    return res;
-}
-
-/**
- * \test DetectTtlParseTest04 is a test for setting up an valid ttl value with
- *       ">" operator and include spaces arround the given values.
- */
-
-static int DetectTtlParseTest04 (void)
-{
-    DetectTtlData *ttld = NULL;
-    uint8_t res = 0;
-
-    ttld = DetectTtlParse(" > 10 ");
-    if (ttld != NULL) {
-        if (ttld->ttl1 == 10 && ttld->mode == DETECT_TTL_GT)
-            res = 1;
-
-        DetectTtlFree(ttld);
-    }
-
-    return res;
-}
-
-/**
- * \test DetectTtlParseTest05 is a test for setting up an valid ttl values with
- *       "-" operator and include spaces arround the given values.
- */
-
-static int DetectTtlParseTest05 (void)
-{
-    DetectTtlData *ttld = NULL;
-    uint8_t res = 0;
-
-    ttld = DetectTtlParse(" 1 - 2 ");
-    if (ttld != NULL) {
-        if (ttld->ttl1 == 1 && ttld->ttl2 == 2 && ttld->mode == DETECT_TTL_RA)
-            res = 1;
-        DetectTtlFree(ttld);
-    }
-
-    return res;
-}
-
-/**
- * \test DetectTtlParseTest06 is a test for setting up an valid ttl values with
- *       invalid "=" operator and include spaces arround the given values.
- */
-
-static int DetectTtlParseTest06 (void)
-{
-    DetectTtlData *ttld = NULL;
-    uint8_t res = 0;
-
-    ttld = DetectTtlParse(" 1 = 2 ");
-    if (ttld == NULL)
-        res = 1;
-    if (ttld) SCFree(ttld);
-
-    return res;
-}
-
-/**
- * \test DetectTtlParseTest07 is a test for setting up an valid ttl values with
- *       invalid "<>" operator and include spaces arround the given values.
- */
-
-static int DetectTtlParseTest07 (void)
-{
-    DetectTtlData *ttld = NULL;
-    uint8_t res = 0;
-
-    ttld = DetectTtlParse(" 1<>2 ");
-    if (ttld == NULL)
-        res = 1;
-
-    if (ttld) SCFree(ttld);
-
-    return res;
-}
-
-/**
- * \test DetectTtlSetpTest01 is a test for setting up an valid ttl values with
- *       valid "-" operator and include spaces arround the given values. In the
- *       test the values are setup with initializing the detection engine context
- *       setting up the signature itself.
- */
-
-static int DetectTtlSetpTest01(void)
-{
-
-    DetectTtlData *ttld = NULL;
-    uint8_t res = 0;
-    Signature *sig = NULL;
-    DetectEngineCtx *de_ctx = NULL;
-
-    res = DetectTtlInitTest(&de_ctx, &sig, &ttld, "1 - 2 ");
-    if (res == 0) {
-        goto end;
-    }
-
-    if(ttld == NULL)
-        goto cleanup;
-
-    if (ttld != NULL) {
-        if (ttld->ttl1 == 1 && ttld->ttl2 == 2 && ttld->mode == DETECT_TTL_RA)
-            res = 1;
-    }
-
-cleanup:
-    if (ttld) SCFree(ttld);
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-end:
-    return res;
-}
-
-/**
- * \test DetectTtlTestSig01 is a test for checking the working of ttl keyword
- *       by setting up the signature and later testing its working by matching
- *       the received packet against the sig.
- */
-
-static int DetectTtlTestSig1(void)
-{
-
-    Packet *p = PacketGetFromAlloc();
-    if (unlikely(p == NULL))
-        return 0;
-    Signature *s = NULL;
-    ThreadVars th_v;
-    DetectEngineThreadCtx *det_ctx;
-    int result = 0;
-    IPV4Hdr ip4h;
-
-    memset(&th_v, 0, sizeof(th_v));
-    memset(&ip4h, 0, sizeof(ip4h));
-
-    p->src.family = AF_INET;
-    p->dst.family = AF_INET;
-    p->proto = IPPROTO_TCP;
-    ip4h.ip_ttl = 15;
-    p->ip4h = &ip4h;
-
-    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL) {
-        goto end;
-    }
-
-    de_ctx->flags |= DE_QUIET;
-
-    s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"with in ttl limit\"; ttl: >16; sid:1;)");
-    if (s == NULL) {
-        goto end;
-    }
-
-    s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Less than 17\"; ttl: <17; sid:2;)");
-    if (s == NULL) {
-        goto end;
-    }
-
-    s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Greater than 5\"; ttl:15; sid:3;)");
-    if (s == NULL) {
-        goto end;
-    }
-
-    s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Equals tcp\"; ttl: 1-30; sid:4;)");
-    if (s == NULL) {
-        goto end;
-    }
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
-    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-    if (PacketAlertCheck(p, 1)) {
-        printf("sid 1 alerted, but should not have: ");
-        goto cleanup;
-    } else if (PacketAlertCheck(p, 2) == 0) {
-        printf("sid 2 did not alert, but should have: ");
-        goto cleanup;
-    } else if (PacketAlertCheck(p, 3) == 0) {
-        printf("sid 3 did not alert, but should have: ");
-        goto cleanup;
-    } else if (PacketAlertCheck(p, 4) == 0) {
-        printf("sid 4 did not alert, but should have: ");
-        goto cleanup;
-    }
-
-    result = 1;
-
-cleanup:
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
-
-    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
-    DetectEngineCtxFree(de_ctx);
-
-end:
-    SCFree(p);
-    return result;
-}
-
-#endif /* UNITTESTS */
-
-/**
- * \brief this function registers unit tests for DetectTtl
- */
-void DetectTtlRegisterTests(void)
-{
-#ifdef UNITTESTS
-    UtRegisterTest("DetectTtlParseTest01", DetectTtlParseTest01);
-    UtRegisterTest("DetectTtlParseTest02", DetectTtlParseTest02);
-    UtRegisterTest("DetectTtlParseTest03", DetectTtlParseTest03);
-    UtRegisterTest("DetectTtlParseTest04", DetectTtlParseTest04);
-    UtRegisterTest("DetectTtlParseTest05", DetectTtlParseTest05);
-    UtRegisterTest("DetectTtlParseTest06", DetectTtlParseTest06);
-    UtRegisterTest("DetectTtlParseTest07", DetectTtlParseTest07);
-    UtRegisterTest("DetectTtlSetpTest01", DetectTtlSetpTest01);
-    UtRegisterTest("DetectTtlTestSig1", DetectTtlTestSig1);
-#endif /* UNITTESTS */
-}
+#include "tests/detect-ttl.c"
+#endif
diff --git a/src/tests/detect-ttl.c b/src/tests/detect-ttl.c
new file mode 100644 (file)
index 0000000..a89d98a
--- /dev/null
@@ -0,0 +1,220 @@
+
+/* Copyright (C) 2007-2018 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
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "../detect-engine.h"
+#include "../util-unittest.h"
+
+/**
+ * \test DetectTtlParseTest01 is a test for setting up an valid ttl value.
+ */
+
+static int DetectTtlParseTest01 (void)
+{
+    DetectTtlData *ttld = DetectTtlParse("10");
+    FAIL_IF_NULL(ttld);
+    FAIL_IF_NOT(ttld->ttl1 == 10);
+    FAIL_IF_NOT(ttld->mode == DETECT_TTL_EQ);
+    DetectTtlFree(ttld);
+    PASS;
+}
+
+/**
+ * \test DetectTtlParseTest02 is a test for setting up an valid ttl value with
+ *       "<" operator.
+ */
+
+static int DetectTtlParseTest02 (void)
+{
+    DetectTtlData *ttld = DetectTtlParse("<10");
+    FAIL_IF_NULL(ttld);
+    FAIL_IF_NOT(ttld->ttl1 == 10);
+    FAIL_IF_NOT(ttld->mode == DETECT_TTL_LT);
+    DetectTtlFree(ttld);
+    PASS;
+}
+
+/**
+ * \test DetectTtlParseTest03 is a test for setting up an valid ttl values with
+ *       "-" operator.
+ */
+
+static int DetectTtlParseTest03 (void)
+{
+    DetectTtlData *ttld = DetectTtlParse("1-2");
+    FAIL_IF_NULL(ttld);
+    FAIL_IF_NOT(ttld->ttl1 == 1);
+    FAIL_IF_NOT(ttld->ttl2 == 2);
+    FAIL_IF_NOT(ttld->mode == DETECT_TTL_RA);
+    DetectTtlFree(ttld);
+    PASS;
+}
+
+/**
+ * \test DetectTtlParseTest04 is a test for setting up an valid ttl value with
+ *       ">" operator and include spaces arround the given values.
+ */
+
+static int DetectTtlParseTest04 (void)
+{
+    DetectTtlData *ttld = DetectTtlParse(" > 10 ");
+    FAIL_IF_NULL(ttld);
+    FAIL_IF_NOT(ttld->ttl1 == 10);
+    FAIL_IF_NOT(ttld->mode == DETECT_TTL_GT);
+    DetectTtlFree(ttld);
+    PASS;
+}
+
+/**
+ * \test DetectTtlParseTest05 is a test for setting up an valid ttl values with
+ *       "-" operator and include spaces arround the given values.
+ */
+
+static int DetectTtlParseTest05 (void)
+{
+    DetectTtlData *ttld = DetectTtlParse(" 1 - 2 ");
+    FAIL_IF_NULL(ttld);
+    FAIL_IF_NOT(ttld->ttl1 == 1);
+    FAIL_IF_NOT(ttld->ttl2 == 2);
+    FAIL_IF_NOT(ttld->mode == DETECT_TTL_RA);
+    DetectTtlFree(ttld);
+    PASS;
+}
+
+/**
+ * \test DetectTtlParseTest06 is a test for setting up an valid ttl values with
+ *       invalid "=" operator and include spaces arround the given values.
+ */
+
+static int DetectTtlParseTest06 (void)
+{
+    DetectTtlData *ttld = DetectTtlParse(" 1 = 2 ");
+    FAIL_IF_NOT_NULL(ttld);
+    PASS;
+}
+
+/**
+ * \test DetectTtlParseTest07 is a test for setting up an valid ttl values with
+ *       invalid "<>" operator and include spaces arround the given values.
+ */
+
+static int DetectTtlParseTest07 (void)
+{
+    DetectTtlData *ttld = DetectTtlParse(" 1<>2 ");
+    FAIL_IF_NOT_NULL(ttld);
+    PASS;
+}
+
+/**
+ * \test DetectTtlSetupTest01 is a test for setting up an valid ttl values with
+ *       valid "-" operator and include spaces arround the given values. In the
+ *       test the values are setup with initializing the detection engine context
+ *       setting up the signature itself.
+ */
+
+static int DetectTtlSetupTest01(void)
+{
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+    de_ctx->flags |= DE_QUIET;
+
+    Signature *s = DetectEngineAppendSig(de_ctx,
+            "alert ip any any -> any any (msg:\"with in ttl limit\"; ttl:1 - 2; sid:1;)");
+    FAIL_IF_NULL(s);
+    SigGroupBuild(de_ctx);
+    FAIL_IF_NULL(s->sm_arrays[DETECT_SM_LIST_MATCH]);
+    FAIL_IF_NULL(s->sm_arrays[DETECT_SM_LIST_MATCH]->ctx);
+    DetectTtlData *ttld = (DetectTtlData *)s->sm_arrays[DETECT_SM_LIST_MATCH]->ctx;
+
+    FAIL_IF_NOT(ttld->ttl1 == 1);
+    FAIL_IF_NOT(ttld->ttl2 == 2);
+    FAIL_IF_NOT(ttld->mode == DETECT_TTL_RA);
+    DetectEngineCtxFree(de_ctx);
+    PASS;
+}
+
+/**
+ * \test DetectTtlTestSig01 is a test for checking the working of ttl keyword
+ *       by setting up the signature and later testing its working by matching
+ *       the received packet against the sig.
+ */
+
+static int DetectTtlTestSig1(void)
+{
+    Packet *p = PacketGetFromAlloc();
+    FAIL_IF_NULL(p);
+    Signature *s = NULL;
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx;
+    IPV4Hdr ip4h;
+
+    memset(&th_v, 0, sizeof(th_v));
+    memset(&ip4h, 0, sizeof(ip4h));
+
+    p->src.family = AF_INET;
+    p->dst.family = AF_INET;
+    p->proto = IPPROTO_TCP;
+    ip4h.ip_ttl = 15;
+    p->ip4h = &ip4h;
+
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+    de_ctx->flags |= DE_QUIET;
+
+    s = DetectEngineAppendSig(de_ctx,"alert ip any any -> any any (msg:\"with in ttl limit\"; ttl: >16; sid:1;)");
+    FAIL_IF_NULL(s);
+
+    s = DetectEngineAppendSig(de_ctx,"alert ip any any -> any any (msg:\"Less than 17\"; ttl: <17; sid:2;)");
+    FAIL_IF_NULL(s);
+
+    s = DetectEngineAppendSig(de_ctx,"alert ip any any -> any any (msg:\"Greater than 5\"; ttl:15; sid:3;)");
+    FAIL_IF_NULL(s);
+
+    s = DetectEngineAppendSig(de_ctx,"alert ip any any -> any any (msg:\"Equals tcp\"; ttl: 1-30; sid:4;)");
+    FAIL_IF_NULL(s);
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    FAIL_IF(PacketAlertCheck(p, 1));
+    FAIL_IF_NOT(PacketAlertCheck(p, 2));
+    FAIL_IF_NOT(PacketAlertCheck(p, 3));
+    FAIL_IF_NOT(PacketAlertCheck(p, 4));
+
+    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    DetectEngineCtxFree(de_ctx);
+
+    SCFree(p);
+    PASS;
+}
+
+/**
+ * \brief this function registers unit tests for DetectTtl
+ */
+void DetectTtlRegisterTests(void)
+{
+    UtRegisterTest("DetectTtlParseTest01", DetectTtlParseTest01);
+    UtRegisterTest("DetectTtlParseTest02", DetectTtlParseTest02);
+    UtRegisterTest("DetectTtlParseTest03", DetectTtlParseTest03);
+    UtRegisterTest("DetectTtlParseTest04", DetectTtlParseTest04);
+    UtRegisterTest("DetectTtlParseTest05", DetectTtlParseTest05);
+    UtRegisterTest("DetectTtlParseTest06", DetectTtlParseTest06);
+    UtRegisterTest("DetectTtlParseTest07", DetectTtlParseTest07);
+    UtRegisterTest("DetectTtlSetupTest01", DetectTtlSetupTest01);
+    UtRegisterTest("DetectTtlTestSig1", DetectTtlTestSig1);
+}