change(socket/icmp): split ICMPv4/v6 processing

Splitting the accept and process functions into separate functions for
IPv4 and IPv6 allows us to avoid the `IpRepr` enum and instead use the
`Ipv4Repr` and `Ipv6Repr` structs directly. This reduces the binary size
by 1.5 KiB.
This commit is contained in:
Thibaut Vandervelden 2024-01-04 14:14:54 +01:00
parent 5ee728a579
commit 951b59ba1c
18 changed files with 344 additions and 338 deletions

View File

@ -187,11 +187,8 @@ fn main() {
remote_addr
);
icmp_repr.emit(
&iface
.get_source_address_ipv6(&address)
.unwrap()
.into_address(),
&remote_addr,
&iface.get_source_address_ipv6(&address).unwrap(),
&address,
&mut icmp_packet,
&device_caps.checksum,
);
@ -223,11 +220,8 @@ fn main() {
IpAddress::Ipv6(address) => {
let icmp_packet = Icmpv6Packet::new_checked(&payload).unwrap();
let icmp_repr = Icmpv6Repr::parse(
&remote_addr,
&iface
.get_source_address_ipv6(&address)
.unwrap()
.into_address(),
&address,
&iface.get_source_address_ipv6(&address).unwrap(),
&icmp_packet,
&device_caps.checksum,
)

View File

@ -166,16 +166,13 @@ impl InterfaceInner {
if udp_packet.src_port() == dhcp_socket.server_port
&& udp_packet.dst_port() == dhcp_socket.client_port
{
let (src_addr, dst_addr) = (ip_repr.src_addr(), ip_repr.dst_addr());
let udp_repr = check!(UdpRepr::parse(
&udp_packet,
&src_addr,
&dst_addr,
&ipv4_repr.src_addr.into(),
&ipv4_repr.dst_addr.into(),
&self.caps.checksum
));
let udp_payload = udp_packet.payload();
dhcp_socket.process(self, &ipv4_repr, &udp_repr, udp_payload);
dhcp_socket.process(self, &ipv4_repr, &udp_repr, udp_packet.payload());
return None;
}
}
@ -200,7 +197,7 @@ impl InterfaceInner {
}
match ipv4_repr.next_header {
IpProtocol::Icmp => self.process_icmpv4(sockets, ip_repr, ip_payload),
IpProtocol::Icmp => self.process_icmpv4(sockets, ipv4_repr, ip_payload),
#[cfg(feature = "proto-igmp")]
IpProtocol::Igmp => self.process_igmp(ipv4_repr, ip_payload),
@ -298,7 +295,7 @@ impl InterfaceInner {
pub(super) fn process_icmpv4<'frame>(
&mut self,
_sockets: &mut SocketSet,
ip_repr: IpRepr,
ip_repr: Ipv4Repr,
ip_payload: &'frame [u8],
) -> Option<Packet<'frame>> {
let icmp_packet = check!(Icmpv4Packet::new_checked(ip_payload));
@ -312,8 +309,8 @@ impl InterfaceInner {
.items_mut()
.filter_map(|i| icmp::Socket::downcast_mut(&mut i.socket))
{
if icmp_socket.accepts(self, &ip_repr, &icmp_repr.into()) {
icmp_socket.process(self, &ip_repr, &icmp_repr.into());
if icmp_socket.accepts_v4(self, &ip_repr, &icmp_repr) {
icmp_socket.process_v4(self, &ip_repr, &icmp_repr);
handled_by_icmp_socket = true;
}
}
@ -331,11 +328,7 @@ impl InterfaceInner {
seq_no,
data,
};
match ip_repr {
IpRepr::Ipv4(ipv4_repr) => self.icmpv4_reply(ipv4_repr, icmp_reply_repr),
#[allow(unreachable_patterns)]
_ => unreachable!(),
}
self.icmpv4_reply(ip_repr, icmp_reply_repr)
}
// Ignore any echo replies.

View File

@ -260,7 +260,7 @@ impl InterfaceInner {
ip_payload: &'frame [u8],
) -> Option<Packet<'frame>> {
match nxt_hdr {
IpProtocol::Icmpv6 => self.process_icmpv6(sockets, ipv6_repr.into(), ip_payload),
IpProtocol::Icmpv6 => self.process_icmpv6(sockets, ipv6_repr, ip_payload),
#[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
IpProtocol::Udp => self.process_udp(
@ -296,13 +296,13 @@ impl InterfaceInner {
pub(super) fn process_icmpv6<'frame>(
&mut self,
_sockets: &mut SocketSet,
ip_repr: IpRepr,
ip_repr: Ipv6Repr,
ip_payload: &'frame [u8],
) -> Option<Packet<'frame>> {
let icmp_packet = check!(Icmpv6Packet::new_checked(ip_payload));
let icmp_repr = check!(Icmpv6Repr::parse(
&ip_repr.src_addr(),
&ip_repr.dst_addr(),
&ip_repr.src_addr,
&ip_repr.dst_addr,
&icmp_packet,
&self.caps.checksum,
));
@ -317,8 +317,8 @@ impl InterfaceInner {
.items_mut()
.filter_map(|i| IcmpSocket::downcast_mut(&mut i.socket))
{
if icmp_socket.accepts(self, &ip_repr, &icmp_repr.into()) {
icmp_socket.process(self, &ip_repr, &icmp_repr.into());
if icmp_socket.accepts_v6(self, &ip_repr, &icmp_repr) {
icmp_socket.process_v6(self, &ip_repr, &icmp_repr);
handled_by_icmp_socket = true;
}
}
@ -330,35 +330,27 @@ impl InterfaceInner {
ident,
seq_no,
data,
} => match ip_repr {
IpRepr::Ipv6(ipv6_repr) => {
let icmp_reply_repr = Icmpv6Repr::EchoReply {
ident,
seq_no,
data,
};
self.icmpv6_reply(ipv6_repr, icmp_reply_repr)
}
#[allow(unreachable_patterns)]
_ => unreachable!(),
},
} => {
let icmp_reply_repr = Icmpv6Repr::EchoReply {
ident,
seq_no,
data,
};
self.icmpv6_reply(ip_repr, icmp_reply_repr)
}
// Ignore any echo replies.
Icmpv6Repr::EchoReply { .. } => None,
// Forward any NDISC packets to the ndisc packet handler
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
Icmpv6Repr::Ndisc(repr) if ip_repr.hop_limit() == 0xff => match ip_repr {
IpRepr::Ipv6(ipv6_repr) => match self.caps.medium {
#[cfg(feature = "medium-ethernet")]
Medium::Ethernet => self.process_ndisc(ipv6_repr, repr),
#[cfg(feature = "medium-ieee802154")]
Medium::Ieee802154 => self.process_ndisc(ipv6_repr, repr),
#[cfg(feature = "medium-ip")]
Medium::Ip => None,
},
#[allow(unreachable_patterns)]
_ => unreachable!(),
Icmpv6Repr::Ndisc(repr) if ip_repr.hop_limit == 0xff => match self.caps.medium {
#[cfg(feature = "medium-ethernet")]
Medium::Ethernet => self.process_ndisc(ip_repr, repr),
#[cfg(feature = "medium-ieee802154")]
Medium::Ieee802154 => self.process_ndisc(ip_repr, repr),
#[cfg(feature = "medium-ip")]
Medium::Ip => None,
},
// Don't report an error if a packet with unknown type

View File

@ -508,8 +508,8 @@ impl InterfaceInner {
match &mut packet.payload {
IpPayload::Icmpv6(icmp_repr) => {
icmp_repr.emit(
&packet.header.src_addr.into(),
&packet.header.dst_addr.into(),
&packet.header.src_addr,
&packet.header.dst_addr,
&mut Icmpv6Packet::new_unchecked(&mut buffer[..icmp_repr.buffer_len()]),
checksum_caps,
);

View File

@ -565,7 +565,6 @@ fn test_icmpv4_socket(#[case] medium: Medium) {
payload_len: 24,
hop_limit: 64,
};
let ip_repr = IpRepr::Ipv4(ipv4_repr);
// Open a socket and ensure the packet is handled due to the listening
// socket.
@ -583,7 +582,9 @@ fn test_icmpv4_socket(#[case] medium: Medium) {
..ipv4_repr
};
assert_eq!(
iface.inner.process_icmpv4(&mut sockets, ip_repr, icmp_data),
iface
.inner
.process_icmpv4(&mut sockets, ipv4_repr, icmp_data),
Some(Packet::new_ipv4(ipv4_reply, IpPayload::Icmpv4(echo_reply)))
);

View File

@ -16,8 +16,8 @@ fn parse_ipv6(data: &[u8]) -> crate::wire::Result<Packet<'_>> {
IpProtocol::IpSecAh => todo!(),
IpProtocol::Icmpv6 => {
let icmp = Icmpv6Repr::parse(
&ipv6.src_addr.into(),
&ipv6.dst_addr.into(),
&ipv6.src_addr,
&ipv6.dst_addr,
&Icmpv6Packet::new_checked(ipv6_header.payload())?,
&Default::default(),
)?;
@ -707,8 +707,8 @@ fn test_handle_valid_ndisc_request(#[case] medium: Medium) {
frame.set_ethertype(EthernetProtocol::Ipv6);
ip_repr.emit(frame.payload_mut(), &ChecksumCapabilities::default());
solicit.emit(
&remote_ip_addr.into(),
&local_ip_addr.solicited_node().into(),
&remote_ip_addr,
&local_ip_addr.solicited_node(),
&mut Icmpv6Packet::new_unchecked(&mut frame.payload_mut()[ip_repr.header_len()..]),
&ChecksumCapabilities::default(),
);

View File

@ -163,7 +163,10 @@ impl Cache {
#[cfg(test)]
mod test {
use super::*;
use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3, MOCK_IP_ADDR_4};
#[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
use crate::wire::ipv4::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3, MOCK_IP_ADDR_4};
#[cfg(feature = "proto-ipv6")]
use crate::wire::ipv6::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3, MOCK_IP_ADDR_4};
use crate::wire::EthernetAddress;
@ -177,30 +180,30 @@ mod test {
let mut cache = Cache::new();
assert!(!cache
.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0))
.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0))
.found());
assert!(!cache
.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
.lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(0))
.found());
cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
assert_eq!(
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
Answer::Found(HADDR_A)
);
assert!(!cache
.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
.lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(0))
.found());
assert!(!cache
.lookup(
&MOCK_IP_ADDR_1,
&MOCK_IP_ADDR_1.into(),
Instant::from_millis(0) + Cache::ENTRY_LIFETIME * 2
)
.found(),);
cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
assert!(!cache
.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
.lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(0))
.found());
}
@ -208,14 +211,14 @@ mod test {
fn test_expire() {
let mut cache = Cache::new();
cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
assert_eq!(
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
Answer::Found(HADDR_A)
);
assert!(!cache
.lookup(
&MOCK_IP_ADDR_1,
&MOCK_IP_ADDR_1.into(),
Instant::from_millis(0) + Cache::ENTRY_LIFETIME * 2
)
.found(),);
@ -225,14 +228,14 @@ mod test {
fn test_replace() {
let mut cache = Cache::new();
cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
assert_eq!(
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
Answer::Found(HADDR_A)
);
cache.fill(MOCK_IP_ADDR_1, HADDR_B, Instant::from_millis(0));
cache.fill(MOCK_IP_ADDR_1.into(), HADDR_B, Instant::from_millis(0));
assert_eq!(
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
Answer::Found(HADDR_B)
);
}
@ -241,23 +244,23 @@ mod test {
fn test_evict() {
let mut cache = Cache::new();
cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(100));
cache.fill(MOCK_IP_ADDR_2, HADDR_B, Instant::from_millis(50));
cache.fill(MOCK_IP_ADDR_3, HADDR_C, Instant::from_millis(200));
cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(100));
cache.fill(MOCK_IP_ADDR_2.into(), HADDR_B, Instant::from_millis(50));
cache.fill(MOCK_IP_ADDR_3.into(), HADDR_C, Instant::from_millis(200));
assert_eq!(
cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(1000)),
cache.lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(1000)),
Answer::Found(HADDR_B)
);
assert!(!cache
.lookup(&MOCK_IP_ADDR_4, Instant::from_millis(1000))
.lookup(&MOCK_IP_ADDR_4.into(), Instant::from_millis(1000))
.found());
cache.fill(MOCK_IP_ADDR_4, HADDR_D, Instant::from_millis(300));
cache.fill(MOCK_IP_ADDR_4.into(), HADDR_D, Instant::from_millis(300));
assert!(!cache
.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(1000))
.lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(1000))
.found());
assert_eq!(
cache.lookup(&MOCK_IP_ADDR_4, Instant::from_millis(1000)),
cache.lookup(&MOCK_IP_ADDR_4.into(), Instant::from_millis(1000)),
Answer::Found(HADDR_D)
);
}
@ -267,17 +270,17 @@ mod test {
let mut cache = Cache::new();
assert_eq!(
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
Answer::NotFound
);
cache.limit_rate(Instant::from_millis(0));
assert_eq!(
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(100)),
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(100)),
Answer::RateLimited
);
assert_eq!(
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(2000)),
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(2000)),
Answer::NotFound
);
}
@ -286,21 +289,21 @@ mod test {
fn test_flush() {
let mut cache = Cache::new();
cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
assert_eq!(
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
Answer::Found(HADDR_A)
);
assert!(!cache
.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
.lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(0))
.found());
cache.flush();
assert!(!cache
.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0))
.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0))
.found());
assert!(!cache
.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0))
.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0))
.found());
}
}

