use hickory_resolver::proto::rr::rdata::*; use hickory_resolver::Resolver; use hickory_resolver::config::*; use core::fmt; use crate::config::Config; // #[derive(Debug)] pub struct Domain { domain_name: String, subdomains: Vec, a_records: Vec, aaaa_records: Vec, txt_records: Vec, mx_records: Vec, ns_records: Vec, soa_records: Vec, // Subdomains CAN have there own SOA records if their zones point elsewhere resolver: Resolver, } impl fmt::Display for Domain { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Domain name: {}\n", self.domain_name)?; write!(f, "DNS Records\n\n")?; for rec in &self.a_records { write!(f, "A: {}\n", rec)?; } for rec in &self.aaaa_records { write!(f, "AAAA: {}\n", rec)?; } for rec in &self.mx_records { write!(f, "MX: {}\n", rec)?; } for rec in &self.txt_records { write!(f, "TXT: {}\n", rec)?; } for rec in &self.ns_records { write!(f, "NS: {}\n", rec)?; } for rec in &self.soa_records { write!(f, "SOA: {}\n", rec)?; } write!(f, "\n\nSubdomains:\n\n")?; for subdomain in &self.subdomains { write!(f, "{}:\n", subdomain.domain_name)?; for rec in &subdomain.a_records { write!(f, "\tA: {}\n", rec)?; } } write!(f, "\n") } } impl Domain { pub fn new(domain: String) -> Domain { Domain { domain_name: domain, subdomains: vec![], a_records: vec![], aaaa_records: vec![], txt_records: vec![], mx_records: vec![], ns_records: vec![], soa_records: vec![], resolver: Resolver::new(ResolverConfig::default(), ResolverOpts::default()).unwrap(), } } pub fn append_subdomain(&mut self, subdomain: String) { let mut new_domain = String::from(subdomain); new_domain.push_str("."); new_domain.push_str(&self.domain_name); let subdomain = Domain::new(new_domain); self.subdomains.push(subdomain); // println!("Added: {}", new_domain); } pub fn apply_config(&mut self, config: &Config) { for subdomain in &config.subdomains { self.append_subdomain(subdomain.to_string()); } self.append_subdomain(config.wildcard_test.to_string()) } pub fn lookup_all_records(&mut self) { // Lookup A records self.lookup_a(); // Lookup AAAA records self.lookup_aaaa(); // Lookup MX records self.lookup_mx(); // Lookup TXT records self.lookup_txt(); // Lookup TXT records self.lookup_ns(); // Lookup TXT records self.lookup_soa(); // Do subdomains? for subdomain in &mut self.subdomains { // println!("Looking up subdomain: {}", subdomain.domain_name); subdomain.lookup_all_records(); } } fn lookup_a(&mut self) { let response = self.resolver.ipv4_lookup(&self.domain_name); match response { Ok(rec) => { for entry in rec { self.a_records.push(entry); } }, Err(_err) => {}, } } fn lookup_aaaa(&mut self) { let response = self.resolver.ipv6_lookup(&self.domain_name); match response { Ok(rec) => { for entry in rec { self.aaaa_records.push(entry); } }, Err(_err) => {} // Log error } } fn lookup_mx(&mut self) { let response = self.resolver.mx_lookup(&self.domain_name); match response { Ok(rec) => { for entry in rec { self.mx_records.push(entry); } }, Err(_err) => {}, } } fn lookup_txt(&mut self) { let response = self.resolver.txt_lookup(&self.domain_name); match response { Ok(rec) => { for entry in rec { self.txt_records.push(entry); } }, Err(_err) => {}, } } fn lookup_ns(&mut self) { let response = self.resolver.ns_lookup(&self.domain_name); match response { Ok(rec) => { for entry in rec { self.ns_records.push(entry); } }, Err(_err) => {}, } } fn lookup_soa(&mut self) { let response = self.resolver.soa_lookup(&self.domain_name); match response { Ok(rec) => { for entry in rec { self.soa_records.push(entry); } }, Err(_err) => {}, } } }