|
|
|
@ -2,6 +2,7 @@
|
|
|
|
|
|
|
|
|
|
#include "eidps-common.h"
|
|
|
|
|
#include "debug.h"
|
|
|
|
|
#include "util-unittest.h"
|
|
|
|
|
#include "decode.h"
|
|
|
|
|
#include "threads.h"
|
|
|
|
|
|
|
|
|
@ -22,8 +23,10 @@
|
|
|
|
|
static Pool *al_result_pool = NULL;
|
|
|
|
|
|
|
|
|
|
/** \brief Alloc a AppLayerParserResultElmt func for the pool */
|
|
|
|
|
static void *AlpResultElmtPoolAlloc(void *null) {
|
|
|
|
|
AppLayerParserResultElmt *e = (AppLayerParserResultElmt *)malloc(sizeof(AppLayerParserResultElmt));
|
|
|
|
|
static void *AlpResultElmtPoolAlloc(void *null)
|
|
|
|
|
{
|
|
|
|
|
AppLayerParserResultElmt *e = (AppLayerParserResultElmt *)malloc
|
|
|
|
|
(sizeof(AppLayerParserResultElmt));
|
|
|
|
|
if (e == NULL) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
@ -32,7 +35,8 @@ static void *AlpResultElmtPoolAlloc(void *null) {
|
|
|
|
|
return e;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void AlpResultElmtPoolFree(void *e) {
|
|
|
|
|
static void AlpResultElmtPoolFree(void *e)
|
|
|
|
|
{
|
|
|
|
|
AppLayerParserResultElmt *re = (AppLayerParserResultElmt *)e;
|
|
|
|
|
|
|
|
|
|
if (re->flags & ALP_RESULT_ELMT_ALLOC) {
|
|
|
|
@ -42,7 +46,8 @@ static void AlpResultElmtPoolFree(void *e) {
|
|
|
|
|
free(re);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static AppLayerParserResultElmt *AlpGetResultElmt(void) {
|
|
|
|
|
static AppLayerParserResultElmt *AlpGetResultElmt(void)
|
|
|
|
|
{
|
|
|
|
|
AppLayerParserResultElmt *e = (AppLayerParserResultElmt *)PoolGet(al_result_pool);
|
|
|
|
|
if (e == NULL) {
|
|
|
|
|
return NULL;
|
|
|
|
@ -51,7 +56,8 @@ static AppLayerParserResultElmt *AlpGetResultElmt(void) {
|
|
|
|
|
return e;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void AlpReturnResultElmt(AppLayerParserResultElmt *e) {
|
|
|
|
|
static void AlpReturnResultElmt(AppLayerParserResultElmt *e)
|
|
|
|
|
{
|
|
|
|
|
if (e->flags & ALP_RESULT_ELMT_ALLOC) {
|
|
|
|
|
if (e->data_ptr != NULL)
|
|
|
|
|
free(e->data_ptr);
|
|
|
|
@ -64,7 +70,8 @@ static void AlpReturnResultElmt(AppLayerParserResultElmt *e) {
|
|
|
|
|
PoolReturn(al_result_pool, (void *)e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void AlpAppendResultElmt(AppLayerParserResult *r, AppLayerParserResultElmt *e) {
|
|
|
|
|
static void AlpAppendResultElmt(AppLayerParserResult *r, AppLayerParserResultElmt *e)
|
|
|
|
|
{
|
|
|
|
|
if (r->head == NULL) {
|
|
|
|
|
r->head = e;
|
|
|
|
|
r->tail = e;
|
|
|
|
@ -81,7 +88,9 @@ static void AlpAppendResultElmt(AppLayerParserResult *r, AppLayerParserResultElm
|
|
|
|
|
* \retval -1 error
|
|
|
|
|
* \retval 0 ok
|
|
|
|
|
*/
|
|
|
|
|
static int AlpStoreField(AppLayerParserResult *output, uint16_t idx, uint8_t *ptr, uint32_t len, uint8_t alloc) {
|
|
|
|
|
static int AlpStoreField(AppLayerParserResult *output, uint16_t idx,
|
|
|
|
|
uint8_t *ptr, uint32_t len, uint8_t alloc)
|
|
|
|
|
{
|
|
|
|
|
SCEnter();
|
|
|
|
|
|
|
|
|
|
AppLayerParserResultElmt *e = AlpGetResultElmt();
|
|
|
|
@ -105,7 +114,10 @@ static int AlpStoreField(AppLayerParserResult *output, uint16_t idx, uint8_t *pt
|
|
|
|
|
* \retval 0 Field parsing in progress.
|
|
|
|
|
* \retval -1 error
|
|
|
|
|
*/
|
|
|
|
|
int AlpParseFieldBySize(AppLayerParserResult *output, AppLayerParserState *pstate, uint16_t field_idx, uint32_t size, uint8_t *input, uint32_t input_len, uint32_t *offset) {
|
|
|
|
|
int AlpParseFieldBySize(AppLayerParserResult *output, AppLayerParserState *pstate,
|
|
|
|
|
uint16_t field_idx, uint32_t size, uint8_t *input,
|
|
|
|
|
uint32_t input_len, uint32_t *offset)
|
|
|
|
|
{
|
|
|
|
|
SCEnter();
|
|
|
|
|
|
|
|
|
|
if ((pstate->store_len + input_len) < size) {
|
|
|
|
@ -146,7 +158,8 @@ int AlpParseFieldBySize(AppLayerParserResult *output, AppLayerParserState *pstat
|
|
|
|
|
memcpy(pstate->store+pstate->store_len, input, diff);
|
|
|
|
|
pstate->store_len += diff;
|
|
|
|
|
|
|
|
|
|
int r = AlpStoreField(output, field_idx, pstate->store, pstate->store_len, /* alloc mem */1);
|
|
|
|
|
int r = AlpStoreField(output, field_idx, pstate->store,
|
|
|
|
|
pstate->store_len, /* alloc mem */1);
|
|
|
|
|
if (r == -1) {
|
|
|
|
|
SCReturnInt(-1);
|
|
|
|
|
}
|
|
|
|
@ -169,7 +182,9 @@ int AlpParseFieldBySize(AppLayerParserResult *output, AppLayerParserState *pstat
|
|
|
|
|
* \retval 0 Field parsing in progress.
|
|
|
|
|
* \retval -1 error
|
|
|
|
|
*/
|
|
|
|
|
int AlpParseFieldByEOF(AppLayerParserResult *output, AppLayerParserState *pstate, uint16_t field_idx, uint8_t *input, uint32_t input_len) {
|
|
|
|
|
int AlpParseFieldByEOF(AppLayerParserResult *output, AppLayerParserState *pstate,
|
|
|
|
|
uint16_t field_idx, uint8_t *input, uint32_t input_len)
|
|
|
|
|
{
|
|
|
|
|
SCEnter();
|
|
|
|
|
|
|
|
|
|
if (pstate->store_len == 0) {
|
|
|
|
@ -239,15 +254,19 @@ int AlpParseFieldByEOF(AppLayerParserResult *output, AppLayerParserState *pstate
|
|
|
|
|
* \retval 0 Field parsing in progress.
|
|
|
|
|
* \retval -1 error
|
|
|
|
|
*/
|
|
|
|
|
int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *pstate, uint16_t field_idx, const uint8_t *delim, uint8_t delim_len, uint8_t *input, uint32_t input_len, uint32_t *offset) {
|
|
|
|
|
int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *pstate,
|
|
|
|
|
uint16_t field_idx, const uint8_t *delim, uint8_t delim_len,
|
|
|
|
|
uint8_t *input, uint32_t input_len, uint32_t *offset)
|
|
|
|
|
{
|
|
|
|
|
SCEnter();
|
|
|
|
|
SCLogDebug("pstate->store_len %" PRIu32 ", delim_len %" PRIu32 "", pstate->store_len, delim_len);
|
|
|
|
|
SCLogDebug("pstate->store_len %" PRIu32 ", delim_len %" PRIu32 "",
|
|
|
|
|
pstate->store_len, delim_len);
|
|
|
|
|
|
|
|
|
|
if (pstate->store_len == 0) {
|
|
|
|
|
uint8_t *ptr = BinSearch(input, input_len, delim, delim_len);
|
|
|
|
|
if (ptr != NULL) {
|
|
|
|
|
uint32_t len = ptr - input;
|
|
|
|
|
//printf("ParseFieldByDelimiter: len %" PRIu32 "\n", len);
|
|
|
|
|
SCLogDebug(" len %" PRIu32 "", len);
|
|
|
|
|
|
|
|
|
|
int r = AlpStoreField(output, field_idx, input, len, 0);
|
|
|
|
|
if (r == -1) {
|
|
|
|
@ -257,11 +276,11 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
|
|
|
|
|
SCReturnInt(1);
|
|
|
|
|
} else {
|
|
|
|
|
if (pstate->flags & APP_LAYER_PARSER_EOF) {
|
|
|
|
|
//printf("ParseFieldByDelimiter: delim not found and EOF\n");
|
|
|
|
|
SCLogDebug("delim not found and EOF");
|
|
|
|
|
SCReturnInt(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//printf("ParseFieldByDelimiter: delim not found, continue\n");
|
|
|
|
|
SCLogDebug("delim not found, continue");
|
|
|
|
|
|
|
|
|
|
/* delimiter field not found, so store the result for the next run */
|
|
|
|
|
pstate->store = malloc(input_len);
|
|
|
|
@ -276,7 +295,8 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
|
|
|
|
|
uint8_t *ptr = BinSearch(input, input_len, delim, delim_len);
|
|
|
|
|
if (ptr != NULL) {
|
|
|
|
|
uint32_t len = ptr - input;
|
|
|
|
|
//printf("ParseFieldByDelimiter: len %" PRIu32 " + %" PRIu32 " = %" PRIu32 "\n", len, pstate->store_len, len + pstate->store_len);
|
|
|
|
|
SCLogDebug("len %" PRIu32 " + %" PRIu32 " = %" PRIu32 "", len,
|
|
|
|
|
pstate->store_len, len + pstate->store_len);
|
|
|
|
|
|
|
|
|
|
pstate->store = realloc(pstate->store, (len + pstate->store_len));
|
|
|
|
|
if (pstate->store == NULL) {
|
|
|
|
@ -286,7 +306,8 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
|
|
|
|
|
memcpy(pstate->store+pstate->store_len, input, len);
|
|
|
|
|
pstate->store_len += len;
|
|
|
|
|
|
|
|
|
|
int r = AlpStoreField(output, field_idx, pstate->store, pstate->store_len, 1);
|
|
|
|
|
int r = AlpStoreField(output, field_idx, pstate->store,
|
|
|
|
|
pstate->store_len, 1);
|
|
|
|
|
if (r == -1) {
|
|
|
|
|
SCReturnInt(-1);
|
|
|
|
|
}
|
|
|
|
@ -300,23 +321,27 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
|
|
|
|
|
/* if the input len is smaller than the delim len we search the
|
|
|
|
|
* pstate->store since we may match there. */
|
|
|
|
|
if (delim_len > input_len) {
|
|
|
|
|
/* delimiter field not found, so store the result for the next run */
|
|
|
|
|
pstate->store = realloc(pstate->store, (input_len + pstate->store_len));
|
|
|
|
|
/* delimiter field not found, so store the result for the
|
|
|
|
|
* next run */
|
|
|
|
|
pstate->store = realloc(pstate->store, (input_len +
|
|
|
|
|
pstate->store_len));
|
|
|
|
|
if (pstate->store == NULL) {
|
|
|
|
|
SCReturnInt(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(pstate->store+pstate->store_len, input, input_len);
|
|
|
|
|
pstate->store_len += input_len;
|
|
|
|
|
//printf("ParseFieldByDelimiter: input_len < delim_len, checking pstate->store\n");
|
|
|
|
|
SCLogDebug("input_len < delim_len, checking pstate->store");
|
|
|
|
|
|
|
|
|
|
if (pstate->store_len >= delim_len) {
|
|
|
|
|
ptr = BinSearch(pstate->store, pstate->store_len, delim, delim_len);
|
|
|
|
|
ptr = BinSearch(pstate->store, pstate->store_len, delim,
|
|
|
|
|
delim_len);
|
|
|
|
|
if (ptr != NULL) {
|
|
|
|
|
//printf("ParseFieldByDelimiter: now we found the delim\n");
|
|
|
|
|
SCLogDebug("now we found the delim");
|
|
|
|
|
|
|
|
|
|
uint32_t len = ptr - pstate->store;
|
|
|
|
|
int r = AlpStoreField(output, field_idx, pstate->store, len, 1);
|
|
|
|
|
int r = AlpStoreField(output, field_idx,
|
|
|
|
|
pstate->store, len, 1);
|
|
|
|
|
if (r == -1) {
|
|
|
|
|
SCReturnInt(-1);
|
|
|
|
|
}
|
|
|
|
@ -326,7 +351,7 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
|
|
|
|
|
|
|
|
|
|
(*offset) += (input_len);
|
|
|
|
|
|
|
|
|
|
//printf("ParseFieldByDelimiter: offset %" PRIu32 "\n", (*offset));
|
|
|
|
|
SCLogDebug("offset %" PRIu32 "", (*offset));
|
|
|
|
|
SCReturnInt(1);
|
|
|
|
|
}
|
|
|
|
|
goto free_and_return;
|
|
|
|
@ -334,7 +359,7 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
|
|
|
|
|
goto free_and_return;
|
|
|
|
|
}
|
|
|
|
|
free_and_return:
|
|
|
|
|
//printf("ParseFieldByDelimiter: not found and EOF, so free what we have so far.\n");
|
|
|
|
|
SCLogDebug("not found and EOF, so free what we have so far.");
|
|
|
|
|
free(pstate->store);
|
|
|
|
|
pstate->store = NULL;
|
|
|
|
|
pstate->store_len = 0;
|
|
|
|
@ -353,11 +378,11 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
|
|
|
|
|
/* if the input len is smaller than the delim len we search the
|
|
|
|
|
* pstate->store since we may match there. */
|
|
|
|
|
if (delim_len > input_len && delim_len <= pstate->store_len) {
|
|
|
|
|
//printf("ParseFieldByDelimiter: input_len < delim_len, checking pstate->store\n");
|
|
|
|
|
SCLogDebug("input_len < delim_len, checking pstate->store");
|
|
|
|
|
|
|
|
|
|
ptr = BinSearch(pstate->store, pstate->store_len, delim, delim_len);
|
|
|
|
|
if (ptr != NULL) {
|
|
|
|
|
//printf("ParseFieldByDelimiter: now we found the delim\n");
|
|
|
|
|
SCLogDebug("now we found the delim");
|
|
|
|
|
|
|
|
|
|
uint32_t len = ptr - pstate->store;
|
|
|
|
|
int r = AlpStoreField(output, field_idx, pstate->store, len, 1);
|
|
|
|
@ -369,7 +394,7 @@ int AlpParseFieldByDelimiter(AppLayerParserResult *output, AppLayerParserState *
|
|
|
|
|
|
|
|
|
|
(*offset) += (input_len);
|
|
|
|
|
|
|
|
|
|
//printf("ParseFieldByDelimiter: offset %" PRIu32 "\n", (*offset));
|
|
|
|
|
SCLogDebug("ffset %" PRIu32 "", (*offset));
|
|
|
|
|
SCReturnInt(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -391,11 +416,13 @@ static uint16_t al_max_parsers = 0; /* incremented for every registered parser *
|
|
|
|
|
*
|
|
|
|
|
* \retval Parser subsys id
|
|
|
|
|
*/
|
|
|
|
|
uint16_t AppLayerParserGetStorageId(void) {
|
|
|
|
|
uint16_t AppLayerParserGetStorageId(void)
|
|
|
|
|
{
|
|
|
|
|
return app_layer_sid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint16_t AppLayerGetProtoByName(const char *name) {
|
|
|
|
|
uint16_t AppLayerGetProtoByName(const char *name)
|
|
|
|
|
{
|
|
|
|
|
uint8_t u = 1;
|
|
|
|
|
SCLogDebug("looking for name %s", name);
|
|
|
|
|
|
|
|
|
@ -418,14 +445,20 @@ uint16_t AppLayerGetProtoByName(const char *name) {
|
|
|
|
|
/** \brief Description: register a parser.
|
|
|
|
|
*
|
|
|
|
|
* \param name full parser name, e.g. "http.request_line"
|
|
|
|
|
* \todo do we need recursive, so a "http" and a "request_line" where the engine knows it's actually "http.request_line"... same difference maybe.
|
|
|
|
|
* \todo do we need recursive, so a "http" and a "request_line" where the engine
|
|
|
|
|
* knows it's actually "http.request_line"... same difference maybe.
|
|
|
|
|
* \param AppLayerParser pointer to the parser function
|
|
|
|
|
* \param max_outputs max number of unique outputs the parser can generate
|
|
|
|
|
*
|
|
|
|
|
* \retval 0 on success
|
|
|
|
|
* \retval -1 on error
|
|
|
|
|
*/
|
|
|
|
|
int AppLayerRegisterParser(char *name, uint16_t proto, uint16_t parser_id, int (*AppLayerParser)(void *protocol_state, AppLayerParserState *parser_state, uint8_t *input, uint32_t input_len, AppLayerParserResult *output), char *dependency) {
|
|
|
|
|
int AppLayerRegisterParser(char *name, uint16_t proto, uint16_t parser_id,
|
|
|
|
|
int (*AppLayerParser)(void *protocol_state,
|
|
|
|
|
AppLayerParserState *parser_state, uint8_t *input,
|
|
|
|
|
uint32_t input_len, AppLayerParserResult *output),
|
|
|
|
|
char *dependency)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
al_max_parsers++;
|
|
|
|
|
|
|
|
|
@ -439,21 +472,28 @@ int AppLayerRegisterParser(char *name, uint16_t proto, uint16_t parser_id, int (
|
|
|
|
|
al_parser_table[al_max_parsers].parser_local_id = parser_id;
|
|
|
|
|
al_parser_table[al_max_parsers].AppLayerParser = AppLayerParser;
|
|
|
|
|
|
|
|
|
|
SCLogDebug("registered %p at proto %" PRIu32 ", al_proto_table idx %" PRIu32 ", storage_id %" PRIu32 ", parser_local_id %" PRIu32 "",
|
|
|
|
|
AppLayerParser, proto, al_max_parsers, al_proto_table[proto].storage_id, parser_id);
|
|
|
|
|
SCLogDebug("registered %p at proto %" PRIu32 ", al_proto_table idx "
|
|
|
|
|
"%" PRIu32 ", storage_id %" PRIu32 ", parser_local_id %" PRIu32 "",
|
|
|
|
|
AppLayerParser, proto, al_max_parsers,
|
|
|
|
|
al_proto_table[proto].storage_id, parser_id);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \brief Description: register a protocol parser.
|
|
|
|
|
*
|
|
|
|
|
* \param name full parser name, e.g. "http.request_line"
|
|
|
|
|
* \todo do we need recursive, so a "http" and a "request_line" where the engine knows it's actually "http.request_line"... same difference maybe.
|
|
|
|
|
* \todo do we need recursive, so a "http" and a "request_line" where the engine
|
|
|
|
|
* knows it's actually "http.request_line"... same difference maybe.
|
|
|
|
|
* \param AppLayerParser pointer to the parser function
|
|
|
|
|
*
|
|
|
|
|
* \retval 0 on success
|
|
|
|
|
* \retval -1 on error
|
|
|
|
|
*/
|
|
|
|
|
int AppLayerRegisterProto(char *name, uint8_t proto, uint8_t flags, int (*AppLayerParser)(void *protocol_state, AppLayerParserState *parser_state, uint8_t *input, uint32_t input_len, AppLayerParserResult *output)) {
|
|
|
|
|
int AppLayerRegisterProto(char *name, uint8_t proto, uint8_t flags,
|
|
|
|
|
int (*AppLayerParser)(void *protocol_state,
|
|
|
|
|
AppLayerParserState *parser_state, uint8_t *input,
|
|
|
|
|
uint32_t input_len, AppLayerParserResult *output))
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
al_max_parsers++;
|
|
|
|
|
|
|
|
|
@ -478,22 +518,28 @@ int AppLayerRegisterProto(char *name, uint8_t proto, uint8_t flags, int (*AppLay
|
|
|
|
|
al_proto_table[proto].storage_id = StreamL7RegisterModule();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SCLogDebug("registered %p at proto %" PRIu32 " flags %02X, al_proto_table idx %" PRIu32 ", storage_id %" PRIu32 "",
|
|
|
|
|
AppLayerParser, proto, flags, al_max_parsers, al_proto_table[proto].storage_id);
|
|
|
|
|
SCLogDebug("registered %p at proto %" PRIu32 " flags %02X, al_proto_table "
|
|
|
|
|
"idx %" PRIu32 ", storage_id %" PRIu32 " %s \n", AppLayerParser, proto,
|
|
|
|
|
flags, al_max_parsers, al_proto_table[proto].storage_id, name);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AppLayerRegisterStateFuncs(uint16_t proto, void *(*StateAlloc)(void), void (*StateFree)(void *)) {
|
|
|
|
|
void AppLayerRegisterStateFuncs(uint16_t proto, void *(*StateAlloc)(void),
|
|
|
|
|
void (*StateFree)(void *))
|
|
|
|
|
{
|
|
|
|
|
al_proto_table[proto].StateAlloc = StateAlloc;
|
|
|
|
|
al_proto_table[proto].StateFree = StateFree;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint16_t AlpGetStateIdx(uint16_t proto) {
|
|
|
|
|
uint16_t AlpGetStateIdx(uint16_t proto)
|
|
|
|
|
{
|
|
|
|
|
return al_proto_table[proto].storage_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AppLayerParserStateStore *AppLayerParserStateStoreAlloc(void) {
|
|
|
|
|
AppLayerParserStateStore *s = (AppLayerParserStateStore *)malloc(sizeof(AppLayerParserStateStore));
|
|
|
|
|
AppLayerParserStateStore *AppLayerParserStateStoreAlloc(void)
|
|
|
|
|
{
|
|
|
|
|
AppLayerParserStateStore *s = (AppLayerParserStateStore *)malloc
|
|
|
|
|
(sizeof(AppLayerParserStateStore));
|
|
|
|
|
if (s == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
@ -503,7 +549,8 @@ AppLayerParserStateStore *AppLayerParserStateStoreAlloc(void) {
|
|
|
|
|
|
|
|
|
|
/** \brief free a AppLayerParserStateStore structure
|
|
|
|
|
* \param s AppLayerParserStateStore structure to free */
|
|
|
|
|
void AppLayerParserStateStoreFree(AppLayerParserStateStore *s) {
|
|
|
|
|
void AppLayerParserStateStoreFree(AppLayerParserStateStore *s)
|
|
|
|
|
{
|
|
|
|
|
if (s->to_server.store != NULL)
|
|
|
|
|
free(s->to_server.store);
|
|
|
|
|
if (s->to_client.store != NULL)
|
|
|
|
@ -512,7 +559,8 @@ void AppLayerParserStateStoreFree(AppLayerParserStateStore *s) {
|
|
|
|
|
free(s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void AppLayerParserResultCleanup(AppLayerParserResult *result) {
|
|
|
|
|
static void AppLayerParserResultCleanup(AppLayerParserResult *result)
|
|
|
|
|
{
|
|
|
|
|
AppLayerParserResultElmt *e = result->head;
|
|
|
|
|
while (e != NULL) {
|
|
|
|
|
AppLayerParserResultElmt *next_e = e->next;
|
|
|
|
@ -527,27 +575,42 @@ static void AppLayerParserResultCleanup(AppLayerParserResult *result) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int AppLayerDoParse(void *app_layer_state, AppLayerParserState *parser_state, uint8_t *input, uint32_t input_len, uint16_t parser_idx, uint16_t proto) {
|
|
|
|
|
static int AppLayerDoParse(void *app_layer_state, AppLayerParserState *parser_state,
|
|
|
|
|
uint8_t *input, uint32_t input_len, uint16_t parser_idx,
|
|
|
|
|
uint16_t proto)
|
|
|
|
|
{
|
|
|
|
|
SCEnter();
|
|
|
|
|
int retval = 0;
|
|
|
|
|
AppLayerParserResult result = { NULL, NULL, 0 };
|
|
|
|
|
|
|
|
|
|
//printf("AppLayerDoParse: parser_idx %" PRIu32 "\n", parser_idx);
|
|
|
|
|
SCLogDebug("parser_idx %" PRIu32 "", parser_idx);
|
|
|
|
|
//PrintRawDataFp(stdout, input,input_len);
|
|
|
|
|
|
|
|
|
|
/* invoke the parser */
|
|
|
|
|
int r = al_parser_table[parser_idx].AppLayerParser(app_layer_state, parser_state, input, input_len, &result);
|
|
|
|
|
if (r < 0)
|
|
|
|
|
return -1;
|
|
|
|
|
int r = al_parser_table[parser_idx].AppLayerParser(app_layer_state,
|
|
|
|
|
parser_state, input, input_len, &result);
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
if (r == -1) {
|
|
|
|
|
AppLayerParserResultCleanup(&result);
|
|
|
|
|
SCReturnInt(-1);
|
|
|
|
|
} else {
|
|
|
|
|
BUG_ON(r); /* this is not supposed to happen!! */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* process the result elements */
|
|
|
|
|
AppLayerParserResultElmt *e = result.head;
|
|
|
|
|
for (; e != NULL; e = e->next) {
|
|
|
|
|
//printf("AppLayerParse: e %p e->name_idx %" PRIu32 ", e->data_ptr %p, e->data_len %" PRIu32 ", map_size %" PRIu32 "\n",
|
|
|
|
|
// e, e->name_idx, e->data_ptr, e->data_len, al_proto_table[proto].map_size);
|
|
|
|
|
SCLogDebug("e %p e->name_idx %" PRIu32 ", e->data_ptr %p, e->data_len "
|
|
|
|
|
"%" PRIu32 ", map_size %" PRIu32 "", e, e->name_idx,
|
|
|
|
|
e->data_ptr, e->data_len, al_proto_table[proto].map_size);
|
|
|
|
|
|
|
|
|
|
/* no parser defined for this field. */
|
|
|
|
|
if (e->name_idx >= al_proto_table[proto].map_size || al_proto_table[proto].map[e->name_idx] == NULL) {
|
|
|
|
|
//printf("AppLayerParse: no parser for proto %" PRIu32 ", parser_local_id %" PRIu32 "\n", proto, e->name_idx);
|
|
|
|
|
if (e->name_idx >= al_proto_table[proto].map_size ||
|
|
|
|
|
al_proto_table[proto].map[e->name_idx] == NULL)
|
|
|
|
|
{
|
|
|
|
|
SCLogDebug("no parser for proto %" PRIu32 ", parser_local_id "
|
|
|
|
|
"%" PRIu32 "", proto, e->name_idx);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -558,7 +621,8 @@ static int AppLayerDoParse(void *app_layer_state, AppLayerParserState *parser_st
|
|
|
|
|
parser_state->parse_field = 0;
|
|
|
|
|
parser_state->flags |= APP_LAYER_PARSER_EOF;
|
|
|
|
|
|
|
|
|
|
r = AppLayerDoParse(app_layer_state, parser_state, e->data_ptr, e->data_len, idx, proto);
|
|
|
|
|
r = AppLayerDoParse(app_layer_state, parser_state, e->data_ptr,
|
|
|
|
|
e->data_len, idx, proto);
|
|
|
|
|
|
|
|
|
|
/* restore */
|
|
|
|
|
parser_state->flags &= ~APP_LAYER_PARSER_EOF;
|
|
|
|
@ -566,13 +630,17 @@ static int AppLayerDoParse(void *app_layer_state, AppLayerParserState *parser_st
|
|
|
|
|
|
|
|
|
|
/* bail out on a serious error */
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
if (r == -1) {
|
|
|
|
|
retval = -1;
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
BUG_ON(r);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AppLayerParserResultCleanup(&result);
|
|
|
|
|
return retval;
|
|
|
|
|
SCReturnInt(retval);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -588,7 +656,9 @@ static int AppLayerDoParse(void *app_layer_state, AppLayerParserState *parser_st
|
|
|
|
|
* \retval -1 error
|
|
|
|
|
* \retval 0 ok
|
|
|
|
|
*/
|
|
|
|
|
int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_t input_len, char need_lock) {
|
|
|
|
|
int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input,
|
|
|
|
|
uint32_t input_len, char need_lock)
|
|
|
|
|
{
|
|
|
|
|
SCEnter();
|
|
|
|
|
|
|
|
|
|
uint16_t parser_idx = 0;
|
|
|
|
@ -596,12 +666,16 @@ int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_
|
|
|
|
|
|
|
|
|
|
TcpSession *ssn = f->protoctx;
|
|
|
|
|
if (ssn == NULL) {
|
|
|
|
|
printf("AppLayerParse: no session\n");
|
|
|
|
|
SCLogDebug("no TCP session");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get the parser state (if any) */
|
|
|
|
|
AppLayerParserStateStore *parser_state_store = (AppLayerParserStateStore *)ssn->aldata[app_layer_sid];
|
|
|
|
|
AppLayerParserStateStore *parser_state_store = NULL;
|
|
|
|
|
|
|
|
|
|
if (ssn->aldata != NULL) {
|
|
|
|
|
parser_state_store = (AppLayerParserStateStore *)
|
|
|
|
|
ssn->aldata[app_layer_sid];
|
|
|
|
|
if (parser_state_store == NULL) {
|
|
|
|
|
parser_state_store = AppLayerParserStateStoreAlloc();
|
|
|
|
|
if (parser_state_store == NULL)
|
|
|
|
@ -611,6 +685,10 @@ int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_
|
|
|
|
|
ssn->aldata[app_layer_sid] = (void *)parser_state_store;
|
|
|
|
|
if (need_lock == TRUE) mutex_unlock(&f->m);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
SCLogDebug("No App Layer Data");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AppLayerParserState *parser_state = NULL;
|
|
|
|
|
if (flags & STREAM_TOSERVER) {
|
|
|
|
@ -620,7 +698,8 @@ int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_
|
|
|
|
|
parser_state->cur_parser = parser_idx;
|
|
|
|
|
parser_state->flags |= APP_LAYER_PARSER_USE;
|
|
|
|
|
} else {
|
|
|
|
|
//printf("AppLayerParse: using parser %" PRIu32 " we stored before (to_server)\n", parser_state->cur_parser);
|
|
|
|
|
SCLogDebug("using parser %" PRIu32 " we stored before (to_server)",
|
|
|
|
|
parser_state->cur_parser);
|
|
|
|
|
parser_idx = parser_state->cur_parser;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
@ -630,13 +709,14 @@ int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_
|
|
|
|
|
parser_state->cur_parser = parser_idx;
|
|
|
|
|
parser_state->flags |= APP_LAYER_PARSER_USE;
|
|
|
|
|
} else {
|
|
|
|
|
//printf("AppLayerParse: using parser %" PRIu32 " we stored before (to_client)\n", parser_state->cur_parser);
|
|
|
|
|
SCLogDebug("using parser %" PRIu32 " we stored before (to_client)",
|
|
|
|
|
parser_state->cur_parser);
|
|
|
|
|
parser_idx = parser_state->cur_parser;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (parser_idx == 0 || parser_state->flags & APP_LAYER_PARSER_DONE) {
|
|
|
|
|
//printf("AppLayerParse: no parser for protocol %" PRIu32 "\n", proto);
|
|
|
|
|
SCLogDebug("no parser for protocol %" PRIu32 "", proto);
|
|
|
|
|
SCReturnInt(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -660,7 +740,8 @@ int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* invoke the recursive parser */
|
|
|
|
|
int r = AppLayerDoParse(app_layer_state, parser_state, input, input_len, parser_idx, proto);
|
|
|
|
|
int r = AppLayerDoParse(app_layer_state, parser_state, input, input_len,
|
|
|
|
|
parser_idx, proto);
|
|
|
|
|
if (r < 0)
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
@ -682,10 +763,44 @@ int AppLayerParse(Flow *f, uint8_t proto, uint8_t flags, uint8_t *input, uint32_
|
|
|
|
|
|
|
|
|
|
SCReturnInt(0);
|
|
|
|
|
error:
|
|
|
|
|
if (ssn != NULL) {
|
|
|
|
|
char src[16];
|
|
|
|
|
char dst[16];
|
|
|
|
|
char dst6[46];
|
|
|
|
|
char src6[46];
|
|
|
|
|
|
|
|
|
|
/* Clear the app layer protocol state memory and the given function also
|
|
|
|
|
* cleans the parser state memory */
|
|
|
|
|
AppLayerParserCleanupState(ssn);
|
|
|
|
|
|
|
|
|
|
/* Set the no reassembly flag for both the stream in this TcpSession */
|
|
|
|
|
StreamTcpSetSessionNoReassemblyFlag(ssn, flags & STREAM_TOCLIENT ? 1 : 0);
|
|
|
|
|
StreamTcpSetSessionNoReassemblyFlag(ssn, flags & STREAM_TOSERVER ? 1 : 0);
|
|
|
|
|
|
|
|
|
|
if (f->src.family == AF_INET) {
|
|
|
|
|
inet_ntop(AF_INET, &f->src.addr_data32[0], src,
|
|
|
|
|
sizeof (src));
|
|
|
|
|
inet_ntop(AF_INET, &f->dst.addr_data32[0], dst,
|
|
|
|
|
sizeof (dst));
|
|
|
|
|
} else {
|
|
|
|
|
inet_ntop(AF_INET6, &f->src.addr_data32[0], src6,
|
|
|
|
|
sizeof (src6));
|
|
|
|
|
inet_ntop(AF_INET6, &f->dst.addr_data32[0], dst6,
|
|
|
|
|
sizeof (dst6));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SCLogError(SC_ALPARSER_ERR, "Error occured in parsing \"%s\" app layer "
|
|
|
|
|
"protocol, using network protocol %"PRIu8", source IP "
|
|
|
|
|
"address %s, destination IP address %s, src port %"PRIu16" and "
|
|
|
|
|
"dst port %"PRIu16"", al_proto_table[ssn->alproto].name,
|
|
|
|
|
f->proto, src, dst, ntohs(f->sp), ntohs(f->dp));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SCReturnInt(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RegisterAppLayerParsers(void) {
|
|
|
|
|
void RegisterAppLayerParsers(void)
|
|
|
|
|
{
|
|
|
|
|
/** \todo move to general init function */
|
|
|
|
|
memset(&al_proto_table, 0, sizeof(al_proto_table));
|
|
|
|
|
memset(&al_parser_table, 0, sizeof(al_parser_table));
|
|
|
|
@ -697,22 +812,23 @@ void RegisterAppLayerParsers(void) {
|
|
|
|
|
al_result_pool = PoolInit(250,10,AlpResultElmtPoolAlloc,NULL,AlpResultElmtPoolFree);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AppLayerParserCleanupState(TcpSession *ssn) {
|
|
|
|
|
void AppLayerParserCleanupState(TcpSession *ssn)
|
|
|
|
|
{
|
|
|
|
|
if (ssn == NULL) {
|
|
|
|
|
//printf("AppLayerParserCleanupState: no ssn\n");
|
|
|
|
|
SCLogDebug("no ssn");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AppLayerProto *p = &al_proto_table[ssn->alproto];
|
|
|
|
|
if (p == NULL) {
|
|
|
|
|
//printf("AppLayerParserCleanupState: no parser state for %"PRIu16"\n", ssn->alproto);
|
|
|
|
|
SCLogDebug("no parser state for %"PRIu16"", ssn->alproto);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* free the parser protocol state */
|
|
|
|
|
if (p->StateFree != NULL) {
|
|
|
|
|
if (p->StateFree != NULL && ssn->aldata != NULL) {
|
|
|
|
|
if (ssn->aldata[p->storage_id] != NULL) {
|
|
|
|
|
//printf("AppLayerParserCleanupState: calling StateFree\n");
|
|
|
|
|
SCLogDebug("calling StateFree");
|
|
|
|
|
p->StateFree(ssn->aldata[p->storage_id]);
|
|
|
|
|
ssn->aldata[p->storage_id] = NULL;
|
|
|
|
|
}
|
|
|
|
@ -720,7 +836,7 @@ void AppLayerParserCleanupState(TcpSession *ssn) {
|
|
|
|
|
|
|
|
|
|
if (ssn->aldata != NULL) {
|
|
|
|
|
if (ssn->aldata[app_layer_sid] != NULL) {
|
|
|
|
|
//printf("AppLayerParserCleanupState: calling AppLayerParserStateStoreFree\n");
|
|
|
|
|
SCLogDebug("calling AppLayerParserStateStoreFree");
|
|
|
|
|
AppLayerParserStateStoreFree(ssn->aldata[app_layer_sid]);
|
|
|
|
|
ssn->aldata[app_layer_sid] = NULL;
|
|
|
|
|
}
|
|
|
|
@ -734,7 +850,8 @@ void AppLayerParserCleanupState(TcpSession *ssn) {
|
|
|
|
|
* and the global field parser id's.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void AppLayerParsersInitPostProcess(void) {
|
|
|
|
|
void AppLayerParsersInitPostProcess(void)
|
|
|
|
|
{
|
|
|
|
|
uint16_t u16 = 0;
|
|
|
|
|
|
|
|
|
|
/* build local->global mapping */
|
|
|
|
@ -743,10 +860,14 @@ void AppLayerParsersInitPostProcess(void) {
|
|
|
|
|
if (al_parser_table[u16].parser_local_id == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (al_parser_table[u16].parser_local_id > al_proto_table[al_parser_table[u16].proto].map_size)
|
|
|
|
|
al_proto_table[al_parser_table[u16].proto].map_size = al_parser_table[u16].parser_local_id;
|
|
|
|
|
|
|
|
|
|
//printf("AppLayerParsersInitPostProcess: map_size %" PRIu32 "\n", al_proto_table[al_parser_table[u16].proto].map_size);
|
|
|
|
|
if (al_parser_table[u16].parser_local_id >
|
|
|
|
|
al_proto_table[al_parser_table[u16].proto].map_size)
|
|
|
|
|
{
|
|
|
|
|
al_proto_table[al_parser_table[u16].proto].map_size =
|
|
|
|
|
al_parser_table[u16].parser_local_id;
|
|
|
|
|
}
|
|
|
|
|
SCLogDebug("map_size %" PRIu32 "", al_proto_table
|
|
|
|
|
[al_parser_table[u16].proto].map_size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* for each proto, alloc the map array */
|
|
|
|
@ -755,12 +876,15 @@ void AppLayerParsersInitPostProcess(void) {
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
al_proto_table[u16].map_size++;
|
|
|
|
|
al_proto_table[u16].map = (AppLayerLocalMap **)malloc(al_proto_table[u16].map_size * sizeof(AppLayerLocalMap *));
|
|
|
|
|
al_proto_table[u16].map = (AppLayerLocalMap **)malloc
|
|
|
|
|
(al_proto_table[u16].map_size *
|
|
|
|
|
sizeof(AppLayerLocalMap *));
|
|
|
|
|
if (al_proto_table[u16].map == NULL) {
|
|
|
|
|
printf("XXX memory error\n");
|
|
|
|
|
SCLogError(SC_ERR_MEM_ALLOC, "memory error");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
memset(al_proto_table[u16].map, 0, al_proto_table[u16].map_size * sizeof(AppLayerLocalMap *));
|
|
|
|
|
memset(al_proto_table[u16].map, 0, al_proto_table[u16].map_size *
|
|
|
|
|
sizeof(AppLayerLocalMap *));
|
|
|
|
|
|
|
|
|
|
uint16_t u = 0;
|
|
|
|
|
for (u = 1; u <= al_max_parsers; u++) {
|
|
|
|
@ -771,14 +895,13 @@ void AppLayerParsersInitPostProcess(void) {
|
|
|
|
|
if (al_parser_table[u].proto != u16)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
//printf("AppLayerParsersInitPostProcess: al_proto_table[%" PRIu32 "].map_size %" PRIu32 ", %p %p\n", u16, al_proto_table[u16].map_size, al_proto_table[u16].map[x], al_proto_table[u16].map);
|
|
|
|
|
uint16_t parser_local_id = al_parser_table[u].parser_local_id;
|
|
|
|
|
//printf("AppLayerParsersInitPostProcess: parser_local_id: %" PRIu32 "\n", parser_local_id);
|
|
|
|
|
SCLogDebug("parser_local_id: %" PRIu32 "", parser_local_id);
|
|
|
|
|
|
|
|
|
|
if (parser_local_id < al_proto_table[u16].map_size) {
|
|
|
|
|
al_proto_table[u16].map[parser_local_id] = malloc(sizeof(AppLayerLocalMap));
|
|
|
|
|
if (al_proto_table[u16].map[parser_local_id] == NULL) {
|
|
|
|
|
printf("XXX memory error\n");
|
|
|
|
|
SCLogError(SC_ERR_MEM_ALLOC, "XXX memory error");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -799,8 +922,121 @@ void AppLayerParsersInitPostProcess(void) {
|
|
|
|
|
if (al_proto_table[u16].map[x] == NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
//printf("AppLayerParsersInitPostProcess: al_proto_table[%" PRIu32 "].map[%" PRIu32 "]->parser_id: %" PRIu32 "\n", u16, x, al_proto_table[u16].map[x]->parser_id);
|
|
|
|
|
SCLogDebug("al_proto_table[%" PRIu32 "].map[%" PRIu32 "]->parser_id:"
|
|
|
|
|
" %" PRIu32 "\n", u16, x, al_proto_table[u16].map[x]->parser_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* UNITTESTS*/
|
|
|
|
|
#ifdef UNITTESTS
|
|
|
|
|
|
|
|
|
|
typedef struct TestState_ {
|
|
|
|
|
uint8_t test;
|
|
|
|
|
}TestState;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \brief Test parser function to test the memory deallocation of app layer
|
|
|
|
|
* parser of occurence of an error.
|
|
|
|
|
*/
|
|
|
|
|
static int TestProtocolParser(void *test_state, AppLayerParserState *pstate,
|
|
|
|
|
uint8_t *input, uint32_t input_len,
|
|
|
|
|
AppLayerParserResult *output)
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \brief Function to allocates the Test protocol state memory
|
|
|
|
|
*/
|
|
|
|
|
static void *TestProtocolStateAlloc(void)
|
|
|
|
|
{
|
|
|
|
|
void *s = malloc(sizeof(TestState));
|
|
|
|
|
if (s == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
memset(s, 0, sizeof(TestState));
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \brief Function to free the Test Protocol state memory
|
|
|
|
|
*/
|
|
|
|
|
static void TestProtocolStateFree(void *s)
|
|
|
|
|
{
|
|
|
|
|
free(s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test Test the deallocation of app layer parser memory on occurance of
|
|
|
|
|
* error in the parsing process.
|
|
|
|
|
*/
|
|
|
|
|
static int AppLayerParserTest01 (void)
|
|
|
|
|
{
|
|
|
|
|
int result = 1;
|
|
|
|
|
Flow f;
|
|
|
|
|
uint8_t testbuf[] = { 0x11 };
|
|
|
|
|
uint32_t testlen = sizeof(testbuf);
|
|
|
|
|
TcpSession ssn;
|
|
|
|
|
struct in_addr addr;
|
|
|
|
|
struct in_addr addr1;
|
|
|
|
|
Address src;
|
|
|
|
|
Address dst;
|
|
|
|
|
|
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
memset(&src, 0, sizeof(src));
|
|
|
|
|
memset(&dst, 0, sizeof(dst));
|
|
|
|
|
|
|
|
|
|
/* Register the Test protocol state and parser functions */
|
|
|
|
|
AppLayerRegisterProto("test", ALPROTO_TEST, STREAM_TOSERVER,
|
|
|
|
|
TestProtocolParser);
|
|
|
|
|
AppLayerRegisterStateFuncs(ALPROTO_TEST, TestProtocolStateAlloc,
|
|
|
|
|
TestProtocolStateFree);
|
|
|
|
|
|
|
|
|
|
ssn.alproto = ALPROTO_TEST;
|
|
|
|
|
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
|
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
|
|
|
|
|
|
inet_pton(AF_INET, "1.2.3.4", &addr.s_addr);
|
|
|
|
|
src.family = AF_INET;
|
|
|
|
|
src.addr_data32[0] = addr.s_addr;
|
|
|
|
|
inet_pton(AF_INET, "4.3.2.1", &addr1.s_addr);
|
|
|
|
|
dst.family = AF_INET;
|
|
|
|
|
dst.addr_data32[0] = addr1.s_addr;
|
|
|
|
|
f.src = src;
|
|
|
|
|
f.dst = dst;
|
|
|
|
|
f.sp = htons(20);
|
|
|
|
|
f.dp = htons(40);
|
|
|
|
|
f.proto = IPPROTO_TCP;
|
|
|
|
|
|
|
|
|
|
int r = AppLayerParse(&f, ALPROTO_TEST, STREAM_TOSERVER|STREAM_EOF, testbuf,
|
|
|
|
|
testlen, FALSE);
|
|
|
|
|
if (r != -1) {
|
|
|
|
|
printf("returned %" PRId32 ", expected -1: \n", r);
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(ssn.flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY) ||
|
|
|
|
|
!(ssn.flags & STREAMTCP_FLAG_NOCLIENT_REASSEMBLY))
|
|
|
|
|
{
|
|
|
|
|
printf("flags should be set, but they are not !\n");
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ssn.aldata != NULL) {
|
|
|
|
|
printf("App Layer state has not been cleared\n");
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
end:
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* UNITESTS */
|
|
|
|
|
|
|
|
|
|
void AppLayerParserRegisterTests(void)
|
|
|
|
|
{
|
|
|
|
|
#ifdef UNITTESTS
|
|
|
|
|
UtRegisterTest("AppLayerParserTest01", AppLayerParserTest01, 1);
|
|
|
|
|
#endif /* UNITTESTS */
|
|
|
|
|
}
|
|
|
|
|