suricata
app-layer-dns-udp.c
Go to the documentation of this file.
1 /* Copyright (C) 2013 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  * \author Victor Julien <victor@inliniac.net>
21  */
22 
23 #include "suricata-common.h"
24 #include "suricata.h"
25 
26 #include "conf.h"
27 #include "util-misc.h"
28 
29 #include "debug.h"
30 #include "decode.h"
31 
32 #include "flow-util.h"
33 
34 #include "threads.h"
35 
36 #include "util-print.h"
37 #include "util-pool.h"
38 #include "util-debug.h"
39 
40 #include "stream-tcp-private.h"
41 #include "stream-tcp-reassemble.h"
42 #include "stream-tcp.h"
43 #include "stream.h"
44 
45 #include "app-layer-protos.h"
46 #include "app-layer-parser.h"
47 
48 #include "util-spm.h"
49 #include "util-unittest.h"
50 
51 #include "app-layer-dns-udp.h"
52 
53 #ifdef HAVE_RUST
54 #include "app-layer-dns-udp-rust.h"
55 #endif
56 
57 #ifndef HAVE_RUST
58 /** \internal
59  * \brief Parse DNS request packet
60  */
61 static int DNSUDPRequestParse(Flow *f, void *dstate,
62  AppLayerParserState *pstate,
63  uint8_t *input, uint32_t input_len,
64  void *local_data, const uint8_t flags)
65 {
66  DNSState *dns_state = (DNSState *)dstate;
67 
68  SCLogDebug("starting %u", input_len);
69 
70  if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
71  SCReturnInt(1);
72  }
73 
74  /** \todo remove this when PP is fixed to enforce ipproto */
75  if (f != NULL && f->proto != IPPROTO_UDP)
76  SCReturnInt(-1);
77 
78  if (input == NULL || input_len == 0 || input_len < sizeof(DNSHeader)) {
79  SCLogDebug("ilen too small, hoped for at least %"PRIuMAX, (uintmax_t)sizeof(DNSHeader));
80  goto insufficient_data;
81  }
82 
83  DNSHeader *dns_header = (DNSHeader *)input;
84  SCLogDebug("DNS %p", dns_header);
85 
86  if (DNSValidateRequestHeader(dns_state, dns_header) < 0)
87  goto bad_data;
88 
89  if (dns_state != NULL) {
90  if (timercmp(&dns_state->last_req, &dns_state->last_resp, >=)) {
91  if (dns_state->window <= dns_state->unreplied_cnt) {
92  dns_state->window++;
93  }
94  }
95  }
96 
97  uint16_t q;
98  const uint8_t *data = input + sizeof(DNSHeader);
99  for (q = 0; q < SCNtohs(dns_header->questions); q++) {
100  uint8_t fqdn[DNS_MAX_SIZE];
101  uint16_t fqdn_offset = 0;
102 
103  if (input + input_len < data + 1) {
104  SCLogDebug("input buffer too small for len");
105  goto insufficient_data;
106  }
107  SCLogDebug("query length %u", *data);
108 
109  while (*data != 0) {
110  if (*data > 63) {
111  /** \todo set event?*/
112  goto insufficient_data;
113  }
114  uint8_t length = *data;
115 
116  data++;
117 
118  if (length == 0) {
119  break;
120  }
121 
122  if (input + input_len < data + length) {
123  SCLogDebug("input buffer too small for domain of len %u", length);
124  goto insufficient_data;
125  }
126  //PrintRawDataFp(stdout, data, qry->length);
127 
128  if ((size_t)(fqdn_offset + length + 1) < sizeof(fqdn)) {
129  memcpy(fqdn + fqdn_offset, data, length);
130  fqdn_offset += length;
131  fqdn[fqdn_offset++] = '.';
132  } else {
133  /** \todo set event? */
134  goto insufficient_data;
135  }
136 
137  data += length;
138 
139  if (input + input_len < data + 1) {
140  SCLogDebug("input buffer too small for len(2)");
141  goto insufficient_data;
142  }
143 
144  SCLogDebug("qry length %u", *data);
145  }
146  if (fqdn_offset) {
147  fqdn_offset--;
148  }
149 
150  data++;
151  if (input + input_len < data + sizeof(DNSQueryTrailer)) {
152  SCLogDebug("input buffer too small for DNSQueryTrailer");
153  goto insufficient_data;
154  }
155  DNSQueryTrailer *trailer = (DNSQueryTrailer *)data;
156  SCLogDebug("trailer type %04x class %04x", SCNtohs(trailer->type), SCNtohs(trailer->class));
157  data += sizeof(DNSQueryTrailer);
158 
159  /* store our data */
160  if (dns_state != NULL) {
161  DNSStoreQueryInState(dns_state, fqdn, fqdn_offset,
162  SCNtohs(trailer->type), SCNtohs(trailer->class),
163  SCNtohs(dns_header->tx_id));
164  }
165  }
166 
167  if (dns_state != NULL && f != NULL) {
168  dns_state->last_req = f->lastts;
169  }
170 
171  SCReturnInt(1);
172 bad_data:
173 insufficient_data:
174  SCReturnInt(-1);
175 }
176 
177 /** \internal
178  * \brief DNS UDP record parser, entry function
179  *
180  * Parses a DNS UDP record and fills the DNS state
181  *
182  */
183 static int DNSUDPResponseParse(Flow *f, void *dstate,
184  AppLayerParserState *pstate,
185  uint8_t *input, uint32_t input_len,
186  void *local_data, const uint8_t flags)
187 {
188  DNSState *dns_state = (DNSState *)dstate;
189 
190  SCLogDebug("starting %u", input_len);
191 
192  if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
193  SCReturnInt(1);
194  }
195 
196  /** \todo remove this when PP is fixed to enforce ipproto */
197  if (f != NULL && f->proto != IPPROTO_UDP)
198  SCReturnInt(-1);
199 
200  if (input == NULL || input_len == 0 || input_len < sizeof(DNSHeader)) {
201  SCLogDebug("ilen too small, hoped for at least %"PRIuMAX, (uintmax_t)sizeof(DNSHeader));
202  goto insufficient_data;
203  }
204 
205  DNSHeader *dns_header = (DNSHeader *)input;
206  SCLogDebug("DNS %p %04x %04x", dns_header, SCNtohs(dns_header->tx_id), dns_header->flags);
207 
208  DNSTransaction *tx = NULL;
209  int found = 0;
210  if ((tx = DNSTransactionFindByTxId(dns_state, SCNtohs(dns_header->tx_id))) != NULL)
211  found = 1;
212 
213  if (!found) {
214  SCLogDebug("DNS_DECODER_EVENT_UNSOLLICITED_RESPONSE");
216  } else if (dns_state->unreplied_cnt > 0) {
217  dns_state->unreplied_cnt--;
218  }
219 
220  if (DNSValidateResponseHeader(dns_state, dns_header) < 0)
221  goto bad_data;
222 
223  SCLogDebug("queries %04x", SCNtohs(dns_header->questions));
224 
225  uint16_t q;
226  const uint8_t *data = input + sizeof(DNSHeader);
227  for (q = 0; q < SCNtohs(dns_header->questions); q++) {
228  uint8_t fqdn[DNS_MAX_SIZE];
229  uint16_t fqdn_offset = 0;
230 
231  if (input + input_len < data + 1) {
232  SCLogDebug("input buffer too small for len");
233  goto insufficient_data;
234  }
235  SCLogDebug("qry length %u", *data);
236 
237  while (*data != 0) {
238  uint8_t length = *data;
239  data++;
240 
241  if (length == 0)
242  break;
243 
244  if (input + input_len < data + length) {
245  SCLogDebug("input buffer too small for domain of len %u", length);
246  goto insufficient_data;
247  }
248  //PrintRawDataFp(stdout, data, length);
249 
250  if ((size_t)(fqdn_offset + length + 1) < sizeof(fqdn)) {
251  memcpy(fqdn + fqdn_offset, data, length);
252  fqdn_offset += length;
253  fqdn[fqdn_offset++] = '.';
254  }
255 
256  data += length;
257 
258  if (input + input_len < data + 1) {
259  SCLogDebug("input buffer too small for len");
260  goto insufficient_data;
261  }
262 
263  SCLogDebug("length %u", *data);
264  }
265  if (fqdn_offset) {
266  fqdn_offset--;
267  }
268 
269  data++;
270  if (input + input_len < data + sizeof(DNSQueryTrailer)) {
271  SCLogDebug("input buffer too small for DNSQueryTrailer");
272  goto insufficient_data;
273  }
274 #if DEBUG
275  DNSQueryTrailer *trailer = (DNSQueryTrailer *)data;
276  SCLogDebug("trailer type %04x class %04x", SCNtohs(trailer->type), SCNtohs(trailer->class));
277 #endif
278  data += sizeof(DNSQueryTrailer);
279  }
280 
281  SCLogDebug("answer_rr %04x", SCNtohs(dns_header->answer_rr));
282  for (q = 0; q < SCNtohs(dns_header->answer_rr); q++) {
283  data = DNSReponseParse(dns_state, dns_header, q, DNS_LIST_ANSWER,
284  input, input_len, data);
285  if (data == NULL) {
286  goto insufficient_data;
287  }
288  }
289 
290  SCLogDebug("authority_rr %04x", SCNtohs(dns_header->authority_rr));
291  for (q = 0; q < SCNtohs(dns_header->authority_rr); q++) {
292  data = DNSReponseParse(dns_state, dns_header, q, DNS_LIST_AUTHORITY,
293  input, input_len, data);
294  if (data == NULL) {
295  goto insufficient_data;
296  }
297  }
298 
299  /* if we previously didn't have a tx, it could have been created by the
300  * above code, so lets check again */
301  if (tx == NULL) {
302  tx = DNSTransactionFindByTxId(dns_state, SCNtohs(dns_header->tx_id));
303  }
304  if (tx != NULL) {
305  /* parse rcode, e.g. "noerror" or "nxdomain" */
306  uint8_t rcode = SCNtohs(dns_header->flags) & 0x0F;
307  if (rcode <= DNS_RCODE_NOTZONE) {
308  SCLogDebug("rcode %u", rcode);
309  tx->rcode = rcode;
310  } else {
311  /* this is not invalid, rcodes can be user defined */
312  SCLogDebug("unexpected DNS rcode %u", rcode);
313  }
314 
315  if (SCNtohs(dns_header->flags) & 0x0080) {
316  SCLogDebug("recursion desired");
317  tx->recursion_desired = 1;
318  }
319 
320  tx->flags = ntohs(dns_header->flags);
321  tx->replied = 1;
322  }
323  if (f != NULL) {
324  dns_state->last_resp = f->lastts;
325  }
326  SCReturnInt(1);
327 
328 bad_data:
329 insufficient_data:
331  SCReturnInt(-1);
332 }
333 
334 static uint16_t DNSUdpProbingParser(Flow *f, uint8_t *input, uint32_t ilen)
335 {
336  if (ilen == 0 || ilen < sizeof(DNSHeader)) {
337  SCLogDebug("ilen too small, hoped for at least %"PRIuMAX, (uintmax_t)sizeof(DNSHeader));
338  return ALPROTO_UNKNOWN;
339  }
340 
341  if (DNSUDPRequestParse(NULL, NULL, NULL, input, ilen, NULL, 0) == -1)
342  return ALPROTO_FAILED;
343 
344  return ALPROTO_DNS;
345 }
346 
347 static void DNSUDPConfigure(void)
348 {
349  uint32_t request_flood = DNS_CONFIG_DEFAULT_REQUEST_FLOOD;
350  uint32_t state_memcap = DNS_CONFIG_DEFAULT_STATE_MEMCAP;
351  uint64_t global_memcap = DNS_CONFIG_DEFAULT_GLOBAL_MEMCAP;
352 
353  ConfNode *p = ConfGetNode("app-layer.protocols.dns.request-flood");
354  if (p != NULL) {
355  uint32_t value;
356  if (ParseSizeStringU32(p->val, &value) < 0) {
357  SCLogError(SC_ERR_DNS_CONFIG, "invalid value for request-flood %s", p->val);
358  } else {
359  request_flood = value;
360  }
361  }
362  SCLogConfig("DNS request flood protection level: %u", request_flood);
363  DNSConfigSetRequestFlood(request_flood);
364 
365  p = ConfGetNode("app-layer.protocols.dns.state-memcap");
366  if (p != NULL) {
367  uint32_t value;
368  if (ParseSizeStringU32(p->val, &value) < 0) {
369  SCLogError(SC_ERR_DNS_CONFIG, "invalid value for state-memcap %s", p->val);
370  } else {
371  state_memcap = value;
372  }
373  }
374  SCLogConfig("DNS per flow memcap (state-memcap): %u", state_memcap);
375  DNSConfigSetStateMemcap(state_memcap);
376 
377  p = ConfGetNode("app-layer.protocols.dns.global-memcap");
378  if (p != NULL) {
379  uint64_t value;
380  if (ParseSizeStringU64(p->val, &value) < 0) {
381  SCLogError(SC_ERR_DNS_CONFIG, "invalid value for global-memcap %s", p->val);
382  } else {
383  global_memcap = value;
384  }
385  }
386  SCLogConfig("DNS global memcap: %"PRIu64, global_memcap);
387  DNSConfigSetGlobalMemcap(global_memcap);
388 }
389 #endif /* HAVE_RUST */
390 
392 {
393 #ifdef HAVE_RUST
394  return RegisterRustDNSUDPParsers();
395 #else
396  const char *proto_name = "dns";
397  /** DNS */
398  if (AppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name)) {
400 
401  if (RunmodeIsUnittests()) {
402  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
403  "53",
404  ALPROTO_DNS,
405  0, sizeof(DNSHeader),
407  DNSUdpProbingParser,
408  NULL);
409  } else {
410  int have_cfg = AppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP,
411  proto_name, ALPROTO_DNS,
412  0, sizeof(DNSHeader),
413  DNSUdpProbingParser, NULL);
414  /* if we have no config, we enable the default port 53 */
415  if (!have_cfg) {
416 #ifndef AFLFUZZ_APPLAYER
417  SCLogWarning(SC_ERR_DNS_CONFIG, "no DNS UDP config found, "
418  "enabling DNS detection on "
419  "port 53.");
420 #endif
421  AppLayerProtoDetectPPRegister(IPPROTO_UDP, "53",
422  ALPROTO_DNS, 0, sizeof(DNSHeader),
423  STREAM_TOSERVER, DNSUdpProbingParser, NULL);
424  }
425  }
426  } else {
427  SCLogInfo("Protocol detection and parser disabled for %s protocol.",
428  proto_name);
429  return;
430  }
431 
432  if (AppLayerParserConfParserEnabled("udp", proto_name)) {
434  DNSUDPRequestParse);
436  DNSUDPResponseParse);
438  DNSStateFree);
441 
447 
449  DNSGetTx);
451  DNSGetTxCnt);
458 
460 
461  DNSUDPConfigure();
462  } else {
463  SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
464  "still on.", proto_name);
465  }
466 #ifdef UNITTESTS
468 #endif
469 #endif /* HAVE_RUST */
470 }
471 
472 /* UNITTESTS */
473 #ifndef HAVE_RUST
474 #ifdef UNITTESTS
475 #include "util-unittest-helper.h"
476 
477 static int DNSUDPParserTest01 (void)
478 {
479  /* query: abcdefghijk.com
480  * TTL: 86400
481  * serial 20130422 refresh 28800 retry 7200 exp 604800 min ttl 86400
482  * ns, hostmaster */
483  uint8_t buf[] = { 0x00, 0x3c, 0x85, 0x00, 0x00, 0x01, 0x00, 0x00,
484  0x00, 0x01, 0x00, 0x00, 0x0b, 0x61, 0x62, 0x63,
485  0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
486  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x0f, 0x00,
487  0x01, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01,
488  0x51, 0x80, 0x00, 0x25, 0x02, 0x6e, 0x73, 0x00,
489  0x0a, 0x68, 0x6f, 0x73, 0x74, 0x6d, 0x61, 0x73,
490  0x74, 0x65, 0x72, 0xc0, 0x2f, 0x01, 0x33, 0x2a,
491  0x76, 0x00, 0x00, 0x70, 0x80, 0x00, 0x00, 0x1c,
492  0x20, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01, 0x51,
493  0x80};
494  size_t buflen = sizeof(buf);
495  Flow *f = NULL;
496 
497  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
498  FAIL_IF_NULL(f);
499  f->proto = IPPROTO_UDP;
500  f->alproto = ALPROTO_DNS;
501  f->alstate = DNSStateAlloc();
502 
503  FAIL_IF_NOT(DNSUDPResponseParse(f, f->alstate, NULL, buf, buflen, NULL, STREAM_START));
504 
505  UTHFreeFlow(f);
506  PASS;
507 }
508 
509 static int DNSUDPParserTest02 (void)
510 {
511  uint8_t buf[] = {
512  0x6D,0x08,0x84,0x80,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x01,0x03,0x57,0x57,0x57,
513  0x04,0x54,0x54,0x54,0x54,0x03,0x56,0x56,0x56,0x03,0x63,0x6F,0x6D,0x02,0x79,0x79,
514  0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,
515  0x02,0xC0,0x0C,0xC0,0x31,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,
516  0x31,0xC0,0x3F,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x3F,0xC0,
517  0x4D,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x4D,0xC0,0x5B,0x00,
518  0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x5B,0xC0,0x69,0x00,0x05,0x00,
519  0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x69,0xC0,0x77,0x00,0x05,0x00,0x01,0x00,
520  0x00,0x0E,0x10,0x00,0x02,0xC0,0x77,0xC0,0x85,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,
521  0x10,0x00,0x02,0xC0,0x85,0x00,0x00,0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
522  };
523  size_t buflen = sizeof(buf);
524  Flow *f = NULL;
525 
526  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
527  FAIL_IF_NULL(f);
528  f->proto = IPPROTO_UDP;
529  f->alproto = ALPROTO_DNS;
530  f->alstate = DNSStateAlloc();
531 
532  FAIL_IF_NOT(DNSUDPResponseParse(f, f->alstate, NULL, buf, buflen, NULL, STREAM_START));
533 
534  UTHFreeFlow(f);
535  PASS;
536 }
537 
538 static int DNSUDPParserTest03 (void)
539 {
540  uint8_t buf[] = {
541  0x6F,0xB4,0x84,0x80,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x03,0x03,0x57,0x57,0x77,
542  0x0B,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x03,0x55,0x55,0x55,
543  0x02,0x79,0x79,0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,
544  0x0E,0x10,0x00,0x02,0xC0,0x10,0xC0,0x34,0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,
545  0x00,0x04,0xC3,0xEA,0x04,0x19,0xC0,0x34,0x00,0x02,0x00,0x01,0x00,0x00,0x0E,0x10,
546  0x00,0x0A,0x03,0x6E,0x73,0x31,0x03,0x61,0x67,0x62,0xC0,0x20,0xC0,0x46,0x00,0x02,
547  0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x06,0x03,0x6E,0x73,0x32,0xC0,0x56,0xC0,0x52,
548  0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x04,0x0A,0xC0,0x68,
549  0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x05,0x14,0x00,0x00,
550  0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00
551  };
552  size_t buflen = sizeof(buf);
553  Flow *f = NULL;
554 
555  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
556  FAIL_IF_NULL(f);
557  f->proto = IPPROTO_UDP;
558  f->alproto = ALPROTO_DNS;
559  f->alstate = DNSStateAlloc();
560 
561  FAIL_IF_NOT(DNSUDPResponseParse(f, f->alstate, NULL, buf, buflen, NULL, STREAM_START));
562 
563  UTHFreeFlow(f);
564  PASS;
565 }
566 
567 /** \test TXT records in answer */
568 static int DNSUDPParserTest04 (void)
569 {
570  uint8_t buf[] = {
571  0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
572  0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
573  0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
574  0x01,
575  /* answer record start */
576  0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
577  /* txt record starts: */
578  0x20, /* <txt len 32 */ 0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
579  0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
580  0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */ 0xc0,0x1d,0x00,0x02,0x00,0x01,
581  0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
582  0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
583  };
584  size_t buflen = sizeof(buf);
585  Flow *f = NULL;
586 
587  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
588  FAIL_IF_NULL(f);
589  f->proto = IPPROTO_UDP;
590  f->alproto = ALPROTO_DNS;
591  f->alstate = DNSStateAlloc();
592 
593  FAIL_IF_NOT(DNSUDPResponseParse(f, f->alstate, NULL, buf, buflen, NULL, STREAM_START));
594 
595  UTHFreeFlow(f);
596  PASS;
597 }
598 
599 /** \test TXT records in answer, bad txtlen */
600 static int DNSUDPParserTest05 (void)
601 {
602  uint8_t buf[] = {
603  0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
604  0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
605  0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
606  0x01,
607  /* answer record start */
608  0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
609  /* txt record starts: */
610  0x40, /* <txt len 64 */ 0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
611  0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
612  0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */ 0xc0,0x1d,0x00,0x02,0x00,0x01,
613  0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
614  0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
615  };
616  size_t buflen = sizeof(buf);
617  Flow *f = NULL;
618 
619  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
620  FAIL_IF_NULL(f);
621  f->proto = IPPROTO_UDP;
622  f->alproto = ALPROTO_DNS;
623  f->alstate = DNSStateAlloc();
624 
625  FAIL_IF(DNSUDPResponseParse(f, f->alstate, NULL, buf, buflen, NULL, STREAM_START) != -1);
626 
627  UTHFreeFlow(f);
628  PASS;
629 }
630 
631 /**
632  * \test Test subsequent requests before response.
633  *
634  * This test sends 2 DNS requests on the same state then sends the response
635  * to the first request checking that it is seen and associated with the
636  * transaction.
637  */
638 static int DNSUDPParserTestDelayedResponse(void)
639 {
640  /* DNS request:
641  * - Flags: 0x0100 Standard query
642  * - A www.google.com
643  */
644  uint8_t req[] = {
645  0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
646  0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77,
647  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
648  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
649  };
650  size_t reqlen = sizeof(req);
651 
652  /* DNS response:
653  * - Flags: 0x8180 Standard query response, no error
654  * - www.google.com A 24.244.4.56
655  * - www.google.com A 24.244.4.54
656  * - www.google.com A 24.244.4.57
657  * - www.google.com A 24.244.4.55
658  * - www.google.com A 24.244.4.52
659  * - www.google.com A 24.244.4.53
660  * - www.google.com A 24.244.4.58
661  * - www.google.com A 24.244.4.59
662  */
663  uint8_t res[] = {
664  0x00, 0x01, 0x81, 0x80, 0x00, 0x01, 0x00, 0x08,
665  0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77,
666  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
667  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
668  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
669  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x38,
670  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
671  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x39,
672  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
673  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x34,
674  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
675  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x35,
676  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
677  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x36,
678  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
679  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x3b,
680  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
681  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x37,
682  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
683  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x3a
684  };
685  size_t reslen = sizeof(res);
686 
687  DNSState *state = DNSStateAlloc();
688  FAIL_IF_NULL(state);
689  Flow *f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 53);
690  FAIL_IF_NULL(f);
691  f->proto = IPPROTO_UDP;
692  f->alproto = ALPROTO_DNS;
693  f->alstate = state;
694 
695  /* Send two requests with an incrementing tx id. */
696  FAIL_IF_NOT(DNSUDPRequestParse(f, f->alstate, NULL, req, reqlen, NULL, STREAM_START));
697  req[1] = 0x02;
698  FAIL_IF_NOT(DNSUDPRequestParse(f, f->alstate, NULL, req, reqlen, NULL, 0));
699 
700  /* Send response to the first request. */
701  FAIL_IF_NOT(DNSUDPResponseParse(f, f->alstate, NULL, res, reslen, NULL, STREAM_START));
702  DNSTransaction *tx = TAILQ_FIRST(&state->tx_list);
703  FAIL_IF_NULL(tx);
704  FAIL_IF_NOT(tx->replied);
705 
706  /* Also free's state. */
707  UTHFreeFlow(f);
708 
709  PASS;
710 }
711 
712 /**
713  * \test Test entering the flood/givenup state.
714  */
715 static int DNSUDPParserTestFlood(void)
716 {
717  /* DNS request:
718  * - Flags: 0x0100 Standard query
719  * - A www.google.com
720  */
721  uint8_t req[] = {
722  0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
723  0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77,
724  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
725  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
726  };
727  size_t reqlen = sizeof(req);
728 
729  DNSState *state = DNSStateAlloc();
730  FAIL_IF_NULL(state);
731  Flow *f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 53);
732  FAIL_IF_NULL(f);
733  f->proto = IPPROTO_UDP;
734  f->alproto = ALPROTO_DNS;
735  f->alstate = state;
736 
737  uint8_t flags = STREAM_START;
738  uint16_t txid;
739  for (txid = 1; txid <= DNS_CONFIG_DEFAULT_REQUEST_FLOOD + 1; txid++) {
740  req[0] = (txid >> 8) & 0xff;
741  req[1] = txid & 0xff;
742  FAIL_IF_NOT(DNSUDPRequestParse(f, f->alstate, NULL, req, reqlen, NULL, flags));
743  FAIL_IF(state->givenup);
744  flags = 0;
745  }
746 
747  /* With one more request we should enter a flooded state. */
748  txid++;
749  req[0] = (txid >> 8) & 0xff;
750  req[1] = txid & 0xff;
751  FAIL_IF_NOT(DNSUDPRequestParse(f, f->alstate, NULL, req, reqlen, NULL, 0));
752  FAIL_IF(!state->givenup);
753 
754  /* Also free's state. */
755  UTHFreeFlow(f);
756 
757  PASS;
758 }
759 
760 static int DNSUDPParserTestLostResponse(void)
761 {
762  /* DNS request:
763  * - Flags: 0x0100 Standard query
764  * - A www.google.com
765  */
766  uint8_t req[] = {
767  0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
768  0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77,
769  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
770  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
771  };
772  size_t reqlen = sizeof(req);
773 
774  uint8_t res[] = {
775  0x00, 0x01, 0x81, 0x80, 0x00, 0x01, 0x00, 0x08,
776  0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77,
777  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
778  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
779  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
780  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x38,
781  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
782  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x39,
783  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
784  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x34,
785  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
786  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x35,
787  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
788  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x36,
789  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
790  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x3b,
791  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
792  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x37,
793  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
794  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x3a
795  };
796  size_t reslen = sizeof(res);
797 
798  DNSTransaction *tx;
799  DNSState *state = DNSStateAlloc();
800  FAIL_IF_NULL(state);
801  Flow *f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 53);
802  FAIL_IF_NULL(f);
803  f->proto = IPPROTO_UDP;
804  f->alproto = ALPROTO_DNS;
805  f->alstate = state;
806 
807  /* First request. */
808  req[1] = 0x01;
809  FAIL_IF_NOT(DNSUDPRequestParse(f, f->alstate, NULL, req, reqlen, NULL, STREAM_START));
810  FAIL_IF_NOT(state->transaction_max == 1);
811  FAIL_IF_NOT(state->unreplied_cnt == 1);
812  FAIL_IF_NOT(state->window == 1);
813 
814  /* Second request. */
815  req[1] = 0x02;
816  FAIL_IF_NOT(DNSUDPRequestParse(f, f->alstate, NULL, req, reqlen, NULL, 0));
817  FAIL_IF_NOT(state->transaction_max == 2);
818  FAIL_IF_NOT(state->unreplied_cnt == 2);
819  FAIL_IF_NOT(state->window == 2);
820 
821  /* Third request. */
822  req[1] = 0x03;
823  FAIL_IF_NOT(DNSUDPRequestParse(f, f->alstate, NULL, req, reqlen, NULL, 0));
824  FAIL_IF_NOT(state->transaction_max == 3);
825  FAIL_IF_NOT(state->unreplied_cnt == 3);
826  FAIL_IF_NOT(state->window == 3);
827 
828  /* Now respond to the second. */
829  res[1] = 0x02;
830  FAIL_IF_NOT(DNSUDPResponseParse(f, f->alstate, NULL, res, reslen, NULL, 0));
831  FAIL_IF_NOT(state->unreplied_cnt == 2);
832  FAIL_IF_NOT(state->window == 3);
833  tx = TAILQ_FIRST(&state->tx_list);
834  FAIL_IF_NULL(tx);
835  FAIL_IF(tx->replied);
836  FAIL_IF(tx->reply_lost);
837 
838  /* Send a 4th request. */
839  req[1] = 0x04;
840  FAIL_IF_NOT(DNSUDPRequestParse(f, f->alstate, NULL, req, reqlen, NULL, 0));
841  FAIL_IF_NOT(state->unreplied_cnt == 3);
842  FAIL_IF(state->window != 3);
843  FAIL_IF_NOT(state->transaction_max == 4);
844 
845  /* Response to the third request. */
846  res[1] = 0x03;
847  FAIL_IF_NOT(DNSUDPResponseParse(f, f->alstate, NULL, res, reslen, NULL, 0));
848  FAIL_IF_NOT(state->unreplied_cnt == 2);
849  FAIL_IF_NOT(state->window == 3);
850  tx = TAILQ_FIRST(&state->tx_list);
851  FAIL_IF_NULL(tx);
852  FAIL_IF(tx->replied);
853  FAIL_IF(!tx->reply_lost);
854 
855  /* Also free's state. */
856  UTHFreeFlow(f);
857 
858  PASS;
859 }
860 
861 static int DNSUDPParserTxCleanup(void)
862 {
863  uint64_t ret[4];
864 
865  /* DNS request:
866  * - Flags: 0x0100 Standard query
867  * - A www.google.com
868  */
869  uint8_t req[] = {
870  0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
871  0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77,
872  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
873  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
874  };
875  size_t reqlen = sizeof(req);
876 
877  uint8_t res[] = {
878  0x00, 0x01, 0x81, 0x80, 0x00, 0x01, 0x00, 0x08,
879  0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77,
880  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
881  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
882  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
883  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x38,
884  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
885  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x39,
886  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
887  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x34,
888  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
889  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x35,
890  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
891  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x36,
892  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
893  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x3b,
894  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
895  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x37,
896  0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
897  0x01, 0x08, 0x00, 0x04, 0x18, 0xf4, 0x04, 0x3a
898  };
899  size_t reslen = sizeof(res);
900 
901  Flow *f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 53);
902  FAIL_IF_NULL(f);
903  f->proto = IPPROTO_UDP;
904  f->protomap = FlowGetProtoMapping(IPPROTO_UDP);
905  f->alproto = ALPROTO_DNS;
906 
908  FAIL_IF_NULL(alp_tctx);
909 
910  /* First request. */
911  req[1] = 0x01;
912  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_DNS,
913  STREAM_TOSERVER | STREAM_START, req, reqlen);
914  FAIL_IF_NOT(r == 0);
915  /* Second request. */
916  req[1] = 0x02;
917  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_DNS,
918  STREAM_TOSERVER, req, reqlen);
919  FAIL_IF_NOT(r == 0);
920  /* Third request. */
921  req[1] = 0x03;
922  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_DNS,
923  STREAM_TOSERVER, req, reqlen);
924  FAIL_IF_NOT(r == 0);
925 
926  /* Now respond to the second. */
927  res[1] = 0x02;
928  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_DNS,
929  STREAM_TOCLIENT, res, reslen);
930  FAIL_IF_NOT(r == 0);
931 
932  /* Send a 4th request. */
933  req[1] = 0x04;
934  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_DNS,
935  STREAM_TOSERVER, req, reqlen);
936  FAIL_IF_NOT(r == 0);
937 
939  UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
940  FAIL_IF_NOT(ret[0] == 0); // inspect_id[0]
941  FAIL_IF_NOT(ret[1] == 0); // inspect_id[1]
942  FAIL_IF_NOT(ret[2] == 0); // log_id
943  FAIL_IF_NOT(ret[3] == 0); // min_id
944 
945  /* Response to the third request. */
946  res[1] = 0x03;
947  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_DNS,
948  STREAM_TOCLIENT, res, reslen);
949  FAIL_IF_NOT(r == 0);
950  DNSState *state = f->alstate;
951  DNSTransaction *tx = TAILQ_FIRST(&state->tx_list);
952  FAIL_IF_NULL(tx);
953  FAIL_IF(tx->replied);
954  FAIL_IF(!tx->reply_lost);
955 
957  UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
958  FAIL_IF_NOT(ret[0] == 3); // inspect_id[0]
959  FAIL_IF_NOT(ret[1] == 3); // inspect_id[1]
960  FAIL_IF_NOT(ret[2] == 3); // log_id
961  FAIL_IF_NOT(ret[3] == 3); // min_id
962 
963  /* Also free's state. */
964  UTHFreeFlow(f);
965 
966  PASS;
967 }
968 
970 {
971  UtRegisterTest("DNSUDPParserTest01", DNSUDPParserTest01);
972  UtRegisterTest("DNSUDPParserTest02", DNSUDPParserTest02);
973  UtRegisterTest("DNSUDPParserTest03", DNSUDPParserTest03);
974  UtRegisterTest("DNSUDPParserTest04", DNSUDPParserTest04);
975  UtRegisterTest("DNSUDPParserTest05", DNSUDPParserTest05);
976  UtRegisterTest("DNSUDPParserTestFlood", DNSUDPParserTestFlood);
977  UtRegisterTest("DNSUDPParserTestDelayedResponse",
978  DNSUDPParserTestDelayedResponse);
979  UtRegisterTest("DNSUDPParserTestLostResponse",
980  DNSUDPParserTestLostResponse);
981  UtRegisterTest("DNSUDPParserTxCleanup",
982  DNSUDPParserTxCleanup);
983 }
984 #endif
985 #endif /* HAVE_RUST */
#define DNS_CONFIG_DEFAULT_GLOBAL_MEMCAP
uint16_t flags
#define SCLogDebug(...)
Definition: util-debug.h:335
int DNSGetAlstateProgressCompletionStatus(uint8_t direction)
get value for &#39;complete&#39; status in DNS
#define TAILQ_FIRST(head)
Definition: queue.h:339
AppLayerDecoderEvents * DNSGetEvents(void *state, uint64_t id)
void DNSConfigSetRequestFlood(uint32_t value)
void AppLayerProtoDetectPPRegister(uint8_t ipproto, const char *portstr, AppProto alproto, uint16_t min_depth, uint16_t max_depth, uint8_t direction, ProbingParserFPtr ProbingParser1, ProbingParserFPtr ProbingParser2)
register parser at a port
uint64_t DNSGetTxDetectFlags(void *vtx, uint8_t dir)
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
uint8_t proto
Definition: flow.h:346
Per flow DNS state container.
void DNSConfigSetStateMemcap(uint32_t value)
#define PASS
Pass the test.
void DNSSetTxDetectFlags(void *vtx, uint8_t dir, uint64_t detect_flags)
void * DNSStateAlloc(void)
int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
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)
void AppLayerParserRegisterDetectFlagsFuncs(uint8_t ipproto, AppProto alproto, uint64_t(*GetTxDetectFlags)(void *tx, uint8_t dir), void(*SetTxDetectFlags)(void *tx, uint8_t dir, uint64_t))
int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag)
void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto, DetectEngineState *(*GetTxDetectState)(void *tx), int(*SetTxDetectState)(void *tx, DetectEngineState *))
struct timeval last_req
LoggerId DNSGetTxLogged(void *alstate, void *tx)
void RegisterRustDNSUDPParsers(void)
DNS Transaction, request/reply with same TX id.
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition: flow-util.c:95
struct timeval last_resp
void AppLayerParserRegisterLoggerFuncs(uint8_t ipproto, AppProto alproto, LoggerId(*StateGetTxLogged)(void *, void *), void(*StateSetTxLogged)(void *, void *, LoggerId))
char * val
Definition: conf.h:34
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:203
DNSTransaction * DNSTransactionFindByTxId(const DNSState *dns_state, const uint16_t tx_id)
void * alstate
Definition: flow.h:436
int AppLayerParserConfParserEnabled(const char *ipproto, const char *alproto_name)
check if a parser is enabled in the config Returns enabled always if: were running unittests and when...
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, uint8_t direction, AppLayerParserFPtr Parser)
Register app layer parser for the protocol.
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
#define DNS_MAX_SIZE
int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name, uint8_t ipproto, const char *alproto_name, AppProto alproto, uint16_t min_depth, uint16_t max_depth, ProbingParserFPtr ProbingParserTs, ProbingParserFPtr ProbingParserTc)
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
DetectEngineState * DNSGetTxDetectState(void *vtx)
uint32_t unreplied_cnt
#define STREAM_TOCLIENT
Definition: stream.h:32
void DNSSetEvent(DNSState *s, uint8_t e)
void DNSConfigSetGlobalMemcap(uint64_t value)
void AppLayerParserRegisterGetStateProgressCompletionStatus(AppProto alproto, int(*StateGetProgressCompletionStatus)(uint8_t direction))
uint64_t DNSGetTxCnt(void *alstate)
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol&#39;s parser thread context.
int RunmodeIsUnittests(void)
Definition: suricata.c:261
int DNSValidateRequestHeader(DNSState *dns_state, const DNSHeader *dns_header)
Validation checks for DNS request header.
#define SCReturnInt(x)
Definition: util-debug.h:341
struct timeval lastts
Definition: flow.h:356
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
void * DNSGetTx(void *alstate, uint64_t tx_id)
void DNSStateFree(void *s)
Definition: conf.h:32
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
void AppLayerParserTransactionsCleanup(Flow *f)
remove obsolete (inspected and logged) transactions
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
PoolThreadReserved res
#define SCNtohs(x)
int DNSValidateResponseHeader(DNSState *dns_state, const DNSHeader *dns_header)
Validation checks for DNS response header.
#define DNS_CONFIG_DEFAULT_REQUEST_FLOOD
void AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto, AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t))
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
#define STREAM_START
Definition: stream.h:29
#define STREAM_TOSERVER
Definition: stream.h:31
#define APP_LAYER_PARSER_EOF
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:176
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
uint16_t length
int DNSGetAlstateProgress(void *tx, uint8_t direction)
#define DNS_CONFIG_DEFAULT_STATE_MEMCAP
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void), void(*StateFree)(void *))
void DNSStateTransactionFree(void *state, uint64_t tx_id)
dns transaction cleanup callback
int ParseSizeStringU32(const char *size, uint32_t *res)
Definition: util-misc.c:186
AppProto alproto
application level protocol
Definition: flow.h:407
void UTHAppLayerParserStateGetIds(void *ptr, uint64_t *i1, uint64_t *i2, uint64_t *log, uint64_t *min)
void RegisterDNSUDPParsers(void)
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
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)
void DNSSetTxLogged(void *alstate, void *tx, LoggerId logged)
uint64_t transaction_max
int DNSSetTxDetectState(void *vtx, DetectEngineState *s)
uint8_t protomap
Definition: flow.h:402
Flow data structure.
Definition: flow.h:327
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
AppLayerParserState * alparser
Definition: flow.h:435
void DNSUDPParserRegisterTests(void)
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, uint8_t *input, uint32_t input_len)
#define DNS_RCODE_NOTZONE
void UTHFreeFlow(Flow *flow)
void DNSAppLayerRegisterGetEventInfo(uint8_t ipproto, AppProto alproto)
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))