From 577a137c62fdad99a08c7b3026d55ad963ff51d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Sun, 11 Nov 2018 18:45:57 +0100 Subject: [PATCH] initial commit --- .gitignore | 2 + Cargo.lock | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 9 +++ src/main.rs | 122 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 290 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..53eaa21 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +**/*.rs.bk diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..fcbdc15 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,157 @@ +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clap" +version = "2.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.43" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libresolv-sys" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lookup" +version = "0.1.0" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "resolv 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "resolv" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libresolv-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "strsim" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "termion" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-width" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" +"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" +"checksum libresolv-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eb7e7216e9097a97b63e53a324c8972b9c499ac8c4a71b6365da9c1c1d589d48" +"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum resolv 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "da9b4625242386471752e8965860cae1c780ba836aaf7b47a8a9e4946752dd9b" +"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..49c7e9f --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "lookup" +version = "0.1.0" +authors = ["Stefan Bühler "] +description = "Lookup IPv4 and IPv6 addresses for a hostname" + +[dependencies] +resolv = "0.1.3" +clap = "2.32.0" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..a5dded4 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,122 @@ +#[macro_use] +extern crate clap; +extern crate resolv; + +use resolv::{ + Resolver, + Class, + Section, + error::{ + Error, + ResolutionError, + }, + record::{ + A, + AAAA, + }, +}; + +use std::process::exit; +use std::ffi::OsStr; +use std::os::unix::ffi::OsStrExt; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +use std::fmt; + +/// Workaround https://github.com/mikedilger/resolv-rs/issues/1 +/// +/// When it gets fixed, this will simply call the inner `.next()` a few +/// times too often, which should hurt much. +struct FixedIterator<'a, T: resolv::record::RecordData>(resolv::RecordItems<'a, T>, usize); + +impl<'a, T: resolv::record::RecordData> Iterator for FixedIterator<'a, T> { + type Item = resolv::Record; + + fn next(&mut self) -> Option { + while self.1 > 0 { + self.1 -= 1; + if let Some(r) = self.0.next() { + return Some(r); + } + } + return None; + } +} + +impl<'a, T: resolv::record::RecordData> FixedIterator<'a, T> { + pub fn answers(response: &'a mut resolv::Response) -> Self { + let count = response.get_section_count(Section::Answer); + FixedIterator(response.answers::(), count) + } +} + +pub trait AddressRecord: resolv::record::RecordData { + type Address: Into + fmt::Display + fmt::Debug; + + fn address(&self) -> Self::Address; +} + +impl AddressRecord for A { + type Address = Ipv4Addr; + + fn address(&self) -> Ipv4Addr { + self.address + } +} + +impl AddressRecord for AAAA { + type Address = Ipv6Addr; + + fn address(&self) -> Ipv6Addr { + self.address + } +} + +fn run(resolver: &mut resolv::Resolver, name: &OsStr) { + match resolver.query(name.as_bytes(), Class::IN, R::get_record_type()) { + Ok(mut response) => { + for answer in FixedIterator::::answers(&mut response) { + println!("{}", answer.data.address()); + } + }, + Err(Error::Resolver(ResolutionError::HostNotFound)) => { + eprintln!("Host not found: {:?}", name); + exit(0); + }, + Err(Error::Resolver(ResolutionError::NoData)) => { + // empty answer is perfectly fine + }, + Err(e) => { + eprintln!("Failed looking up {:?}: {}", name, e); + exit(1); + }, + } +} + +fn main() { + let app = clap_app!(("lookup") => + (version: crate_version!()) + (author: crate_authors!("\n")) + (about: crate_description!()) + (@arg IPv4: short("4") conflicts_with("IPv6") "Query only IPv4 records (A)") + (@arg IPv6: short("6") "Query only IPv6 records (AAAA)") + (@arg NAME: +required "Name to lookup") + ); + let matches = app.get_matches(); + + let ipv4_only = matches.is_present("IPv4"); + let ipv6_only = matches.is_present("IPv6"); + let name = matches.value_of_os("NAME").unwrap(); + + let mut resolver = Resolver::new().unwrap_or_else(|| { + eprintln!("Couldn't initialize resolver"); + exit(1); + }); + + if !ipv6_only { + run::(&mut resolver, name); + } + + if !ipv4_only { + run::(&mut resolver, name); + } +}