Skip to content

Commit 1f35e6f

Browse files
bors[bot]Johannes Draaijerdatdenkikniet
authored
Merge #678
678: DHCPv4: use a Vec to store DNS server addresses instead of an array o… r=Dirbaio a=datdenkikniet …f options This simplifies usage of this field, but does remove the `Copy` derive from that struct. If the `Copy` derive on `Dhcpv4Repr` is not a requirement, I would like to replace it's internal `Option<[Option<Ipv4Address>; 3]>` with an `Option<Vec<Ipv4Address; 3>>` too. Co-authored-by: Johannes Draaijer <johannes.draaijer@mobilaris.se> Co-authored-by: datdenkikniet <jcdra1@gmail.com>
2 parents 42f485a + db87f0f commit 1f35e6f

File tree

4 files changed

+96
-81
lines changed

4 files changed

+96
-81
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ url = "2.0"
3636
std = ["managed/std", "defmt?/alloc"]
3737
alloc = ["managed/alloc", "defmt?/alloc"]
3838
verbose = []
39+
defmt = [ "dep:defmt", "heapless/defmt", "heapless/defmt-impl" ]
3940
"medium-ethernet" = ["socket"]
4041
"medium-ip" = ["socket"]
4142
"medium-ieee802154" = ["socket", "proto-sixlowpan"]

examples/dhcp_client.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,7 @@ fn main() {
7878
}
7979

