diff options
author | HimbeerserverDE <himbeerserverde@gmail.com> | 2023-03-04 23:20:30 +0100 |
---|---|---|
committer | HimbeerserverDE <himbeerserverde@gmail.com> | 2023-03-04 23:20:30 +0100 |
commit | 8ffc7a8d4d152ec29fd604ce89b14f948eaf561c (patch) | |
tree | 6553ec881a6ca83c0a0bd10cf967abd4bdcce2be /src | |
parent | 98071536ddac18eba76e305df823e3e66d2ac6c7 (diff) |
support renewal without explicit address request
Diffstat (limited to 'src')
-rw-r--r-- | src/lease.rs | 43 | ||||
-rw-r--r-- | src/main.rs | 75 |
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(()) } |