diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/error.rs | 8 | ||||
-rw-r--r-- | src/main.rs | 105 |
2 files changed, 33 insertions, 80 deletions
diff --git a/src/error.rs b/src/error.rs index 03145e1..0bbc367 100644 --- a/src/error.rs +++ b/src/error.rs @@ -4,20 +4,16 @@ use thiserror::Error; #[derive(Debug, Error)] pub enum Error { - #[error("not enough ipv6 subnets")] - NotEnoughIpv6Subnets, #[error("no address associated with aftr name")] NoDnsRecord, + #[error("not enough ipv6 subnets")] + NotEnoughIpv6Subnets, #[error("io: {0}")] Io(#[from] io::Error), #[error("ipnet prefix len: {0}")] IpnetPrefixLen(#[from] ipnet::PrefixLenError), - #[error("notify: {0}")] - Notify(#[from] notify::Error), - #[error("rsdsl_netlinkd: {0}")] - RsdslNetlinkd(#[from] rsdsl_netlinkd::error::Error), #[error("rsdsl_netlinkd_sys: {0}")] RsdslNetlinkdSys(#[from] rsdsl_netlinkd_sys::Error), #[error("serde_json: {0}")] diff --git a/src/main.rs b/src/main.rs index 2c10c66..ba4fd21 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,98 +1,52 @@ +use rsdsl_dslite::{Error, Result}; + use std::fs::File; -use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr}; -use std::path::Path; +use std::net::{Ipv6Addr, SocketAddr}; use std::thread; use std::time::Duration; use ipnet::Ipv6Net; -use notify::event::{CreateKind, ModifyKind}; -use notify::{Event, EventKind, RecursiveMode, Watcher}; -use rsdsl_dslite::{Error, Result}; -use rsdsl_ip_config::DsConfig; -use rsdsl_netlinkd::{addr, link, route}; use rsdsl_netlinkd_sys::IpIp6; use rsdsl_pd_config::PdConfig; +use signal_hook::{consts::SIGUSR1, iterator::Signals}; +use sysinfo::{ProcessExt, Signal, System, SystemExt}; use trust_dns_resolver::config::{NameServerConfig, Protocol, ResolverConfig, ResolverOpts}; use trust_dns_resolver::Resolver; -const ADDR4_AFTR: Ipv4Addr = Ipv4Addr::new(192, 0, 0, 1); -const ADDR4_B4: Ipv4Addr = Ipv4Addr::new(192, 0, 0, 2); - const MAX_ATTEMPTS: usize = 3; +const BACKOFF: u64 = 900; fn main() -> Result<()> { - println!("wait for up ppp0"); - link::wait_up("ppp0".into())?; - - let pd_config = Path::new(rsdsl_pd_config::LOCATION); - - println!("wait for dhcp6"); - while !pd_config.exists() { - thread::sleep(Duration::from_secs(8)); - } + println!("[info] init"); let mut tnl = None; - let do_setup = |tnl: &mut Option<IpIp6>| -> Result<()> { - *tnl = None; - - let mut file = File::open(rsdsl_pd_config::LOCATION)?; - let pdconfig: PdConfig = serde_json::from_reader(&mut file)?; - - if let Some(ref aftr) = pdconfig.aftr { - let local = local_address(&pdconfig)?; - let remote = multitry_resolve6(&pdconfig, aftr)?; - *tnl = Some(IpIp6::new("dslite0", "ppp0", local, remote)?); - - configure_dslite(); - } else { - println!("no aftr"); - } - - Ok(()) - }; - let setup = move |tnl: &mut Option<IpIp6>| match do_setup(tnl) { - Ok(_) => {} - Err(e) => println!("can't create dslite0: {}", e), - }; - - setup(&mut tnl); - - let mut watcher = notify::recommended_watcher(move |res: notify::Result<Event>| match res { - Ok(event) => match event.kind { - EventKind::Create(kind) if kind == CreateKind::File => setup(&mut tnl), - EventKind::Modify(kind) if matches!(kind, ModifyKind::Data(_)) => setup(&mut tnl), - _ => {} - }, - Err(e) => println!("watch error: {:?}", e), - })?; - - watcher.watch(pd_config, RecursiveMode::NonRecursive)?; - - loop { - thread::sleep(Duration::MAX); + let mut signals = Signals::new([SIGUSR1])?; + for _ in signals.forever() { + logic(&mut tnl)?; } -} -fn configure_dslite() { - match configure_dslite0() { - Ok(_) => println!("configure dslite0"), - Err(e) => println!("can't configure dslite0: {}", e), - } + unreachable!() } -fn configure_dslite0() -> Result<()> { - link::up("dslite0".into())?; +fn logic(tnl: &mut Option<IpIp6>) -> Result<()> { + *tnl = None; // Delete old tunnel. - addr::flush("dslite0".into())?; - addr::add("dslite0".into(), ADDR4_B4.into(), 29)?; + let mut file = File::open(rsdsl_pd_config::LOCATION)?; + let pdconfig: PdConfig = serde_json::from_reader(&mut file)?; - let mut file = File::open(rsdsl_ip_config::LOCATION)?; - let dsconfig: DsConfig = serde_json::from_reader(&mut file)?; + if let Some(ref aftr) = pdconfig.aftr { + let local = local_address(&pdconfig)?; + let remote = multitry_resolve6(&pdconfig, aftr)?; + *tnl = Some(IpIp6::new("dslite0", "ppp0", local, remote)?); + + for netlinkd in System::default().processes_by_exact_name("/bin/rsdsl_netlinkd") { + netlinkd.kill_with(Signal::User1); + } - // Check for native connectivity to avoid breaking netlinkd. - if dsconfig.v4.is_none() { - route::add4(Ipv4Addr::UNSPECIFIED, 0, Some(ADDR4_AFTR), "dslite0".into())?; + println!("[info] init ds-lite tunnel {} <=> {}", local, remote); + } else { + println!("[info] no aftr"); } Ok(()) @@ -137,12 +91,15 @@ fn multitry_resolve6(pdconfig: &PdConfig, fqdn: &str) -> Result<Ipv6Addr> { if i >= MAX_ATTEMPTS - 1 { return Err(e); } else { - println!("{}", e) + println!( + "[warn] resolve aftr {}: {} (attempt {}/{})", + fqdn, e, i, MAX_ATTEMPTS + ) } } } - thread::sleep(Duration::from_secs(8)); + thread::sleep(Duration::from_secs(BACKOFF)); } unreachable!() |