]> git.ipfire.org Git - people/ms/suricata.git/blob - rust/src/dns/dns.rs
dns: add rdata logging for NS rrtype
[people/ms/suricata.git] / rust / src / dns / dns.rs
1 /* Copyright (C) 2017 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 extern crate nom;
19
20 use std;
21 use std::ffi::CString;
22 use std::mem::transmute;
23 use std::collections::HashMap;
24 use std::collections::VecDeque;
25
26 use crate::applayer::*;
27 use crate::core::{self, AppProto, ALPROTO_UNKNOWN, IPPROTO_UDP, IPPROTO_TCP};
28 use crate::dns::parser;
29
30 use nom::IResult;
31 use nom::number::streaming::be_u16;
32
33 /// DNS record types.
34 pub const DNS_RECORD_TYPE_A : u16 = 1;
35 pub const DNS_RECORD_TYPE_NS : u16 = 2;
36 pub const DNS_RECORD_TYPE_MD : u16 = 3; // Obsolete
37 pub const DNS_RECORD_TYPE_MF : u16 = 4; // Obsolete
38 pub const DNS_RECORD_TYPE_CNAME : u16 = 5;
39 pub const DNS_RECORD_TYPE_SOA : u16 = 6;
40 pub const DNS_RECORD_TYPE_MB : u16 = 7; // Experimental
41 pub const DNS_RECORD_TYPE_MG : u16 = 8; // Experimental
42 pub const DNS_RECORD_TYPE_MR : u16 = 9; // Experimental
43 pub const DNS_RECORD_TYPE_NULL : u16 = 10; // Experimental
44 pub const DNS_RECORD_TYPE_WKS : u16 = 11;
45 pub const DNS_RECORD_TYPE_PTR : u16 = 12;
46 pub const DNS_RECORD_TYPE_HINFO : u16 = 13;
47 pub const DNS_RECORD_TYPE_MINFO : u16 = 14;
48 pub const DNS_RECORD_TYPE_MX : u16 = 15;
49 pub const DNS_RECORD_TYPE_TXT : u16 = 16;
50 pub const DNS_RECORD_TYPE_RP : u16 = 17;
51 pub const DNS_RECORD_TYPE_AFSDB : u16 = 18;
52 pub const DNS_RECORD_TYPE_X25 : u16 = 19;
53 pub const DNS_RECORD_TYPE_ISDN : u16 = 20;
54 pub const DNS_RECORD_TYPE_RT : u16 = 21;
55 pub const DNS_RECORD_TYPE_NSAP : u16 = 22;
56 pub const DNS_RECORD_TYPE_NSAPPTR : u16 = 23;
57 pub const DNS_RECORD_TYPE_SIG : u16 = 24;
58 pub const DNS_RECORD_TYPE_KEY : u16 = 25;
59 pub const DNS_RECORD_TYPE_PX : u16 = 26;
60 pub const DNS_RECORD_TYPE_GPOS : u16 = 27;
61 pub const DNS_RECORD_TYPE_AAAA : u16 = 28;
62 pub const DNS_RECORD_TYPE_LOC : u16 = 29;
63 pub const DNS_RECORD_TYPE_NXT : u16 = 30; // Obsolete
64 pub const DNS_RECORD_TYPE_SRV : u16 = 33;
65 pub const DNS_RECORD_TYPE_ATMA : u16 = 34;
66 pub const DNS_RECORD_TYPE_NAPTR : u16 = 35;
67 pub const DNS_RECORD_TYPE_KX : u16 = 36;
68 pub const DNS_RECORD_TYPE_CERT : u16 = 37;
69 pub const DNS_RECORD_TYPE_A6 : u16 = 38; // Obsolete
70 pub const DNS_RECORD_TYPE_DNAME : u16 = 39;
71 pub const DNS_RECORD_TYPE_OPT : u16 = 41;
72 pub const DNS_RECORD_TYPE_APL : u16 = 42;
73 pub const DNS_RECORD_TYPE_DS : u16 = 43;
74 pub const DNS_RECORD_TYPE_SSHFP : u16 = 44;
75 pub const DNS_RECORD_TYPE_IPSECKEY : u16 = 45;
76 pub const DNS_RECORD_TYPE_RRSIG : u16 = 46;
77 pub const DNS_RECORD_TYPE_NSEC : u16 = 47;
78 pub const DNS_RECORD_TYPE_DNSKEY : u16 = 48;
79 pub const DNS_RECORD_TYPE_DHCID : u16 = 49;
80 pub const DNS_RECORD_TYPE_NSEC3 : u16 = 50;
81 pub const DNS_RECORD_TYPE_NSEC3PARAM : u16 = 51;
82 pub const DNS_RECORD_TYPE_TLSA : u16 = 52;
83 pub const DNS_RECORD_TYPE_HIP : u16 = 55;
84 pub const DNS_RECORD_TYPE_CDS : u16 = 59;
85 pub const DNS_RECORD_TYPE_CDNSKEY : u16 = 60;
86 pub const DNS_RECORD_TYPE_SPF : u16 = 99; // Obsolete
87 pub const DNS_RECORD_TYPE_TKEY : u16 = 249;
88 pub const DNS_RECORD_TYPE_TSIG : u16 = 250;
89 pub const DNS_RECORD_TYPE_MAILA : u16 = 254; // Obsolete
90 pub const DNS_RECORD_TYPE_ANY : u16 = 255;
91 pub const DNS_RECORD_TYPE_URI : u16 = 256;
92
93 /// DNS error codes.
94 pub const DNS_RCODE_NOERROR: u16 = 0;
95 pub const DNS_RCODE_FORMERR: u16 = 1;
96 pub const DNS_RCODE_SERVFAIL: u16 = 2;
97 pub const DNS_RCODE_NXDOMAIN: u16 = 3;
98 pub const DNS_RCODE_NOTIMP: u16 = 4;
99 pub const DNS_RCODE_REFUSED: u16 = 5;
100 pub const DNS_RCODE_YXDOMAIN: u16 = 6;
101 pub const DNS_RCODE_YXRRSET: u16 = 7;
102 pub const DNS_RCODE_NXRRSET: u16 = 8;
103 pub const DNS_RCODE_NOTAUTH: u16 = 9;
104 pub const DNS_RCODE_NOTZONE: u16 = 10;
105 // Support for OPT RR from RFC6891 will be needed to
106 // parse RCODE values over 15
107 pub const DNS_RCODE_BADVERS: u16 = 16;
108 pub const DNS_RCODE_BADSIG: u16 = 16;
109 pub const DNS_RCODE_BADKEY: u16 = 17;
110 pub const DNS_RCODE_BADTIME: u16 = 18;
111 pub const DNS_RCODE_BADMODE: u16 = 19;
112 pub const DNS_RCODE_BADNAME: u16 = 20;
113 pub const DNS_RCODE_BADALG: u16 = 21;
114 pub const DNS_RCODE_BADTRUNC: u16 = 22;
115
116
117 /// The maximum number of transactions to keep in the queue pending
118 /// processing before they are aggressively purged. Due to the
119 /// stateless nature of this parser this is rarely needed, especially
120 /// when one call to parse a request parses and a single request, and
121 /// likewise for responses.
122 ///
123 /// Where this matters is when one TCP buffer contains multiple
124 /// requests are responses and one call into the parser creates
125 /// multiple transactions. In this case we have to hold onto
126 /// transactions longer than until handling the next transaction so it
127 /// gets logged.
128 const MAX_TRANSACTIONS: usize = 32;
129
130 static mut ALPROTO_DNS: AppProto = ALPROTO_UNKNOWN;
131
132 #[repr(u32)]
133 pub enum DNSEvent {
134 MalformedData = 0,
135 NotRequest = 1,
136 NotResponse = 2,
137 ZFlagSet = 3,
138 }
139
140 impl DNSEvent {
141 pub fn to_cstring(&self) -> &str {
142 match *self {
143 DNSEvent::MalformedData => "MALFORMED_DATA\0",
144 DNSEvent::NotRequest => "NOT_A_REQUEST\0",
145 DNSEvent::NotResponse => "NOT_A_RESPONSE\0",
146 DNSEvent::ZFlagSet => "Z_FLAG_SET\0",
147 }
148 }
149
150 pub fn from_id(id: u32) -> Option<DNSEvent> {
151 match id {
152 0 => Some(DNSEvent::MalformedData),
153 1 => Some(DNSEvent::NotRequest),
154 2 => Some(DNSEvent::NotResponse),
155 4 => Some(DNSEvent::ZFlagSet),
156 _ => None,
157 }
158 }
159
160 pub fn from_string(s: &str) -> Option<DNSEvent> {
161 match s.to_lowercase().as_ref() {
162 "malformed_data" => Some(DNSEvent::MalformedData),
163 "not_a_request" => Some(DNSEvent::NotRequest),
164 "not_a_response" => Some(DNSEvent::NotRequest),
165 "z_flag_set" => Some(DNSEvent::ZFlagSet),
166 _ => None
167 }
168 }
169 }
170
171 #[no_mangle]
172 pub extern "C" fn rs_dns_state_get_event_info_by_id(
173 event_id: std::os::raw::c_int,
174 event_name: *mut *const std::os::raw::c_char,
175 event_type: *mut core::AppLayerEventType,
176 ) -> i8 {
177 if let Some(e) = DNSEvent::from_id(event_id as u32) {
178 unsafe {
179 *event_name = e.to_cstring().as_ptr() as *const std::os::raw::c_char;
180 *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
181 }
182 return 0;
183 }
184 return -1;
185 }
186
187 #[no_mangle]
188 pub extern "C" fn rs_dns_state_get_event_info(
189 event_name: *const std::os::raw::c_char,
190 event_id: *mut std::os::raw::c_int,
191 event_type: *mut core::AppLayerEventType
192 ) -> std::os::raw::c_int {
193 if event_name == std::ptr::null() {
194 return -1;
195 }
196
197 let event_name = unsafe { std::ffi::CStr::from_ptr(event_name) };
198 if let Ok(event_name) = event_name.to_str() {
199 if let Some(event) = DNSEvent::from_string(event_name) {
200 unsafe {
201 *event_id = event as std::os::raw::c_int;
202 *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
203 }
204 } else {
205 // Unknown event...
206 return -1;
207 }
208 } else {
209 // UTF-8 conversion failed. Should not happen.
210 return -1;
211 }
212
213 return 0;
214 }
215
216 #[derive(Debug,PartialEq)]
217 #[repr(C)]
218 pub struct DNSHeader {
219 pub tx_id: u16,
220 pub flags: u16,
221 pub questions: u16,
222 pub answer_rr: u16,
223 pub authority_rr: u16,
224 pub additional_rr: u16,
225 }
226
227 #[derive(Debug)]
228 pub struct DNSQueryEntry {
229 pub name: Vec<u8>,
230 pub rrtype: u16,
231 pub rrclass: u16,
232 }
233
234 #[derive(Debug,PartialEq)]
235 pub struct DNSRDataSOA {
236 /// Primary name server for this zone
237 pub mname: Vec<u8>,
238 /// Authority's mailbox
239 pub rname: Vec<u8>,
240 /// Serial version number
241 pub serial: u32,
242 /// Refresh interval (seconds)
243 pub refresh: u32,
244 /// Retry interval (seconds)
245 pub retry: u32,
246 /// Upper time limit until zone is no longer authoritative (seconds)
247 pub expire: u32,
248 /// Minimum ttl for records in this zone (seconds)
249 pub minimum: u32,
250 }
251
252 #[derive(Debug,PartialEq)]
253 pub struct DNSRDataSSHFP {
254 /// Algorithm number
255 pub algo: u8,
256 /// Fingerprint type
257 pub fp_type: u8,
258 /// Fingerprint
259 pub fingerprint: Vec<u8>,
260 }
261
262 /// Represents RData of various formats
263 #[derive(Debug,PartialEq)]
264 pub enum DNSRData {
265 // RData is an address
266 A(Vec<u8>),
267 AAAA(Vec<u8>),
268 // RData is a domain name
269 CNAME(Vec<u8>),
270 PTR(Vec<u8>),
271 MX(Vec<u8>),
272 NS(Vec<u8>),
273 // RData is text
274 TXT(Vec<u8>),
275 NULL(Vec<u8>),
276 // RData has several fields
277 SOA(DNSRDataSOA),
278 SSHFP(DNSRDataSSHFP),
279 // RData for remaining types is sometimes ignored
280 Unknown(Vec<u8>),
281 }
282
283 #[derive(Debug,PartialEq)]
284 pub struct DNSAnswerEntry {
285 pub name: Vec<u8>,
286 pub rrtype: u16,
287 pub rrclass: u16,
288 pub ttl: u32,
289 pub data: DNSRData,
290 }
291
292 #[derive(Debug)]
293 pub struct DNSRequest {
294 pub header: DNSHeader,
295 pub queries: Vec<DNSQueryEntry>,
296 }
297
298 #[derive(Debug)]
299 pub struct DNSResponse {
300 pub header: DNSHeader,
301 pub queries: Vec<DNSQueryEntry>,
302 pub answers: Vec<DNSAnswerEntry>,
303 pub authorities: Vec<DNSAnswerEntry>,
304 }
305
306 #[derive(Debug)]
307 pub struct DNSTransaction {
308 pub id: u64,
309 pub request: Option<DNSRequest>,
310 pub response: Option<DNSResponse>,
311 pub de_state: Option<*mut core::DetectEngineState>,
312 pub events: *mut core::AppLayerDecoderEvents,
313 pub tx_data: AppLayerTxData,
314 }
315
316 impl DNSTransaction {
317
318 pub fn new() -> DNSTransaction {
319 return DNSTransaction{
320 id: 0,
321 request: None,
322 response: None,
323 de_state: None,
324 events: std::ptr::null_mut(),
325 tx_data: AppLayerTxData::new(),
326 }
327 }
328
329 pub fn free(&mut self) {
330 if self.events != std::ptr::null_mut() {
331 core::sc_app_layer_decoder_events_free_events(&mut self.events);
332 }
333 match self.de_state {
334 Some(state) => {
335 core::sc_detect_engine_state_free(state);
336 }
337 None => { },
338 }
339 }
340
341 /// Get the DNS transactions ID (not the internal tracking ID).
342 pub fn tx_id(&self) -> u16 {
343 if let &Some(ref request) = &self.request {
344 return request.header.tx_id;
345 }
346 if let &Some(ref response) = &self.response {
347 return response.header.tx_id;
348 }
349
350 // Shouldn't happen.
351 return 0;
352 }
353
354 /// Get the reply code of the transaction. Note that this will
355 /// also return 0 if there is no reply.
356 pub fn rcode(&self) -> u16 {
357 if let &Some(ref response) = &self.response {
358 return response.header.flags & 0x000f;
359 }
360 return 0;
361 }
362
363 }
364
365 impl Drop for DNSTransaction {
366 fn drop(&mut self) {
367 self.free();
368 }
369 }
370
371 struct ConfigTracker {
372 map: HashMap<u16, AppLayerTxConfig>,
373 queue: VecDeque<u16>,
374 }
375
376 impl ConfigTracker {
377 fn new() -> ConfigTracker {
378 ConfigTracker {
379 map: HashMap::new(),
380 queue: VecDeque::new(),
381 }
382 }
383
384 fn add(&mut self, id: u16, config: AppLayerTxConfig) {
385 // If at size limit, remove the oldest entry.
386 if self.queue.len() > 499 {
387 if let Some(id) = self.queue.pop_front() {
388 self.map.remove(&id);
389 }
390 }
391
392 self.map.insert(id, config);
393 self.queue.push_back(id);
394 }
395
396 fn remove(&mut self, id: &u16) -> Option<AppLayerTxConfig> {
397 self.map.remove(id)
398 }
399 }
400
401 pub struct DNSState {
402 // Internal transaction ID.
403 pub tx_id: u64,
404
405 // Transactions.
406 pub transactions: Vec<DNSTransaction>,
407
408 pub events: u16,
409
410 config: Option<ConfigTracker>,
411
412 gap: bool,
413 }
414
415 impl DNSState {
416
417 pub fn new() -> DNSState {
418 return DNSState{
419 tx_id: 0,
420 transactions: Vec::new(),
421 events: 0,
422 config: None,
423 gap: false,
424 };
425 }
426
427 pub fn new_tcp() -> DNSState {
428 return DNSState{
429 tx_id: 0,
430 transactions: Vec::new(),
431 events: 0,
432 config: None,
433 gap: false,
434 };
435 }
436
437 pub fn new_tx(&mut self) -> DNSTransaction {
438 let mut tx = DNSTransaction::new();
439 self.tx_id += 1;
440 tx.id = self.tx_id;
441 return tx;
442 }
443
444 pub fn free_tx(&mut self, tx_id: u64) {
445 let len = self.transactions.len();
446 let mut found = false;
447 let mut index = 0;
448 for i in 0..len {
449 let tx = &self.transactions[i];
450 if tx.id == tx_id + 1 {
451 found = true;
452 index = i;
453 break;
454 }
455 }
456 if found {
457 self.transactions.remove(index);
458 }
459 }
460
461 // Purges all transactions except one. This is a stateless parser
462 // so we don't need to hang onto old transactions.
463 //
464 // This is to actually handle an edge case where a DNS flood
465 // occurs in a single direction with no response packets. In such
466 // a case the functions to free a transaction are never called by
467 // the app-layer as they require bidirectional traffic.
468 pub fn purge(&mut self, tx_id: u64) {
469 while self.transactions.len() > MAX_TRANSACTIONS {
470 if self.transactions[0].id == tx_id + 1 {
471 return;
472 }
473 SCLogDebug!("Purging DNS TX with ID {}", self.transactions[0].id);
474 self.transactions.remove(0);
475 }
476 }
477
478 pub fn get_tx(&mut self, tx_id: u64) -> Option<&DNSTransaction> {
479 SCLogDebug!("get_tx: tx_id={}", tx_id);
480 self.purge(tx_id);
481 for tx in &mut self.transactions {
482 if tx.id == tx_id + 1 {
483 SCLogDebug!("Found DNS TX with ID {}", tx_id);
484 return Some(tx);
485 }
486 }
487 SCLogDebug!("Failed to find DNS TX with ID {}", tx_id);
488 return None;
489 }
490
491 /// Set an event. The event is set on the most recent transaction.
492 pub fn set_event(&mut self, event: DNSEvent) {
493 let len = self.transactions.len();
494 if len == 0 {
495 return;
496 }
497
498 let tx = &mut self.transactions[len - 1];
499 core::sc_app_layer_decoder_events_set_event_raw(&mut tx.events,
500 event as u8);
501 self.events += 1;
502 }
503
504 pub fn parse_request(&mut self, input: &[u8]) -> bool {
505 match parser::dns_parse_request(input) {
506 Ok((_, request)) => {
507 if request.header.flags & 0x8000 != 0 {
508 SCLogDebug!("DNS message is not a request");
509 self.set_event(DNSEvent::NotRequest);
510 return false;
511 }
512
513 if request.header.flags & 0x0040 != 0 {
514 SCLogDebug!("Z-flag set on DNS response");
515 self.set_event(DNSEvent::ZFlagSet);
516 return false;
517 }
518
519 let mut tx = self.new_tx();
520 tx.request = Some(request);
521 self.transactions.push(tx);
522 return true;
523 }
524 Err(nom::Err::Incomplete(_)) => {
525 // Insufficient data.
526 SCLogDebug!("Insufficient data while parsing DNS request");
527 self.set_event(DNSEvent::MalformedData);
528 return false;
529 }
530 Err(_) => {
531 // Error, probably malformed data.
532 SCLogDebug!("An error occurred while parsing DNS request");
533 self.set_event(DNSEvent::MalformedData);
534 return false;
535 }
536 }
537 }
538
539 pub fn parse_response(&mut self, input: &[u8]) -> bool {
540 match parser::dns_parse_response(input) {
541 Ok((_, response)) => {
542
543 SCLogDebug!("Response header flags: {}", response.header.flags);
544
545 if response.header.flags & 0x8000 == 0 {
546 SCLogDebug!("DNS message is not a response");
547 self.set_event(DNSEvent::NotResponse);
548 }
549
550 if response.header.flags & 0x0040 != 0 {
551 SCLogDebug!("Z-flag set on DNS response");
552 self.set_event(DNSEvent::ZFlagSet);
553 return false;
554 }
555
556 let mut tx = self.new_tx();
557 if let Some(ref mut config) = &mut self.config {
558 if let Some(config) = config.remove(&response.header.tx_id) {
559 tx.tx_data.config = config;
560 }
561 }
562 tx.response = Some(response);
563 self.transactions.push(tx);
564 return true;
565 }
566 Err(nom::Err::Incomplete(_)) => {
567 // Insufficient data.
568 SCLogDebug!("Insufficient data while parsing DNS response");
569 self.set_event(DNSEvent::MalformedData);
570 return false;
571 }
572 Err(_) => {
573 // Error, probably malformed data.
574 SCLogDebug!("An error occurred while parsing DNS response");
575 self.set_event(DNSEvent::MalformedData);
576 return false;
577 }
578 }
579 }
580
581 /// TCP variation of response request parser to handle the length
582 /// prefix.
583 ///
584 /// Returns the number of messages parsed.
585 pub fn parse_request_tcp(&mut self, input: &[u8]) -> AppLayerResult {
586 if self.gap {
587 let (is_dns, _, is_incomplete) = probe_tcp(input);
588 if is_dns || is_incomplete {
589 self.gap = false;
590 } else {
591 AppLayerResult::ok();
592 }
593 }
594
595 let mut cur_i = input;
596 let mut consumed = 0;
597 while cur_i.len() > 0 {
598 if cur_i.len() == 1 {
599 return AppLayerResult::incomplete(consumed as u32, 2 as u32);
600 }
601 let size = match be_u16(&cur_i) as IResult<&[u8],u16> {
602 Ok((_, len)) => len,
603 _ => 0
604 } as usize;
605 SCLogDebug!("[request] Have {} bytes, need {} to parse",
606 cur_i.len(), size + 2);
607 if size > 0 && cur_i.len() >= size + 2 {
608 let msg = &cur_i[0..(size + 2)];
609 if self.parse_request(&msg[2..]) {
610 cur_i = &cur_i[(size + 2)..];
611 consumed += size + 2;
612 } else {
613 return AppLayerResult::err();
614 }
615 } else if size == 0 {
616 cur_i = &cur_i[2..];
617 consumed += 2;
618 } else {
619 SCLogDebug!("[request]Not enough DNS traffic to parse. Returning {}/{}",
620 consumed as u32, (size + 2) as u32);
621 return AppLayerResult::incomplete(consumed as u32,
622 (size + 2) as u32);
623 }
624 }
625 AppLayerResult::ok()
626 }
627
628 /// TCP variation of the response parser to handle the length
629 /// prefix.
630 ///
631 /// Returns the number of messages parsed.
632 pub fn parse_response_tcp(&mut self, input: &[u8]) -> AppLayerResult {
633 if self.gap {
634 let (is_dns, _, is_incomplete) = probe_tcp(input);
635 if is_dns || is_incomplete {
636 self.gap = false;
637 } else {
638 return AppLayerResult::ok();
639 }
640 }
641
642 let mut cur_i = input;
643 let mut consumed = 0;
644 while cur_i.len() > 0 {
645 if cur_i.len() == 1 {
646 return AppLayerResult::incomplete(consumed as u32, 2 as u32);
647 }
648 let size = match be_u16(&cur_i) as IResult<&[u8],u16> {
649 Ok((_, len)) => len,
650 _ => 0
651 } as usize;
652 SCLogDebug!("[response] Have {} bytes, need {} to parse",
653 cur_i.len(), size + 2);
654 if size > 0 && cur_i.len() >= size + 2 {
655 let msg = &cur_i[0..(size + 2)];
656 if self.parse_response(&msg[2..]) {
657 cur_i = &cur_i[(size + 2)..];
658 consumed += size + 2;
659 } else {
660 return AppLayerResult::err();
661 }
662 } else if size == 0 {
663 cur_i = &cur_i[2..];
664 consumed += 2;
665 } else {
666 SCLogDebug!("[response]Not enough DNS traffic to parse. Returning {}/{}",
667 consumed as u32, (cur_i.len() - consumed) as u32);
668 return AppLayerResult::incomplete(consumed as u32,
669 (size + 2) as u32);
670 }
671 }
672 AppLayerResult::ok()
673 }
674
675 /// A gap has been seen in the request direction. Set the gap flag.
676 pub fn request_gap(&mut self, gap: u32) {
677 if gap > 0 {
678 self.gap = true;
679 }
680 }
681
682 /// A gap has been seen in the response direction. Set the gap
683 /// flag.
684 pub fn response_gap(&mut self, gap: u32) {
685 if gap > 0 {
686 self.gap = true;
687 }
688 }
689 }
690
691 /// Probe input to see if it looks like DNS.
692 fn probe(input: &[u8]) -> (bool, bool) {
693 match parser::dns_parse_request(input) {
694 Ok((_, request)) => {
695 let is_request = request.header.flags & 0x8000 == 0;
696 return (true, is_request);
697 },
698 Err(_) => (false, false),
699 }
700 }
701
702 /// Probe TCP input to see if it looks like DNS.
703 pub fn probe_tcp(input: &[u8]) -> (bool, bool, bool) {
704 match be_u16(input) as IResult<&[u8],_> {
705 Ok((rem, _)) => {
706 let r = probe(rem);
707 return (r.0, r.1, false);
708 },
709 Err(nom::Err::Incomplete(_)) => {
710 return (false, false, true);
711 }
712 _ => {}
713 }
714 return (false, false, false);
715 }
716
717 /// Returns *mut DNSState
718 #[no_mangle]
719 pub extern "C" fn rs_dns_state_new(_orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto) -> *mut std::os::raw::c_void {
720 let state = DNSState::new();
721 let boxed = Box::new(state);
722 return unsafe{transmute(boxed)};
723 }
724
725 /// Returns *mut DNSState
726 #[no_mangle]
727 pub extern "C" fn rs_dns_state_tcp_new() -> *mut std::os::raw::c_void {
728 let state = DNSState::new_tcp();
729 let boxed = Box::new(state);
730 return unsafe{transmute(boxed)};
731 }
732
733 /// Params:
734 /// - state: *mut DNSState as void pointer
735 #[no_mangle]
736 pub extern "C" fn rs_dns_state_free(state: *mut std::os::raw::c_void) {
737 // Just unbox...
738 let _drop: Box<DNSState> = unsafe{transmute(state)};
739 }
740
741 #[no_mangle]
742 pub extern "C" fn rs_dns_state_tx_free(state: *mut std::os::raw::c_void,
743 tx_id: u64)
744 {
745 let state = cast_pointer!(state, DNSState);
746 state.free_tx(tx_id);
747 }
748
749 /// C binding parse a DNS request. Returns 1 on success, -1 on failure.
750 #[no_mangle]
751 pub extern "C" fn rs_dns_parse_request(_flow: *const core::Flow,
752 state: *mut std::os::raw::c_void,
753 _pstate: *mut std::os::raw::c_void,
754 input: *const u8,
755 input_len: u32,
756 _data: *const std::os::raw::c_void,
757 _flags: u8)
758 -> AppLayerResult {
759 let state = cast_pointer!(state, DNSState);
760 let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)};
761 if state.parse_request(buf) {
762 AppLayerResult::ok()
763 } else {
764 AppLayerResult::err()
765 }
766 }
767
768 #[no_mangle]
769 pub extern "C" fn rs_dns_parse_response(_flow: *const core::Flow,
770 state: *mut std::os::raw::c_void,
771 _pstate: *mut std::os::raw::c_void,
772 input: *const u8,
773 input_len: u32,
774 _data: *const std::os::raw::c_void,
775 _flags: u8)
776 -> AppLayerResult {
777 let state = cast_pointer!(state, DNSState);
778 let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)};
779 if state.parse_response(buf) {
780 AppLayerResult::ok()
781 } else {
782 AppLayerResult::err()
783 }
784 }
785
786 /// C binding parse a DNS request. Returns 1 on success, -1 on failure.
787 #[no_mangle]
788 pub extern "C" fn rs_dns_parse_request_tcp(_flow: *const core::Flow,
789 state: *mut std::os::raw::c_void,
790 _pstate: *mut std::os::raw::c_void,
791 input: *const u8,
792 input_len: u32,
793 _data: *const std::os::raw::c_void,
794 _flags: u8)
795 -> AppLayerResult {
796 let state = cast_pointer!(state, DNSState);
797 if input_len > 0 {
798 if input != std::ptr::null_mut() {
799 let buf = unsafe{
800 std::slice::from_raw_parts(input, input_len as usize)};
801 return state.parse_request_tcp(buf);
802 }
803 state.request_gap(input_len);
804 }
805 AppLayerResult::ok()
806 }
807
808 #[no_mangle]
809 pub extern "C" fn rs_dns_parse_response_tcp(_flow: *const core::Flow,
810 state: *mut std::os::raw::c_void,
811 _pstate: *mut std::os::raw::c_void,
812 input: *const u8,
813 input_len: u32,
814 _data: *const std::os::raw::c_void,
815 _flags: u8)
816 -> AppLayerResult {
817 let state = cast_pointer!(state, DNSState);
818 if input_len > 0 {
819 if input != std::ptr::null_mut() {
820 let buf = unsafe{
821 std::slice::from_raw_parts(input, input_len as usize)};
822 return state.parse_response_tcp(buf);
823 }
824 state.response_gap(input_len);
825 }
826 AppLayerResult::ok()
827 }
828
829 #[no_mangle]
830 pub extern "C" fn rs_dns_tx_get_alstate_progress(_tx: *mut std::os::raw::c_void,
831 _direction: u8)
832 -> std::os::raw::c_int
833 {
834 // This is a stateless parser, just the existence of a transaction
835 // means its complete.
836 SCLogDebug!("rs_dns_tx_get_alstate_progress");
837 return 1;
838 }
839
840 #[no_mangle]
841 pub extern "C" fn rs_dns_state_get_tx_count(state: *mut std::os::raw::c_void)
842 -> u64
843 {
844 let state = cast_pointer!(state, DNSState);
845 SCLogDebug!("rs_dns_state_get_tx_count: returning {}", state.tx_id);
846 return state.tx_id;
847 }
848
849 #[no_mangle]
850 pub extern "C" fn rs_dns_state_get_tx(state: *mut std::os::raw::c_void,
851 tx_id: u64)
852 -> *mut std::os::raw::c_void
853 {
854 let state = cast_pointer!(state, DNSState);
855 match state.get_tx(tx_id) {
856 Some(tx) => {
857 return unsafe{transmute(tx)};
858 }
859 None => {
860 return std::ptr::null_mut();
861 }
862 }
863 }
864
865 #[no_mangle]
866 pub extern "C" fn rs_dns_state_set_tx_detect_state(
867 tx: *mut std::os::raw::c_void,
868 de_state: &mut core::DetectEngineState) -> std::os::raw::c_int
869 {
870 let tx = cast_pointer!(tx, DNSTransaction);
871 tx.de_state = Some(de_state);
872 return 0;
873 }
874
875 #[no_mangle]
876 pub extern "C" fn rs_dns_state_get_tx_detect_state(
877 tx: *mut std::os::raw::c_void)
878 -> *mut core::DetectEngineState
879 {
880 let tx = cast_pointer!(tx, DNSTransaction);
881 match tx.de_state {
882 Some(ds) => {
883 return ds;
884 },
885 None => {
886 return std::ptr::null_mut();
887 }
888 }
889 }
890
891 #[no_mangle]
892 pub extern "C" fn rs_dns_state_get_events(tx: *mut std::os::raw::c_void)
893 -> *mut core::AppLayerDecoderEvents
894 {
895 let tx = cast_pointer!(tx, DNSTransaction);
896 return tx.events;
897 }
898
899 #[no_mangle]
900 pub extern "C" fn rs_dns_state_get_tx_data(
901 tx: *mut std::os::raw::c_void)
902 -> *mut AppLayerTxData
903 {
904 let tx = cast_pointer!(tx, DNSTransaction);
905 return &mut tx.tx_data;
906 }
907
908 #[no_mangle]
909 pub extern "C" fn rs_dns_tx_get_query_name(tx: &mut DNSTransaction,
910 i: u16,
911 buf: *mut *const u8,
912 len: *mut u32)
913 -> u8
914 {
915 if let &Some(ref request) = &tx.request {
916 if (i as usize) < request.queries.len() {
917 let query = &request.queries[i as usize];
918 if query.name.len() > 0 {
919 unsafe {
920 *len = query.name.len() as u32;
921 *buf = query.name.as_ptr();
922 }
923 return 1;
924 }
925 }
926 }
927 return 0;
928 }
929
930 /// Get the DNS transaction ID of a transaction.
931 //
932 /// extern uint16_t rs_dns_tx_get_tx_id(RSDNSTransaction *);
933 #[no_mangle]
934 pub extern "C" fn rs_dns_tx_get_tx_id(tx: &mut DNSTransaction) -> u16
935 {
936 return tx.tx_id()
937 }
938
939 /// Get the DNS response flags for a transaction.
940 ///
941 /// extern uint16_t rs_dns_tx_get_response_flags(RSDNSTransaction *);
942 #[no_mangle]
943 pub extern "C" fn rs_dns_tx_get_response_flags(tx: &mut DNSTransaction)
944 -> u16
945 {
946 return tx.rcode();
947 }
948
949 #[no_mangle]
950 pub extern "C" fn rs_dns_tx_get_query_rrtype(tx: &mut DNSTransaction,
951 i: u16,
952 rrtype: *mut u16)
953 -> u8
954 {
955 if let &Some(ref request) = &tx.request {
956 if (i as usize) < request.queries.len() {
957 let query = &request.queries[i as usize];
958 if query.name.len() > 0 {
959 unsafe {
960 *rrtype = query.rrtype;
961 }
962 return 1;
963 }
964 }
965 }
966 return 0;
967 }
968
969 #[no_mangle]
970 pub extern "C" fn rs_dns_probe(
971 _flow: *const core::Flow,
972 _dir: u8,
973 input: *const u8,
974 len: u32,
975 rdir: *mut u8,
976 ) -> AppProto {
977 if len == 0 || len < std::mem::size_of::<DNSHeader>() as u32 {
978 return core::ALPROTO_UNKNOWN;
979 }
980 let slice: &[u8] = unsafe {
981 std::slice::from_raw_parts(input as *mut u8, len as usize)
982 };
983 let (is_dns, is_request) = probe(slice);
984 if is_dns {
985 let dir = if is_request {
986 core::STREAM_TOSERVER
987 } else {
988 core::STREAM_TOCLIENT
989 };
990 unsafe {
991 *rdir = dir;
992 return ALPROTO_DNS;
993 }
994 }
995 return 0;
996 }
997
998 #[no_mangle]
999 pub extern "C" fn rs_dns_probe_tcp(
1000 _flow: *const core::Flow,
1001 direction: u8,
1002 input: *const u8,
1003 len: u32,
1004 rdir: *mut u8
1005 ) -> AppProto {
1006 if len == 0 || len < std::mem::size_of::<DNSHeader>() as u32 + 2 {
1007 return core::ALPROTO_UNKNOWN;
1008 }
1009 let slice: &[u8] = unsafe {
1010 std::slice::from_raw_parts(input as *mut u8, len as usize)
1011 };
1012 //is_incomplete is checked by caller
1013 let (is_dns, is_request, _) = probe_tcp(slice);
1014 if is_dns {
1015 let dir = if is_request {
1016 core::STREAM_TOSERVER
1017 } else {
1018 core::STREAM_TOCLIENT
1019 };
1020 if direction & (core::STREAM_TOSERVER|core::STREAM_TOCLIENT) != dir {
1021 unsafe { *rdir = dir };
1022 }
1023 return unsafe { ALPROTO_DNS };
1024 }
1025 return 0;
1026 }
1027
1028 #[no_mangle]
1029 pub extern "C" fn rs_dns_apply_tx_config(
1030 _state: *mut std::os::raw::c_void, _tx: *mut std::os::raw::c_void,
1031 _mode: std::os::raw::c_int, config: AppLayerTxConfig
1032 ) {
1033 let tx = cast_pointer!(_tx, DNSTransaction);
1034 let state = cast_pointer!(_state, DNSState);
1035 if let Some(request) = &tx.request {
1036 if state.config.is_none() {
1037 state.config = Some(ConfigTracker::new());
1038 }
1039 if let Some(ref mut tracker) = &mut state.config {
1040 tracker.add(request.header.tx_id, config);
1041 }
1042 }
1043 }
1044
1045 #[no_mangle]
1046 pub unsafe extern "C" fn rs_dns_init(proto: AppProto) {
1047 ALPROTO_DNS = proto;
1048 }
1049
1050 #[no_mangle]
1051 pub unsafe extern "C" fn rs_dns_udp_register_parser() {
1052 let default_port = std::ffi::CString::new("[53]").unwrap();
1053 let parser = RustParser{
1054 name: b"dns\0".as_ptr() as *const std::os::raw::c_char,
1055 default_port: default_port.as_ptr(),
1056 ipproto: IPPROTO_UDP,
1057 probe_ts: Some(rs_dns_probe),
1058 probe_tc: Some(rs_dns_probe),
1059 min_depth: 0,
1060 max_depth: std::mem::size_of::<DNSHeader>() as u16,
1061 state_new: rs_dns_state_new,
1062 state_free: rs_dns_state_free,
1063 tx_free: rs_dns_state_tx_free,
1064 parse_ts: rs_dns_parse_request,
1065 parse_tc: rs_dns_parse_response,
1066 get_tx_count: rs_dns_state_get_tx_count,
1067 get_tx: rs_dns_state_get_tx,
1068 tx_comp_st_ts: 1,
1069 tx_comp_st_tc: 1,
1070 tx_get_progress: rs_dns_tx_get_alstate_progress,
1071 get_events: Some(rs_dns_state_get_events),
1072 get_eventinfo: Some(rs_dns_state_get_event_info),
1073 get_eventinfo_byid: Some(rs_dns_state_get_event_info_by_id),
1074 localstorage_new: None,
1075 localstorage_free: None,
1076 get_files: None,
1077 get_tx_iterator: None,
1078 get_de_state: rs_dns_state_get_tx_detect_state,
1079 set_de_state: rs_dns_state_set_tx_detect_state,
1080 get_tx_data: rs_dns_state_get_tx_data,
1081 apply_tx_config: Some(rs_dns_apply_tx_config),
1082 flags: APP_LAYER_PARSER_OPT_UNIDIR_TXS,
1083 truncate: None,
1084 };
1085
1086 let ip_proto_str = CString::new("udp").unwrap();
1087 if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1088 let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
1089 ALPROTO_DNS = alproto;
1090 if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1091 let _ = AppLayerRegisterParser(&parser, alproto);
1092 }
1093 }
1094 }
1095
1096 #[no_mangle]
1097 pub unsafe extern "C" fn rs_dns_tcp_register_parser() {
1098 let default_port = std::ffi::CString::new("53").unwrap();
1099 let parser = RustParser{
1100 name: b"dns\0".as_ptr() as *const std::os::raw::c_char,
1101 default_port: default_port.as_ptr(),
1102 ipproto: IPPROTO_TCP,
1103 probe_ts: Some(rs_dns_probe_tcp),
1104 probe_tc: Some(rs_dns_probe_tcp),
1105 min_depth: 0,
1106 max_depth: std::mem::size_of::<DNSHeader>() as u16 + 2,
1107 state_new: rs_dns_state_new,
1108 state_free: rs_dns_state_free,
1109 tx_free: rs_dns_state_tx_free,
1110 parse_ts: rs_dns_parse_request_tcp,
1111 parse_tc: rs_dns_parse_response_tcp,
1112 get_tx_count: rs_dns_state_get_tx_count,
1113 get_tx: rs_dns_state_get_tx,
1114 tx_comp_st_ts: 1,
1115 tx_comp_st_tc: 1,
1116 tx_get_progress: rs_dns_tx_get_alstate_progress,
1117 get_events: Some(rs_dns_state_get_events),
1118 get_eventinfo: Some(rs_dns_state_get_event_info),
1119 get_eventinfo_byid: Some(rs_dns_state_get_event_info_by_id),
1120 localstorage_new: None,
1121 localstorage_free: None,
1122 get_files: None,
1123 get_tx_iterator: None,
1124 get_de_state: rs_dns_state_get_tx_detect_state,
1125 set_de_state: rs_dns_state_set_tx_detect_state,
1126 get_tx_data: rs_dns_state_get_tx_data,
1127 apply_tx_config: Some(rs_dns_apply_tx_config),
1128 flags: APP_LAYER_PARSER_OPT_ACCEPT_GAPS | APP_LAYER_PARSER_OPT_UNIDIR_TXS,
1129 truncate: None,
1130 };
1131
1132 let ip_proto_str = CString::new("tcp").unwrap();
1133 if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1134 let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
1135 ALPROTO_DNS = alproto;
1136 if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1137 let _ = AppLayerRegisterParser(&parser, alproto);
1138 }
1139 }
1140 }
1141
1142 #[cfg(test)]
1143 mod tests {
1144
1145 use super::*;
1146
1147 #[test]
1148 fn test_dns_parse_request_tcp_valid() {
1149 // A UDP DNS request with the DNS payload starting at byte 42.
1150 // From pcap: https://github.com/jasonish/suricata-verify/blob/7cc0e1bd0a5249b52e6e87d82d57c0b6aaf75fce/dns-udp-dig-a-www-suricata-ids-org/dig-a-www.suricata-ids.org.pcap
1151 let buf: &[u8] = &[
1152 0x00, 0x15, 0x17, 0x0d, 0x06, 0xf7, 0xd8, 0xcb, /* ........ */
1153 0x8a, 0xed, 0xa1, 0x46, 0x08, 0x00, 0x45, 0x00, /* ...F..E. */
1154 0x00, 0x4d, 0x23, 0x11, 0x00, 0x00, 0x40, 0x11, /* .M#...@. */
1155 0x41, 0x64, 0x0a, 0x10, 0x01, 0x0b, 0x0a, 0x10, /* Ad...... */
1156 0x01, 0x01, 0xa3, 0x4d, 0x00, 0x35, 0x00, 0x39, /* ...M.5.9 */
1157 0xb2, 0xb3, 0x8d, 0x32, 0x01, 0x20, 0x00, 0x01, /* ...2. .. */
1158 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x77, /* .......w */
1159 0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1160 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1161 0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1162 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00, /* ..)..... */
1163 0x00, 0x00, 0x00 /* ... */
1164 ];
1165
1166 // The DNS payload starts at offset 42.
1167 let dns_payload = &buf[42..];
1168
1169 // Make a TCP DNS request payload.
1170 let mut request = Vec::new();
1171 request.push(((dns_payload.len() as u16) >> 8) as u8);
1172 request.push(((dns_payload.len() as u16) & 0xff) as u8);
1173 request.extend(dns_payload);
1174
1175 let mut state = DNSState::new();
1176 assert_eq!(
1177 AppLayerResult::ok(),
1178 state.parse_request_tcp(&request)
1179 );
1180 }
1181
1182 #[test]
1183 fn test_dns_parse_request_tcp_short_payload() {
1184 // A UDP DNS request with the DNS payload starting at byte 42.
1185 // From pcap: https://github.com/jasonish/suricata-verify/blob/7cc0e1bd0a5249b52e6e87d82d57c0b6aaf75fce/dns-udp-dig-a-www-suricata-ids-org/dig-a-www.suricata-ids.org.pcap
1186 let buf: &[u8] = &[
1187 0x00, 0x15, 0x17, 0x0d, 0x06, 0xf7, 0xd8, 0xcb, /* ........ */
1188 0x8a, 0xed, 0xa1, 0x46, 0x08, 0x00, 0x45, 0x00, /* ...F..E. */
1189 0x00, 0x4d, 0x23, 0x11, 0x00, 0x00, 0x40, 0x11, /* .M#...@. */
1190 0x41, 0x64, 0x0a, 0x10, 0x01, 0x0b, 0x0a, 0x10, /* Ad...... */
1191 0x01, 0x01, 0xa3, 0x4d, 0x00, 0x35, 0x00, 0x39, /* ...M.5.9 */
1192 0xb2, 0xb3, 0x8d, 0x32, 0x01, 0x20, 0x00, 0x01, /* ...2. .. */
1193 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x77, /* .......w */
1194 0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1195 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1196 0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1197 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00, /* ..)..... */
1198 0x00, 0x00, 0x00 /* ... */
1199 ];
1200
1201 // The DNS payload starts at offset 42.
1202 let dns_payload = &buf[42..];
1203
1204 // Make a TCP DNS request payload but with the length 1 larger
1205 // than the available data.
1206 let mut request = Vec::new();
1207 request.push(((dns_payload.len() as u16) >> 8) as u8);
1208 request.push(((dns_payload.len() as u16) & 0xff) as u8 + 1);
1209 request.extend(dns_payload);
1210
1211 let mut state = DNSState::new();
1212 assert_eq!(
1213 AppLayerResult::incomplete(0, 52),
1214 state.parse_request_tcp(&request)
1215 );
1216 }
1217
1218 #[test]
1219 fn test_dns_parse_response_tcp_valid() {
1220 // A UDP DNS response with the DNS payload starting at byte 42.
1221 // From pcap: https://github.com/jasonish/suricata-verify/blob/7cc0e1bd0a5249b52e6e87d82d57c0b6aaf75fce/dns-udp-dig-a-www-suricata-ids-org/dig-a-www.suricata-ids.org.pcap
1222 let buf: &[u8] = &[
1223 0xd8, 0xcb, 0x8a, 0xed, 0xa1, 0x46, 0x00, 0x15, /* .....F.. */
1224 0x17, 0x0d, 0x06, 0xf7, 0x08, 0x00, 0x45, 0x00, /* ......E. */
1225 0x00, 0x80, 0x65, 0x4e, 0x40, 0x00, 0x40, 0x11, /* ..eN@.@. */
1226 0xbe, 0xf3, 0x0a, 0x10, 0x01, 0x01, 0x0a, 0x10, /* ........ */
1227 0x01, 0x0b, 0x00, 0x35, 0xa3, 0x4d, 0x00, 0x6c, /* ...5.M.l */
1228 0x8d, 0x8c, 0x8d, 0x32, 0x81, 0xa0, 0x00, 0x01, /* ...2.... */
1229 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, /* .......w */
1230 0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1231 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1232 0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1233 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, /* ........ */
1234 0x0d, 0xd8, 0x00, 0x12, 0x0c, 0x73, 0x75, 0x72, /* .....sur */
1235 0x69, 0x63, 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, /* icata-id */
1236 0x73, 0x03, 0x6f, 0x72, 0x67, 0x00, 0xc0, 0x32, /* s.org..2 */
1237 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1238 0x00, 0x04, 0xc0, 0x00, 0x4e, 0x18, 0xc0, 0x32, /* ....N..2 */
1239 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1240 0x00, 0x04, 0xc0, 0x00, 0x4e, 0x19 /* ....N. */
1241 ];
1242
1243 // The DNS payload starts at offset 42.
1244 let dns_payload = &buf[42..];
1245
1246 // Make a TCP DNS response payload.
1247 let mut request = Vec::new();
1248 request.push(((dns_payload.len() as u16) >> 8) as u8);
1249 request.push(((dns_payload.len() as u16) & 0xff) as u8);
1250 request.extend(dns_payload);
1251
1252 let mut state = DNSState::new();
1253 assert_eq!(
1254 AppLayerResult::ok(),
1255 state.parse_response_tcp(&request)
1256 );
1257 }
1258
1259 // Test that a TCP DNS payload won't be parsed if there is not
1260 // enough data.
1261 #[test]
1262 fn test_dns_parse_response_tcp_short_payload() {
1263 // A UDP DNS response with the DNS payload starting at byte 42.
1264 // From pcap: https://github.com/jasonish/suricata-verify/blob/7cc0e1bd0a5249b52e6e87d82d57c0b6aaf75fce/dns-udp-dig-a-www-suricata-ids-org/dig-a-www.suricata-ids.org.pcap
1265 let buf: &[u8] = &[
1266 0xd8, 0xcb, 0x8a, 0xed, 0xa1, 0x46, 0x00, 0x15, /* .....F.. */
1267 0x17, 0x0d, 0x06, 0xf7, 0x08, 0x00, 0x45, 0x00, /* ......E. */
1268 0x00, 0x80, 0x65, 0x4e, 0x40, 0x00, 0x40, 0x11, /* ..eN@.@. */
1269 0xbe, 0xf3, 0x0a, 0x10, 0x01, 0x01, 0x0a, 0x10, /* ........ */
1270 0x01, 0x0b, 0x00, 0x35, 0xa3, 0x4d, 0x00, 0x6c, /* ...5.M.l */
1271 0x8d, 0x8c, 0x8d, 0x32, 0x81, 0xa0, 0x00, 0x01, /* ...2.... */
1272 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, /* .......w */
1273 0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1274 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1275 0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1276 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, /* ........ */
1277 0x0d, 0xd8, 0x00, 0x12, 0x0c, 0x73, 0x75, 0x72, /* .....sur */
1278 0x69, 0x63, 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, /* icata-id */
1279 0x73, 0x03, 0x6f, 0x72, 0x67, 0x00, 0xc0, 0x32, /* s.org..2 */
1280 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1281 0x00, 0x04, 0xc0, 0x00, 0x4e, 0x18, 0xc0, 0x32, /* ....N..2 */
1282 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1283 0x00, 0x04, 0xc0, 0x00, 0x4e, 0x19 /* ....N. */
1284 ];
1285
1286 // The DNS payload starts at offset 42.
1287 let dns_payload = &buf[42..];
1288
1289 // Make a TCP DNS response payload, but make the length 1 byte
1290 // larger than the actual size.
1291 let mut request = Vec::new();
1292 request.push(((dns_payload.len() as u16) >> 8) as u8);
1293 request.push((((dns_payload.len() as u16) & 0xff) + 1) as u8);
1294 request.extend(dns_payload);
1295
1296 let mut state = DNSState::new();
1297 assert_eq!(
1298 AppLayerResult::incomplete(0, 103),
1299 state.parse_response_tcp(&request)
1300 );
1301 }
1302
1303 // Port of the C RustDNSUDPParserTest02 unit test.
1304 #[test]
1305 fn test_dns_udp_parser_test_01() {
1306 /* query: abcdefghijk.com
1307 * TTL: 86400
1308 * serial 20130422 refresh 28800 retry 7200 exp 604800 min ttl 86400
1309 * ns, hostmaster */
1310 let buf: &[u8] = &[
1311 0x00, 0x3c, 0x85, 0x00, 0x00, 0x01, 0x00, 0x00,
1312 0x00, 0x01, 0x00, 0x00, 0x0b, 0x61, 0x62, 0x63,
1313 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
1314 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x0f, 0x00,
1315 0x01, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01,
1316 0x51, 0x80, 0x00, 0x25, 0x02, 0x6e, 0x73, 0x00,
1317 0x0a, 0x68, 0x6f, 0x73, 0x74, 0x6d, 0x61, 0x73,
1318 0x74, 0x65, 0x72, 0xc0, 0x2f, 0x01, 0x33, 0x2a,
1319 0x76, 0x00, 0x00, 0x70, 0x80, 0x00, 0x00, 0x1c,
1320 0x20, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01, 0x51,
1321 0x80,
1322 ];
1323 let mut state = DNSState::new();
1324 assert!(state.parse_response(buf));
1325 }
1326
1327 // Port of the C RustDNSUDPParserTest02 unit test.
1328 #[test]
1329 fn test_dns_udp_parser_test_02() {
1330 let buf: &[u8] = &[
1331 0x6D,0x08,0x84,0x80,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x01,0x03,0x57,0x57,0x57,
1332 0x04,0x54,0x54,0x54,0x54,0x03,0x56,0x56,0x56,0x03,0x63,0x6F,0x6D,0x02,0x79,0x79,
1333 0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,
1334 0x02,0xC0,0x0C,0xC0,0x31,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,
1335 0x31,0xC0,0x3F,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x3F,0xC0,
1336 0x4D,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x4D,0xC0,0x5B,0x00,
1337 0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x5B,0xC0,0x69,0x00,0x05,0x00,
1338 0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x69,0xC0,0x77,0x00,0x05,0x00,0x01,0x00,
1339 0x00,0x0E,0x10,0x00,0x02,0xC0,0x77,0xC0,0x85,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,
1340 0x10,0x00,0x02,0xC0,0x85,0x00,0x00,0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1341 ];
1342 let mut state = DNSState::new();
1343 assert!(state.parse_response(buf));
1344 }
1345
1346 // Port of the C RustDNSUDPParserTest03 unit test.
1347 #[test]
1348 fn test_dns_udp_parser_test_03() {
1349 let buf: &[u8] = &[
1350 0x6F,0xB4,0x84,0x80,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x03,0x03,0x57,0x57,0x77,
1351 0x0B,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x03,0x55,0x55,0x55,
1352 0x02,0x79,0x79,0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,
1353 0x0E,0x10,0x00,0x02,0xC0,0x10,0xC0,0x34,0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,
1354 0x00,0x04,0xC3,0xEA,0x04,0x19,0xC0,0x34,0x00,0x02,0x00,0x01,0x00,0x00,0x0E,0x10,
1355 0x00,0x0A,0x03,0x6E,0x73,0x31,0x03,0x61,0x67,0x62,0xC0,0x20,0xC0,0x46,0x00,0x02,
1356 0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x06,0x03,0x6E,0x73,0x32,0xC0,0x56,0xC0,0x52,
1357 0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x04,0x0A,0xC0,0x68,
1358 0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x05,0x14,0x00,0x00,
1359 0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00
1360 ];
1361 let mut state = DNSState::new();
1362 assert!(state.parse_response(buf));
1363 }
1364
1365 // Port of the C RustDNSUDPParserTest04 unit test.
1366 //
1367 // Test the TXT records in an answer.
1368 #[test]
1369 fn test_dns_udp_parser_test_04() {
1370 let buf: &[u8] = &[
1371 0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
1372 0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
1373 0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
1374 0x01,
1375 /* answer record start */
1376 0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
1377 /* txt record starts: */
1378 0x20, /* <txt len 32 */ 0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
1379 0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
1380 0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */ 0xc0,0x1d,0x00,0x02,0x00,0x01,
1381 0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
1382 0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
1383 ];
1384 let mut state = DNSState::new();
1385 assert!(state.parse_response(buf));
1386 }
1387
1388 // Port of the C RustDNSUDPParserTest05 unit test.
1389 //
1390 // Test TXT records in answer with a bad length.
1391 #[test]
1392 fn test_dns_udp_parser_test_05() {
1393 let buf: &[u8] = &[
1394 0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
1395 0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
1396 0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
1397 0x01,
1398 /* answer record start */
1399 0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
1400 /* txt record starts: */
1401 0x40, /* <txt len 64 */ 0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
1402 0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
1403 0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */ 0xc0,0x1d,0x00,0x02,0x00,0x01,
1404 0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
1405 0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
1406 ];
1407 let mut state = DNSState::new();
1408 assert!(!state.parse_response(buf));
1409 }
1410
1411 // Port of the C RustDNSTCPParserTestMultiRecord unit test.
1412 #[test]
1413 fn test_dns_tcp_parser_multi_record() {
1414 let buf: &[u8] = &[
1415 0x00, 0x1e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
1416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30,
1417 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1418 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1419 0x00, 0x1e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
1420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31,
1421 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1422 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1423 0x00, 0x1e, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01,
1424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x32,
1425 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1426 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1427 0x00, 0x1e, 0x00, 0x03, 0x01, 0x00, 0x00, 0x01,
1428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x33,
1429 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1430 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1431 0x00, 0x1e, 0x00, 0x04, 0x01, 0x00, 0x00, 0x01,
1432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x34,
1433 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1434 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1435 0x00, 0x1e, 0x00, 0x05, 0x01, 0x00, 0x00, 0x01,
1436 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x35,
1437 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1438 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1439 0x00, 0x1e, 0x00, 0x06, 0x01, 0x00, 0x00, 0x01,
1440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x36,
1441 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1442 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1443 0x00, 0x1e, 0x00, 0x07, 0x01, 0x00, 0x00, 0x01,
1444 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x37,
1445 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1446 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1447 0x00, 0x1e, 0x00, 0x08, 0x01, 0x00, 0x00, 0x01,
1448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38,
1449 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1450 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1451 0x00, 0x1e, 0x00, 0x09, 0x01, 0x00, 0x00, 0x01,
1452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x39,
1453 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1454 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1455 0x00, 0x1f, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x01,
1456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
1457 0x30, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
1458 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
1459 0x01, 0x00, 0x1f, 0x00, 0x0b, 0x01, 0x00, 0x00,
1460 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1461 0x31, 0x31, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
1462 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
1463 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0c, 0x01, 0x00,
1464 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1465 0x02, 0x31, 0x32, 0x06, 0x67, 0x6f, 0x6f, 0x67,
1466 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00,
1467 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0d, 0x01,
1468 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1469 0x00, 0x02, 0x31, 0x33, 0x06, 0x67, 0x6f, 0x6f,
1470 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
1471 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0e,
1472 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1473 0x00, 0x00, 0x02, 0x31, 0x34, 0x06, 0x67, 0x6f,
1474 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d,
1475 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00,
1476 0x0f, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1477 0x00, 0x00, 0x00, 0x02, 0x31, 0x35, 0x06, 0x67,
1478 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f,
1479 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f,
1480 0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
1481 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x36, 0x06,
1482 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63,
1483 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
1484 0x1f, 0x00, 0x11, 0x01, 0x00, 0x00, 0x01, 0x00,
1485 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x37,
1486 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1487 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1488 0x00, 0x1f, 0x00, 0x12, 0x01, 0x00, 0x00, 0x01,
1489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
1490 0x38, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
1491 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
1492 0x01, 0x00, 0x1f, 0x00, 0x13, 0x01, 0x00, 0x00,
1493 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1494 0x31, 0x39, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
1495 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
1496 0x00, 0x01
1497 ];
1498 let mut state = DNSState::new();
1499 assert_eq!(
1500 AppLayerResult::ok(),
1501 state.parse_request_tcp(buf)
1502 );
1503 }
1504
1505 #[test]
1506 fn test_dns_tcp_parser_split_payload() {
1507 /* incomplete payload */
1508 let buf1: &[u8] = &[
1509 0x00, 0x1c, 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
1510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1511 ];
1512 /* complete payload plus the start of a new payload */
1513 let buf2: &[u8] = &[
1514 0x00, 0x1c, 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
1515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1516 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x03,
1517 0x63, 0x6F, 0x6D, 0x00, 0x00, 0x10, 0x00, 0x01,
1518
1519 // next.
1520 0x00, 0x1c, 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
1521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1522 ];
1523
1524 /* and the complete payload again with no trailing data. */
1525 let buf3: &[u8] = &[
1526 0x00, 0x1c, 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
1527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1528 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x03,
1529 0x63, 0x6F, 0x6D, 0x00, 0x00, 0x10, 0x00, 0x01,
1530 ];
1531
1532 let mut state = DNSState::new();
1533 assert_eq!(
1534 AppLayerResult::incomplete(0, 30),
1535 state.parse_request_tcp(buf1)
1536 );
1537 assert_eq!(
1538 AppLayerResult::incomplete(30, 30),
1539 state.parse_request_tcp(buf2)
1540 );
1541 assert_eq!(
1542 AppLayerResult::ok(),
1543 state.parse_request_tcp(buf3)
1544 );
1545 }
1546 }