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;
/** \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);
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
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.
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";
/**
* \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