App layer: add 'StateHasEvents' API call

Per TX decoder events resulted in significant overhead to the
detection engine, as it walked all TX' all the time to check
if decoder events were available.

This commit introduces a new API call StateHasEvents, which speeds
up this process, at the expense of keeping a counter in the state.

Implement this for DNS as well.
pull/418/merge
Victor Julien 13 years ago
parent cd7b4fac40
commit e8ad876b48

@ -45,6 +45,11 @@ void DNSAppLayerDecoderEventsRegister(int alproto) {
AppLayerDecoderEvents *DNSGetEvents(void *state, uint64_t id) {
DNSState *dns_state = (DNSState *)state;
DNSTransaction *tx;
if (dns_state->curr && dns_state->curr->tx_num == (id + 1)) {
return dns_state->curr->decoder_events;
}
TAILQ_FOREACH(tx, &dns_state->tx_list, next) {
if (tx->tx_num == (id+1))
return tx->decoder_events;
@ -52,6 +57,11 @@ AppLayerDecoderEvents *DNSGetEvents(void *state, uint64_t id) {
return NULL;
}
int DNSHasEvents(void *state) {
DNSState *dns_state = (DNSState *)state;
return (dns_state->events > 0);
}
void *DNSStateAlloc(void) {
void *s = SCMalloc(sizeof(DNSState));
if (unlikely(s == NULL))
@ -87,6 +97,9 @@ void *DNSGetTx(void *alstate, uint64_t tx_id) {
DNSState *dns_state = (DNSState *)alstate;
DNSTransaction *tx = NULL;
if (dns_state->curr && dns_state->curr->tx_num == tx_id + 1)
return dns_state->curr;
TAILQ_FOREACH(tx, &dns_state->tx_list, next) {
SCLogDebug("tx->tx_num %u, tx_id %"PRIu64, tx->tx_num, (tx_id+1));
if ((tx_id+1) != tx->tx_num)
@ -119,6 +132,7 @@ void DNSSetEvent(DNSState *s, uint8_t e) {
SCLogDebug("s->curr->decoder_events %p", s->curr->decoder_events);
AppLayerDecoderEventsSetEventRaw(s->curr->decoder_events, e);
SCLogDebug("s->curr->decoder_events %p", s->curr->decoder_events);
s->events++;
} else {
SCLogDebug("couldn't set event %u", e);
}

@ -142,7 +142,7 @@ typedef struct DNSState_ {
TAILQ_HEAD(, DNSTransaction_) tx_list; /**< transaction list */
DNSTransaction *curr; /**< ptr to current tx */
uint16_t transaction_max;
uint16_t transaction_done;
uint16_t events;
/* used by TCP only */
uint16_t offset;
@ -168,6 +168,7 @@ void DNSSetEvent(DNSState *s, uint8_t e);
void *DNSStateAlloc(void);
void DNSStateFree(void *s);
AppLayerDecoderEvents *DNSGetEvents(void *state, uint64_t id);
int DNSHasEvents(void *state);
int DNSValidateRequestHeader(DNSState *, const DNSHeader *dns_header);
int DNSValidateResponseHeader(DNSState *, const DNSHeader *dns_header);

@ -603,7 +603,6 @@ void DNSStateTransactionFree(void *state, uint16_t id) {
DNSState *s = state;
s->transaction_done = id;
SCLogDebug("state %p, id %"PRIu16, s, id);
/* we can't remove the actual transactions here */
@ -624,7 +623,9 @@ void RegisterDNSTCPParsers(void) {
DNSStateFree);
AppLayerRegisterTransactionIdFuncs(ALPROTO_DNS_TCP,
DNSStateUpdateTransactionId, DNSStateTransactionFree);
AppLayerRegisterGetEventsFunc(ALPROTO_DNS_TCP, DNSGetEvents);
AppLayerRegisterHasEventsFunc(ALPROTO_DNS_TCP, DNSHasEvents);
AppLayerRegisterGetTx(ALPROTO_DNS_TCP,
DNSGetTx);

@ -324,7 +324,6 @@ static void DNSStateTransactionFree(void *state, uint16_t id) {
DNSState *s = state;
s->transaction_done = id;
SCLogDebug("state %p, id %"PRIu16, s, id);
/* we can't remove the actual transactions here */
@ -345,7 +344,9 @@ void RegisterDNSUDPParsers(void) {
DNSStateFree);
AppLayerRegisterTransactionIdFuncs(ALPROTO_DNS_UDP,
DNSStateUpdateTransactionId, DNSStateTransactionFree);
AppLayerRegisterGetEventsFunc(ALPROTO_DNS_UDP, DNSGetEvents);
AppLayerRegisterHasEventsFunc(ALPROTO_DNS_UDP, DNSHasEvents);
AppLayerRegisterGetTx(ALPROTO_DNS_UDP,
DNSGetTx);

@ -121,10 +121,11 @@ AppLayerDecoderEvents *AppLayerGetEventsFromFlowByTx(Flow *f, uint64_t tx_id) {
}
}
/** \brief check if we have decoder events */
/** \brief check if we have decoder events
* \retval 1 yes
* \retval 0 no */
int AppLayerFlowHasDecoderEvents(Flow *f, uint8_t flags) {
AppLayerDecoderEvents *decoder_events;
uint64_t tx_id, max_id;
DEBUG_ASSERT_FLOW_LOCKED(f);
@ -132,13 +133,20 @@ int AppLayerFlowHasDecoderEvents(Flow *f, uint8_t flags) {
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)
/* fast path if supported by proto */
if (al_proto_table[f->alproto].StateHasEvents != NULL) {
if (al_proto_table[f->alproto].StateHasEvents(f->alstate) == 1)
return 1;
} else {
/* check each tx */
uint64_t tx_id = AppLayerTransactionGetInspectId(f, flags);
uint64_t 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;
}
}
}
@ -802,6 +810,11 @@ void AppLayerRegisterGetEventsFunc(uint16_t proto,
al_proto_table[proto].StateGetEvents = StateGetEvents;
}
void AppLayerRegisterHasEventsFunc(uint16_t proto,
int (*StateHasEvents)(void *)) {
al_proto_table[proto].StateHasEvents = StateHasEvents;
}
/** \brief Indicate to the app layer parser that a logger is active
* for this protocol.
*/

@ -59,6 +59,8 @@ typedef struct AppLayerProto_ {
void (*Truncate)(void *, uint8_t);
FileContainer *(*StateGetFiles)(void *, uint8_t);
AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t);
/* bool indicating a state has decoder/parser events */
int (*StateHasEvents)(void *);
int (*StateGetAlstateProgress)(void *alstate, uint8_t direction);
uint64_t (*StateGetTxCnt)(void *alstate);
@ -261,6 +263,9 @@ void AppLayerRegisterGetFilesFunc(uint16_t proto,
FileContainer *(*StateGetFile)(void *, uint8_t));
void AppLayerRegisterGetEventsFunc(uint16_t proto,
AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t));
void AppLayerRegisterHasEventsFunc(uint16_t proto,
int (*StateHasEvents)(void *));
void AppLayerRegisterLogger(uint16_t proto);
uint16_t AppLayerGetProtoByName(const char *);
const char *AppLayerGetProtoString(int proto);

Loading…
Cancel
Save