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,
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 {
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,
}
}
}
} 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);
};
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(());
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);
- }
}
}
}
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;
flow,
) {
Ok(_) => {
- tx_same.handle_dns_data(over, dir, flow);
+ if over {
+ tx_same.handle_dns_data(dir, flow);
+ }
}
_ => {
self.set_event(HTTP2Event::FailedDecompression);
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()