app-layer-event: refactor

Move app layer event handling into app-layer-event.[ch].
Convert 'Set' macro's to functions.
Get rid of duplication in Set and SetRaw. Set now calls SetRaw.
Fix potentential int overflow condition in the event storage.
Update callers.
pull/795/head
Victor Julien 12 years ago
parent 4ce53753bc
commit 347c0df9c4

@ -20,6 +20,7 @@ app-layer-detect-proto.c app-layer-detect-proto.h \
app-layer-dns-common.c app-layer-dns-common.h \
app-layer-dns-tcp.c app-layer-dns-tcp.h \
app-layer-dns-udp.c app-layer-dns-udp.h \
app-layer-events.c app-layer-events.h \
app-layer-ftp.c app-layer-ftp.h \
app-layer-htp-body.c app-layer-htp-body.h \
app-layer-htp.c app-layer-htp.h \

@ -196,7 +196,7 @@ int DNSGetAlstateProgressCompletionStatus(uint8_t direction) {
void DNSSetEvent(DNSState *s, uint8_t e) {
if (s && s->curr) {
SCLogDebug("s->curr->decoder_events %p", s->curr->decoder_events);
AppLayerDecoderEventsSetEventRaw(s->curr->decoder_events, e);
AppLayerDecoderEventsSetEventRaw(&s->curr->decoder_events, e);
SCLogDebug("s->curr->decoder_events %p", s->curr->decoder_events);
s->events++;
} else {
@ -251,7 +251,7 @@ static void DNSTransactionFree(DNSTransaction *tx, DNSState *state) {
SCFree(a);
}
AppLayerDecoderEventsFreeEvents(tx->decoder_events);
AppLayerDecoderEventsFreeEvents(&tx->decoder_events);
DNSDecrMemcap(sizeof(DNSTransaction), state);
SCFree(tx);

@ -0,0 +1,137 @@
/* Copyright (C) 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 Victor Julien <victor@inliniac.net>
* \author Anoop Saldanha <anoopsaldanha@gmail.com>
*/
#include "suricata-common.h"
#include "decode.h"
#include "flow.h"
#include "app-layer-events.h"
#include "app-layer-parser.h"
#include "util-enum.h"
/* events raised during protocol detection are stored in the
* packets storage, not in the flow. */
SCEnumCharMap app_layer_event_pkt_table[ ] = {
{ "APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS",
APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS },
{ "APPLAYER_WRONG_DIRECTION_FIRST_DATA",
APPLAYER_WRONG_DIRECTION_FIRST_DATA },
{ "APPLAYER_DETECT_PROTOCOL_ONLY_ONE_DIRECTION",
APPLAYER_DETECT_PROTOCOL_ONLY_ONE_DIRECTION },
{ "APPLAYER_PROTO_DETECTION_SKIPPED",
APPLAYER_PROTO_DETECTION_SKIPPED },
{ NULL,
-1 },
};
int AppLayerGetPktEventInfo(const char *event_name, int *event_id)
{
*event_id = SCMapEnumNameToValue(event_name, app_layer_event_pkt_table);
if (*event_id == -1) {
SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%s\" not present in "
"app-layer-event's packet event table.", event_name);
/* this should be treated as fatal */
return -1;
}
return 0;
}
#define DECODER_EVENTS_BUFFER_STEPS 8
/**
* \brief Set an app layer decoder event.
*
* \param sevents Pointer to a AppLayerDecoderEvents pointer. If *sevents is NULL
* memory will be allocated.
* \param event The event to be stored.
*/
void AppLayerDecoderEventsSetEventRaw(AppLayerDecoderEvents **sevents, uint8_t event)
{
if (*sevents == NULL) {
AppLayerDecoderEvents *new_devents = SCMalloc(sizeof(AppLayerDecoderEvents));
if (new_devents == NULL)
return;
memset(new_devents, 0, sizeof(AppLayerDecoderEvents));
*sevents = new_devents;
}
if ((*sevents)->cnt == UCHAR_MAX) {
/* we're full */
return;
}
if ((*sevents)->cnt == (*sevents)->events_buffer_size) {
int steps = DECODER_EVENTS_BUFFER_STEPS;
if (UCHAR_MAX - (*sevents)->cnt < steps)
steps = UCHAR_MAX - (*sevents)->cnt < steps;
void *ptr = SCRealloc((*sevents)->events,
((*sevents)->cnt + steps) * sizeof(uint8_t));
if (ptr == NULL) {
/* couldn't grow buffer, but no reason to free old
* so we keep the events that may already be here */
return;
}
(*sevents)->events = ptr;
(*sevents)->events_buffer_size += steps;
}
(*sevents)->events[(*sevents)->cnt++] = event;
}
/**
* \brief Set an app layer decoder event.
*
* \param f Pointer to a flow containing DecoderEvents pointer head. If
* the head points to a DecoderEvents instance, a
* new instance would be created and the pointer head would
* would be updated with this new instance
* \param event The event to be stored.
*/
void AppLayerDecoderEventsSetEvent(Flow *f, uint8_t event)
{
AppLayerDecoderEvents *events = AppLayerParserGetDecoderEvents(f->alparser);
AppLayerDecoderEvents *new = events;
AppLayerDecoderEventsSetEventRaw(&events, event);
if (events != new)
AppLayerParserSetDecoderEvents(f->alparser, events);
}
void AppLayerDecoderEventsResetEvents(AppLayerDecoderEvents *events)
{
if (events != NULL)
events->cnt = 0;
}
void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events)
{
if (events && *events != NULL) {
if ((*events)->events != NULL)
SCFree((*events)->events);
SCFree(*events);
*events = NULL;
}
}

@ -0,0 +1,83 @@
/* Copyright (C) 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 Victor Julien <victor@inliniac.net>
* \author Anoop Saldanha <anoopsaldanha@gmail.com>
*/
#ifndef __APP_LAYER_EVENTS_H__
#define __APP_LAYER_EVENTS_H__
/* contains fwd declaration of AppLayerDecoderEvents_ */
#include "decode.h"
/**
* \brief Data structure to store app layer decoder events.
*/
struct AppLayerDecoderEvents_ {
/* array of events */
uint8_t *events;
/* number of events in the above buffer */
uint8_t cnt;
/* current event buffer size */
uint8_t events_buffer_size;
};
/* app layer pkt level events */
enum {
APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS,
APPLAYER_WRONG_DIRECTION_FIRST_DATA,
APPLAYER_DETECT_PROTOCOL_ONLY_ONE_DIRECTION,
APPLAYER_PROTO_DETECTION_SKIPPED,
};
/* the event types for app events */
typedef enum AppLayerEventType_ {
APP_LAYER_EVENT_TYPE_GENERAL = 1,
APP_LAYER_EVENT_TYPE_TRANSACTION,
APP_LAYER_EVENT_TYPE_PACKET,
} AppLayerEventType;
int AppLayerGetPktEventInfo(const char *event_name, int *event_id);
void AppLayerDecoderEventsSetEventRaw(AppLayerDecoderEvents **sevents, uint8_t event);
void AppLayerDecoderEventsSetEvent(Flow *f, uint8_t event);
static inline int AppLayerDecoderEventsIsEventSet(AppLayerDecoderEvents *devents,
uint8_t event)
{
if (devents == NULL)
return 0;
int i;
int cnt = devents->cnt;
for (i = 0; i < cnt; i++) {
if (devents->events[i] == event)
return 1;
}
return 0;
}
void AppLayerDecoderEventsResetEvents(AppLayerDecoderEvents *events);
void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events);
#endif /* __APP_LAYER_EVENTS_H__ */

