aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs2
-rw-r--r--src/main.rs56
-rw-r--r--src/util.rs33
3 files changed, 24 insertions, 67 deletions
diff --git a/src/lib.rs b/src/lib.rs
index e708ecb..7edf3bf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,2 @@
mod error;
pub use error::*;
-
-pub mod util;
diff --git a/src/main.rs b/src/main.rs
index 4c27d26..c753823 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,3 @@
-use rsdsl_dhcp6::util::setsockopt;
use rsdsl_dhcp6::{Error, Result};
use std::ffi::CString;
@@ -11,7 +10,10 @@ use std::process;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use std::thread;
-use std::time::{Duration, Instant, SystemTime};
+use std::time::SystemTime;
+
+use tokio::net::{ToSocketAddrs, UdpSocket};
+use tokio::time::{self, Duration, Instant};
use dhcproto::v6::{duid::Duid, DhcpOption, IAPrefix, Message, MessageType, OptionCode, IAPD, ORO};
use dhcproto::{Decodable, Decoder, Encodable, Encoder, Name};
@@ -20,8 +22,8 @@ use rsdsl_pd_config::PdConfig;
use socket2::{Domain, SockAddr, Socket, Type};
use trust_dns_proto::serialize::binary::BinDecodable;
-const BUFSIZE: usize = 1500;
const DUID_LOCATION: &str = "/data/dhcp6.duid";
+const TICK_INTERVAL: u64 = 60;
#[derive(Clone, Debug, Eq, PartialEq)]
struct Dhcp6 {
@@ -31,8 +33,6 @@ struct Dhcp6 {
impl Dhcp6 {
fn load_from_disk() -> Result<Self> {
- let mut lease_file = File::open(rsdsl_pd_config::LOCATION)?;
-
Ok(Self {
duid: load_or_generate_duid()?,
lease: load_lease_optional(),
@@ -41,11 +41,11 @@ impl Dhcp6 {
}
fn load_or_generate_duid() -> Result<Duid> {
- match fs::read("/data/dhcp6.duid") {
+ match fs::read(DUID_LOCATION) {
Ok(duid) => Ok(duid.into()),
Err(_) => {
let duid = Duid::uuid(&rand::random::<u128>().to_be_bytes());
- fs::write("/data/dhcp6.duid", &duid)?;
+ fs::write(DUID_LOCATION, &duid)?;
Ok(duid)
}
@@ -57,7 +57,8 @@ fn load_lease_optional() -> Option<PdConfig> {
serde_json::from_reader(&mut file).ok()
}
-fn main() -> Result<()> {
+#[tokio::main]
+async fn main() -> Result<()> {
let dhcp6 = Dhcp6::load_from_disk()?;
let sock = Socket::new(Domain::IPV6, Type::DGRAM, None)?;
@@ -66,38 +67,29 @@ fn main() -> Result<()> {
sock.set_reuse_port(true)?;
sock.set_reuse_address(true)?;
- // Bind socket to interface.
- unsafe {
- let link_index = CString::new("ppp0")?.into_raw();
-
- setsockopt(
- sock.as_raw_fd(),
- libc::SOL_SOCKET,
- libc::SO_BINDTODEVICE,
- link_index,
- "ppp0".len() as i32,
- )?;
-
- // Prevent memory leak.
- let _ = CString::from_raw(link_index);
- }
-
let address = SocketAddr::from_str("[::]:546")?;
sock.bind(&address.into())?;
- loop {
- let mut buf = [MaybeUninit::new(0); BUFSIZE];
- let (n, remote) = sock.recv_from(&mut buf)?;
+ let sock: std::net::UdpSocket = sock.into();
+ let sock: UdpSocket = sock.try_into()?;
+
+ sock.bind_device(Some("ppp0".as_bytes()))?;
- // See unstable `MaybeUninit::slice_assume_init_ref`.
- let buf = unsafe { &*(&buf as *const [MaybeUninit<u8>] as *const [u8]) };
+ let mut interval = time::interval(Duration::from_secs(TICK_INTERVAL));
- let buf = &buf[..n];
+ let mut buf = [0; 1500];
+ loop {
+ tokio::select! {
+ result = sock.recv_from(&mut buf) => {
+ }
+ _ = interval.tick() => {
+ }
+ }
}
}
-fn send_to_exact(sock: &Socket, buf: &[u8], dst: &SockAddr) -> Result<()> {
- let n = sock.send_to(buf, dst)?;
+async fn send_to_exact<A: ToSocketAddrs>(sock: &UdpSocket, buf: &[u8], target: A) -> Result<()> {
+ let n = sock.send_to(buf, target).await?;
if n != buf.len() {
Err(Error::PartialSend)
} else {
diff --git a/src/util.rs b/src/util.rs
deleted file mode 100644
index 245f755..0000000
--- a/src/util.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-use std::ffi::{c_char, c_int};
-use std::io;
-
-/// Helper macro to execute a system call that returns an `io::Result`.
-macro_rules! syscall {
- ($fn: ident ( $($arg: expr),* $(,)* ) ) => {{
- #[allow(unused_unsafe)]
- let res = unsafe { libc::$fn($($arg, )*) };
- if res == -1 {
- Err(io::Error::last_os_error())
- } else {
- Ok(res)
- }
- }};
-}
-
-#[allow(clippy::missing_safety_doc)]
-pub unsafe fn setsockopt(
- fd: c_int,
- opt: c_int,
- val: c_int,
- payload: *const c_char,
- optlen: c_int,
-) -> io::Result<()> {
- syscall!(setsockopt(
- fd,
- opt,
- val,
- payload.cast(),
- optlen as libc::socklen_t
- ))
- .map(|_| ())
-}