suricata
app-layer-dns-common.c
Go to the documentation of this file.
1 /* Copyright (C) 2013-2014 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  */
23 
24 #include "suricata-common.h"
25 #include "stream.h"
26 #include "app-layer-parser.h"
27 #include "app-layer-dns-common.h"
28 #ifdef DEBUG
29 #include "util-print.h"
30 #endif
31 #include "util-memcmp.h"
32 #include "util-atomic.h"
33 
34 typedef struct DNSConfig_ {
35  uint32_t request_flood;
36  uint32_t state_memcap; /**< memcap in bytes per state */
37  uint64_t global_memcap; /**< memcap in bytes globally for parser */
38 } DNSConfig;
39 static DNSConfig dns_config;
40 
41 void DNSConfigInit(void)
42 {
43  memset(&dns_config, 0x00, sizeof(dns_config));
44 }
45 
46 void DNSConfigSetRequestFlood(uint32_t value)
47 {
48  dns_config.request_flood = value;
49 }
50 
51 void DNSConfigSetStateMemcap(uint32_t value)
52 {
53  dns_config.state_memcap = value;
54 }
55 
56 SC_ATOMIC_DECLARE(uint64_t, dns_memuse); /**< byte counter of current memuse */
57 SC_ATOMIC_DECLARE(uint64_t, dns_memcap_state); /**< counts number of 'rejects' */
58 SC_ATOMIC_DECLARE(uint64_t, dns_memcap_global); /**< counts number of 'rejects' */
59 
60 void DNSConfigSetGlobalMemcap(uint64_t value)
61 {
62  dns_config.global_memcap = value;
63 
64  SC_ATOMIC_INIT(dns_memuse);
65  SC_ATOMIC_INIT(dns_memcap_state);
66  SC_ATOMIC_INIT(dns_memcap_global);
67 }
68 
69 void DNSIncrMemcap(uint32_t size, DNSState *state)
70 {
71  if (state != NULL) {
72  state->memuse += size;
73  }
74  SC_ATOMIC_ADD(dns_memuse, size);
75 }
76 
77 void DNSDecrMemcap(uint32_t size, DNSState *state)
78 {
79  if (state != NULL) {
80  BUG_ON(size > state->memuse); /**< TODO remove later */
81  state->memuse -= size;
82  }
83 
84  BUG_ON(size > SC_ATOMIC_GET(dns_memuse)); /**< TODO remove later */
85  (void)SC_ATOMIC_SUB(dns_memuse, size);
86 }
87 
88 int DNSCheckMemcap(uint32_t want, DNSState *state)
89 {
90  if (state != NULL) {
91  if (state->memuse + want > dns_config.state_memcap) {
92  SC_ATOMIC_ADD(dns_memcap_state, 1);
94  return -1;
95  }
96  }
97 
98  if (SC_ATOMIC_GET(dns_memuse) + (uint64_t)want > dns_config.global_memcap) {
99  SC_ATOMIC_ADD(dns_memcap_global, 1);
100  return -2;
101  }
102 
103  return 0;
104 }
105 
107 {
108  uint64_t x = SC_ATOMIC_GET(dns_memuse);
109  return x;
110 }
111 
113 {
114  uint64_t x = SC_ATOMIC_GET(dns_memcap_state);
115  return x;
116 }
117 
119 {
120  uint64_t x = SC_ATOMIC_GET(dns_memcap_global);
121  return x;
122 }
123 
125  { "UNSOLLICITED_RESPONSE", DNS_DECODER_EVENT_UNSOLLICITED_RESPONSE, },
126  { "MALFORMED_DATA", DNS_DECODER_EVENT_MALFORMED_DATA, },
127  { "NOT_A_REQUEST", DNS_DECODER_EVENT_NOT_A_REQUEST, },
128  { "NOT_A_RESPONSE", DNS_DECODER_EVENT_NOT_A_RESPONSE, },
129  { "Z_FLAG_SET", DNS_DECODER_EVENT_Z_FLAG_SET, },
130  { "FLOODED", DNS_DECODER_EVENT_FLOODED, },
131  { "STATE_MEMCAP_REACHED", DNS_DECODER_EVENT_STATE_MEMCAP_REACHED, },
132 
133  { NULL, -1 },
134 };
135 
136 int DNSStateGetEventInfo(const char *event_name,
137  int *event_id, AppLayerEventType *event_type)
138 {
139  *event_id = SCMapEnumNameToValue(event_name, dns_decoder_event_table);
140  if (*event_id == -1) {
141  SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%s\" not present in "
142  "dns's enum map table.", event_name);
143  /* this should be treated as fatal */
144  return -1;
145  }
146 
147  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
148 
149  return 0;
150 }
151 
152 void DNSAppLayerRegisterGetEventInfo(uint8_t ipproto, AppProto alproto)
153 {
155 
156  return;
157 }
158 
159 AppLayerDecoderEvents *DNSGetEvents(void *state, uint64_t id)
160 {
161  DNSState *dns_state = (DNSState *)state;
162  DNSTransaction *tx;
163 
164  if (dns_state->curr && dns_state->curr->tx_num == (id + 1)) {
165  return dns_state->curr->decoder_events;
166  }
167 
168  TAILQ_FOREACH(tx, &dns_state->tx_list, next) {
169  if (tx->tx_num == (id+1))
170  return tx->decoder_events;
171  }
172  return NULL;
173 }
174 
175 void *DNSGetTx(void *alstate, uint64_t tx_id)
176 {
177  DNSState *dns_state = (DNSState *)alstate;
178  DNSTransaction *tx = NULL;
179 
180  /* fast track: try the current tx */
181  if (dns_state->curr && dns_state->curr->tx_num == tx_id + 1)
182  return dns_state->curr;
183 
184  /* fast track:
185  * if the prev tx_id is equal to the stored tx ptr, we can
186  * use this shortcut to get to the next. */
187  if (dns_state->iter) {
188  if (tx_id == dns_state->iter->tx_num) {
189  tx = TAILQ_NEXT(dns_state->iter, next);
190  if (tx && tx->tx_num == tx_id + 1) {
191  dns_state->iter = tx;
192  return tx;
193  }
194  }
195  }
196 
197  /* no luck with the fast tracks, do the full list walk */
198  TAILQ_FOREACH(tx, &dns_state->tx_list, next) {
199  SCLogDebug("tx->tx_num %u, tx_id %"PRIu64, tx->tx_num, (tx_id+1));
200  if ((tx_id+1) != tx->tx_num)
201  continue;
202 
203  SCLogDebug("returning tx %p", tx);
204  dns_state->iter = tx;
205  return tx;
206  }
207 
208  return NULL;
209 }
210 
211 uint64_t DNSGetTxCnt(void *alstate)
212 {
213  DNSState *dns_state = (DNSState *)alstate;
214  return (uint64_t)dns_state->transaction_max;
215 }
216 
217 int DNSGetAlstateProgress(void *tx, uint8_t direction)
218 {
219  DNSTransaction *dns_tx = (DNSTransaction *)tx;
220  if (direction & STREAM_TOCLIENT) {
221  /* response side of the tx is done if we parsed a reply
222  * or if we tagged this tx as 'reply lost'. */
223  return (dns_tx->replied|dns_tx->reply_lost) ? 1 : 0;
224  }
225  else {
226  /* tx is only created if we have a complete request,
227  * or if we lost the request. Either way, if we have
228  * a tx it we consider the request complete. */
229  return 1;
230  }
231 }
232 
233 void DNSSetTxLogged(void *alstate, void *tx, LoggerId logged)
234 {
235  DNSTransaction *dns_tx = (DNSTransaction *)tx;
236  dns_tx->logged = logged;
237 }
238 
239 LoggerId DNSGetTxLogged(void *alstate, void *tx)
240 {
241  DNSTransaction *dns_tx = (DNSTransaction *)tx;
242  return dns_tx->logged;
243 }
244 
245 uint64_t DNSGetTxDetectFlags(void *vtx, uint8_t dir)
246 {
247  DNSTransaction *tx = (DNSTransaction *)vtx;
248  if (dir & STREAM_TOSERVER) {
249  return tx->detect_flags_ts;
250  } else {
251  return tx->detect_flags_tc;
252  }
253 }
254 
255 void DNSSetTxDetectFlags(void *vtx, uint8_t dir, uint64_t detect_flags)
256 {
257  DNSTransaction *tx = (DNSTransaction *)vtx;
258  if (dir & STREAM_TOSERVER) {
259  tx->detect_flags_ts = detect_flags;
260  } else {
261  tx->detect_flags_tc = detect_flags;
262  }
263 }
264 
265 /** \brief get value for 'complete' status in DNS
266  *
267  * For DNS we use a simple bool. 1 means done.
268  */
270 {
271  return 1;
272 }
273 
274 void DNSSetEvent(DNSState *s, uint8_t e)
275 {
276  if (s && s->curr) {
277  SCLogDebug("s->curr->decoder_events %p", s->curr->decoder_events);
279  SCLogDebug("s->curr->decoder_events %p", s->curr->decoder_events);
280  s->events++;
281  } else {
282  SCLogDebug("couldn't set event %u", e);
283  }
284 }
285 
286 /** \internal
287  * \brief Allocate a DNS TX
288  * \retval tx or NULL */
289 static DNSTransaction *DNSTransactionAlloc(DNSState *state, const uint16_t tx_id)
290 {
291  if (DNSCheckMemcap(sizeof(DNSTransaction), state) < 0)
292  return NULL;
293 
294  DNSTransaction *tx = SCMalloc(sizeof(DNSTransaction));
295  if (unlikely(tx == NULL))
296  return NULL;
297  DNSIncrMemcap(sizeof(DNSTransaction), state);
298 
299  memset(tx, 0x00, sizeof(DNSTransaction));
300 
301  TAILQ_INIT(&tx->query_list);
302  TAILQ_INIT(&tx->answer_list);
303  TAILQ_INIT(&tx->authority_list);
304 
305  tx->tx_id = tx_id;
306  return tx;
307 }
308 
309 /** \internal
310  * \brief Free a DNS TX
311  * \param tx DNS TX to free */
312 static void DNSTransactionFree(DNSTransaction *tx, DNSState *state)
313 {
314  SCEnter();
315 
316  DNSQueryEntry *q = NULL;
317  while ((q = TAILQ_FIRST(&tx->query_list))) {
318  TAILQ_REMOVE(&tx->query_list, q, next);
319  DNSDecrMemcap((sizeof(DNSQueryEntry) + q->len), state);
320  SCFree(q);
321  }
322 
323  DNSAnswerEntry *a = NULL;
324  while ((a = TAILQ_FIRST(&tx->answer_list))) {
325  TAILQ_REMOVE(&tx->answer_list, a, next);
326  DNSDecrMemcap((sizeof(DNSAnswerEntry) + a->fqdn_len + a->data_len), state);
327  SCFree(a);
328  }
329  while ((a = TAILQ_FIRST(&tx->authority_list))) {
330  TAILQ_REMOVE(&tx->authority_list, a, next);
331  DNSDecrMemcap((sizeof(DNSAnswerEntry) + a->fqdn_len + a->data_len), state);
332  SCFree(a);
333  }
334 
336 
337  if (tx->de_state != NULL) {
339  }
340 
341  if (state->iter == tx)
342  state->iter = NULL;
343 
344  DNSDecrMemcap(sizeof(DNSTransaction), state);
345  SCFree(tx);
346  SCReturn;
347 }
348 
349 /**
350  * \brief dns transaction cleanup callback
351  */
352 void DNSStateTransactionFree(void *state, uint64_t tx_id)
353 {
354  SCEnter();
355 
356  DNSState *dns_state = state;
357  DNSTransaction *tx = NULL;
358 
359  SCLogDebug("state %p, id %"PRIu64, dns_state, tx_id);
360 
361  TAILQ_FOREACH(tx, &dns_state->tx_list, next) {
362  SCLogDebug("tx %p tx->tx_num %u, tx_id %"PRIu64, tx, tx->tx_num, (tx_id+1));
363  if ((tx_id+1) < tx->tx_num)
364  break;
365  else if ((tx_id+1) > tx->tx_num)
366  continue;
367 
368  if (tx == dns_state->curr)
369  dns_state->curr = NULL;
370 
371  if (tx->decoder_events != NULL) {
372  if (tx->decoder_events->cnt <= dns_state->events)
373  dns_state->events -= tx->decoder_events->cnt;
374  else
375  dns_state->events = 0;
376  }
377 
378  TAILQ_REMOVE(&dns_state->tx_list, tx, next);
379  DNSTransactionFree(tx, state);
380  break;
381  }
382  SCReturn;
383 }
384 
385 /** \internal
386  * \brief Find the DNS Tx in the state
387  * \param tx_id id of the tx
388  * \retval tx or NULL if not found */
389 DNSTransaction *DNSTransactionFindByTxId(const DNSState *dns_state, const uint16_t tx_id)
390 {
391  if (dns_state->curr == NULL)
392  return NULL;
393 
394  /* fast path */
395  if (dns_state->curr->tx_id == tx_id) {
396  return dns_state->curr;
397 
398  /* slow path, iterate list */
399  } else {
400  DNSTransaction *tx = NULL;
401  TAILQ_FOREACH(tx, &dns_state->tx_list, next) {
402  if (tx->tx_id == tx_id) {
403  return tx;
404  } else if ((dns_state->transaction_max - tx->tx_num) >
405  (dns_state->window - 1U)) {
406  tx->reply_lost = 1;
407  }
408  }
409  }
410  /* not found */
411  return NULL;
412 }
413 
415 {
416  DNSTransaction *tx = (DNSTransaction *)vtx;
417  return tx->de_state;
418 }
419 
421 {
422  DNSTransaction *tx = (DNSTransaction *)vtx;
423  tx->de_state = s;
424  return 0;
425 }
426 
427 void *DNSStateAlloc(void)
428 {
429  void *s = SCMalloc(sizeof(DNSState));
430  if (unlikely(s == NULL))
431  return NULL;
432 
433  memset(s, 0, sizeof(DNSState));
434 
435  DNSState *dns_state = (DNSState *)s;
436 
437  DNSIncrMemcap(sizeof(DNSState), dns_state);
438 
439  TAILQ_INIT(&dns_state->tx_list);
440  return s;
441 }
442 
443 void DNSStateFree(void *s)
444 {
445  SCEnter();
446  if (s) {
447  DNSState *dns_state = (DNSState *) s;
448 
449  DNSTransaction *tx = NULL;
450  while ((tx = TAILQ_FIRST(&dns_state->tx_list))) {
451  TAILQ_REMOVE(&dns_state->tx_list, tx, next);
452  DNSTransactionFree(tx, dns_state);
453  }
454 
455  if (dns_state->buffer != NULL) {
456  DNSDecrMemcap(0xffff, dns_state); /** TODO update if/once we alloc
457  * in a smarter way */
458  SCFree(dns_state->buffer);
459  }
460 
461  DNSDecrMemcap(sizeof(DNSState), dns_state);
462  BUG_ON(dns_state->memuse > 0);
463  SCFree(s);
464  }
465  SCReturn;
466 }
467 
468 /** \brief Validation checks for DNS request header
469  *
470  * Will set decoder events if anomalies are found.
471  *
472  * \retval 0 ok
473  * \retval -1 error
474  */
475 int DNSValidateRequestHeader(DNSState *dns_state, const DNSHeader *dns_header)
476 {
477  uint16_t flags = SCNtohs(dns_header->flags);
478 
479  if ((flags & 0x8000) != 0) {
480  SCLogDebug("not a request 0x%04x", flags);
482  goto bad_data;
483  }
484 
485  if ((flags & 0x0040) != 0) {
486  SCLogDebug("Z flag not 0, 0x%04x", flags);
488  goto bad_data;
489  }
490 
491  return 0;
492 bad_data:
493  return -1;
494 }
495 
496 /** \brief Validation checks for DNS response header
497  *
498  * Will set decoder events if anomalies are found.
499  *
500  * \retval 0 ok
501  * \retval -1 error
502  */
503 int DNSValidateResponseHeader(DNSState *dns_state, const DNSHeader *dns_header)
504 {
505  uint16_t flags = SCNtohs(dns_header->flags);
506 
507  if ((flags & 0x8000) == 0) {
508  SCLogDebug("not a response 0x%04x", flags);
510  goto bad_data;
511  }
512 
513  if ((flags & 0x0040) != 0) {
514  SCLogDebug("Z flag not 0, 0x%04x", flags);
516  goto bad_data;
517  }
518 
519  return 0;
520 bad_data:
521  return -1;
522 }
523 
524 /** \internal
525  * \brief check the query list to see if we already have this exact query
526  * \retval bool true or false
527  */
528 static int QueryIsDuplicate(DNSTransaction *tx, const uint8_t *fqdn, const uint16_t fqdn_len,
529  const uint16_t type, const uint16_t class)
530 {
531  DNSQueryEntry *q = NULL;
532 
533  TAILQ_FOREACH(q, &tx->query_list, next) {
534  uint8_t *qfqdn = (uint8_t *)q + sizeof(DNSQueryEntry);
535 
536  if (q->len == fqdn_len && q->type == type &&
537  q->class == class &&
538  SCMemcmp(qfqdn, fqdn, fqdn_len) == 0) {
539  return TRUE;
540  }
541  }
542  return FALSE;
543 }
544 
545 void DNSStoreQueryInState(DNSState *dns_state, const uint8_t *fqdn, const uint16_t fqdn_len,
546  const uint16_t type, const uint16_t class, const uint16_t tx_id)
547 {
548  /* flood protection */
549  if (dns_state->givenup)
550  return;
551 
552  /* find the tx and see if this is an exact duplicate */
553  DNSTransaction *tx = DNSTransactionFindByTxId(dns_state, tx_id);
554  if ((tx != NULL) && (QueryIsDuplicate(tx, fqdn, fqdn_len, type, class) == TRUE)) {
555  SCLogDebug("query is duplicate");
556  return;
557  }
558 
559  /* check flood limit */
560  if (dns_config.request_flood != 0 &&
561  dns_state->unreplied_cnt > dns_config.request_flood) {
563  dns_state->givenup = 1;
564  }
565 
566  if (tx == NULL) {
567  tx = DNSTransactionAlloc(dns_state, tx_id);
568  if (tx == NULL)
569  return;
570  dns_state->transaction_max++;
571  SCLogDebug("dns_state->transaction_max updated to %"PRIu64, dns_state->transaction_max);
572  TAILQ_INSERT_TAIL(&dns_state->tx_list, tx, next);
573  dns_state->curr = tx;
574  tx->tx_num = dns_state->transaction_max;
575  SCLogDebug("new tx %u with internal id %u", tx->tx_id, tx->tx_num);
576  dns_state->unreplied_cnt++;
577  }
578 
579  if (DNSCheckMemcap((sizeof(DNSQueryEntry) + fqdn_len), dns_state) < 0)
580  return;
581  DNSQueryEntry *q = SCMalloc(sizeof(DNSQueryEntry) + fqdn_len);
582  if (unlikely(q == NULL))
583  return;
584  DNSIncrMemcap((sizeof(DNSQueryEntry) + fqdn_len), dns_state);
585 
586  q->type = type;
587  q->class = class;
588  q->len = fqdn_len;
589  memcpy((uint8_t *)q + sizeof(DNSQueryEntry), fqdn, fqdn_len);
590 
591  TAILQ_INSERT_TAIL(&tx->query_list, q, next);
592 
593  SCLogDebug("Query for TX %04x stored", tx_id);
594 }
595 
596 void DNSStoreAnswerInState(DNSState *dns_state, const int rtype, const uint8_t *fqdn,
597  const uint16_t fqdn_len, const uint16_t type, const uint16_t class, const uint16_t ttl,
598  const uint8_t *data, const uint16_t data_len, const uint16_t tx_id)
599 {
600  DNSTransaction *tx = DNSTransactionFindByTxId(dns_state, tx_id);
601  if (tx == NULL) {
602  tx = DNSTransactionAlloc(dns_state, tx_id);
603  if (tx == NULL)
604  return;
605  TAILQ_INSERT_TAIL(&dns_state->tx_list, tx, next);
606  dns_state->curr = tx;
607  dns_state->transaction_max++;
608  tx->tx_num = dns_state->transaction_max;
609  }
610 
611  if (DNSCheckMemcap((sizeof(DNSAnswerEntry) + fqdn_len + data_len), dns_state) < 0)
612  return;
613  DNSAnswerEntry *q = SCMalloc(sizeof(DNSAnswerEntry) + fqdn_len + data_len);
614  if (unlikely(q == NULL))
615  return;
616  DNSIncrMemcap((sizeof(DNSAnswerEntry) + fqdn_len + data_len), dns_state);
617 
618  q->type = type;
619  q->class = class;
620  q->ttl = ttl;
621  q->fqdn_len = fqdn_len;
622  q->data_len = data_len;
623 
624  uint8_t *ptr = (uint8_t *)q + sizeof(DNSAnswerEntry);
625  if (fqdn != NULL && fqdn_len > 0) {
626  memcpy(ptr, fqdn, fqdn_len);
627  ptr += fqdn_len;
628  }
629  if (data != NULL && data_len > 0) {
630  memcpy(ptr, data, data_len);
631  }
632 
633  if (rtype == DNS_LIST_ANSWER)
634  TAILQ_INSERT_TAIL(&tx->answer_list, q, next);
635  else if (rtype == DNS_LIST_AUTHORITY)
636  TAILQ_INSERT_TAIL(&tx->authority_list, q, next);
637  else
638  BUG_ON(1);
639 
640  SCLogDebug("Answer for TX %04x stored", tx_id);
641 
642  /* mark tx is as replied so we can log it */
643  tx->replied = 1;
644 }
645 
646 /** \internal
647  * \brief get domain name from dns packet
648  *
649  * In case of compressed name storage this function follows the ptrs to
650  * create the full domain name.
651  *
652  * The length bytes are converted into dots, e.g. |03|com|00| becomes
653  * .com
654  * The trailing . is not stored.
655  *
656  * \param input input buffer (complete dns record)
657  * \param input_len lenght of input buffer
658  * \param offset offset into @input where dns name starts
659  * \param fqdn buffer to store result
660  * \param fqdn_size size of @fqdn buffer
661  * \retval 0 on error/no buffer
662  * \retval size size of fqdn
663  */
664 static uint16_t DNSResponseGetNameByOffset(const uint8_t * const input, const uint32_t input_len,
665  const uint16_t offset, uint8_t *fqdn, const size_t fqdn_size)
666 {
667  if (offset >= input_len) {
668  SCLogDebug("input buffer too small for domain of len %u", offset);
669  goto insufficient_data;
670  }
671 
672  int steps = 0;
673  uint16_t fqdn_offset = 0;
674  uint8_t length = *(input + offset);
675  const uint8_t *qdata = input + offset;
676  SCLogDebug("qry length %u", length);
677 
678  if (length == 0) {
679  memcpy(fqdn, "<root>", 6);
680  SCReturnUInt(6U);
681  }
682 
683  if ((uint64_t)((qdata + 1) - input) >= (uint64_t)input_len) {
684  SCLogDebug("input buffer too small");
685  goto insufficient_data;
686  }
687 
688  while (length != 0) {
689  int cnt = 0;
690  while (length & 0xc0) {
691  uint16_t off = ((length & 0x3f) << 8) + *(qdata+1);
692  qdata = (const uint8_t *)input + off;
693 
694  if ((uint64_t)((qdata + 1) - input) >= (uint64_t)input_len) {
695  SCLogDebug("input buffer too small");
696  goto insufficient_data;
697  }
698 
699  length = *qdata;
700  SCLogDebug("qry length %u", length);
701 
702  if (cnt++ == 100) {
703  SCLogDebug("too many pointer iterations, loop?");
704  goto bad_data;
705  }
706  }
707  qdata++;
708 
709  if (length == 0) {
710  break;
711  }
712 
713  if (input + input_len < qdata + length) {
714  SCLogDebug("input buffer too small for domain of len %u", length);
715  goto insufficient_data;
716  }
717  //PrintRawDataFp(stdout, qdata, length);
718 
719  if ((size_t)(fqdn_offset + length + 1) < fqdn_size) {
720  memcpy(fqdn + fqdn_offset, qdata, length);
721  fqdn_offset += length;
722  fqdn[fqdn_offset++] = '.';
723  }
724  qdata += length;
725 
726  /* if we're at the end of the input data, we're done */
727  if ((uint64_t)((qdata + 1) - input) == (uint64_t)input_len) {
728  break;
729  }
730  else if ((uint64_t)((qdata + 1) - input) > (uint64_t)input_len) {
731  SCLogDebug("input buffer too small");
732  goto insufficient_data;
733  }
734 
735  length = *qdata;
736  SCLogDebug("qry length %u", length);
737  steps++;
738  if (steps >= 255)
739  goto bad_data;
740  }
741  if (fqdn_offset) {
742  fqdn_offset--;
743  }
744  //PrintRawDataFp(stdout, fqdn, fqdn_offset);
745  SCReturnUInt(fqdn_offset);
746 bad_data:
747 insufficient_data:
748  SCReturnUInt(0U);
749 }
750 
751 /** \internal
752  * \brief skip past domain name field
753  *
754  * Skip the domain at position data. We don't care about following compressed names
755  * as we only want to know when the next part of the buffer starts
756  *
757  * \param input input buffer (complete dns record)
758  * \param input_len lenght of input buffer
759  * \param data current position
760  *
761  * \retval NULL on out of bounds data
762  * \retval sdata ptr to position in buffer past the name
763  */
764 static const uint8_t *SkipDomain(const uint8_t * const input,
765  const uint32_t input_len, const uint8_t *data)
766 {
767  const uint8_t *sdata = data;
768  while (*sdata != 0x00) {
769  if (*sdata & 0xc0) {
770  sdata++;
771  break;
772  } else {
773  sdata += ((*sdata) + 1);
774  }
775  if (input + input_len < sdata) {
776  SCLogDebug("input buffer too small for data of len");
777  goto insufficient_data;
778  }
779  }
780  sdata++;
781  if (input + input_len < sdata) {
782  SCLogDebug("input buffer too small for data of len");
783  goto insufficient_data;
784  }
785  return sdata;
786 insufficient_data:
787  return NULL;
788 }
789 
790 const uint8_t *DNSReponseParse(DNSState *dns_state, const DNSHeader * const dns_header,
791  const uint16_t num, const DnsListEnum list, const uint8_t * const input,
792  const uint32_t input_len, const uint8_t *data)
793 {
794  if (input + input_len < data + 2) {
795  SCLogDebug("input buffer too small for record 'name' field, record %u, "
796  "total answer_rr %u", num, SCNtohs(dns_header->answer_rr));
797  goto insufficient_data;
798  }
799 
800  uint8_t fqdn[DNS_MAX_SIZE];
801  uint16_t fqdn_len = 0;
802 
803  /* see if name is compressed */
804  if (!(data[0] & 0xc0)) {
805  if ((fqdn_len = DNSResponseGetNameByOffset(input, input_len,
806  data - input, fqdn, sizeof(fqdn))) == 0)
807  {
809  goto insufficient_data;
810  }
811  //PrintRawDataFp(stdout, fqdn, fqdn_len);
812  const uint8_t *tdata = SkipDomain(input, input_len, data);
813  if (tdata == NULL) {
814  goto insufficient_data;
815  }
816  data = tdata;
817  } else {
818  uint16_t offset = (data[0] & 0x3f) << 8 | data[1];
819 
820  if ((fqdn_len = DNSResponseGetNameByOffset(input, input_len,
821  offset, fqdn, sizeof(fqdn))) == 0)
822  {
824  goto insufficient_data;
825  }
826  //PrintRawDataFp(stdout, fqdn, fqdn_len);
827  data += 2;
828  }
829 
830  if (input + input_len < data + sizeof(DNSAnswerHeader)) {
831  SCLogDebug("input buffer too small for DNSAnswerHeader");
832  goto insufficient_data;
833  }
834 
835  const DNSAnswerHeader *head = (DNSAnswerHeader *)data;
836  const uint16_t datalen = SCNtohs(head->len);
837 
838  data += sizeof(DNSAnswerHeader);
839 
840  SCLogDebug("head->len %u", SCNtohs(head->len));
841 
842  if (input + input_len < data + SCNtohs(head->len)) {
843  SCLogDebug("input buffer too small for data of len %u", SCNtohs(head->len));
844  goto insufficient_data;
845  }
846 
847  SCLogDebug("TTL %u", SCNtohl(head->ttl));
848 
849  switch (SCNtohs(head->type)) {
850  case DNS_RECORD_TYPE_A:
851  {
852  if (datalen == 0 || datalen == 4) {
853  //PrintRawDataFp(stdout, data, SCNtohs(head->len));
854  //char a[16];
855  //PrintInet(AF_INET, (const void *)data, a, sizeof(a));
856  //SCLogInfo("A %s TTL %u", a, SCNtohl(head->ttl));
857 
858  DNSStoreAnswerInState(dns_state, list, fqdn, fqdn_len,
859  SCNtohs(head->type), SCNtohs(head->class), SCNtohl(head->ttl),
860  data, datalen, SCNtohs(dns_header->tx_id));
861  } else {
862  SCLogDebug("invalid length for A response data: %u", SCNtohs(head->len));
863  goto bad_data;
864  }
865 
866  data += datalen;
867  break;
868  }
870  {
871  if (datalen == 0 || datalen == 16) {
872  //char a[46];
873  //PrintInet(AF_INET6, (const void *)data, a, sizeof(a));
874  //SCLogInfo("AAAA %s TTL %u", a, SCNtohl(head->ttl));
875 
876  DNSStoreAnswerInState(dns_state, list, fqdn, fqdn_len,
877  SCNtohs(head->type), SCNtohs(head->class), SCNtohl(head->ttl),
878  data, datalen, SCNtohs(dns_header->tx_id));
879  } else {
880  SCLogDebug("invalid length for AAAA response data: %u", SCNtohs(head->len));
881  goto bad_data;
882  }
883 
884  data += datalen;
885  break;
886  }
887  case DNS_RECORD_TYPE_MX:
889  case DNS_RECORD_TYPE_PTR:
890  {
891  uint8_t name[DNS_MAX_SIZE];
892  uint16_t name_len = 0;
893  uint8_t skip = 0;
894 
895  if (SCNtohs(head->type) == DNS_RECORD_TYPE_MX) {
896  // Skip the preference header
897  skip = 2;
898  }
899 
900  if ((name_len = DNSResponseGetNameByOffset(input, input_len,
901  data - input + skip, name, sizeof(name))) == 0)
902  {
904  goto insufficient_data;
905  }
906 
907  DNSStoreAnswerInState(dns_state, list, fqdn, fqdn_len,
908  SCNtohs(head->type), SCNtohs(head->class), SCNtohl(head->ttl),
909  name, name_len, SCNtohs(dns_header->tx_id));
910 
911  data += SCNtohs(head->len);
912  break;
913  }
914  case DNS_RECORD_TYPE_NS:
915  case DNS_RECORD_TYPE_SOA:
916  {
917  uint8_t pname[DNS_MAX_SIZE];
918  uint16_t pname_len = 0;
919 
920  if ((pname_len = DNSResponseGetNameByOffset(input, input_len,
921  data - input, pname, sizeof(pname))) == 0)
922  {
924  goto insufficient_data;
925  }
926 
927  if (SCNtohs(head->type) == DNS_RECORD_TYPE_SOA) {
928  const uint8_t *sdata = SkipDomain(input, input_len, data);
929  if (sdata == NULL) {
930  goto insufficient_data;
931  }
932 
933  uint8_t pmail[DNS_MAX_SIZE];
934  uint16_t pmail_len = 0;
935  SCLogDebug("getting pmail");
936  if ((pmail_len = DNSResponseGetNameByOffset(input, input_len,
937  sdata - input, pmail, sizeof(pmail))) == 0)
938  {
940  goto insufficient_data;
941  }
942  SCLogDebug("pmail_len %u", pmail_len);
943  //PrintRawDataFp(stdout, (uint8_t *)pmail, pmail_len);
944 
945  const uint8_t *tdata = SkipDomain(input, input_len, sdata);
946  if (tdata == NULL) {
947  goto insufficient_data;
948  }
949 #if DEBUG
950  struct Trailer {
951  uint32_t serial;
952  uint32_t refresh;
953  uint32_t retry;
954  uint32_t experiation;
955  uint32_t minttl;
956  } *tail = (struct Trailer *)tdata;
957 
958  if (input + input_len < tdata + sizeof(struct Trailer)) {
959  SCLogDebug("input buffer too small for data of len");
960  goto insufficient_data;
961  }
962 
963  SCLogDebug("serial %u refresh %u retry %u exp %u min ttl %u",
964  SCNtohl(tail->serial), SCNtohl(tail->refresh),
965  SCNtohl(tail->retry), SCNtohl(tail->experiation),
966  SCNtohl(tail->minttl));
967 #endif
968  }
969 
970  DNSStoreAnswerInState(dns_state, list, fqdn, fqdn_len,
971  SCNtohs(head->type), SCNtohs(head->class), SCNtohl(head->ttl),
972  pname, pname_len, SCNtohs(dns_header->tx_id));
973 
974  data += SCNtohs(head->len);
975  break;
976  }
977  case DNS_RECORD_TYPE_TXT:
978  {
979  uint16_t txtdatalen = datalen;
980 
981  if (txtdatalen == 0) {
983  goto bad_data;
984  }
985 
986  uint8_t txtlen = *data;
987  const uint8_t *tdata = data + 1;
988 
989  do {
990  //PrintRawDataFp(stdout, (uint8_t*)tdata, txtlen);
991 
992  if (txtlen >= txtdatalen)
993  goto bad_data;
994 
995  DNSStoreAnswerInState(dns_state, list, fqdn, fqdn_len,
996  SCNtohs(head->type), SCNtohs(head->class), SCNtohl(head->ttl),
997  (uint8_t*)tdata, (uint16_t)txtlen, SCNtohs(dns_header->tx_id));
998 
999  txtdatalen -= txtlen;
1000  tdata += txtlen;
1001  txtlen = *tdata;
1002 
1003  tdata++;
1004  txtdatalen--;
1005 
1006  SCLogDebug("datalen %u, txtlen %u", txtdatalen, txtlen);
1007  } while (txtdatalen > 1);
1008 
1009  data += datalen;
1010  break;
1011  }
1012  case DNS_RECORD_TYPE_SSHFP:
1013  {
1014  /* data here should be:
1015  * [1 byte algo][1 byte type][var bytes fingerprint]
1016  * As we currently can't store each of those in the state,
1017  * we just store the raw data an let the output/detect
1018  * code figure out what to do with it. */
1019 
1020  DNSStoreAnswerInState(dns_state, list, fqdn, fqdn_len,
1021  SCNtohs(head->type), SCNtohs(head->class), SCNtohl(head->ttl),
1022  data, SCNtohs(head->len), SCNtohs(dns_header->tx_id));
1023 
1024  data += datalen;
1025  break;
1026  }
1027  default: /* unsupported record */
1028  {
1029  DNSStoreAnswerInState(dns_state, list, NULL, 0,
1030  SCNtohs(head->type), SCNtohs(head->class), SCNtohl(head->ttl),
1031  NULL, 0, SCNtohs(dns_header->tx_id));
1032 
1033  //PrintRawDataFp(stdout, data, SCNtohs(head->len));
1034  data += datalen;
1035  break;
1036  }
1037  }
1038  return data;
1039 bad_data:
1040 insufficient_data:
1041  return NULL;
1042 }
1043 
1044 void DNSCreateTypeString(uint16_t type, char *str, size_t str_size)
1045 {
1046  switch (type) {
1047  case DNS_RECORD_TYPE_A:
1048  snprintf(str, str_size, "A");
1049  break;
1050  case DNS_RECORD_TYPE_NS:
1051  snprintf(str, str_size, "NS");
1052  break;
1053  case DNS_RECORD_TYPE_AAAA:
1054  snprintf(str, str_size, "AAAA");
1055  break;
1056  case DNS_RECORD_TYPE_CNAME:
1057  snprintf(str, str_size, "CNAME");
1058  break;
1059  case DNS_RECORD_TYPE_TXT:
1060  snprintf(str, str_size, "TXT");
1061  break;
1062  case DNS_RECORD_TYPE_MX:
1063  snprintf(str, str_size, "MX");
1064  break;
1065  case DNS_RECORD_TYPE_SOA:
1066  snprintf(str, str_size, "SOA");
1067  break;
1068  case DNS_RECORD_TYPE_PTR:
1069  snprintf(str, str_size, "PTR");
1070  break;
1071  case DNS_RECORD_TYPE_SIG:
1072  snprintf(str, str_size, "SIG");
1073  break;
1074  case DNS_RECORD_TYPE_KEY:
1075  snprintf(str, str_size, "KEY");
1076  break;
1077  case DNS_RECORD_TYPE_WKS:
1078  snprintf(str, str_size, "WKS");
1079  break;
1080  case DNS_RECORD_TYPE_TKEY:
1081  snprintf(str, str_size, "TKEY");
1082  break;
1083  case DNS_RECORD_TYPE_TSIG:
1084  snprintf(str, str_size, "TSIG");
1085  break;
1086  case DNS_RECORD_TYPE_ANY:
1087  snprintf(str, str_size, "ANY");
1088  break;
1089  case DNS_RECORD_TYPE_RRSIG:
1090  snprintf(str, str_size, "RRSIG");
1091  break;
1092  case DNS_RECORD_TYPE_NSEC:
1093  snprintf(str, str_size, "NSEC");
1094  break;
1096  snprintf(str, str_size, "DNSKEY");
1097  break;
1098  case DNS_RECORD_TYPE_HINFO:
1099  snprintf(str, str_size, "HINFO");
1100  break;
1101  case DNS_RECORD_TYPE_MINFO:
1102  snprintf(str, str_size, "MINFO");
1103  break;
1104  case DNS_RECORD_TYPE_RP:
1105  snprintf(str, str_size, "RP");
1106  break;
1107  case DNS_RECORD_TYPE_AFSDB:
1108  snprintf(str, str_size, "AFSDB");
1109  break;
1110  case DNS_RECORD_TYPE_X25:
1111  snprintf(str, str_size, "X25");
1112  break;
1113  case DNS_RECORD_TYPE_ISDN:
1114  snprintf(str, str_size, "ISDN");
1115  break;
1116  case DNS_RECORD_TYPE_RT:
1117  snprintf(str, str_size, "RT");
1118  break;
1119  case DNS_RECORD_TYPE_NSAP:
1120  snprintf(str, str_size, "NSAP");
1121  break;
1123  snprintf(str, str_size, "NSAPPTR");
1124  break;
1125  case DNS_RECORD_TYPE_PX:
1126  snprintf(str, str_size, "PX");
1127  break;
1128  case DNS_RECORD_TYPE_GPOS:
1129  snprintf(str, str_size, "GPOS");
1130  break;
1131  case DNS_RECORD_TYPE_LOC:
1132  snprintf(str, str_size, "LOC");
1133  break;
1134  case DNS_RECORD_TYPE_SRV:
1135  snprintf(str, str_size, "SRV");
1136  break;
1137  case DNS_RECORD_TYPE_ATMA:
1138  snprintf(str, str_size, "ATMA");
1139  break;
1140  case DNS_RECORD_TYPE_NAPTR:
1141  snprintf(str, str_size, "NAPTR");
1142  break;
1143  case DNS_RECORD_TYPE_KX:
1144  snprintf(str, str_size, "KX");
1145  break;
1146  case DNS_RECORD_TYPE_CERT:
1147  snprintf(str, str_size, "CERT");
1148  break;
1149  case DNS_RECORD_TYPE_A6:
1150  snprintf(str, str_size, "A6");
1151  break;
1152  case DNS_RECORD_TYPE_DNAME:
1153  snprintf(str, str_size, "DNAME");
1154  break;
1155  case DNS_RECORD_TYPE_OPT:
1156  snprintf(str, str_size, "OPT");
1157  break;
1158  case DNS_RECORD_TYPE_APL:
1159  snprintf(str, str_size, "APL");
1160  break;
1161  case DNS_RECORD_TYPE_DS:
1162  snprintf(str, str_size, "DS");
1163  break;
1164  case DNS_RECORD_TYPE_SSHFP:
1165  snprintf(str, str_size, "SSHFP");
1166  break;
1168  snprintf(str, str_size, "IPSECKEY");
1169  break;
1170  case DNS_RECORD_TYPE_DHCID:
1171  snprintf(str, str_size, "DHCID");
1172  break;
1173  case DNS_RECORD_TYPE_NSEC3:
1174  snprintf(str, str_size, "NSEC3");
1175  break;
1177  snprintf(str, str_size, "NSEC3PARAM");
1178  break;
1179  case DNS_RECORD_TYPE_TLSA:
1180  snprintf(str, str_size, "TLSA");
1181  break;
1182  case DNS_RECORD_TYPE_HIP:
1183  snprintf(str, str_size, "HIP");
1184  break;
1185  case DNS_RECORD_TYPE_CDS:
1186  snprintf(str, str_size, "CDS");
1187  break;
1189  snprintf(str, str_size, "CDNSKEY");
1190  break;
1191  case DNS_RECORD_TYPE_MAILA:
1192  snprintf(str, str_size, "MAILA");
1193  break;
1194  case DNS_RECORD_TYPE_URI:
1195  snprintf(str, str_size, "URI");
1196  break;
1197  case DNS_RECORD_TYPE_MB:
1198  snprintf(str, str_size, "MB");
1199  break;
1200  case DNS_RECORD_TYPE_MG:
1201  snprintf(str, str_size, "MG");
1202  break;
1203  case DNS_RECORD_TYPE_MR:
1204  snprintf(str, str_size, "MR");
1205  break;
1206  case DNS_RECORD_TYPE_NULL:
1207  snprintf(str, str_size, "NULL");
1208  break;
1209  case DNS_RECORD_TYPE_SPF:
1210  snprintf(str, str_size, "SPF");
1211  break;
1212  case DNS_RECORD_TYPE_NXT:
1213  snprintf(str, str_size, "NXT");
1214  break;
1215  case DNS_RECORD_TYPE_MD:
1216  snprintf(str, str_size, "MD");
1217  break;
1218  case DNS_RECORD_TYPE_MF:
1219  snprintf(str, str_size, "MF");
1220  break;
1221  default:
1222  snprintf(str, str_size, "%04x/%u", type, type);
1223  }
1224 }
1225 
1226 void DNSCreateRcodeString(uint8_t rcode, char *str, size_t str_size)
1227 {
1228  switch (rcode) {
1229  case DNS_RCODE_NOERROR:
1230  snprintf(str, str_size, "NOERROR");
1231  break;
1232  case DNS_RCODE_FORMERR:
1233  snprintf(str, str_size, "FORMERR");
1234  break;
1235  case DNS_RCODE_SERVFAIL:
1236  snprintf(str, str_size, "SERVFAIL");
1237  break;
1238  case DNS_RCODE_NXDOMAIN:
1239  snprintf(str, str_size, "NXDOMAIN");
1240  break;
1241  case DNS_RCODE_NOTIMP:
1242  snprintf(str, str_size, "NOTIMP");
1243  break;
1244  case DNS_RCODE_REFUSED:
1245  snprintf(str, str_size, "REFUSED");
1246  break;
1247  case DNS_RCODE_YXDOMAIN:
1248  snprintf(str, str_size, "YXDOMAIN");
1249  break;
1250  case DNS_RCODE_YXRRSET:
1251  snprintf(str, str_size, "YXRRSET");
1252  break;
1253  case DNS_RCODE_NXRRSET:
1254  snprintf(str, str_size, "NXRRSET");
1255  break;
1256  case DNS_RCODE_NOTAUTH:
1257  snprintf(str, str_size, "NOTAUTH");
1258  break;
1259  case DNS_RCODE_NOTZONE:
1260  snprintf(str, str_size, "NOTZONE");
1261  break;
1262  /* these are the same, need more logic */
1263  case DNS_RCODE_BADVERS:
1264  //case DNS_RCODE_BADSIG:
1265  snprintf(str, str_size, "BADVERS/BADSIG");
1266  break;
1267  case DNS_RCODE_BADKEY:
1268  snprintf(str, str_size, "BADKEY");
1269  break;
1270  case DNS_RCODE_BADTIME:
1271  snprintf(str, str_size, "BADTIME");
1272  break;
1273  case DNS_RCODE_BADMODE:
1274  snprintf(str, str_size, "BADMODE");
1275  break;
1276  case DNS_RCODE_BADNAME:
1277  snprintf(str, str_size, "BADNAME");
1278  break;
1279  case DNS_RCODE_BADALG:
1280  snprintf(str, str_size, "BADALG");
1281  break;
1282  case DNS_RCODE_BADTRUNC:
1283  snprintf(str, str_size, "BADTRUNC");
1284  break;
1285  default:
1286  SCLogDebug("could not map DNS rcode to name, bug!");
1287  snprintf(str, str_size, "%04x/%u", rcode, rcode);
1288  }
1289 }
#define DNS_RECORD_TYPE_NSEC
#define DNS_RCODE_YXDOMAIN
enum AppLayerEventType_ AppLayerEventType
uint16_t flags
#define SCMemcmp(a, b, c)
Definition: util-memcmp.h:490
void DNSIncrMemcap(uint32_t size, DNSState *state)
DnsListEnum
List types in the TX. Used when storing answers from "Answer" or "Authority".
int DNSStateGetEventInfo(const char *event_name, int *event_id, AppLayerEventType *event_type)
#define DNS_RECORD_TYPE_ATMA
#define DNS_RECORD_TYPE_AFSDB
#define SCLogDebug(...)
Definition: util-debug.h:335
int DNSGetAlstateProgressCompletionStatus(uint8_t direction)
get value for &#39;complete&#39; status in DNS
#define DNS_RCODE_YXRRSET
#define TAILQ_FIRST(head)
Definition: queue.h:339
AppLayerDecoderEvents * DNSGetEvents(void *state, uint64_t id)
void DNSConfigSetRequestFlood(uint32_t value)
#define DNS_RECORD_TYPE_MF
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:350
struct HtpBodyChunk_ * next
uint64_t DNSGetTxDetectFlags(void *vtx, uint8_t dir)
#define BUG_ON(x)
uint32_t event_type
Per flow DNS state container.
#define FALSE
void DNSConfigSetStateMemcap(uint32_t value)
LoggerId
int logged
#define DNS_RECORD_TYPE_NSEC3
#define DNS_RECORD_TYPE_LOC
#define unlikely(expr)
Definition: util-optimize.h:35
#define DNS_RCODE_NOTIMP
void DNSSetTxDetectFlags(void *vtx, uint8_t dir, uint64_t detect_flags)
void * DNSStateAlloc(void)
#define DNS_RECORD_TYPE_KEY
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)
#define DNS_RCODE_SERVFAIL
#define DNS_RECORD_TYPE_SPF
LoggerId DNSGetTxLogged(void *alstate, void *tx)
#define DNS_RECORD_TYPE_DS
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:108
DNS Transaction, request/reply with same TX id.
uint64_t offset
#define DNS_RCODE_NXDOMAIN
#define SCReturnUInt(x)
Definition: util-debug.h:343
void AppLayerDecoderEventsSetEventRaw(AppLayerDecoderEvents **sevents, uint8_t event)
Set an app layer decoder event.
void DNSCreateRcodeString(uint8_t rcode, char *str, size_t str_size)
#define DNS_RECORD_TYPE_RT
uint64_t DNSMemcapGetMemcapStateCounter(void)
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:125
int SCMapEnumNameToValue(const char *enum_name, SCEnumCharMap *table)
Maps a string name to an enum value from the supplied table. Please specify the last element of any m...
Definition: util-enum.c:41
#define DNS_RCODE_BADKEY
uint16_t AppProto
Flow * head
Definition: flow-hash.h:102
#define DNS_RECORD_TYPE_TLSA
uint64_t global_memcap
#define DNS_RECORD_TYPE_NSEC3PARAM
DNS Answer storage. Stored in TX list.
#define TRUE
uint64_t DNSMemcapGetMemcapGlobalCounter(void)
#define DNS_RCODE_FORMERR
void DNSDecrMemcap(uint32_t size, DNSState *state)
#define DNS_RCODE_BADVERS
int DNSCheckMemcap(uint32_t want, DNSState *state)
#define DNS_RECORD_TYPE_NXT
void DNSConfigInit(void)
DNSTransaction * DNSTransactionFindByTxId(const DNSState *dns_state, const uint16_t tx_id)
#define DNS_RCODE_BADMODE
#define DNS_RECORD_TYPE_APL
#define SC_ATOMIC_INIT(name)
Initialize the previously declared atomic variable and it&#39;s lock.
Definition: util-atomic.h:82
DNS Query storage. Stored in TX list.
#define DNS_RECORD_TYPE_ISDN
#define str(s)
Data structure to store app layer decoder events.
void DNSStoreAnswerInState(DNSState *dns_state, const int rtype, const uint8_t *fqdn, const uint16_t fqdn_len, const uint16_t type, const uint16_t class, const uint16_t ttl, const uint8_t *data, const uint16_t data_len, const uint16_t tx_id)
#define DNS_MAX_SIZE
uint16_t type
#define DNS_RCODE_NOTAUTH
#define TAILQ_INIT(head)
Definition: queue.h:370
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfo)(const char *event_name, int *event_id, AppLayerEventType *event_type))
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define DNS_RECORD_TYPE_A
#define DNS_RECORD_TYPE_TSIG
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:412
#define SCEnter(...)
Definition: util-debug.h:337
#define DNS_RCODE_REFUSED
#define DNS_RECORD_TYPE_MG
DNSTransaction * curr
DetectEngineState * DNSGetTxDetectState(void *vtx)
uint32_t unreplied_cnt
#define STREAM_TOCLIENT
Definition: stream.h:32
void DNSSetEvent(DNSState *s, uint8_t e)
#define DNS_RECORD_TYPE_DNAME
#define DNS_RECORD_TYPE_CDNSKEY
void DNSConfigSetGlobalMemcap(uint64_t value)
uint64_t DNSGetTxCnt(void *alstate)
#define DNS_RECORD_TYPE_NSAP
#define DNS_RECORD_TYPE_SRV
DNSTransaction * iter
void DetectEngineStateFree(DetectEngineState *state)
Frees a DetectEngineState object.
#define DNS_RECORD_TYPE_MB
#define DNS_RECORD_TYPE_KX
int DNSValidateRequestHeader(DNSState *dns_state, const DNSHeader *dns_header)
Validation checks for DNS request header.
#define DNS_RECORD_TYPE_X25
uint32_t ttl
#define SCNtohl(x)
#define DNS_RECORD_TYPE_PTR
#define DNS_RECORD_TYPE_AAAA
#define DNS_RECORD_TYPE_CNAME
struct DNSAnswerHeader_ DNSAnswerHeader
AppLayerDecoderEvents * decoder_events
SCEnumCharMap dns_decoder_event_table[]
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:385
#define DNS_RECORD_TYPE_RP
DNS answer header packed as we don&#39;t want alignment to mess up sizeof()
void * DNSGetTx(void *alstate, uint64_t tx_id)
#define DNS_RECORD_TYPE_WKS
void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events)
#define DNS_RECORD_TYPE_NSAPPTR
void DNSStateFree(void *s)
#define DNS_RECORD_TYPE_CERT
#define SCMalloc(a)
Definition: util-mem.h:174
#define DNS_RECORD_TYPE_OPT
#define DNS_RECORD_TYPE_RRSIG
DetectEngineState * de_state
Flow * tail
Definition: flow-hash.h:103
#define DNS_RECORD_TYPE_SIG
#define DNS_RECORD_TYPE_IPSECKEY
#define DNS_RECORD_TYPE_NULL
uint32_t state_memcap
#define DNS_RECORD_TYPE_MX
#define SCFree(a)
Definition: util-mem.h:236
#define SCNtohs(x)
#define DNS_RCODE_BADALG
#define DNS_RECORD_TYPE_A6
#define DNS_RECORD_TYPE_CDS
#define DNS_RCODE_BADTRUNC
int DNSValidateResponseHeader(DNSState *dns_state, const DNSHeader *dns_header)
Validation checks for DNS response header.
uint16_t tx_id
struct DNSConfig_ DNSConfig
#define DNS_RECORD_TYPE_ANY
#define DNS_RECORD_TYPE_GPOS
#define DNS_RECORD_TYPE_MR
uint32_t request_flood
#define DNS_RECORD_TYPE_HINFO
#define DNS_RECORD_TYPE_MD
#define DNS_RECORD_TYPE_NAPTR
#define STREAM_TOSERVER
Definition: stream.h:31
#define DNS_RECORD_TYPE_TXT
#define DNS_RECORD_TYPE_MAILA
#define DNS_RCODE_BADNAME
#define DNS_RECORD_TYPE_DHCID
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:193
#define DNS_RCODE_BADTIME
#define DNS_RECORD_TYPE_NS
#define DNS_RCODE_NXRRSET
uint16_t length
#define DNS_RECORD_TYPE_TKEY
#define DNS_RECORD_TYPE_HIP
#define DNS_RECORD_TYPE_SOA
int DNSGetAlstateProgress(void *tx, uint8_t direction)
#define TAILQ_NEXT(elm, field)
Definition: queue.h:341
#define SCReturn
Definition: util-debug.h:339
void DNSStateTransactionFree(void *state, uint64_t tx_id)
dns transaction cleanup callback
SC_ATOMIC_DECLARE(uint64_t, dns_memuse)
#define DNS_RCODE_NOERROR
#define DNS_RECORD_TYPE_DNSKEY
const uint8_t * DNSReponseParse(DNSState *dns_state, const DNSHeader *const dns_header, const uint16_t num, const DnsListEnum list, const uint8_t *const input, const uint32_t input_len, const uint8_t *data)
uint64_t DNSMemcapGetMemuseCounter(void)
void DNSSetTxLogged(void *alstate, void *tx, LoggerId logged)
#define DNS_RECORD_TYPE_URI
#define DNS_RECORD_TYPE_PX
uint64_t transaction_max
int DNSSetTxDetectState(void *vtx, DetectEngineState *s)
#define DNS_RECORD_TYPE_MINFO
#define DNS_RCODE_NOTZONE
void DNSCreateTypeString(uint16_t type, char *str, size_t str_size)
void DNSAppLayerRegisterGetEventInfo(uint8_t ipproto, AppProto alproto)
#define DNS_RECORD_TYPE_SSHFP