Skip to content

Commit 3c3cc26

Browse files
committed
DHCP: return address: 0.0.0.0/0 when resetting to discovery state
1 parent 7201fb8 commit 3c3cc26

File tree

1 file changed

+34
-10
lines changed

1 file changed

+34
-10
lines changed

src/dhcp/clientv4.rs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ pub struct Client {
6464
///
6565
/// To provide memory for the dynamic IP address, configure your
6666
/// `Interface` with one of `ip_addrs` and the `ipv4_gateway` being
67-
/// `Ipv4Address::UNSPECIFIED`.
67+
/// `Ipv4Address::UNSPECIFIED`. You must also assign this `0.0.0.0/0`
68+
/// while the client's state is `Discovering`. Hence, the `poll()`
69+
/// method returns a corresponding `Config` struct in this case.
6870
///
6971
/// You must call `dhcp_client.poll()` after `iface.poll()` to send
7072
/// and receive DHCP packets.
@@ -135,12 +137,18 @@ impl Client {
135137
None
136138
};
137139

138-
// Send requests
139-
if udp_socket.can_send() && now >= self.next_egress {
140-
self.egress(iface, &mut *udp_socket, now)?;
140+
if config.is_some() {
141+
// Return a new config immediately so that addresses can
142+
// be configured that are required by egress().
143+
Ok(config)
144+
} else {
145+
// Send requests
146+
if udp_socket.can_send() && now >= self.next_egress {
147+
self.egress(iface, &mut *udp_socket, now)
148+
} else {
149+
Ok(None)
150+
}
141151
}
142-
143-
Ok(config)
144152
}
145153

146154
fn ingress<DeviceT: for<'d> Device<'d>>
@@ -227,7 +235,7 @@ impl Client {
227235
config
228236
}
229237

230-
fn egress<DeviceT: for<'d> Device<'d>>(&mut self, iface: &mut Interface<DeviceT>, udp_socket: &mut UdpSocket, now: Instant) -> Result<()> {
238+
fn egress<DeviceT: for<'d> Device<'d>>(&mut self, iface: &mut Interface<DeviceT>, udp_socket: &mut UdpSocket, now: Instant) -> Result<Option<Config>> {
231239
// Reset after maximum amount of retries
232240
let retries_exceeded = match self.state {
233241
ClientState::Requesting(ref mut r_state) if r_state.retry >= REQUEST_RETRIES => {
@@ -242,6 +250,14 @@ impl Client {
242250
};
243251
if retries_exceeded {
244252
self.reset(now);
253+
// Return a config now so that user code assigns the
254+
// 0.0.0.0/0 address, which will be used sending a DHCP
255+
// discovery packet in the next call to egress().
256+
return Ok(Some(Config {
257+
address: Some(Ipv4Cidr::new(Ipv4Address::UNSPECIFIED, 0)),
258+
router: None,
259+
dns_servers: [None; 3],
260+
}));
245261
}
246262

247263
// Prepare sending next packet
@@ -265,6 +281,11 @@ impl Client {
265281
parameter_request_list: None,
266282
dns_servers: None,
267283
};
284+
let mut send_packet = |endpoint, dhcp_repr| {
285+
send_packet(udp_socket, &endpoint, dhcp_repr)
286+
.map(|()| None)
287+
};
288+
268289

269290
match self.state {
270291
ClientState::Discovering => {
@@ -275,7 +296,7 @@ impl Client {
275296
port: UDP_SERVER_PORT,
276297
};
277298
net_trace!("DHCP send discover to {}: {:?}", endpoint, dhcp_repr);
278-
send_packet(udp_socket, &endpoint, &dhcp_repr)
299+
send_packet(endpoint, &dhcp_repr)
279300
}
280301
ClientState::Requesting(ref mut r_state) => {
281302
r_state.retry += 1;
@@ -296,7 +317,7 @@ impl Client {
296317
dhcp_repr.server_identifier = Some(r_state.server_identifier);
297318
dhcp_repr.parameter_request_list = Some(PARAMETER_REQUEST_LIST);
298319
net_trace!("DHCP send request to {} = {:?}", endpoint, dhcp_repr);
299-
send_packet(udp_socket, &endpoint, &dhcp_repr)
320+
send_packet(endpoint, &dhcp_repr)
300321
}
301322
ClientState::Renew(ref mut p_state) => {
302323
p_state.retry += 1;
@@ -310,7 +331,7 @@ impl Client {
310331
dhcp_repr.message_type = DhcpMessageType::Request;
311332
dhcp_repr.client_ip = client_ip;
312333
net_trace!("DHCP send renew to {}: {:?}", endpoint, dhcp_repr);
313-
send_packet(udp_socket, &endpoint, &dhcp_repr)
334+
send_packet(endpoint, &dhcp_repr)
314335
}
315336
}
316337
}
@@ -319,6 +340,9 @@ impl Client {
319340
///
320341
/// Use this to speed up acquisition of an address in a new
321342
/// network if a link was down and it is now back up.
343+
///
344+
/// You *must* configure a `0.0.0.0` address on your interface
345+
/// before the next call to `poll()`!
322346
pub fn reset(&mut self, now: Instant) {
323347
net_trace!("DHCP reset");
324348
self.state = ClientState::Discovering;

0 commit comments

Comments
 (0)