123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- //! dog, the command-line DNS client.
- #![warn(deprecated_in_future)]
- #![warn(future_incompatible)]
- #![warn(missing_copy_implementations)]
- #![warn(missing_docs)]
- #![warn(nonstandard_style)]
- #![warn(rust_2018_compatibility)]
- #![warn(rust_2018_idioms)]
- #![warn(single_use_lifetimes)]
- #![warn(trivial_casts, trivial_numeric_casts)]
- #![warn(unused)]
- #![warn(clippy::all, clippy::pedantic)]
- #![allow(clippy::enum_glob_use)]
- #![allow(clippy::module_name_repetitions)]
- #![allow(clippy::option_if_let_else)]
- #![allow(clippy::too_many_lines)]
- #![allow(clippy::upper_case_acronyms)]
- #![allow(clippy::wildcard_imports)]
- #![deny(unsafe_code)]
- use log::*;
- mod colours;
- mod connect;
- mod hints;
- mod logger;
- mod output;
- mod requests;
- mod resolve;
- mod table;
- mod txid;
- mod options;
- use self::options::*;
- /// Configures logging, parses the command-line options, and handles any
- /// errors before passing control over to the Dog type.
- fn main() {
- use std::env;
- use std::process::exit;
- logger::configure(env::var_os("DOG_DEBUG"));
- #[cfg(windows)]
- if let Err(e) = ansi_term::enable_ansi_support() {
- warn!("Failed to enable ANSI support: {}", e);
- }
- match Options::getopts(env::args_os().skip(1)) {
- OptionsResult::Ok(options) => {
- info!("Running with options -> {:#?}", options);
- disabled_feature_check(&options);
- exit(run(options));
- }
- OptionsResult::Help(help_reason, use_colours) => {
- if use_colours.should_use_colours() {
- print!("{}", include_str!(concat!(env!("OUT_DIR"), "/usage.pretty.txt")));
- }
- else {
- print!("{}", include_str!(concat!(env!("OUT_DIR"), "/usage.bland.txt")));
- }
- if help_reason == HelpReason::NoDomains {
- exit(exits::OPTIONS_ERROR);
- }
- else {
- exit(exits::SUCCESS);
- }
- }
- OptionsResult::Version(use_colours) => {
- if use_colours.should_use_colours() {
- print!("{}", include_str!(concat!(env!("OUT_DIR"), "/version.pretty.txt")));
- }
- else {
- print!("{}", include_str!(concat!(env!("OUT_DIR"), "/version.bland.txt")));
- }
- exit(exits::SUCCESS);
- }
- OptionsResult::InvalidOptionsFormat(oe) => {
- eprintln!("dog: Invalid options: {}", oe);
- exit(exits::OPTIONS_ERROR);
- }
- OptionsResult::InvalidOptions(why) => {
- eprintln!("dog: Invalid options: {}", why);
- exit(exits::OPTIONS_ERROR);
- }
- }
- }
- /// Runs dog with some options, returning the status to exit with.
- fn run(Options { requests, format, measure_time }: Options) -> i32 {
- use std::time::Instant;
- let should_show_opt = requests.edns.should_show();
- let mut responses = Vec::new();
- let timer = if measure_time { Some(Instant::now()) } else { None };
- let mut errored = false;
- let local_host_hints = match hints::LocalHosts::load() {
- Ok(lh) => lh,
- Err(e) => {
- warn!("Error loading local host hints: {}", e);
- hints::LocalHosts::default()
- }
- };
- for hostname_in_query in &requests.inputs.domains {
- if local_host_hints.contains(hostname_in_query) {
- eprintln!("warning: domain '{}' also exists in hosts file", hostname_in_query);
- }
- }
- let request_tuples = match requests.generate() {
- Ok(rt) => rt,
- Err(e) => {
- eprintln!("Unable to obtain resolver: {}", e);
- return exits::SYSTEM_ERROR;
- }
- };
- for (transport, request_list) in request_tuples {
- let request_list_len = request_list.len();
- for (i, request) in request_list.into_iter().enumerate() {
- let result = transport.send(&request);
- match result {
- Ok(mut response) => {
- if response.flags.error_code.is_some() && i != request_list_len - 1 {
- continue;
- }
- if ! should_show_opt {
- response.answers.retain(dns::Answer::is_standard);
- response.authorities.retain(dns::Answer::is_standard);
- response.additionals.retain(dns::Answer::is_standard);
- }
- responses.push(response);
- break;
- }
- Err(e) => {
- format.print_error(e);
- errored = true;
- break;
- }
- }
- }
- }
- let duration = timer.map(|t| t.elapsed());
- if format.print(responses, duration) {
- if errored {
- exits::NETWORK_ERROR
- }
- else {
- exits::SUCCESS
- }
- }
- else {
- exits::NO_SHORT_RESULTS
- }
- }
- /// Checks whether the options contain parameters that will cause dog to fail
- /// because the feature is disabled by exiting if so.
- #[allow(unused)]
- fn disabled_feature_check(options: &Options) {
- use std::process::exit;
- use crate::connect::TransportType;
- #[cfg(all(not(feature = "with_tls"), not(feature = "with_rustls_tls")))]
- if options.requests.inputs.transport_types.contains(&TransportType::TLS) {
- eprintln!("dog: Cannot use '--tls': This version of dog has been compiled without TLS support");
- exit(exits::OPTIONS_ERROR);
- }
- #[cfg(all(not(feature = "with_https"), not(feature = "with_rustls_https")))]
- if options.requests.inputs.transport_types.contains(&TransportType::HTTPS) {
- eprintln!("dog: Cannot use '--https': This version of dog has been compiled without HTTPS support");
- exit(exits::OPTIONS_ERROR);
- }
- }
- /// The possible status numbers dog can exit with.
- mod exits {
- /// Exit code for when everything turns out OK.
- pub const SUCCESS: i32 = 0;
- /// Exit code for when there was at least one network error during execution.
- pub const NETWORK_ERROR: i32 = 1;
- /// Exit code for when there is no result from the server when running in
- /// short mode. This can be any received server error, not just `NXDOMAIN`.
- pub const NO_SHORT_RESULTS: i32 = 2;
- /// Exit code for when the command-line options are invalid.
- pub const OPTIONS_ERROR: i32 = 3;
- /// Exit code for when the system network configuration could not be determined.
- pub const SYSTEM_ERROR: i32 = 4;
- }
|