8080
for (i, s) in config.dns_servers.iter().enumerate() {
81-
if let Some(s) = s {
82-
debug!("DNS server {}: {}", i, s);
83-
}
81+
debug!("DNS server {}: {}", i, s);
8482
}
8583
}
8684
Some(dhcpv4::Event::Deconfigured) => {

src/socket/dhcpv4.rs

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::wire::{
99
UdpRepr, DHCP_CLIENT_PORT, DHCP_MAX_DNS_SERVER_COUNT, DHCP_SERVER_PORT, UDP_HEADER_LEN,
1010
};
1111
use crate::wire::{DhcpOption, HardwareAddress};
12+
use heapless::Vec;
1213

1314
#[cfg(feature = "async")]
1415
use super::WakerRegistration;
@@ -24,7 +25,7 @@ const DEFAULT_PARAMETER_REQUEST_LIST: &[u8] = &[
2425
];
2526

2627
/// IPv4 configuration data provided by the DHCP server.
27-
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
28+
#[derive(Debug, Eq, PartialEq, Clone)]
2829
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2930
pub struct Config<'a> {
3031
/// Information on how to reach the DHCP server that responded with DHCP
@@ -36,7 +37,7 @@ pub struct Config<'a> {
3637
/// match the DHCP server's address.
3738
pub router: Option<Ipv4Address>,
3839
/// DNS servers
39-
pub dns_servers: [Option<Ipv4Address>; DHCP_MAX_DNS_SERVER_COUNT],
40+
pub dns_servers: Vec<Ipv4Address, DHCP_MAX_DNS_SERVER_COUNT>,
4041
/// Received DHCP packet
4142
pub packet: Option<DhcpPacket<&'a [u8]>>,
4243
}
@@ -417,17 +418,19 @@ impl<'a> Socket<'a> {
417418

418419
// Cleanup the DNS servers list, keeping only unicasts/
419420
// TP-Link TD-W8970 sends 0.0.0.0 as second DNS server if there's only one configured :(
420-
let mut dns_servers = [None; DHCP_MAX_DNS_SERVER_COUNT];
421-
if let Some(received) = dhcp_repr.dns_servers {
422-
let mut i = 0;
423-
for addr in received.iter().flatten() {
424-
if addr.is_unicast() {
425-
// This can never be out-of-bounds since both arrays have length DHCP_MAX_DNS_SERVER_COUNT
426-
dns_servers[i] = Some(*addr);
427-
i += 1;
428-
}
429-
}
430-
}
421+
let mut dns_servers = Vec::new();
422+
423+
dhcp_repr
424+
.dns_servers
425+
.iter()
426+
.flatten()
427+
.filter(|s| s.is_unicast())
428+
.for_each(|a| {
429+
// This will never produce an error, as both the arrays and `dns_servers`
430+
// have length DHCP_MAX_DNS_SERVER_COUNT
431+
dns_servers.push(*a).ok();
432+
});
433+
431434
let config = Config {
432435
server,
433436
address: Ipv4Cidr::new(dhcp_repr.your_ip, prefix_len),
@@ -627,7 +630,7 @@ impl<'a> Socket<'a> {
627630
server: state.config.server,
628631
address: state.config.address,
629632
router: state.config.router,
630-
dns_servers: state.config.dns_servers,
633+
dns_servers: state.config.dns_servers.clone(),
631634
packet: self
632635
.receive_packet_buffer
633636
.as_deref()
@@ -775,8 +778,8 @@ mod test {
775778
const DNS_IP_1: Ipv4Address = Ipv4Address([1, 1, 1, 1]);
776779
const DNS_IP_2: Ipv4Address = Ipv4Address([1, 1, 1, 2]);
777780
const DNS_IP_3: Ipv4Address = Ipv4Address([1, 1, 1, 3]);
778-
const DNS_IPS: [Option<Ipv4Address>; DHCP_MAX_DNS_SERVER_COUNT] =
779-
[Some(DNS_IP_1), Some(DNS_IP_2), Some(DNS_IP_3)];
781+
const DNS_IPS: &[Ipv4Address] = &[DNS_IP_1, DNS_IP_2, DNS_IP_3];
782+
780783
const MASK_24: Ipv4Address = Ipv4Address([255, 255, 255, 0]);
781784

782785
const MY_MAC: EthernetAddress = EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]);
@@ -852,19 +855,21 @@ mod test {
852855
..DHCP_DEFAULT
853856
};
854857

855-
const DHCP_OFFER: DhcpRepr = DhcpRepr {
856-
message_type: DhcpMessageType::Offer,
857-
server_ip: SERVER_IP,
858-
server_identifier: Some(SERVER_IP),
858+
fn dhcp_offer() -> DhcpRepr<'static> {
859+
DhcpRepr {
860+
message_type: DhcpMessageType::Offer,
861+
server_ip: SERVER_IP,
862+
server_identifier: Some(SERVER_IP),
859863

860-
your_ip: MY_IP,
861-
router: Some(SERVER_IP),
862-
subnet_mask: Some(MASK_24),
863-
dns_servers: Some(DNS_IPS),
864-
lease_duration: Some(1000),
864+
your_ip: MY_IP,
865+
router: Some(SERVER_IP),
866+
subnet_mask: Some(MASK_24),
867+
dns_servers: Some(Vec::from_slice(DNS_IPS).unwrap()),
868+
lease_duration: Some(1000),
865869

866-
..DHCP_DEFAULT
867-
};
870+
..DHCP_DEFAULT
871+
}
872+
}
868873

869874
const DHCP_REQUEST: DhcpRepr = DhcpRepr {
870875
message_type: DhcpMessageType::Request,
@@ -877,19 +882,21 @@ mod test {
877882
..DHCP_DEFAULT
878883
};
879884

880-
const DHCP_ACK: DhcpRepr = DhcpRepr {
881-
message_type: DhcpMessageType::Ack,
882-
server_ip: SERVER_IP,
883-
server_identifier: Some(SERVER_IP),
885+
fn dhcp_ack() -> DhcpRepr<'static> {
886+
DhcpRepr {
887+
message_type: DhcpMessageType::Ack,
888+
server_ip: SERVER_IP,
889+
server_identifier: Some(SERVER_IP),
884890

885-
your_ip: MY_IP,
886-
router: Some(SERVER_IP),
887-
subnet_mask: Some(MASK_24),
888-
dns_servers: Some(DNS_IPS),
889-
lease_duration: Some(1000),
891+
your_ip: MY_IP,
892+
router: Some(SERVER_IP),
893+
subnet_mask: Some(MASK_24),
894+
dns_servers: Some(Vec::from_slice(DNS_IPS).unwrap()),
895+
lease_duration: Some(1000),
890896

891-
..DHCP_DEFAULT
892-
};
897+
..DHCP_DEFAULT
898+
}
899+
}
893900

894901
const DHCP_NAK: DhcpRepr = DhcpRepr {
895902
message_type: DhcpMessageType::Nak,
@@ -931,7 +938,7 @@ mod test {
931938
identifier: SERVER_IP,
932939
},
933940
address: Ipv4Cidr::new(MY_IP, 24),
934-
dns_servers: DNS_IPS,
941+
dns_servers: Vec::from_slice(DNS_IPS).unwrap(),
935942
router: Some(SERVER_IP),
936943
packet: None,
937944
},
@@ -948,11 +955,11 @@ mod test {
948955

949956
recv!(s, [(IP_BROADCAST, UDP_SEND, DHCP_DISCOVER)]);
950957
assert_eq!(s.poll(), None);
951-
send!(s, (IP_RECV, UDP_RECV, DHCP_OFFER));
958+
send!(s, (IP_RECV, UDP_RECV, dhcp_offer()));
952959
assert_eq!(s.poll(), None);
953960
recv!(s, [(IP_BROADCAST, UDP_SEND, DHCP_REQUEST)]);
954961
assert_eq!(s.poll(), None);
955-
send!(s, (IP_RECV, UDP_RECV, DHCP_ACK));
962+
send!(s, (IP_RECV, UDP_RECV, dhcp_ack()));
956963

957964
assert_eq!(
958965
s.poll(),
@@ -962,7 +969,7 @@ mod test {
962969
identifier: SERVER_IP,
963970
},
964971
address: Ipv4Cidr::new(MY_IP, 24),
965-
dns_servers: DNS_IPS,
972+
dns_servers: Vec::from_slice(DNS_IPS).unwrap(),
966973
router: Some(SERVER_IP),
967974
packet: None,
968975
}))
@@ -988,7 +995,7 @@ mod test {
988995
recv!(s, time 20_000, [(IP_BROADCAST, UDP_SEND, DHCP_DISCOVER)]);
989996

990997
// check after retransmits it still works
991-
send!(s, time 20_000, (IP_RECV, UDP_RECV, DHCP_OFFER));
998+
send!(s, time 20_000, (IP_RECV, UDP_RECV, dhcp_offer()));
992999
recv!(s, time 20_000, [(IP_BROADCAST, UDP_SEND, DHCP_REQUEST)]);
9931000
}
9941001

