]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
doh: move fields into dedicated Optional struct
authorPhilippe Antoine <pantoine@oisf.net>
Tue, 25 Jun 2024 11:29:53 +0000 (13:29 +0200)
committerVictor Julien <victor@inliniac.net>
Sat, 20 Jul 2024 08:37:58 +0000 (10:37 +0200)
So as to consume less memory for HTTP2Transaction

rust/src/http2/http2.rs
rust/src/http2/logger.rs

index 2c561c70d4a99ce391d55ac2f6e2c7b32f084c59..802d6ef53b76af705f2c8d1a4561ed90e60bafbf 100644 (file)
@@ -128,6 +128,19 @@ pub struct HTTP2Frame {
     pub data: HTTP2FrameTypeData,
 }
 
+#[derive(Debug, Default)]
+/// Dns Over HTTP2 Data inside a HTTP2 transaction
+pub struct DohHttp2Tx {
+    /// wether the HTTP2 data is DNS, for both directions
+    is_doh_data: [bool; 2],
+    /// http2 data buffer to parse as DNS on completion
+    pub data_buf: [Vec<u8>; 2],
+    /// dns request transation
+    pub dns_request_tx: Option<DNSTransaction>,
+    /// dns response transation
+    pub dns_response_tx: Option<DNSTransaction>,
+}
+
 #[derive(Debug)]
 pub struct HTTP2Transaction {
     tx_id: u64,
@@ -151,11 +164,7 @@ pub struct HTTP2Transaction {
     pub req_line: Vec<u8>,
     pub resp_line: Vec<u8>,
 
-    is_doh_data: [bool; 2],
-    // dns response buffer
-    pub doh_data_buf: [Vec<u8>; 2],
-    pub dns_request_tx: Option<DNSTransaction>,
-    pub dns_response_tx: Option<DNSTransaction>,
+    pub doh: Option<DohHttp2Tx>,
 }
 
 impl Transaction for HTTP2Transaction {
@@ -187,10 +196,7 @@ impl HTTP2Transaction {
             escaped: Vec::with_capacity(16),
             req_line: Vec::new(),
             resp_line: Vec::new(),
-            is_doh_data: [false; 2],
-            doh_data_buf: Default::default(),
-            dns_request_tx: None,
-            dns_response_tx: None,
+            doh: None,
         }
     }
 
@@ -235,7 +241,13 @@ impl HTTP2Transaction {
                 }
             } else if block.name.as_ref() == b"content-type" {
                 if block.value.as_ref() == b"application/dns-message" {
-                    self.is_doh_data[dir.index()] = true;
+                    if let Some(doh) = &mut self.doh {
+                        doh.is_doh_data[dir.index()] = true;
+                    } else {
+                        let mut doh = DohHttp2Tx::default();
+                        doh.is_doh_data[dir.index()] = true;
+                        self.doh = Some(doh);
+                    }
                 }
             } else if block.name.as_ref() == b":path" {
                 path = Some(&block.value);
@@ -347,9 +359,11 @@ impl HTTP2Transaction {
         };
         if unsafe { ALPROTO_DOH2 } != ALPROTO_UNKNOWN {
             // we store DNS response, and process it when complete
-            if self.is_doh_data[dir.index()] && self.doh_data_buf[dir.index()].len() < 0xFFFF {
-                // a DNS message is U16_MAX
-                self.doh_data_buf[dir.index()].extend_from_slice(decompressed);
+            if let Some(doh) = &mut self.doh {
+                if doh.is_doh_data[dir.index()] && doh.data_buf[dir.index()].len() < 0xFFFF {
+                    // a DNS message is U16_MAX
+                    doh.data_buf[dir.index()].extend_from_slice(decompressed);
+                }
             }
         }
         return Ok(());
@@ -433,22 +447,24 @@ impl HTTP2Transaction {
         return r;
     }
 
-    fn handle_dns_data(&mut self, over: bool, dir: Direction, flow: *const Flow) {
-        if !self.doh_data_buf[dir.index()].is_empty() && over {
-            if dir.is_to_client() {
-                if let Ok(mut dtx) = dns_parse_response(&self.doh_data_buf[dir.index()]) {
+    fn handle_dns_data(&mut self, dir: Direction, flow: *const Flow) {
+        if let Some(doh) = &mut self.doh {
+            if !doh.data_buf[dir.index()].is_empty() {
+                if dir.is_to_client() {
+                    if let Ok(mut dtx) = dns_parse_response(&doh.data_buf[dir.index()]) {
+                        dtx.id = 1;
+                        doh.dns_response_tx = Some(dtx);
+                        unsafe {
+                            AppLayerForceProtocolChange(flow, ALPROTO_DOH2);
+                        }
+                    }
+                } else if let Ok(mut dtx) = dns_parse_request(&doh.data_buf[dir.index()]) {
                     dtx.id = 1;
-                    self.dns_response_tx = Some(dtx);
+                    doh.dns_request_tx = Some(dtx);
                     unsafe {
                         AppLayerForceProtocolChange(flow, ALPROTO_DOH2);
                     }
                 }
-            } else if let Ok(mut dtx) = dns_parse_request(&self.doh_data_buf[dir.index()]) {
-                dtx.id = 1;
-                self.dns_request_tx = Some(dtx);
-                unsafe {
-                    AppLayerForceProtocolChange(flow, ALPROTO_DOH2);
-                }
             }
         }
     }
@@ -1131,17 +1147,21 @@ impl HTTP2State {
                     if let Some(doh_req_buf) = tx.handle_frame(&head, &txdata, dir) {
                         if let Ok(mut dtx) = dns_parse_request(&doh_req_buf) {
                             dtx.id = 1;
-                            tx.dns_request_tx = Some(dtx);
                             unsafe {
                                 AppLayerForceProtocolChange(flow, ALPROTO_DOH2);
                             }
+                            if let Some(doh) = &mut tx.doh {
+                                doh.dns_request_tx = Some(dtx);
+                            } else {
+                                let doh = DohHttp2Tx { dns_request_tx: Some(dtx), ..Default::default() };
+                                tx.doh = Some(doh);
+                            }
                         }
                     }
                     if reass_limit_reached {
                         tx.tx_data
                             .set_event(HTTP2Event::ReassemblyLimitReached as u8);
                     }
-                    tx.handle_frame(&head, &txdata, dir);
                     let over = head.flags & parser::HTTP2_FLAG_HEADER_EOS != 0;
                     let ftype = head.ftype;
                     let sid = head.stream_id;
@@ -1185,7 +1205,9 @@ impl HTTP2State {
                                         flow,
                                     ) {
                                         Ok(_) => {
-                                            tx_same.handle_dns_data(over, dir, flow);
+                                            if over {
+                                                tx_same.handle_dns_data(dir, flow);
+                                            }
                                         }
                                         _ => {
                                             self.set_event(HTTP2Event::FailedDecompression);
@@ -1288,13 +1310,15 @@ impl HTTP2State {
 pub unsafe extern "C" fn SCDoH2GetDnsTx(
     tx: &HTTP2Transaction, flags: u8,
 ) -> *mut std::os::raw::c_void {
-    if flags & Direction::ToServer as u8 != 0 {
-        if let Some(ref dtx) = &tx.dns_request_tx {
-            return dtx as *const _ as *mut _;
-        }
-    } else if flags & Direction::ToClient as u8 != 0 {
-        if let Some(ref dtx) = &tx.dns_response_tx {
-            return dtx as *const _ as *mut _;
+    if let Some(doh) = &tx.doh {
+        if flags & Direction::ToServer as u8 != 0 {
+            if let Some(ref dtx) = &doh.dns_request_tx {
+                return dtx as *const _ as *mut _;
+            }
+        } else if flags & Direction::ToClient as u8 != 0 {
+            if let Some(ref dtx) = &doh.dns_response_tx {
+                return dtx as *const _ as *mut _;
+            }
         }
     }
     std::ptr::null_mut()
index 445b546d0561cb6ce8a77f89a2853b96249140a6..b424e62b8446166a85229c52e69da2328209c7d6 100644 (file)
@@ -282,9 +282,9 @@ fn log_http2(tx: &HTTP2Transaction, js: &mut JsonBuilder) -> Result<bool, JsonEr
     js.close()?; // http2
     js.close()?; // http
 
-    if tx.dns_request_tx.is_some() || tx.dns_response_tx.is_some() {
+    if let Some(doh) = &tx.doh {
         js.open_object("dns")?;
-        if let Some(dtx) = &tx.dns_request_tx {
+        if let Some(dtx) = &doh.dns_request_tx {
             let mark = js.get_mark();
             let mut has_dns_query = false;
             js.open_array("query")?;
@@ -303,7 +303,7 @@ fn log_http2(tx: &HTTP2Transaction, js: &mut JsonBuilder) -> Result<bool, JsonEr
                 js.restore_mark(&mark)?;
             }
         }
-        if let Some(dtx) = &tx.dns_response_tx {
+        if let Some(dtx) = &doh.dns_response_tx {
             if SCDnsLogAnswerEnabled(dtx, 0xFFFFFFFFFFFFFFFF) {
                 // logging at root of dns object
                 SCDnsLogJsonAnswer(dtx, 0xFFFFFFFFFFFFFFFF, js);