View File

@ -84,12 +84,20 @@ impl<'p> Packet<'p> {
#[cfg(feature = "proto-igmp")]
IpPayload::Igmp(igmp_repr) => igmp_repr.emit(&mut IgmpPacket::new_unchecked(payload)),
#[cfg(feature = "proto-ipv6")]
IpPayload::Icmpv6(icmpv6_repr) => icmpv6_repr.emit(
&_ip_repr.src_addr(),
&_ip_repr.dst_addr(),
&mut Icmpv6Packet::new_unchecked(payload),
&caps.checksum,
),
IpPayload::Icmpv6(icmpv6_repr) => {
let ipv6_repr = match _ip_repr {
#[cfg(feature = "proto-ipv4")]
IpRepr::Ipv4(_) => unreachable!(),
IpRepr::Ipv6(repr) => repr,
};
icmpv6_repr.emit(
&ipv6_repr.src_addr,
&ipv6_repr.dst_addr,
&mut Icmpv6Packet::new_unchecked(payload),
&caps.checksum,
)
}
#[cfg(feature = "socket-raw")]
IpPayload::Raw(raw_packet) => payload.copy_from_slice(raw_packet),
#[cfg(any(feature = "socket-udp", feature = "socket-dns"))]

View File

@ -412,41 +412,68 @@ impl<'a> Socket<'a> {
Ok((length, endpoint))
}
/// Filter determining which packets received by the interface are appended to
/// the given sockets received buffer.
pub(crate) fn accepts(&self, cx: &mut Context, ip_repr: &IpRepr, icmp_repr: &IcmpRepr) -> bool {
/// Fitler determining whether the socket accepts a given ICMPv4 packet.
/// Accepted packets are enqueued into the socket's receive buffer.
#[cfg(feature = "proto-ipv4")]
#[inline]
pub(crate) fn accepts_v4(
&self,
cx: &mut Context,
ip_repr: &Ipv4Repr,
icmp_repr: &Icmpv4Repr,
) -> bool {
match (&self.endpoint, icmp_repr) {
// If we are bound to ICMP errors associated to a UDP port, only
// accept Destination Unreachable or Time Exceeded messages with
// the data containing a UDP packet send from the local port we
// are bound to.
#[cfg(feature = "proto-ipv4")]
(
&Endpoint::Udp(endpoint),
&IcmpRepr::Ipv4(
Icmpv4Repr::DstUnreachable { data, header, .. }
| Icmpv4Repr::TimeExceeded { data, header, .. },
),
) if endpoint.addr.is_none() || endpoint.addr == Some(ip_repr.dst_addr()) => {
let packet = UdpPacket::new_unchecked(data);
match UdpRepr::parse(
&packet,
&header.src_addr.into(),
&header.dst_addr.into(),
&cx.checksum_caps(),
) {
Ok(repr) => endpoint.port == repr.src_port,
Err(_) => false,
}
}
#[cfg(feature = "proto-ipv6")]
(
&Endpoint::Udp(endpoint),
&IcmpRepr::Ipv6(
Icmpv6Repr::DstUnreachable { data, header, .. }
| Icmpv6Repr::TimeExceeded { data, header, .. },
),
) if endpoint.addr.is_none() || endpoint.addr == Some(ip_repr.dst_addr()) => {
&Icmpv4Repr::DstUnreachable { data, header, .. }
| &Icmpv4Repr::TimeExceeded { data, header, .. },
) if endpoint.addr.is_none() || endpoint.addr == Some(ip_repr.dst_addr.into()) => {
let packet = UdpPacket::new_unchecked(data);
match UdpRepr::parse(
&packet,
&header.src_addr.into(),
&header.dst_addr.into(),
&cx.checksum_caps(),
) {
Ok(repr) => endpoint.port == repr.src_port,
Err(_) => false,
}
}
// If we are bound to a specific ICMP identifier value, only accept an
// Echo Request/Reply with the identifier field matching the endpoint
// port.
(&Endpoint::Ident(bound_ident), &Icmpv4Repr::EchoRequest { ident, .. })
| (&Endpoint::Ident(bound_ident), &Icmpv4Repr::EchoReply { ident, .. }) => {
ident == bound_ident
}
_ => false,
}
}
/// Fitler determining whether the socket accepts a given ICMPv6 packet.
/// Accepted packets are enqueued into the socket's receive buffer.
#[cfg(feature = "proto-ipv6")]
#[inline]
pub(crate) fn accepts_v6(
&self,
cx: &mut Context,
ip_repr: &Ipv6Repr,
icmp_repr: &Icmpv6Repr,
) -> bool {
match (&self.endpoint, icmp_repr) {
// If we are bound to ICMP errors associated to a UDP port, only
// accept Destination Unreachable or Time Exceeded messages with
// the data containing a UDP packet send from the local port we
// are bound to.
(
&Endpoint::Udp(endpoint),
&Icmpv6Repr::DstUnreachable { data, header, .. }
| &Icmpv6Repr::TimeExceeded { data, header, .. },
) if endpoint.addr.is_none() || endpoint.addr == Some(ip_repr.dst_addr.into()) => {
let packet = UdpPacket::new_unchecked(data);
match UdpRepr::parse(
&packet,
@ -461,64 +488,60 @@ impl<'a> Socket<'a> {
// If we are bound to a specific ICMP identifier value, only accept an
// Echo Request/Reply with the identifier field matching the endpoint
// port.
#[cfg(feature = "proto-ipv4")]
(
&Endpoint::Ident(bound_ident),
&IcmpRepr::Ipv4(Icmpv4Repr::EchoRequest { ident, .. }),
)
| (
&Endpoint::Ident(bound_ident),
&IcmpRepr::Ipv4(Icmpv4Repr::EchoReply { ident, .. }),
) => ident == bound_ident,
#[cfg(feature = "proto-ipv6")]
(
&Endpoint::Ident(bound_ident),
&IcmpRepr::Ipv6(Icmpv6Repr::EchoRequest { ident, .. }),
)
| (
&Endpoint::Ident(bound_ident),
&IcmpRepr::Ipv6(Icmpv6Repr::EchoReply { ident, .. }),
&Icmpv6Repr::EchoRequest { ident, .. } | &Icmpv6Repr::EchoReply { ident, .. },
) => ident == bound_ident,
_ => false,
}
}
pub(crate) fn process(&mut self, _cx: &mut Context, ip_repr: &IpRepr, icmp_repr: &IcmpRepr) {
match icmp_repr {
#[cfg(feature = "proto-ipv4")]
IcmpRepr::Ipv4(icmp_repr) => {
net_trace!("icmp: receiving {} octets", icmp_repr.buffer_len());
#[cfg(feature = "proto-ipv4")]
pub(crate) fn process_v4(
&mut self,
_cx: &mut Context,
ip_repr: &Ipv4Repr,
icmp_repr: &Icmpv4Repr,
) {
net_trace!("icmp: receiving {} octets", icmp_repr.buffer_len());
match self
.rx_buffer
.enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())
{
Ok(packet_buf) => {
icmp_repr.emit(
&mut Icmpv4Packet::new_unchecked(packet_buf),
&ChecksumCapabilities::default(),
);
}
Err(_) => net_trace!("icmp: buffer full, dropped incoming packet"),
}
match self
.rx_buffer
.enqueue(icmp_repr.buffer_len(), ip_repr.src_addr.into())
{
Ok(packet_buf) => {
icmp_repr.emit(
&mut Icmpv4Packet::new_unchecked(packet_buf),
&ChecksumCapabilities::default(),
);
}
#[cfg(feature = "proto-ipv6")]
IcmpRepr::Ipv6(icmp_repr) => {
net_trace!("icmp: receiving {} octets", icmp_repr.buffer_len());
Err(_) => net_trace!("icmp: buffer full, dropped incoming packet"),
}
match self
.rx_buffer
.enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())
{
Ok(packet_buf) => icmp_repr.emit(
&ip_repr.src_addr(),
&ip_repr.dst_addr(),
&mut Icmpv6Packet::new_unchecked(packet_buf),
&ChecksumCapabilities::default(),
),
Err(_) => net_trace!("icmp: buffer full, dropped incoming packet"),
}
}
#[cfg(feature = "async")]
self.rx_waker.wake();
}
#[cfg(feature = "proto-ipv6")]
pub(crate) fn process_v6(
&mut self,
_cx: &mut Context,
ip_repr: &Ipv6Repr,
icmp_repr: &Icmpv6Repr,
) {
net_trace!("icmp: receiving {} octets", icmp_repr.buffer_len());
match self
.rx_buffer
.enqueue(icmp_repr.buffer_len(), ip_repr.src_addr.into())
{
Ok(packet_buf) => icmp_repr.emit(
&ip_repr.src_addr,
&ip_repr.dst_addr,
&mut Icmpv6Packet::new_unchecked(packet_buf),
&ChecksumCapabilities::default(),
),
Err(_) => net_trace!("icmp: buffer full, dropped incoming packet"),
}
#[cfg(feature = "async")]
@ -583,8 +606,8 @@ impl<'a> Socket<'a> {
};
let packet = Icmpv6Packet::new_unchecked(&*packet_buf);
let repr = match Icmpv6Repr::parse(
&src_addr.into(),
&dst_addr.into(),
&src_addr,
&dst_addr,
&packet,
&ChecksumCapabilities::ignored(),
) {
@ -684,13 +707,13 @@ mod test_ipv4 {
hop_limit: 0x40,
});
static REMOTE_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
static REMOTE_IPV4_REPR: Ipv4Repr = Ipv4Repr {
src_addr: REMOTE_IPV4,
dst_addr: LOCAL_IPV4,
next_header: IpProtocol::Icmp,
payload_len: 24,
hop_limit: 0x40,
});
};
#[test]
fn test_send_unaddressable() {
@ -816,12 +839,12 @@ mod test_ipv4 {
ECHOV4_REPR.emit(&mut packet, &checksum);
let data = &*packet.into_inner();
assert!(socket.accepts(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()));
socket.process(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into());
assert!(socket.accepts_v4(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR));
socket.process_v4(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR);
assert!(socket.can_recv());
assert!(socket.accepts(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()));
socket.process(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into());
assert!(socket.accepts_v4(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR));
socket.process_v4(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR);
assert_eq!(socket.recv(), Ok((data, REMOTE_IPV4.into())));
assert!(!socket.can_recv());
@ -849,7 +872,7 @@ mod test_ipv4 {
// Ensure that a packet with an identifier that isn't the bound
// ID is not accepted
assert!(!socket.accepts(cx, &REMOTE_IPV4_REPR, &icmp_repr.into()));
assert!(!socket.accepts_v4(cx, &REMOTE_IPV4_REPR, &icmp_repr));
}
#[rstest]
@ -888,20 +911,20 @@ mod test_ipv4 {
},
data,
};
let ip_repr = IpRepr::Ipv4(Ipv4Repr {
let ip_repr = Ipv4Repr {
src_addr: REMOTE_IPV4,
dst_addr: LOCAL_IPV4,
next_header: IpProtocol::Icmp,
payload_len: icmp_repr.buffer_len(),
hop_limit: 0x40,
});
};
assert!(!socket.can_recv());
// Ensure we can accept ICMP error response to the bound
// UDP port
assert!(socket.accepts(cx, &ip_repr, &icmp_repr.into()));
socket.process(cx, &ip_repr, &icmp_repr.into());
assert!(socket.accepts_v4(cx, &ip_repr, &icmp_repr));
socket.process_v4(cx, &ip_repr, &icmp_repr);
assert!(socket.can_recv());
let mut bytes = [0x00; 46];
@ -939,21 +962,21 @@ mod test_ipv6 {
data: &[0xff; 16],
};
static LOCAL_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
static LOCAL_IPV6_REPR: Ipv6Repr = Ipv6Repr {
src_addr: LOCAL_IPV6,
dst_addr: REMOTE_IPV6,
next_header: IpProtocol::Icmpv6,
payload_len: 24,
hop_limit: 0x40,
});
};
static REMOTE_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
static REMOTE_IPV6_REPR: Ipv6Repr = Ipv6Repr {
src_addr: REMOTE_IPV6,
dst_addr: LOCAL_IPV6,
next_header: IpProtocol::Icmpv6,
payload_len: 24,
hop_limit: 0x40,
});
};
#[test]
fn test_send_unaddressable() {
@ -986,12 +1009,7 @@ mod test_ipv6 {
let mut bytes = vec![0xff; 24];
let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
ECHOV6_REPR.emit(
&LOCAL_IPV6.into(),
&REMOTE_IPV6.into(),
&mut packet,
&checksum,
);
ECHOV6_REPR.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
assert_eq!(
socket.send_slice(&*packet.into_inner(), REMOTE_IPV6.into()),
@ -1005,7 +1023,7 @@ mod test_ipv6 {
assert_eq!(
socket.dispatch(cx, |_, (ip_repr, icmp_repr)| {
assert_eq!(ip_repr, LOCAL_IPV6_REPR);
assert_eq!(ip_repr, LOCAL_IPV6_REPR.into());
assert_eq!(icmp_repr, ECHOV6_REPR.into());
Err(())
}),
@ -1016,7 +1034,7 @@ mod test_ipv6 {
assert_eq!(
socket.dispatch(cx, |_, (ip_repr, icmp_repr)| {
assert_eq!(ip_repr, LOCAL_IPV6_REPR);
assert_eq!(ip_repr, LOCAL_IPV6_REPR.into());
assert_eq!(icmp_repr, ECHOV6_REPR.into());
Ok::<_, ()>(())
}),
@ -1038,12 +1056,7 @@ mod test_ipv6 {
let mut bytes = vec![0xff; 24];
let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
ECHOV6_REPR.emit(
&LOCAL_IPV6.into(),
&REMOTE_IPV6.into(),
&mut packet,
&checksum,
);
ECHOV6_REPR.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
s.set_hop_limit(Some(0x2a));
@ -1086,20 +1099,15 @@ mod test_ipv6 {
let mut bytes = [0xff; 24];
let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
ECHOV6_REPR.emit(
&LOCAL_IPV6.into(),
&REMOTE_IPV6.into(),
&mut packet,
&checksum,
);
ECHOV6_REPR.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
let data = &*packet.into_inner();
assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into());
assert!(socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR));
socket.process_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR);
assert!(socket.can_recv());
assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into());
assert!(socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR));
socket.process_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR);
assert_eq!(socket.recv(), Ok((data, REMOTE_IPV6.into())));
assert!(!socket.can_recv());
@ -1119,19 +1127,14 @@ mod test_ipv6 {
let mut bytes = [0xff; 24];
let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
ECHOV6_REPR.emit(
&LOCAL_IPV6.into(),
&REMOTE_IPV6.into(),
&mut packet,
&checksum,
);
ECHOV6_REPR.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into());
assert!(socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR));
socket.process_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR);
assert!(socket.can_recv());
assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into());
assert!(socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR));
socket.process_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR);
let mut buffer = [0u8; 1];
assert_eq!(
@ -1159,16 +1162,11 @@ mod test_ipv6 {
seq_no: 0x5678,
data: &[0xff; 16],
};
icmp_repr.emit(
&LOCAL_IPV6.into(),
&REMOTE_IPV6.into(),
&mut packet,
&checksum,
);
icmp_repr.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
// Ensure that a packet with an identifier that isn't the bound
// ID is not accepted
assert!(!socket.accepts(cx, &REMOTE_IPV6_REPR, &icmp_repr.into()));
assert!(!socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &icmp_repr));
}
#[rstest]
@ -1207,30 +1205,25 @@ mod test_ipv6 {
},
data,
};
let ip_repr = IpRepr::Ipv6(Ipv6Repr {
let ip_repr = Ipv6Repr {
src_addr: REMOTE_IPV6,
dst_addr: LOCAL_IPV6,
next_header: IpProtocol::Icmpv6,
payload_len: icmp_repr.buffer_len(),
hop_limit: 0x40,
});
};
assert!(!socket.can_recv());
// Ensure we can accept ICMP error response to the bound
// UDP port
assert!(socket.accepts(cx, &ip_repr, &icmp_repr.into()));
socket.process(cx, &ip_repr, &icmp_repr.into());
assert!(socket.accepts_v6(cx, &ip_repr, &icmp_repr));
socket.process_v6(cx, &ip_repr, &icmp_repr);
assert!(socket.can_recv());
let mut bytes = [0x00; 66];
let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
icmp_repr.emit(
&LOCAL_IPV6.into(),
&REMOTE_IPV6.into(),
&mut packet,
&checksum,
);
icmp_repr.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
assert_eq!(
socket.recv(),
Ok((&*packet.into_inner(), REMOTE_IPV6.into()))

View File

@ -9,7 +9,7 @@ use crate::wire::MldRepr;
use crate::wire::NdiscRepr;
#[cfg(feature = "proto-rpl")]
use crate::wire::RplRepr;
use crate::wire::{IpAddress, IpProtocol, Ipv6Packet, Ipv6Repr};
use crate::wire::{IpProtocol, Ipv6Address, Ipv6Packet, Ipv6Repr};
use crate::wire::{IPV6_HEADER_LEN, IPV6_MIN_MTU};
/// Error packets must not exceed min MTU
@ -421,14 +421,14 @@ impl<T: AsRef<[u8]>> Packet<T> {
///
/// # Fuzzing
/// This function always returns `true` when fuzzing.
pub fn verify_checksum(&self, src_addr: &IpAddress, dst_addr: &IpAddress) -> bool {
pub fn verify_checksum(&self, src_addr: &Ipv6Address, dst_addr: &Ipv6Address) -> bool {
if cfg!(fuzzing) {
return true;
}
let data = self.buffer.as_ref();
checksum::combine(&[
checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Icmpv6, data.len() as u32),
checksum::pseudo_header_v6(src_addr, dst_addr, IpProtocol::Icmpv6, data.len() as u32),
checksum::data(data),
]) == !0
}
@ -535,12 +535,17 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
}
/// Compute and fill in the header checksum.
pub fn fill_checksum(&mut self, src_addr: &IpAddress, dst_addr: &IpAddress) {
pub fn fill_checksum(&mut self, src_addr: &Ipv6Address, dst_addr: &Ipv6Address) {
self.set_checksum(0);
let checksum = {
let data = self.buffer.as_ref();
!checksum::combine(&[
checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Icmpv6, data.len() as u32),
checksum::pseudo_header_v6(
src_addr,
dst_addr,
IpProtocol::Icmpv6,
data.len() as u32,
),
checksum::data(data),
])
};
@ -609,8 +614,8 @@ impl<'a> Repr<'a> {
/// Parse an Internet Control Message Protocol version 6 packet and return
/// a high-level representation.
pub fn parse<T>(
src_addr: &IpAddress,
dst_addr: &IpAddress,
src_addr: &Ipv6Address,
dst_addr: &Ipv6Address,
packet: &Packet<&'a T>,
checksum_caps: &ChecksumCapabilities,
) -> Result<Repr<'a>>
@ -725,8 +730,8 @@ impl<'a> Repr<'a> {
/// packet.
pub fn emit<T>(
&self,
src_addr: &IpAddress,
dst_addr: &IpAddress,
src_addr: &Ipv6Address,
dst_addr: &Ipv6Address,
packet: &mut Packet<&mut T>,
checksum_caps: &ChecksumCapabilities,
) where
@ -840,9 +845,13 @@ impl<'a> Repr<'a> {
#[cfg(test)]
mod test {
use super::*;
use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2};
use crate::wire::{IpProtocol, Ipv6Address, Ipv6Repr};
const MOCK_IP_ADDR_1: Ipv6Address =
Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
const MOCK_IP_ADDR_2: Ipv6Address =
Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
static ECHO_PACKET_BYTES: [u8; 12] = [
0x80, 0x00, 0x19, 0xb3, 0x12, 0x34, 0xab, 0xcd, 0xaa, 0x00, 0x00, 0xff,
];

View File

@ -753,7 +753,42 @@ pub mod checksum {
propagate_carries(accum)
}
/// Compute an IP pseudo header checksum.
#[cfg(feature = "proto-ipv4")]
pub fn pseudo_header_v4(
src_addr: &Ipv4Address,
dst_addr: &Ipv4Address,
next_header: Protocol,
length: u32,
) -> u16 {
let mut proto_len = [0u8; 4];
proto_len[1] = next_header.into();
NetworkEndian::write_u16(&mut proto_len[2..4], length as u16);
combine(&[
data(src_addr.as_bytes()),
data(dst_addr.as_bytes()),
data(&proto_len[..]),
])
}
#[cfg(feature = "proto-ipv6")]
pub fn pseudo_header_v6(
src_addr: &Ipv6Address,
dst_addr: &Ipv6Address,
next_header: Protocol,
length: u32,
) -> u16 {
let mut proto_len = [0u8; 4];
proto_len[1] = next_header.into();
NetworkEndian::write_u16(&mut proto_len[2..4], length as u16);
combine(&[
data(src_addr.as_bytes()),
data(dst_addr.as_bytes()),
data(&proto_len[..]),
])
}
pub fn pseudo_header(
src_addr: &Address,
dst_addr: &Address,
@ -762,32 +797,15 @@ pub mod checksum {
) -> u16 {
match (src_addr, dst_addr) {
#[cfg(feature = "proto-ipv4")]
(&Address::Ipv4(src_addr), &Address::Ipv4(dst_addr)) => {
let mut proto_len = [0u8; 4];
proto_len[1] = next_header.into();
NetworkEndian::write_u16(&mut proto_len[2..4], length as u16);
combine(&[
data(src_addr.as_bytes()),
data(dst_addr.as_bytes()),
data(&proto_len[..]),
])
(Address::Ipv4(src_addr), Address::Ipv4(dst_addr)) => {
pseudo_header_v4(src_addr, dst_addr, next_header, length)
}
#[cfg(feature = "proto-ipv6")]
(&Address::Ipv6(src_addr), &Address::Ipv6(dst_addr)) => {
let mut proto_len = [0u8; 8];
proto_len[7] = next_header.into();
NetworkEndian::write_u32(&mut proto_len[0..4], length);
combine(&[
data(src_addr.as_bytes()),
data(dst_addr.as_bytes()),
data(&proto_len[..]),
])
(Address::Ipv6(src_addr), Address::Ipv6(dst_addr)) => {
pseudo_header_v6(src_addr, dst_addr, next_header, length)
}
#[allow(unreachable_patterns)]
_ => panic!("Unexpected pseudo header addresses: {src_addr}, {dst_addr}"),
_ => unreachable!(),
}
}
@ -882,36 +900,6 @@ pub fn pretty_print_ip_payload<T: Into<Repr>>(
pub(crate) mod test {
#![allow(unused)]
#[cfg(feature = "proto-ipv6")]
pub(crate) const MOCK_IP_ADDR_1: IpAddress = IpAddress::Ipv6(Ipv6Address([
0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
]));
#[cfg(feature = "proto-ipv6")]
pub(crate) const MOCK_IP_ADDR_2: IpAddress = IpAddress::Ipv6(Ipv6Address([
0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
]));
#[cfg(feature = "proto-ipv6")]
pub(crate) const MOCK_IP_ADDR_3: IpAddress = IpAddress::Ipv6(Ipv6Address([
0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
]));
#[cfg(feature = "proto-ipv6")]
pub(crate) const MOCK_IP_ADDR_4: IpAddress = IpAddress::Ipv6(Ipv6Address([
0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,
]));
#[cfg(feature = "proto-ipv6")]
pub(crate) const MOCK_UNSPECIFIED: IpAddress = IpAddress::Ipv6(Ipv6Address::UNSPECIFIED);
#[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
pub(crate) const MOCK_IP_ADDR_1: IpAddress = IpAddress::Ipv4(Ipv4Address([192, 168, 1, 1]));
#[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
pub(crate) const MOCK_IP_ADDR_2: IpAddress = IpAddress::Ipv4(Ipv4Address([192, 168, 1, 2]));
#[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
pub(crate) const MOCK_IP_ADDR_3: IpAddress = IpAddress::Ipv4(Ipv4Address([192, 168, 1, 3]));
#[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
pub(crate) const MOCK_IP_ADDR_4: IpAddress = IpAddress::Ipv4(Ipv4Address([192, 168, 1, 4]));
#[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
pub(crate) const MOCK_UNSPECIFIED: IpAddress = IpAddress::Ipv4(Ipv4Address::UNSPECIFIED);
use super::*;
use crate::wire::{IpAddress, IpCidr, IpProtocol};
#[cfg(feature = "proto-ipv4")]

View File

@ -796,9 +796,20 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
}
#[cfg(test)]
mod test {
pub(crate) mod test {
use super::*;
#[allow(unused)]
pub(crate) const MOCK_IP_ADDR_1: Address = Address([192, 168, 1, 1]);
#[allow(unused)]
pub(crate) const MOCK_IP_ADDR_2: Address = Address([192, 168, 1, 2]);
#[allow(unused)]
pub(crate) const MOCK_IP_ADDR_3: Address = Address([192, 168, 1, 3]);
#[allow(unused)]
pub(crate) const MOCK_IP_ADDR_4: Address = Address([192, 168, 1, 4]);
#[allow(unused)]
pub(crate) const MOCK_UNSPECIFIED: Address = Address::UNSPECIFIED;
static PACKET_BYTES: [u8; 30] = [
0x45, 0x00, 0x00, 0x1e, 0x01, 0x02, 0x62, 0x03, 0x1a, 0x01, 0xd5, 0x6e, 0x11, 0x12, 0x13,
0x14, 0x21, 0x22, 0x23, 0x24, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,

View File

@ -897,7 +897,7 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
}
#[cfg(test)]
mod test {
pub(crate) mod test {
use super::Error;
use super::{Address, Cidr};
use super::{Packet, Protocol, Repr};
@ -906,6 +906,21 @@ mod test {
#[cfg(feature = "proto-ipv4")]
use crate::wire::ipv4::Address as Ipv4Address;
#[allow(unused)]
pub(crate) const MOCK_IP_ADDR_1: Address =
Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
#[allow(unused)]
pub(crate) const MOCK_IP_ADDR_2: Address =
Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
#[allow(unused)]
pub(crate) const MOCK_IP_ADDR_3: Address =
Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]);
#[allow(unused)]
pub(crate) const MOCK_IP_ADDR_4: Address =
Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4]);
#[allow(unused)]
pub(crate) const MOCK_UNSPECIFIED: Address = Address::UNSPECIFIED;
const LINK_LOCAL_ADDR: Address = Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
const UNIQUE_LOCAL_ADDR: Address = Address::new(0xfd00, 0, 0, 201, 1, 1, 1, 1);
const GLOBAL_UNICAST_ADDR: Address = Address::new(0x2001, 0xdb8, 0x3, 0, 0, 0, 0, 1);

View File

@ -476,8 +476,8 @@ mod test {
.copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes());
packet.clear_reserved();
packet.fill_checksum(
&Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
&Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
&Ipv6Address::LINK_LOCAL_ALL_NODES,
&Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
);
assert_eq!(&*packet.into_inner(), &QUERY_PACKET_BYTES[..]);
}
@ -519,8 +519,8 @@ mod test {
.copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes());
}
packet.fill_checksum(
&Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
&Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
&Ipv6Address::LINK_LOCAL_ALL_NODES,
&Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
);
assert_eq!(&*packet.into_inner(), &REPORT_PACKET_BYTES[..]);
}
@ -529,8 +529,8 @@ mod test {
fn test_query_repr_parse() {
let packet = Packet::new_unchecked(&QUERY_PACKET_BYTES[..]);
let repr = Icmpv6Repr::parse(
&Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
&Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
&Ipv6Address::LINK_LOCAL_ALL_NODES,
&Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
&packet,
&ChecksumCapabilities::default(),
);
@ -541,8 +541,8 @@ mod test {
fn test_report_repr_parse() {
let packet = Packet::new_unchecked(&REPORT_PACKET_BYTES[..]);
let repr = Icmpv6Repr::parse(
&Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
&Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
&Ipv6Address::LINK_LOCAL_ALL_NODES,
&Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
&packet,
&ChecksumCapabilities::default(),
);
@ -555,8 +555,8 @@ mod test {
let mut packet = Packet::new_unchecked(&mut bytes[..]);
let repr = create_repr(Message::MldQuery);
repr.emit(
&Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
&Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
&Ipv6Address::LINK_LOCAL_ALL_NODES,
&Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
&mut packet,
&ChecksumCapabilities::default(),
);
@ -569,8 +569,8 @@ mod test {
let mut packet = Packet::new_unchecked(&mut bytes[..]);
let repr = create_repr(Message::MldReport);
repr.emit(
&Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
&Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
&Ipv6Address::LINK_LOCAL_ALL_NODES,
&Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
&mut packet,
&ChecksumCapabilities::default(),
);

View File

@ -97,9 +97,9 @@ pub mod ieee802154;
mod igmp;
pub(crate) mod ip;
#[cfg(feature = "proto-ipv4")]
mod ipv4;
pub(crate) mod ipv4;
#[cfg(feature = "proto-ipv6")]
mod ipv6;
pub(crate) mod ipv6;
#[cfg(feature = "proto-ipv6")]
mod ipv6ext_header;
#[cfg(feature = "proto-ipv6")]

View File

@ -459,10 +459,14 @@ impl<'a> Repr<'a> {
mod test {
use super::*;
use crate::phy::ChecksumCapabilities;
use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2};
use crate::wire::EthernetAddress;
use crate::wire::Icmpv6Repr;
const MOCK_IP_ADDR_1: Ipv6Address =
Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
const MOCK_IP_ADDR_2: Ipv6Address =
Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
static ROUTER_ADVERT_BYTES: [u8; 24] = [
0x86, 0x00, 0xa9, 0xde, 0x40, 0x80, 0x03, 0x84, 0x00, 0x00, 0x03, 0x84, 0x00, 0x00, 0x03,
0x84, 0x01, 0x01, 0x52, 0x54, 0x00, 0x12, 0x34, 0x56,

View File

@ -2414,8 +2414,8 @@ mod tests {
SixlowpanNextHeader::Uncompressed(IpProtocol::Icmpv6) => {
let icmp_packet = Icmpv6Packet::new_checked(packet.payload()).unwrap();
match Icmpv6Repr::parse(
&IpAddress::Ipv6(repr.src_addr),
&IpAddress::Ipv6(repr.dst_addr),
&repr.src_addr,
&repr.dst_addr,
&icmp_packet,
&ChecksumCapabilities::ignored(),
) {

View File

@ -4,12 +4,7 @@
use super::{Error, NextHeader, Result, DISPATCH_EXT_HEADER, DISPATCH_UDP_HEADER};
use crate::{
phy::ChecksumCapabilities,
wire::{
ip::{checksum, Address as IpAddress},
ipv6,
udp::Repr as UdpRepr,
IpProtocol,
},
wire::{ip::checksum, ipv6, udp::Repr as UdpRepr, IpProtocol},
};
use byteorder::{ByteOrder, NetworkEndian};
use ipv6::Address;
@ -708,9 +703,9 @@ impl<'a> UdpNhcRepr {
if checksum_caps.udp.rx() {
let payload_len = packet.payload().len();
let chk_sum = !checksum::combine(&[
checksum::pseudo_header(
&IpAddress::Ipv6(*src_addr),
&IpAddress::Ipv6(*dst_addr),
checksum::pseudo_header_v6(
src_addr,
dst_addr,
crate::wire::ip::Protocol::Udp,
payload_len as u32 + 8,
),
@ -763,9 +758,9 @@ impl<'a> UdpNhcRepr {
if checksum_caps.udp.tx() {
let chk_sum = !checksum::combine(&[
checksum::pseudo_header(
&IpAddress::Ipv6(*src_addr),
&IpAddress::Ipv6(*dst_addr),
checksum::pseudo_header_v6(
src_addr,
dst_addr,
crate::wire::ip::Protocol::Udp,
payload_len as u32 + 8,
),