diff --git a/Cargo.toml b/Cargo.toml index 6f21132..15af164 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "check_ip" -version = "2.0.0" +version = "2.1.0" edition = "2018" [dependencies] @@ -15,4 +15,5 @@ simplelog = "^0.10.0" clokwerk = "0.3" trust-dns-resolver = {version = "0.20", features = ["serde-config"] } query_external_ip = "0.1" -tokio = "1" \ No newline at end of file +tokio = "1" +systemstat = "0.1" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index b4c4618..77794c4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,17 +6,18 @@ extern crate log; extern crate native_tls; extern crate serde; extern crate simplelog; +extern crate systemstat; extern crate tokio; extern crate toml; extern crate trust_dns_resolver; use self::native_tls::{Protocol, TlsConnector}; -use anyhow::{bail, Result}; +use anyhow::{anyhow, bail, Result}; use clokwerk::{Scheduler, TimeUnits}; use lettre::smtp::authentication::Credentials; use lettre::{ClientSecurity, ClientTlsParameters, SmtpClient, Transport}; use lettre_email::EmailBuilder; -use log::{error, info}; +use log::{error, info, warn}; use query_external_ip::Consensus; use serde::Deserialize; use simplelog::{ConfigBuilder, LevelFilter, WriteLogger}; @@ -24,6 +25,7 @@ use std::fs::{self, OpenOptions}; use std::net::{Ipv4Addr, Ipv6Addr}; use std::string::String; use std::{thread, time::Duration}; +use systemstat::{Platform, System}; use tokio::runtime::{Builder, Runtime}; use trust_dns_resolver::{config::*, Name, Resolver}; @@ -54,12 +56,19 @@ fn main() -> Result<()> { Ok(tester) => tester, }; + // Test Ethernet + if let Err(e) = wait_eth_connection() { + error!("Error {}", e); + return Err(e); + } + // Initial check if let Err(e) = tester.check() { error!("Error {}", e); bail!("Cannot get initial IP"); } + // Lauch scheduler if let Some(false) = tester.config.test { // Init scheduler info!("Init scheduler"); @@ -80,6 +89,31 @@ fn main() -> Result<()> { Ok(()) } +fn wait_eth_connection() -> Result<()> { + let mut wait_s = 0; + loop { + let sys = System::new(); + for netif in sys.networks()?.values() { + if netif.addrs.len() > 0 { + for addr in netif.addrs.iter() { + if let systemstat::IpAddr::V4(ipv4_addr) = addr.addr { + if ipv4_addr != Ipv4Addr::LOCALHOST { + return Ok(()); + } + } + } + } + } + if wait_s >= 60 { + break; + } + warn!("Cannot get ethernet connection, wait 5s and retry"); + wait_s += 5; + std::thread::sleep(std::time::Duration::from_secs(5)); + } + bail!("Cannot get ethernet connection") +} + struct Tester { config: Config, dns_resolver: Resolver, @@ -117,8 +151,12 @@ impl Tester { fn get_ip(&self) -> Result<(Ipv4Addr, Ipv6Addr)> { let cons = self.async_runtime.block_on(Consensus::get())?; - let ipv4 = cons.v4().unwrap(); - let ipv6 = cons.v6().unwrap(); + let ipv4 = cons + .v4() + .ok_or(anyhow!("Cannot get current IPv4 address"))?; + let ipv6 = cons + .v6() + .ok_or(anyhow!("Cannot get current IPv6 address"))?; info!("Current IPv4 is {} and IPv6 {}", ipv4, ipv6); Ok((ipv4, ipv6)) @@ -136,12 +174,13 @@ impl Tester { let mut full_msg = String::new(); for domain in self.config.server.domains.iter() { + info!("Test domain {}", domain); if let Ok(dns_ipv4_lookup) = self.dns_resolver.ipv4_lookup(domain.clone()) { let dns_ipv4 = dns_ipv4_lookup.iter().next().unwrap(); if *dns_ipv4 != ipv4 { msg!( full_msg, - "Wrong IPV4 for {} (DNS: {}, current: {})", + "Wrong IPv4 for {} (DNS: {}, current: {})", domain, dns_ipv4, ipv4 @@ -155,7 +194,7 @@ impl Tester { if *dns_ipv6 != ipv6 { msg!( full_msg, - "Wrong IPV6 for {} (DNS: {}, current: {})", + "Wrong IPv6 for {} (DNS: {}, current: {})", domain, dns_ipv6, ipv6