aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeerserverDE <himbeerserverde@gmail.com>2022-10-28 16:36:28 +0200
committerHimbeerserverDE <himbeerserverde@gmail.com>2022-10-28 16:36:28 +0200
commit4b4510108aab8ed937a4d6f3a79292f97f341416 (patch)
tree5786cbff09a6f65f03eb4bcb96fcdcd076f9fbef
parent40b3398b7d56006568ceb9eae7bc2d30676885f0 (diff)
use ipnet for ipv6 calculations
closes #2
-rw-r--r--Cargo.toml2
-rw-r--r--src/main.rs51
2 files changed, 21 insertions, 32 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 42f4f4b..cc7e561 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,6 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-arrayref = "0.3.6"
inwx = { version = "0.1.0", git = "https://github.com/HimbeerserverDE/inwx-rs.git" }
+ipnet = "2.5.0"
preferred-ip = { version = "0.1.0", git = "https://github.com/HimbeerserverDE/preferred-ip.git" }
diff --git a/src/main.rs b/src/main.rs
index a576e79..a65e799 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -5,20 +5,21 @@ use std::sync::{mpsc, Arc};
use std::thread;
use std::time::Duration;
-use arrayref::array_ref;
use inwx::call::nameserver::{RecordInfo as RecordInfoCall, RecordUpdate};
use inwx::common::nameserver::RecordType;
use inwx::response::nameserver::RecordInfo as RecordInfoResponse;
use inwx::{Client, Endpoint};
+use ipnet::{IpBitAnd, IpBitOr, Ipv6Net};
#[derive(Debug)]
enum Error {
ChannelRecv(mpsc::RecvError),
ChannelSend4(mpsc::SendError<Ipv4Addr>),
- ChannelSend6(mpsc::SendError<Ipv6Addr>),
+ ChannelSend6(mpsc::SendError<Ipv6Net>),
Inwx(inwx::Error),
PreferredIp(preferred_ip::Error),
ParseAddr(std::net::AddrParseError),
+ PrefixLen(ipnet::PrefixLenError),
}
impl std::error::Error for Error {}
@@ -32,6 +33,7 @@ impl fmt::Display for Error {
Self::Inwx(e) => write!(fmt, "inwx library error: {}", e),
Self::PreferredIp(e) => write!(fmt, "preferred_ip library error: {}", e),
Self::ParseAddr(e) => write!(fmt, "can't parse ip address: {}", e),
+ Self::PrefixLen(e) => write!(fmt, "prefix length error: {}", e),
}
}
}
@@ -48,8 +50,8 @@ impl From<mpsc::SendError<Ipv4Addr>> for Error {
}
}
-impl From<mpsc::SendError<Ipv6Addr>> for Error {
- fn from(e: mpsc::SendError<Ipv6Addr>) -> Self {
+impl From<mpsc::SendError<Ipv6Net>> for Error {
+ fn from(e: mpsc::SendError<Ipv6Net>) -> Self {
Self::ChannelSend6(e)
}
}
@@ -72,6 +74,12 @@ impl From<std::net::AddrParseError> for Error {
}
}
+impl From<ipnet::PrefixLenError> for Error {
+ fn from(e: ipnet::PrefixLenError) -> Self {
+ Self::PrefixLen(e)
+ }
+}
+
type Result<T> = std::result::Result<T, Error>;
#[derive(Clone, Debug)]
@@ -80,7 +88,7 @@ struct Config {
pass: String,
records4: Vec<i32>,
records6: Vec<i32>,
- prefix_len: u32,
+ prefix_len: u8,
link4: String,
link6: String,
interval4: Duration,
@@ -174,14 +182,14 @@ fn monitor4(config: Arc<Config>, tx: mpsc::Sender<Ipv4Addr>) -> Result<()> {
}
}
-fn monitor6(config: Arc<Config>, tx: mpsc::Sender<Ipv6Addr>) -> Result<()> {
+fn monitor6(config: Arc<Config>, tx: mpsc::Sender<Ipv6Net>) -> Result<()> {
let mut ipv6 = None;
loop {
let new_ipv6 = preferred_ip::ipv6_unicast_global(&config.link6)?;
if ipv6.is_none() || ipv6.unwrap() != new_ipv6 {
- tx.send(new_ipv6)?;
+ tx.send(Ipv6Net::new(new_ipv6, config.prefix_len)?)?;
ipv6 = Some(new_ipv6);
}
@@ -217,7 +225,7 @@ fn push4(config: Arc<Config>, rx: &mpsc::Receiver<Ipv4Addr>) -> Result<()> {
}
}
-fn push6(config: Arc<Config>, rx: &mpsc::Receiver<Ipv6Addr>) -> Result<()> {
+fn push6(config: Arc<Config>, rx: &mpsc::Receiver<Ipv6Net>) -> Result<()> {
let mut last_prefix = None;
loop {
let prefix = rx.recv()?;
@@ -249,11 +257,10 @@ fn push6(config: Arc<Config>, rx: &mpsc::Receiver<Ipv6Addr>) -> Result<()> {
for record in total_records {
let address = Ipv6Addr::from_str(&record.content)?;
- let b_addr = address.octets().to_vec();
- let b_net = prefix.octets().to_vec();
-
- let new_raw = change_prefix(b_addr, b_net, config.prefix_len);
- let new = Ipv6Addr::from(*array_ref!(new_raw.as_slice(), 0, 16));
+ // Get the interface identifier.
+ let if_id = address.bitand(prefix.hostmask());
+ let clean_prefix = prefix.addr().bitand(prefix.netmask());
+ let new = clean_prefix.bitor(if_id);
clt.call(RecordUpdate {
ids: vec![record.id],
@@ -276,21 +283,3 @@ fn push6(config: Arc<Config>, rx: &mpsc::Receiver<Ipv6Addr>) -> Result<()> {
}
}
}
-
-fn change_prefix(address: Vec<u8>, prefix: Vec<u8>, bits: u32) -> Vec<u8> {
- address
- .iter()
- .zip(prefix.iter())
- .enumerate()
- .map(|(i, (a, b))| {
- if i as u32 >= bits / 8 {
- let ones = bits % 8;
- let mask = !(0xff_u8.overflowing_shr(ones).0);
-
- (a & !mask) | (b & mask)
- } else {
- *b
- }
- })
- .collect()
-}