/** * \test DetectFlowTestParse01 is a test to make sure that we return "something" * when given valid flow opt */ int DetectFlowTestParse01 (void) { DetectFlowData *fd = NULL; fd = DetectFlowParse("established"); FAIL_IF_NULL(fd); DetectFlowFree(fd); PASS; }
/** * \test DetectFlowTestParseNocase01 is a test to make sure that we return "something" * when given valid flow opt */ int DetectFlowTestParseNocase01 (void) { DetectFlowData *fd = NULL; fd = DetectFlowParse("ESTABLISHED"); FAIL_IF_NULL(fd); DetectFlowFree(fd); PASS; }
/** * \test DetectFlowTestParse03 is a test for setting the stateless flow opt */ int DetectFlowTestParse03 (void) { DetectFlowData *fd = NULL; fd = DetectFlowParse("stateless"); FAIL_IF_NULL(fd); FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_STATELESS && fd->match_cnt == 1); DetectFlowFree(fd); PASS; }
/** * \test DetectFlowTestParse06 is a test for setting the from_server flow opt */ int DetectFlowTestParse06 (void) { DetectFlowData *fd = NULL; fd = DetectFlowParse("from_server"); FAIL_IF_NULL(fd); FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 1); DetectFlowFree(fd); PASS; }
/** * \test DetectFlowTestParse08 is a test for setting the established,to_client flow opts */ int DetectFlowTestParse08 (void) { DetectFlowData *fd = NULL; fd = DetectFlowParse("established,to_client"); FAIL_IF_NULL(fd); FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED && fd->flags & DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 2); DetectFlowFree(fd); PASS; }
/** * \test DetectFlowTestParseNocase07 is a test for setting the from_client flow opt */ int DetectFlowTestParseNocase07 (void) { DetectFlowData *fd = NULL; fd = DetectFlowParse("FROM_CLIENT"); FAIL_IF_NULL(fd); FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOSERVER && fd->match_cnt == 1); DetectFlowFree(fd); PASS; }
/** * \test Test parsing of the not_established keyword. */ static int DetectFlowTestParseNotEstablished(void) { DetectFlowData *fd = NULL; fd = DetectFlowParse("not_established"); FAIL_IF_NULL(fd); FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_NOT_ESTABLISHED); DetectFlowFree(fd); PASS; }
/** * \test Test parsing of the "only_frag" flow argument. */ static int DetectFlowTestParseOnlyFrag(void) { DetectFlowData *fd = NULL; fd = DetectFlowParse("only_frag"); FAIL_IF_NULL(fd); FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG); DetectFlowFree(fd); PASS; }
/** * \test DetectFlowTestParseNocase02 is a test for setting the established flow opt */ int DetectFlowTestParseNocase02 (void) { DetectFlowData *fd = NULL; fd = DetectFlowParse("ESTABLISHED"); FAIL_IF_NULL(fd); FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_ESTABLISHED && fd->match_cnt == 1); DetectFlowFree(fd); PASS; }
/** * \test DetectFlowTestParseNocase01 is a test to make sure that we return "something" * when given valid flow opt */ int DetectFlowTestParseNocase01 (void) { int result = 0; DetectFlowData *fd = NULL; fd = DetectFlowParse("ESTABLISHED"); if (fd != NULL) { DetectFlowFree(fd); result = 1; } return result; }
/** * \brief this function is used to add the parsed flowdata into the current signature * * \param de_ctx pointer to the Detection Engine Context * \param s pointer to the Current Signature * \param flowstr pointer to the user provided flow options * * \retval 0 on Success * \retval -1 on Failure */ int DetectFlowSetup (DetectEngineCtx *de_ctx, Signature *s, char *flowstr) { DetectFlowData *fd = NULL; SigMatch *sm = NULL; fd = DetectFlowParse(flowstr); if (fd == NULL) goto error; /*ensure only one flow option*/ if (s->init_flags & SIG_FLAG_INIT_FLOW) { SCLogError (SC_ERR_INVALID_SIGNATURE, "A signature may have only one flow option."); goto error; } /* Okay so far so good, lets get this into a SigMatch * and put it in the Signature. */ sm = SigMatchAlloc(); if (sm == NULL) goto error; sm->type = DETECT_FLOW; sm->ctx = (SigMatchCtx *)fd; SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH); /* set the signature direction flags */ if (fd->flags & DETECT_FLOW_FLAG_TOSERVER) { s->flags |= SIG_FLAG_TOSERVER; } else if (fd->flags & DETECT_FLOW_FLAG_TOCLIENT) { s->flags |= SIG_FLAG_TOCLIENT; } else { s->flags |= SIG_FLAG_TOSERVER; s->flags |= SIG_FLAG_TOCLIENT; } if (fd->flags & DETECT_FLOW_FLAG_ONLYSTREAM) { s->flags |= SIG_FLAG_REQUIRE_STREAM; } if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM) { s->flags |= SIG_FLAG_REQUIRE_PACKET; } else { s->init_flags |= SIG_FLAG_INIT_FLOW; } return 0; error: if (fd != NULL) DetectFlowFree(fd); if (sm != NULL) SCFree(sm); return -1; }
/** * \test DetectFlowTestParseNocase08 is a test for setting the established,to_client flow opts */ int DetectFlowTestParseNocase08 (void) { DetectFlowData *fd = NULL; fd = DetectFlowParse("ESTABLISHED,TO_CLIENT"); FAIL_IF_NULL(fd); FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED && fd->flags & DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 2); DetectFlowFree(fd); PASS; }
/** * \test DetectFlowTestParseNocase11 is a test for setting the from_server,stateless flow opts with spaces all around */ int DetectFlowTestParseNocase11 (void) { DetectFlowData *fd = NULL; fd = DetectFlowParse(" FROM_SERVER , STATELESS "); FAIL_IF_NULL(fd); FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_STATELESS && fd->flags & DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 2); DetectFlowFree(fd); PASS; }
/** * \test DetectFlowTestParse01 is a test to make sure that we return "something" * when given valid flow opt */ int DetectFlowTestParse01 (void) { int result = 0; DetectFlowData *fd = NULL; fd = DetectFlowParse("established"); if (fd != NULL) { DetectFlowFree(fd); result = 1; } return result; }
/** * \test DetectFlowTestParse11 is a test for setting the from_server,stateless flow opts with spaces all around */ int DetectFlowTestParse11 (void) { DetectFlowData *fd = NULL; fd = DetectFlowParse(" from_server , stateless "); FAIL_IF_NULL(fd); FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_STATELESS && fd->flags & DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 2); DetectFlowFree(fd); PASS; }
/** * \test DetectFlowTestParse20 is a test for setting from_server, established, no_stream */ int DetectFlowTestParse20 (void) { DetectFlowData *fd = NULL; fd = DetectFlowParse("from_server,established,no_stream"); FAIL_IF_NULL(fd); FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED && fd->flags & DETECT_FLOW_FLAG_TOCLIENT && fd->flags & DETECT_FLOW_FLAG_NOSTREAM && fd->match_cnt == 3); DetectFlowFree(fd); PASS; }
/** * \test DetectFlowTestParse13 is a test for an invalid option */ int DetectFlowTestParse13 (void) { int result = 1; DetectFlowData *fd = NULL; fd = DetectFlowParse("invalidoptiontest"); if (fd != NULL) { printf("expected: NULL got 0x%02X %" PRId32 ": ",fd->flags, fd->match_cnt); result = 0; DetectFlowFree(fd); } return result; }
/** * \test DetectFlowTestParse15 is a test for an invalid combo of options established,stateless */ int DetectFlowTestParse15 (void) { int result = 1; DetectFlowData *fd = NULL; fd = DetectFlowParse("established,stateless"); if (fd != NULL) { printf("expected: NULL got 0x%02X %" PRId32 ": ",fd->flags, fd->match_cnt); result = 0; DetectFlowFree(fd); } return result; }
/** * \test DetectFlowTestParse21 is a test for an invalid opt between to valid opts */ int DetectFlowTestParse21 (void) { int result = 1; DetectFlowData *fd = NULL; fd = DetectFlowParse("from_server,a,no_stream"); if (fd != NULL) { printf("expected: NULL got 0x%02X %" PRId32 ": ",fd->flags, fd->match_cnt); result = 0; DetectFlowFree(fd); } return result; }
/** * \test DetectFlowTestParse20 is a test for setting from_server, established, no_stream */ int DetectFlowTestParseNocase20 (void) { DetectFlowData *fd = NULL; fd = DetectFlowParse("FROM_SERVER,ESTABLISHED,NO_STREAM"); FAIL_IF_NULL(fd); FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED && fd->flags & DETECT_FLOW_FLAG_TOCLIENT && fd->flags & DETECT_FLOW_FLAG_NOSTREAM && fd->match_cnt == 3); DetectFlowFree(fd); PASS; }
/** * \test DetectFlowTestParse06 is a test for setting the from_server flow opt */ int DetectFlowTestParse06 (void) { int result = 0; DetectFlowData *fd = NULL; fd = DetectFlowParse("from_server"); if (fd != NULL) { if (fd->flags == FLOW_PKT_TOCLIENT && fd->match_cnt == 1) { result = 1; } else { printf("expected 0x%02X cnt %" PRId32 " got 0x%02X cnt %" PRId32 ": ", FLOW_PKT_TOCLIENT, 1, fd->flags, fd->match_cnt); } DetectFlowFree(fd); } return result; }
/** * \test DetectFlowTestParseNocase03 is a test for setting the stateless flow opt */ int DetectFlowTestParseNocase03 (void) { int result = 0; DetectFlowData *fd = NULL; fd = DetectFlowParse("STATELESS"); if (fd != NULL) { if (fd->flags == FLOW_PKT_STATELESS && fd->match_cnt == 1) { result = 1; } else { printf("expected 0x%02X cnt %" PRId32 " got 0x%02X cnt %" PRId32 ": ", FLOW_PKT_STATELESS, 1, fd->flags, fd->match_cnt); } DetectFlowFree(fd); } return result; }
/** * \test DetectFlowTestParseNocase07 is a test for setting the from_client flow opt */ int DetectFlowTestParseNocase07 (void) { int result = 0; DetectFlowData *fd = NULL; fd = DetectFlowParse("FROM_CLIENT"); if (fd != NULL) { if (fd->flags == FLOW_PKT_TOSERVER && fd->match_cnt == 1) { result = 1; } else { printf("expected 0x%02X cnt %" PRId32 " got 0x%02X cnt %" PRId32 ": ", FLOW_PKT_TOSERVER, 1, fd->flags, fd->match_cnt); } DetectFlowFree(fd); } return result; }
/** * \test DetectFlowTestParseNocase08 is a test for setting the established,to_client flow opts */ int DetectFlowTestParseNocase08 (void) { int result = 0; DetectFlowData *fd = NULL; fd = DetectFlowParse("ESTABLISHED,TO_CLIENT"); if (fd != NULL) { if (fd->flags & FLOW_PKT_ESTABLISHED && fd->flags & FLOW_PKT_TOCLIENT && fd->match_cnt == 2) { result = 1; } else { printf("expected: 0x%02X cnt %" PRId32 " got 0x%02X cnt %" PRId32 ": ", FLOW_PKT_ESTABLISHED + FLOW_PKT_TOCLIENT, 2, fd->flags, fd->match_cnt); } DetectFlowFree(fd); } return result; }
/** * \test DetectFlowTestParseNocase11 is a test for setting the from_server,stateless flow opts with spaces all around */ int DetectFlowTestParseNocase11 (void) { int result = 0; DetectFlowData *fd = NULL; fd = DetectFlowParse(" FROM_SERVER , STATELESS "); if (fd != NULL) { if (fd->flags & FLOW_PKT_STATELESS && fd->flags & FLOW_PKT_TOCLIENT && fd->match_cnt == 2){ result = 1; } else { printf("expected: 0x%02X cnt %" PRId32 " got 0x%02X cnt %" PRId32 ": ", FLOW_PKT_STATELESS + FLOW_PKT_TOCLIENT, 2, fd->flags, fd->match_cnt); } DetectFlowFree(fd); } return result; }
/** * \test DetectFlowTestParse02 is a test for setting the established flow opt */ int DetectFlowTestParse02 (void) { int result = 0; DetectFlowData *fd = NULL; fd = DetectFlowParse("established"); if (fd != NULL) { if (fd->flags == FLOW_PKT_ESTABLISHED && fd->match_cnt == 1) { result = 1; } else { printf("expected 0x%02X cnt %" PRId32 " got 0x%02X cnt %" PRId32 ": ", FLOW_PKT_ESTABLISHED, 1, fd->flags, fd->match_cnt); } DetectFlowFree(fd); } return result; }
/** * \test DetectFlowTestParseNocase18 is a test for setting the from_server,stateless,only_stream flow opts (order of state,dir reversed) */ int DetectFlowTestParseNocase18 (void) { int result = 0; DetectFlowData *fd = NULL; fd = DetectFlowParse("FROM_SERVER,ESTABLISHED,ONLY_STREAM"); if (fd != NULL) { if (fd->flags & FLOW_PKT_ESTABLISHED && fd->flags & FLOW_PKT_TOCLIENT && fd->flags & FLOW_PKT_ONLYSTREAM && fd->match_cnt == 3) { result = 1; } else { printf("expected 0x%02X cnt %" PRId32 " got 0x%02X cnt %" PRId32 ": ", FLOW_PKT_ESTABLISHED + FLOW_PKT_TOCLIENT + FLOW_PKT_ONLYSTREAM, 3, fd->flags, fd->match_cnt); } DetectFlowFree(fd); } return result; }
/** * \test DetectFlowTestParse18 is a test for setting the from_server,stateless,only_stream flow opts (order of state,dir reversed) */ int DetectFlowTestParse18 (void) { int result = 0; DetectFlowData *fd = NULL; fd = DetectFlowParse("from_server,established,only_stream"); if (fd != NULL) { if (fd->flags & FLOW_PKT_ESTABLISHED && fd->flags & FLOW_PKT_TOCLIENT && fd->flags & FLOW_PKT_ONLYSTREAM && fd->match_cnt == 3) { result = 1; } else { printf("expected 0x%02X cnt %" PRId32 " got 0x%02X cnt %" PRId32 ": ", FLOW_PKT_ESTABLISHED + FLOW_PKT_TOCLIENT + FLOW_PKT_ONLYSTREAM, 3, fd->flags, fd->match_cnt); } DetectFlowFree(fd); } return result; }
/** * \brief This function is used to parse flow options passed via flow: keyword * * \param flowstr Pointer to the user provided flow options * * \retval fd pointer to DetectFlowData on success * \retval NULL on failure */ DetectFlowData *DetectFlowParse (char *flowstr) { DetectFlowData *fd = NULL; char *args[3] = {NULL,NULL,NULL}; #define MAX_SUBSTRINGS 30 int ret = 0, res = 0; int ov[MAX_SUBSTRINGS]; ret = pcre_exec(parse_regex, parse_regex_study, flowstr, strlen(flowstr), 0, 0, ov, MAX_SUBSTRINGS); if (ret < 1 || ret > 4) { SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 ", string %s", ret, flowstr); goto error; } if (ret > 1) { const char *str_ptr; res = pcre_get_substring((char *)flowstr, ov, MAX_SUBSTRINGS, 1, &str_ptr); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); goto error; } args[0] = (char *)str_ptr; if (ret > 2) { res = pcre_get_substring((char *)flowstr, ov, MAX_SUBSTRINGS, 2, &str_ptr); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); goto error; } args[1] = (char *)str_ptr; } if (ret > 3) { res = pcre_get_substring((char *)flowstr, ov, MAX_SUBSTRINGS, 3, &str_ptr); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); goto error; } args[2] = (char *)str_ptr; } } fd = SCMalloc(sizeof(DetectFlowData)); if (fd == NULL) goto error; fd->flags = 0; fd->match_cnt = 0; int i; for (i = 0; i < (ret - 1); i++) { if (args[i]) { /* inspect our options and set the flags */ if (strcasecmp(args[i], "established") == 0) { if (fd->flags & FLOW_PKT_ESTABLISHED) { SCLogError(SC_ERR_FLAGS_MODIFIER, "FLOW_PKT_ESTABLISHED flag is already set"); goto error; } else if (fd->flags & FLOW_PKT_STATELESS) { SCLogError(SC_ERR_FLAGS_MODIFIER, "FLOW_PKT_STATELESS already set"); goto error; } fd->flags |= FLOW_PKT_ESTABLISHED; } else if (strcasecmp(args[i], "stateless") == 0) { if (fd->flags & FLOW_PKT_STATELESS) { SCLogError(SC_ERR_FLAGS_MODIFIER, "FLOW_PKT_STATELESS flag is already set"); goto error; } else if (fd->flags & FLOW_PKT_ESTABLISHED) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set FLOW_PKT_STATELESS, FLOW_PKT_ESTABLISHED already set"); goto error; } fd->flags |= FLOW_PKT_STATELESS; } else if (strcasecmp(args[i], "to_client") == 0 || strcasecmp(args[i], "from_server") == 0) { if (fd->flags & FLOW_PKT_TOCLIENT) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set FLOW_PKT_TOCLIENT flag is already set"); goto error; } else if (fd->flags & FLOW_PKT_TOSERVER) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set to_client, FLOW_PKT_TOSERVER already set"); goto error; } fd->flags |= FLOW_PKT_TOCLIENT; } else if (strcasecmp(args[i], "to_server") == 0 || strcasecmp(args[i], "from_client") == 0){ if (fd->flags & FLOW_PKT_TOSERVER) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set FLOW_PKT_TOSERVER flag is already set"); goto error; } else if (fd->flags & FLOW_PKT_TOCLIENT) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set to_server, FLOW_PKT_TO_CLIENT flag already set"); goto error; } fd->flags |= FLOW_PKT_TOSERVER; } else if (strcasecmp(args[i], "only_stream") == 0) { if (fd->flags & FLOW_PKT_ONLYSTREAM) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_stream flag is already set"); goto error; } else if (fd->flags & FLOW_PKT_NOSTREAM) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_stream flag, FLOW_PKT_NOSTREAM already set"); goto error; } fd->flags |= FLOW_PKT_ONLYSTREAM; } else if (strcasecmp(args[i], "no_stream") == 0) { if (fd->flags & FLOW_PKT_NOSTREAM) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_stream flag is already set"); goto error; } else if (fd->flags & FLOW_PKT_ONLYSTREAM) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_stream flag, FLOW_PKT_ONLYSTREAM already set"); goto error; } fd->flags |= FLOW_PKT_NOSTREAM; } else { SCLogError(SC_ERR_INVALID_VALUE, "invalid flow option \"%s\"", args[i]); goto error; } fd->match_cnt++; //printf("args[%" PRId32 "]: %s match_cnt: %" PRId32 " flags: 0x%02X\n", i, args[i], fd->match_cnt, fd->flags); } } for (i = 0; i < (ret -1); i++){ if (args[i] != NULL) SCFree(args[i]); } return fd; error: /* ret can be higher than 3 */ for (i = 0; i < (ret - 1) && i < 3; i++){ if (args[i] != NULL) SCFree(args[i]); } if (fd != NULL) DetectFlowFree(fd); return NULL; }
/** * \brief This function is used to parse flow options passed via flow: keyword * * \param flowstr Pointer to the user provided flow options * * \retval fd pointer to DetectFlowData on success * \retval NULL on failure */ DetectFlowData *DetectFlowParse (char *flowstr) { DetectFlowData *fd = NULL; char *args[3] = {NULL,NULL,NULL}; #define MAX_SUBSTRINGS 30 int ret = 0, res = 0; int ov[MAX_SUBSTRINGS]; char str1[16] = "", str2[16] = "", str3[16] = ""; ret = pcre_exec(parse_regex, parse_regex_study, flowstr, strlen(flowstr), 0, 0, ov, MAX_SUBSTRINGS); if (ret < 1 || ret > 4) { SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 ", string %s", ret, flowstr); goto error; } if (ret > 1) { res = pcre_copy_substring((char *)flowstr, ov, MAX_SUBSTRINGS, 1, str1, sizeof(str1)); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed"); goto error; } args[0] = (char *)str1; if (ret > 2) { res = pcre_copy_substring((char *)flowstr, ov, MAX_SUBSTRINGS, 2, str2, sizeof(str2)); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed"); goto error; } args[1] = (char *)str2; } if (ret > 3) { res = pcre_copy_substring((char *)flowstr, ov, MAX_SUBSTRINGS, 3, str3, sizeof(str3)); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed"); goto error; } args[2] = (char *)str3; } } fd = SCMalloc(sizeof(DetectFlowData)); if (unlikely(fd == NULL)) goto error; fd->flags = 0; fd->match_cnt = 0; int i; for (i = 0; i < (ret - 1); i++) { if (args[i]) { /* inspect our options and set the flags */ if (strcasecmp(args[i], "established") == 0) { if (fd->flags & DETECT_FLOW_FLAG_ESTABLISHED) { SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_ESTABLISHED flag is already set"); goto error; } else if (fd->flags & DETECT_FLOW_FLAG_STATELESS) { SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_STATELESS already set"); goto error; } fd->flags |= DETECT_FLOW_FLAG_ESTABLISHED; } else if (strcasecmp(args[i], "not_established") == 0) { if (fd->flags & DETECT_FLOW_FLAG_NOT_ESTABLISHED) { SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_NOT_ESTABLISHED flag is already set"); goto error; } else if (fd->flags & DETECT_FLOW_FLAG_NOT_ESTABLISHED) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_NOT_ESTABLISHED, DETECT_FLOW_FLAG_ESTABLISHED already set"); goto error; } fd->flags |= DETECT_FLOW_FLAG_NOT_ESTABLISHED; } else if (strcasecmp(args[i], "stateless") == 0) { if (fd->flags & DETECT_FLOW_FLAG_STATELESS) { SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_STATELESS flag is already set"); goto error; } else if (fd->flags & DETECT_FLOW_FLAG_ESTABLISHED) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_STATELESS, DETECT_FLOW_FLAG_ESTABLISHED already set"); goto error; } fd->flags |= DETECT_FLOW_FLAG_STATELESS; } else if (strcasecmp(args[i], "to_client") == 0 || strcasecmp(args[i], "from_server") == 0) { if (fd->flags & DETECT_FLOW_FLAG_TOCLIENT) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_TOCLIENT flag is already set"); goto error; } else if (fd->flags & DETECT_FLOW_FLAG_TOSERVER) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set to_client, DETECT_FLOW_FLAG_TOSERVER already set"); goto error; } fd->flags |= DETECT_FLOW_FLAG_TOCLIENT; } else if (strcasecmp(args[i], "to_server") == 0 || strcasecmp(args[i], "from_client") == 0){ if (fd->flags & DETECT_FLOW_FLAG_TOSERVER) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_TOSERVER flag is already set"); goto error; } else if (fd->flags & DETECT_FLOW_FLAG_TOCLIENT) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set to_server, DETECT_FLOW_FLAG_TO_CLIENT flag already set"); goto error; } fd->flags |= DETECT_FLOW_FLAG_TOSERVER; } else if (strcasecmp(args[i], "only_stream") == 0) { if (fd->flags & DETECT_FLOW_FLAG_ONLYSTREAM) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_stream flag is already set"); goto error; } else if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_stream flag, DETECT_FLOW_FLAG_NOSTREAM already set"); goto error; } fd->flags |= DETECT_FLOW_FLAG_ONLYSTREAM; } else if (strcasecmp(args[i], "no_stream") == 0) { if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_stream flag is already set"); goto error; } else if (fd->flags & DETECT_FLOW_FLAG_ONLYSTREAM) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_stream flag, DETECT_FLOW_FLAG_ONLYSTREAM already set"); goto error; } fd->flags |= DETECT_FLOW_FLAG_NOSTREAM; } else if (strcasecmp(args[i], "no_frag") == 0) { if (fd->flags & DETECT_FLOW_FLAG_NO_FRAG) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_frag flag is already set"); goto error; } else if (fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_frag flag, only_frag already set"); goto error; } fd->flags |= DETECT_FLOW_FLAG_NO_FRAG; } else if (strcasecmp(args[i], "only_frag") == 0) { if (fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_frag flag is already set"); goto error; } else if (fd->flags & DETECT_FLOW_FLAG_NO_FRAG) { SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_frag flag, no_frag already set"); goto error; } fd->flags |= DETECT_FLOW_FLAG_ONLY_FRAG; } else { SCLogError(SC_ERR_INVALID_VALUE, "invalid flow option \"%s\"", args[i]); goto error; } fd->match_cnt++; //printf("args[%" PRId32 "]: %s match_cnt: %" PRId32 " flags: 0x%02X\n", i, args[i], fd->match_cnt, fd->flags); } } return fd; error: if (fd != NULL) DetectFlowFree(fd); return NULL; }