diff options
author | HimbeerserverDE <himbeerserverde@gmail.com> | 2023-08-13 19:05:15 +0200 |
---|---|---|
committer | HimbeerserverDE <himbeerserverde@gmail.com> | 2023-08-13 19:05:15 +0200 |
commit | 72f04e3494b4f3ba810274447235e9051f5e1749 (patch) | |
tree | 81a9e909d05d85f561ec4b16b6f3c2df2a44009b /src | |
parent | 644023c680db2346c3144e7218d9ece7402e65b5 (diff) |
add native ipv6 support0.6.0
Diffstat (limited to 'src')
-rw-r--r-- | src/error.rs | 4 | ||||
-rw-r--r-- | src/main.rs | 82 |
2 files changed, 85 insertions, 1 deletions
diff --git a/src/error.rs b/src/error.rs index 78bd0ba..6458cc1 100644 --- a/src/error.rs +++ b/src/error.rs @@ -7,8 +7,12 @@ use thiserror::Error; pub enum Error { #[error("link {0} not found")] LinkNotFound(String), + #[error("not enough ipv6 subnets")] + NotEnoughIpv6Subnets, #[error("io: {0}")] Io(#[from] io::Error), + #[error("ipnet prefix len: {0}")] + IpnetPrefixLen(#[from] ipnet::PrefixLenError), #[error("net: parse ip address: {0}")] NetAddrParseError(#[from] net::AddrParseError), #[error("notify: {0}")] diff --git a/src/main.rs b/src/main.rs index 3afefcb..8ea3f89 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use rsdsl_netlinkd::error::Result; +use rsdsl_netlinkd::error::{Error, Result}; use rsdsl_netlinkd::{addr, link, route}; use std::fs::{self, File}; @@ -7,9 +7,13 @@ use std::path::Path; use std::thread; use std::time::Duration; +use ipnet::Ipv6Net; use notify::event::{CreateKind, ModifyKind}; use notify::{Event, EventKind, RecursiveMode, Watcher}; use rsdsl_ip_config::DsConfig; +use rsdsl_pd_config::PdConfig; + +const LINK_LOCAL: Ipv6Addr = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1); fn main() -> Result<()> { println!("wait for eth0"); @@ -37,6 +41,9 @@ fn main() -> Result<()> { fs::write("/proc/sys/net/ipv4/ip_forward", "1")?; println!("enable ipv4 routing"); + fs::write("/proc/sys/net/ipv6/conf/all/forwarding", "1")?; + println!("enable ipv6 routing"); + println!("wait for eth1"); link::wait_exists("eth1".into())?; println!("detect eth1"); @@ -74,6 +81,30 @@ fn main() -> Result<()> { watcher.watch(ip_config, RecursiveMode::NonRecursive)?; + let pd_config = Path::new(rsdsl_pd_config::LOCATION); + + println!("wait for dhcp6"); + while !pd_config.exists() { + thread::sleep(Duration::from_secs(8)); + } + + configure_ipv6(); + + let mut watcher = notify::recommended_watcher(|res: notify::Result<Event>| match res { + Ok(event) => match event.kind { + EventKind::Create(kind) if kind == CreateKind::File => { + configure_ipv6(); + } + EventKind::Modify(kind) if matches!(kind, ModifyKind::Data(_)) => { + configure_ipv6(); + } + _ => {} + }, + Err(e) => println!("watch error: {:?}", e), + })?; + + watcher.watch(pd_config, RecursiveMode::NonRecursive)?; + loop { thread::sleep(Duration::MAX) } @@ -139,3 +170,52 @@ fn configure_ppp0() -> Result<()> { Ok(()) } + +fn configure_ipv6() { + match configure_all_v6() { + Ok(_) => println!("configure ipv6"), + Err(e) => println!("can't configure ipv6: {:?}", e), + } +} + +fn configure_all_v6() -> Result<()> { + let mut file = File::open(rsdsl_pd_config::LOCATION)?; + let pd_config: PdConfig = serde_json::from_reader(&mut file)?; + + let prefix = Ipv6Net::new(pd_config.prefix, pd_config.len)?.trunc(); + let mut subnets = prefix.subnets(64)?; + + addr::add("ppp0".into(), IpAddr::V6(next_ifid1(&mut subnets)?), 64)?; + + let addr = next_ifid1(&mut subnets)?; + + fs::write("/proc/sys/net/ipv6/conf/eth0/accept_ra", "0")?; + + addr::add_link_local("eth0".into(), LINK_LOCAL.into(), 64)?; + addr::add("eth0".into(), addr.into(), 64)?; + + println!("configure eth0 ({}/64)", addr); + + let zones = ["trusted", "untrusted", "isolated", "exposed"]; + for (i, zone) in zones.iter().enumerate() { + let vlan_id = 10 * (i + 1); + let vlan_name = format!("eth0.{}", vlan_id); + let vlan_addr = next_ifid1(&mut subnets)?; + + fs::write( + format!("/proc/sys/net/ipv6/conf/{}/accept_ra", vlan_name), + "0", + )?; + + addr::add_link_local(vlan_name.clone(), LINK_LOCAL.into(), 64)?; + addr::add(vlan_name.clone(), vlan_addr.into(), 64)?; + + println!("configure {} ({}/64) zone {}", vlan_name, vlan_addr, zone); + } + + Ok(()) +} + +fn next_ifid1<T: Iterator<Item = Ipv6Net>>(subnets: &mut T) -> Result<Ipv6Addr> { + Ok((u128::from(subnets.next().ok_or(Error::NotEnoughIpv6Subnets)?.addr()) + 1).into()) +} |