use tracing::{debug, error};
use crate::{
net::{udp::MAX_RECEIVE_BUFFER_SIZE, xfer::Protocol},
proto::{
ProtoError,
op::{
Edns, Header, HeaderCounts, MessageType, Metadata, OpCode, ResponseCode,
emit_message_parts,
},
rr::{Record, rdata::TSIG},
serialize::binary::{BinEncodable, BinEncoder},
},
server::ResponseInfo,
zone_handler::{Queries, message_request::MessageRequest},
};
#[derive(Debug)]
pub struct MessageResponse<'q, 'a, Answers, Authorities, Soa, Additionals>
where
Answers: Iterator<Item = &'a Record> + Send + 'a,
Authorities: Iterator<Item = &'a Record> + Send + 'a,
Soa: Iterator<Item = &'a Record> + Send + 'a,
Additionals: Iterator<Item = &'a Record> + Send + 'a,
{
metadata: Metadata,
queries: &'q Queries,
answers: Answers,
authorities: Authorities,
soa: Soa,
additionals: Additionals,
signature: Option<Box<Record<TSIG>>>,
edns: Option<&'q Edns>,
}
impl<'q, 'a, A, N, S, D> MessageResponse<'q, 'a, A, N, S, D>
where
A: Iterator<Item = &'a Record> + Send + 'a,
N: Iterator<Item = &'a Record> + Send + 'a,
S: Iterator<Item = &'a Record> + Send + 'a,
D: Iterator<Item = &'a Record> + Send + 'a,
{
pub fn metadata(&self) -> &Metadata {
&self.metadata
}
pub fn metadata_mut(&mut self) -> &mut Metadata {
&mut self.metadata
}
pub fn set_edns(&mut self, edns: &'q Edns) -> &mut Self {
self.edns = Some(edns);
self
}
pub fn edns(&self) -> Option<&'q Edns> {
self.edns
}
pub fn set_signature(&mut self, signature: Box<Record<TSIG>>) {
self.signature = Some(signature);
}
pub(crate) fn encode(self, protocol: Protocol) -> Result<(ResponseInfo, Vec<u8>), ProtoError> {
let id = self.metadata.id;
debug!(
id,
response_code = %self.metadata.response_code,
"encoding response"
);
let mut bytes = Vec::with_capacity(512);
let mut encoder = BinEncoder::new(&mut bytes);
encoder.set_max_size(match protocol {
Protocol::Udp => match &self.edns {
Some(edns) => edns.max_payload(),
None => MAX_RECEIVE_BUFFER_SIZE as u16,
},
_ => u16::MAX,
});
let error = match self.destructive_emit(&mut encoder) {
Ok(info) => return Ok((info, bytes)),
Err(error) => error,
};
error!(%error, "error encoding message");
bytes.clear();
let mut encoder = BinEncoder::new(&mut bytes);
encoder.set_max_size(512);
let mut metadata = Metadata::new(id, MessageType::Response, OpCode::Query);
metadata.response_code = ResponseCode::ServFail;
let header = Header {
metadata,
counts: HeaderCounts::default(),
};
header.emit(&mut encoder)?;
Ok((ResponseInfo::from(header), bytes))
}
pub fn destructive_emit(
mut self,
encoder: &mut BinEncoder<'_>,
) -> Result<ResponseInfo, ProtoError> {
let mut authorities = self.authorities.chain(self.soa);
let header = emit_message_parts(
&self.metadata,
&mut self.queries.as_emit_and_count(),
&mut self.answers,
&mut authorities,
&mut self.additionals,
self.edns,
self.signature.as_deref(),
encoder,
)?;
Ok(ResponseInfo::from(header))
}
}
pub struct MessageResponseBuilder<'q> {
queries: &'q Queries,
signature: Option<Box<Record<TSIG>>>,
edns: Option<&'q Edns>,
}
impl<'q> MessageResponseBuilder<'q> {
pub fn new(queries: &'q Queries, edns: Option<&'q Edns>) -> Self {
MessageResponseBuilder {
queries,
signature: None,
edns,
}
}
pub fn from_message_request(message: &'q MessageRequest) -> Self {
Self::new(&message.queries, None)
}
pub fn edns(&mut self, edns: &'q Edns) -> &mut Self {
self.edns = Some(edns);
self
}
pub fn build<'a, A, N, S, D>(
self,
metadata: Metadata,
answers: A,
authorities: N,
soa: S,
additionals: D,
) -> MessageResponse<'q, 'a, A::IntoIter, N::IntoIter, S::IntoIter, D::IntoIter>
where
A: IntoIterator<Item = &'a Record> + Send + 'a,
A::IntoIter: Send,
N: IntoIterator<Item = &'a Record> + Send + 'a,
N::IntoIter: Send,
S: IntoIterator<Item = &'a Record> + Send + 'a,
S::IntoIter: Send,
D: IntoIterator<Item = &'a Record> + Send + 'a,
D::IntoIter: Send,
{
MessageResponse {
metadata,
queries: self.queries,
answers: answers.into_iter(),
authorities: authorities.into_iter(),
soa: soa.into_iter(),
additionals: additionals.into_iter(),
signature: self.signature,
edns: self.edns,
}
}
pub fn build_no_records<'a>(
self,
metadata: Metadata,
) -> MessageResponse<
'q,
'a,
impl Iterator<Item = &'a Record> + Send + 'a,
impl Iterator<Item = &'a Record> + Send + 'a,
impl Iterator<Item = &'a Record> + Send + 'a,
impl Iterator<Item = &'a Record> + Send + 'a,
> {
MessageResponse {
metadata,
queries: self.queries,
answers: Box::new(None.into_iter()),
authorities: Box::new(None.into_iter()),
soa: Box::new(None.into_iter()),
additionals: Box::new(None.into_iter()),
signature: self.signature,
edns: self.edns,
}
}
pub fn error_msg<'a>(
self,
request_meta: &Metadata,
response_code: ResponseCode,
) -> MessageResponse<
'q,
'a,
impl Iterator<Item = &'a Record> + Send + 'a,
impl Iterator<Item = &'a Record> + Send + 'a,
impl Iterator<Item = &'a Record> + Send + 'a,
impl Iterator<Item = &'a Record> + Send + 'a,
> {
let mut metadata = Metadata::response_from_request(request_meta);
metadata.response_code = response_code;
MessageResponse {
metadata,
queries: self.queries,
answers: Box::new(None.into_iter()),
authorities: Box::new(None.into_iter()),
soa: Box::new(None.into_iter()),
additionals: Box::new(None.into_iter()),
signature: self.signature,
edns: self.edns,
}
}
}
#[cfg(test)]
mod tests {
use std::iter;
use std::net::Ipv4Addr;
use std::str::FromStr;
use crate::proto::op::{Header, Message, MessageType, Metadata, OpCode};
use crate::proto::rr::{DNSClass, Name, RData, Record};
use crate::proto::serialize::binary::{BinDecodable, BinDecoder, BinEncoder};
use super::*;
#[test]
fn test_truncation_ridiculous_number_answers() {
let mut buf = Vec::with_capacity(512);
{
let mut encoder = BinEncoder::new(&mut buf);
encoder.set_max_size(512);
let mut answer = Record::from_rdata(
Name::from_str("www.example.com.").unwrap(),
0,
RData::A(Ipv4Addr::new(93, 184, 215, 14).into()),
);
answer.dns_class = DNSClass::NONE;
let message = MessageResponse {
metadata: Metadata::new(10, MessageType::Response, OpCode::Query),
queries: &Queries::empty(),
answers: iter::repeat(&answer),
authorities: iter::once(&answer),
soa: iter::once(&answer),
additionals: iter::once(&answer),
signature: None,
edns: None,
};
message
.destructive_emit(&mut encoder)
.expect("failed to encode");
}
let response = Message::from_vec(&buf).expect("failed to decode");
assert!(response.metadata.truncation);
assert!(response.answers.len() > 1);
assert_eq!(response.authorities.len(), 0);
}
#[test]
fn test_truncation_ridiculous_number_nameservers() {
let mut buf = Vec::with_capacity(512);
{
let mut encoder = BinEncoder::new(&mut buf);
encoder.set_max_size(512);
let mut answer = Record::from_rdata(
Name::from_str("www.example.com.").unwrap(),
0,
RData::A(Ipv4Addr::new(93, 184, 215, 14).into()),
);
answer.dns_class = DNSClass::NONE;
let message = MessageResponse {
metadata: Metadata::new(10, MessageType::Response, OpCode::Query),
queries: &Queries::empty(),
answers: iter::empty(),
authorities: iter::repeat(&answer),
soa: iter::repeat(&answer),
additionals: iter::repeat(&answer),
signature: None,
edns: None,
};
message
.destructive_emit(&mut encoder)
.expect("failed to encode");
}
let response = Message::from_vec(&buf).expect("failed to decode");
assert!(response.metadata.truncation);
assert_eq!(response.answers.len(), 0);
assert!(response.authorities.len() > 1);
}
#[test]
fn bad_length_of_named_pointers() {
let mut buf = Vec::with_capacity(512);
let mut encoder = BinEncoder::new(&mut buf);
let data: &[u8] = &[
0x08u8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut decoder = BinDecoder::new(data);
let header = Header::read(&mut decoder).unwrap();
let msg = MessageRequest::read(&mut decoder, header).unwrap();
eprintln!("queries: {:?}", msg.queries.queries());
MessageResponseBuilder::new(&msg.queries, None)
.build_no_records(Metadata::response_from_request(&msg.metadata))
.destructive_emit(&mut encoder)
.unwrap();
}
}