aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeerserverDE <himbeerserverde@gmail.com>2023-03-04 16:15:00 +0100
committerHimbeerserverDE <himbeerserverde@gmail.com>2023-03-04 16:15:00 +0100
commit2bf7a76d864804c38c47426b40a00b71f00136d7 (patch)
treefcbd8b5de20e521c3a564fb1d09dac7ffdab05e5
parentfa16ecc5202a8ba9e329e2f25c67106beb517d2f (diff)
support DHCPRELEASE
-rw-r--r--src/lease.rs17
-rw-r--r--src/main.rs26
2 files changed, 43 insertions, 0 deletions
diff --git a/src/lease.rs b/src/lease.rs
index 779ec31..0369a72 100644
--- a/src/lease.rs
+++ b/src/lease.rs
@@ -28,6 +28,7 @@ pub trait LeaseManager {
fn leases(&self) -> Box<dyn Iterator<Item = Lease>>;
fn request(&mut self, address: Ipv4Addr, client_id: &[u8]) -> bool;
fn lease_time(&self) -> Duration;
+ fn release(&mut self, client_id: &[u8]) -> Box<dyn Iterator<Item = Ipv4Addr>>;
fn all_addresses(&self) -> Vec<Ipv4Addr> {
let range = self.range();
@@ -169,4 +170,20 @@ impl LeaseManager for LeaseDummyManager {
fn lease_time(&self) -> Duration {
Duration::from_secs(300)
}
+
+ fn release(&mut self, client_id: &[u8]) -> Box<dyn Iterator<Item = Ipv4Addr>> {
+ let mut released = Vec::new();
+
+ self.leases
+ .clone()
+ .into_iter()
+ .enumerate()
+ .filter(|(_, lease)| lease.client_id == client_id)
+ .for_each(|(i, lease)| {
+ self.leases.remove(i);
+ released.push(lease.address);
+ });
+
+ Box::new(released.into_iter())
+ }
}
diff --git a/src/main.rs b/src/main.rs
index 4d58082..ac2f8ff 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -225,6 +225,32 @@ fn handle_request(
}
}
}
+ MessageType::Release => {
+ let client_id = match opts
+ .get(OptionCode::ClientIdentifier)
+ .ok_or(anyhow!("no client id"))?
+ {
+ DhcpOption::ClientIdentifier(id) => id,
+ _ => bail!("expected ClientIdentifier"),
+ };
+
+ let mut lease_mgr = lease_mgr.lock().unwrap();
+ let released: Vec<String> = lease_mgr
+ .release(client_id)
+ .map(|addr| addr.to_string())
+ .collect();
+
+ let released_pretty = released.join(", ");
+
+ let cid = client_id
+ .iter()
+ .map(|octet| format!("{:x}", octet))
+ .reduce(|acc, octet| acc + &octet)
+ .ok_or(anyhow!("zero-length client id"))?;
+
+ println!("releasing {} for client ID {}", released_pretty, cid);
+ Ok(())
+ }
_ => Err(anyhow!("invalid message type {:?}", msg_type,)),
}
}