1 /* Copyright (C) 2017 Open Information Security Foundation
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
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.
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
21 use std::ffi::CString;
22 use std::mem::transmute;
23 use std::collections::HashMap;
24 use std::collections::VecDeque;
27 use crate::applayer::*;
28 use crate::core::{self, AppProto, ALPROTO_UNKNOWN, IPPROTO_UDP, IPPROTO_TCP};
29 use crate::dns::parser;
32 use nom::number::streaming::be_u16;
35 pub const DNS_RECORD_TYPE_A : u16 = 1;
36 pub const DNS_RECORD_TYPE_NS : u16 = 2;
37 pub const DNS_RECORD_TYPE_MD : u16 = 3; // Obsolete
38 pub const DNS_RECORD_TYPE_MF : u16 = 4; // Obsolete
39 pub const DNS_RECORD_TYPE_CNAME : u16 = 5;
40 pub const DNS_RECORD_TYPE_SOA : u16 = 6;
41 pub const DNS_RECORD_TYPE_MB : u16 = 7; // Experimental
42 pub const DNS_RECORD_TYPE_MG : u16 = 8; // Experimental
43 pub const DNS_RECORD_TYPE_MR : u16 = 9; // Experimental
44 pub const DNS_RECORD_TYPE_NULL : u16 = 10; // Experimental
45 pub const DNS_RECORD_TYPE_WKS : u16 = 11;
46 pub const DNS_RECORD_TYPE_PTR : u16 = 12;
47 pub const DNS_RECORD_TYPE_HINFO : u16 = 13;
48 pub const DNS_RECORD_TYPE_MINFO : u16 = 14;
49 pub const DNS_RECORD_TYPE_MX : u16 = 15;
50 pub const DNS_RECORD_TYPE_TXT : u16 = 16;
51 pub const DNS_RECORD_TYPE_RP : u16 = 17;
52 pub const DNS_RECORD_TYPE_AFSDB : u16 = 18;
53 pub const DNS_RECORD_TYPE_X25 : u16 = 19;
54 pub const DNS_RECORD_TYPE_ISDN : u16 = 20;
55 pub const DNS_RECORD_TYPE_RT : u16 = 21;
56 pub const DNS_RECORD_TYPE_NSAP : u16 = 22;
57 pub const DNS_RECORD_TYPE_NSAPPTR : u16 = 23;
58 pub const DNS_RECORD_TYPE_SIG : u16 = 24;
59 pub const DNS_RECORD_TYPE_KEY : u16 = 25;
60 pub const DNS_RECORD_TYPE_PX : u16 = 26;
61 pub const DNS_RECORD_TYPE_GPOS : u16 = 27;
62 pub const DNS_RECORD_TYPE_AAAA : u16 = 28;
63 pub const DNS_RECORD_TYPE_LOC : u16 = 29;
64 pub const DNS_RECORD_TYPE_NXT : u16 = 30; // Obsolete
65 pub const DNS_RECORD_TYPE_SRV : u16 = 33;
66 pub const DNS_RECORD_TYPE_ATMA : u16 = 34;
67 pub const DNS_RECORD_TYPE_NAPTR : u16 = 35;
68 pub const DNS_RECORD_TYPE_KX : u16 = 36;
69 pub const DNS_RECORD_TYPE_CERT : u16 = 37;
70 pub const DNS_RECORD_TYPE_A6 : u16 = 38; // Obsolete
71 pub const DNS_RECORD_TYPE_DNAME : u16 = 39;
72 pub const DNS_RECORD_TYPE_OPT : u16 = 41;
73 pub const DNS_RECORD_TYPE_APL : u16 = 42;
74 pub const DNS_RECORD_TYPE_DS : u16 = 43;
75 pub const DNS_RECORD_TYPE_SSHFP : u16 = 44;
76 pub const DNS_RECORD_TYPE_IPSECKEY : u16 = 45;
77 pub const DNS_RECORD_TYPE_RRSIG : u16 = 46;
78 pub const DNS_RECORD_TYPE_NSEC : u16 = 47;
79 pub const DNS_RECORD_TYPE_DNSKEY : u16 = 48;
80 pub const DNS_RECORD_TYPE_DHCID : u16 = 49;
81 pub const DNS_RECORD_TYPE_NSEC3 : u16 = 50;
82 pub const DNS_RECORD_TYPE_NSEC3PARAM : u16 = 51;
83 pub const DNS_RECORD_TYPE_TLSA : u16 = 52;
84 pub const DNS_RECORD_TYPE_HIP : u16 = 55;
85 pub const DNS_RECORD_TYPE_CDS : u16 = 59;
86 pub const DNS_RECORD_TYPE_CDNSKEY : u16 = 60;
87 pub const DNS_RECORD_TYPE_SPF : u16 = 99; // Obsolete
88 pub const DNS_RECORD_TYPE_TKEY : u16 = 249;
89 pub const DNS_RECORD_TYPE_TSIG : u16 = 250;
90 pub const DNS_RECORD_TYPE_MAILA : u16 = 254; // Obsolete
91 pub const DNS_RECORD_TYPE_ANY : u16 = 255;
92 pub const DNS_RECORD_TYPE_URI : u16 = 256;
95 pub const DNS_RCODE_NOERROR: u16 = 0;
96 pub const DNS_RCODE_FORMERR: u16 = 1;
97 pub const DNS_RCODE_SERVFAIL: u16 = 2;
98 pub const DNS_RCODE_NXDOMAIN: u16 = 3;
99 pub const DNS_RCODE_NOTIMP: u16 = 4;
100 pub const DNS_RCODE_REFUSED: u16 = 5;
101 pub const DNS_RCODE_YXDOMAIN: u16 = 6;
102 pub const DNS_RCODE_YXRRSET: u16 = 7;
103 pub const DNS_RCODE_NXRRSET: u16 = 8;
104 pub const DNS_RCODE_NOTAUTH: u16 = 9;
105 pub const DNS_RCODE_NOTZONE: u16 = 10;
106 // Support for OPT RR from RFC6891 will be needed to
107 // parse RCODE values over 15
108 pub const DNS_RCODE_BADVERS: u16 = 16;
109 pub const DNS_RCODE_BADSIG: u16 = 16;
110 pub const DNS_RCODE_BADKEY: u16 = 17;
111 pub const DNS_RCODE_BADTIME: u16 = 18;
112 pub const DNS_RCODE_BADMODE: u16 = 19;
113 pub const DNS_RCODE_BADNAME: u16 = 20;
114 pub const DNS_RCODE_BADALG: u16 = 21;
115 pub const DNS_RCODE_BADTRUNC: u16 = 22;
118 /// The maximum number of transactions to keep in the queue pending
119 /// processing before they are aggressively purged. Due to the
120 /// stateless nature of this parser this is rarely needed, especially
121 /// when one call to parse a request parses and a single request, and
122 /// likewise for responses.
124 /// Where this matters is when one TCP buffer contains multiple
125 /// requests are responses and one call into the parser creates
126 /// multiple transactions. In this case we have to hold onto
127 /// transactions longer than until handling the next transaction so it
129 const MAX_TRANSACTIONS: usize = 32;
131 static mut ALPROTO_DNS: AppProto = ALPROTO_UNKNOWN;
142 pub fn to_cstring(&self) -> &str {
144 DNSEvent::MalformedData => "MALFORMED_DATA\0",
145 DNSEvent::NotRequest => "NOT_A_REQUEST\0",
146 DNSEvent::NotResponse => "NOT_A_RESPONSE\0",
147 DNSEvent::ZFlagSet => "Z_FLAG_SET\0",
151 pub fn from_id(id: u32) -> Option<DNSEvent> {
153 0 => Some(DNSEvent::MalformedData),
154 1 => Some(DNSEvent::NotRequest),
155 2 => Some(DNSEvent::NotResponse),
156 4 => Some(DNSEvent::ZFlagSet),
161 pub fn from_string(s: &str) -> Option<DNSEvent> {
162 match s.to_lowercase().as_ref() {
163 "malformed_data" => Some(DNSEvent::MalformedData),
164 "not_a_request" => Some(DNSEvent::NotRequest),
165 "not_a_response" => Some(DNSEvent::NotRequest),
166 "z_flag_set" => Some(DNSEvent::ZFlagSet),
173 pub extern "C" fn rs_dns_state_get_event_info_by_id(
174 event_id: std::os::raw::c_int,
175 event_name: *mut *const std::os::raw::c_char,
176 event_type: *mut core::AppLayerEventType,
178 if let Some(e) = DNSEvent::from_id(event_id as u32) {
180 *event_name = e.to_cstring().as_ptr() as *const std::os::raw::c_char;
181 *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
189 pub extern "C" fn rs_dns_state_get_event_info(
190 event_name: *const std::os::raw::c_char,
191 event_id: *mut std::os::raw::c_int,
192 event_type: *mut core::AppLayerEventType
193 ) -> std::os::raw::c_int {
194 if event_name == std::ptr::null() {
198 let event_name = unsafe { std::ffi::CStr::from_ptr(event_name) };
199 if let Ok(event_name) = event_name.to_str() {
200 if let Some(event) = DNSEvent::from_string(event_name) {
202 *event_id = event as std::os::raw::c_int;
203 *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
210 // UTF-8 conversion failed. Should not happen.
217 #[derive(Debug,PartialEq)]
219 pub struct DNSHeader {
224 pub authority_rr: u16,
225 pub additional_rr: u16,
229 pub struct DNSQueryEntry {
235 #[derive(Debug,PartialEq)]
236 pub struct DNSAnswerEntry {
245 pub struct DNSRequest {
246 pub header: DNSHeader,
247 pub queries: Vec<DNSQueryEntry>,
251 pub struct DNSResponse {
252 pub header: DNSHeader,
253 pub queries: Vec<DNSQueryEntry>,
254 pub answers: Vec<DNSAnswerEntry>,
255 pub authorities: Vec<DNSAnswerEntry>,
259 pub struct DNSTransaction {
261 pub request: Option<DNSRequest>,
262 pub response: Option<DNSResponse>,
263 pub de_state: Option<*mut core::DetectEngineState>,
264 pub events: *mut core::AppLayerDecoderEvents,
265 pub tx_data: AppLayerTxData,
268 impl DNSTransaction {
270 pub fn new() -> DNSTransaction {
271 return DNSTransaction{
276 events: std::ptr::null_mut(),
277 tx_data: AppLayerTxData::new(),
281 pub fn free(&mut self) {
282 if self.events != std::ptr::null_mut() {
283 core::sc_app_layer_decoder_events_free_events(&mut self.events);
285 match self.de_state {
287 core::sc_detect_engine_state_free(state);
293 /// Get the DNS transactions ID (not the internal tracking ID).
294 pub fn tx_id(&self) -> u16 {
295 if let &Some(ref request) = &self.request {
296 return request.header.tx_id;
298 if let &Some(ref response) = &self.response {
299 return response.header.tx_id;
306 /// Get the reply code of the transaction. Note that this will
307 /// also return 0 if there is no reply.
308 pub fn rcode(&self) -> u16 {
309 if let &Some(ref response) = &self.response {
310 return response.header.flags & 0x000f;
317 impl Drop for DNSTransaction {
323 struct ConfigTracker {
324 map: HashMap<u16, AppLayerTxConfig>,
325 queue: VecDeque<u16>,
329 fn new() -> ConfigTracker {
332 queue: VecDeque::new(),
336 fn add(&mut self, id: u16, config: AppLayerTxConfig) {
337 // If at size limit, remove the oldest entry.
338 if self.queue.len() > 499 {
339 if let Some(id) = self.queue.pop_front() {
340 self.map.remove(&id);
344 self.map.insert(id, config);
345 self.queue.push_back(id);
348 fn remove(&mut self, id: &u16) -> Option<AppLayerTxConfig> {
353 pub struct DNSState {
354 // Internal transaction ID.
358 pub transactions: Vec<DNSTransaction>,
362 pub request_buffer: Vec<u8>,
363 pub response_buffer: Vec<u8>,
365 config: Option<ConfigTracker>,
372 pub fn new() -> DNSState {
375 transactions: Vec::new(),
377 request_buffer: Vec::new(),
378 response_buffer: Vec::new(),
384 /// Allocate a new state with capacites in the buffers for
385 /// potentially buffering as might be needed in TCP.
386 pub fn new_tcp() -> DNSState {
389 transactions: Vec::new(),
391 request_buffer: Vec::with_capacity(0xffff),
392 response_buffer: Vec::with_capacity(0xffff),
398 pub fn new_tx(&mut self) -> DNSTransaction {
399 let mut tx = DNSTransaction::new();
405 pub fn free_tx(&mut self, tx_id: u64) {
406 let len = self.transactions.len();
407 let mut found = false;
410 let tx = &self.transactions[i];
411 if tx.id == tx_id + 1 {
418 self.transactions.remove(index);
422 // Purges all transactions except one. This is a stateless parser
423 // so we don't need to hang onto old transactions.
425 // This is to actually handle an edge case where a DNS flood
426 // occurs in a single direction with no response packets. In such
427 // a case the functions to free a transaction are never called by
428 // the app-layer as they require bidirectional traffic.
429 pub fn purge(&mut self, tx_id: u64) {
430 while self.transactions.len() > MAX_TRANSACTIONS {
431 if self.transactions[0].id == tx_id + 1 {
434 SCLogDebug!("Purging DNS TX with ID {}", self.transactions[0].id);
435 self.transactions.remove(0);
439 pub fn get_tx(&mut self, tx_id: u64) -> Option<&DNSTransaction> {
440 SCLogDebug!("get_tx: tx_id={}", tx_id);
442 for tx in &mut self.transactions {
443 if tx.id == tx_id + 1 {
444 SCLogDebug!("Found DNS TX with ID {}", tx_id);
448 SCLogDebug!("Failed to find DNS TX with ID {}", tx_id);
452 /// Set an event. The event is set on the most recent transaction.
453 pub fn set_event(&mut self, event: DNSEvent) {
454 let len = self.transactions.len();
459 let tx = &mut self.transactions[len - 1];
460 core::sc_app_layer_decoder_events_set_event_raw(&mut tx.events,
465 pub fn parse_request(&mut self, input: &[u8]) -> bool {
466 match parser::dns_parse_request(input) {
467 Ok((_, request)) => {
468 if request.header.flags & 0x8000 != 0 {
469 SCLogDebug!("DNS message is not a request");
470 self.set_event(DNSEvent::NotRequest);
474 if request.header.flags & 0x0040 != 0 {
475 SCLogDebug!("Z-flag set on DNS response");
476 self.set_event(DNSEvent::ZFlagSet);
480 let mut tx = self.new_tx();
481 tx.request = Some(request);
482 self.transactions.push(tx);
485 Err(nom::Err::Incomplete(_)) => {
486 // Insufficient data.
487 SCLogDebug!("Insufficient data while parsing DNS request");
488 self.set_event(DNSEvent::MalformedData);
492 // Error, probably malformed data.
493 SCLogDebug!("An error occurred while parsing DNS request");
494 self.set_event(DNSEvent::MalformedData);
500 pub fn parse_response(&mut self, input: &[u8]) -> bool {
501 match parser::dns_parse_response(input) {
502 Ok((_, response)) => {
504 SCLogDebug!("Response header flags: {}", response.header.flags);
506 if response.header.flags & 0x8000 == 0 {
507 SCLogDebug!("DNS message is not a response");
508 self.set_event(DNSEvent::NotResponse);
511 if response.header.flags & 0x0040 != 0 {
512 SCLogDebug!("Z-flag set on DNS response");
513 self.set_event(DNSEvent::ZFlagSet);
517 let mut tx = self.new_tx();
518 if let Some(ref mut config) = &mut self.config {
519 if let Some(config) = config.remove(&response.header.tx_id) {
520 tx.tx_data.config = config;
523 tx.response = Some(response);
524 self.transactions.push(tx);
527 Err(nom::Err::Incomplete(_)) => {
528 // Insufficient data.
529 SCLogDebug!("Insufficient data while parsing DNS response");
530 self.set_event(DNSEvent::MalformedData);
534 // Error, probably malformed data.
535 SCLogDebug!("An error occurred while parsing DNS response");
536 self.set_event(DNSEvent::MalformedData);
542 /// TCP variation of response request parser to handle the length
543 /// prefix as well as buffering.
545 /// Always buffer and read from the buffer. Should optimize to skip
546 /// the buffer if not needed.
548 /// Returns the number of messages parsed.
549 pub fn parse_request_tcp(&mut self, input: &[u8]) -> i8 {
551 let (is_dns, _, is_incomplete) = probe_tcp(input);
552 if is_dns || is_incomplete{
559 self.request_buffer.extend_from_slice(input);
562 while self.request_buffer.len() > 0 {
563 let size = match be_u16(&self.request_buffer) as IResult<&[u8],_> {
564 Ok((_, len)) => i32::from(len),
567 SCLogDebug!("Have {} bytes, need {} to parse",
568 self.request_buffer.len(), size);
569 if size > 0 && self.request_buffer.len() >= size + 2 {
570 let msg: Vec<u8> = self.request_buffer.drain(0..(size + 2))
572 if self.parse_request(&msg[2..]) {
576 SCLogDebug!("Not enough DNS traffic to parse.");
583 /// TCP variation of the response parser to handle the length
584 /// prefix as well as buffering.
586 /// Always buffer and read from the buffer. Should optimize to skip
587 /// the buffer if not needed.
589 /// Returns the number of messages parsed.
590 pub fn parse_response_tcp(&mut self, input: &[u8]) -> i8 {
592 let (is_dns, _, is_incomplete) = probe_tcp(input);
593 if is_dns || is_incomplete{
600 self.response_buffer.extend_from_slice(input);
603 while self.response_buffer.len() > 0 {
604 let size = match be_u16(&self.response_buffer) as IResult<&[u8],_> {
605 Ok((_, len)) => i32::from(len),
608 if size > 0 && self.response_buffer.len() >= size + 2 {
609 let msg: Vec<u8> = self.response_buffer.drain(0..(size + 2))
611 if self.parse_response(&msg[2..]) {
621 /// A gap has been seen in the request direction. Set the gap flag
622 /// to clear any buffered data.
623 pub fn request_gap(&mut self, gap: u32) {
625 self.request_buffer.clear();
630 /// A gap has been seen in the response direction. Set the gap
631 /// flag to clear any buffered data.
632 pub fn response_gap(&mut self, gap: u32) {
634 self.response_buffer.clear();
640 /// Probe input to see if it looks like DNS.
641 fn probe(input: &[u8]) -> (bool, bool) {
642 match parser::dns_parse_request(input) {
643 Ok((_, request)) => {
644 let is_request = request.header.flags & 0x8000 == 0;
645 return (true, is_request);
647 Err(_) => (false, false),
651 /// Probe TCP input to see if it looks like DNS.
652 pub fn probe_tcp(input: &[u8]) -> (bool, bool, bool) {
653 match be_u16(input) as IResult<&[u8],_> {
656 return (r.0, r.1, false);
658 Err(nom::Err::Incomplete(_)) => {
659 return (false, false, true);
663 return (false, false, false);
666 /// Returns *mut DNSState
668 pub extern "C" fn rs_dns_state_new() -> *mut std::os::raw::c_void {
669 let state = DNSState::new();
670 let boxed = Box::new(state);
671 return unsafe{transmute(boxed)};
674 /// Returns *mut DNSState
676 pub extern "C" fn rs_dns_state_tcp_new() -> *mut std::os::raw::c_void {
677 let state = DNSState::new_tcp();
678 let boxed = Box::new(state);
679 return unsafe{transmute(boxed)};
683 /// - state: *mut DNSState as void pointer
685 pub extern "C" fn rs_dns_state_free(state: *mut std::os::raw::c_void) {
687 let _drop: Box<DNSState> = unsafe{transmute(state)};
691 pub extern "C" fn rs_dns_state_tx_free(state: *mut std::os::raw::c_void,
694 let state = cast_pointer!(state, DNSState);
695 state.free_tx(tx_id);
698 /// C binding parse a DNS request. Returns 1 on success, -1 on failure.
700 pub extern "C" fn rs_dns_parse_request(_flow: *const core::Flow,
701 state: *mut std::os::raw::c_void,
702 _pstate: *mut std::os::raw::c_void,
705 _data: *const std::os::raw::c_void,
708 let state = cast_pointer!(state, DNSState);
709 let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)};
710 if state.parse_request(buf) {
713 AppLayerResult::err()
718 pub extern "C" fn rs_dns_parse_response(_flow: *const core::Flow,
719 state: *mut std::os::raw::c_void,
720 _pstate: *mut std::os::raw::c_void,
723 _data: *const std::os::raw::c_void,
726 let state = cast_pointer!(state, DNSState);
727 let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)};
728 if state.parse_response(buf) {
731 AppLayerResult::err()
735 /// C binding parse a DNS request. Returns 1 on success, -1 on failure.
737 pub extern "C" fn rs_dns_parse_request_tcp(_flow: *const core::Flow,
738 state: *mut std::os::raw::c_void,
739 _pstate: *mut std::os::raw::c_void,
742 _data: *const std::os::raw::c_void,
745 let state = cast_pointer!(state, DNSState);
747 if input != std::ptr::null_mut() {
749 std::slice::from_raw_parts(input, input_len as usize)};
750 let _ = state.parse_request_tcp(buf);
751 return AppLayerResult::ok();
753 state.request_gap(input_len);
759 pub extern "C" fn rs_dns_parse_response_tcp(_flow: *const core::Flow,
760 state: *mut std::os::raw::c_void,
761 _pstate: *mut std::os::raw::c_void,
764 _data: *const std::os::raw::c_void,
767 let state = cast_pointer!(state, DNSState);
769 if input != std::ptr::null_mut() {
771 std::slice::from_raw_parts(input, input_len as usize)};
772 let _ = state.parse_response_tcp(buf);
773 return AppLayerResult::ok();
775 state.response_gap(input_len);
781 pub extern "C" fn rs_dns_state_progress_completion_status(
783 -> std::os::raw::c_int
785 SCLogDebug!("rs_dns_state_progress_completion_status");
790 pub extern "C" fn rs_dns_tx_get_alstate_progress(_tx: *mut std::os::raw::c_void,
792 -> std::os::raw::c_int
794 // This is a stateless parser, just the existence of a transaction
795 // means its complete.
796 SCLogDebug!("rs_dns_tx_get_alstate_progress");
801 pub extern "C" fn rs_dns_state_get_tx_count(state: *mut std::os::raw::c_void)
804 let state = cast_pointer!(state, DNSState);
805 SCLogDebug!("rs_dns_state_get_tx_count: returning {}", state.tx_id);
810 pub extern "C" fn rs_dns_state_get_tx(state: *mut std::os::raw::c_void,
812 -> *mut std::os::raw::c_void
814 let state = cast_pointer!(state, DNSState);
815 match state.get_tx(tx_id) {
817 return unsafe{transmute(tx)};
820 return std::ptr::null_mut();
826 pub extern "C" fn rs_dns_state_set_tx_detect_state(
827 tx: *mut std::os::raw::c_void,
828 de_state: &mut core::DetectEngineState) -> std::os::raw::c_int
830 let tx = cast_pointer!(tx, DNSTransaction);
831 tx.de_state = Some(de_state);
836 pub extern "C" fn rs_dns_state_get_tx_detect_state(
837 tx: *mut std::os::raw::c_void)
838 -> *mut core::DetectEngineState
840 let tx = cast_pointer!(tx, DNSTransaction);
846 return std::ptr::null_mut();
852 pub extern "C" fn rs_dns_state_get_events(tx: *mut std::os::raw::c_void)
853 -> *mut core::AppLayerDecoderEvents
855 let tx = cast_pointer!(tx, DNSTransaction);
860 pub extern "C" fn rs_dns_state_get_tx_data(
861 tx: *mut std::os::raw::c_void)
862 -> *mut AppLayerTxData
864 let tx = cast_pointer!(tx, DNSTransaction);
865 return &mut tx.tx_data;
869 pub extern "C" fn rs_dns_tx_get_query_name(tx: &mut DNSTransaction,
875 if let &Some(ref request) = &tx.request {
876 if (i as usize) < request.queries.len() {
877 let query = &request.queries[i as usize];
878 if query.name.len() > 0 {
880 *len = query.name.len() as u32;
881 *buf = query.name.as_ptr();
890 /// Get the DNS transaction ID of a transaction.
892 /// extern uint16_t rs_dns_tx_get_tx_id(RSDNSTransaction *);
894 pub extern "C" fn rs_dns_tx_get_tx_id(tx: &mut DNSTransaction) -> u16
899 /// Get the DNS response flags for a transaction.
901 /// extern uint16_t rs_dns_tx_get_response_flags(RSDNSTransaction *);
903 pub extern "C" fn rs_dns_tx_get_response_flags(tx: &mut DNSTransaction)
910 pub extern "C" fn rs_dns_tx_get_query_rrtype(tx: &mut DNSTransaction,
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 {
920 *rrtype = query.rrtype;
930 pub extern "C" fn rs_dns_probe(
931 _flow: *const core::Flow,
937 if len == 0 || len < std::mem::size_of::<DNSHeader>() as u32 {
938 return core::ALPROTO_UNKNOWN;
940 let slice: &[u8] = unsafe {
941 std::slice::from_raw_parts(input as *mut u8, len as usize)
943 let (is_dns, is_request) = probe(slice);
945 let dir = if is_request {
946 core::STREAM_TOSERVER
948 core::STREAM_TOCLIENT
959 pub extern "C" fn rs_dns_probe_tcp(
960 _flow: *const core::Flow,
966 if len == 0 || len < std::mem::size_of::<DNSHeader>() as u32 + 2 {
967 return core::ALPROTO_UNKNOWN;
969 let slice: &[u8] = unsafe {
970 std::slice::from_raw_parts(input as *mut u8, len as usize)
972 //is_incomplete is checked by caller
973 let (is_dns, is_request, _) = probe_tcp(slice);
975 let dir = if is_request {
976 core::STREAM_TOSERVER
978 core::STREAM_TOCLIENT
980 if direction & (core::STREAM_TOSERVER|core::STREAM_TOCLIENT) != dir {
981 unsafe { *rdir = dir };
983 return unsafe { ALPROTO_DNS };
989 pub extern "C" fn rs_dns_apply_tx_config(
990 _state: *mut std::os::raw::c_void, _tx: *mut std::os::raw::c_void,
991 _mode: std::os::raw::c_int, config: AppLayerTxConfig
993 let tx = cast_pointer!(_tx, DNSTransaction);
994 let state = cast_pointer!(_state, DNSState);
995 if let Some(request) = &tx.request {
996 if state.config.is_none() {
997 state.config = Some(ConfigTracker::new());
999 if let Some(ref mut tracker) = &mut state.config {
1000 tracker.add(request.header.tx_id, config);
1006 pub unsafe extern "C" fn rs_dns_init(proto: AppProto) {
1007 ALPROTO_DNS = proto;
1011 pub unsafe extern "C" fn rs_dns_udp_register_parser() {
1012 let default_port = std::ffi::CString::new("[53]").unwrap();
1013 let parser = RustParser{
1014 name: b"dns\0".as_ptr() as *const std::os::raw::c_char,
1015 default_port: default_port.as_ptr(),
1016 ipproto: IPPROTO_UDP,
1017 probe_ts: Some(rs_dns_probe),
1018 probe_tc: Some(rs_dns_probe),
1020 max_depth: std::mem::size_of::<DNSHeader>() as u16,
1021 state_new: rs_dns_state_new,
1022 state_free: rs_dns_state_free,
1023 tx_free: rs_dns_state_tx_free,
1024 parse_ts: rs_dns_parse_request,
1025 parse_tc: rs_dns_parse_response,
1026 get_tx_count: rs_dns_state_get_tx_count,
1027 get_tx: rs_dns_state_get_tx,
1028 tx_get_comp_st: rs_dns_state_progress_completion_status,
1029 tx_get_progress: rs_dns_tx_get_alstate_progress,
1030 get_events: Some(rs_dns_state_get_events),
1031 get_eventinfo: Some(rs_dns_state_get_event_info),
1032 get_eventinfo_byid: Some(rs_dns_state_get_event_info_by_id),
1033 localstorage_new: None,
1034 localstorage_free: None,
1036 get_tx_iterator: None,
1037 get_de_state: rs_dns_state_get_tx_detect_state,
1038 set_de_state: rs_dns_state_set_tx_detect_state,
1039 get_tx_data: rs_dns_state_get_tx_data,
1040 apply_tx_config: Some(rs_dns_apply_tx_config),
1044 let ip_proto_str = CString::new("udp").unwrap();
1045 if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1046 let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
1047 ALPROTO_DNS = alproto;
1048 if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1049 let _ = AppLayerRegisterParser(&parser, alproto);
1051 AppLayerParserRegisterOptionFlags(IPPROTO_UDP as u8, ALPROTO_DNS,
1052 crate::applayer::APP_LAYER_PARSER_OPT_UNIDIR_TXS);
1057 pub unsafe extern "C" fn rs_dns_tcp_register_parser() {
1058 let default_port = std::ffi::CString::new("53").unwrap();
1059 let parser = RustParser{
1060 name: b"dns\0".as_ptr() as *const std::os::raw::c_char,
1061 default_port: default_port.as_ptr(),
1062 ipproto: IPPROTO_TCP,
1063 probe_ts: Some(rs_dns_probe_tcp),
1064 probe_tc: Some(rs_dns_probe_tcp),
1066 max_depth: std::mem::size_of::<DNSHeader>() as u16 + 2,
1067 state_new: rs_dns_state_new,
1068 state_free: rs_dns_state_free,
1069 tx_free: rs_dns_state_tx_free,
1070 parse_ts: rs_dns_parse_request_tcp,
1071 parse_tc: rs_dns_parse_response_tcp,
1072 get_tx_count: rs_dns_state_get_tx_count,
1073 get_tx: rs_dns_state_get_tx,
1074 tx_get_comp_st: rs_dns_state_progress_completion_status,
1075 tx_get_progress: rs_dns_tx_get_alstate_progress,
1076 get_events: Some(rs_dns_state_get_events),
1077 get_eventinfo: Some(rs_dns_state_get_event_info),
1078 get_eventinfo_byid: Some(rs_dns_state_get_event_info_by_id),
1079 localstorage_new: None,
1080 localstorage_free: None,
1082 get_tx_iterator: None,
1083 get_de_state: rs_dns_state_get_tx_detect_state,
1084 set_de_state: rs_dns_state_set_tx_detect_state,
1085 get_tx_data: rs_dns_state_get_tx_data,
1086 apply_tx_config: Some(rs_dns_apply_tx_config),
1090 let ip_proto_str = CString::new("tcp").unwrap();
1091 if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1092 let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
1093 ALPROTO_DNS = alproto;
1094 if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1095 let _ = AppLayerRegisterParser(&parser, alproto);
1097 AppLayerParserRegisterOptionFlags(IPPROTO_TCP as u8, ALPROTO_DNS,
1098 crate::applayer::APP_LAYER_PARSER_OPT_ACCEPT_GAPS);
1099 AppLayerParserRegisterOptionFlags(IPPROTO_TCP as u8, ALPROTO_DNS,
1100 crate::applayer::APP_LAYER_PARSER_OPT_UNIDIR_TXS);
1110 fn test_dns_parse_request_tcp_valid() {
1111 // A UDP DNS request with the DNS payload starting at byte 42.
1112 // 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
1114 0x00, 0x15, 0x17, 0x0d, 0x06, 0xf7, 0xd8, 0xcb, /* ........ */
1115 0x8a, 0xed, 0xa1, 0x46, 0x08, 0x00, 0x45, 0x00, /* ...F..E. */
1116 0x00, 0x4d, 0x23, 0x11, 0x00, 0x00, 0x40, 0x11, /* .M#...@. */
1117 0x41, 0x64, 0x0a, 0x10, 0x01, 0x0b, 0x0a, 0x10, /* Ad...... */
1118 0x01, 0x01, 0xa3, 0x4d, 0x00, 0x35, 0x00, 0x39, /* ...M.5.9 */
1119 0xb2, 0xb3, 0x8d, 0x32, 0x01, 0x20, 0x00, 0x01, /* ...2. .. */
1120 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x77, /* .......w */
1121 0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1122 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1123 0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1124 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00, /* ..)..... */
1125 0x00, 0x00, 0x00 /* ... */
1128 // The DNS payload starts at offset 42.
1129 let dns_payload = &buf[42..];
1131 // Make a TCP DNS request payload.
1132 let mut request = Vec::new();
1133 request.push(((dns_payload.len() as u16) >> 8) as u8);
1134 request.push(((dns_payload.len() as u16) & 0xff) as u8);
1135 request.extend(dns_payload);
1137 let mut state = DNSState::new();
1138 assert_eq!(1, state.parse_request_tcp(&request));
1142 fn test_dns_parse_request_tcp_short_payload() {
1143 // A UDP DNS request with the DNS payload starting at byte 42.
1144 // 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
1146 0x00, 0x15, 0x17, 0x0d, 0x06, 0xf7, 0xd8, 0xcb, /* ........ */
1147 0x8a, 0xed, 0xa1, 0x46, 0x08, 0x00, 0x45, 0x00, /* ...F..E. */
1148 0x00, 0x4d, 0x23, 0x11, 0x00, 0x00, 0x40, 0x11, /* .M#...@. */
1149 0x41, 0x64, 0x0a, 0x10, 0x01, 0x0b, 0x0a, 0x10, /* Ad...... */
1150 0x01, 0x01, 0xa3, 0x4d, 0x00, 0x35, 0x00, 0x39, /* ...M.5.9 */
1151 0xb2, 0xb3, 0x8d, 0x32, 0x01, 0x20, 0x00, 0x01, /* ...2. .. */
1152 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x77, /* .......w */
1153 0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1154 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1155 0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1156 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00, /* ..)..... */
1157 0x00, 0x00, 0x00 /* ... */
1160 // The DNS payload starts at offset 42.
1161 let dns_payload = &buf[42..];
1163 // Make a TCP DNS request payload but with the length 1 larger
1164 // than the available data.
1165 let mut request = Vec::new();
1166 request.push(((dns_payload.len() as u16) >> 8) as u8);
1167 request.push(((dns_payload.len() as u16) & 0xff) as u8 + 1);
1168 request.extend(dns_payload);
1170 let mut state = DNSState::new();
1171 assert_eq!(0, state.parse_request_tcp(&request));
1175 fn test_dns_parse_response_tcp_valid() {
1176 // A UDP DNS response with the DNS payload starting at byte 42.
1177 // 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
1179 0xd8, 0xcb, 0x8a, 0xed, 0xa1, 0x46, 0x00, 0x15, /* .....F.. */
1180 0x17, 0x0d, 0x06, 0xf7, 0x08, 0x00, 0x45, 0x00, /* ......E. */
1181 0x00, 0x80, 0x65, 0x4e, 0x40, 0x00, 0x40, 0x11, /* ..eN@.@. */
1182 0xbe, 0xf3, 0x0a, 0x10, 0x01, 0x01, 0x0a, 0x10, /* ........ */
1183 0x01, 0x0b, 0x00, 0x35, 0xa3, 0x4d, 0x00, 0x6c, /* ...5.M.l */
1184 0x8d, 0x8c, 0x8d, 0x32, 0x81, 0xa0, 0x00, 0x01, /* ...2.... */
1185 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, /* .......w */
1186 0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1187 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1188 0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1189 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, /* ........ */
1190 0x0d, 0xd8, 0x00, 0x12, 0x0c, 0x73, 0x75, 0x72, /* .....sur */
1191 0x69, 0x63, 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, /* icata-id */
1192 0x73, 0x03, 0x6f, 0x72, 0x67, 0x00, 0xc0, 0x32, /* s.org..2 */
1193 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1194 0x00, 0x04, 0xc0, 0x00, 0x4e, 0x18, 0xc0, 0x32, /* ....N..2 */
1195 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1196 0x00, 0x04, 0xc0, 0x00, 0x4e, 0x19 /* ....N. */
1199 // The DNS payload starts at offset 42.
1200 let dns_payload = &buf[42..];
1202 // Make a TCP DNS response payload.
1203 let mut request = Vec::new();
1204 request.push(((dns_payload.len() as u16) >> 8) as u8);
1205 request.push(((dns_payload.len() as u16) & 0xff) as u8);
1206 request.extend(dns_payload);
1208 let mut state = DNSState::new();
1209 assert_eq!(1, state.parse_response_tcp(&request));
1212 // Test that a TCP DNS payload won't be parsed if there is not
1215 fn test_dns_parse_response_tcp_short_payload() {
1216 // A UDP DNS response with the DNS payload starting at byte 42.
1217 // 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
1219 0xd8, 0xcb, 0x8a, 0xed, 0xa1, 0x46, 0x00, 0x15, /* .....F.. */
1220 0x17, 0x0d, 0x06, 0xf7, 0x08, 0x00, 0x45, 0x00, /* ......E. */
1221 0x00, 0x80, 0x65, 0x4e, 0x40, 0x00, 0x40, 0x11, /* ..eN@.@. */
1222 0xbe, 0xf3, 0x0a, 0x10, 0x01, 0x01, 0x0a, 0x10, /* ........ */
1223 0x01, 0x0b, 0x00, 0x35, 0xa3, 0x4d, 0x00, 0x6c, /* ...5.M.l */
1224 0x8d, 0x8c, 0x8d, 0x32, 0x81, 0xa0, 0x00, 0x01, /* ...2.... */
1225 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, /* .......w */
1226 0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1227 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1228 0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1229 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, /* ........ */
1230 0x0d, 0xd8, 0x00, 0x12, 0x0c, 0x73, 0x75, 0x72, /* .....sur */
1231 0x69, 0x63, 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, /* icata-id */
1232 0x73, 0x03, 0x6f, 0x72, 0x67, 0x00, 0xc0, 0x32, /* s.org..2 */
1233 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1234 0x00, 0x04, 0xc0, 0x00, 0x4e, 0x18, 0xc0, 0x32, /* ....N..2 */
1235 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1236 0x00, 0x04, 0xc0, 0x00, 0x4e, 0x19 /* ....N. */
1239 // The DNS payload starts at offset 42.
1240 let dns_payload = &buf[42..];
1242 // Make a TCP DNS response payload, but make the length 1 byte
1243 // larger than the actual size.
1244 let mut request = Vec::new();
1245 request.push(((dns_payload.len() as u16) >> 8) as u8);
1246 request.push((((dns_payload.len() as u16) & 0xff) + 1) as u8);
1247 request.extend(dns_payload);
1249 let mut state = DNSState::new();
1250 assert_eq!(0, state.parse_response_tcp(&request));
1253 // Port of the C RustDNSUDPParserTest02 unit test.
1255 fn test_dns_udp_parser_test_01() {
1256 /* query: abcdefghijk.com
1258 * serial 20130422 refresh 28800 retry 7200 exp 604800 min ttl 86400
1261 0x00, 0x3c, 0x85, 0x00, 0x00, 0x01, 0x00, 0x00,
1262 0x00, 0x01, 0x00, 0x00, 0x0b, 0x61, 0x62, 0x63,
1263 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
1264 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x0f, 0x00,
1265 0x01, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01,
1266 0x51, 0x80, 0x00, 0x25, 0x02, 0x6e, 0x73, 0x00,
1267 0x0a, 0x68, 0x6f, 0x73, 0x74, 0x6d, 0x61, 0x73,
1268 0x74, 0x65, 0x72, 0xc0, 0x2f, 0x01, 0x33, 0x2a,
1269 0x76, 0x00, 0x00, 0x70, 0x80, 0x00, 0x00, 0x1c,
1270 0x20, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01, 0x51,
1273 let mut state = DNSState::new();
1274 assert!(state.parse_response(buf));
1277 // Port of the C RustDNSUDPParserTest02 unit test.
1279 fn test_dns_udp_parser_test_02() {
1281 0x6D,0x08,0x84,0x80,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x01,0x03,0x57,0x57,0x57,
1282 0x04,0x54,0x54,0x54,0x54,0x03,0x56,0x56,0x56,0x03,0x63,0x6F,0x6D,0x02,0x79,0x79,
1283 0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,
1284 0x02,0xC0,0x0C,0xC0,0x31,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,
1285 0x31,0xC0,0x3F,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x3F,0xC0,
1286 0x4D,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x4D,0xC0,0x5B,0x00,
1287 0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x5B,0xC0,0x69,0x00,0x05,0x00,
1288 0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x69,0xC0,0x77,0x00,0x05,0x00,0x01,0x00,
1289 0x00,0x0E,0x10,0x00,0x02,0xC0,0x77,0xC0,0x85,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,
1290 0x10,0x00,0x02,0xC0,0x85,0x00,0x00,0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1292 let mut state = DNSState::new();
1293 assert!(state.parse_response(buf));
1296 // Port of the C RustDNSUDPParserTest03 unit test.
1298 fn test_dns_udp_parser_test_03() {
1300 0x6F,0xB4,0x84,0x80,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x03,0x03,0x57,0x57,0x77,
1301 0x0B,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x03,0x55,0x55,0x55,
1302 0x02,0x79,0x79,0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,
1303 0x0E,0x10,0x00,0x02,0xC0,0x10,0xC0,0x34,0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,
1304 0x00,0x04,0xC3,0xEA,0x04,0x19,0xC0,0x34,0x00,0x02,0x00,0x01,0x00,0x00,0x0E,0x10,
1305 0x00,0x0A,0x03,0x6E,0x73,0x31,0x03,0x61,0x67,0x62,0xC0,0x20,0xC0,0x46,0x00,0x02,
1306 0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x06,0x03,0x6E,0x73,0x32,0xC0,0x56,0xC0,0x52,
1307 0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x04,0x0A,0xC0,0x68,
1308 0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x05,0x14,0x00,0x00,
1309 0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00
1311 let mut state = DNSState::new();
1312 assert!(state.parse_response(buf));
1315 // Port of the C RustDNSUDPParserTest04 unit test.
1317 // Test the TXT records in an answer.
1319 fn test_dns_udp_parser_test_04() {
1321 0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
1322 0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
1323 0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
1325 /* answer record start */
1326 0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
1327 /* txt record starts: */
1328 0x20, /* <txt len 32 */ 0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
1329 0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
1330 0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */ 0xc0,0x1d,0x00,0x02,0x00,0x01,
1331 0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
1332 0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
1334 let mut state = DNSState::new();
1335 assert!(state.parse_response(buf));
1338 // Port of the C RustDNSUDPParserTest05 unit test.
1340 // Test TXT records in answer with a bad length.
1342 fn test_dns_udp_parser_test_05() {
1344 0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
1345 0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
1346 0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
1348 /* answer record start */
1349 0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
1350 /* txt record starts: */
1351 0x40, /* <txt len 64 */ 0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
1352 0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
1353 0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */ 0xc0,0x1d,0x00,0x02,0x00,0x01,
1354 0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
1355 0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
1357 let mut state = DNSState::new();
1358 assert!(!state.parse_response(buf));
1361 // Port of the C RustDNSTCPParserTestMultiRecord unit test.
1363 fn test_dns_tcp_parser_multi_record() {
1365 0x00, 0x1e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
1366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30,
1367 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1368 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1369 0x00, 0x1e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
1370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31,
1371 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1372 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1373 0x00, 0x1e, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01,
1374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x32,
1375 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1376 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1377 0x00, 0x1e, 0x00, 0x03, 0x01, 0x00, 0x00, 0x01,
1378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x33,
1379 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1380 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1381 0x00, 0x1e, 0x00, 0x04, 0x01, 0x00, 0x00, 0x01,
1382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x34,
1383 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1384 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1385 0x00, 0x1e, 0x00, 0x05, 0x01, 0x00, 0x00, 0x01,
1386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x35,
1387 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1388 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1389 0x00, 0x1e, 0x00, 0x06, 0x01, 0x00, 0x00, 0x01,
1390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x36,
1391 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1392 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1393 0x00, 0x1e, 0x00, 0x07, 0x01, 0x00, 0x00, 0x01,
1394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x37,
1395 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1396 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1397 0x00, 0x1e, 0x00, 0x08, 0x01, 0x00, 0x00, 0x01,
1398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38,
1399 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1400 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1401 0x00, 0x1e, 0x00, 0x09, 0x01, 0x00, 0x00, 0x01,
1402 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x39,
1403 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1404 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1405 0x00, 0x1f, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x01,
1406 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
1407 0x30, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
1408 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
1409 0x01, 0x00, 0x1f, 0x00, 0x0b, 0x01, 0x00, 0x00,
1410 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1411 0x31, 0x31, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
1412 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
1413 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0c, 0x01, 0x00,
1414 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1415 0x02, 0x31, 0x32, 0x06, 0x67, 0x6f, 0x6f, 0x67,
1416 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00,
1417 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0d, 0x01,
1418 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1419 0x00, 0x02, 0x31, 0x33, 0x06, 0x67, 0x6f, 0x6f,
1420 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
1421 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0e,
1422 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1423 0x00, 0x00, 0x02, 0x31, 0x34, 0x06, 0x67, 0x6f,
1424 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d,
1425 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00,
1426 0x0f, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1427 0x00, 0x00, 0x00, 0x02, 0x31, 0x35, 0x06, 0x67,
1428 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f,
1429 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f,
1430 0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
1431 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x36, 0x06,
1432 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63,
1433 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
1434 0x1f, 0x00, 0x11, 0x01, 0x00, 0x00, 0x01, 0x00,
1435 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x37,
1436 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1437 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1438 0x00, 0x1f, 0x00, 0x12, 0x01, 0x00, 0x00, 0x01,
1439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
1440 0x38, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
1441 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
1442 0x01, 0x00, 0x1f, 0x00, 0x13, 0x01, 0x00, 0x00,
1443 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1444 0x31, 0x39, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
1445 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
1448 let mut state = DNSState::new();
1449 assert_eq!(state.parse_request_tcp(buf), 20);