|
|
|
@ -383,18 +383,23 @@ impl DNSState {
|
|
|
|
tx.tx_data.set_event(event as u8);
|
|
|
|
tx.tx_data.set_event(event as u8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn validate_header(&self, input: &[u8]) -> bool {
|
|
|
|
fn validate_header<'a>(&self, input: &'a [u8]) -> Option<(&'a [u8], DNSHeader)> {
|
|
|
|
parser::dns_parse_header(input)
|
|
|
|
if let Ok((body, header)) = parser::dns_parse_header(input) {
|
|
|
|
.map(|(_, header)| probe_header_validity(header, input.len()).0)
|
|
|
|
if probe_header_validity(&header, input.len()).0 {
|
|
|
|
.unwrap_or(false)
|
|
|
|
return Some((body, header));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn parse_request(&mut self, input: &[u8], is_tcp: bool) -> bool {
|
|
|
|
fn parse_request(&mut self, input: &[u8], is_tcp: bool) -> bool {
|
|
|
|
if !self.validate_header(input) {
|
|
|
|
let (body, header) = if let Some((body, header)) = self.validate_header(input) {
|
|
|
|
|
|
|
|
(body, header)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
return !is_tcp;
|
|
|
|
return !is_tcp;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
match parser::dns_parse_request(input) {
|
|
|
|
match parser::dns_parse_request_body(body, input, header) {
|
|
|
|
Ok((_, request)) => {
|
|
|
|
Ok((_, request)) => {
|
|
|
|
if request.header.flags & 0x8000 != 0 {
|
|
|
|
if request.header.flags & 0x8000 != 0 {
|
|
|
|
SCLogDebug!("DNS message is not a request");
|
|
|
|
SCLogDebug!("DNS message is not a request");
|
|
|
|
@ -460,11 +465,13 @@ impl DNSState {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn parse_response(&mut self, input: &[u8], is_tcp: bool) -> bool {
|
|
|
|
pub fn parse_response(&mut self, input: &[u8], is_tcp: bool) -> bool {
|
|
|
|
if !self.validate_header(input) {
|
|
|
|
let (body, header) = if let Some((body, header)) = self.validate_header(input) {
|
|
|
|
|
|
|
|
(body, header)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
return !is_tcp;
|
|
|
|
return !is_tcp;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
match parser::dns_parse_response(input) {
|
|
|
|
match parser::dns_parse_response_body(body, input, header) {
|
|
|
|
Ok((_, response)) => {
|
|
|
|
Ok((_, response)) => {
|
|
|
|
SCLogDebug!("Response header flags: {}", response.header.flags);
|
|
|
|
SCLogDebug!("Response header flags: {}", response.header.flags);
|
|
|
|
|
|
|
|
|
|
|
|
@ -653,7 +660,7 @@ impl DNSState {
|
|
|
|
|
|
|
|
|
|
|
|
const DNS_HEADER_SIZE: usize = 12;
|
|
|
|
const DNS_HEADER_SIZE: usize = 12;
|
|
|
|
|
|
|
|
|
|
|
|
fn probe_header_validity(header: DNSHeader, rlen: usize) -> (bool, bool, bool) {
|
|
|
|
fn probe_header_validity(header: &DNSHeader, rlen: usize) -> (bool, bool, bool) {
|
|
|
|
let min_msg_size = 2
|
|
|
|
let min_msg_size = 2
|
|
|
|
* (header.additional_rr as usize
|
|
|
|
* (header.additional_rr as usize
|
|
|
|
+ header.answer_rr as usize
|
|
|
|
+ header.answer_rr as usize
|
|
|
|
@ -686,7 +693,7 @@ fn probe(input: &[u8], dlen: usize) -> (bool, bool, bool) {
|
|
|
|
// parse a complete message, so perform header validation only.
|
|
|
|
// parse a complete message, so perform header validation only.
|
|
|
|
if input.len() < dlen {
|
|
|
|
if input.len() < dlen {
|
|
|
|
if let Ok((_, header)) = parser::dns_parse_header(input) {
|
|
|
|
if let Ok((_, header)) = parser::dns_parse_header(input) {
|
|
|
|
return probe_header_validity(header, dlen);
|
|
|
|
return probe_header_validity(&header, dlen);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
return (false, false, false);
|
|
|
|
return (false, false, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -694,11 +701,11 @@ fn probe(input: &[u8], dlen: usize) -> (bool, bool, bool) {
|
|
|
|
|
|
|
|
|
|
|
|
match parser::dns_parse_request(input) {
|
|
|
|
match parser::dns_parse_request(input) {
|
|
|
|
Ok((_, request)) => {
|
|
|
|
Ok((_, request)) => {
|
|
|
|
return probe_header_validity(request.header, dlen);
|
|
|
|
return probe_header_validity(&request.header, dlen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(Err::Incomplete(_)) => match parser::dns_parse_header(input) {
|
|
|
|
Err(Err::Incomplete(_)) => match parser::dns_parse_header(input) {
|
|
|
|
Ok((_, header)) => {
|
|
|
|
Ok((_, header)) => {
|
|
|
|
return probe_header_validity(header, dlen);
|
|
|
|
return probe_header_validity(&header, dlen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(Err::Incomplete(_)) => (false, false, true),
|
|
|
|
Err(Err::Incomplete(_)) => (false, false, true),
|
|
|
|
Err(_) => (false, false, false),
|
|
|
|
Err(_) => (false, false, false),
|
|
|
|
|