-/* 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);
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;
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
static int DetectTtlMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p,
const Signature *s, const SigMatchCtx *ctx)
{
-
if (PKT_IS_PSEUDOPKT(p))
return 0;
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;
}
/**
*/
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;
}
/**
}
#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
--- /dev/null
+
+/* 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);
+}