aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHimbeerserverDE <himbeerserverde@gmail.com>2023-03-04 23:20:30 +0100
committerHimbeerserverDE <himbeerserverde@gmail.com>2023-03-04 23:20:30 +0100
commit8ffc7a8d4d152ec29fd604ce89b14f948eaf561c (patch)
tree6553ec881a6ca83c0a0bd10cf967abd4bdcce2be /src
parent98071536ddac18eba76e305df823e3e66d2ac6c7 (diff)
support renewal without explicit address request
Diffstat (limited to 'src')
-rw-r--r--src/lease.rs43
-rw-r--r--src/main.rs75
2 files changed, 92 insertions, 26 deletions
diff --git a/src/lease.rs b/src/lease.rs
index 2c5c152..969b3f0 100644
--- a/src/lease.rs
+++ b/src/lease.rs
@@ -29,6 +29,11 @@ impl Lease {
pub fn expired(&self) -> bool {
SystemTime::now().duration_since(self.expires).is_ok()
}
+
+ pub fn renew(&mut self, lease_time: Duration) {
+ self.expires = SystemTime::now() + lease_time;
+ self.lease_time = lease_time;
+ }
}
pub trait LeaseManager {
@@ -37,6 +42,7 @@ pub trait LeaseManager {
fn lease_time(&self) -> Duration;
fn leases(&self) -> Box<dyn Iterator<Item = Lease>>;
fn request(&mut self, address: Ipv4Addr, client_id: &[u8]) -> Result<bool>;
+ fn renew(&mut self, client_id: &[u8]) -> Result<Option<Ipv4Addr>>;
fn release(&mut self, client_id: &[u8]) -> Result<Box<dyn Iterator<Item = Ipv4Addr>>>;
fn all_addresses(&self) -> Vec<Ipv4Addr> {
@@ -184,6 +190,21 @@ impl LeaseManager for LeaseDummyManager {
}
}
+ fn renew(&mut self, client_id: &[u8]) -> Result<Option<Ipv4Addr>> {
+ let lease_time = self.lease_time();
+ let mut address = None;
+
+ self.leases
+ .iter_mut()
+ .filter(|lease| lease.client_id == client_id)
+ .for_each(|lease| {
+ address = Some(lease.address);
+ lease.renew(lease_time);
+ });
+
+ Ok(address)
+ }
+
fn release(&mut self, client_id: &[u8]) -> Result<Box<dyn Iterator<Item = Ipv4Addr>>> {
let mut released = Vec::new();
@@ -278,10 +299,10 @@ impl LeaseManager for LeaseFileManager {
}
fn request(&mut self, address: Ipv4Addr, client_id: &[u8]) -> Result<bool> {
- let range = self.range();
-
self.garbage_collect()?;
+ let range = self.range();
+
if self.is_unavailable(address, client_id)
|| !Ipv4AddrRange::new(range.0, range.1).any(|addr| addr == address)
{
@@ -305,6 +326,24 @@ impl LeaseManager for LeaseFileManager {
}
}
+ fn renew(&mut self, client_id: &[u8]) -> Result<Option<Ipv4Addr>> {
+ self.garbage_collect()?;
+
+ let lease_time = self.lease_time();
+ let mut address = None;
+
+ self.leases
+ .iter_mut()
+ .filter(|lease| lease.client_id == client_id)
+ .for_each(|lease| {
+ address = Some(lease.address);
+ lease.renew(lease_time);
+ });
+
+ self.save()?;
+ Ok(address)
+ }
+
fn release(&mut self, client_id: &[u8]) -> Result<Box<dyn Iterator<Item = Ipv4Addr>>> {
self.garbage_collect()?;
diff --git a/src/main.rs b/src/main.rs
index 9b16ce6..9f5e669 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -182,15 +182,23 @@ fn handle_request<T: LeaseManager>(
_ => unreachable!(),
};
- let requested_addr = match opts
- .get(OptionCode::RequestedIpAddress)
- .ok_or(Error::NoAddrRequested)?
- {
- DhcpOption::RequestedIpAddress(addr) => addr,
- _ => unreachable!(),
- };
-
- if !lease_mgr.request(*requested_addr, client_id)? {
+ let mut renew = false;
+ let requested_addr =
+ match opts.get(OptionCode::RequestedIpAddress).map(|v| match v {
+ DhcpOption::RequestedIpAddress(addr) => addr,
+ _ => unreachable!(),
+ }) {
+ Some(addr) => *addr,
+ None => match lease_mgr.renew(client_id)? {
+ Some(addr) => {
+ renew = true;
+ addr
+ }
+ None => return Err(Error::NoAddrRequested),
+ },
+ };
+
+ if !lease_mgr.request(requested_addr, client_id)? {
let own_addr = local_ip(link)?;
let mut resp = Message::default();
@@ -198,7 +206,7 @@ fn handle_request<T: LeaseManager>(
.set_flags(Flags::default().set_broadcast())
.set_opcode(Opcode::BootReply)
.set_xid(xid)
- .set_yiaddr(*requested_addr)
+ .set_yiaddr(requested_addr)
.set_siaddr(own_addr)
.set_chaddr(msg.chaddr())
.opts_mut();
@@ -213,12 +221,21 @@ fn handle_request<T: LeaseManager>(
if n != resp_buf.len() {
Err(Error::PartialResponse)
} else {
- println!(
- "not ackknowledging {} for client ID {} on {}",
- requested_addr,
- format_client_id(client_id)?,
- link
- );
+ if renew {
+ println!(
+ "not renewing {} for client ID {} on {}",
+ requested_addr,
+ format_client_id(client_id)?,
+ link
+ );
+ } else {
+ println!(
+ "not ackknowledging {} for client ID {} on {}",
+ requested_addr,
+ format_client_id(client_id)?,
+ link
+ );
+ }
Ok(())
}
@@ -231,7 +248,7 @@ fn handle_request<T: LeaseManager>(
.set_flags(Flags::default().set_broadcast())
.set_opcode(Opcode::BootReply)
.set_xid(xid)
- .set_yiaddr(*requested_addr)
+ .set_yiaddr(requested_addr)
.set_siaddr(own_addr)
.set_chaddr(msg.chaddr())
.opts_mut();
@@ -250,13 +267,23 @@ fn handle_request<T: LeaseManager>(
if n != resp_buf.len() {
Err(Error::PartialResponse)
} else {
- println!(
- "ackknowledging {} for client ID {} for {:?} on {}",
- requested_addr,
- format_client_id(client_id)?,
- lease_time,
- link
- );
+ if renew {
+ println!(
+ "renewing {} for client ID {} for {:?} on {}",
+ requested_addr,
+ format_client_id(client_id)?,
+ lease_time,
+ link
+ );
+ } else {
+ println!(
+ "ackknowledging {} for client ID {} for {:?} on {}",
+ requested_addr,
+ format_client_id(client_id)?,
+ lease_time,
+ link
+ );
+ }
Ok(())
}