]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
dns: consolidate DNSRequest and DNSResponse to DNSMessage
authorJason Ish <jason.ish@oisf.net>
Wed, 15 Nov 2023 21:58:36 +0000 (15:58 -0600)
committerVictor Julien <victor@inliniac.net>
Wed, 13 Dec 2023 18:17:17 +0000 (19:17 +0100)
DNS request and response messages follow the same format so there is
no reason not to use the same data structure for each. While its
unlikely to see fields like answers in a request, the message format
does not disallow them, so it might be interesting data to have the
ability to log.

rust/src/dns/dns.rs
rust/src/dns/log.rs
rust/src/dns/parser.rs

index c93547c15126a8cd4693714bff9eb33a4dd9fbd3..aa0042f0b2595f3151d4d5f4e8d6e9cc2b727671 100644 (file)
@@ -221,13 +221,7 @@ pub struct DNSAnswerEntry {
 }
 
 #[derive(Debug)]
-pub struct DNSRequest {
-    pub header: DNSHeader,
-    pub queries: Vec<DNSQueryEntry>,
-}
-
-#[derive(Debug)]
-pub struct DNSResponse {
+pub struct DNSMessage {
     pub header: DNSHeader,
     pub queries: Vec<DNSQueryEntry>,
     pub answers: Vec<DNSAnswerEntry>,
@@ -237,8 +231,8 @@ pub struct DNSResponse {
 #[derive(Debug, Default)]
 pub struct DNSTransaction {
     pub id: u64,
-    pub request: Option<DNSRequest>,
-    pub response: Option<DNSResponse>,
+    pub request: Option<DNSMessage>,
+    pub response: Option<DNSMessage>,
     pub tx_data: AppLayerTxData,
 }
 
@@ -402,7 +396,7 @@ impl DNSState {
             return !is_tcp;
         };
 
-        match parser::dns_parse_request_body(body, input, header) {
+        match parser::dns_parse_body(body, input, header) {
             Ok((_, request)) => {
                 if request.header.flags & 0x8000 != 0 {
                     SCLogDebug!("DNS message is not a request");
@@ -474,7 +468,7 @@ impl DNSState {
             return !is_tcp;
         };
 
-        match parser::dns_parse_response_body(body, input, header) {
+        match parser::dns_parse_body(body, input, header) {
             Ok((_, response)) => {
                 SCLogDebug!("Response header flags: {}", response.header.flags);
 
@@ -702,14 +696,9 @@ fn probe(input: &[u8], dlen: usize) -> (bool, bool, bool) {
         }
     }
 
-    match parser::dns_parse_request(input) {
-        Ok((_, request)) => {
-            return probe_header_validity(&request.header, dlen);
-        }
-        Err(Err::Incomplete(_)) => match parser::dns_parse_header(input) {
-            Ok((_, header)) => {
-                return probe_header_validity(&header, dlen);
-            }
+    match parser::dns_parse_header(input) {
+        Ok((body, header)) => match parser::dns_parse_body(body, input, header) {
+            Ok((_, request)) => probe_header_validity(&request.header, dlen),
             Err(Err::Incomplete(_)) => (false, false, true),
             Err(_) => (false, false, false),
         },
index 1bece89a5ae6ff66f60a00f471864243fd9dedc2..4c0d4fc065b44c085285f76ab89f5d6289efb131 100644 (file)
@@ -476,7 +476,7 @@ fn dns_log_json_answer_detail(answer: &DNSAnswerEntry) -> Result<JsonBuilder, Js
 }
 
 fn dns_log_json_answer(
-    js: &mut JsonBuilder, response: &DNSResponse, flags: u64,
+    js: &mut JsonBuilder, response: &DNSMessage, flags: u64,
 ) -> Result<(), JsonError> {
     let header = &response.header;
 
index a1d97a53fd028017872d6b9b3c9bff35e2079143..f7f9fd0d6e8c0cefd58c8d49e128bb701bfa9c88 100644 (file)
@@ -24,27 +24,6 @@ use nom7::multi::{count, length_data, many_m_n};
 use nom7::number::streaming::{be_u16, be_u32, be_u8};
 use nom7::{error_position, Err, IResult};
 
-// Parse a DNS header.
-pub fn dns_parse_header(i: &[u8]) -> IResult<&[u8], DNSHeader> {
-    let (i, tx_id) = be_u16(i)?;
-    let (i, flags) = be_u16(i)?;
-    let (i, questions) = be_u16(i)?;
-    let (i, answer_rr) = be_u16(i)?;
-    let (i, authority_rr) = be_u16(i)?;
-    let (i, additional_rr) = be_u16(i)?;
-    Ok((
-        i,
-        DNSHeader {
-            tx_id,
-            flags,
-            questions,
-            answer_rr,
-            authority_rr,
-            additional_rr,
-        },
-    ))
-}
-
 /// Parse a DNS name.
 ///
 /// Parameters:
@@ -191,23 +170,6 @@ fn dns_parse_answer<'a>(
     return Ok((input, answers));
 }
 
-pub fn dns_parse_response_body<'a>(
-    i: &'a [u8], message: &'a [u8], header: DNSHeader,
-) -> IResult<&'a [u8], DNSResponse> {
-    let (i, queries) = count(|b| dns_parse_query(b, message), header.questions as usize)(i)?;
-    let (i, answers) = dns_parse_answer(i, message, header.answer_rr as usize)?;
-    let (i, authorities) = dns_parse_answer(i, message, header.authority_rr as usize)?;
-    Ok((
-        i,
-        DNSResponse {
-            header,
-            queries,
-            answers,
-            authorities,
-        },
-    ))
-}
-
 /// Parse a single DNS query.
 ///
 /// Arguments are suitable for using with call!:
@@ -343,19 +305,42 @@ pub fn dns_parse_rdata<'a>(
     }
 }
 
-/// Parse a DNS request.
-pub fn dns_parse_request(input: &[u8]) -> IResult<&[u8], DNSRequest> {
-    let i = input;
-    let (i, header) = dns_parse_header(i)?;
-    dns_parse_request_body(i, input, header)
+// Parse a DNS header.
+pub fn dns_parse_header(i: &[u8]) -> IResult<&[u8], DNSHeader> {
+    let (i, tx_id) = be_u16(i)?;
+    let (i, flags) = be_u16(i)?;
+    let (i, questions) = be_u16(i)?;
+    let (i, answer_rr) = be_u16(i)?;
+    let (i, authority_rr) = be_u16(i)?;
+    let (i, additional_rr) = be_u16(i)?;
+    Ok((
+        i,
+        DNSHeader {
+            tx_id,
+            flags,
+            questions,
+            answer_rr,
+            authority_rr,
+            additional_rr,
+        },
+    ))
 }
 
-pub fn dns_parse_request_body<'a>(
-    input: &'a [u8], message: &'a [u8], header: DNSHeader,
-) -> IResult<&'a [u8], DNSRequest> {
-    let i = input;
+pub fn dns_parse_body<'a>(
+    i: &'a [u8], message: &'a [u8], header: DNSHeader,
+) -> IResult<&'a [u8], DNSMessage> {
     let (i, queries) = count(|b| dns_parse_query(b, message), header.questions as usize)(i)?;
-    Ok((i, DNSRequest { header, queries }))
+    let (i, answers) = dns_parse_answer(i, message, header.answer_rr as usize)?;
+    let (i, authorities) = dns_parse_answer(i, message, header.authority_rr as usize)?;
+    Ok((
+        i,
+        DNSMessage {
+            header,
+            queries,
+            answers,
+            authorities,
+        },
+    ))
 }
 
 #[cfg(test)]
@@ -490,7 +475,8 @@ mod tests {
             0x00, 0x00, 0x00, /* ... */
         ];
 
-        let res = dns_parse_request(pkt);
+        let (body, header) = dns_parse_header(pkt).unwrap();
+        let res = dns_parse_body(body, pkt, header);
         match res {
             Ok((rem, request)) => {
                 // For now we have some remainder data as there is an
@@ -523,10 +509,10 @@ mod tests {
     }
 
     /// Parse a DNS response.
-    fn dns_parse_response(message: &[u8]) -> IResult<&[u8], DNSResponse> {
+    fn dns_parse_response(message: &[u8]) -> IResult<&[u8], DNSMessage> {
         let i = message;
         let (i, header) = dns_parse_header(i)?;
-        dns_parse_response_body(i, message, header)
+        dns_parse_body(i, message, header)
     }
 
     #[test]