1use super::config::*;
2use super::leases::*;
3use crate::v4::error::Result;
4use crate::v4::message::*;
5use inherface::get_interfaces;
6use log::{debug, error, warn};
7use std::net::Ipv4Addr;
8
9pub struct Server {
16 pub socket: Socket,
18 pub ip: Ipv4Addr,
22 pub config: Config,
24 pub leases: Leases,
26}
27
28fn get_interface_broadcast(maybe_interface_name: Option<String>) -> Option<Ipv4Addr> {
29 let interface = maybe_interface_name?;
30 let interfaces = get_interfaces().ok()?;
31 let maybe_interface = interfaces.get(&interface);
32 let maybe_addr = maybe_interface?
33 .v4_addr
34 .iter()
35 .find(|address| address.broadcast.is_some());
36
37 debug!(
38 "found ipv4 broadcast address ({:?}) in list of addresses for interface",
39 maybe_addr
40 );
41
42 maybe_addr?.broadcast
43}
44
45impl Server {
46 pub fn new(config: Config) -> Self {
51 let broadcast = get_interface_broadcast(config.interface.clone());
52 let socket = Socket::new(config.listen_address, broadcast);
53 let ip = config.server_address.unwrap_or_else(|| socket.get_ip());
54 let leases = Leases::restore_or_new(&config);
55
56 Self {
57 socket,
58 ip,
59 config,
60 leases,
61 }
62 }
63
64 pub fn listen_once(&mut self) {
68 let (decoded, src) = match self.socket.receive::<Message>() {
69 Ok(values) => values,
70 Err(error) => {
71 error!("{error}");
72 return;
73 }
74 };
75
76 let message_type = match decoded.find_option(53) {
77 Some(MessageOptions::MessageType(message_type)) => message_type,
78 _ => {
79 error!("Request does not have option 53");
80 return;
81 }
82 };
83
84 let response = match message_type {
85 MessageTypes::Discover => 'discover: {
86 debug!("Received Discover message");
87 if self.config.rapid_commit {
88 debug!("Rapid commit enabled on server");
89 match decoded.find_option(80) {
90 Some(MessageOptions::RapidCommit) => {
91 debug!("Discover message has rapid commit option");
92 let mac_address = decoded.get_mac_address();
93
94 let ip = match self.leases.ack(mac_address) {
95 Ok(ip) => ip,
96 Err(error) => {
97 error!("{}", error);
98 return;
99 }
100 };
101 let mut message = self.ack(decoded, ip);
102 message.add_option(MessageOptions::RapidCommit);
103 break 'discover message;
104 }
105 _ => {
106 error!(
107 "Discover message has not sent a (valid) rapid commit option, will send Offer"
108 );
109 }
110 };
111 }
112
113 match self.offer(decoded) {
114 Ok(message) => message,
115 Err(error) => {
116 error!("{}", error);
117 return;
118 }
119 }
120 }
121 MessageTypes::Request => 'request: {
122 debug!("Received Request message");
123 let mac_address = decoded.get_mac_address();
124
125 match decoded.find_option(54) {
128 Some(MessageOptions::ServerIdentifier(address_option)) => {
129 let server_identifier = address_option.inner();
130 if server_identifier != self.ip {
131 debug!("Ignoring client broadcast of DHCP Request for {} which is not this server ({}).", server_identifier, self.ip);
132
133 match self.leases.release(mac_address) {
134 Ok(_) => {
135 debug!("Removed IP address previously offered to this client")
136 }
137 Err(error) => error!("{}", error),
138 }
139
140 return;
141 }
142
143 debug!("client has selected this server for a lease");
144 let ip = match self.leases.ack(mac_address) {
145 Ok(ip) => ip,
146 Err(error) => {
147 error!("{}", error);
148 return;
149 }
150 };
151 self.ack(decoded, ip)
152 }
153 _ => {
154 if decoded.ciaddr.is_unspecified() {
155 debug!("client is attempting to verify lease");
157
158 let ip = match decoded.find_option(50) {
159 Some(MessageOptions::RequestedIp(address_option)) => {
160 address_option.inner()
161 }
162 _ => {
163 break 'request self.nak(decoded, "Request does not have required option 50 (requested ip address)".to_string());
166 }
167 };
168
169 match self.leases.verify_lease(mac_address, &ip) {
170 Ok(_) => self.ack(decoded, ip),
171 Err(error) => {
172 if error == "No IP address lease found with that owner" {
173 debug!("{}. Not sending response", error);
176 return;
177 } else {
178 self.nak(decoded, error.to_string())
180 }
181 }
182 }
183 } else {
184 debug!("client is attempting to renew/rebind lease");
186 match self.leases.extend(mac_address) {
187 Ok(_) => {
188 let ip = decoded.ciaddr;
192 self.ack(decoded, ip)
193 }
194 Err(error) => self.nak(decoded, error.to_string()),
195 }
196 }
197 }
198 }
199 }
200 MessageTypes::Release => {
201 debug!("Received Release message");
202 if let Err(error) = self.leases.release(decoded.get_mac_address()) {
203 error!("{}", error);
204 }
205 return;
206 }
207 MessageTypes::Decline => {
208 debug!("Received Decline message");
209
210 if let Err(error) = self.leases.release(decoded.get_mac_address()) {
214 error!("{}", error);
215 }
216 return;
217 }
218 MessageTypes::Inform => {
219 debug!("Received Inform message");
220 self.ack_inform(decoded)
221 }
222 MessageTypes::LeaseQuery
223 | MessageTypes::BulkLeaseQuery
224 | MessageTypes::ActiveLeaseQuery
225 | MessageTypes::Tls => {
226 warn!("Client sent a message type that is known but not yet handled");
227 return;
228 }
229 _ => {
230 error!("Client sent unknown message type");
231 return;
232 }
233 };
234
235 match self.socket.broadcast(&response, src.port()) {
236 Ok(_) => {}
237 Err(error) => {
238 error!("{error}");
239 }
240 };
241 }
242
243 pub fn listen(&mut self) -> ! {
245 loop {
246 self.listen_once();
247 }
248 }
249
250 fn handle_parameter_requests(&self, request_message: &Message) -> Vec<MessageOptions> {
254 match request_message.find_option(55) {
255 Some(MessageOptions::RequestedOptions(list)) => {
256 list.iter()
258 .filter_map(|parameter_request| {
259 self.config
260 .parameters
261 .get(¶meter_request.to_string())
262 .cloned()
263 })
264 .collect()
265 }
266 _ => vec![],
267 }
268 }
269
270 pub fn offer(&mut self, message: Message) -> Result<Message> {
272 debug!("Sending Offer message");
273
274 let maybe_requested_ip = match message.find_option(50) {
279 Some(MessageOptions::RequestedIp(address_option)) => Some(address_option.inner()),
280 _ => None,
281 };
282 let mac_address = message.get_mac_address();
283 let yiaddr = self.leases.offer(mac_address, maybe_requested_ip)?;
284
285 let mut parameters = self.handle_parameter_requests(&message);
286 parameters.push(MessageOptions::MessageType(MessageTypes::Offer)); parameters.push(MessageOptions::LeaseTime(TimeOption::new(
288 self.config.lease_time.as_client(),
289 ))); parameters.push(MessageOptions::ServerIdentifier(AddressOption::new(
291 self.ip,
292 ))); parameters.push(MessageOptions::End); Ok(Message {
296 op: Ops::Reply,
297 htype: HTypes::Ethernet,
298 hlen: 6,
299 hops: 0,
300 xid: message.xid,
301 secs: 0,
302 flags: message.flags,
303 ciaddr: Ipv4Addr::UNSPECIFIED, yiaddr,
305 siaddr: self.ip,
306 giaddr: message.giaddr,
307 chaddr: message.chaddr,
308 sname: SName::EMPTY,
309 file: File::EMPTY,
310 magic: MAGIC,
311 options: parameters,
312 })
313 }
314
315 pub fn ack(&mut self, message: Message, yiaddr: Ipv4Addr) -> Message {
324 debug!("Sending Ack message");
325
326 let mut parameters = self.handle_parameter_requests(&message);
327 parameters.push(MessageOptions::MessageType(MessageTypes::Ack)); parameters.push(MessageOptions::LeaseTime(TimeOption::new(
329 self.config.lease_time.as_client(),
330 ))); parameters.push(MessageOptions::ServerIdentifier(AddressOption::new(
332 self.ip,
333 ))); parameters.push(MessageOptions::End); Message {
337 op: Ops::Reply,
338 htype: HTypes::Ethernet,
339 hlen: 6,
340 hops: 0,
341 xid: message.xid,
342 secs: 0,
343 flags: message.flags,
344 ciaddr: message.ciaddr,
345 yiaddr,
346 siaddr: self.ip, giaddr: message.giaddr,
348 chaddr: message.chaddr,
349 sname: SName::EMPTY,
350 file: File::EMPTY,
351 magic: MAGIC,
352 options: parameters,
353 }
354 }
355
356 pub fn ack_inform(&self, message: Message) -> Message {
361 debug!("Sending Ack message (in response to an inform)");
362
363 let mut parameters = self.handle_parameter_requests(&message);
364 parameters.push(MessageOptions::MessageType(MessageTypes::Ack)); parameters.push(MessageOptions::ServerIdentifier(AddressOption::new(
366 self.ip,
367 ))); parameters.push(MessageOptions::End); Message {
371 op: Ops::Reply,
372 htype: HTypes::Ethernet,
373 hlen: 6,
374 hops: 0,
375 xid: message.xid,
376 secs: 0,
377 flags: message.flags,
378 ciaddr: message.ciaddr,
379 yiaddr: Ipv4Addr::UNSPECIFIED,
380 siaddr: self.ip, giaddr: message.giaddr,
382 chaddr: message.chaddr,
383 sname: SName::EMPTY,
384 file: File::EMPTY,
385 magic: MAGIC,
386 options: parameters,
387 }
388 }
389
390 pub fn nak(&self, message: Message, error: String) -> Message {
392 debug!("Sending Nak message");
393
394 let mut response = Message {
395 op: Ops::Reply,
396 htype: HTypes::Ethernet,
397 hlen: 6,
398 hops: 0,
399 xid: message.xid,
400 secs: 0,
401 flags: message.flags,
402 ciaddr: Ipv4Addr::UNSPECIFIED,
403 yiaddr: Ipv4Addr::UNSPECIFIED,
404 siaddr: Ipv4Addr::UNSPECIFIED,
405 giaddr: message.giaddr,
406 chaddr: message.chaddr,
407 sname: SName::EMPTY, file: File::EMPTY, magic: MAGIC,
410 options: vec![
411 MessageOptions::MessageType(MessageTypes::Nak), MessageOptions::ServerIdentifier(AddressOption::new(self.ip)), MessageOptions::End, ],
415 };
416
417 match StringOption::new(error) {
418 Ok(converted) => {
419 response.add_option(MessageOptions::Message(converted)); }
421 Err(_) => {
422 error!("Sending Nak without error message option because option's value is empty");
423 }
424 };
425
426 response
427 }
428}