diff --git a/src/app-layer-dns-common.c b/src/app-layer-dns-common.c index 95a49935e9..1c3f164518 100644 --- a/src/app-layer-dns-common.c +++ b/src/app-layer-dns-common.c @@ -62,37 +62,6 @@ int DNSHasEvents(void *state) { return (dns_state->events > 0); } -void *DNSStateAlloc(void) { - void *s = SCMalloc(sizeof(DNSState)); - if (unlikely(s == NULL)) - return NULL; - - memset(s, 0, sizeof(DNSState)); - - DNSState *dns_state = (DNSState *)s; - - TAILQ_INIT(&dns_state->tx_list); - return s; -} - -void DNSStateFree(void *s) { - if (s) { - DNSState *dns_state = (DNSState *) s; - - DNSTransaction *tx = NULL; - while ((tx = TAILQ_FIRST(&dns_state->tx_list))) { - TAILQ_REMOVE(&dns_state->tx_list, tx, next); - DNSTransactionFree(tx); - } - - if (dns_state->buffer != NULL) - SCFree(dns_state->buffer); - - SCFree(s); - s = NULL; - } -} - void *DNSGetTx(void *alstate, uint64_t tx_id) { DNSState *dns_state = (DNSState *)alstate; DNSTransaction *tx = NULL; @@ -158,7 +127,7 @@ DNSTransaction *DNSTransactionAlloc(const uint16_t tx_id) { /** \internal * \brief Free a DNS TX * \param tx DNS TX to free */ -void DNSTransactionFree(DNSTransaction *tx) { +static void DNSTransactionFree(DNSTransaction *tx) { DNSQueryEntry *q = NULL; while ((q = TAILQ_FIRST(&tx->query_list))) { TAILQ_REMOVE(&tx->query_list, q, next); @@ -177,6 +146,40 @@ void DNSTransactionFree(DNSTransaction *tx) { SCFree(tx); } +/** + * \brief dns transaction cleanup callback + */ +void DNSStateTransactionFree(void *state, uint64_t tx_id) { + SCEnter(); + + DNSState *dns_state = state; + DNSTransaction *tx = NULL; + + SCLogDebug("state %p, id %"PRIu64, dns_state, tx_id); + + TAILQ_FOREACH(tx, &dns_state->tx_list, next) { + SCLogDebug("tx %p tx->tx_num %u, tx_id %"PRIu64, tx, tx->tx_num, (tx_id+1)); + if ((tx_id+1) < tx->tx_num) + break; + else if ((tx_id+1) > tx->tx_num) + continue; + + if (tx == dns_state->curr) + dns_state->curr = NULL; + + if (tx->decoder_events != NULL) { + if (tx->decoder_events->cnt <= dns_state->events) + dns_state->events -= tx->decoder_events->cnt; + else + dns_state->events = 0; + } + + TAILQ_REMOVE(&dns_state->tx_list, tx, next); + DNSTransactionFree(tx); + break; + } +} + /** \internal * \brief Find the DNS Tx in the state * \param tx_id id of the tx @@ -202,6 +205,37 @@ DNSTransaction *DNSTransactionFindByTxId(const DNSState *dns_state, const uint16 return NULL; } +void *DNSStateAlloc(void) { + void *s = SCMalloc(sizeof(DNSState)); + if (unlikely(s == NULL)) + return NULL; + + memset(s, 0, sizeof(DNSState)); + + DNSState *dns_state = (DNSState *)s; + + TAILQ_INIT(&dns_state->tx_list); + return s; +} + +void DNSStateFree(void *s) { + if (s) { + DNSState *dns_state = (DNSState *) s; + + DNSTransaction *tx = NULL; + while ((tx = TAILQ_FIRST(&dns_state->tx_list))) { + TAILQ_REMOVE(&dns_state->tx_list, tx, next); + DNSTransactionFree(tx); + } + + if (dns_state->buffer != NULL) + SCFree(dns_state->buffer); + + SCFree(s); + s = NULL; + } +} + /** \brief Validation checks for DNS request header * * Will set decoder events if anomalies are found. diff --git a/src/app-layer-dns-common.h b/src/app-layer-dns-common.h index ae1a8c663a..7a7e99d34c 100644 --- a/src/app-layer-dns-common.h +++ b/src/app-layer-dns-common.h @@ -161,7 +161,7 @@ int DNSGetAlstateProgress(void *tx, uint8_t direction); int DNSGetAlstateProgressCompletionStatus(uint8_t direction); DNSTransaction *DNSTransactionAlloc(const uint16_t tx_id); -void DNSTransactionFree(DNSTransaction *tx); +void DNSStateTransactionFree(void *state, uint64_t tx_id); DNSTransaction *DNSTransactionFindByTxId(const DNSState *dns_state, const uint16_t tx_id); void DNSSetEvent(DNSState *s, uint8_t e); diff --git a/src/app-layer-dns-tcp.c b/src/app-layer-dns-tcp.c index 8a11496d79..109c9e07ab 100644 --- a/src/app-layer-dns-tcp.c +++ b/src/app-layer-dns-tcp.c @@ -572,45 +572,6 @@ static uint16_t DNSTcpProbingParser(uint8_t *input, uint32_t ilen) return ALPROTO_DNS_TCP; } -/** - * \brief Update the transaction id based on the dns state - */ -void DNSStateUpdateTransactionId(void *state, uint16_t *id) { - SCEnter(); - - DNSState *s = state; - - SCLogDebug("original id %"PRIu16", s->transaction_max %"PRIu64, - *id, (s->transaction_max)); - - if ((s->transaction_max) > (*id)) { - SCLogDebug("original id %"PRIu16", updating with s->transaction_max %"PRIu64, - *id, (s->transaction_max)); - - (*id) = (s->transaction_max); - - SCLogDebug("updated id %"PRIu16, *id); - } - - SCReturn; -} - -/** - * \brief dns transaction cleanup callback - */ -void DNSStateTransactionFree(void *state, uint64_t id) { - SCEnter(); - - DNSState *s = state; - - SCLogDebug("state %p, id %"PRIu64, s, id); - - /* we can't remove the actual transactions here */ - - SCReturn; -} - - void RegisterDNSTCPParsers(void) { char *proto_name = "dnstcp"; diff --git a/src/app-layer-dns-udp.c b/src/app-layer-dns-udp.c index 2e8f8bc247..b642e06137 100644 --- a/src/app-layer-dns-udp.c +++ b/src/app-layer-dns-udp.c @@ -293,21 +293,6 @@ static uint16_t DNSUdpProbingParser(uint8_t *input, uint32_t ilen) return ALPROTO_DNS_UDP; } -/** - * \brief dns transaction cleanup callback - */ -static void DNSStateTransactionFree(void *state, uint64_t id) { - SCEnter(); - - DNSState *s = state; - - SCLogDebug("state %p, id %"PRIu64, s, id); - - /* we can't remove the actual transactions here */ - - SCReturn; -} - void RegisterDNSUDPParsers(void) { char *proto_name = "dnsudp"; diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 0d73db58d1..41a899d29d 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -953,32 +953,30 @@ static int AppLayerDoParse(void *local_data, Flow *f, /** * \brief remove obsolete (inspected and logged) transactions */ -static int AppLayerTransactionsCleanup(AppLayerProto *p, AppLayerParserStateStore *parser_state_store, void *app_layer_state) +static void AppLayerTransactionsCleanup(AppLayerProto *p, AppLayerParserStateStore *parser_state_store, void *app_layer_state) { - uint64_t low; - if (p->StateTransactionFree == NULL) - goto end; + return; + + uint64_t inspect = 0, log = 0; + if (parser_state_store->inspect_id[0] < parser_state_store->inspect_id[1]) + inspect = parser_state_store->inspect_id[0]; + else + inspect = parser_state_store->inspect_id[1]; + log = parser_state_store->log_id; if (p->logger == TRUE) { - if (parser_state_store->inspect_id[0] < parser_state_store->inspect_id[1]) - low = parser_state_store->inspect_id[0]; - else - low = parser_state_store->inspect_id[1]; - if (parser_state_store->log_id < low) { - low = parser_state_store->log_id; + uint64_t min = log < inspect ? log : inspect; + if (min > 0) { + SCLogDebug("freeing %"PRIu64" (with logger) %p", min - 1, p->StateTransactionFree); + p->StateTransactionFree(app_layer_state, min - 1); } } else { - if (parser_state_store->inspect_id[0] < parser_state_store->inspect_id[1]) - low = parser_state_store->inspect_id[0]; - else - low = parser_state_store->inspect_id[1]; + if (inspect > 0) { + SCLogDebug("freeing %"PRIu64" (no logger) %p", inspect - 1, p->StateTransactionFree); + p->StateTransactionFree(app_layer_state, inspect - 1); + } } - - p->StateTransactionFree(app_layer_state, low); - -end: - return 0; } #ifdef DEBUG