@ -158,7 +158,7 @@ void AppLayerParserStateFree(AppLayerParserState *pstate)
SCEnter();
if (pstate->decoder_events != NULL)
AppLayerDecoderEventsFreeEvents(pstate->decoder_events);
AppLayerDecoderEventsFreeEvents(&pstate->decoder_events);
SCFree(pstate);
SCReturn;

@ -25,7 +25,7 @@
#ifndef __APP_LAYER_PARSER_H__
#define __APP_LAYER_PARSER_H__
#include "decode-events.h"
#include "app-layer-events.h"
#include "util-file.h"
#define APP_LAYER_PARSER_EOF 0x01

@ -156,7 +156,7 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
if (*alproto != ALPROTO_UNKNOWN) {
if (*alproto_otherdir != ALPROTO_UNKNOWN && *alproto_otherdir != *alproto) {
AppLayerDecoderEventsSetEventRaw(p->app_layer_events,
AppLayerDecoderEventsSetEventRaw(&p->app_layer_events,
APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS);
/* it indicates some data has already been sent to the parser */
if (ssn->data_first_seen_dir == APP_LAYER_DATA_ALREADY_SENT_TO_APP_LAYER) {
@ -254,7 +254,7 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
first_data_dir = AppLayerParserGetFirstDataDir(f->proto, *alproto);
if (first_data_dir && !(first_data_dir & ssn->data_first_seen_dir)) {
AppLayerDecoderEventsSetEventRaw(p->app_layer_events,
AppLayerDecoderEventsSetEventRaw(&p->app_layer_events,
APPLAYER_WRONG_DIRECTION_FIRST_DATA);
FlowSetSessionNoApplayerInspectionFlag(f);
StreamTcpSetStreamFlagAppProtoDetectionCompleted(&ssn->server);
@ -324,7 +324,7 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
data + data_al_so_far, data_len - data_al_so_far);
PACKET_PROFILING_APP_END(app_tctx, *alproto_otherdir);
if (FLOW_IS_PM_DONE(f, flags) && FLOW_IS_PP_DONE(f, flags)) {
AppLayerDecoderEventsSetEventRaw(p->app_layer_events,
AppLayerDecoderEventsSetEventRaw(&p->app_layer_events,
APPLAYER_DETECT_PROTOCOL_ONLY_ONE_DIRECTION);
StreamTcpSetStreamFlagAppProtoDetectionCompleted(stream);
f->data_al_so_far[dir] = 0;

@ -22,30 +22,6 @@
*/
#include "suricata-common.h"
#include "util-enum.h"
SCEnumCharMap app_layer_event_pkt_table[ ] = {
{ "APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS",
APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS },
{ "APPLAYER_WRONG_DIRECTION_FIRST_DATA",
APPLAYER_WRONG_DIRECTION_FIRST_DATA },
{ "APPLAYER_DETECT_PROTOCOL_ONLY_ONE_DIRECTION",
APPLAYER_DETECT_PROTOCOL_ONLY_ONE_DIRECTION },
{ "APPLAYER_PROTO_DETECTION_SKIPPED",
APPLAYER_PROTO_DETECTION_SKIPPED },
{ NULL,
-1 },
};
/* code moved to app-layer-events */
int AppLayerGetPktEventInfo(const char *event_name, int *event_id)
{
*event_id = SCMapEnumNameToValue(event_name, app_layer_event_pkt_table);
if (*event_id == -1) {
SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%s\" not present in "
"app-layer-event's packet event table.", event_name);
/* this should be treated as fatal */
return -1;
}
return 0;
}

@ -224,141 +224,4 @@ enum {
DECODE_EVENT_MAX,
};
/* app layer pkt level events */
enum {
APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS,
APPLAYER_WRONG_DIRECTION_FIRST_DATA,
APPLAYER_DETECT_PROTOCOL_ONLY_ONE_DIRECTION,
APPLAYER_PROTO_DETECTION_SKIPPED,
};
#define DECODER_EVENTS_BUFFER_STEPS 5
/* the event types for app events */
typedef enum AppLayerEventType_ {
APP_LAYER_EVENT_TYPE_GENERAL = 1,
APP_LAYER_EVENT_TYPE_TRANSACTION,
APP_LAYER_EVENT_TYPE_PACKET,
} AppLayerEventType;
/**
* \brief Data structure to store app layer decoder events.
*/
typedef struct AppLayerDecoderEvents_ {
/* array of events */
uint8_t *events;
/* number of events in the above buffer */
uint8_t cnt;
/* current event buffer size */
uint8_t events_buffer_size;
} AppLayerDecoderEvents;
/**
* \brief Set an app layer decoder event.
*
* \param sevents Pointer to a DecoderEvents pointer head. If
* the head points to a DecoderEvents instance, a
* new instance would be created and the pointer head would
* would be updated with this new instance
* \param event The event to be stored.
*/
#define AppLayerDecoderEventsSetEventRaw(sevents, event) \
do { \
AppLayerDecoderEvents *devents = (sevents); \
if (devents == NULL) { \
AppLayerDecoderEvents *new_devents = \
SCMalloc(sizeof(AppLayerDecoderEvents)); \
if (new_devents == NULL) \
break; \
memset(new_devents, 0, sizeof(AppLayerDecoderEvents)); \
(sevents) = devents = new_devents; \
} \
if (devents->cnt == devents->events_buffer_size) { \
devents->events = SCRealloc(devents->events, \
(devents->cnt + \
DECODER_EVENTS_BUFFER_STEPS) * \
sizeof(uint8_t)); \
if (devents->events == NULL) { \
devents->events_buffer_size = 0; \
devents->cnt = 0; \
(sevents) = NULL; \
break; \
} \
devents->events_buffer_size += DECODER_EVENTS_BUFFER_STEPS; \
} \
devents->events[devents->cnt++] = (event); \
} while (0)
/**
* \brief Set an app layer decoder event.
*
* \param devents_head Pointer to a DecoderEvents pointer head. If
* the head points to a DecoderEvents instance, a
* new instance would be created and the pointer head would
* would be updated with this new instance
* \param event The event to be stored.
*/
#define AppLayerDecoderEventsSetEvent(f, event) \
do { \
AppLayerDecoderEvents *devents = \
AppLayerParserGetDecoderEvents((f)->alparser); \
if (devents == NULL) { \
AppLayerDecoderEvents *new_devents = \
SCMalloc(sizeof(AppLayerDecoderEvents)); \
if (new_devents == NULL) \
break; \
memset(new_devents, 0, sizeof(AppLayerDecoderEvents)); \
AppLayerParserSetDecoderEvents((f)->alparser, new_devents); \
devents = new_devents; \
} \
if (devents->cnt == devents->events_buffer_size) { \
devents->events = SCRealloc(devents->events, \
(devents->cnt + \
DECODER_EVENTS_BUFFER_STEPS) * \
sizeof(uint8_t)); \
if (devents->events == NULL) { \
devents->events_buffer_size = 0; \
devents->cnt = 0; \
break; \
} \
devents->events_buffer_size += DECODER_EVENTS_BUFFER_STEPS; \
} \
devents->events[devents->cnt++] = (event); \
SCLogDebug("setting app-layer-event %u", (event)); \
} while (0)
static inline int AppLayerDecoderEventsIsEventSet(AppLayerDecoderEvents *devents,
uint8_t event)
{
if (devents == NULL)
return 0;
int i;
int cnt = devents->cnt;
for (i = 0; i < cnt; i++) {
if (devents->events[i] == event)
return 1;
}
return 0;
}
#define AppLayerDecoderEventsResetEvents(devents) \
do { \
if ((devents) != NULL) { \
(devents)->cnt = 0; \
} \
} while (0)
#define AppLayerDecoderEventsFreeEvents(devents) \
do { \
if ((devents) != NULL) { \
if ((devents)->events != NULL) \
SCFree((devents)->events); \
} \
SCFree((devents)); \
} while (0)
int AppLayerGetPktEventInfo(const char *event_name, int *event_id);
#endif /* __DECODE_EVENTS_H__ */

@ -83,10 +83,15 @@ enum PktSrcEnum {
#include "app-layer-protos.h"
/* forward declarations */
struct DetectionEngineThreadCtx_;
typedef struct AppLayerThreadCtx_ AppLayerThreadCtx;
/* forward declaration */
struct DetectionEngineThreadCtx_;
/* declare these here as they are called from the
* PACKET_RECYCLE and PACKET_CLEANUP macro's. */
typedef struct AppLayerDecoderEvents_ AppLayerDecoderEvents;
void AppLayerDecoderEventsResetEvents(AppLayerDecoderEvents *events);
void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events);
/* Address */
typedef struct Address_ {
@ -712,7 +717,7 @@ typedef struct DecodeThreadVars_
PktVarFree((p)->pktvar); \
} \
SCMutexDestroy(&(p)->tunnel_mutex); \
AppLayerDecoderEventsFreeEvents((p)->app_layer_events); \
AppLayerDecoderEventsFreeEvents(&(p)->app_layer_events); \
} while (0)

@ -55,6 +55,7 @@
#include "util-debug.h"
#include "app-layer-protos.h"
#include "app-layer.h"
#include "app-layer-events.h"
#include "detect-engine-state.h"
@ -1720,7 +1721,7 @@ int StreamTcpReassembleHandleSegmentHandleData(ThreadVars *tv, TcpReassemblyThre
if (stream->seg_list == NULL &&
stream->flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_SKIPPED) {
AppLayerDecoderEventsSetEventRaw(p->app_layer_events,
AppLayerDecoderEventsSetEventRaw(&p->app_layer_events,
APPLAYER_PROTO_DETECTION_SKIPPED);
}

Loading…
Cancel
Save