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!(
132 "Ignoring client broadcast of DHCP Request for {} which is not this server ({}).",
133 server_identifier, self.ip
134 );
135
136 match self.leases.release(mac_address) {
137 Ok(_) => {
138 debug!("Removed IP address previously offered to this client")
139 }
140 Err(error) => error!("{}", error),
141 }
142
143 return;
144 }
145
146 debug!("client has selected this server for a lease");
147 let ip = match self.leases.ack(mac_address) {
148 Ok(ip) => ip,
149 Err(error) => {
150 error!("{}", error);
151 return;
152 }
153 };
154 self.ack(decoded, ip)
155 }
156 _ => {
157 if decoded.ciaddr.is_unspecified() {
158 debug!("client is attempting to verify lease");
160
161 let ip = match decoded.find_option(50) {
162 Some(MessageOptions::RequestedIp(address_option)) => {
163 address_option.inner()
164 }
165 _ => {
166 break 'request self.nak(decoded, "Request does not have required option 50 (requested ip address)".to_string());
169 }
170 };
171
172 match self.leases.verify_lease(mac_address, &ip) {
173 Ok(_) => self.ack(decoded, ip),
174 Err(error) => {
175 if error == "No IP address lease found with that owner" {
176 debug!("{}. Not sending response", error);
179 return;
180 } else {
181 self.nak(decoded, error.to_string())
183 }
184 }
185 }
186 } else {
187 debug!("client is attempting to renew/rebind lease");
189 match self.leases.extend(mac_address) {
190 Ok(_) => {
191 let ip = decoded.ciaddr;
195 self.ack(decoded, ip)
196 }
197 Err(error) => self.nak(decoded, error.to_string()),
198 }
199 }
200 }
201 }
202 }
203 MessageTypes::Release => {
204 debug!("Received Release message");
205 if let Err(error) = self.leases.release(decoded.get_mac_address()) {
206 error!("{}", error);
207 }
208 return;
209 }
210 MessageTypes::Decline => {
211 debug!("Received Decline message");
212
213 if let Err(error) = self.leases.release(decoded.get_mac_address()) {
217 error!("{}", error);
218 }
219 return;
220 }
221 MessageTypes::Inform => {
222 debug!("Received Inform message");
223 self.ack_inform(decoded)
224 }
225 MessageTypes::LeaseQuery
226 | MessageTypes::BulkLeaseQuery
227 | MessageTypes::ActiveLeaseQuery
228 | MessageTypes::Tls => {
229 warn!("Client sent a message type that is known but not yet handled");
230 return;
231 }
232 _ => {
233 error!("Client sent unknown message type");
234 return;
235 }
236 };
237
238 match self.socket.broadcast(&response, src.port()) {
239 Ok(_) => {}
240 Err(error) => {
241 error!("{error}");
242 }
243 };
244 }
245
246 pub fn listen(&mut self) -> ! {
248 loop {
249 self.listen_once();
250 }
251 }
252
253 fn handle_parameter_requests(&self, request_message: &Message) -> Vec<MessageOptions> {
257 match request_message.find_option(55) {
258 Some(MessageOptions::RequestedOptions(list)) => {
259 list.iter()
261 .filter_map(|parameter_request| {
262 self.config
263 .parameters
264 .get(¶meter_request.to_string())
265 .cloned()
266 })
267 .collect()
268 }
269 _ => vec![],
270 }
271 }
272
273 pub fn offer(&mut self, message: Message) -> Result<Message> {
275 debug!("Sending Offer message");
276
277 let maybe_requested_ip = match message.find_option(50) {
282 Some(MessageOptions::RequestedIp(address_option)) => Some(address_option.inner()),
283 _ => None,
284 };
285 let mac_address = message.get_mac_address();
286 let yiaddr = self.leases.offer(mac_address, maybe_requested_ip)?;
287
288 let mut parameters = self.handle_parameter_requests(&message);
289 parameters.push(MessageOptions::MessageType(MessageTypes::Offer)); parameters.push(MessageOptions::LeaseTime(TimeOption::new(
291 self.config.lease_time.as_client(),
292 ))); parameters.push(MessageOptions::ServerIdentifier(AddressOption::new(
294 self.ip,
295 ))); Ok(Message {
298 op: Ops::Reply,
299 htype: HTypes::Ethernet,
300 hlen: 6,
301 hops: 0,
302 xid: message.xid,
303 secs: 0,
304 flags: message.flags,
305 ciaddr: Ipv4Addr::UNSPECIFIED, yiaddr,
307 siaddr: self.ip,
308 giaddr: message.giaddr,
309 chaddr: message.chaddr,
310 sname: SName::EMPTY,
311 file: File::EMPTY,
312 magic: MAGIC,
313 options: parameters,
314 })
315 }
316
317 pub fn ack(&mut self, message: Message, yiaddr: Ipv4Addr) -> Message {
326 debug!("Sending Ack message");
327
328 let mut parameters = self.handle_parameter_requests(&message);
329 parameters.push(MessageOptions::MessageType(MessageTypes::Ack)); parameters.push(MessageOptions::LeaseTime(TimeOption::new(
331 self.config.lease_time.as_client(),
332 ))); parameters.push(MessageOptions::ServerIdentifier(AddressOption::new(
334 self.ip,
335 ))); Message {
338 op: Ops::Reply,
339 htype: HTypes::Ethernet,
340 hlen: 6,
341 hops: 0,
342 xid: message.xid,
343 secs: 0,
344 flags: message.flags,
345 ciaddr: message.ciaddr,
346 yiaddr,
347 siaddr: self.ip, giaddr: message.giaddr,
349 chaddr: message.chaddr,
350 sname: SName::EMPTY,
351 file: File::EMPTY,
352 magic: MAGIC,
353 options: parameters,
354 }
355 }
356
357 pub fn ack_inform(&self, message: Message) -> Message {
362 debug!("Sending Ack message (in response to an inform)");
363
364 let mut parameters = self.handle_parameter_requests(&message);
365 parameters.push(MessageOptions::MessageType(MessageTypes::Ack)); parameters.push(MessageOptions::ServerIdentifier(AddressOption::new(
367 self.ip,
368 ))); 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)), ],
414 };
415
416 match StringOption::new(error) {
417 Ok(converted) => {
418 response.add_option(MessageOptions::Message(converted)); }
420 Err(_) => {
421 error!("Sending Nak without error message option because option's value is empty");
422 }
423 };
424
425 response
426 }
427}