Skip to content

Commit

Permalink
[DR] Feat: Add test for resource record
Browse files Browse the repository at this point in the history
  • Loading branch information
Phuong Dao committed Aug 11, 2024
1 parent f4189e4 commit af07a66
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 37 deletions.
61 changes: 25 additions & 36 deletions src/lib/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use std::{
};

use message::DnsMessage;
use rr::ResourceRecord;

pub mod header;
pub mod message;
Expand Down Expand Up @@ -46,7 +45,7 @@ impl DnsClient {
println!("[\n\t{}\n]", ip_addrs.join("\n\t"));
found_ip_addrs = true;
break;
}
}
}
if !found_ip_addrs {
error!("Can's resolve {}", host_name);
Expand All @@ -56,18 +55,18 @@ impl DnsClient {
/// Get all root servers address
fn get_root_servers(&self) -> Vec<String> {
vec![
String::from("198.41.0.4"), // a.root-servers.net
String::from("199.9.14.201"), // b.root-servers.net
String::from("192.33.4.12"), // c.root-servers.net
String::from("199.7.91.13"), // d.root-servers.net
String::from("198.41.0.4"), // a.root-servers.net
String::from("199.9.14.201"), // b.root-servers.net
String::from("192.33.4.12"), // c.root-servers.net
String::from("199.7.91.13"), // d.root-servers.net
String::from("192.203.230.10"), // e.root-servers.net
String::from("192.5.5.241"), // f.root-servers.net
String::from("198.97.190.53"), // h.root-servers.net
String::from("192.36.148.17"), // i.root-servers.net
String::from("192.58.128.30"), // j.root-servers.net
String::from("193.0.14.129"), // k.root-servers.net
String::from("199.7.83.42"), // l.root-servers.net
String::from("202.12.27.33") // m.root-servers.net
String::from("192.5.5.241"), // f.root-servers.net
String::from("198.97.190.53"), // h.root-servers.net
String::from("192.36.148.17"), // i.root-servers.net
String::from("192.58.128.30"), // j.root-servers.net
String::from("193.0.14.129"), // k.root-servers.net
String::from("199.7.83.42"), // l.root-servers.net
String::from("202.12.27.33"), // m.root-servers.net
]
}

Expand All @@ -88,15 +87,25 @@ impl DnsClient {
info!("Querying {} for {}", dns_server, host_name);
self.send(&dns_server, 53, &dns_question.into_bytes());
let bytes = self.listen().unwrap();
println!("{:#2x?}", bytes);
let dns_response = DnsMessage::parse(&bytes).unwrap();
if dns_response.header.an_cnt > 0 {
let ip_addrs = self.parse_rr(0x01, &dns_response.answers);
let ip_addrs = dns_response
.answers
.iter()
.filter(|an| an.is_host_addr())
.map(|an| an.get_ip_addr())
.collect();
return (Some(ip_addrs), None);
}

if dns_response.header.ar_cnt > 0 {
let mut auth_servers =
VecDeque::from(self.parse_rr(0x01, &dns_response.additionals));
let mut auth_servers = dns_response
.additionals
.iter()
.filter(|ar| ar.is_host_addr())
.map(|ar| ar.get_ip_addr())
.collect();
dns_servers.append(&mut auth_servers);
} else if dns_response.header.ns_cnt > 0 {
ns_names = dns_response
Expand All @@ -114,26 +123,6 @@ impl DnsClient {
(None, None)
}

/// Parse resource records and transform them into ip addresses
fn parse_rr(&self, rr_type: u16, rrs: &Vec<ResourceRecord>) -> Vec<String> {
let mut ip_addrs = vec![];
for i in 0..rrs.len() {
if rrs[i].rr_type == rr_type {
ip_addrs.push(self.get_ip_addr(&rrs[i]));
}
}
ip_addrs
}

/// Show IP address in DNS answer section
fn get_ip_addr(&self, rr: &ResourceRecord) -> String {
rr.rr_rdata
.iter()
.map(|&seg| seg.to_string())
.collect::<Vec<String>>()
.join(".")
}

/// Send a udp message to a remote address
fn send(&self, remote_addr: &str, port: u16, msg: &[u8]) -> usize {
let result: usize = 0;
Expand Down
15 changes: 14 additions & 1 deletion src/lib/client/rr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl ResourceRecord {
if is_pointer == 0xC0 {
let offset = (utility::to_u16(&message[start..start + 2]) & 0x3F) as usize;
let null_pos = utility::find_first_null(&message[offset as usize..])?;
let rr_name = message[offset as usize.. offset + null_pos + 1].to_vec();
let rr_name = message[offset as usize..offset + null_pos + 1].to_vec();
let rr_type = utility::to_u16(&message[start + 2..start + 4]);
let rr_class = utility::to_u16(&message[start + 4..start + 6]);
let rr_ttl = utility::to_u32(&message[start + 6..start + 10]);
Expand Down Expand Up @@ -91,4 +91,17 @@ impl ResourceRecord {
Ok((offset + 11 + rr_rdlength as usize, rr))
}
}

/// Get the ip address from resource record
pub fn get_ip_addr(&self) -> String {
self.rr_rdata
.iter()
.map(|&seg| seg.to_string())
.collect::<Vec<String>>()
.join(".")
}

pub fn is_host_addr(&self) -> bool {
self.rr_type == 0x01
}
}
44 changes: 44 additions & 0 deletions tests/rr_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use dns_resolver::client::message::DnsMessage;

#[test]
fn parse_resource_record() {
let rr = vec![
0x6e, 0x78, 0x80, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x4, 0x0, 0x8, 0x3, 0x64, 0x6e, 0x73, 0x6,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x3, 0x63, 0x6f, 0x6d, 0x0, 0x0, 0x1, 0x0, 0x1, 0xc0,
0x10, 0x0, 0x2, 0x0, 0x1, 0x0, 0x2, 0xa3, 0x0, 0x0, 0x6, 0x3, 0x6e, 0x73, 0x32, 0xc0, 0x10,
0xc0, 0x10, 0x0, 0x2, 0x0, 0x1, 0x0, 0x2, 0xa3, 0x0, 0x0, 0x6, 0x3, 0x6e, 0x73, 0x31, 0xc0,
0x10, 0xc0, 0x10, 0x0, 0x2, 0x0, 0x1, 0x0, 0x2, 0xa3, 0x0, 0x0, 0x6, 0x3, 0x6e, 0x73, 0x33,
0xc0, 0x10, 0xc0, 0x10, 0x0, 0x2, 0x0, 0x1, 0x0, 0x2, 0xa3, 0x0, 0x0, 0x6, 0x3, 0x6e, 0x73,
0x34, 0xc0, 0x10, 0xc0, 0x2c, 0x0, 0x1c, 0x0, 0x1, 0x0, 0x2, 0xa3, 0x0, 0x0, 0x10, 0x20,
0x1, 0x48, 0x60, 0x48, 0x2, 0x0, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xc0, 0x2c,
0x0, 0x1, 0x0, 0x1, 0x0, 0x2, 0xa3, 0x0, 0x0, 0x4, 0xd8, 0xef, 0x22, 0xa, 0xc0, 0x3e, 0x0,
0x1c, 0x0, 0x1, 0x0, 0x2, 0xa3, 0x0, 0x0, 0x10, 0x20, 0x1, 0x48, 0x60, 0x48, 0x2, 0x0,
0x32, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xc0, 0x3e, 0x0, 0x1, 0x0, 0x1, 0x0, 0x2,
0xa3, 0x0, 0x0, 0x4, 0xd8, 0xef, 0x20, 0xa, 0xc0, 0x50, 0x0, 0x1c, 0x0, 0x1, 0x0, 0x2,
0xa3, 0x0, 0x0, 0x10, 0x20, 0x1, 0x48, 0x60, 0x48, 0x2, 0x0, 0x36, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0xa, 0xc0, 0x50, 0x0, 0x1, 0x0, 0x1, 0x0, 0x2, 0xa3, 0x0, 0x0, 0x4, 0xd8, 0xef,
0x24, 0xa, 0xc0, 0x62, 0x0, 0x1c, 0x0, 0x1, 0x0, 0x2, 0xa3, 0x0, 0x0, 0x10, 0x20, 0x1,
0x48, 0x60, 0x48, 0x2, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xc0, 0x62, 0x0,
0x1, 0x0, 0x1, 0x0, 0x2, 0xa3, 0x0, 0x0, 0x4, 0xd8, 0xef, 0x26, 0xa,
];

let response = DnsMessage::parse(&rr);
assert!(response.is_ok());
let response = response.unwrap();
let ip_addrs = response
.additionals
.iter()
.filter(|rr| rr.is_host_addr())
.map(|ar| ar.get_ip_addr())
.collect::<Vec<String>>();

assert_eq!(
ip_addrs,
vec![
"216.239.34.10",
"216.239.32.10",
"216.239.36.10",
"216.239.38.10"
]
);
}

0 comments on commit af07a66

Please sign in to comment.