From f3fe2fa1237bbe8ad6a74d75377749bf904a37d1 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Sat, 7 Dec 2019 22:52:23 +0100 Subject: [PATCH] up --- src/dns.rs | 27 ++++++++++++++++++++------- src/resolver.rs | 26 +++++++++++++++++++++----- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/dns.rs b/src/dns.rs index 1765a4f..0cffa49 100644 --- a/src/dns.rs +++ b/src/dns.rs @@ -16,14 +16,17 @@ const DNS_FLAGS_RA: u16 = 1u16 << 7; const DNS_FLAGS_RD: u16 = 1u16 << 8; const DNS_FLAGS_CD: u16 = 1u16 << 4; const DNS_OFFSET_QUESTION: usize = DNS_HEADER_SIZE; -const DNS_TYPE_OPT: u16 = 41; -const DNS_TYPE_TXT: u16 = 16; -const DNS_TYPE_HINFO: u16 = 13; -const DNS_CLASS_INET: u16 = 1; -const DNS_RCODE_SERVFAIL: u8 = 2; -const DNS_RCODE_NXDOMAIN: u8 = 3; -const DNS_RCODE_REFUSED: u8 = 5; +pub const DNS_TYPE_A: u16 = 1; +pub const DNS_TYPE_AAAA: u16 = 28; +pub const DNS_TYPE_OPT: u16 = 41; +pub const DNS_TYPE_TXT: u16 = 16; +pub const DNS_TYPE_HINFO: u16 = 13; +pub const DNS_CLASS_INET: u16 = 1; + +pub const DNS_RCODE_SERVFAIL: u8 = 2; +pub const DNS_RCODE_NXDOMAIN: u8 = 3; +pub const DNS_RCODE_REFUSED: u8 = 5; #[inline] pub fn rcode(packet: &[u8]) -> u8 { @@ -478,6 +481,16 @@ pub fn serve_truncated_response(client_packet: Vec) -> Result, Error Ok(packet) } +pub fn qtype_qclass(packet: &[u8]) -> Result<(u16, u16), Error> { + ensure!(packet.len() >= DNS_HEADER_SIZE, "Short packet"); + ensure!(qdcount(&packet) == 1, "No question"); + let offset = skip_name(packet, DNS_HEADER_SIZE)?; + ensure!(packet.len() - offset >= 4, "Short packet"); + let qtype = BigEndian::read_u16(&packet[offset..]); + let qclass = BigEndian::read_u16(&packet[offset + 2..]); + Ok((qtype, qclass)) +} + pub fn serve_nxdomain_response(client_packet: Vec) -> Result, Error> { ensure!(client_packet.len() >= DNS_HEADER_SIZE, "Short packet"); ensure!(qdcount(&client_packet) == 1, "No question"); diff --git a/src/resolver.rs b/src/resolver.rs index d03ac16..0d41676 100644 --- a/src/resolver.rs +++ b/src/resolver.rs @@ -170,12 +170,28 @@ pub async fn get_cached_response_or_resolve( return dns::serve_blocked_response(packet.to_vec()); } } - if let Some(undelegated_list) = &globals.undelegated_list { - if undelegated_list.find(dns::qname_tld(&packet_qname)) { - #[cfg(feature = "metrics")] - globals.varz.client_queries_rcode_nxdomain.inc(); - return dns::serve_nxdomain_response(packet.to_vec()); + let tld = dns::qname_tld(&packet_qname); + let synthesize_nxdomain = { + if tld.len() == packet_qname.len() { + let (qtype, qclass) = dns::qtype_qclass(&packet)?; + if qtype == dns::DNS_CLASS_INET + && (qclass == dns::DNS_TYPE_A || qclass == dns::DNS_TYPE_AAAA) + { + dbg!(String::from_utf8_lossy(&packet_qname)); + true + } else { + false + } + } else if let Some(undelegated_list) = &globals.undelegated_list { + undelegated_list.find(tld) + } else { + false } + }; + if synthesize_nxdomain { + #[cfg(feature = "metrics")] + globals.varz.client_queries_rcode_nxdomain.inc(); + return dns::serve_nxdomain_response(packet.to_vec()); } let original_tid = dns::tid(&packet); dns::set_tid(&mut packet, 0);