diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 46ee54ea52..1e3c180e41 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -99,6 +99,67 @@ FileContainer *AppLayerGetFilesFromFlow(Flow *f, uint8_t direction) { } } +/** \brief Get the decoder events from the flow + * \param f flow pointer to a LOCKED flow + * \param tx_id transaction id + * \retval files void pointer to the state + * \retval NULL in case we have no state */ +AppLayerDecoderEvents *AppLayerGetEventsFromFlowByTx(Flow *f, uint64_t tx_id) { + SCEnter(); + + DEBUG_ASSERT_FLOW_LOCKED(f); + + uint16_t alproto = f->alproto; + if (alproto == ALPROTO_UNKNOWN) + SCReturnPtr(NULL, "AppLayerDecoderEvents"); + + if (al_proto_table[alproto].StateGetEvents != NULL) { + AppLayerDecoderEvents *ptr = al_proto_table[alproto].StateGetEvents(AppLayerGetProtoStateFromFlow(f), tx_id); + SCReturnPtr(ptr, "AppLayerDecoderEvents"); + } else { + SCReturnPtr(NULL, "AppLayerDecoderEvents"); + } +} + +/** \brief check if we have decoder events */ +int AppLayerFlowHasDecoderEvents(Flow *f, uint8_t flags) { + AppLayerDecoderEvents *decoder_events; + uint64_t tx_id, max_id; + + DEBUG_ASSERT_FLOW_LOCKED(f); + + if (f->alproto <= ALPROTO_UNKNOWN || f->alproto >= ALPROTO_MAX) + return 0; + + if (AppLayerProtoIsTxEventAware(f->alproto)) { + tx_id = AppLayerTransactionGetInspectId(f, flags); + max_id = AppLayerGetTxCnt(f->alproto, f->alstate); + + for ( ; tx_id < max_id; tx_id++) { + decoder_events = AppLayerGetEventsFromFlowByTx(f, tx_id); + if (decoder_events && decoder_events->cnt) + return 1; + } + } + + decoder_events = AppLayerGetDecoderEventsForFlow(f); + if (decoder_events && decoder_events->cnt) + return 1; + + return 0; +} + +/** \brief Return true if alproto uses per TX events + * \param alproto proto to check + */ +int AppLayerProtoIsTxEventAware(uint16_t alproto) { + if (alproto > ALPROTO_UNKNOWN && alproto < ALPROTO_MAX && + al_proto_table[alproto].StateGetEvents != NULL) + return 1; + + return 0; +} + /** \brief Alloc a AppLayerParserResultElmt func for the pool */ static void *AlpResultElmtPoolAlloc() { @@ -735,6 +796,12 @@ void AppLayerRegisterGetAlstateProgressCompletionStatus(uint16_t alproto, StateGetAlstateProgressCompletionStatus; } +void AppLayerRegisterGetEventsFunc(uint16_t proto, + AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t)) +{ + al_proto_table[proto].StateGetEvents = StateGetEvents; +} + /** \brief Indicate to the app layer parser that a logger is active * for this protocol. */ diff --git a/src/app-layer-parser.h b/src/app-layer-parser.h index 3670e046fe..81c53c7304 100644 --- a/src/app-layer-parser.h +++ b/src/app-layer-parser.h @@ -58,6 +58,7 @@ typedef struct AppLayerProto_ { /** truncate state after a gap/depth event */ void (*Truncate)(void *, uint8_t); FileContainer *(*StateGetFiles)(void *, uint8_t); + AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t); int (*StateGetAlstateProgress)(void *alstate, uint8_t direction); uint64_t (*StateGetTxCnt)(void *alstate); @@ -258,6 +259,8 @@ void AppLayerRegisterLocalStorageFunc(uint16_t proto, void *AppLayerGetProtocolParserLocalStorage(uint16_t); void AppLayerRegisterGetFilesFunc(uint16_t proto, FileContainer *(*StateGetFile)(void *, uint8_t)); +void AppLayerRegisterGetEventsFunc(uint16_t proto, + AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t)); void AppLayerRegisterLogger(uint16_t proto); uint16_t AppLayerGetProtoByName(const char *); const char *AppLayerGetProtoString(int proto); @@ -332,6 +335,9 @@ void AppLayerPrintProbingParsers(AppLayerProbingParser *); void AppLayerListSupportedProtocols(void); AppLayerDecoderEvents *AppLayerGetDecoderEventsForFlow(Flow *); +AppLayerDecoderEvents *AppLayerGetEventsFromFlowByTx(Flow *f, uint64_t tx_id); +int AppLayerProtoIsTxEventAware(uint16_t alproto); +int AppLayerFlowHasDecoderEvents(Flow *f, uint8_t flags); /***** Alproto param retrieval ******/ diff --git a/src/decode-events.h b/src/decode-events.h index 6c7f4df7c4..93cf8bc605 100644 --- a/src/decode-events.h +++ b/src/decode-events.h @@ -310,6 +310,42 @@ static inline int AppLayerDecoderEventsIsEventSet(int module_id, #endif /* #if 0 */ +/** + * \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. * diff --git a/src/detect-app-layer-event.c b/src/detect-app-layer-event.c index b20417ccb6..2b6290e970 100644 --- a/src/detect-app-layer-event.c +++ b/src/detect-app-layer-event.c @@ -73,16 +73,36 @@ int DetectAppLayerEventMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, SigMatch *m) { SCEnter(); + AppLayerDecoderEvents *decoder_events = NULL; int r = 0; - + uint64_t tx_id = 0, max_id; DetectAppLayerEventData *aled = (DetectAppLayerEventData *)m->ctx; FLOWLOCK_RDLOCK(f); - AppLayerDecoderEvents *decoder_events = AppLayerGetDecoderEventsForFlow(f); - if (decoder_events != NULL && - AppLayerDecoderEventsIsEventSet(decoder_events, aled->event_id)) { - r = 1; + /* inspect TX events first if we need to */ + if (AppLayerProtoIsTxEventAware(f->alproto)) { + SCLogDebug("proto is AppLayerProtoIsTxEventAware true"); + + tx_id = AppLayerTransactionGetInspectId(f, flags); + max_id = AppLayerGetTxCnt(f->alproto, f->alstate); + + for ( ; tx_id < max_id; tx_id++) { + decoder_events = AppLayerGetEventsFromFlowByTx(f, tx_id); + if (decoder_events != NULL && + AppLayerDecoderEventsIsEventSet(decoder_events, aled->event_id)) { + r = 1; + break; + } + } + } + + if (r == 0) { + decoder_events = AppLayerGetDecoderEventsForFlow(f); + if (decoder_events != NULL && + AppLayerDecoderEventsIsEventSet(decoder_events, aled->event_id)) { + r = 1; + } } FLOWLOCK_UNLOCK(f); diff --git a/src/detect.c b/src/detect.c index cd1e23d8e3..784d0015d6 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1258,10 +1258,9 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh SigMatch *sm = NULL; uint16_t alversion = 0; int reset_de_state = 0; - AppLayerDecoderEvents *app_decoder_events = NULL; - int app_decoder_events_cnt = 0; int alerts = 0; int i; + int app_decoder_events = 0; SCEnter(); @@ -1346,9 +1345,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh SCLogDebug("packet doesn't have established flag set (proto %d)", p->proto); } - app_decoder_events = AppLayerGetDecoderEventsForFlow(p->flow); - if (app_decoder_events != NULL) - app_decoder_events_cnt = app_decoder_events->cnt; + app_decoder_events = AppLayerFlowHasDecoderEvents(p->flow, flags); } FLOWLOCK_UNLOCK(p->flow); @@ -1447,7 +1444,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh /* create our prefilter mask */ SignatureMask mask = 0; - PacketCreateMask(p, &mask, alproto, alstate, smsg, app_decoder_events_cnt); + PacketCreateMask(p, &mask, alproto, alstate, smsg, app_decoder_events); /* run the mpm for each type */ PACKET_PROFILING_DETECT_START(p, PROF_DETECT_MPM); @@ -2184,7 +2181,7 @@ deonly: */ static void PacketCreateMask(Packet *p, SignatureMask *mask, uint16_t alproto, void *alstate, StreamMsg *smsg, - int app_decoder_events_cnt) + int app_decoder_events) { if (!(p->flags & PKT_NOPAYLOAD_INSPECTION) && (p->payload_len > 0 || smsg != NULL)) { SCLogDebug("packet has payload"); @@ -2194,7 +2191,7 @@ PacketCreateMask(Packet *p, SignatureMask *mask, uint16_t alproto, void *alstate (*mask) |= SIG_MASK_REQUIRE_NO_PAYLOAD; } - if (p->events.cnt > 0 || app_decoder_events_cnt > 0) { + if (p->events.cnt > 0 || app_decoder_events != 0) { SCLogDebug("packet/flow has events set"); (*mask) |= SIG_MASK_REQUIRE_ENGINE_EVENT; }