Skip to content

Commit 93d175f

Browse files
bors[bot]KOLANICH
andauthored
Merge #675
675: Made IPv4 and IPv6 modules a bit DRYer by moving sizes into constants and exposed IPv4-mapping prefix. r=Dirbaio a=KOLANICH Co-authored-by: KOLANICH <kolan_n@mail.ru>
2 parents 7091565 + f7bbb57 commit 93d175f

File tree

2 files changed

+49
-25
lines changed

2 files changed

+49
-25
lines changed

src/wire/ipv4.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ pub use super::IpProtocol as Protocol;
2121
// accept a packet of the following size.
2222
pub const MIN_MTU: usize = 576;
2323

24+
/// Size of IPv4 adderess in octets.
25+
///
26+
/// [RFC 8200 § 2]: https://www.rfc-editor.org/rfc/rfc791#section-3.2
27+
pub const ADDR_SIZE: usize = 4;
28+
2429
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
2530
pub struct Key {
2631
id: u16,
@@ -31,14 +36,14 @@ pub struct Key {
3136

3237
/// A four-octet IPv4 address.
3338
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
34-
pub struct Address(pub [u8; 4]);
39+
pub struct Address(pub [u8; ADDR_SIZE]);
3540

3641
impl Address {
3742
/// An unspecified address.
38-
pub const UNSPECIFIED: Address = Address([0x00; 4]);
43+
pub const UNSPECIFIED: Address = Address([0x00; ADDR_SIZE]);
3944

4045
/// The broadcast address.
41-
pub const BROADCAST: Address = Address([0xff; 4]);
46+
pub const BROADCAST: Address = Address([0xff; ADDR_SIZE]);
4247

4348
/// All multicast-capable nodes
4449
pub const MULTICAST_ALL_SYSTEMS: Address = Address([224, 0, 0, 1]);
@@ -56,7 +61,7 @@ impl Address {
5661
/// # Panics
5762
/// The function panics if `data` is not four octets long.
5863
pub fn from_bytes(data: &[u8]) -> Address {
59-
let mut bytes = [0; 4];
64+
let mut bytes = [0; ADDR_SIZE];
6065
bytes.copy_from_slice(data);
6166
Address(bytes)
6267
}
@@ -73,7 +78,7 @@ impl Address {
7378

7479
/// Query whether the address is the broadcast address.
7580
pub fn is_broadcast(&self) -> bool {
76-
self.0[0..4] == [255; 4]
81+
self.0[0..4] == [255; ADDR_SIZE]
7782
}
7883

7984
/// Query whether the address is a multicast address.
@@ -873,7 +878,7 @@ mod test {
873878
0x14, 0x21, 0x22, 0x23, 0x24, 0xaa, 0x00, 0x00, 0xff,
874879
];
875880

876-
static REPR_PAYLOAD_BYTES: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
881+
static REPR_PAYLOAD_BYTES: [u8; ADDR_SIZE] = [0xaa, 0x00, 0x00, 0xff];
877882

878883
fn packet_repr() -> Repr {
879884
Repr {

src/wire/ipv6.rs

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,26 @@ pub use super::IpProtocol as Protocol;
1515
/// [RFC 8200 § 5]: https://tools.ietf.org/html/rfc8200#section-5
1616
pub const MIN_MTU: usize = 1280;
1717

18+
/// Size of IPv6 adderess in octets.
19+
///
20+
/// [RFC 8200 § 2]: https://www.rfc-editor.org/rfc/rfc4291#section-2
21+
pub const ADDR_SIZE: usize = 16;
22+
23+
/// Size of IPv4-mapping prefix in octets.
24+
///
25+
/// [RFC 8200 § 2]: https://www.rfc-editor.org/rfc/rfc4291#section-2
26+
pub const IPV4_MAPPED_PREFIX_SIZE: usize = ADDR_SIZE - 4; // 4 == ipv4::ADDR_SIZE , cannot DRY here because of dependency on a IPv4 module which is behind the feature
27+
1828
/// A sixteen-octet IPv6 address.
1929
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
2030
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21-
pub struct Address(pub [u8; 16]);
31+
pub struct Address(pub [u8; ADDR_SIZE]);
2232

2333
impl Address {
2434
/// The [unspecified address].
2535
///
2636
/// [unspecified address]: https://tools.ietf.org/html/rfc4291#section-2.5.2
27-
pub const UNSPECIFIED: Address = Address([0x00; 16]);
37+
pub const UNSPECIFIED: Address = Address([0x00; ADDR_SIZE]);
2838

2939
/// The link-local [all nodes multicast address].
3040
///
@@ -50,18 +60,24 @@ impl Address {
5060
0x01,
5161
]);
5262

63+
/// The prefix used in [IPv4-mapped addresses].
64+
///
65+
/// [IPv4-mapped addresses]: https://www.rfc-editor.org/rfc/rfc4291#section-2.5.5.2
66+
pub const IPV4_MAPPED_PREFIX: [u8; IPV4_MAPPED_PREFIX_SIZE] =
67+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff];
68+
5369
/// Construct an IPv6 address from parts.
5470
#[allow(clippy::too_many_arguments)]
5571
pub fn new(a0: u16, a1: u16, a2: u16, a3: u16, a4: u16, a5: u16, a6: u16, a7: u16) -> Address {
56-
let mut addr = [0u8; 16];
57-
NetworkEndian::write_u16(&mut addr[0..2], a0);
72+
let mut addr = [0u8; ADDR_SIZE];
73+
NetworkEndian::write_u16(&mut addr[..2], a0);
5874
NetworkEndian::write_u16(&mut addr[2..4], a1);
5975
NetworkEndian::write_u16(&mut addr[4..6], a2);
6076
NetworkEndian::write_u16(&mut addr[6..8], a3);
6177
NetworkEndian::write_u16(&mut addr[8..10], a4);
6278
NetworkEndian::write_u16(&mut addr[10..12], a5);
6379
NetworkEndian::write_u16(&mut addr[12..14], a6);
64-
NetworkEndian::write_u16(&mut addr[14..16], a7);
80+
NetworkEndian::write_u16(&mut addr[14..], a7);
6581
Address(addr)
6682
}
6783

@@ -70,7 +86,7 @@ impl Address {
7086
/// # Panics
7187
/// The function panics if `data` is not sixteen octets long.
7288
pub fn from_bytes(data: &[u8]) -> Address {
73-
let mut bytes = [0; 16];
89+
let mut bytes = [0; ADDR_SIZE];
7490
bytes.copy_from_slice(data);
7591
Address(bytes)
7692
}
@@ -81,7 +97,7 @@ impl Address {
8197
/// The function panics if `data` is not 8 words long.
8298
pub fn from_parts(data: &[u16]) -> Address {
8399
assert!(data.len() >= 8);
84-
let mut bytes = [0; 16];
100+
let mut bytes = [0; ADDR_SIZE];
85101
for (word_idx, chunk) in bytes.chunks_mut(2).enumerate() {
86102
NetworkEndian::write_u16(chunk, data[word_idx]);
87103
}
@@ -122,7 +138,7 @@ impl Address {
122138
///
123139
/// [unspecified address]: https://tools.ietf.org/html/rfc4291#section-2.5.2
124140
pub fn is_unspecified(&self) -> bool {
125-
self.0 == [0x00; 16]
141+
self.0 == [0x00; ADDR_SIZE]
126142
}
127143

128144
/// Query whether the IPv6 address is in the [link-local] scope.
@@ -143,15 +159,15 @@ impl Address {
143159
///
144160
/// [IPv4 mapped IPv6 address]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
145161
pub fn is_ipv4_mapped(&self) -> bool {
146-
self.0[0..12] == [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff]
162+
self.0[..IPV4_MAPPED_PREFIX_SIZE] == Self::IPV4_MAPPED_PREFIX
147163
}
148164

149165
#[cfg(feature = "proto-ipv4")]
150166
/// Convert an IPv4 mapped IPv6 address to an IPv4 address.
151167
pub fn as_ipv4(&self) -> Option<ipv4::Address> {
152168
if self.is_ipv4_mapped() {
153-
Some(ipv4::Address::new(
154-
self.0[12], self.0[13], self.0[14], self.0[15],
169+
Some(ipv4::Address::from_bytes(
170+
&self.0[IPV4_MAPPED_PREFIX_SIZE..],
155171
))
156172
} else {
157173
None
@@ -162,14 +178,14 @@ impl Address {
162178
///
163179
/// # Panics
164180
/// This function panics if `mask` is greater than 128.
165-
pub(super) fn mask(&self, mask: u8) -> [u8; 16] {
181+
pub(super) fn mask(&self, mask: u8) -> [u8; ADDR_SIZE] {
166182
assert!(mask <= 128);
167-
let mut bytes = [0u8; 16];
183+
let mut bytes = [0u8; ADDR_SIZE];
168184
let idx = (mask as usize) / 8;
169185
let modulus = (mask as usize) % 8;
170186
let (first, second) = self.0.split_at(idx);
171187
bytes[0..idx].copy_from_slice(first);
172-
if idx < 16 {
188+
if idx < ADDR_SIZE {
173189
let part = second[0];
174190
bytes[idx] = part & (!(0xff >> modulus) as u8);
175191
}
@@ -217,7 +233,10 @@ impl fmt::Display for Address {
217233
return write!(
218234
f,
219235
"::ffff:{}.{}.{}.{}",
220-
self.0[12], self.0[13], self.0[14], self.0[15]
236+
self.0[IPV4_MAPPED_PREFIX_SIZE + 0],
237+
self.0[IPV4_MAPPED_PREFIX_SIZE + 1],
238+
self.0[IPV4_MAPPED_PREFIX_SIZE + 2],
239+
self.0[IPV4_MAPPED_PREFIX_SIZE + 3]
221240
);
222241
}
223242

@@ -273,10 +292,10 @@ impl fmt::Display for Address {
273292
/// Convert the given IPv4 address into a IPv4-mapped IPv6 address
274293
impl From<ipv4::Address> for Address {
275294
fn from(address: ipv4::Address) -> Self {
276-
let octets = address.0;
277-
Address([
278-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, octets[0], octets[1], octets[2], octets[3],
279-
])
295+
let mut b = [0_u8; ADDR_SIZE];
296+
b[..Self::IPV4_MAPPED_PREFIX.len()].copy_from_slice(&Self::IPV4_MAPPED_PREFIX);
297+
b[Self::IPV4_MAPPED_PREFIX.len()..].copy_from_slice(&address.0);
298+
Self(b)
280299
}
281300
}
282301

0 commit comments

Comments
 (0)