diff --git a/src/lib/client.rs b/src/lib/client.rs index aa49917..e406329 100644 --- a/src/lib/client.rs +++ b/src/lib/client.rs @@ -5,7 +5,6 @@ use std::{ }; use message::DnsMessage; -use rr::ResourceRecord; pub mod header; pub mod message; @@ -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); @@ -56,18 +55,18 @@ impl DnsClient { /// Get all root servers address fn get_root_servers(&self) -> Vec { 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 ] } @@ -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 @@ -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) -> Vec { - 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::>() - .join(".") - } - /// Send a udp message to a remote address fn send(&self, remote_addr: &str, port: u16, msg: &[u8]) -> usize { let result: usize = 0; diff --git a/src/lib/client/rr.rs b/src/lib/client/rr.rs index 5085bce..baf95bd 100644 --- a/src/lib/client/rr.rs +++ b/src/lib/client/rr.rs @@ -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]); @@ -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::>() + .join(".") + } + + pub fn is_host_addr(&self) -> bool { + self.rr_type == 0x01 + } } diff --git a/tests/rr_test.rs b/tests/rr_test.rs new file mode 100644 index 0000000..2030b4f --- /dev/null +++ b/tests/rr_test.rs @@ -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::>(); + + assert_eq!( + ip_addrs, + vec![ + "216.239.34.10", + "216.239.32.10", + "216.239.36.10", + "216.239.38.10" + ] + ); +}