#ifdef DEBUG
#include "util-print.h"
#endif
+#include "util-memcmp.h"
typedef struct DNSConfig_ {
uint32_t request_flood;
return -1;
}
+/** \internal
+ * \brief check the query list to see if we already have this exact query
+ * \retval bool true or false
+ */
+static int QueryIsDuplicate(DNSTransaction *tx, const uint8_t *fqdn, const uint16_t fqdn_len,
+ const uint16_t type, const uint16_t class) {
+ DNSQueryEntry *q = NULL;
+
+ TAILQ_FOREACH(q, &tx->query_list, next) {
+ uint8_t *qfqdn = (uint8_t *)q + sizeof(DNSQueryEntry);
+
+ if (q->len == fqdn_len && q->type == type &&
+ q->class == class &&
+ SCMemcmp(qfqdn, fqdn, fqdn_len) == 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
void DNSStoreQueryInState(DNSState *dns_state, const uint8_t *fqdn, const uint16_t fqdn_len,
const uint16_t type, const uint16_t class, const uint16_t tx_id)
{
if (dns_state->givenup)
return;
- if (dns_state->curr != NULL && dns_state->curr->replied == 0) {
+ /* find the tx and see if this is an exact duplicate */
+ DNSTransaction *tx = DNSTransactionFindByTxId(dns_state, tx_id);
+ if ((tx != NULL) && (QueryIsDuplicate(tx, fqdn, fqdn_len, type, class) == TRUE)) {
+ SCLogDebug("query is duplicate");
+ return;
+ }
+
+ /* see if the last tx is unreplied */
+ if (dns_state->curr != tx && dns_state->curr != NULL &&
+ dns_state->curr->replied == 0)
+ {
dns_state->curr->reply_lost = 1;
dns_state->unreplied_cnt++;
/* check flood limit */
if (dns_config.request_flood != 0 &&
- dns_state->unreplied_cnt > dns_config.request_flood) {
+ dns_state->unreplied_cnt > dns_config.request_flood) {
DNSSetEvent(dns_state, DNS_DECODER_EVENT_FLOODED);
dns_state->givenup = 1;
}
}
- DNSTransaction *tx = DNSTransactionFindByTxId(dns_state, tx_id);
if (tx == NULL) {
tx = DNSTransactionAlloc(tx_id);
if (tx == NULL)