Compare commits

..

2 Commits

Author SHA1 Message Date
bca8892147 Added config parsing 2024-03-22 17:01:34 +11:00
91db678c55 Moved Domain struct and impl to its own file 2024-03-22 16:32:25 +11:00
6 changed files with 234 additions and 177 deletions

7
Cargo.lock generated
View File

@ -73,6 +73,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "configparser"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec6d3da8e550377a85339063af6e3735f4b1d9392108da4e083a1b3b9820288"
[[package]] [[package]]
name = "data-encoding" name = "data-encoding"
version = "2.5.0" version = "2.5.0"
@ -83,6 +89,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
name = "dns_lookup_project" name = "dns_lookup_project"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"configparser",
"hickory-resolver", "hickory-resolver",
] ]

View File

@ -6,4 +6,5 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
configparser = "3.0.4"
hickory-resolver = { version = "0.24.0" } hickory-resolver = { version = "0.24.0" }

33
src/config.rs Normal file
View File

@ -0,0 +1,33 @@
use configparser::ini::Ini;
use core::fmt;
pub struct Config {
pub subdomains: Vec<String>,
wildcard_test: String,
}
impl fmt::Display for Config {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Subdomains: {:?}\nWildcard Test: {}", self.subdomains, self.wildcard_test)
}
}
impl Config {
pub fn from_file(file_path: String) -> Config {
let mut config = Ini::new();
let _map = config.load(file_path).unwrap();
let subdomains = config.get("General", "subdomains").unwrap();
let mut subvec: Vec<String> = vec![];
for x in subdomains.split(',') {
subvec.push(x.to_string());
}
let wildcard_test = config.get("General", "wildcard_test");
Config {
subdomains: subvec,
wildcard_test: wildcard_test.unwrap()
}
}
}

182
src/domain.rs Normal file
View File

@ -0,0 +1,182 @@
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<Domain>,
a_records: Vec<A>,
aaaa_records: Vec<AAAA>,
txt_records: Vec<TXT>,
mx_records: Vec<MX>,
ns_records: Vec<NS>,
soa_records: Vec<SOA>, // 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());
}
}
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) => {},
}
}
}

View File

@ -1,184 +1,15 @@
use hickory_resolver::proto::rr::rdata::*; mod domain;
use hickory_resolver::Resolver; use crate::domain::Domain;
use hickory_resolver::config::*;
use core::fmt; mod config;
use crate::config::Config;
// #[derive(Debug)]
struct Domain {
domain_name: String,
subdomains: Vec<Domain>,
a_records: Vec<A>,
aaaa_records: Vec<AAAA>,
txt_records: Vec<TXT>,
mx_records: Vec<MX>,
ns_records: Vec<NS>,
soa_records: Vec<SOA>, // 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")?;
for subdomain in &self.subdomains {
write!(f, "{}\n", subdomain.domain_name)?;
for rec in &subdomain.a_records {
write!(f, "A: {}\n", rec)?;
}
}
write!(f, "\n")
}
}
impl Domain {
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(),
}
}
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);
}
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) => {},
}
}
}
fn main() { fn main() {
let mut test = Domain::new("swin.edu.au.".to_string()); let mut test = Domain::new("pigandpilgrim.com.au".to_string());
test.append_subdomain("www".to_string()); let config = Config::from_file("test.ini".to_string());
test.append_subdomain("mail".to_string()); test.apply_config(&config);
test.append_subdomain("ftp".to_string());
test.lookup_all_records(); test.lookup_all_records();
println!("{}", test); println!("{}", test);

3
test.ini Normal file
View File

@ -0,0 +1,3 @@
[General]
wildcard_test=dfjgnkdfjngkdfngjkd
subdomains=www,ftp,mail