Skip to content

Commit 8abb588

Browse files
committed
Remove ieee802154 from IphcRepr
1 parent 74bd1e5 commit 8abb588

File tree

7 files changed

+765
-269
lines changed

7 files changed

+765
-269
lines changed

fuzz/fuzz_targets/sixlowpan_packet.rs

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,10 @@ fuzz_target!(|fuzz: SixlowpanPacketFuzzer| {
3939
}
4040
Ok(SixlowpanPacket::IphcHeader) => {
4141
if let Ok(frame) = SixlowpanIphcPacket::new_checked(fuzz.data) {
42-
if let Ok(iphc_repr) = SixlowpanIphcRepr::parse(
43-
&frame,
44-
fuzz.ll_src_addr.map(Into::into),
45-
fuzz.ll_dst_addr.map(Into::into),
46-
&[],
47-
) {
42+
if let Ok(iphc_repr) = SixlowpanIphcRepr::parse(&frame) {
43+
let src_addr = iphc_repr.src_addr.resolve(fuzz.ll_src_addr.map(Into::into), &[], iphc_repr.context_identifier).unwrap();
44+
let dst_addr = iphc_repr.dst_addr.resolve(fuzz.ll_dst_addr.map(Into::into), &[], iphc_repr.context_identifier).unwrap();
45+
4846
let mut buffer = vec![0; iphc_repr.buffer_len()];
4947
let mut iphc_frame = SixlowpanIphcPacket::new_unchecked(&mut buffer[..]);
5048
iphc_repr.emit(&mut iphc_frame);
@@ -75,8 +73,8 @@ fuzz_target!(|fuzz: SixlowpanPacketFuzzer| {
7573
{
7674
if let Ok(repr) = SixlowpanUdpNhcRepr::parse(
7775
&frame,
78-
&iphc_repr.src_addr,
79-
&iphc_repr.dst_addr,
76+
&src_addr,
77+
&dst_addr,
8078
&Default::default(),
8179
) {
8280
let mut buffer = vec![
@@ -90,8 +88,8 @@ fuzz_target!(|fuzz: SixlowpanPacketFuzzer| {
9088
);
9189
repr.emit(
9290
&mut udp_packet,
93-
&iphc_repr.src_addr,
94-
&iphc_repr.dst_addr,
91+
&src_addr,
92+
&dst_addr,
9593
frame.payload().len(),
9694
|b| b.copy_from_slice(frame.payload()),
9795
&ChecksumCapabilities::ignored(),
@@ -141,16 +139,16 @@ fuzz_target!(|fuzz: SixlowpanPacketFuzzer| {
141139
if let Ok(frame) = TcpPacket::new_checked(payload) {
142140
if let Ok(repr) = TcpRepr::parse(
143141
&frame,
144-
&iphc_repr.src_addr.into_address(),
145-
&iphc_repr.dst_addr.into_address(),
142+
&src_addr.into_address(),
143+
&dst_addr.into_address(),
146144
&ChecksumCapabilities::default(),
147145
) {
148146
let mut buffer = vec![0; repr.buffer_len()];
149147
let mut frame = TcpPacket::new_unchecked(&mut buffer[..]);
150148
repr.emit(
151149
&mut frame,
152-
&iphc_repr.src_addr.into_address(),
153-
&iphc_repr.dst_addr.into_address(),
150+
&src_addr.into_address(),
151+
&dst_addr.into_address(),
154152
&ChecksumCapabilities::default(),
155153
);
156154
}
@@ -160,17 +158,17 @@ fuzz_target!(|fuzz: SixlowpanPacketFuzzer| {
160158
if let Ok(frame) = UdpPacket::new_checked(payload) {
161159
if let Ok(repr) = UdpRepr::parse(
162160
&frame,
163-
&iphc_repr.src_addr.into_address(),
164-
&iphc_repr.dst_addr.into_address(),
161+
&src_addr.into_address(),
162+
&dst_addr.into_address(),
165163
&ChecksumCapabilities::default(),
166164
) {
167165
let mut buffer =
168166
vec![0; repr.header_len() + frame.payload().len()];
169167
let mut packet = UdpPacket::new_unchecked(&mut buffer[..]);
170168
repr.emit(
171169
&mut packet,
172-
&iphc_repr.src_addr.into_address(),
173-
&iphc_repr.dst_addr.into_address(),
170+
&src_addr.into_address(),
171+
&dst_addr.into_address(),
174172
frame.payload().len(),
175173
|b| b.copy_from_slice(frame.payload()),
176174
&ChecksumCapabilities::default(),
@@ -200,17 +198,17 @@ fuzz_target!(|fuzz: SixlowpanPacketFuzzer| {
200198
IpProtocol::Icmpv6 => {
201199
if let Ok(packet) = Icmpv6Packet::new_checked(payload) {
202200
if let Ok(repr) = Icmpv6Repr::parse(
203-
&iphc_repr.src_addr.into_address(),
204-
&iphc_repr.dst_addr.into_address(),
201+
&src_addr.into_address(),
202+
&dst_addr.into_address(),
205203
&packet,
206204
&ChecksumCapabilities::default(),
207205
) {
208206
let mut buffer = vec![0; repr.buffer_len()];
209207
let mut packet =
210208
Icmpv6Packet::new_unchecked(&mut buffer[..]);
211209
repr.emit(
212-
&iphc_repr.src_addr.into_address(),
213-
&iphc_repr.dst_addr.into_address(),
210+
&src_addr.into_address(),
211+
&dst_addr.into_address(),
214212
&mut packet,
215213
&ChecksumCapabilities::default(),
216214
);

src/iface/interface/sixlowpan.rs

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::*;
2+
use crate::wire::ieee802154::{compress_destination_address, compress_source_address};
23
use crate::wire::Result;
34

45
// Max len of non-fragmented packets after decompression (including ipv6 header and payload)
@@ -206,12 +207,7 @@ impl InterfaceInner {
206207
buffer: &mut [u8],
207208
) -> Result<usize> {
208209
let iphc = SixlowpanIphcPacket::new_checked(iphc_payload)?;
209-
let iphc_repr = SixlowpanIphcRepr::parse(
210-
&iphc,
211-
ieee802154_repr.src_addr,
212-
ieee802154_repr.dst_addr,
213-
address_context,
214-
)?;
210+
let iphc_repr = SixlowpanIphcRepr::parse(&iphc)?;
215211

216212
// The first thing we have to decompress is the IPv6 header. However, at this point we
217213
// don't know the total size of the packet, neither the next header, since that can be a
@@ -245,6 +241,8 @@ impl InterfaceInner {
245241
}
246242
SixlowpanNhcPacket::UdpHeader => {
247243
decompress_udp(
244+
address_context,
245+
ieee802154_repr,
248246
data,
249247
&iphc_repr,
250248
buffer,
@@ -282,8 +280,16 @@ impl InterfaceInner {
282280
}
283281

284282
let ipv6_repr = Ipv6Repr {
285-
src_addr: iphc_repr.src_addr,
286-
dst_addr: iphc_repr.dst_addr,
283+
src_addr: iphc_repr.src_addr.resolve(
284+
ieee802154_repr.src_addr,
285+
address_context,
286+
iphc_repr.context_identifier,
287+
)?,
288+
dst_addr: iphc_repr.dst_addr.resolve(
289+
ieee802154_repr.dst_addr,
290+
address_context,
291+
iphc_repr.context_identifier,
292+
)?,
287293
next_header: decompress_next_header(iphc_repr.next_header, iphc.payload())?,
288294
payload_len: total_len.unwrap_or(payload_len) - 40,
289295
hop_limit: iphc_repr.hop_limit,
@@ -446,10 +452,9 @@ impl InterfaceInner {
446452
};
447453

448454
let iphc_repr = SixlowpanIphcRepr {
449-
src_addr: packet.header.src_addr,
450-
ll_src_addr: ieee_repr.src_addr,
451-
dst_addr: packet.header.dst_addr,
452-
ll_dst_addr: ieee_repr.dst_addr,
455+
src_addr: compress_source_address(packet.header.src_addr, ieee_repr.src_addr),
456+
dst_addr: compress_destination_address(packet.header.dst_addr, ieee_repr.dst_addr),
457+
context_identifier: None,
453458
next_header,
454459
hop_limit: packet.header.hop_limit,
455460
ecn: None,
@@ -529,8 +534,8 @@ impl InterfaceInner {
529534
&mut SixlowpanUdpNhcPacket::new_unchecked(
530535
&mut buffer[..udp_repr.header_len() + payload.len()],
531536
),
532-
&iphc_repr.src_addr,
533-
&iphc_repr.dst_addr,
537+
&packet.header.src_addr,
538+
&packet.header.dst_addr,
534539
payload.len(),
535540
|buf| buf.copy_from_slice(payload),
536541
checksum_caps,
@@ -581,10 +586,9 @@ impl InterfaceInner {
581586
};
582587

583588
let iphc = SixlowpanIphcRepr {
584-
src_addr: packet.header.src_addr,
585-
ll_src_addr: ieee_repr.src_addr,
586-
dst_addr: packet.header.dst_addr,
587-
ll_dst_addr: ieee_repr.dst_addr,
589+
src_addr: compress_source_address(packet.header.src_addr, ieee_repr.src_addr),
590+
dst_addr: compress_destination_address(packet.header.dst_addr, ieee_repr.dst_addr),
591+
context_identifier: None,
588592
next_header,
589593
hop_limit: packet.header.hop_limit,
590594
ecn: None,
@@ -746,6 +750,8 @@ fn decompress_ext_hdr<'d>(
746750
// NOTE: we always inline this function into the sixlowpan_to_ipv6 function, since it is only used there.
747751
#[inline(always)]
748752
fn decompress_udp(
753+
address_context: &[SixlowpanAddressContext],
754+
ieee802154_repr: &Ieee802154Repr,
749755
data: &[u8],
750756
iphc_repr: &SixlowpanIphcRepr,
751757
buffer: &mut [u8],
@@ -757,8 +763,16 @@ fn decompress_udp(
757763
let payload = udp_packet.payload();
758764
let udp_repr = SixlowpanUdpNhcRepr::parse(
759765
&udp_packet,
760-
&iphc_repr.src_addr,
761-
&iphc_repr.dst_addr,
766+
&iphc_repr.src_addr.resolve(
767+
ieee802154_repr.src_addr,
768+
address_context,
769+
iphc_repr.context_identifier,
770+
)?,
771+
&iphc_repr.dst_addr.resolve(
772+
ieee802154_repr.dst_addr,
773+
address_context,
774+
iphc_repr.context_identifier,
775+
)?,
762776
&ChecksumCapabilities::ignored(),
763777
)?;
764778
if udp_repr.header_len() + payload.len() > buffer.len() {

src/iface/interface/tests/sixlowpan.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -138,20 +138,29 @@ fn test_echo_request_sixlowpan_128_bytes() {
138138
let request_first_part_iphc_packet =
139139
SixlowpanIphcPacket::new_checked(request_first_part_packet.payload()).unwrap();
140140

141-
let request_first_part_iphc_repr = SixlowpanIphcRepr::parse(
142-
&request_first_part_iphc_packet,
143-
ieee802154_repr.src_addr,
144-
ieee802154_repr.dst_addr,
145-
&iface.inner.sixlowpan_address_context,
146-
)
147-
.unwrap();
141+
let request_first_part_iphc_repr =
142+
SixlowpanIphcRepr::parse(&request_first_part_iphc_packet).unwrap();
148143

149144
assert_eq!(
150-
request_first_part_iphc_repr.src_addr,
145+
request_first_part_iphc_repr
146+
.src_addr
147+
.resolve(
148+
ieee802154_repr.src_addr,
149+
&iface.inner.sixlowpan_address_context,
150+
request_first_part_iphc_repr.context_identifier
151+
)
152+
.unwrap(),
151153
Ipv6Address::new(0xfe80, 0, 0, 0, 0x4042, 0x4242, 0x4242, 0x0b1a),
152154
);
153155
assert_eq!(
154-
request_first_part_iphc_repr.dst_addr,
156+
request_first_part_iphc_repr
157+
.dst_addr
158+
.resolve(
159+
ieee802154_repr.dst_addr,
160+
&iface.inner.sixlowpan_address_context,
161+
request_first_part_iphc_repr.context_identifier
162+
)
163+
.unwrap(),
155164
Ipv6Address::new(0xfe80, 0, 0, 0, 0x92fc, 0x48c2, 0xa441, 0xfc76),
156165
);
157166

src/wire/ieee802154.rs

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ use core::fmt;
22

33
use byteorder::{ByteOrder, LittleEndian};
44

5-
use super::{Error, Result};
5+
use super::{ipv6, Error, Result};
6+
use crate::wire::sixlowpan::{
7+
DestinationAddress, LinkLocalAddress, MulticastAddress, SourceAddress,
8+
};
69
use crate::wire::{Ipv6Address, Ipv6AddressExt};
710

811
enum_with_unknown! {
@@ -1006,6 +1009,105 @@ impl Repr {
10061009
}
10071010
}
10081011

1012+
pub fn compress_source_address(
1013+
src_addr: ipv6::Address,
1014+
ll_src_addr: Option<Address>,
1015+
) -> SourceAddress {
1016+
let src = src_addr.octets();
1017+
1018+
if src_addr == ipv6::Address::UNSPECIFIED {
1019+
SourceAddress::Unspecified
1020+
} else if src_addr.is_link_local() {
1021+
// We have a link local address.
1022+
// The remainder of the address can be elided when the context contains
1023+
// a 802.15.4 short address or a 802.15.4 extended address which can be
1024+
// converted to a eui64 address.
1025+
let is_eui_64 = ll_src_addr
1026+
.map(|addr| {
1027+
addr.as_eui_64()
1028+
.map(|addr| addr[..] == src[8..])
1029+
.unwrap_or(false)
1030+
})
1031+
.unwrap_or(false);
1032+
1033+
if src[8..14] == [0, 0, 0, 0xff, 0xfe, 0] {
1034+
let ll = [src[14], src[15]];
1035+
1036+
if ll_src_addr == Some(crate::wire::ieee802154::Address::Short(ll)) {
1037+
// We have the context from the 802.15.4 frame.
1038+
// The context contains the short address.
1039+
// We can elide the source address.
1040+
SourceAddress::LinkLocal(LinkLocalAddress::FullyElided)
1041+
} else {
1042+
// We don't have the context from the 802.15.4 frame.
1043+
// We cannot elide the source address, however we can elide 112 bits.
1044+
SourceAddress::LinkLocal(LinkLocalAddress::InLine16bits(
1045+
src[14..].try_into().unwrap(),
1046+
))
1047+
}
1048+
} else if is_eui_64 {
1049+
// We have the context from the 802.15.4 frame.
1050+
// The context contains the extended address.
1051+
// We can elide the source address.
1052+
SourceAddress::LinkLocal(LinkLocalAddress::FullyElided)
1053+
} else {
1054+
// We cannot elide the source address, however we can elide 64 bits.
1055+
SourceAddress::LinkLocal(LinkLocalAddress::InLine64bits(src[8..].try_into().unwrap()))
1056+
}
1057+
} else {
1058+
// We cannot elide anything.
1059+
SourceAddress::LinkLocal(LinkLocalAddress::InLine128bits(src))
1060+
}
1061+
}
1062+
1063+
pub fn compress_destination_address(
1064+
dst_addr: ipv6::Address,
1065+
ll_dst_addr: Option<Address>,
1066+
) -> DestinationAddress {
1067+
let dst = dst_addr.octets();
1068+
if dst_addr.is_multicast() {
1069+
if dst[1] == 0x02 && dst[2..15] == [0; 13] {
1070+
DestinationAddress::Multicast(MulticastAddress::Inline8bits(dst[15]))
1071+
} else if dst[2..13] == [0; 11] {
1072+
let address = [dst[1], dst[13], dst[14], dst[15]];
1073+
DestinationAddress::Multicast(MulticastAddress::Inline32bits(address))
1074+
} else if dst[2..11] == [0; 9] {
1075+
let address = [dst[1], dst[11], dst[12], dst[13], dst[14], dst[15]];
1076+
DestinationAddress::Multicast(MulticastAddress::Inline48bits(address))
1077+
} else {
1078+
DestinationAddress::Multicast(MulticastAddress::FullInline(dst))
1079+
}
1080+
} else if dst_addr.is_link_local() {
1081+
let is_eui_64 = ll_dst_addr
1082+
.map(|addr| {
1083+
addr.as_eui_64()
1084+
.map(|addr| addr[..] == dst[8..])
1085+
.unwrap_or(false)
1086+
})
1087+
.unwrap_or(false);
1088+
1089+
if dst[8..14] == [0, 0, 0, 0xff, 0xfe, 0] {
1090+
let ll = [dst[14], dst[15]];
1091+
1092+
if ll_dst_addr == Some(crate::wire::ieee802154::Address::Short(ll)) {
1093+
DestinationAddress::LinkLocal(LinkLocalAddress::FullyElided)
1094+
} else {
1095+
DestinationAddress::LinkLocal(LinkLocalAddress::InLine16bits(
1096+
dst[14..].try_into().unwrap(),
1097+
))
1098+
}
1099+
} else if is_eui_64 {
1100+
DestinationAddress::LinkLocal(LinkLocalAddress::FullyElided)
1101+
} else {
1102+
DestinationAddress::LinkLocal(LinkLocalAddress::InLine64bits(
1103+
dst[8..].try_into().unwrap(),
1104+
))
1105+
}
1106+
} else {
1107+
DestinationAddress::LinkLocal(LinkLocalAddress::InLine128bits(dst))
1108+
}
1109+
}
1110+
10091111
#[cfg(test)]
10101112
mod test {
10111113
use super::*;

0 commit comments

Comments
 (0)