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