You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/src/util-mpm-ac-gfbs.c

2677 lines
86 KiB
C

/* Copyright (C) 2007-2014 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.
*/
/**
* \file
*
* \author Anoop Saldanha <anoopsaldanha@gmail.com>
*
* Implementation of aho-corasick MPM from -
*
* Efficient String Matching: An Aid to Bibliographic Search
* Alfred V. Aho and Margaret J. Corasick
*
* - We use the goto-failure table to calculate transitions.
* - If we cross 2 ** 16 states, we use 4 bytes in the transition table
* to hold each state, otherwise we use 2 bytes.
* - To reduce memory consumption, we throw all the failure transitions
* out and use binary search to pick out the right transition in
* the modified goto table.
*
* \todo - Do a proper analyis of our existing MPMs and suggest a good one based
* on the pattern distribution and the expected traffic(say http).
* - Tried out loop unrolling without any perf increase. Need to dig deeper.
* - Try out holding whether they are any output strings from a particular
* state in one of the bytes of a state var. Will be useful in cuda esp.
*/
#include "suricata-common.h"
#include "suricata.h"
#include "detect.h"
#include "detect-parse.h"
#include "detect-engine.h"
#include "util-mpm-ac-gfbs.h"
#include "conf.h"
#include "util-memcmp.h"
#include "util-memcpy.h"
#include "util-debug.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
void SCACGfbsInitCtx(MpmCtx *);
void SCACGfbsInitThreadCtx(MpmCtx *, MpmThreadCtx *, uint32_t);
void SCACGfbsDestroyCtx(MpmCtx *);
void SCACGfbsDestroyThreadCtx(MpmCtx *, MpmThreadCtx *);
int SCACGfbsAddPatternCI(MpmCtx *, uint8_t *, uint16_t, uint16_t, uint16_t,
uint32_t, uint32_t, uint8_t);
int SCACGfbsAddPatternCS(MpmCtx *, uint8_t *, uint16_t, uint16_t, uint16_t,
uint32_t, uint32_t, uint8_t);
int SCACGfbsPreparePatterns(MpmCtx *mpm_ctx);
uint32_t SCACGfbsSearch(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx,
PatternMatcherQueue *pmq, uint8_t *buf, uint16_t buflen);
void SCACGfbsPrintInfo(MpmCtx *mpm_ctx);
void SCACGfbsPrintSearchStats(MpmThreadCtx *mpm_thread_ctx);
void SCACGfbsRegisterTests(void);
/* a placeholder to denote a failure transition in the goto table */
#define SC_AC_GFBS_FAIL (-1)
/* size of the hash table used to speed up pattern insertions initially */
#define INIT_HASH_SIZE 65536
#define STATE_QUEUE_CONTAINER_SIZE 65536
/**
* \brief Helper structure used by AC during state table creation
*/
typedef struct StateQueue_ {
int32_t store[STATE_QUEUE_CONTAINER_SIZE];
int top;
int bot;
} StateQueue;
/**
* \brief Register the goto failure table based aho-corasick mpm.
*/
void MpmACGfbsRegister(void)
{
mpm_table[MPM_AC_GFBS].name = "ac-gfbs";
/* don't need this. isn't that awesome? no more chopping and blah blah */
mpm_table[MPM_AC_GFBS].max_pattern_length = 0;
mpm_table[MPM_AC_GFBS].InitCtx = SCACGfbsInitCtx;
mpm_table[MPM_AC_GFBS].InitThreadCtx = SCACGfbsInitThreadCtx;
mpm_table[MPM_AC_GFBS].DestroyCtx = SCACGfbsDestroyCtx;
mpm_table[MPM_AC_GFBS].DestroyThreadCtx = SCACGfbsDestroyThreadCtx;
mpm_table[MPM_AC_GFBS].AddPattern = SCACGfbsAddPatternCS;
mpm_table[MPM_AC_GFBS].AddPatternNocase = SCACGfbsAddPatternCI;
mpm_table[MPM_AC_GFBS].Prepare = SCACGfbsPreparePatterns;
mpm_table[MPM_AC_GFBS].Search = SCACGfbsSearch;
mpm_table[MPM_AC_GFBS].Cleanup = NULL;
mpm_table[MPM_AC_GFBS].PrintCtx = SCACGfbsPrintInfo;
mpm_table[MPM_AC_GFBS].PrintThreadCtx = SCACGfbsPrintSearchStats;
mpm_table[MPM_AC_GFBS].RegisterUnittests = SCACGfbsRegisterTests;
return;
}
/**
* \internal
* \brief Initialize the AC context with user specified conf parameters. We
* aren't retrieving anything for AC conf now, but we will certainly
* need it, when we customize AC.
*/
static void SCACGfbsGetConfig()
{
//ConfNode *ac_conf;
//const char *hash_val = NULL;
//ConfNode *pm = ConfGetNode("pattern-matcher");
return;
}
/**
* \internal
* \brief Creates a hash of the pattern. We use it for the hashing process
* during the initial pattern insertion time, to cull duplicate sigs.
*
* \param pat Pointer to the pattern.
* \param patlen Pattern length.
*
* \retval hash A 32 bit unsigned hash.
*/
static inline uint32_t SCACGfbsInitHashRaw(uint8_t *pat, uint16_t patlen)
{
uint32_t hash = patlen * pat[0];
if (patlen > 1)
hash += pat[1];
return (hash % INIT_HASH_SIZE);
}
/**
* \internal
* \brief Looks up a pattern. We use it for the hashing process during the
* the initial pattern insertion time, to cull duplicate sigs.
*
* \param ctx Pointer to the AC ctx.
* \param pat Pointer to the pattern.
* \param patlen Pattern length.
* \param flags Flags. We don't need this.
*
* \retval hash A 32 bit unsigned hash.
*/
static inline SCACGfbsPattern *SCACGfbsInitHashLookup(SCACGfbsCtx *ctx, uint8_t *pat,
uint16_t patlen, char flags,
uint32_t pid)
{
uint32_t hash = SCACGfbsInitHashRaw(pat, patlen);
if (ctx->init_hash == NULL)
return NULL;
SCACGfbsPattern *t = ctx->init_hash[hash];
for ( ; t != NULL; t = t->next) {
if (t->id == pid)
return t;
}
return NULL;
}
/**
* \internal
* \brief Allocs a new pattern instance.
*
* \param mpm_ctx Pointer to the mpm context.
*
* \retval p Pointer to the newly created pattern.
*/
static inline SCACGfbsPattern *SCACGfbsAllocPattern(MpmCtx *mpm_ctx)
{
SCACGfbsPattern *p = SCMalloc(sizeof(SCACGfbsPattern));
if (unlikely(p == NULL)) {
exit(EXIT_FAILURE);
}
memset(p, 0, sizeof(SCACGfbsPattern));
mpm_ctx->memory_cnt++;
mpm_ctx->memory_size += sizeof(SCACGfbsPattern);
return p;
}
/**
* \internal
* \brief Used to free SCACGfbsPattern instances.
*
* \param mpm_ctx Pointer to the mpm context.
* \param p Pointer to the SCACGfbsPattern instance to be freed.
*/
static inline void SCACGfbsFreePattern(MpmCtx *mpm_ctx, SCACGfbsPattern *p)
{
if (p != NULL && p->cs != NULL && p->cs != p->ci) {
SCFree(p->cs);
mpm_ctx->memory_cnt--;
mpm_ctx->memory_size -= p->len;
}
if (p != NULL && p->ci != NULL) {
SCFree(p->ci);
mpm_ctx->memory_cnt--;
mpm_ctx->memory_size -= p->len;
}
if (p != NULL && p->original_pat != NULL) {
SCFree(p->original_pat);
mpm_ctx->memory_cnt--;
mpm_ctx->memory_size -= p->len;
}
if (p != NULL) {
SCFree(p);
mpm_ctx->memory_cnt--;
mpm_ctx->memory_size -= sizeof(SCACGfbsPattern);
}
return;
}
static inline uint32_t SCACGfbsInitHash(SCACGfbsPattern *p)
{
uint32_t hash = p->len * p->original_pat[0];
if (p->len > 1)
hash += p->original_pat[1];
return (hash % INIT_HASH_SIZE);
}
static inline int SCACGfbsInitHashAdd(SCACGfbsCtx *ctx, SCACGfbsPattern *p)
{
uint32_t hash = SCACGfbsInitHash(p);
if (ctx->init_hash == NULL) {
return 0;
}
if (ctx->init_hash[hash] == NULL) {
ctx->init_hash[hash] = p;
return 0;
}
SCACGfbsPattern *tt = NULL;
SCACGfbsPattern *t = ctx->init_hash[hash];
/* get the list tail */
do {
tt = t;
t = t->next;
} while (t != NULL);
tt->next = p;
return 0;
}
/**
* \internal
* \brief Add a pattern to the mpm-ac context.
*
* \param mpm_ctx Mpm context.
* \param pat Pointer to the pattern.
* \param patlen Length of the pattern.
* \param pid Pattern id
* \param sid Signature id (internal id).
* \param flags Pattern's MPM_PATTERN_* flags.
*
* \retval 0 On success.
* \retval -1 On failure.
*/
static int SCACGfbsAddPattern(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen,
uint16_t offset, uint16_t depth, uint32_t pid,
uint32_t sid, uint8_t flags)
{
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
SCLogDebug("Adding pattern for ctx %p, patlen %"PRIu16" and pid %" PRIu32,
ctx, patlen, pid);
if (patlen == 0) {
SCLogWarning(SC_ERR_INVALID_ARGUMENTS, "pattern length 0");
return 0;
}
/* check if we have already inserted this pattern */
SCACGfbsPattern *p = SCACGfbsInitHashLookup(ctx, pat, patlen, flags, pid);
if (p == NULL) {
SCLogDebug("Allocing new pattern");
/* p will never be NULL */
p = SCACGfbsAllocPattern(mpm_ctx);
p->len = patlen;
p->flags = flags;
p->id = pid;
p->original_pat = SCMalloc(patlen);
if (p->original_pat == NULL)
goto error;
mpm_ctx->memory_cnt++;
mpm_ctx->memory_size += patlen;
memcpy(p->original_pat, pat, patlen);
p->ci = SCMalloc(patlen);
if (p->ci == NULL)
goto error;
mpm_ctx->memory_cnt++;
mpm_ctx->memory_size += patlen;
memcpy_tolower(p->ci, pat, patlen);
/* setup the case sensitive part of the pattern */
if (p->flags & MPM_PATTERN_FLAG_NOCASE) {
/* nocase means no difference between cs and ci */
p->cs = p->ci;
} else {
if (memcmp(p->ci, pat, p->len) == 0) {
/* no diff between cs and ci: pat is lowercase */
p->cs = p->ci;
} else {
p->cs = SCMalloc(patlen);
if (p->cs == NULL)
goto error;
mpm_ctx->memory_cnt++;
mpm_ctx->memory_size += patlen;
memcpy(p->cs, pat, patlen);
}
}
/* put in the pattern hash */
SCACGfbsInitHashAdd(ctx, p);
if (mpm_ctx->pattern_cnt == 65535) {
SCLogError(SC_ERR_AHO_CORASICK, "Max search words reached. Can't "
"insert anymore. Exiting");
exit(EXIT_FAILURE);
}
mpm_ctx->pattern_cnt++;
if (mpm_ctx->maxlen < patlen)
mpm_ctx->maxlen = patlen;
if (mpm_ctx->minlen == 0) {
mpm_ctx->minlen = patlen;
} else {
if (mpm_ctx->minlen > patlen)
mpm_ctx->minlen = patlen;
}
/* we need the max pat id */
if (pid > ctx->max_pat_id)
ctx->max_pat_id = pid;
}
return 0;
error:
SCACGfbsFreePattern(mpm_ctx, p);
return -1;
}
/**
* \internal
* \brief Initialize a new state in the goto and output tables.
*
* \param mpm_ctx Pointer to the mpm context.
*
* \retval The state id, of the newly created state.
*/
static inline int SCACGfbsInitNewState(MpmCtx *mpm_ctx)
{
void *ptmp;
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
int ascii_code = 0;
int size = 0;
/* reallocate space in the goto table to include a new state */
size = (ctx->state_count + 1) * 1024;
ptmp = SCRealloc(ctx->goto_table, size);
if (ptmp == NULL) {
SCFree(ctx->goto_table);
ctx->goto_table = NULL;
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
exit(EXIT_FAILURE);
}
ctx->goto_table = ptmp;
/* set all transitions for the newly assigned state as FAIL transitions */
for (ascii_code = 0; ascii_code < 256; ascii_code++) {
ctx->goto_table[ctx->state_count][ascii_code] = SC_AC_GFBS_FAIL;
}
/* reallocate space in the output table for the new state */
size = (ctx->state_count + 1) * sizeof(SCACGfbsOutputTable);
ptmp = SCRealloc(ctx->output_table, size);
if (ptmp == NULL) {
SCFree(ctx->output_table);
ctx->output_table = NULL;
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
exit(EXIT_FAILURE);
}
ctx->output_table = ptmp;
memset(ctx->output_table + ctx->state_count, 0, sizeof(SCACGfbsOutputTable));
/* \todo using it temporarily now during dev, since I have restricted
* state var in SCACGfbsCtx->state_table to uint16_t. */
//if (ctx->state_count > 65536) {
// printf("state count exceeded\n");
// exit(EXIT_FAILURE);
//}
return ctx->state_count++;
}
/**
* \internal
* \brief Adds a pid to the output table for a state.
*
* \param state The state to whose output table we should add the pid.
* \param pid The pattern id to add.
* \param mpm_ctx Pointer to the mpm context.
*/
static void SCACGfbsSetOutputState(int32_t state, uint32_t pid, MpmCtx *mpm_ctx)
{
void *ptmp;
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
SCACGfbsOutputTable *output_state = &ctx->output_table[state];
uint32_t i = 0;
for (i = 0; i < output_state->no_of_entries; i++) {
if (output_state->pids[i] == pid)
return;
}
output_state->no_of_entries++;
ptmp = SCRealloc(output_state->pids,
output_state->no_of_entries * sizeof(uint32_t));
if (ptmp == NULL) {
SCFree(output_state->pids);
output_state->pids = NULL;
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
exit(EXIT_FAILURE);
}
output_state->pids = ptmp;
output_state->pids[output_state->no_of_entries - 1] = pid;
return;
}
/**
* \brief Helper function used by SCACGfbsCreateGotoTable. Adds a pattern to the
* goto table.
*
* \param pattern Pointer to the pattern.
* \param pattern_len Pattern length.
* \param pid The pattern id, that corresponds to this pattern. We
* need it to updated the output table for this pattern.
* \param mpm_ctx Pointer to the mpm context.
*/
static inline void SCACGfbsEnter(uint8_t *pattern, uint16_t pattern_len, uint32_t pid,
MpmCtx *mpm_ctx)
{
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
int32_t state = 0;
int32_t newstate = 0;
int i = 0;
int p = 0;
/* walk down the trie till we have a match for the pattern prefix */
state = 0;
for (i = 0; i < pattern_len; i++) {
if (ctx->goto_table[state][pattern[i]] != SC_AC_GFBS_FAIL) {
state = ctx->goto_table[state][pattern[i]];
} else {
break;
}
}
/* add the non-matching pattern suffix to the trie, from the last state
* we left off */
for (p = i; p < pattern_len; p++) {
newstate = SCACGfbsInitNewState(mpm_ctx);
ctx->goto_table[state][pattern[p]] = newstate;
state = newstate;
}
/* add this pattern id, to the output table of the last state, where the
* pattern ends in the trie */
SCACGfbsSetOutputState(state, pid, mpm_ctx);
return;
}
/**
* \internal
* \brief Create the goto table.
*
* \param mpm_ctx Pointer to the mpm context.
*/
static inline void SCACGfbsCreateGotoTable(MpmCtx *mpm_ctx)
{
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
uint32_t i = 0;
/* add each pattern to create the goto table */
for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
SCACGfbsEnter(ctx->parray[i]->ci, ctx->parray[i]->len,
ctx->parray[i]->id, mpm_ctx);
}
int ascii_code = 0;
for (ascii_code = 0; ascii_code < 256; ascii_code++) {
if (ctx->goto_table[0][ascii_code] == SC_AC_GFBS_FAIL) {
ctx->goto_table[0][ascii_code] = 0;
}
}
return;
}
static inline int SCACGfbsStateQueueIsEmpty(StateQueue *q)
{
if (q->top == q->bot)
return 1;
else
return 0;
}
static inline void SCACGfbsEnqueue(StateQueue *q, int32_t state)
{
int i = 0;
/*if we already have this */
for (i = q->bot; i < q->top; i++) {
if (q->store[i] == state)
return;
}
q->store[q->top++] = state;
if (q->top == STATE_QUEUE_CONTAINER_SIZE)
q->top = 0;
if (q->top == q->bot) {
SCLogCritical(SC_ERR_AHO_CORASICK, "Just ran out of space in the queue. "
"Fatal Error. Exiting. Please file a bug report on this");
exit(EXIT_FAILURE);
}
return;
}
static inline int32_t SCACGfbsDequeue(StateQueue *q)
{
if (q->bot == STATE_QUEUE_CONTAINER_SIZE)
q->bot = 0;
if (q->bot == q->top) {
SCLogCritical(SC_ERR_AHO_CORASICK, "StateQueue behaving weirdly. "
"Fatal Error. Exiting. Please file a bug report on this");
exit(EXIT_FAILURE);
}
return q->store[q->bot++];
}
/*
#define SCACGfbsStateQueueIsEmpty(q) (((q)->top == (q)->bot) ? 1 : 0)
#define SCACGfbsEnqueue(q, state) do { \
int i = 0; \
\
for (i = (q)->bot; i < (q)->top; i++) { \
if ((q)->store[i] == state) \
return; \
} \
\
(q)->store[(q)->top++] = state; \
\
if ((q)->top == STATE_QUEUE_CONTAINER_SIZE) \
(q)->top = 0; \
\
if ((q)->top == (q)->bot) { \
SCLogCritical(SC_ERR_AHO_CORASICK, "Just ran out of space in the queue. " \
"Fatal Error. Exiting. Please file a bug report on this"); \
exit(EXIT_FAILURE); \
} \
} while (0)
#define SCACGfbsDequeue(q) ( (((q)->bot == STATE_QUEUE_CONTAINER_SIZE)? ((q)->bot = 0): 0), \
(((q)->bot == (q)->top) ? \
(printf("StateQueue behaving " \
"weirdly. Fatal Error. Exiting. Please " \
"file a bug report on this"), \
exit(EXIT_FAILURE)) : 0), \
(q)->store[(q)->bot++]) \
*/
/**
* \internal
* \brief Club the output data from 2 states and store it in the 1st state.
* dst_state_data = {dst_state_data} UNION {src_state_data}
*
* \todo Use a better way to find union of 2 sets.
*
* \param dst_state First state(also the destination) for the union operation.
* \param src_state Second state for the union operation.
* \param mpm_ctx Pointer to the mpm context.
*/
static inline void SCACGfbsClubOutputStates(int32_t dst_state, int32_t src_state,
MpmCtx *mpm_ctx)
{
void *ptmp;
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
uint32_t i = 0;
uint32_t j = 0;
SCACGfbsOutputTable *output_dst_state = &ctx->output_table[dst_state];
SCACGfbsOutputTable *output_src_state = &ctx->output_table[src_state];
for (i = 0; i < output_src_state->no_of_entries; i++) {
for (j = 0; j < output_dst_state->no_of_entries; j++) {
if (output_src_state->pids[i] == output_dst_state->pids[j]) {
break;
}
}
if (j == output_dst_state->no_of_entries) {
output_dst_state->no_of_entries++;
ptmp = SCRealloc(output_dst_state->pids,
(output_dst_state->no_of_entries * sizeof(uint32_t)));
if (ptmp == NULL) {
SCFree(output_dst_state->pids);
output_dst_state->pids = NULL;
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
exit(EXIT_FAILURE);
}
output_dst_state->pids = ptmp;
output_dst_state->pids[output_dst_state->no_of_entries - 1] =
output_src_state->pids[i];
}
}
return;
}
/**
* \internal
* \brief Create the failure table.
*
* \param mpm_ctx Pointer to the mpm context.
*/
static inline void SCACGfbsCreateFailureTable(MpmCtx *mpm_ctx)
{
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
int ascii_code = 0;
int32_t state = 0;
int32_t r_state = 0;
StateQueue q;
memset(&q, 0, sizeof(StateQueue));
/* allot space for the failure table. A failure entry in the table for
* every state(SCACGfbsCtx->state_count) */
ctx->failure_table = SCMalloc(ctx->state_count * sizeof(int32_t));
if (ctx->failure_table == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
exit(EXIT_FAILURE);
}
memset(ctx->failure_table, 0, ctx->state_count * sizeof(int32_t));
/* add the failure transitions for the 0th state, and add every non-fail
* transition from the 0th state to the queue for further processing
* of failure states */
for (ascii_code = 0; ascii_code < 256; ascii_code++) {
int32_t temp_state = ctx->goto_table[0][ascii_code];
if (temp_state != 0) {
SCACGfbsEnqueue(&q, temp_state);
ctx->failure_table[temp_state] = 0;
}
}
while (!SCACGfbsStateQueueIsEmpty(&q)) {
/* pick up every state from the queue and add failure transitions */
r_state = SCACGfbsDequeue(&q);
for (ascii_code = 0; ascii_code < 256; ascii_code++) {
int32_t temp_state = ctx->goto_table[r_state][ascii_code];
if (temp_state == SC_AC_GFBS_FAIL)
continue;
SCACGfbsEnqueue(&q, temp_state);
state = ctx->failure_table[r_state];
while(ctx->goto_table[state][ascii_code] == SC_AC_GFBS_FAIL)
state = ctx->failure_table[state];
ctx->failure_table[temp_state] = ctx->goto_table[state][ascii_code];
SCACGfbsClubOutputStates(temp_state, ctx->failure_table[temp_state],
mpm_ctx);
}
}
return;
}
/**
* \internal
* \brief Creates a new goto table structure(throw out all the failure
* transitions), to hold the existing goto table.
*
* \param mpm_ctx Pointer to the mpm context.
*/
static inline void SCACGfbsCreateModGotoTable(MpmCtx *mpm_ctx)
{
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
if (ctx->state_count < 32767) {
int size = 0;
int32_t state = 0;
for (state = 1; state < ctx->state_count; state++) {
int k = 0;
int ascii_code = 0;
for (; ascii_code < 256; ascii_code++) {
if (ctx->goto_table[state][ascii_code] == SC_AC_GFBS_FAIL)
continue;
k++;
}
if ((k % 2) != 0)
size += 1;
}
/* Let us use uint16_t for all. That way we don't have to worry about
* alignment. Technically 8 bits is all we need to store ascii codes,
* but by avoiding it, we save a lot of time on handling alignment */
size += (ctx->state_count * sizeof(SC_AC_GFBS_STATE_TYPE_U16) * 3 +
ctx->state_count * sizeof(uint8_t) +
256 * sizeof(SC_AC_GFBS_STATE_TYPE_U16) * 1);
ctx->goto_table_mod = SCMalloc(size);
if (ctx->goto_table_mod == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
exit(EXIT_FAILURE);
}
memset(ctx->goto_table_mod, 0, size);
//printf("size- %d\n", size);
mpm_ctx->memory_cnt++;
mpm_ctx->memory_size += size;
/* buffer to hold pointers in the buffer, so that a state can use it
* directly to access its state data */
ctx->goto_table_mod_pointers = SCMalloc(ctx->state_count * sizeof(uint8_t *));
if (ctx->goto_table_mod_pointers == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
exit(EXIT_FAILURE);
}
memset(ctx->goto_table_mod_pointers, 0,
ctx->state_count * sizeof(uint8_t *));
SC_AC_GFBS_STATE_TYPE_U16 temp_states[256];
uint16_t *curr_loc = (uint16_t *)ctx->goto_table_mod;
uint16_t *no_of_entries = NULL;
uint16_t *failure_entry = NULL;
uint8_t *ascii_codes = NULL;
uint16_t ascii_code = 0;
uint16_t k = 0;
for (state = 0; state < ctx->state_count; state++) {
/* store the starting location in the buffer for this state */
ctx->goto_table_mod_pointers[state] = (uint8_t *)curr_loc;
no_of_entries = curr_loc++;
failure_entry = curr_loc++;
ascii_codes = (uint8_t *)curr_loc;
k = 0;
/* store all states that have non fail transitions in the temp buffer */
for (ascii_code = 0; ascii_code < 256; ascii_code++) {
if (ctx->goto_table[state][ascii_code] == SC_AC_GFBS_FAIL)
continue;
ascii_codes[k] = ascii_code;
temp_states[k] = ctx->goto_table[state][ascii_code];
k++;
}
/* if we have any non fail transitions from our previous for search,
* store the acii codes as well the corresponding states */
if (k > 0) {
no_of_entries[0] = k;
if (state != 0) {
int jump = (k + 1) & 0xFFE;
curr_loc += jump / 2;
}
memcpy(curr_loc, temp_states, k * sizeof(SC_AC_GFBS_STATE_TYPE_U16));
curr_loc += k;
}
failure_entry[0] = ctx->failure_table[state];
}
/* > 33766 */
} else {
int size = 0;
int32_t state = 0;
for (state = 1; state < ctx->state_count; state++) {
int k = 0;
int ascii_code = 0;
for (; ascii_code < 256; ascii_code++) {
if (ctx->goto_table[state][ascii_code] == SC_AC_GFBS_FAIL)
continue;
k++;
}
if ( (k % 4) != 0)
size += (4 - (k % 4));
}
/* Let us use uint32_t for all. That way we don't have to worry about
* alignment. Technically 8 bits is all we need to store ascii codes,
* but by avoiding it, we save a lot of time on handling alignment */
size += (ctx->state_count * (sizeof(SC_AC_GFBS_STATE_TYPE_U32) * 3)+
ctx->state_count * sizeof(uint8_t) +
256 * (sizeof(SC_AC_GFBS_STATE_TYPE_U32) * 1));
ctx->goto_table_mod = SCMalloc(size);
if (ctx->goto_table_mod == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
exit(EXIT_FAILURE);
}
memset(ctx->goto_table_mod, 0, size);
mpm_ctx->memory_cnt++;
mpm_ctx->memory_size += size;
/* buffer to hold pointers in the buffer, so that a state can use it
* directly to access its state data */
ctx->goto_table_mod_pointers = SCMalloc(ctx->state_count * sizeof(uint8_t *));
if (ctx->goto_table_mod_pointers == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
exit(EXIT_FAILURE);
}
memset(ctx->goto_table_mod_pointers, 0,
ctx->state_count * sizeof(uint8_t *));
SC_AC_GFBS_STATE_TYPE_U32 temp_states[256];
uint32_t *curr_loc = (uint32_t *)ctx->goto_table_mod;
uint32_t *no_of_entries = NULL;
uint32_t *failure_entry = NULL;
uint8_t *ascii_codes = NULL;
uint16_t ascii_code = 0;
uint16_t k = 0;
for (state = 0; state < ctx->state_count; state++) {
/* store the starting location in the buffer for this state */
ctx->goto_table_mod_pointers[state] = (uint8_t *)curr_loc;
no_of_entries = curr_loc++;
failure_entry = curr_loc++;
ascii_codes = (uint8_t *)curr_loc;
k = 0;
/* store all states that have non fail transitions in the temp buffer */
for (ascii_code = 0; ascii_code < 256; ascii_code++) {
if (ctx->goto_table[state][ascii_code] == SC_AC_GFBS_FAIL)
continue;
ascii_codes[k] = ascii_code;
temp_states[k] = ctx->goto_table[state][ascii_code];
k++;
}
/* if we have any non fail transitions from our previous for search,
* store the acii codes as well the corresponding states */
if (k > 0) {
no_of_entries[0] = k;
if (state != 0) {
int jump = (k + 3) & 0xFFC;
curr_loc += jump / 4;
}
memcpy(curr_loc, temp_states, k * sizeof(SC_AC_GFBS_STATE_TYPE_U32));
curr_loc += k;
}
failure_entry[0] = ctx->failure_table[state];
}
}
return;
}
static inline void SCACGfbsClubOutputStatePresenceWithModGotoTable(MpmCtx *mpm_ctx)
{
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
int state = 0;
int no_of_entries;
int i;
if (ctx->state_count < 32767) {
uint16_t *states;
for (state = 0; state < ctx->state_count; state++) {
no_of_entries = *((uint16_t *)ctx->goto_table_mod_pointers[state]);
if (no_of_entries == 0)
continue;
//if (*((uint16_t *)ctx->goto_table_mod_pointers[state] + 1) != 0) {
if (ctx->output_table[((uint16_t *)ctx->goto_table_mod_pointers[state] + 1)[0]].no_of_entries != 0) {
*((uint16_t *)ctx->goto_table_mod_pointers[state] + 1) |= (1 << 15);
}
if (state == 0)
states = ((uint16_t *)ctx->goto_table_mod_pointers[state] + 2);
else
states = ((uint16_t *)ctx->goto_table_mod_pointers[state] + 2 + ((no_of_entries + 1) & 0xFFE) / 2);
for (i = 0; i < no_of_entries; i++) {
//if (states[i] == 0)
if (ctx->output_table[states[i]].no_of_entries == 0)
continue;
states[i] |= (1 << 15);
}
}
} else {
uint32_t *states;
for (state = 0; state < ctx->state_count; state++) {
no_of_entries = *((uint32_t *)ctx->goto_table_mod_pointers[state]);
if (no_of_entries == 0)
continue;
//if (*((uint32_t *)ctx->goto_table_mod_pointers[state] + 1) != 0) {
if (ctx->output_table[((uint32_t *)ctx->goto_table_mod_pointers[state] + 1)[0]].no_of_entries != 0) {
*((uint32_t *)ctx->goto_table_mod_pointers[state] + 1) |= (1 << 24);
}
if (state == 0)
states = ((uint32_t *)ctx->goto_table_mod_pointers[state] + 2);
else
states = ((uint32_t *)ctx->goto_table_mod_pointers[state] + 2 + ((no_of_entries + 3) & 0xFFC) / 4);
for (i = 0; i < no_of_entries; i++) {
//if (states[i] == 0)
if (ctx->output_table[states[i]].no_of_entries == 0)
continue;
states[i] |= (1 << 24);
}
}
}
return;
}
static inline void SCACGfbsInsertCaseSensitiveEntriesForPatterns(MpmCtx *mpm_ctx)
{
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
int32_t state = 0;
uint32_t k = 0;
for (state = 0; state < ctx->state_count; state++) {
if (ctx->output_table[state].no_of_entries == 0)
continue;
for (k = 0; k < ctx->output_table[state].no_of_entries; k++) {
if (ctx->pid_pat_list[ctx->output_table[state].pids[k]].cs != NULL) {
ctx->output_table[state].pids[k] &= 0x0000FFFF;
ctx->output_table[state].pids[k] |= 1 << 16;
}
}
}
return;
}
/**
* \brief Process the patterns and prepare the state table.
*
* \param mpm_ctx Pointer to the mpm context.
*/
static inline void SCACGfbsPrepareStateTable(MpmCtx *mpm_ctx)
{
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
/* create the 0th state in the goto table and output_table */
SCACGfbsInitNewState(mpm_ctx);
/* create the goto table */
SCACGfbsCreateGotoTable(mpm_ctx);
/* create the failure table */
SCACGfbsCreateFailureTable(mpm_ctx);
/* create the final state(delta) table */
SCACGfbsCreateModGotoTable(mpm_ctx);
/* club the output state presence with transition entries */
SCACGfbsClubOutputStatePresenceWithModGotoTable(mpm_ctx);
/* club nocase entries */
SCACGfbsInsertCaseSensitiveEntriesForPatterns(mpm_ctx);
/* we don't need this anymore */
SCFree(ctx->goto_table);
ctx->goto_table = NULL;
SCFree(ctx->failure_table);
ctx->failure_table = NULL;
return;
}
/**
* \brief Process the patterns added to the mpm, and create the internal tables.
*
* \param mpm_ctx Pointer to the mpm context.
*/
int SCACGfbsPreparePatterns(MpmCtx *mpm_ctx)
{
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
if (mpm_ctx->pattern_cnt == 0 || ctx->init_hash == NULL) {
SCLogDebug("No patterns supplied to this mpm_ctx");
return 0;
}
/* alloc the pattern array */
ctx->parray = (SCACGfbsPattern **)SCMalloc(mpm_ctx->pattern_cnt *
sizeof(SCACGfbsPattern *));
if (ctx->parray == NULL)
goto error;
memset(ctx->parray, 0, mpm_ctx->pattern_cnt * sizeof(SCACGfbsPattern *));
mpm_ctx->memory_cnt++;
mpm_ctx->memory_size += (mpm_ctx->pattern_cnt * sizeof(SCACGfbsPattern *));
/* populate it with the patterns in the hash */
uint32_t i = 0, p = 0;
for (i = 0; i < INIT_HASH_SIZE; i++) {
SCACGfbsPattern *node = ctx->init_hash[i], *nnode = NULL;
while(node != NULL) {
nnode = node->next;
node->next = NULL;
ctx->parray[p++] = node;
node = nnode;
}
}
/* we no longer need the hash, so free it's memory */
SCFree(ctx->init_hash);
ctx->init_hash = NULL;
/* the memory consumed by a single state in our goto table */
//ctx->single_state_size = sizeof(int32_t) * 256;
/* handle no case patterns */
ctx->pid_pat_list = SCMalloc((ctx->max_pat_id + 1)* sizeof(SCACGfbsPatternList));
if (ctx->pid_pat_list == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
exit(EXIT_FAILURE);
}
memset(ctx->pid_pat_list, 0, (ctx->max_pat_id + 1) * sizeof(SCACGfbsPatternList));
for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
if (!(ctx->parray[i]->flags & MPM_PATTERN_FLAG_NOCASE)) {
ctx->pid_pat_list[ctx->parray[i]->id].cs = SCMalloc(ctx->parray[i]->len);
if (ctx->pid_pat_list[ctx->parray[i]->id].cs == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
exit(EXIT_FAILURE);
}
memcpy(ctx->pid_pat_list[ctx->parray[i]->id].cs,
ctx->parray[i]->original_pat, ctx->parray[i]->len);
ctx->pid_pat_list[ctx->parray[i]->id].patlen = ctx->parray[i]->len;
}
}
/* prepare the state table required by AC */
SCACGfbsPrepareStateTable(mpm_ctx);
/* free all the stored patterns. Should save us a good 100-200 mbs */
for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
if (ctx->parray[i] != NULL) {
SCACGfbsFreePattern(mpm_ctx, ctx->parray[i]);
}
}
SCFree(ctx->parray);
ctx->parray = NULL;
mpm_ctx->memory_cnt--;
mpm_ctx->memory_size -= (mpm_ctx->pattern_cnt * sizeof(SCACGfbsPattern *));
return 0;
error:
return -1;
}
/**
* \brief Init the mpm thread context.
*
* \param mpm_ctx Pointer to the mpm context.
* \param mpm_thread_ctx Pointer to the mpm thread context.
* \param matchsize We don't need this.
*/
void SCACGfbsInitThreadCtx(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx,
uint32_t matchsize)
{
memset(mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
mpm_thread_ctx->ctx = SCMalloc(sizeof(SCACGfbsThreadCtx));
if (mpm_thread_ctx->ctx == NULL) {
exit(EXIT_FAILURE);
}
memset(mpm_thread_ctx->ctx, 0, sizeof(SCACGfbsThreadCtx));
mpm_thread_ctx->memory_cnt++;
mpm_thread_ctx->memory_size += sizeof(SCACGfbsThreadCtx);
return;
}
/**
* \brief Initialize the AC context.
*
* \param mpm_ctx Mpm context.
* \param module_handle Cuda module handle from the cuda handler API. We don't
* have to worry about this here.
*/
void SCACGfbsInitCtx(MpmCtx *mpm_ctx)
{
if (mpm_ctx->ctx != NULL)
return;
mpm_ctx->ctx = SCMalloc(sizeof(SCACGfbsCtx));
if (mpm_ctx->ctx == NULL) {
exit(EXIT_FAILURE);
}
memset(mpm_ctx->ctx, 0, sizeof(SCACGfbsCtx));
mpm_ctx->memory_cnt++;
mpm_ctx->memory_size += sizeof(SCACGfbsCtx);
/* initialize the hash we use to speed up pattern insertions */
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
ctx->init_hash = SCMalloc(sizeof(SCACGfbsPattern *) * INIT_HASH_SIZE);
if (ctx->init_hash == NULL) {
exit(EXIT_FAILURE);
}
memset(ctx->init_hash, 0, sizeof(SCACGfbsPattern *) * INIT_HASH_SIZE);
/* get conf values for AC from our yaml file. We have no conf values for
* now. We will certainly need this, as we develop the algo */
SCACGfbsGetConfig();
SCReturn;
}
/**
* \brief Destroy the mpm thread context.
*
* \param mpm_ctx Pointer to the mpm context.
* \param mpm_thread_ctx Pointer to the mpm thread context.
*/
void SCACGfbsDestroyThreadCtx(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx)
{
SCACGfbsPrintSearchStats(mpm_thread_ctx);
if (mpm_thread_ctx->ctx != NULL) {
SCFree(mpm_thread_ctx->ctx);
mpm_thread_ctx->ctx = NULL;
mpm_thread_ctx->memory_cnt--;
mpm_thread_ctx->memory_size -= sizeof(SCACGfbsThreadCtx);
}
return;
}
/**
* \brief Destroy the mpm context.
*
* \param mpm_ctx Pointer to the mpm context.
*/
void SCACGfbsDestroyCtx(MpmCtx *mpm_ctx)
{
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
if (ctx == NULL)
return;
if (ctx->init_hash != NULL) {
SCFree(ctx->init_hash);
ctx->init_hash = NULL;
mpm_ctx->memory_cnt--;
mpm_ctx->memory_size -= (INIT_HASH_SIZE * sizeof(SCACGfbsPattern *));
}
if (ctx->parray != NULL) {
uint32_t i;
for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
if (ctx->parray[i] != NULL) {
SCACGfbsFreePattern(mpm_ctx, ctx->parray[i]);
}
}
SCFree(ctx->parray);
ctx->parray = NULL;
mpm_ctx->memory_cnt--;
mpm_ctx->memory_size -= (mpm_ctx->pattern_cnt * sizeof(SCACGfbsPattern *));
}
if (ctx->goto_table_mod != NULL) {
SCFree(ctx->goto_table_mod);
ctx->goto_table_mod = NULL;
mpm_ctx->memory_cnt--;
if (ctx->state_count < 32767) {
mpm_ctx->memory_size -= (ctx->state_count * sizeof(SC_AC_GFBS_STATE_TYPE_U16) * 3 +
256 * sizeof(SC_AC_GFBS_STATE_TYPE_U16) * 2);
} else {
mpm_ctx->memory_size -= (ctx->state_count * sizeof(SC_AC_GFBS_STATE_TYPE_U32) * 3 +
256 * sizeof(SC_AC_GFBS_STATE_TYPE_U32) * 2);
}
}
if (ctx->goto_table_mod_pointers != NULL) {
SCFree(ctx->goto_table_mod_pointers);
ctx->goto_table_mod_pointers = NULL;
mpm_ctx->memory_cnt--;
mpm_ctx->memory_size -= ctx->state_count * sizeof(uint8_t *);
}
if (ctx->output_table != NULL) {
int32_t state_count;
for (state_count = 0; state_count < ctx->state_count; state_count++) {
if (ctx->output_table[state_count].pids != NULL) {
SCFree(ctx->output_table[state_count].pids);
}
}
SCFree(ctx->output_table);
}
if (ctx->pid_pat_list != NULL) {
int i;
for (i = 0; i < (ctx->max_pat_id + 1); i++) {
if (ctx->pid_pat_list[i].cs != NULL)
SCFree(ctx->pid_pat_list[i].cs);
}
SCFree(ctx->pid_pat_list);
}
SCFree(mpm_ctx->ctx);
mpm_ctx->memory_cnt--;
mpm_ctx->memory_size -= sizeof(SCACGfbsCtx);
return;
}
/**
* \brief The aho corasick search function.
*
* \param mpm_ctx Pointer to the mpm context.
* \param mpm_thread_ctx Pointer to the mpm thread context.
* \param pmq Pointer to the Pattern Matcher Queue to hold
* search matches.
* \param buf Buffer to be searched.
* \param buflen Buffer length.
*
* \retval matches Match count.
*/
uint32_t SCACGfbsSearch(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx,
PatternMatcherQueue *pmq, uint8_t *buf, uint16_t buflen)
{
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
int matches = 0;
uint8_t buf_local;
SCACGfbsPatternList *pid_pat_list = ctx->pid_pat_list;
/* really hate the extra cmp here, but can't help it */
if (ctx->state_count < 32767) {
/* \todo Change it for stateful MPM. Supply the state using mpm_thread_ctx */
int32_t temp_state;
uint16_t no_of_entries;
uint8_t *ascii_codes;
uint16_t **goto_table_mod_pointers = (uint16_t **)ctx->goto_table_mod_pointers;
//int32_t *failure_table = ctx->failure_table;
int i;
/* \todo tried loop unrolling with register var, with no perf increase. Need
* to dig deeper */
/* with so many var declarations the register declaration here is useless */
register int32_t state = 0;
for (i = 0; i < buflen; i++) {
if (state == 0) {
state = (goto_table_mod_pointers[0] + 2)[u8_tolower(buf[i])];
} else {
/* get the goto state transition */
no_of_entries = *(goto_table_mod_pointers[state & 0x7FFF]);
if (no_of_entries == 0) {
temp_state = SC_AC_GFBS_FAIL;
} else {
if (no_of_entries == 1) {
ascii_codes = (uint8_t *)(goto_table_mod_pointers[state & 0x7FFF] + 2);
buf_local = u8_tolower(buf[i]);
if (buf_local == ascii_codes[0])
temp_state = ((uint16_t *)(ascii_codes + ((no_of_entries + 1) & 0xFFE)))[0];
else
temp_state = SC_AC_GFBS_FAIL;
} else {
buf_local = u8_tolower(buf[i]);
ascii_codes = (uint8_t *)(goto_table_mod_pointers[state & 0x7FFF] + 2);
int low = 0;
int high = no_of_entries;
int mid;
temp_state = SC_AC_GFBS_FAIL;
while (low <= high) {
mid = (low + high) / 2;
if (ascii_codes[mid] == buf_local) {
temp_state = ((uint16_t *)(ascii_codes + ((no_of_entries + 1) & 0xFFE)))[mid];
break;
} else if (ascii_codes[mid] < buf_local) {
low = mid + 1;
} else {
high = mid - 1;
}
}
}
}
while (temp_state == SC_AC_GFBS_FAIL) {
state = *(goto_table_mod_pointers[state & 0x7FFF] + 1);
/* get the goto state transition */
no_of_entries = *(goto_table_mod_pointers[state & 0x7FFF]);
if (no_of_entries == 0) {
temp_state = SC_AC_GFBS_FAIL;
} else {
if (no_of_entries == 1) {
ascii_codes = (uint8_t *)(goto_table_mod_pointers[state & 0x7FFF] + 2);
buf_local = u8_tolower(buf[i]);
if (buf_local == ascii_codes[0])
temp_state = ((uint16_t *)(ascii_codes + ((no_of_entries + 1) & 0xFFE)))[0];
else
temp_state = SC_AC_GFBS_FAIL;
} else {
ascii_codes = (uint8_t *)(goto_table_mod_pointers[state & 0x7FFF] + 2);
buf_local = u8_tolower(buf[i]);
if (state == 0) {
temp_state = ((uint16_t *)ascii_codes)[buf_local];
} else {
int low = 0;
int high = no_of_entries;
int mid;
temp_state = SC_AC_GFBS_FAIL;
while (low <= high) {
mid = (low + high) / 2;
if (ascii_codes[mid] == buf_local) {
temp_state = ((uint16_t *)(ascii_codes + ((no_of_entries + 1) & 0xFFE)))[mid];
break;
} else if (ascii_codes[mid] < buf_local) {
low = mid + 1;
} else {
high = mid - 1;
}
}
}
}
} /* else - if (no_of_entries == 0) */
} /* while (temp_state == SC_AC_GFBS_FAIL) */
state = temp_state;
}
if (state & 0x8000) {
uint32_t no_of_pid_entries = ctx->output_table[state & 0x7FFF].no_of_entries;
uint32_t *pids = ctx->output_table[state & 0x7FFF].pids;
uint32_t k = 0;
for (k = 0; k < no_of_pid_entries; k++) {
if (pids[k] & 0xFFFF0000) {
if (SCMemcmp(pid_pat_list[pids[k] & 0x0000FFFF].cs,
buf + i - pid_pat_list[pids[k] & 0x0000FFFF].patlen + 1,
pid_pat_list[pids[k] & 0x0000FFFF].patlen) != 0) {
/* inside loop */
continue;
}
if (pmq->pattern_id_bitarray[(pids[k] & 0x0000FFFF) / 8] & (1 << ((pids[k] & 0x0000FFFF) % 8))) {
;
} else {
pmq->pattern_id_bitarray[(pids[k] & 0x0000FFFF) / 8] |= (1 << ((pids[k] & 0x0000FFFF) % 8));
pmq->pattern_id_array[pmq->pattern_id_array_cnt++] = (pids[k] & 0x0000FFFF);
}
matches++;
} else {
if (pmq->pattern_id_bitarray[pids[k] / 8] & (1 << (pids[k] % 8))) {
;
} else {
pmq->pattern_id_bitarray[pids[k] / 8] |= (1 << (pids[k] % 8));
pmq->pattern_id_array[pmq->pattern_id_array_cnt++] = pids[k];
}
matches++;
}
}
} /* if (ctx->output_table[state].no_of_entries != 0) */
} /* for (i = 0; i < buflen; i++) */
} else {
/* \todo Change it for stateful MPM. Supply the state using mpm_thread_ctx */
int32_t temp_state = 0;
uint32_t no_of_entries;
uint8_t *ascii_codes = NULL;
uint32_t **goto_table_mod_pointers = (uint32_t **)ctx->goto_table_mod_pointers;
//int32_t *failure_table = ctx->failure_table;
int i = 0;
/* \todo tried loop unrolling with register var, with no perf increase. Need
* to dig deeper */
register int32_t state = 0;
for (i = 0; i < buflen; i++) {
if (state == 0) {
state = (goto_table_mod_pointers[0] + 2)[u8_tolower(buf[i])];
} else {
/* get the goto state transition */
no_of_entries = *(goto_table_mod_pointers[state & 0x00FFFFFF]);
if (no_of_entries == 0) {
temp_state = SC_AC_GFBS_FAIL;
} else {
if (no_of_entries == 1) {
ascii_codes = (uint8_t *)(goto_table_mod_pointers[state & 0x00FFFFFF] + 2);
buf_local = u8_tolower(buf[i]);
if (buf_local == ascii_codes[0])
temp_state = ((uint32_t *)(ascii_codes + ((no_of_entries + 3) & 0xFFC)))[0];
else
temp_state = SC_AC_GFBS_FAIL;
} else {
buf_local = u8_tolower(buf[i]);
ascii_codes = (uint8_t *)(goto_table_mod_pointers[state & 0x00FFFFFF] + 2);
int low = 0;
int high = no_of_entries;
int mid;
temp_state = SC_AC_GFBS_FAIL;
while (low <= high) {
mid = (low + high) / 2;
if (ascii_codes[mid] == buf_local) {
temp_state = ((uint32_t *)(ascii_codes + ((no_of_entries + 3) & 0xFFC)))[mid];
break;
} else if (ascii_codes[mid] < buf_local) {
low = mid + 1;
} else {
high = mid - 1;
}
}
}
}
while (temp_state == SC_AC_GFBS_FAIL) {
state = *(goto_table_mod_pointers[state & 0x00FFFFFF] + 1);
/* get the goto state transition */
no_of_entries = *(goto_table_mod_pointers[state & 0x00FFFFFF]);
if (no_of_entries == 0) {
temp_state = SC_AC_GFBS_FAIL;
} else {
if (no_of_entries == 1) {
ascii_codes = (uint8_t *)(goto_table_mod_pointers[state & 0x00FFFFFF] + 2);
buf_local = u8_tolower(buf[i]);
if (buf_local == ascii_codes[0])
temp_state = ((uint32_t *)(ascii_codes + ((no_of_entries + 3) & 0xFFC)))[0];
else
temp_state = SC_AC_GFBS_FAIL;
} else {
ascii_codes = (uint8_t *)(goto_table_mod_pointers[state & 0x00FFFFFF] + 2);
buf_local = u8_tolower(buf[i]);
if (state == 0) {
temp_state = ((uint32_t *)ascii_codes)[buf_local];
} else {
int low = 0;
int high = no_of_entries;
int mid;
temp_state = SC_AC_GFBS_FAIL;
while (low <= high) {
mid = (low + high) / 2;
if (ascii_codes[mid] == buf_local) {
temp_state = ((uint32_t *)(ascii_codes + ((no_of_entries + 3) & 0xFFC)))[mid];
break;
} else if (ascii_codes[mid] < buf_local) {
low = mid + 1;
} else {
high = mid - 1;
}
}
}
} /* else - if (no_of_entries[0] == 1) */
} /* else - if (no_of_entries[0] == 0) */
} /* while (temp_state == SC_AC_GFBS_FAIL) */
state = temp_state;
}
if (state & 0x01000000) {
uint32_t no_of_pid_entries = ctx->output_table[state & 0x00FFFFFF].no_of_entries;
uint32_t *pids = ctx->output_table[state & 0x00FFFFFF].pids;
uint32_t k = 0;
for (k = 0; k < no_of_pid_entries; k++) {
if (pids[k] & 0xFFFF0000) {
if (SCMemcmp(pid_pat_list[pids[k] & 0x0000FFFF].cs,
buf + i - pid_pat_list[pids[k] & 0x0000FFFF].patlen + 1,
pid_pat_list[pids[k] & 0x0000FFFF].patlen) != 0) {
/* inside loop */
continue;
}
if (pmq->pattern_id_bitarray[(pids[k] & 0x0000FFFF) / 8] & (1 << ((pids[k] & 0x0000FFFF) % 8))) {
;
} else {
pmq->pattern_id_bitarray[(pids[k] & 0x0000FFFF) / 8] |= (1 << ((pids[k] & 0x0000FFFF) % 8));
pmq->pattern_id_array[pmq->pattern_id_array_cnt++] = (pids[k] & 0x0000FFFF);
}
matches++;
} else {
if (pmq->pattern_id_bitarray[pids[k] / 8] & (1 << (pids[k] % 8))) {
;
} else {
pmq->pattern_id_bitarray[pids[k] / 8] |= (1 << (pids[k] % 8));
pmq->pattern_id_array[pmq->pattern_id_array_cnt++] = pids[k];
}
matches++;
}
//loop1:
//;
}
} /* if (ctx->output_table[state].no_of_entries != 0) */
} /* for (i = 0; i < buflen; i++) */
}
return matches;
}
/**
* \brief Add a case insensitive pattern. Although we have different calls for
* adding case sensitive and insensitive patterns, we make a single call
* for either case. No special treatment for either case.
*
* \param mpm_ctx Pointer to the mpm context.
* \param pat The pattern to add.
* \param patnen The pattern length.
* \param offset Ignored.
* \param depth Ignored.
* \param pid The pattern id.
* \param sid Ignored.
* \param flags Flags associated with this pattern.
*
* \retval 0 On success.
* \retval -1 On failure.
*/
int SCACGfbsAddPatternCI(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen,
uint16_t offset, uint16_t depth, uint32_t pid,
uint32_t sid, uint8_t flags)
{
flags |= MPM_PATTERN_FLAG_NOCASE;
return SCACGfbsAddPattern(mpm_ctx, pat, patlen, offset, depth, pid, sid, flags);
}
/**
* \brief Add a case sensitive pattern. Although we have different calls for
* adding case sensitive and insensitive patterns, we make a single call
* for either case. No special treatment for either case.
*
* \param mpm_ctx Pointer to the mpm context.
* \param pat The pattern to add.
* \param patnen The pattern length.
* \param offset Ignored.
* \param depth Ignored.
* \param pid The pattern id.
* \param sid Ignored.
* \param flags Flags associated with this pattern.
*
* \retval 0 On success.
* \retval -1 On failure.
*/
int SCACGfbsAddPatternCS(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen,
uint16_t offset, uint16_t depth, uint32_t pid,
uint32_t sid, uint8_t flags)
{
return SCACGfbsAddPattern(mpm_ctx, pat, patlen, offset, depth, pid, sid, flags);
}
void SCACGfbsPrintSearchStats(MpmThreadCtx *mpm_thread_ctx)
{
#ifdef SC_AC_COUNTERS
SCACGfbsThreadCtx *ctx = (SCACGfbsThreadCtx *)mpm_thread_ctx->ctx;
printf("AC Thread Search stats (ctx %p)\n", ctx);
printf("Total calls: %" PRIu32 "\n", ctx->total_calls);
printf("Total matches: %" PRIu64 "\n", ctx->total_matches);
#endif /* SC_AC_COUNTERS */
return;
}
void SCACGfbsPrintInfo(MpmCtx *mpm_ctx)
{
SCACGfbsCtx *ctx = (SCACGfbsCtx *)mpm_ctx->ctx;
printf("MPM AC Information:\n");
printf("Memory allocs: %" PRIu32 "\n", mpm_ctx->memory_cnt);
printf("Memory alloced: %" PRIu32 "\n", mpm_ctx->memory_size);
printf(" Sizeof:\n");
printf(" MpmCtx %" PRIuMAX "\n", (uintmax_t)sizeof(MpmCtx));
printf(" SCACGfbsCtx: %" PRIuMAX "\n", (uintmax_t)sizeof(SCACGfbsCtx));
printf(" SCACGfbsPattern %" PRIuMAX "\n", (uintmax_t)sizeof(SCACGfbsPattern));
printf(" SCACGfbsPattern %" PRIuMAX "\n", (uintmax_t)sizeof(SCACGfbsPattern));
printf("Unique Patterns: %" PRIu32 "\n", mpm_ctx->pattern_cnt);
printf("Smallest: %" PRIu32 "\n", mpm_ctx->minlen);
printf("Largest: %" PRIu32 "\n", mpm_ctx->maxlen);
printf("Total states in the state table: %" PRIu32 "\n", ctx->state_count);
printf("\n");
return;
}
/*************************************Unittests********************************/
#ifdef UNITTESTS
static int SCACGfbsTest01(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 match */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "abcdefghjiklmnopqrstuvwxyz";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest02(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 match */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abce", 4, 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "abcdefghjiklmnopqrstuvwxyz";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 0)
result = 1;
else
printf("0 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest03(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 match */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
/* 1 match */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcde", 4, 0, 0, 1, 0, 0);
/* 1 match */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghj", 4, 0, 0, 2, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 3);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "abcdefghjiklmnopqrstuvwxyz";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 3)
result = 1;
else
printf("3 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest04(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcdegh", 6, 0, 0, 1, 0, 0);
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghjxyz", 7, 0, 0, 2, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 3);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "abcdefghjiklmnopqrstuvwxyz";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest05(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghJikl", 7, 0, 0, 2, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 3);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "abcdefghjiklmnopqrstuvwxyz";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 3)
result = 1;
else
printf("3 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest06(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "abcd";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest07(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* should match 30 times */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"A", 1, 0, 0, 0, 0, 0);
/* should match 29 times */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 1, 0, 0);
/* should match 28 times */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAA", 3, 0, 0, 2, 0, 0);
/* 26 */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAA", 5, 0, 0, 3, 0, 0);
/* 21 */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAA", 10, 0, 0, 4, 0, 0);
/* 1 */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
30, 0, 0, 5, 0, 0);
/* total matches: 135 */
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 6);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 135)
result = 1;
else
printf("135 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest08(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 match */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)"a", 1);
if (cnt == 0)
result = 1;
else
printf("0 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest09(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 match */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ab", 2, 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)"ab", 2);
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest10(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 match */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcdefgh", 8, 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "01234567890123456789012345678901234567890123456789"
"01234567890123456789012345678901234567890123456789"
"abcdefgh"
"01234567890123456789012345678901234567890123456789"
"01234567890123456789012345678901234567890123456789";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest11(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"he", 2, 0, 0, 1, 0, 0) == -1)
goto end;
if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"she", 3, 0, 0, 2, 0, 0) == -1)
goto end;
if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"his", 3, 0, 0, 3, 0, 0) == -1)
goto end;
if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"hers", 4, 0, 0, 4, 0, 0) == -1)
goto end;
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 4);
if (SCACGfbsPreparePatterns(&mpm_ctx) == -1)
goto end;
result = 1;
char *buf = "he";
result &= (SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
strlen(buf)) == 1);
buf = "she";
result &= (SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
strlen(buf)) == 2);
buf = "his";
result &= (SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
strlen(buf)) == 1);
buf = "hers";
result &= (SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
strlen(buf)) == 2);
end:
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest12(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 match */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"wxyz", 4, 0, 0, 0, 0, 0);
/* 1 match */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"vwxyz", 5, 0, 0, 1, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 2);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "abcdefghijklmnopqrstuvwxyz";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 2)
result = 1;
else
printf("2 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest13(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 match */
char *pat = "abcdefghijklmnopqrstuvwxyzABCD";
MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, strlen(pat), 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "abcdefghijklmnopqrstuvwxyzABCD";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest14(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 match */
char *pat = "abcdefghijklmnopqrstuvwxyzABCDE";
MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, strlen(pat), 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "abcdefghijklmnopqrstuvwxyzABCDE";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest15(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 match */
char *pat = "abcdefghijklmnopqrstuvwxyzABCDEF";
MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, strlen(pat), 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "abcdefghijklmnopqrstuvwxyzABCDEF";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest16(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 match */
char *pat = "abcdefghijklmnopqrstuvwxyzABC";
MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, strlen(pat), 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "abcdefghijklmnopqrstuvwxyzABC";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest17(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 match */
char *pat = "abcdefghijklmnopqrstuvwxyzAB";
MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, strlen(pat), 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "abcdefghijklmnopqrstuvwxyzAB";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest18(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 match */
char *pat = "abcde""fghij""klmno""pqrst""uvwxy""z";
MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, strlen(pat), 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "abcde""fghij""klmno""pqrst""uvwxy""z";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest19(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 */
char *pat = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, strlen(pat), 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest20(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 */
char *pat = "AAAAA""AAAAA""AAAAA""AAAAA""AAAAA""AAAAA""AA";
MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, strlen(pat), 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "AAAAA""AAAAA""AAAAA""AAAAA""AAAAA""AAAAA""AA";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest21(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)"AA", 2);
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest22(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 match */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
/* 1 match */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcde", 5, 0, 0, 1, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 2);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "abcdefghijklmnopqrstuvwxyz";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 2)
result = 1;
else
printf("2 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest23(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)"aa", 2);
if (cnt == 0)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest24(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 1 */
MpmAddPatternCI(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)"aa", 2);
if (cnt == 1)
result = 1;
else
printf("1 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest25(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghiJkl", 7, 0, 0, 2, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 3);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 3)
result = 1;
else
printf("3 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest26(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
MpmAddPatternCI(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 0, 0, 0);
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 1, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 2);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "works";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 1)
result = 1;
else
printf("3 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest27(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 0 match */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ONE", 3, 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "tone";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 0)
result = 1;
else
printf("0 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest28(void)
{
int result = 0;
MpmCtx mpm_ctx;
MpmThreadCtx mpm_thread_ctx;
PatternMatcherQueue pmq;
memset(&mpm_ctx, 0, sizeof(MpmCtx));
memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
MpmInitCtx(&mpm_ctx, MPM_AC_GFBS);
SCACGfbsInitThreadCtx(&mpm_ctx, &mpm_thread_ctx, 0);
/* 0 match */
MpmAddPatternCS(&mpm_ctx, (uint8_t *)"one", 3, 0, 0, 0, 0, 0);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
13 years ago
PmqSetup(&pmq, 1);
SCACGfbsPreparePatterns(&mpm_ctx);
char *buf = "tONE";
uint32_t cnt = SCACGfbsSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
(uint8_t *)buf, strlen(buf));
if (cnt == 0)
result = 1;
else
printf("0 != %" PRIu32 " ",cnt);
SCACGfbsDestroyCtx(&mpm_ctx);
SCACGfbsDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
PmqFree(&pmq);
return result;
}
static int SCACGfbsTest29(void)
{
uint8_t *buf = (uint8_t *)"onetwothreefourfivesixseveneightnine";
uint16_t buflen = strlen((char *)buf);
Packet *p = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
int result = 0;
memset(&th_v, 0, sizeof(th_v));
p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->mpm_matcher = MPM_AC_GFBS;
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
"(content:\"onetwothreefourfivesixseveneightnine\"; sid:1;)");
if (de_ctx->sig_list == NULL)
goto end;
de_ctx->sig_list->next = SigInit(de_ctx, "alert tcp any any -> any any "
"(content:\"onetwothreefourfivesixseveneightnine\"; fast_pattern:3,3; sid:2;)");
if (de_ctx->sig_list->next == 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) != 1) {
printf("if (PacketAlertCheck(p, 1) != 1) failure\n");
goto end;
}
if (PacketAlertCheck(p, 2) != 1) {
printf("if (PacketAlertCheck(p, 1) != 2) failure\n");
goto end;
}
result = 1;
end:
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
DetectEngineCtxFree(de_ctx);
}
UTHFreePackets(&p, 1);
return result;
}
#endif /* UNITTESTS */
void SCACGfbsRegisterTests(void)
{
#ifdef UNITTESTS
UtRegisterTest("SCACGfbsTest01", SCACGfbsTest01, 1);
UtRegisterTest("SCACGfbsTest02", SCACGfbsTest02, 1);
UtRegisterTest("SCACGfbsTest03", SCACGfbsTest03, 1);
UtRegisterTest("SCACGfbsTest04", SCACGfbsTest04, 1);
UtRegisterTest("SCACGfbsTest05", SCACGfbsTest05, 1);
UtRegisterTest("SCACGfbsTest06", SCACGfbsTest06, 1);
UtRegisterTest("SCACGfbsTest07", SCACGfbsTest07, 1);
UtRegisterTest("SCACGfbsTest08", SCACGfbsTest08, 1);
UtRegisterTest("SCACGfbsTest09", SCACGfbsTest09, 1);
UtRegisterTest("SCACGfbsTest10", SCACGfbsTest10, 1);
UtRegisterTest("SCACGfbsTest11", SCACGfbsTest11, 1);
UtRegisterTest("SCACGfbsTest12", SCACGfbsTest12, 1);
UtRegisterTest("SCACGfbsTest13", SCACGfbsTest13, 1);
UtRegisterTest("SCACGfbsTest14", SCACGfbsTest14, 1);
UtRegisterTest("SCACGfbsTest15", SCACGfbsTest15, 1);
UtRegisterTest("SCACGfbsTest16", SCACGfbsTest16, 1);
UtRegisterTest("SCACGfbsTest17", SCACGfbsTest17, 1);
UtRegisterTest("SCACGfbsTest18", SCACGfbsTest18, 1);
UtRegisterTest("SCACGfbsTest19", SCACGfbsTest19, 1);
UtRegisterTest("SCACGfbsTest20", SCACGfbsTest20, 1);
UtRegisterTest("SCACGfbsTest21", SCACGfbsTest21, 1);
UtRegisterTest("SCACGfbsTest22", SCACGfbsTest22, 1);
UtRegisterTest("SCACGfbsTest23", SCACGfbsTest23, 1);
UtRegisterTest("SCACGfbsTest24", SCACGfbsTest24, 1);
UtRegisterTest("SCACGfbsTest25", SCACGfbsTest25, 1);
UtRegisterTest("SCACGfbsTest26", SCACGfbsTest26, 1);
UtRegisterTest("SCACGfbsTest27", SCACGfbsTest27, 1);
UtRegisterTest("SCACGfbsTest28", SCACGfbsTest28, 1);
UtRegisterTest("SCACGfbsTest29", SCACGfbsTest29, 1);
#endif
return;
}