@@ -997,7 +1004,7 @@ mod test {
9971004
let mut s = socket();
9981005

9991006
recv!(s, time 0, [(IP_BROADCAST, UDP_SEND, DHCP_DISCOVER)]);
1000-
send!(s, time 0, (IP_RECV, UDP_RECV, DHCP_OFFER));
1007+
send!(s, time 0, (IP_RECV, UDP_RECV, dhcp_offer()));
10011008
recv!(s, time 0, [(IP_BROADCAST, UDP_SEND, DHCP_REQUEST)]);
10021009
recv!(s, time 1_000, []);
10031010
recv!(s, time 5_000, [(IP_BROADCAST, UDP_SEND, DHCP_REQUEST)]);
@@ -1007,7 +1014,7 @@ mod test {
10071014
recv!(s, time 20_000, [(IP_BROADCAST, UDP_SEND, DHCP_REQUEST)]);
10081015

10091016
// check after retransmits it still works
1010-
send!(s, time 20_000, (IP_RECV, UDP_RECV, DHCP_ACK));
1017+
send!(s, time 20_000, (IP_RECV, UDP_RECV, dhcp_ack()));
10111018

10121019
match &s.state {
10131020
ClientState::Renewing(r) => {
@@ -1023,7 +1030,7 @@ mod test {
10231030
let mut s = socket();
10241031

10251032
recv!(s, time 0, [(IP_BROADCAST, UDP_SEND, DHCP_DISCOVER)]);
1026-
send!(s, time 0, (IP_RECV, UDP_RECV, DHCP_OFFER));
1033+
send!(s, time 0, (IP_RECV, UDP_RECV, dhcp_offer()));
10271034
recv!(s, time 0, [(IP_BROADCAST, UDP_SEND, DHCP_REQUEST)]);
10281035
recv!(s, time 5_000, [(IP_BROADCAST, UDP_SEND, DHCP_REQUEST)]);
10291036
recv!(s, time 10_000, [(IP_BROADCAST, UDP_SEND, DHCP_REQUEST)]);
@@ -1035,7 +1042,7 @@ mod test {
10351042
recv!(s, time 70_000, [(IP_BROADCAST, UDP_SEND, DHCP_DISCOVER)]);
10361043

10371044
// check it still works
1038-
send!(s, time 60_000, (IP_RECV, UDP_RECV, DHCP_OFFER));
1045+
send!(s, time 60_000, (IP_RECV, UDP_RECV, dhcp_offer()));
10391046
recv!(s, time 60_000, [(IP_BROADCAST, UDP_SEND, DHCP_REQUEST)]);
10401047
}
10411048

@@ -1044,7 +1051,7 @@ mod test {
10441051
let mut s = socket();
10451052

10461053
recv!(s, time 0, [(IP_BROADCAST, UDP_SEND, DHCP_DISCOVER)]);
1047-
send!(s, time 0, (IP_RECV, UDP_RECV, DHCP_OFFER));
1054+
send!(s, time 0, (IP_RECV, UDP_RECV, dhcp_offer()));
10481055
recv!(s, time 0, [(IP_BROADCAST, UDP_SEND, DHCP_REQUEST)]);
10491056
send!(s, time 0, (IP_SERVER_BROADCAST, UDP_RECV, DHCP_NAK));
10501057
recv!(s, time 0, [(IP_BROADCAST, UDP_SEND, DHCP_DISCOVER)]);
@@ -1068,7 +1075,7 @@ mod test {
10681075
_ => panic!("Invalid state"),
10691076
}
10701077

1071-
send!(s, time 500_000, (IP_RECV, UDP_RECV, DHCP_ACK));
1078+
send!(s, time 500_000, (IP_RECV, UDP_RECV, dhcp_ack()));
10721079
assert_eq!(s.poll(), None);
10731080

10741081
match &s.state {
@@ -1093,7 +1100,7 @@ mod test {
10931100
recv!(s, time 875_000, [(IP_SEND, UDP_SEND, DHCP_RENEW)]);
10941101

10951102
// check it still works
1096-
send!(s, time 875_000, (IP_RECV, UDP_RECV, DHCP_ACK));
1103+
send!(s, time 875_000, (IP_RECV, UDP_RECV, dhcp_ack()));
10971104
match &s.state {
10981105
ClientState::Renewing(r) => {
10991106
// NOW the expiration gets bumped

src/wire/dhcpv4.rs

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use bitflags::bitflags;
44
use byteorder::{ByteOrder, NetworkEndian};
55
use core::iter;
6+
use heapless::Vec;
67

78
use super::{Error, Result};
89
use crate::wire::arp::Hardware;
@@ -582,7 +583,7 @@ impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> Packet<&'a mut T> {
582583
/// length) is set to `6`.
583584
///
584585
/// The `options` field has a variable length.
585-
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
586+
#[derive(Debug, PartialEq, Eq, Clone)]
586587
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
587588
pub struct Repr<'a> {
588589
/// This field is also known as `op` in the RFC. It indicates the type of DHCP message this
@@ -645,7 +646,7 @@ pub struct Repr<'a> {
645646
/// the client is interested in.
646647
pub parameter_request_list: Option<&'a [u8]>,
647648
/// DNS servers
648-
pub dns_servers: Option<[Option<Ipv4Address>; MAX_DNS_SERVER_COUNT]>,
649+
pub dns_servers: Option<Vec<Ipv4Address, MAX_DNS_SERVER_COUNT>>,
649650
/// The maximum size dhcp packet the interface can receive
650651
pub max_size: Option<u16>,
651652
/// The DHCP IP lease duration, specified in seconds.
@@ -683,9 +684,9 @@ impl<'a> Repr<'a> {
683684
if self.lease_duration.is_some() {
684685
len += 6;
685686
}
686-
if let Some(dns_servers) = self.dns_servers {
687+
if let Some(dns_servers) = &self.dns_servers {
687688
len += 2;
688-
len += dns_servers.iter().flatten().count() * core::mem::size_of::<u32>();
689+
len += dns_servers.iter().count() * core::mem::size_of::<u32>();
689690
}
690691
if let Some(list) = self.parameter_request_list {
691692
len += list.len() + 2;
@@ -773,13 +774,13 @@ impl<'a> Repr<'a> {
773774
parameter_request_list = Some(data);
774775
}
775776
(field::OPT_DOMAIN_NAME_SERVER, _) => {
776-
let mut servers = [None; MAX_DNS_SERVER_COUNT];
777-
let chunk_size = 4;
778-
for (server, chunk) in servers.iter_mut().zip(data.chunks(chunk_size)) {
779-
if chunk.len() != chunk_size {
780-
return Err(Error);
781-
}
782-
*server = Some(Ipv4Address::from_bytes(chunk));
777+
let mut servers = Vec::new();
778+
const IP_ADDR_BYTE_LEN: usize = 4;
779+
for chunk in data.chunks(IP_ADDR_BYTE_LEN) {
780+
// We ignore push failures because that will only happen
781+
// if we attempt to push more than 4 addresses, and the only
782+
// solution to that is to support more addresses.
783+
servers.push(Ipv4Address::from_bytes(chunk)).ok();
783784
}
784785
dns_servers = Some(servers);
785786
}
@@ -901,13 +902,12 @@ impl<'a> Repr<'a> {
901902
})?;
902903
}
903904

904-
if let Some(dns_servers) = self.dns_servers {
905+
if let Some(dns_servers) = &self.dns_servers {
905906
const IP_SIZE: usize = core::mem::size_of::<u32>();
906907
let mut servers = [0; MAX_DNS_SERVER_COUNT * IP_SIZE];
907908

908909
let data_len = dns_servers
909910
.iter()
910-
.flatten()
911911
.enumerate()
912912
.inspect(|(i, ip)| {
913913
servers[(i * IP_SIZE)..((i + 1) * IP_SIZE)].copy_from_slice(ip.as_bytes());
@@ -1210,11 +1210,14 @@ mod test {
12101210
fn test_emit_offer_dns() {
12111211
let repr = {
12121212
let mut repr = offer_repr();
1213-
repr.dns_servers = Some([
1214-
Some(Ipv4Address([163, 1, 74, 6])),
1215-
Some(Ipv4Address([163, 1, 74, 7])),
1216-
Some(Ipv4Address([163, 1, 74, 3])),
1217-
]);
1213+
repr.dns_servers = Some(
1214+
Vec::from_slice(&[
1215+
Ipv4Address([163, 1, 74, 6]),
1216+
Ipv4Address([163, 1, 74, 7]),
1217+
Ipv4Address([163, 1, 74, 3]),
1218+
])
1219+
.unwrap(),
1220+
);
12181221
repr
12191222
};
12201223
let mut bytes = vec![0xa5; repr.buffer_len()];
@@ -1226,11 +1229,14 @@ mod test {
12261229

12271230
assert_eq!(
12281231
repr_parsed.dns_servers,
1229-
Some([
1230-
Some(Ipv4Address([163, 1, 74, 6])),
1231-
Some(Ipv4Address([163, 1, 74, 7])),
1232-
Some(Ipv4Address([163, 1, 74, 3]))
1233-
])
1232+
Some(
1233+
Vec::from_slice(&[
1234+
Ipv4Address([163, 1, 74, 6]),
1235+
Ipv4Address([163, 1, 74, 7]),
1236+
Ipv4Address([163, 1, 74, 3]),
1237+
])
1238+
.unwrap()
1239+
)
12341240
);
12351241
}
12361242

@@ -1263,11 +1269,14 @@ mod test {
12631269
// length-3 array (see issue #305)
12641270
assert_eq!(
12651271
repr.dns_servers,
1266-
Some([
1267-
Some(Ipv4Address([163, 1, 74, 6])),
1268-
Some(Ipv4Address([163, 1, 74, 7])),
1269-
Some(Ipv4Address([163, 1, 74, 3]))
1270-
])
1272+
Some(
1273+
Vec::from_slice(&[
1274+
Ipv4Address([163, 1, 74, 6]),
1275+
Ipv4Address([163, 1, 74, 7]),
1276+
Ipv4Address([163, 1, 74, 3])
1277+
])
1278+
.unwrap()
1279+
)
12711280
);
12721281
}
12731282

0 commit comments

Comments
 (0)