diff --git a/Cargo.toml b/Cargo.toml index 9d42b06a1..15b8321e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "smoltcp" version = "0.11.0" edition = "2021" -rust-version = "1.77" +rust-version = "1.80" authors = ["whitequark "] description = "A TCP/IP stack designed for bare-metal, real-time systems without a heap." documentation = "https://docs.rs/smoltcp/" @@ -25,7 +25,7 @@ byteorder = { version = "1.0", default-features = false } log = { version = "0.4.4", default-features = false, optional = true } libc = { version = "0.2.18", optional = true } bitflags = { version = "1.0", default-features = false } -defmt = { version = "0.3", optional = true } +defmt = { version = "0.3.8", optional = true, features = ["ip_in_core"] } cfg-if = "1.0.0" heapless = "0.8" diff --git a/README.md b/README.md index 82a455b61..45c4c4970 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ include complicated compile-time computations, such as macro or type tricks, eve at cost of performance degradation. _smoltcp_ does not need heap allocation *at all*, is [extensively documented][docs], -and compiles on stable Rust 1.77 and later. +and compiles on stable Rust 1.80 and later. _smoltcp_ achieves [~Gbps of throughput](#examplesbenchmarkrs) when tested against the Linux TCP stack in loopback mode. diff --git a/benches/bench.rs b/benches/bench.rs index 0920958d9..a05ccff91 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -13,18 +13,14 @@ mod wire { extern crate test; #[cfg(feature = "proto-ipv6")] - const SRC_ADDR: IpAddress = IpAddress::Ipv6(Ipv6Address([ - 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - ])); + const SRC_ADDR: IpAddress = IpAddress::Ipv6(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)); #[cfg(feature = "proto-ipv6")] - const DST_ADDR: IpAddress = IpAddress::Ipv6(Ipv6Address([ - 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, - ])); + const DST_ADDR: IpAddress = IpAddress::Ipv6(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2)); #[cfg(all(not(feature = "proto-ipv6"), feature = "proto-ipv4"))] - const SRC_ADDR: IpAddress = IpAddress::Ipv4(Ipv4Address([192, 168, 1, 1])); + const SRC_ADDR: IpAddress = IpAddress::Ipv4(Ipv4Address::new(192, 168, 1, 1)); #[cfg(all(not(feature = "proto-ipv6"), feature = "proto-ipv4"))] - const DST_ADDR: IpAddress = IpAddress::Ipv4(Ipv4Address([192, 168, 1, 2])); + const DST_ADDR: IpAddress = IpAddress::Ipv4(Ipv4Address::new(192, 168, 1, 2)); #[bench] #[cfg(any(feature = "proto-ipv6", feature = "proto-ipv4"))] @@ -84,8 +80,8 @@ mod wire { #[cfg(feature = "proto-ipv4")] fn bench_emit_ipv4(b: &mut test::Bencher) { let repr = Ipv4Repr { - src_addr: Ipv4Address([192, 168, 1, 1]), - dst_addr: Ipv4Address([192, 168, 1, 2]), + src_addr: Ipv4Address::new(192, 168, 1, 1), + dst_addr: Ipv4Address::new(192, 168, 1, 2), next_header: IpProtocol::Tcp, payload_len: 100, hop_limit: 64, @@ -102,8 +98,8 @@ mod wire { #[cfg(feature = "proto-ipv6")] fn bench_emit_ipv6(b: &mut test::Bencher) { let repr = Ipv6Repr { - src_addr: Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]), - dst_addr: Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]), + src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), + dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2), next_header: IpProtocol::Tcp, payload_len: 100, hop_limit: 64, diff --git a/ci.sh b/ci.sh index eb9235f7e..39a9cd334 100755 --- a/ci.sh +++ b/ci.sh @@ -4,7 +4,7 @@ set -eox pipefail export DEFMT_LOG=trace -MSRV="1.77.0" +MSRV="1.80.0" RUSTC_VERSIONS=( $MSRV diff --git a/examples/loopback.rs b/examples/loopback.rs index 7ca95b188..574ac9d0b 100644 --- a/examples/loopback.rs +++ b/examples/loopback.rs @@ -3,7 +3,6 @@ #![allow(clippy::collapsible_if)] #[cfg(feature = "std")] -#[allow(dead_code)] mod utils; use core::str; diff --git a/examples/multicast.rs b/examples/multicast.rs index 44162d6d3..ab86a4bce 100644 --- a/examples/multicast.rs +++ b/examples/multicast.rs @@ -12,7 +12,7 @@ use smoltcp::wire::{ }; const MDNS_PORT: u16 = 5353; -const MDNS_GROUP: [u8; 4] = [224, 0, 0, 251]; +const MDNS_GROUP: Ipv4Address = Ipv4Address::new(224, 0, 0, 251); fn main() { utils::setup_logging("warn"); @@ -81,9 +81,7 @@ fn main() { let udp_handle = sockets.add(udp_socket); // Join a multicast group to receive mDNS traffic - iface - .join_multicast_group(Ipv4Address::from_bytes(&MDNS_GROUP)) - .unwrap(); + iface.join_multicast_group(MDNS_GROUP).unwrap(); loop { let timestamp = Instant::now(); diff --git a/examples/multicast6.rs b/examples/multicast6.rs index 46e4e7bd7..e9a2712b2 100644 --- a/examples/multicast6.rs +++ b/examples/multicast6.rs @@ -19,9 +19,9 @@ use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv6Address}; // will send packets to the multicast group we join below on tap0. const PORT: u16 = 8123; -const GROUP: [u16; 8] = [0xff02, 0, 0, 0, 0, 0, 0, 0x1234]; -const LOCAL_ADDR: [u16; 8] = [0xfe80, 0, 0, 0, 0, 0, 0, 0x101]; -const ROUTER_ADDR: [u16; 8] = [0xfe80, 0, 0, 0, 0, 0, 0, 0x100]; +const GROUP: Ipv6Address = Ipv6Address::new(0xff02, 0, 0, 0, 0, 0, 0, 0x1234); +const LOCAL_ADDR: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x101); +const ROUTER_ADDR: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x100); fn main() { utils::setup_logging("warn"); @@ -37,7 +37,6 @@ fn main() { utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false); // Create interface - let local_addr = Ipv6Address::from_parts(&LOCAL_ADDR); let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]); let mut config = match device.capabilities().medium { Medium::Ethernet => Config::new(ethernet_addr.into()), @@ -49,12 +48,12 @@ fn main() { let mut iface = Interface::new(config, &mut device, Instant::now()); iface.update_ip_addrs(|ip_addrs| { ip_addrs - .push(IpCidr::new(IpAddress::from(local_addr), 64)) + .push(IpCidr::new(IpAddress::from(LOCAL_ADDR), 64)) .unwrap(); }); iface .routes_mut() - .add_default_ipv6_route(Ipv6Address::from_parts(&ROUTER_ADDR)) + .add_default_ipv6_route(ROUTER_ADDR) .unwrap(); // Create sockets @@ -65,9 +64,7 @@ fn main() { let udp_handle = sockets.add(udp_socket); // Join a multicast group - iface - .join_multicast_group(Ipv6Address::from_parts(&GROUP)) - .unwrap(); + iface.join_multicast_group(GROUP).unwrap(); loop { let timestamp = Instant::now(); diff --git a/src/iface/fragmentation.rs b/src/iface/fragmentation.rs index ed00f1775..16c84f456 100644 --- a/src/iface/fragmentation.rs +++ b/src/iface/fragmentation.rs @@ -137,7 +137,7 @@ impl PacketAssembler { /// # Errors /// /// - Returns [`Error::PacketAssemblerBufferTooSmall`] when trying to add data into the buffer at a non-existing - /// place. + /// place. pub(crate) fn add(&mut self, data: &[u8], offset: usize) -> Result<(), AssemblerError> { #[cfg(not(feature = "alloc"))] if self.buffer.len() < offset + data.len() { @@ -329,8 +329,8 @@ impl Fragmenter { #[cfg(feature = "proto-ipv4-fragmentation")] ipv4: Ipv4Fragmenter { repr: Ipv4Repr { - src_addr: Ipv4Address::default(), - dst_addr: Ipv4Address::default(), + src_addr: Ipv4Address::new(0, 0, 0, 0), + dst_addr: Ipv4Address::new(0, 0, 0, 0), next_header: IpProtocol::Unknown(0), payload_len: 0, hop_limit: 0, @@ -373,8 +373,8 @@ impl Fragmenter { #[cfg(feature = "proto-ipv4-fragmentation")] { self.ipv4.repr = Ipv4Repr { - src_addr: Ipv4Address::default(), - dst_addr: Ipv4Address::default(), + src_addr: Ipv4Address::new(0, 0, 0, 0), + dst_addr: Ipv4Address::new(0, 0, 0, 0), next_header: IpProtocol::Unknown(0), payload_len: 0, hop_limit: 0, diff --git a/src/iface/interface/ipv4.rs b/src/iface/interface/ipv4.rs index 2e93a336e..7fda3ae3b 100644 --- a/src/iface/interface/ipv4.rs +++ b/src/iface/interface/ipv4.rs @@ -70,7 +70,7 @@ impl InterfaceInner { /// Checks if an ipv4 address is unicast, taking into account subnet broadcast addresses fn is_unicast_v4(&self, address: Ipv4Address) -> bool { - address.is_unicast() && !self.is_broadcast_v4(address) + address.x_is_unicast() && !self.is_broadcast_v4(address) } /// Get the first IPv4 address of the interface. @@ -181,13 +181,27 @@ impl InterfaceInner { { // Ignore IP packets not directed at us, or broadcast, or any of the multicast groups. // If AnyIP is enabled, also check if the packet is routed locally. - if !self.any_ip - || !ipv4_repr.dst_addr.is_unicast() - || self - .routes - .lookup(&IpAddress::Ipv4(ipv4_repr.dst_addr), self.now) - .map_or(true, |router_addr| !self.has_ip_addr(router_addr)) + + if !self.any_ip { + net_trace!("Rejecting IPv4 packet; any_ip=false"); + return None; + } + + if !ipv4_repr.dst_addr.x_is_unicast() { + net_trace!( + "Rejecting IPv4 packet; {} is not a unicast address", + ipv4_repr.dst_addr + ); + return None; + } + + if self + .routes + .lookup(&IpAddress::Ipv4(ipv4_repr.dst_addr), self.now) + .map_or(true, |router_addr| !self.has_ip_addr(router_addr)) { + net_trace!("Rejecting IPv4 packet; no matching routes"); + return None; } } @@ -260,7 +274,7 @@ impl InterfaceInner { } // Discard packets with non-unicast source addresses. - if !source_protocol_addr.is_unicast() || !source_hardware_addr.is_unicast() { + if !source_protocol_addr.x_is_unicast() || !source_hardware_addr.is_unicast() { net_debug!("arp: non-unicast source address"); return None; } diff --git a/src/iface/interface/ipv6.rs b/src/iface/interface/ipv6.rs index a8d29e48c..96e999f7e 100644 --- a/src/iface/interface/ipv6.rs +++ b/src/iface/interface/ipv6.rs @@ -37,9 +37,9 @@ impl InterfaceInner { } if dst_addr.is_multicast() - && matches!(dst_addr.multicast_scope(), Ipv6MulticastScope::LinkLocal) + && matches!(dst_addr.x_multicast_scope(), Ipv6MulticastScope::LinkLocal) && src_addr.is_multicast() - && !matches!(src_addr.multicast_scope(), Ipv6MulticastScope::LinkLocal) + && !matches!(src_addr.x_multicast_scope(), Ipv6MulticastScope::LinkLocal) { return false; } @@ -58,7 +58,7 @@ impl InterfaceInner { fn common_prefix_length(dst_addr: &Ipv6Cidr, src_addr: &Ipv6Address) -> usize { let addr = dst_addr.address(); let mut bits = 0; - for (l, r) in addr.as_bytes().iter().zip(src_addr.as_bytes().iter()) { + for (l, r) in addr.octets().iter().zip(src_addr.octets().iter()) { if l == r { bits += 8; } else { @@ -82,7 +82,7 @@ impl InterfaceInner { .count() == 0 { - return Ipv6Address::LOOPBACK; + return Ipv6Address::LOCALHOST; } let mut candidate = self @@ -111,15 +111,16 @@ impl InterfaceInner { } // Rule 2: prefer appropriate scope. - if (candidate.address().multicast_scope() as u8) - < (addr.address().multicast_scope() as u8) + if (candidate.address().x_multicast_scope() as u8) + < (addr.address().x_multicast_scope() as u8) { - if (candidate.address().multicast_scope() as u8) - < (dst_addr.multicast_scope() as u8) + if (candidate.address().x_multicast_scope() as u8) + < (dst_addr.x_multicast_scope() as u8) { candidate = addr; } - } else if (addr.address().multicast_scope() as u8) > (dst_addr.multicast_scope() as u8) + } else if (addr.address().x_multicast_scope() as u8) + > (dst_addr.x_multicast_scope() as u8) { candidate = addr; } @@ -147,10 +148,10 @@ impl InterfaceInner { pub fn has_solicited_node(&self, addr: Ipv6Address) -> bool { self.ip_addrs.iter().any(|cidr| { match *cidr { - IpCidr::Ipv6(cidr) if cidr.address() != Ipv6Address::LOOPBACK => { + IpCidr::Ipv6(cidr) if cidr.address() != Ipv6Address::LOCALHOST => { // Take the lower order 24 bits of the IPv6 address and // append those bits to FF02:0:0:0:0:1:FF00::/104. - addr.as_bytes()[14..] == cidr.address().as_bytes()[14..] + addr.octets()[14..] == cidr.address().octets()[14..] } _ => false, } @@ -192,7 +193,7 @@ impl InterfaceInner { ) -> Option> { let ipv6_repr = check!(Ipv6Repr::parse(ipv6_packet)); - if !ipv6_repr.src_addr.is_unicast() { + if !ipv6_repr.src_addr.x_is_unicast() { // Discard packets with non-unicast source addresses. net_debug!("non-unicast source address"); return None; @@ -211,15 +212,26 @@ impl InterfaceInner { && !self.has_multicast_group(ipv6_repr.dst_addr) && !ipv6_repr.dst_addr.is_loopback() { - // If AnyIP is enabled, also check if the packet is routed locally. - if !self.any_ip - || !ipv6_repr.dst_addr.is_unicast() - || self - .routes - .lookup(&IpAddress::Ipv6(ipv6_repr.dst_addr), self.now) - .map_or(true, |router_addr| !self.has_ip_addr(router_addr)) + if !self.any_ip { + net_trace!("Rejecting IPv6 packet; any_ip=false"); + return None; + } + + if !ipv6_repr.dst_addr.x_is_unicast() { + net_trace!( + "Rejecting IPv6 packet; {} is not a unicast address", + ipv6_repr.dst_addr + ); + return None; + } + + if self + .routes + .lookup(&IpAddress::Ipv6(ipv6_repr.dst_addr), self.now) + .map_or(true, |router_addr| !self.has_ip_addr(router_addr)) { - net_trace!("packet IP address not for this interface"); + net_trace!("Rejecting IPv6 packet; no matching routes"); + return None; } } @@ -230,7 +242,7 @@ impl InterfaceInner { let handled_by_raw_socket = false; #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] - if ipv6_repr.dst_addr.is_unicast() { + if ipv6_repr.dst_addr.x_is_unicast() { self.neighbor_cache.reset_expiry_if_existing( IpAddress::Ipv6(ipv6_repr.src_addr), source_hardware_addr, @@ -288,12 +300,13 @@ impl InterfaceInner { Ipv6OptionFailureType::DiscardSendAll => { return HopByHopResponse::Discard(param_problem()); } - Ipv6OptionFailureType::DiscardSendUnicast - if !ipv6_repr.dst_addr.is_multicast() => - { - return HopByHopResponse::Discard(param_problem()); + Ipv6OptionFailureType::DiscardSendUnicast => { + if !ipv6_repr.dst_addr.is_multicast() { + return HopByHopResponse::Discard(param_problem()); + } else { + return HopByHopResponse::Discard(None); + } } - _ => unreachable!(), } } } @@ -435,7 +448,7 @@ impl InterfaceInner { let ip_addr = ip_repr.src_addr.into(); if let Some(lladdr) = lladdr { let lladdr = check!(lladdr.parse(self.caps.medium)); - if !lladdr.is_unicast() || !target_addr.is_unicast() { + if !lladdr.is_unicast() || !target_addr.x_is_unicast() { return None; } if flags.contains(NdiscNeighborFlags::OVERRIDE) @@ -453,7 +466,7 @@ impl InterfaceInner { } => { if let Some(lladdr) = lladdr { let lladdr = check!(lladdr.parse(self.caps.medium)); - if !lladdr.is_unicast() || !target_addr.is_unicast() { + if !lladdr.is_unicast() || !target_addr.x_is_unicast() { return None; } self.neighbor_cache @@ -491,7 +504,7 @@ impl InterfaceInner { let src_addr = ipv6_repr.dst_addr; let dst_addr = ipv6_repr.src_addr; - let src_addr = if src_addr.is_unicast() { + let src_addr = if src_addr.x_is_unicast() { src_addr } else { self.get_source_address_ipv6(&dst_addr) @@ -523,7 +536,7 @@ impl InterfaceInner { // Per [RFC 3810 § 5.2.14], all MLDv2 reports are sent to ff02::16. // [RFC 3810 § 5.2.14]: https://tools.ietf.org/html/rfc3810#section-5.2.14 - let dst_addr = Ipv6Address::LINK_LOCAL_ALL_MLDV2_ROUTERS; + let dst_addr = IPV6_LINK_LOCAL_ALL_MLDV2_ROUTERS; // Create a dummy IPv6 extension header so we can calculate the total length of the packet. // The actual extension header will be created later by Packet::emit_payload(). diff --git a/src/iface/interface/mod.rs b/src/iface/interface/mod.rs index 8ff4aad56..a69ed71f7 100644 --- a/src/iface/interface/mod.rs +++ b/src/iface/interface/mod.rs @@ -845,12 +845,12 @@ impl InterfaceInner { match addr { #[cfg(feature = "proto-ipv4")] - IpAddress::Ipv4(key) => key == Ipv4Address::MULTICAST_ALL_SYSTEMS, + IpAddress::Ipv4(key) => key == IPV4_MULTICAST_ALL_SYSTEMS, #[cfg(feature = "proto-rpl")] - IpAddress::Ipv6(Ipv6Address::LINK_LOCAL_ALL_RPL_NODES) => true, + IpAddress::Ipv6(IPV6_LINK_LOCAL_ALL_RPL_NODES) => true, #[cfg(feature = "proto-ipv6")] IpAddress::Ipv6(key) => { - key == Ipv6Address::LINK_LOCAL_ALL_NODES || self.has_solicited_node(key) + key == IPV6_LINK_LOCAL_ALL_NODES || self.has_solicited_node(key) } #[allow(unreachable_patterns)] _ => false, @@ -1002,30 +1002,35 @@ impl InterfaceInner { } if dst_addr.is_multicast() { - let b = dst_addr.as_bytes(); let hardware_addr = match *dst_addr { #[cfg(feature = "proto-ipv4")] - IpAddress::Ipv4(_addr) => match self.caps.medium { + IpAddress::Ipv4(addr) => match self.caps.medium { #[cfg(feature = "medium-ethernet")] - Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[ - 0x01, - 0x00, - 0x5e, - b[1] & 0x7F, - b[2], - b[3], - ])), + Medium::Ethernet => { + let b = addr.octets(); + HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[ + 0x01, + 0x00, + 0x5e, + b[1] & 0x7F, + b[2], + b[3], + ])) + } #[cfg(feature = "medium-ieee802154")] Medium::Ieee802154 => unreachable!(), #[cfg(feature = "medium-ip")] Medium::Ip => unreachable!(), }, #[cfg(feature = "proto-ipv6")] - IpAddress::Ipv6(_addr) => match self.caps.medium { + IpAddress::Ipv6(addr) => match self.caps.medium { #[cfg(feature = "medium-ethernet")] - Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[ - 0x33, 0x33, b[12], b[13], b[14], b[15], - ])), + Medium::Ethernet => { + let b = addr.octets(); + HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[ + 0x33, 0x33, b[12], b[13], b[14], b[15], + ])) + } #[cfg(feature = "medium-ieee802154")] Medium::Ieee802154 => { // Not sure if this is correct @@ -1198,8 +1203,8 @@ impl InterfaceInner { }; // Emit function for the IP header and payload. - let emit_ip = |repr: &IpRepr, mut tx_buffer: &mut [u8]| { - repr.emit(&mut tx_buffer, &self.caps.checksum); + let emit_ip = |repr: &IpRepr, tx_buffer: &mut [u8]| { + repr.emit(&mut *tx_buffer, &self.caps.checksum); let payload = &mut tx_buffer[repr.header_len()..]; packet.emit_payload(repr, payload, &caps) diff --git a/src/iface/interface/multicast.rs b/src/iface/interface/multicast.rs index 7542a12f4..68b1c7750 100644 --- a/src/iface/interface/multicast.rs +++ b/src/iface/interface/multicast.rs @@ -334,9 +334,7 @@ impl InterfaceInner { max_resp_time, } => { // General query - if group_addr.is_unspecified() - && ipv4_repr.dst_addr == Ipv4Address::MULTICAST_ALL_SYSTEMS - { + if group_addr.is_unspecified() && ipv4_repr.dst_addr == IPV4_MULTICAST_ALL_SYSTEMS { let ipv4_multicast_group_count = self .multicast .groups @@ -418,7 +416,7 @@ impl InterfaceInner { Packet::new_ipv4( Ipv4Repr { src_addr: iface_addr, - dst_addr: Ipv4Address::MULTICAST_ALL_ROUTERS, + dst_addr: IPV4_MULTICAST_ALL_ROUTERS, next_header: IpProtocol::Igmp, payload_len: igmp_repr.buffer_len(), hop_limit: 1, diff --git a/src/iface/interface/sixlowpan.rs b/src/iface/interface/sixlowpan.rs index 5cdfa3315..d5e3cafb8 100644 --- a/src/iface/interface/sixlowpan.rs +++ b/src/iface/interface/sixlowpan.rs @@ -114,6 +114,15 @@ impl InterfaceInner { // unless we have a complete one after processing this fragment. let frag = check!(SixlowpanFragPacket::new_checked(payload)); + // From RFC 4944 § 5.3: "The value of datagram_size SHALL be 40 octets more than the value + // of Payload Length in the IPv6 header of the packet." + // We should check that this is true, otherwise `buffer.split_at_mut(40)` will panic, since + // we assume that the decompressed packet is at least 40 bytes. + if frag.datagram_size() < 40 { + net_debug!("6LoWPAN: fragment size too small"); + return None; + } + // The key specifies to which 6LoWPAN fragment it belongs too. // It is based on the link layer addresses, the tag and the size. let key = FragKey::Sixlowpan(frag.get_key(ieee802154_repr)); @@ -548,7 +557,8 @@ impl InterfaceInner { /// - total size: the size of a compressed IPv6 packet /// - compressed header size: the size of the compressed headers /// - uncompressed header size: the size of the headers that are not compressed - /// They are returned as a tuple in the same order. + /// + /// They are returned as a tuple in the same order. fn compressed_packet_size( packet: &PacketV6, ieee_repr: &Ieee802154Repr, diff --git a/src/iface/interface/tests/ipv4.rs b/src/iface/interface/tests/ipv4.rs index 41e35301c..d3b8c61e8 100644 --- a/src/iface/interface/tests/ipv4.rs +++ b/src/iface/interface/tests/ipv4.rs @@ -72,7 +72,7 @@ fn test_no_icmp_no_unicast(#[case] medium: Medium) { // this should not trigger and Destination Unreachable // response. See RFC 1122 § 3.2.2. let repr = IpRepr::Ipv4(Ipv4Repr { - src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]), + src_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x01), dst_addr: Ipv4Address::BROADCAST, next_header: IpProtocol::Unknown(0x0c), payload_len: 0, @@ -110,8 +110,8 @@ fn test_icmp_error_no_payload(#[case] medium: Medium) { // Unknown Ipv4 Protocol with no payload let repr = IpRepr::Ipv4(Ipv4Repr { - src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]), - dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]), + src_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x02), + dst_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x01), next_header: IpProtocol::Unknown(0x0c), payload_len: 0, hop_limit: 0x40, @@ -126,8 +126,8 @@ fn test_icmp_error_no_payload(#[case] medium: Medium) { let icmp_repr = Icmpv4Repr::DstUnreachable { reason: Icmpv4DstUnreachable::ProtoUnreachable, header: Ipv4Repr { - src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]), - dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]), + src_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x02), + dst_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x01), next_header: IpProtocol::Unknown(12), payload_len: 0, hop_limit: 64, @@ -137,8 +137,8 @@ fn test_icmp_error_no_payload(#[case] medium: Medium) { let expected_repr = Packet::new_ipv4( Ipv4Repr { - src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]), - dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]), + src_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x01), + dst_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x02), next_header: IpProtocol::Icmp, payload_len: icmp_repr.buffer_len(), hop_limit: 64, @@ -170,62 +170,70 @@ fn test_local_subnet_broadcasts(#[case] medium: Medium) { let (mut iface, _, _device) = setup(medium); iface.update_ip_addrs(|addrs| { addrs.iter_mut().next().map(|addr| { - *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 1, 23]), 24)); + *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address::new(192, 168, 1, 23), 24)); }); }); assert!(iface .inner - .is_broadcast_v4(Ipv4Address([255, 255, 255, 255]))); + .is_broadcast_v4(Ipv4Address::new(255, 255, 255, 255))); assert!(!iface .inner - .is_broadcast_v4(Ipv4Address([255, 255, 255, 254]))); - assert!(iface.inner.is_broadcast_v4(Ipv4Address([192, 168, 1, 255]))); - assert!(!iface.inner.is_broadcast_v4(Ipv4Address([192, 168, 1, 254]))); + .is_broadcast_v4(Ipv4Address::new(255, 255, 255, 254))); + assert!(iface + .inner + .is_broadcast_v4(Ipv4Address::new(192, 168, 1, 255))); + assert!(!iface + .inner + .is_broadcast_v4(Ipv4Address::new(192, 168, 1, 254))); iface.update_ip_addrs(|addrs| { addrs.iter_mut().next().map(|addr| { - *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 23, 24]), 16)); + *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address::new(192, 168, 23, 24), 16)); }); }); assert!(iface .inner - .is_broadcast_v4(Ipv4Address([255, 255, 255, 255]))); + .is_broadcast_v4(Ipv4Address::new(255, 255, 255, 255))); assert!(!iface .inner - .is_broadcast_v4(Ipv4Address([255, 255, 255, 254]))); + .is_broadcast_v4(Ipv4Address::new(255, 255, 255, 254))); assert!(!iface .inner - .is_broadcast_v4(Ipv4Address([192, 168, 23, 255]))); + .is_broadcast_v4(Ipv4Address::new(192, 168, 23, 255))); assert!(!iface .inner - .is_broadcast_v4(Ipv4Address([192, 168, 23, 254]))); + .is_broadcast_v4(Ipv4Address::new(192, 168, 23, 254))); assert!(!iface .inner - .is_broadcast_v4(Ipv4Address([192, 168, 255, 254]))); + .is_broadcast_v4(Ipv4Address::new(192, 168, 255, 254))); assert!(iface .inner - .is_broadcast_v4(Ipv4Address([192, 168, 255, 255]))); + .is_broadcast_v4(Ipv4Address::new(192, 168, 255, 255))); iface.update_ip_addrs(|addrs| { addrs.iter_mut().next().map(|addr| { - *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 23, 24]), 8)); + *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address::new(192, 168, 23, 24), 8)); }); }); assert!(iface .inner - .is_broadcast_v4(Ipv4Address([255, 255, 255, 255]))); + .is_broadcast_v4(Ipv4Address::new(255, 255, 255, 255))); assert!(!iface .inner - .is_broadcast_v4(Ipv4Address([255, 255, 255, 254]))); - assert!(!iface.inner.is_broadcast_v4(Ipv4Address([192, 23, 1, 255]))); - assert!(!iface.inner.is_broadcast_v4(Ipv4Address([192, 23, 1, 254]))); + .is_broadcast_v4(Ipv4Address::new(255, 255, 255, 254))); assert!(!iface .inner - .is_broadcast_v4(Ipv4Address([192, 255, 255, 254]))); + .is_broadcast_v4(Ipv4Address::new(192, 23, 1, 255))); + assert!(!iface + .inner + .is_broadcast_v4(Ipv4Address::new(192, 23, 1, 254))); + assert!(!iface + .inner + .is_broadcast_v4(Ipv4Address::new(192, 255, 255, 254))); assert!(iface .inner - .is_broadcast_v4(Ipv4Address([192, 255, 255, 255]))); + .is_broadcast_v4(Ipv4Address::new(192, 255, 255, 255))); } #[rstest] @@ -250,8 +258,8 @@ fn test_icmp_error_port_unreachable(#[case] medium: Medium) { }; let ip_repr = IpRepr::Ipv4(Ipv4Repr { - src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]), - dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]), + src_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x02), + dst_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x01), next_header: IpProtocol::Udp, payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(), hop_limit: 64, @@ -274,8 +282,8 @@ fn test_icmp_error_port_unreachable(#[case] medium: Medium) { let icmp_repr = Icmpv4Repr::DstUnreachable { reason: Icmpv4DstUnreachable::PortUnreachable, header: Ipv4Repr { - src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]), - dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]), + src_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x02), + dst_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x01), next_header: IpProtocol::Udp, payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(), hop_limit: 64, @@ -284,8 +292,8 @@ fn test_icmp_error_port_unreachable(#[case] medium: Medium) { }; let expected_repr = Packet::new_ipv4( Ipv4Repr { - src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]), - dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]), + src_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x01), + dst_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x02), next_header: IpProtocol::Icmp, payload_len: icmp_repr.buffer_len(), hop_limit: 64, @@ -303,7 +311,7 @@ fn test_icmp_error_port_unreachable(#[case] medium: Medium) { ); let ip_repr = IpRepr::Ipv4(Ipv4Repr { - src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]), + src_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x02), dst_addr: Ipv4Address::BROADCAST, next_header: IpProtocol::Udp, payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(), @@ -346,7 +354,7 @@ fn test_handle_ipv4_broadcast(#[case] medium: Medium) { let (mut iface, mut sockets, _device) = setup(medium); let our_ipv4_addr = iface.ipv4_addr().unwrap(); - let src_ipv4_addr = Ipv4Address([127, 0, 0, 2]); + let src_ipv4_addr = Ipv4Address::new(127, 0, 0, 2); // ICMPv4 echo request let icmpv4_data: [u8; 4] = [0xaa, 0x00, 0x00, 0xff]; @@ -415,8 +423,8 @@ fn test_handle_valid_arp_request(#[case] medium: Medium) { let mut eth_bytes = vec![0u8; 42]; - let local_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x01]); - let remote_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x02]); + let local_ip_addr = Ipv4Address::new(0x7f, 0x00, 0x00, 0x01); + let remote_ip_addr = Ipv4Address::new(0x7f, 0x00, 0x00, 0x02); let local_hw_addr = EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]); let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]); @@ -471,7 +479,7 @@ fn test_handle_other_arp_request(#[case] medium: Medium) { let mut eth_bytes = vec![0u8; 42]; - let remote_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x02]); + let remote_ip_addr = Ipv4Address::new(0x7f, 0x00, 0x00, 0x02); let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]); let repr = ArpRepr::EthernetIpv4 { @@ -479,7 +487,7 @@ fn test_handle_other_arp_request(#[case] medium: Medium) { source_hardware_addr: remote_hw_addr, source_protocol_addr: remote_ip_addr, target_hardware_addr: EthernetAddress::default(), - target_protocol_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x03]), + target_protocol_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x03), }; let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes); @@ -519,8 +527,8 @@ fn test_arp_flush_after_update_ip(#[case] medium: Medium) { let mut eth_bytes = vec![0u8; 42]; - let local_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x01]); - let remote_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x02]); + let local_ip_addr = Ipv4Address::new(0x7f, 0x00, 0x00, 0x01); + let remote_ip_addr = Ipv4Address::new(0x7f, 0x00, 0x00, 0x02); let local_hw_addr = EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]); let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]); @@ -529,7 +537,7 @@ fn test_arp_flush_after_update_ip(#[case] medium: Medium) { source_hardware_addr: remote_hw_addr, source_protocol_addr: remote_ip_addr, target_hardware_addr: EthernetAddress::default(), - target_protocol_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]), + target_protocol_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x01), }; let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes); @@ -569,7 +577,7 @@ fn test_arp_flush_after_update_ip(#[case] medium: Medium) { ); // Update IP addrs to trigger ARP cache flush - let local_ip_addr_new = Ipv4Address([0x7f, 0x00, 0x00, 0x01]); + let local_ip_addr_new = Ipv4Address::new(0x7f, 0x00, 0x00, 0x01); iface.update_ip_addrs(|addrs| { addrs.iter_mut().next().map(|addr| { *addr = IpCidr::Ipv4(Ipv4Cidr::new(local_ip_addr_new, 24)); @@ -746,7 +754,7 @@ fn test_handle_igmp(#[case] medium: Medium) { assert_eq!(leaves.len(), 2); for (i, group_addr) in groups.iter().cloned().enumerate() { assert_eq!(leaves[i].0.next_header, IpProtocol::Igmp); - assert_eq!(leaves[i].0.dst_addr, Ipv4Address::MULTICAST_ALL_ROUTERS); + assert_eq!(leaves[i].0.dst_addr, IPV4_MULTICAST_ALL_ROUTERS); assert_eq!(leaves[i].1, IgmpRepr::LeaveGroup { group_addr }); } } @@ -771,8 +779,8 @@ fn test_raw_socket_no_reply(#[case] medium: Medium) { let raw_socket = raw::Socket::new(IpVersion::Ipv4, IpProtocol::Udp, rx_buffer, tx_buffer); sockets.add(raw_socket); - let src_addr = Ipv4Address([127, 0, 0, 2]); - let dst_addr = Ipv4Address([127, 0, 0, 1]); + let src_addr = Ipv4Address::new(127, 0, 0, 2); + let dst_addr = Ipv4Address::new(127, 0, 0, 1); const PAYLOAD_LEN: usize = 10; @@ -871,8 +879,8 @@ fn test_raw_socket_with_udp_socket(#[case] medium: Medium) { ); sockets.add(raw_socket); - let src_addr = Ipv4Address([127, 0, 0, 2]); - let dst_addr = Ipv4Address([127, 0, 0, 1]); + let src_addr = Ipv4Address::new(127, 0, 0, 2); + let dst_addr = Ipv4Address::new(127, 0, 0, 1); let udp_repr = UdpRepr { src_port: 67, @@ -951,8 +959,8 @@ fn test_icmp_reply_size(#[case] medium: Medium) { let (mut iface, mut sockets, _device) = setup(medium); - let src_addr = Ipv4Address([192, 168, 1, 1]); - let dst_addr = Ipv4Address([192, 168, 1, 2]); + let src_addr = Ipv4Address::new(192, 168, 1, 1); + let dst_addr = Ipv4Address::new(192, 168, 1, 2); // UDP packet that if not tructated will cause a icmp port unreachable reply // to exceed the minimum mtu bytes in length. diff --git a/src/iface/interface/tests/ipv6.rs b/src/iface/interface/tests/ipv6.rs index 620712c9c..adc058fd3 100644 --- a/src/iface/interface/tests/ipv6.rs +++ b/src/iface/interface/tests/ipv6.rs @@ -49,8 +49,8 @@ fn any_ip(#[case] medium: Medium) { parse_ipv6(&data), Ok(Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), - dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0003]), + src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002), + dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0003), hop_limit: 64, next_header: IpProtocol::Icmpv6, payload_len: 8, @@ -73,9 +73,7 @@ fn any_ip(#[case] medium: Medium) { Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0), 64, )), - via_router: IpAddress::Ipv6(Ipv6Address::from_parts(&[ - 0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001, - ])), + via_router: IpAddress::Ipv6(Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001)), preferred_until: None, expires_at: None, }) @@ -157,8 +155,8 @@ fn hop_by_hop_skip_with_icmp(#[case] medium: Medium) { let response = Some(Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]), - dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), + src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001), + dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002), hop_limit: 64, next_header: IpProtocol::Icmpv6, payload_len: 19, @@ -350,8 +348,8 @@ fn imcp_empty_echo_request(#[case] medium: Medium) { parse_ipv6(&data), Ok(Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), - dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]), + src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002), + dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001), hop_limit: 64, next_header: IpProtocol::Icmpv6, payload_len: 8, @@ -366,8 +364,8 @@ fn imcp_empty_echo_request(#[case] medium: Medium) { let response = Some(Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]), - dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), + src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001), + dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002), hop_limit: 64, next_header: IpProtocol::Icmpv6, payload_len: 8, @@ -411,8 +409,8 @@ fn icmp_echo_request(#[case] medium: Medium) { parse_ipv6(&data), Ok(Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), - dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]), + src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002), + dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001), hop_limit: 64, next_header: IpProtocol::Icmpv6, payload_len: 19, @@ -427,8 +425,8 @@ fn icmp_echo_request(#[case] medium: Medium) { let response = Some(Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]), - dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), + src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001), + dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002), hop_limit: 64, next_header: IpProtocol::Icmpv6, payload_len: 19, @@ -472,8 +470,8 @@ fn icmp_echo_reply_as_input(#[case] medium: Medium) { parse_ipv6(&data), Ok(Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), - dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]), + src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002), + dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001), hop_limit: 64, next_header: IpProtocol::Icmpv6, payload_len: 19, @@ -517,8 +515,8 @@ fn unknown_proto_with_multicast_dst_address(#[case] medium: Medium) { let response = Some(Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]), - dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), + src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001), + dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002), hop_limit: 64, next_header: IpProtocol::Icmpv6, payload_len: 48, @@ -527,8 +525,8 @@ fn unknown_proto_with_multicast_dst_address(#[case] medium: Medium) { reason: Icmpv6ParamProblem::UnrecognizedNxtHdr, pointer: 40, header: Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), - dst_addr: Ipv6Address::from_parts(&[0xff02, 0, 0, 0, 0, 0, 0, 0x0001]), + src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002), + dst_addr: Ipv6Address::new(0xff02, 0, 0, 0, 0, 0, 0, 0x0001), hop_limit: 64, next_header: IpProtocol::Unknown(0x0c), payload_len: 0, @@ -567,8 +565,8 @@ fn unknown_proto(#[case] medium: Medium) { let response = Some(Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]), - dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), + src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001), + dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002), hop_limit: 64, next_header: IpProtocol::Icmpv6, payload_len: 48, @@ -577,8 +575,8 @@ fn unknown_proto(#[case] medium: Medium) { reason: Icmpv6ParamProblem::UnrecognizedNxtHdr, pointer: 40, header: Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), - dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]), + src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002), + dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001), hop_limit: 64, next_header: IpProtocol::Unknown(0x0c), payload_len: 0, @@ -616,15 +614,15 @@ fn ndsic_neighbor_advertisement_ethernet(#[case] medium: Medium) { parse_ipv6(&data), Ok(Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), - dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]), + src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002), + dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001), hop_limit: 255, next_header: IpProtocol::Icmpv6, payload_len: 32, }, IpPayload::Icmpv6(Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert { flags: NdiscNeighborFlags::SOLICITED, - target_addr: Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0, 0, 0, 0x0002]), + target_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x0002), lladdr: Some(RawHardwareAddress::from_bytes(&[0, 0, 0, 0, 0, 1])), })) )) @@ -646,7 +644,7 @@ fn ndsic_neighbor_advertisement_ethernet(#[case] medium: Medium) { assert_eq!( iface.inner.neighbor_cache.lookup( - &IpAddress::Ipv6(Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002])), + &IpAddress::Ipv6(Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002)), iface.inner.now, ), NeighborAnswer::Found(HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[ @@ -671,15 +669,15 @@ fn ndsic_neighbor_advertisement_ethernet_multicast_addr(#[case] medium: Medium) parse_ipv6(&data), Ok(Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), - dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]), + src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002), + dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001), hop_limit: 255, next_header: IpProtocol::Icmpv6, payload_len: 32, }, IpPayload::Icmpv6(Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert { flags: NdiscNeighborFlags::SOLICITED, - target_addr: Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0, 0, 0, 0x0002]), + target_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x0002), lladdr: Some(RawHardwareAddress::from_bytes(&[ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ])), @@ -703,7 +701,7 @@ fn ndsic_neighbor_advertisement_ethernet_multicast_addr(#[case] medium: Medium) assert_eq!( iface.inner.neighbor_cache.lookup( - &IpAddress::Ipv6(Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002])), + &IpAddress::Ipv6(Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002)), iface.inner.now, ), NeighborAnswer::NotFound, @@ -726,15 +724,15 @@ fn ndsic_neighbor_advertisement_ieee802154(#[case] medium: Medium) { parse_ipv6(&data), Ok(Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]), - dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]), + src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002), + dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001), hop_limit: 255, next_header: IpProtocol::Icmpv6, payload_len: 40, }, IpPayload::Icmpv6(Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert { flags: NdiscNeighborFlags::SOLICITED, - target_addr: Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0, 0, 0, 0x0002]), + target_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x0002), lladdr: Some(RawHardwareAddress::from_bytes(&[0, 0, 0, 0, 0, 0, 0, 1])), })) )) @@ -756,7 +754,7 @@ fn ndsic_neighbor_advertisement_ieee802154(#[case] medium: Medium) { assert_eq!( iface.inner.neighbor_cache.lookup( - &IpAddress::Ipv6(Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002])), + &IpAddress::Ipv6(Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002)), iface.inner.now, ), NeighborAnswer::Found(HardwareAddress::Ieee802154(Ieee802154Address::from_bytes( @@ -1004,8 +1002,8 @@ fn get_source_address() { Ipv6Address::new(0x2001, 0x0db9, 0x0003, 0, 0, 0, 0, 2); assert_eq!( - iface.inner.get_source_address_ipv6(&Ipv6Address::LOOPBACK), - Ipv6Address::LOOPBACK + iface.inner.get_source_address_ipv6(&Ipv6Address::LOCALHOST), + Ipv6Address::LOCALHOST ); assert_eq!( @@ -1027,7 +1025,7 @@ fn get_source_address() { assert_eq!( iface .inner - .get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES), + .get_source_address_ipv6(&IPV6_LINK_LOCAL_ALL_NODES), OWN_LINK_LOCAL_ADDR ); assert_eq!( @@ -1056,7 +1054,7 @@ fn get_source_address() { OWN_UNIQUE_LOCAL_ADDR1 ); assert_eq!( - iface.get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES), + iface.get_source_address_ipv6(&IPV6_LINK_LOCAL_ALL_NODES), OWN_LINK_LOCAL_ADDR ); assert_eq!( @@ -1102,8 +1100,8 @@ fn get_source_address_only_link_local() { Ipv6Address::new(0x2001, 0x0db9, 0x0003, 0, 0, 0, 0, 2); assert_eq!( - iface.inner.get_source_address_ipv6(&Ipv6Address::LOOPBACK), - Ipv6Address::LOOPBACK + iface.inner.get_source_address_ipv6(&Ipv6Address::LOCALHOST), + Ipv6Address::LOCALHOST ); assert_eq!( @@ -1125,7 +1123,7 @@ fn get_source_address_only_link_local() { assert_eq!( iface .inner - .get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES), + .get_source_address_ipv6(&IPV6_LINK_LOCAL_ALL_NODES), OWN_LINK_LOCAL_ADDR ); assert_eq!( @@ -1154,7 +1152,7 @@ fn get_source_address_only_link_local() { OWN_LINK_LOCAL_ADDR ); assert_eq!( - iface.get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES), + iface.get_source_address_ipv6(&IPV6_LINK_LOCAL_ALL_NODES), OWN_LINK_LOCAL_ADDR ); assert_eq!( @@ -1193,68 +1191,68 @@ fn get_source_address_empty_interface() { Ipv6Address::new(0x2001, 0x0db9, 0x0003, 0, 0, 0, 0, 2); assert_eq!( - iface.inner.get_source_address_ipv6(&Ipv6Address::LOOPBACK), - Ipv6Address::LOOPBACK + iface.inner.get_source_address_ipv6(&Ipv6Address::LOCALHOST), + Ipv6Address::LOCALHOST ); assert_eq!( iface.inner.get_source_address_ipv6(&LINK_LOCAL_ADDR), - Ipv6Address::LOOPBACK + Ipv6Address::LOCALHOST ); assert_eq!( iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR1), - Ipv6Address::LOOPBACK + Ipv6Address::LOCALHOST ); assert_eq!( iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR2), - Ipv6Address::LOOPBACK + Ipv6Address::LOCALHOST ); assert_eq!( iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR3), - Ipv6Address::LOOPBACK + Ipv6Address::LOCALHOST ); assert_eq!( iface .inner - .get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES), - Ipv6Address::LOOPBACK + .get_source_address_ipv6(&IPV6_LINK_LOCAL_ALL_NODES), + Ipv6Address::LOCALHOST ); assert_eq!( iface.inner.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR1), - Ipv6Address::LOOPBACK + Ipv6Address::LOCALHOST ); assert_eq!( iface.inner.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR2), - Ipv6Address::LOOPBACK + Ipv6Address::LOCALHOST ); assert_eq!( iface.get_source_address_ipv6(&LINK_LOCAL_ADDR), - Ipv6Address::LOOPBACK + Ipv6Address::LOCALHOST ); assert_eq!( iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR1), - Ipv6Address::LOOPBACK + Ipv6Address::LOCALHOST ); assert_eq!( iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR2), - Ipv6Address::LOOPBACK + Ipv6Address::LOCALHOST ); assert_eq!( iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR3), - Ipv6Address::LOOPBACK + Ipv6Address::LOCALHOST ); assert_eq!( - iface.get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES), - Ipv6Address::LOOPBACK + iface.get_source_address_ipv6(&IPV6_LINK_LOCAL_ALL_NODES), + Ipv6Address::LOCALHOST ); assert_eq!( iface.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR1), - Ipv6Address::LOOPBACK + Ipv6Address::LOCALHOST ); assert_eq!( iface.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR2), - Ipv6Address::LOOPBACK + Ipv6Address::LOCALHOST ); } @@ -1292,8 +1290,8 @@ fn test_join_ipv6_multicast_group(#[case] medium: Medium) { let (mut iface, mut sockets, mut device) = setup(medium); let groups = [ - Ipv6Address::from_parts(&[0xff05, 0, 0, 0, 0, 0, 0, 0x00fb]), - Ipv6Address::from_parts(&[0xff0e, 0, 0, 0, 0, 0, 0, 0x0017]), + Ipv6Address::new(0xff05, 0, 0, 0, 0, 0, 0, 0x00fb), + Ipv6Address::new(0xff0e, 0, 0, 0, 0, 0, 0, 0x0017), ]; let timestamp = Instant::from_millis(0); @@ -1302,9 +1300,9 @@ fn test_join_ipv6_multicast_group(#[case] medium: Medium) { iface.join_multicast_group(group).unwrap(); assert!(iface.has_multicast_group(group)); } - assert!(iface.has_multicast_group(Ipv6Address::LINK_LOCAL_ALL_NODES)); + assert!(iface.has_multicast_group(IPV6_LINK_LOCAL_ALL_NODES)); iface.poll(timestamp, &mut device, &mut sockets); - assert!(iface.has_multicast_group(Ipv6Address::LINK_LOCAL_ALL_NODES)); + assert!(iface.has_multicast_group(IPV6_LINK_LOCAL_ALL_NODES)); let reports = recv_icmpv6(&mut device, timestamp); assert_eq!(reports.len(), 2); diff --git a/src/iface/interface/tests/mod.rs b/src/iface/interface/tests/mod.rs index fe98ddd3d..1d70f88c2 100644 --- a/src/iface/interface/tests/mod.rs +++ b/src/iface/interface/tests/mod.rs @@ -98,7 +98,7 @@ fn test_handle_udp_broadcast(#[case] medium: Medium) { #[cfg(feature = "proto-ipv6")] let ip_repr = IpRepr::Ipv6(Ipv6Repr { src_addr: src_ip, - dst_addr: Ipv6Address::LINK_LOCAL_ALL_NODES, + dst_addr: IPV6_LINK_LOCAL_ALL_NODES, next_header: IpProtocol::Udp, payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(), hop_limit: 0x40, diff --git a/src/iface/interface/tests/sixlowpan.rs b/src/iface/interface/tests/sixlowpan.rs index 14a4c46ae..56e1fb8ca 100644 --- a/src/iface/interface/tests/sixlowpan.rs +++ b/src/iface/interface/tests/sixlowpan.rs @@ -40,8 +40,8 @@ fn icmp_echo_request(#[case] medium: Medium) { let response = Some(Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0x180b, 0x4242, 0x4242, 0x4242]), - dst_addr: Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0x241c, 0x2957, 0x34a6, 0x3a62]), + src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0x180b, 0x4242, 0x4242, 0x4242), + dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0x241c, 0x2957, 0x34a6, 0x3a62), hop_limit: 64, next_header: IpProtocol::Icmpv6, payload_len: 64, @@ -61,7 +61,7 @@ fn icmp_echo_request(#[case] medium: Medium) { let (mut iface, mut sockets, _device) = setup(medium); iface.update_ip_addrs(|ips| { ips.push(IpCidr::Ipv6(Ipv6Cidr::new( - Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0x180b, 0x4242, 0x4242, 0x4242]), + Ipv6Address::new(0xfe80, 0, 0, 0, 0x180b, 0x4242, 0x4242, 0x4242), 10, ))) .unwrap(); @@ -99,7 +99,7 @@ fn test_echo_request_sixlowpan_128_bytes() { let now = iface.inner.now(); iface.inner.neighbor_cache.fill( - Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0x2, 0, 0, 0, 0, 0, 0, 0]).into(), + Ipv6Address::new(0xfe80, 0, 0, 0, 0x0200, 0, 0, 0).into(), HardwareAddress::Ieee802154(Ieee802154Address::default()), now, ); @@ -148,17 +148,11 @@ fn test_echo_request_sixlowpan_128_bytes() { assert_eq!( request_first_part_iphc_repr.src_addr, - Ipv6Address([ - 0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42, 0xb, - 0x1a, - ]), + Ipv6Address::new(0xfe80, 0, 0, 0, 0x4042, 0x4242, 0x4242, 0x0b1a), ); assert_eq!( request_first_part_iphc_repr.dst_addr, - Ipv6Address([ - 0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x92, 0xfc, 0x48, 0xc2, 0xa4, 0x41, 0xfc, - 0x76, - ]), + Ipv6Address::new(0xfe80, 0, 0, 0, 0x92fc, 0x48c2, 0xa441, 0xfc76), ); let request_second_part = [ @@ -206,14 +200,8 @@ fn test_echo_request_sixlowpan_128_bytes() { result, Some(Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address([ - 0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x92, 0xfc, 0x48, 0xc2, 0xa4, 0x41, - 0xfc, 0x76, - ]), - dst_addr: Ipv6Address([ - 0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42, - 0xb, 0x1a, - ]), + src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0x92fc, 0x48c2, 0xa441, 0xfc76), + dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0x4042, 0x4242, 0x4242, 0x0b1a), next_header: IpProtocol::Icmpv6, payload_len: 136, hop_limit: 64, @@ -227,9 +215,9 @@ fn test_echo_request_sixlowpan_128_bytes() { ); iface.inner.neighbor_cache.fill( - IpAddress::Ipv6(Ipv6Address([ - 0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42, 0xb, 0x1a, - ])), + IpAddress::Ipv6(Ipv6Address::new( + 0xfe80, 0, 0, 0, 0x4042, 0x4242, 0x4242, 0x0b1a, + )), HardwareAddress::Ieee802154(Ieee802154Address::default()), Instant::now(), ); @@ -370,17 +358,12 @@ In at rhoncus tortor. Cras blandit tellus diam, varius vestibulum nibh commodo n &udp_data[..], udp::UdpMetadata { local_address: Some( - Ipv6Address([ - 0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x92, 0xfc, 0x48, 0xc2, 0xa4, - 0x41, 0xfc, 0x76, - ]) - .into() + Ipv6Address::new(0xfe80, 0, 0, 0, 0x92fc, 0x48c2, 0xa441, 0xfc76).into() ), ..IpEndpoint { - addr: IpAddress::Ipv6(Ipv6Address([ - 0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x42, 0x42, 0x42, 0x42, - 0x42, 0xb, 0x1a, - ])), + addr: IpAddress::Ipv6(Ipv6Address::new( + 0xfe80, 0, 0, 0, 0x4042, 0x4242, 0x4242, 0x0b1a + )), port: 54217, } .into() @@ -395,8 +378,8 @@ In at rhoncus tortor. Cras blandit tellus diam, varius vestibulum nibh commodo n PacketMeta::default(), Packet::new_ipv6( Ipv6Repr { - src_addr: Ipv6Address::default(), - dst_addr: Ipv6Address::default(), + src_addr: Ipv6Address::UNSPECIFIED, + dst_addr: Ipv6Address::UNSPECIFIED, next_header: IpProtocol::Udp, payload_len: udp_data.len(), hop_limit: 64, diff --git a/src/iface/route.rs b/src/iface/route.rs index 123c6950c..f14a57d39 100644 --- a/src/iface/route.rs +++ b/src/iface/route.rs @@ -172,45 +172,34 @@ mod test { #[cfg(feature = "proto-ipv6")] mod mock { use super::super::*; - pub const ADDR_1A: Ipv6Address = - Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1]); - pub const ADDR_1B: Ipv6Address = - Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 13]); - pub const ADDR_1C: Ipv6Address = - Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 42]); + pub const ADDR_1A: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 2, 0, 0, 0, 1); + pub const ADDR_1B: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 2, 0, 0, 0, 13); + pub const ADDR_1C: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 2, 0, 0, 0, 42); pub fn cidr_1() -> Ipv6Cidr { - Ipv6Cidr::new( - Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]), - 64, - ) + Ipv6Cidr::new(Ipv6Address::new(0xfe80, 0, 0, 2, 0, 0, 0, 0), 64) } - pub const ADDR_2A: Ipv6Address = - Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 51, 100, 0, 0, 0, 0, 0, 0, 0, 1]); - pub const ADDR_2B: Ipv6Address = - Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 51, 100, 0, 0, 0, 0, 0, 0, 0, 21]); + pub const ADDR_2A: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0x3364, 0, 0, 0, 1); + pub const ADDR_2B: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0x3364, 0, 0, 0, 21); pub fn cidr_2() -> Ipv6Cidr { - Ipv6Cidr::new( - Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 51, 100, 0, 0, 0, 0, 0, 0, 0, 0]), - 64, - ) + Ipv6Cidr::new(Ipv6Address::new(0xfe80, 0, 0, 0x3364, 0, 0, 0, 0), 64) } } #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))] mod mock { use super::super::*; - pub const ADDR_1A: Ipv4Address = Ipv4Address([192, 0, 2, 1]); - pub const ADDR_1B: Ipv4Address = Ipv4Address([192, 0, 2, 13]); - pub const ADDR_1C: Ipv4Address = Ipv4Address([192, 0, 2, 42]); + pub const ADDR_1A: Ipv4Address = Ipv4Address::new(192, 0, 2, 1); + pub const ADDR_1B: Ipv4Address = Ipv4Address::new(192, 0, 2, 13); + pub const ADDR_1C: Ipv4Address = Ipv4Address::new(192, 0, 2, 42); pub fn cidr_1() -> Ipv4Cidr { - Ipv4Cidr::new(Ipv4Address([192, 0, 2, 0]), 24) + Ipv4Cidr::new(Ipv4Address::new(192, 0, 2, 0), 24) } - pub const ADDR_2A: Ipv4Address = Ipv4Address([198, 51, 100, 1]); - pub const ADDR_2B: Ipv4Address = Ipv4Address([198, 51, 100, 21]); + pub const ADDR_2A: Ipv4Address = Ipv4Address::new(198, 51, 100, 1); + pub const ADDR_2B: Ipv4Address = Ipv4Address::new(198, 51, 100, 21); pub fn cidr_2() -> Ipv4Cidr { - Ipv4Cidr::new(Ipv4Address([198, 51, 100, 0]), 24) + Ipv4Cidr::new(Ipv4Address::new(198, 51, 100, 0), 24) } } diff --git a/src/iface/rpl/of0.rs b/src/iface/rpl/of0.rs index 99e4d1f36..299938f8a 100644 --- a/src/iface/rpl/of0.rs +++ b/src/iface/rpl/of0.rs @@ -99,12 +99,11 @@ mod tests { let mut parents = ParentSet::default(); parents.add( - Ipv6Address::default(), - Parent::new(0, Rank::ROOT, Default::default(), Ipv6Address::default()), + Ipv6Address::UNSPECIFIED, + Parent::new(0, Rank::ROOT, Default::default(), Ipv6Address::UNSPECIFIED), ); - let mut address = Ipv6Address::default(); - address.0[15] = 1; + let address = Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, 1); parents.add( address, @@ -112,7 +111,7 @@ mod tests { 0, Rank::new(1024, DEFAULT_MIN_HOP_RANK_INCREASE), Default::default(), - Ipv6Address::default(), + Ipv6Address::UNSPECIFIED, ), ); @@ -122,7 +121,7 @@ mod tests { 0, Rank::ROOT, Default::default(), - Ipv6Address::default(), + Ipv6Address::UNSPECIFIED, )) ); } diff --git a/src/iface/rpl/parents.rs b/src/iface/rpl/parents.rs index 70d5a5e88..7d4d60e22 100644 --- a/src/iface/rpl/parents.rs +++ b/src/iface/rpl/parents.rs @@ -87,17 +87,17 @@ mod tests { fn add_parent() { let mut set = ParentSet::default(); set.add( - Default::default(), - Parent::new(0, Rank::ROOT, Default::default(), Default::default()), + Ipv6Address::UNSPECIFIED, + Parent::new(0, Rank::ROOT, Default::default(), Ipv6Address::UNSPECIFIED), ); assert_eq!( - set.find(&Default::default()), + set.find(&Ipv6Address::UNSPECIFIED), Some(&Parent::new( 0, Rank::ROOT, Default::default(), - Default::default() + Ipv6Address::UNSPECIFIED )) ); } @@ -107,11 +107,10 @@ mod tests { use super::super::consts::DEFAULT_MIN_HOP_RANK_INCREASE; let mut set = ParentSet::default(); - let mut last_address = Default::default(); + let mut last_address = Ipv6Address::UNSPECIFIED; for i in 0..RPL_PARENTS_BUFFER_COUNT { let i = i as u16; - let mut address = Ipv6Address::default(); - address.0[15] = i as u8; + let address = Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, i as _); last_address = address; set.add( @@ -137,8 +136,7 @@ mod tests { // This one is not added to the set, because its Rank is worse than any other parent in the // set. - let mut address = Ipv6Address::default(); - address.0[15] = 8; + let address = Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, 8); set.add( address, Parent::new( @@ -151,8 +149,7 @@ mod tests { assert_eq!(set.find(&address), None); /// This Parent has a better rank than the last one in the set. - let mut address = Ipv6Address::default(); - address.0[15] = 9; + let address = Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, 9); set.add( address, Parent::new( diff --git a/src/iface/rpl/relations.rs b/src/iface/rpl/relations.rs index da02a3cf9..c2972f2ec 100644 --- a/src/iface/rpl/relations.rs +++ b/src/iface/rpl/relations.rs @@ -73,11 +73,7 @@ mod tests { fn addresses(count: usize) -> Vec { (0..count) - .map(|i| { - let mut ip = Ipv6Address::default(); - ip.0[0] = i as u8; - ip - }) + .map(|i| Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, i as _)) .collect() } diff --git a/src/lib.rs b/src/lib.rs index 2e99c9576..8f2ba3b37 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,7 +65,7 @@ //! //! # Minimum Supported Rust Version (MSRV) //! -//! This crate is guaranteed to compile on stable Rust 1.77 and up with any valid set of features. +//! This crate is guaranteed to compile on stable Rust 1.80 and up with any valid set of features. //! It *might* compile on older versions but that may change in any new patch release. //! //! The exception is when using the `defmt` feature, in which case `defmt`'s MSRV applies, which diff --git a/src/macros.rs b/src/macros.rs index e899d24ec..3da0123be 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -132,7 +132,7 @@ macro_rules! get { #[cfg(feature = "proto-rpl")] macro_rules! set { ($buffer:expr, address: $address:ident, field: $field:expr $(,)?) => {{ - $buffer.as_mut()[$field].copy_from_slice($address.as_bytes()); + $buffer.as_mut()[$field].copy_from_slice(&$address.octets()); }}; ($buffer:expr, $value:ident, field: $field:expr $(,)?) => { diff --git a/src/parsers.rs b/src/parsers.rs index 16419ab5c..99ce28453 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -10,7 +10,7 @@ use core::str::FromStr; use crate::wire::EthernetAddress; use crate::wire::{IpAddress, IpCidr, IpEndpoint}; #[cfg(feature = "proto-ipv4")] -use crate::wire::{Ipv4Address, Ipv4Cidr}; +use crate::wire::{Ipv4Address, Ipv4AddressExt, Ipv4Cidr}; #[cfg(feature = "proto-ipv6")] use crate::wire::{Ipv6Address, Ipv6Cidr}; @@ -277,7 +277,7 @@ impl<'a> Parser<'a> { // end of the address. addr[8 - tail_idx..].copy_from_slice(&tail[..tail_idx]); - Ok(Ipv6Address::from_parts(&addr)) + Ok(Ipv6Address::from(addr)) } fn accept_ipv4_octets(&mut self) -> Result<[u8; 4]> { @@ -294,7 +294,7 @@ impl<'a> Parser<'a> { #[cfg(feature = "proto-ipv4")] fn accept_ipv4(&mut self) -> Result { let octets = self.accept_ipv4_octets()?; - Ok(Ipv4Address(octets)) + Ok(Ipv4Address::from_bytes(&octets)) } fn accept_ip(&mut self) -> Result { @@ -383,26 +383,6 @@ impl FromStr for EthernetAddress { } } -#[cfg(feature = "proto-ipv4")] -impl FromStr for Ipv4Address { - type Err = (); - - /// Parse a string representation of an IPv4 address. - fn from_str(s: &str) -> Result { - Parser::new(s).until_eof(|p| p.accept_ipv4()) - } -} - -#[cfg(feature = "proto-ipv6")] -impl FromStr for Ipv6Address { - type Err = (); - - /// Parse a string representation of an IPv6 address. - fn from_str(s: &str) -> Result { - Parser::new(s).until_eof(|p| p.accept_ipv6()) - } -} - impl FromStr for IpAddress { type Err = (); @@ -526,111 +506,13 @@ mod test { assert_eq!(EthernetAddress::from_str("02:00:00:00:00:0x"), Err(())); } - #[test] - #[cfg(feature = "proto-ipv4")] - fn test_ipv4() { - assert_eq!(Ipv4Address::from_str(""), Err(())); - assert_eq!( - Ipv4Address::from_str("1.2.3.4"), - Ok(Ipv4Address([1, 2, 3, 4])) - ); - assert_eq!( - Ipv4Address::from_str("001.2.3.4"), - Ok(Ipv4Address([1, 2, 3, 4])) - ); - assert_eq!(Ipv4Address::from_str("0001.2.3.4"), Err(())); - assert_eq!(Ipv4Address::from_str("999.2.3.4"), Err(())); - assert_eq!(Ipv4Address::from_str("1.2.3.4.5"), Err(())); - assert_eq!(Ipv4Address::from_str("1.2.3"), Err(())); - assert_eq!(Ipv4Address::from_str("1.2.3."), Err(())); - assert_eq!(Ipv4Address::from_str("1.2.3.4."), Err(())); - } - - #[test] - #[cfg(feature = "proto-ipv6")] - fn test_ipv6() { - // Obviously not valid - assert_eq!(Ipv6Address::from_str(""), Err(())); - assert_eq!( - Ipv6Address::from_str("fe80:0:0:0:0:0:0:1"), - Ok(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)) - ); - assert_eq!(Ipv6Address::from_str("::1"), Ok(Ipv6Address::LOOPBACK)); - assert_eq!(Ipv6Address::from_str("::"), Ok(Ipv6Address::UNSPECIFIED)); - assert_eq!( - Ipv6Address::from_str("fe80::1"), - Ok(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)) - ); - assert_eq!( - Ipv6Address::from_str("1234:5678::"), - Ok(Ipv6Address::new(0x1234, 0x5678, 0, 0, 0, 0, 0, 0)) - ); - assert_eq!( - Ipv6Address::from_str("1234:5678::8765:4321"), - Ok(Ipv6Address::new(0x1234, 0x5678, 0, 0, 0, 0, 0x8765, 0x4321)) - ); - // Two double colons in address - assert_eq!(Ipv6Address::from_str("1234:5678::1::1"), Err(())); - assert_eq!( - Ipv6Address::from_str("4444:333:22:1::4"), - Ok(Ipv6Address::new(0x4444, 0x0333, 0x0022, 0x0001, 0, 0, 0, 4)) - ); - assert_eq!( - Ipv6Address::from_str("1:1:1:1:1:1::"), - Ok(Ipv6Address::new(1, 1, 1, 1, 1, 1, 0, 0)) - ); - assert_eq!( - Ipv6Address::from_str("::1:1:1:1:1:1"), - Ok(Ipv6Address::new(0, 0, 1, 1, 1, 1, 1, 1)) - ); - assert_eq!(Ipv6Address::from_str("::1:1:1:1:1:1:1"), Err(())); - // Double colon appears too late indicating an address that is too long - assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1::"), Err(())); - // Section after double colon is too long for a valid address - assert_eq!(Ipv6Address::from_str("::1:1:1:1:1:1:1"), Err(())); - // Obviously too long - assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1:1:1"), Err(())); - // Address is too short - assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1"), Err(())); - // Long number - assert_eq!(Ipv6Address::from_str("::000001"), Err(())); - // IPv4-Mapped address - assert_eq!( - Ipv6Address::from_str("::ffff:192.168.1.1"), - Ok(Ipv6Address([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1 - ])) - ); - assert_eq!( - Ipv6Address::from_str("0:0:0:0:0:ffff:192.168.1.1"), - Ok(Ipv6Address([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1 - ])) - ); - assert_eq!( - Ipv6Address::from_str("0::ffff:192.168.1.1"), - Ok(Ipv6Address([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1 - ])) - ); - // Only ffff is allowed in position 6 when IPv4 mapped - assert_eq!(Ipv6Address::from_str("0:0:0:0:0:eeee:192.168.1.1"), Err(())); - // Positions 1-5 must be 0 when IPv4 mapped - assert_eq!(Ipv6Address::from_str("0:0:0:0:1:ffff:192.168.1.1"), Err(())); - assert_eq!(Ipv6Address::from_str("1::ffff:192.168.1.1"), Err(())); - // Out of range ipv4 octet - assert_eq!(Ipv6Address::from_str("0:0:0:0:0:ffff:256.168.1.1"), Err(())); - // Invalid hex in ipv4 octet - assert_eq!(Ipv6Address::from_str("0:0:0:0:0:ffff:c0.168.1.1"), Err(())); - } - #[test] #[cfg(feature = "proto-ipv4")] fn test_ip_ipv4() { assert_eq!(IpAddress::from_str(""), Err(())); assert_eq!( IpAddress::from_str("1.2.3.4"), - Ok(IpAddress::Ipv4(Ipv4Address([1, 2, 3, 4]))) + Ok(IpAddress::Ipv4(Ipv4Address::new(1, 2, 3, 4))) ); assert_eq!(IpAddress::from_str("x"), Err(())); } @@ -654,19 +536,19 @@ mod test { let tests = [ ( "127.0.0.1/8", - Ok(Ipv4Cidr::new(Ipv4Address([127, 0, 0, 1]), 8u8)), + Ok(Ipv4Cidr::new(Ipv4Address::new(127, 0, 0, 1), 8u8)), ), ( "192.168.1.1/24", - Ok(Ipv4Cidr::new(Ipv4Address([192, 168, 1, 1]), 24u8)), + Ok(Ipv4Cidr::new(Ipv4Address::new(192, 168, 1, 1), 24u8)), ), ( "8.8.8.8/32", - Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 32u8)), + Ok(Ipv4Cidr::new(Ipv4Address::new(8, 8, 8, 8), 32u8)), ), ( "8.8.8.8/0", - Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 0u8)), + Ok(Ipv4Cidr::new(Ipv4Address::new(8, 8, 8, 8), 0u8)), ), ("", Err(())), ("1", Err(())), @@ -698,7 +580,7 @@ mod test { 64u8, )), ), - ("::1/128", Ok(Ipv6Cidr::new(Ipv6Address::LOOPBACK, 128u8))), + ("::1/128", Ok(Ipv6Cidr::new(Ipv6Address::LOCALHOST, 128u8))), ("::/128", Ok(Ipv6Cidr::new(Ipv6Address::UNSPECIFIED, 128u8))), ( "fe80:0:0:0:0:0:0:1/64", diff --git a/src/phy/fault_injector.rs b/src/phy/fault_injector.rs index 6a9091004..39ad0882c 100644 --- a/src/phy/fault_injector.rs +++ b/src/phy/fault_injector.rs @@ -315,10 +315,10 @@ impl<'a, Tx: phy::TxToken> phy::TxToken for TxToken<'a, Tx> { return f(&mut self.junk[..len]); } - self.token.consume(len, |mut buf| { + self.token.consume(len, |buf| { if self.state.maybe(self.config.corrupt_pct) { net_trace!("tx: corrupting a packet"); - self.state.corrupt(&mut buf) + self.state.corrupt(&mut *buf); } f(buf) }) diff --git a/src/socket/dhcpv4.rs b/src/socket/dhcpv4.rs index b1b3cb583..72980a946 100644 --- a/src/socket/dhcpv4.rs +++ b/src/socket/dhcpv4.rs @@ -5,8 +5,9 @@ use crate::iface::Context; use crate::time::{Duration, Instant}; use crate::wire::dhcpv4::field as dhcpv4_field; use crate::wire::{ - DhcpMessageType, DhcpPacket, DhcpRepr, IpAddress, IpProtocol, Ipv4Address, Ipv4Cidr, Ipv4Repr, - UdpRepr, DHCP_CLIENT_PORT, DHCP_MAX_DNS_SERVER_COUNT, DHCP_SERVER_PORT, UDP_HEADER_LEN, + DhcpMessageType, DhcpPacket, DhcpRepr, IpAddress, IpProtocol, Ipv4Address, Ipv4AddressExt, + Ipv4Cidr, Ipv4Repr, UdpRepr, DHCP_CLIENT_PORT, DHCP_MAX_DNS_SERVER_COUNT, DHCP_SERVER_PORT, + UDP_HEADER_LEN, }; use crate::wire::{DhcpOption, HardwareAddress}; use heapless::Vec; @@ -365,7 +366,7 @@ impl<'a> Socket<'a> { match (&mut self.state, dhcp_repr.message_type) { (ClientState::Discovering(_state), DhcpMessageType::Offer) => { - if !dhcp_repr.your_ip.is_unicast() { + if !dhcp_repr.your_ip.x_is_unicast() { net_debug!("DHCP ignoring OFFER because your_ip is not unicast"); return; } @@ -461,7 +462,7 @@ impl<'a> Socket<'a> { } }; - if !dhcp_repr.your_ip.is_unicast() { + if !dhcp_repr.your_ip.x_is_unicast() { net_debug!("DHCP ignoring ACK because your_ip is not unicast"); return None; } @@ -482,7 +483,7 @@ impl<'a> Socket<'a> { .dns_servers .iter() .flatten() - .filter(|s| s.is_unicast()) + .filter(|s| s.x_is_unicast()) .for_each(|a| { // This will never produce an error, as both the arrays and `dns_servers` // have length DHCP_MAX_DNS_SERVER_COUNT @@ -880,14 +881,14 @@ mod test { const TXID: u32 = 0x12345678; - const MY_IP: Ipv4Address = Ipv4Address([192, 168, 1, 42]); - const SERVER_IP: Ipv4Address = Ipv4Address([192, 168, 1, 1]); - const DNS_IP_1: Ipv4Address = Ipv4Address([1, 1, 1, 1]); - const DNS_IP_2: Ipv4Address = Ipv4Address([1, 1, 1, 2]); - const DNS_IP_3: Ipv4Address = Ipv4Address([1, 1, 1, 3]); + const MY_IP: Ipv4Address = Ipv4Address::new(192, 168, 1, 42); + const SERVER_IP: Ipv4Address = Ipv4Address::new(192, 168, 1, 1); + const DNS_IP_1: Ipv4Address = Ipv4Address::new(1, 1, 1, 1); + const DNS_IP_2: Ipv4Address = Ipv4Address::new(1, 1, 1, 2); + const DNS_IP_3: Ipv4Address = Ipv4Address::new(1, 1, 1, 3); const DNS_IPS: &[Ipv4Address] = &[DNS_IP_1, DNS_IP_2, DNS_IP_3]; - const MASK_24: Ipv4Address = Ipv4Address([255, 255, 255, 0]); + const MASK_24: Ipv4Address = Ipv4Address::new(255, 255, 255, 0); const MY_MAC: EthernetAddress = EthernetAddress([0x02, 0x02, 0x02, 0x02, 0x02, 0x02]); diff --git a/src/socket/dns.rs b/src/socket/dns.rs index abb0f0caa..681cf10f2 100644 --- a/src/socket/dns.rs +++ b/src/socket/dns.rs @@ -22,13 +22,13 @@ const RETRANSMIT_TIMEOUT: Duration = Duration::from_millis(10_000); // Should ge #[cfg(feature = "proto-ipv6")] #[allow(unused)] -const MDNS_IPV6_ADDR: IpAddress = IpAddress::Ipv6(crate::wire::Ipv6Address([ - 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, -])); +const MDNS_IPV6_ADDR: IpAddress = IpAddress::Ipv6(crate::wire::Ipv6Address::new( + 0xff02, 0, 0, 0, 0, 0, 0, 0xfb, +)); #[cfg(feature = "proto-ipv4")] #[allow(unused)] -const MDNS_IPV4_ADDR: IpAddress = IpAddress::Ipv4(crate::wire::Ipv4Address([224, 0, 0, 251])); +const MDNS_IPV4_ADDR: IpAddress = IpAddress::Ipv4(crate::wire::Ipv4Address::new(224, 0, 0, 251)); /// Error returned by [`Socket::start_query`] #[derive(Debug, PartialEq, Eq, Clone, Copy)] diff --git a/src/socket/icmp.rs b/src/socket/icmp.rs index 85a34b1f1..dee3416a3 100644 --- a/src/socket/icmp.rs +++ b/src/socket/icmp.rs @@ -412,6 +412,16 @@ impl<'a> Socket<'a> { Ok((length, endpoint)) } + /// Return the amount of octets queued in the transmit buffer. + pub fn send_queue(&self) -> usize { + self.tx_buffer.payload_bytes_count() + } + + /// Return the amount of octets queued in the receive buffer. + pub fn recv_queue(&self) -> usize { + self.rx_buffer.payload_bytes_count() + } + /// Fitler determining whether the socket accepts a given ICMPv4 packet. /// Accepted packets are enqueued into the socket's receive buffer. #[cfg(feature = "proto-ipv4")] @@ -678,8 +688,8 @@ mod test_ipv4 { use super::tests_common::*; use crate::wire::{Icmpv4DstUnreachable, IpEndpoint, Ipv4Address}; - const REMOTE_IPV4: Ipv4Address = Ipv4Address([192, 168, 1, 2]); - const LOCAL_IPV4: Ipv4Address = Ipv4Address([192, 168, 1, 1]); + const REMOTE_IPV4: Ipv4Address = Ipv4Address::new(192, 168, 1, 2); + const LOCAL_IPV4: Ipv4Address = Ipv4Address::new(192, 168, 1, 1); const LOCAL_END_V4: IpEndpoint = IpEndpoint { addr: IpAddress::Ipv4(LOCAL_IPV4), port: LOCAL_PORT, @@ -711,7 +721,7 @@ mod test_ipv4 { fn test_send_unaddressable() { let mut socket = socket(buffer(0), buffer(1)); assert_eq!( - socket.send_slice(b"abcdef", IpAddress::Ipv4(Ipv4Address::default())), + socket.send_slice(b"abcdef", IpAddress::Ipv4(Ipv4Address::new(0, 0, 0, 0))), Err(SendError::Unaddressable) ); assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV4.into()), Ok(())); @@ -940,10 +950,8 @@ mod test_ipv6 { use crate::wire::{Icmpv6DstUnreachable, IpEndpoint, Ipv6Address}; - const REMOTE_IPV6: Ipv6Address = - Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]); - const LOCAL_IPV6: Ipv6Address = - Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); + const REMOTE_IPV6: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2); + const LOCAL_IPV6: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1); const LOCAL_END_V6: IpEndpoint = IpEndpoint { addr: IpAddress::Ipv6(LOCAL_IPV6), port: LOCAL_PORT, @@ -974,7 +982,7 @@ mod test_ipv6 { fn test_send_unaddressable() { let mut socket = socket(buffer(0), buffer(1)); assert_eq!( - socket.send_slice(b"abcdef", IpAddress::Ipv6(Ipv6Address::default())), + socket.send_slice(b"abcdef", IpAddress::Ipv6(Ipv6Address::UNSPECIFIED)), Err(SendError::Unaddressable) ); assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV6.into()), Ok(())); diff --git a/src/socket/raw.rs b/src/socket/raw.rs index bb3a204ad..c79f99b95 100644 --- a/src/socket/raw.rs +++ b/src/socket/raw.rs @@ -327,6 +327,16 @@ impl<'a> Socket<'a> { Ok(length) } + /// Return the amount of octets queued in the transmit buffer. + pub fn send_queue(&self) -> usize { + self.tx_buffer.payload_bytes_count() + } + + /// Return the amount of octets queued in the receive buffer. + pub fn recv_queue(&self) -> usize { + self.rx_buffer.payload_bytes_count() + } + pub(crate) fn accepts(&self, ip_repr: &IpRepr) -> bool { if ip_repr.version() != self.ip_version { return false; @@ -494,8 +504,8 @@ mod test { pub const IP_PROTO: u8 = 63; pub const HEADER_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr { - src_addr: Ipv4Address([10, 0, 0, 1]), - dst_addr: Ipv4Address([10, 0, 0, 2]), + src_addr: Ipv4Address::new(10, 0, 0, 1), + dst_addr: Ipv4Address::new(10, 0, 0, 2), next_header: IpProtocol::Unknown(IP_PROTO), payload_len: 4, hop_limit: 64, @@ -525,14 +535,8 @@ mod test { pub const IP_PROTO: u8 = 63; pub const HEADER_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr { - src_addr: Ipv6Address([ - 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, - ]), - dst_addr: Ipv6Address([ - 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, - ]), + src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), + dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2), next_header: IpProtocol::Unknown(IP_PROTO), payload_len: 4, hop_limit: 64, diff --git a/src/socket/tcp.rs b/src/socket/tcp.rs index 1e192c9bf..ba8e515f4 100644 --- a/src/socket/tcp.rs +++ b/src/socket/tcp.rs @@ -586,6 +586,7 @@ impl<'a> Socket<'a> { /// * Small embedded processors (such as Cortex-M0, Cortex-M1, and Cortex-M3) do not have an FPU, and floating point operations consume significant amounts of CPU time and Flash space. /// * Interrupt handlers should almost always avoid floating-point operations. /// * Kernel-mode code on desktop processors usually avoids FPU operations to reduce the penalty of saving and restoring FPU registers. + /// /// In all these cases, `CongestionControl::Reno` is a better choice of congestion control algorithm. pub fn set_congestion_control(&mut self, congestion_control: CongestionControl) { use congestion::*; @@ -792,6 +793,12 @@ impl<'a> Socket<'a> { self.hop_limit = hop_limit } + /// Return the listen endpoint + #[inline] + pub fn listen_endpoint(&self) -> IpListenEndpoint { + self.listen_endpoint + } + /// Return the local endpoint, or None if not connected. #[inline] pub fn local_endpoint(&self) -> Option { @@ -1507,11 +1514,6 @@ impl<'a> Socket<'a> { (State::Listen, _, None) => (), // This case is handled in `accepts()`. (State::Listen, _, Some(_)) => unreachable!(), - // Every packet after the initial SYN must be an acknowledgement. - (_, _, None) => { - net_debug!("expecting an ACK"); - return None; - } // SYN|ACK in the SYN-SENT state must have the exact ACK number. (State::SynSent, TcpControl::Syn, Some(ack_number)) => { if ack_number != self.local_seq_no + 1 { @@ -1519,6 +1521,10 @@ impl<'a> Socket<'a> { return Some(Self::rst_reply(ip_repr, repr)); } } + // TCP simultaneous open. + // This is required by RFC 9293, which states "A TCP implementation MUST support + // simultaneous open attempts (MUST-10)." + (State::SynSent, TcpControl::Syn, None) => (), // ACKs in the SYN-SENT state are invalid. (State::SynSent, TcpControl::None, Some(ack_number)) => { // If the sequence number matches, ignore it instead of RSTing. @@ -1542,6 +1548,11 @@ impl<'a> Socket<'a> { net_debug!("expecting a SYN|ACK"); return None; } + // Every packet after the initial SYN must be an acknowledgement. + (_, _, None) => { + net_debug!("expecting an ACK"); + return None; + } // ACK in the SYN-RECEIVED state must have the exact ACK number, or we RST it. (State::SynReceived, _, Some(ack_number)) => { if ack_number != self.local_seq_no + 1 { @@ -1721,7 +1732,10 @@ impl<'a> Socket<'a> { (State::Listen, TcpControl::Rst) => return None, // RSTs in SYN-RECEIVED flip the socket back to the LISTEN state. - (State::SynReceived, TcpControl::Rst) => { + // Here we need to additionally check `listen_endpoint`, because we want to make sure + // that SYN-RECEIVED was actually converted from the LISTEN state (another possible + // reason is TCP simultaneous open). + (State::SynReceived, TcpControl::Rst) if self.listen_endpoint.port != 0 => { tcp_trace!("received RST"); self.tuple = None; self.set_state(State::Listen); @@ -1788,8 +1802,13 @@ impl<'a> Socket<'a> { } // SYN|ACK packets in the SYN-SENT state change it to ESTABLISHED. + // SYN packets in the SYN-SENT state change it to SYN-RECEIVED. (State::SynSent, TcpControl::Syn) => { - tcp_trace!("received SYN|ACK"); + if repr.ack_number.is_some() { + tcp_trace!("received SYN|ACK"); + } else { + tcp_trace!("received SYN"); + } if let Some(max_seg_size) = repr.max_seg_size { if max_seg_size == 0 { tcp_trace!("received SYNACK with zero MSS, ignoring"); @@ -1815,7 +1834,11 @@ impl<'a> Socket<'a> { self.tsval_generator = None; } - self.set_state(State::Established); + if repr.ack_number.is_some() { + self.set_state(State::Established); + } else { + self.set_state(State::SynReceived); + } self.timer.set_for_idle(cx.now(), self.keep_alive); } @@ -1967,7 +1990,7 @@ impl<'a> Socket<'a> { "received duplicate ACK for seq {} (duplicate nr {}{})", ack_number, self.local_rx_dup_acks, - if self.local_rx_dup_acks == u8::max_value() { + if self.local_rx_dup_acks == u8::MAX { "+" } else { "" @@ -2056,20 +2079,20 @@ impl<'a> Socket<'a> { // Handle delayed acks if let Some(ack_delay) = self.ack_delay { - if self.ack_to_transmit() || self.window_to_update() { + if self.ack_to_transmit() { self.ack_delay_timer = match self.ack_delay_timer { AckDelayTimer::Idle => { tcp_trace!("starting delayed ack timer"); - AckDelayTimer::Waiting(cx.now() + ack_delay) } - // RFC1122 says "in a stream of full-sized segments there SHOULD be an ACK - // for at least every second segment". - // For now, we send an ACK every second received packet, full-sized or not. - AckDelayTimer::Waiting(_) => { + AckDelayTimer::Waiting(_) if self.immediate_ack_to_transmit() => { tcp_trace!("delayed ack timer already started, forcing expiry"); AckDelayTimer::Immediate } + timer @ AckDelayTimer::Waiting(_) => { + tcp_trace!("waiting until delayed ack timer expires"); + timer + } AckDelayTimer::Immediate => { tcp_trace!("delayed ack timer already force-expired"); AckDelayTimer::Immediate @@ -2182,6 +2205,24 @@ impl<'a> Socket<'a> { } } + /// Return whether to send ACK immediately due to the amount of unacknowledged data. + /// + /// RFC 9293 states "An ACK SHOULD be generated for at least every second full-sized segment or + /// 2*RMSS bytes of new data (where RMSS is the MSS specified by the TCP endpoint receiving the + /// segments to be acknowledged, or the default value if not specified) (SHLD-19)." + /// + /// Note that the RFC above only says "at least 2*RMSS bytes", which is not a hard requirement. + /// In practice, we follow the Linux kernel's empirical value of sending an ACK for every RMSS + /// byte of new data. For details, see + /// . + fn immediate_ack_to_transmit(&self) -> bool { + if let Some(remote_last_ack) = self.remote_last_ack { + remote_last_ack + self.remote_mss < self.remote_seq_no + self.rx_buffer.len() + } else { + false + } + } + /// Return whether we should send ACK immediately due to significant window updates. /// /// ACKs with significant window updates should be sent immediately to let the sender know that @@ -2332,6 +2373,7 @@ impl<'a> Socket<'a> { // We transmit a SYN|ACK in the SYN-RECEIVED state. State::SynSent | State::SynReceived => { repr.control = TcpControl::Syn; + repr.seq_number = self.local_seq_no; // window len must NOT be scaled in SYNs. repr.window_len = u16::try_from(self.rx_buffer.window()).unwrap_or(u16::MAX); if self.state == State::SynSent { @@ -2569,7 +2611,6 @@ impl<'a> fmt::Write for Socket<'a> { mod test { use super::*; use crate::wire::IpRepr; - use core::i32; use std::ops::{Deref, DerefMut}; use std::vec::Vec; @@ -2583,14 +2624,6 @@ mod test { addr: None, port: LOCAL_PORT, }; - const LOCAL_END: IpEndpoint = IpEndpoint { - addr: LOCAL_ADDR.into_address(), - port: LOCAL_PORT, - }; - const REMOTE_END: IpEndpoint = IpEndpoint { - addr: REMOTE_ADDR.into_address(), - port: REMOTE_PORT, - }; const TUPLE: Tuple = Tuple { local: LOCAL_END, remote: REMOTE_END, @@ -2604,27 +2637,39 @@ mod test { use crate::wire::Ipv4Repr as IpvXRepr; use IpRepr::Ipv4 as IpReprIpvX; - const LOCAL_ADDR: IpvXAddress = IpvXAddress([192, 168, 1, 1]); - const REMOTE_ADDR: IpvXAddress = IpvXAddress([192, 168, 1, 2]); - const OTHER_ADDR: IpvXAddress = IpvXAddress([192, 168, 1, 3]); + const LOCAL_ADDR: IpvXAddress = IpvXAddress::new(192, 168, 1, 1); + const REMOTE_ADDR: IpvXAddress = IpvXAddress::new(192, 168, 1, 2); + const OTHER_ADDR: IpvXAddress = IpvXAddress::new(192, 168, 1, 3); const BASE_MSS: u16 = 1460; + + const LOCAL_END: IpEndpoint = IpEndpoint { + addr: IpAddress::Ipv4(LOCAL_ADDR), + port: LOCAL_PORT, + }; + const REMOTE_END: IpEndpoint = IpEndpoint { + addr: IpAddress::Ipv4(REMOTE_ADDR), + port: REMOTE_PORT, + }; } else { use crate::wire::Ipv6Address as IpvXAddress; use crate::wire::Ipv6Repr as IpvXRepr; use IpRepr::Ipv6 as IpReprIpvX; - const LOCAL_ADDR: IpvXAddress = IpvXAddress([ - 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - ]); - const REMOTE_ADDR: IpvXAddress = IpvXAddress([ - 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, - ]); - const OTHER_ADDR: IpvXAddress = IpvXAddress([ - 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, - ]); + const LOCAL_ADDR: IpvXAddress = IpvXAddress::new(0xfe80, 0, 0, 0, 0, 0, 0, 1); + const REMOTE_ADDR: IpvXAddress = IpvXAddress::new(0xfe80, 0, 0, 0, 0, 0, 0, 2); + const OTHER_ADDR: IpvXAddress = IpvXAddress::new(0xfe80, 0, 0, 0, 0, 0, 0, 3); const BASE_MSS: u16 = 1440; + + const LOCAL_END: IpEndpoint = IpEndpoint { + addr: IpAddress::Ipv6(LOCAL_ADDR), + port: LOCAL_PORT, + }; + const REMOTE_END: IpEndpoint = IpEndpoint { + addr: IpAddress::Ipv6(REMOTE_ADDR), + port: REMOTE_PORT, + }; } } @@ -3533,6 +3578,78 @@ mod test { sanity!(s, socket_established()); } + #[test] + fn test_syn_sent_syn_received_ack() { + let mut s = socket_syn_sent(); + recv!( + s, + [TcpRepr { + control: TcpControl::Syn, + seq_number: LOCAL_SEQ, + ack_number: None, + max_seg_size: Some(BASE_MSS), + window_scale: Some(0), + sack_permitted: true, + ..RECV_TEMPL + }] + ); + + // A SYN packet changes the SYN-SENT state to SYN-RECEIVED. + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: None, + max_seg_size: Some(BASE_MSS - 80), + window_scale: Some(0), + ..SEND_TEMPL + } + ); + assert_eq!(s.state, State::SynReceived); + + // The socket will then send a SYN|ACK packet. + recv!( + s, + [TcpRepr { + control: TcpControl::Syn, + seq_number: LOCAL_SEQ, + ack_number: Some(REMOTE_SEQ + 1), + max_seg_size: Some(BASE_MSS), + window_scale: Some(0), + ..RECV_TEMPL + }] + ); + recv_nothing!(s); + + // The socket may retransmit the SYN|ACK packet. + recv!( + s, + time 1001, + Ok(TcpRepr { + control: TcpControl::Syn, + seq_number: LOCAL_SEQ, + ack_number: Some(REMOTE_SEQ + 1), + max_seg_size: Some(BASE_MSS), + window_scale: Some(0), + ..RECV_TEMPL + }) + ); + + // An ACK packet changes the SYN-RECEIVED state to ESTABLISHED. + send!( + s, + TcpRepr { + control: TcpControl::None, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); + assert_eq!(s.state, State::Established); + sanity!(s, socket_established()); + } + #[test] fn test_syn_sent_syn_ack_not_incremented() { let mut s = socket_syn_sent(); @@ -3569,6 +3686,49 @@ mod test { assert_eq!(s.state, State::SynSent); } + #[test] + fn test_syn_sent_syn_received_rst() { + let mut s = socket_syn_sent(); + recv!( + s, + [TcpRepr { + control: TcpControl::Syn, + seq_number: LOCAL_SEQ, + ack_number: None, + max_seg_size: Some(BASE_MSS), + window_scale: Some(0), + sack_permitted: true, + ..RECV_TEMPL + }] + ); + + // A SYN packet changes the SYN-SENT state to SYN-RECEIVED. + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: None, + max_seg_size: Some(BASE_MSS - 80), + window_scale: Some(0), + ..SEND_TEMPL + } + ); + assert_eq!(s.state, State::SynReceived); + + // A RST packet changes the SYN-RECEIVED state to CLOSED. + send!( + s, + TcpRepr { + control: TcpControl::Rst, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ), + ..SEND_TEMPL + } + ); + assert_eq!(s.state, State::Closed); + } + #[test] fn test_syn_sent_rst() { let mut s = socket_syn_sent(); @@ -6126,7 +6286,7 @@ mod test { }); // A lot of retransmits happen here - s.local_rx_dup_acks = u8::max_value() - 1; + s.local_rx_dup_acks = u8::MAX - 1; // Send 3 more ACKs, which could overflow local_rx_dup_acks, // but intended behaviour is that we saturate the bounds @@ -6148,7 +6308,7 @@ mod test { }); assert_eq!( s.local_rx_dup_acks, - u8::max_value(), + u8::MAX, "duplicate ACK count should not overflow but saturate" ); } @@ -7357,15 +7517,15 @@ mod test { } #[test] - fn test_delayed_ack_every_second_packet() { - let mut s = socket_established(); + fn test_delayed_ack_every_rmss() { + let mut s = socket_established_with_buffer_sizes(DEFAULT_MSS * 2, DEFAULT_MSS * 2); s.set_ack_delay(Some(ACK_DELAY_DEFAULT)); send!( s, TcpRepr { seq_number: REMOTE_SEQ + 1, ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abc"[..], + payload: &[0; DEFAULT_MSS - 1], ..SEND_TEMPL } ); @@ -7376,35 +7536,48 @@ mod test { send!( s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 3, + seq_number: REMOTE_SEQ + 1 + (DEFAULT_MSS - 1), ack_number: Some(LOCAL_SEQ + 1), - payload: &b"def"[..], + payload: &b"a"[..], + ..SEND_TEMPL + } + ); + + // No ACK is immediately sent. + recv_nothing!(s); + + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + DEFAULT_MSS, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"a"[..], ..SEND_TEMPL } ); - // Every 2nd packet, ACK is sent without delay. + // RMSS+1 bytes of data has been received, so ACK is sent without delay. recv!( s, Ok(TcpRepr { seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 6), - window_len: 58, + ack_number: Some(REMOTE_SEQ + 1 + (DEFAULT_MSS + 1)), + window_len: (DEFAULT_MSS - 1) as u16, ..RECV_TEMPL }) ); } #[test] - fn test_delayed_ack_three_packets() { - let mut s = socket_established(); + fn test_delayed_ack_every_rmss_or_more() { + let mut s = socket_established_with_buffer_sizes(DEFAULT_MSS * 2, DEFAULT_MSS * 2); s.set_ack_delay(Some(ACK_DELAY_DEFAULT)); send!( s, TcpRepr { seq_number: REMOTE_SEQ + 1, ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abc"[..], + payload: &[0; DEFAULT_MSS], ..SEND_TEMPL } ); @@ -7415,9 +7588,9 @@ mod test { send!( s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 3, + seq_number: REMOTE_SEQ + 1 + DEFAULT_MSS, ack_number: Some(LOCAL_SEQ + 1), - payload: &b"def"[..], + payload: &b"a"[..], ..SEND_TEMPL } ); @@ -7425,20 +7598,20 @@ mod test { send!( s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 6, + seq_number: REMOTE_SEQ + 1 + (DEFAULT_MSS + 1), ack_number: Some(LOCAL_SEQ + 1), - payload: &b"ghi"[..], + payload: &b"b"[..], ..SEND_TEMPL } ); - // Every 2nd (or more) packet, ACK is sent without delay. + // RMSS+2 bytes of data has been received, so ACK is sent without delay. recv!( s, Ok(TcpRepr { seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 9), - window_len: 55, + ack_number: Some(REMOTE_SEQ + 1 + (DEFAULT_MSS + 2)), + window_len: (DEFAULT_MSS - 2) as u16, ..RECV_TEMPL }) ); diff --git a/src/socket/udp.rs b/src/socket/udp.rs index 269043ef7..1e09116f3 100644 --- a/src/socket/udp.rs +++ b/src/socket/udp.rs @@ -459,6 +459,22 @@ impl<'a> Socket<'a> { Ok((length, endpoint)) } + /// Return the amount of octets queued in the transmit buffer. + /// + /// Note that the Berkeley sockets interface does not have an equivalent of this API. + pub fn send_queue(&self) -> usize { + self.tx_buffer.payload_bytes_count() + } + + /// Return the amount of octets queued in the receive buffer. This value can be larger than + /// the slice read by the next `recv` or `peek` call because it includes all queued octets, + /// and not only the octets that may be returned as a contiguous slice. + /// + /// Note that the Berkeley sockets interface does not have an equivalent of this API. + pub fn recv_queue(&self) -> usize { + self.rx_buffer.payload_bytes_count() + } + pub(crate) fn accepts(&self, cx: &mut Context, ip_repr: &IpRepr, repr: &UdpRepr) -> bool { if self.endpoint.port != repr.dst_port { return false; @@ -619,34 +635,38 @@ mod test { use crate::wire::Ipv4Repr as IpvXRepr; use IpRepr::Ipv4 as IpReprIpvX; - const LOCAL_ADDR: IpvXAddress = IpvXAddress([192, 168, 1, 1]); - const REMOTE_ADDR: IpvXAddress = IpvXAddress([192, 168, 1, 2]); - const OTHER_ADDR: IpvXAddress = IpvXAddress([192, 168, 1, 3]); + const LOCAL_ADDR: IpvXAddress = IpvXAddress::new(192, 168, 1, 1); + const REMOTE_ADDR: IpvXAddress = IpvXAddress::new(192, 168, 1, 2); + const OTHER_ADDR: IpvXAddress = IpvXAddress::new(192, 168, 1, 3); + + const LOCAL_END: IpEndpoint = IpEndpoint { + addr: IpAddress::Ipv4(LOCAL_ADDR), + port: LOCAL_PORT, + }; + const REMOTE_END: IpEndpoint = IpEndpoint { + addr: IpAddress::Ipv4(REMOTE_ADDR), + port: REMOTE_PORT, + }; } else { use crate::wire::Ipv6Address as IpvXAddress; use crate::wire::Ipv6Repr as IpvXRepr; use IpRepr::Ipv6 as IpReprIpvX; - const LOCAL_ADDR: IpvXAddress = IpvXAddress([ - 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - ]); - const REMOTE_ADDR: IpvXAddress = IpvXAddress([ - 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, - ]); - const OTHER_ADDR: IpvXAddress = IpvXAddress([ - 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, - ]); + const LOCAL_ADDR: IpvXAddress = IpvXAddress::new(0xfe80, 0, 0, 0, 0, 0, 0, 1); + const REMOTE_ADDR: IpvXAddress = IpvXAddress::new(0xfe80, 0, 0, 0, 0, 0, 0, 2); + const OTHER_ADDR: IpvXAddress = IpvXAddress::new(0xfe80, 0, 0, 0, 0, 0, 0, 3); + + const LOCAL_END: IpEndpoint = IpEndpoint { + addr: IpAddress::Ipv6(LOCAL_ADDR), + port: LOCAL_PORT, + }; + const REMOTE_END: IpEndpoint = IpEndpoint { + addr: IpAddress::Ipv6(REMOTE_ADDR), + port: REMOTE_PORT, + }; } } - pub const LOCAL_END: IpEndpoint = IpEndpoint { - addr: LOCAL_ADDR.into_address(), - port: LOCAL_PORT, - }; - pub const REMOTE_END: IpEndpoint = IpEndpoint { - addr: REMOTE_ADDR.into_address(), - port: REMOTE_PORT, - }; fn remote_metadata_with_local() -> UdpMetadata { // Would be great as a const once we have const `.into()`. UdpMetadata { diff --git a/src/storage/packet_buffer.rs b/src/storage/packet_buffer.rs index 28119fa10..f9121e611 100644 --- a/src/storage/packet_buffer.rs +++ b/src/storage/packet_buffer.rs @@ -239,6 +239,11 @@ impl<'a, H> PacketBuffer<'a, H> { self.payload_ring.capacity() } + /// Return the current number of bytes in the payload ring buffer. + pub fn payload_bytes_count(&self) -> usize { + self.payload_ring.len() + } + /// Reset the packet buffer and clear any staged. #[allow(unused)] pub(crate) fn reset(&mut self) { diff --git a/src/wire/arp.rs b/src/wire/arp.rs index c7d0b8add..8129c59da 100644 --- a/src/wire/arp.rs +++ b/src/wire/arp.rs @@ -2,6 +2,7 @@ use byteorder::{ByteOrder, NetworkEndian}; use core::fmt; use super::{Error, Result}; +use super::{EthernetAddress, Ipv4Address, Ipv4AddressExt}; pub use super::EthernetProtocol as Protocol; @@ -250,8 +251,6 @@ impl> AsRef<[u8]> for Packet { } } -use crate::wire::{EthernetAddress, Ipv4Address}; - /// A high-level representation of an Address Resolution Protocol packet. #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -313,9 +312,9 @@ impl Repr { packet.set_protocol_len(4); packet.set_operation(operation); packet.set_source_hardware_addr(source_hardware_addr.as_bytes()); - packet.set_source_protocol_addr(source_protocol_addr.as_bytes()); + packet.set_source_protocol_addr(&source_protocol_addr.octets()); packet.set_target_hardware_addr(target_hardware_addr.as_bytes()); - packet.set_target_protocol_addr(target_protocol_addr.as_bytes()); + packet.set_target_protocol_addr(&target_protocol_addr.octets()); } } } diff --git a/src/wire/dhcpv4.rs b/src/wire/dhcpv4.rs index b00f26ff7..87ace13e4 100644 --- a/src/wire/dhcpv4.rs +++ b/src/wire/dhcpv4.rs @@ -7,7 +7,7 @@ use heapless::Vec; use super::{Error, Result}; use crate::wire::arp::Hardware; -use crate::wire::{EthernetAddress, Ipv4Address}; +use crate::wire::{EthernetAddress, Ipv4Address, Ipv4AddressExt}; pub const SERVER_PORT: u16 = 67; pub const CLIENT_PORT: u16 = 68; @@ -443,7 +443,7 @@ impl + AsMut<[u8]>> Packet { pub fn set_hardware_type(&mut self, value: Hardware) { let data = self.buffer.as_mut(); let number: u16 = value.into(); - assert!(number <= u16::from(u8::max_value())); // TODO: Replace with TryFrom when it's stable + assert!(number <= u16::from(u8::MAX)); // TODO: Replace with TryFrom when it's stable data[field::HTYPE] = number as u8; } @@ -503,25 +503,25 @@ impl + AsMut<[u8]>> Packet { /// and can respond to ARP requests”. pub fn set_client_ip(&mut self, value: Ipv4Address) { let field = &mut self.buffer.as_mut()[field::CIADDR]; - field.copy_from_slice(value.as_bytes()); + field.copy_from_slice(&value.octets()); } /// Sets the value of the `yiaddr` field. pub fn set_your_ip(&mut self, value: Ipv4Address) { let field = &mut self.buffer.as_mut()[field::YIADDR]; - field.copy_from_slice(value.as_bytes()); + field.copy_from_slice(&value.octets()); } /// Sets the value of the `siaddr` field. pub fn set_server_ip(&mut self, value: Ipv4Address) { let field = &mut self.buffer.as_mut()[field::SIADDR]; - field.copy_from_slice(value.as_bytes()); + field.copy_from_slice(&value.octets()); } /// Sets the value of the `giaddr` field. pub fn set_relay_agent_ip(&mut self, value: Ipv4Address) { let field = &mut self.buffer.as_mut()[field::GIADDR]; - field.copy_from_slice(value.as_bytes()); + field.copy_from_slice(&value.octets()); } /// Sets the flags to the specified value. @@ -881,26 +881,26 @@ impl<'a> Repr<'a> { if let Some(val) = &self.server_identifier { options.emit(DhcpOption { kind: field::OPT_SERVER_IDENTIFIER, - data: val.as_bytes(), + data: &val.octets(), })?; } if let Some(val) = &self.router { options.emit(DhcpOption { kind: field::OPT_ROUTER, - data: val.as_bytes(), + data: &val.octets(), })?; } if let Some(val) = &self.subnet_mask { options.emit(DhcpOption { kind: field::OPT_SUBNET_MASK, - data: val.as_bytes(), + data: &val.octets(), })?; } if let Some(val) = &self.requested_ip { options.emit(DhcpOption { kind: field::OPT_REQUESTED_IP, - data: val.as_bytes(), + data: &val.octets(), })?; } if let Some(val) = &self.max_size { @@ -930,7 +930,7 @@ impl<'a> Repr<'a> { .iter() .enumerate() .inspect(|(i, ip)| { - servers[(i * IP_SIZE)..((i + 1) * IP_SIZE)].copy_from_slice(ip.as_bytes()); + servers[(i * IP_SIZE)..((i + 1) * IP_SIZE)].copy_from_slice(&ip.octets()); }) .count() * IP_SIZE; @@ -1029,7 +1029,7 @@ mod test { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; - const IP_NULL: Ipv4Address = Ipv4Address([0, 0, 0, 0]); + const IP_NULL: Ipv4Address = Ipv4Address::new(0, 0, 0, 0); const CLIENT_MAC: EthernetAddress = EthernetAddress([0x0, 0x0b, 0x82, 0x01, 0xfc, 0x42]); const DHCP_SIZE: u16 = 1500; @@ -1236,9 +1236,9 @@ mod test { let mut repr = offer_repr(); repr.dns_servers = Some( Vec::from_slice(&[ - Ipv4Address([163, 1, 74, 6]), - Ipv4Address([163, 1, 74, 7]), - Ipv4Address([163, 1, 74, 3]), + Ipv4Address::new(163, 1, 74, 6), + Ipv4Address::new(163, 1, 74, 7), + Ipv4Address::new(163, 1, 74, 3), ]) .unwrap(), ); @@ -1255,9 +1255,9 @@ mod test { repr_parsed.dns_servers, Some( Vec::from_slice(&[ - Ipv4Address([163, 1, 74, 6]), - Ipv4Address([163, 1, 74, 7]), - Ipv4Address([163, 1, 74, 3]), + Ipv4Address::new(163, 1, 74, 6), + Ipv4Address::new(163, 1, 74, 7), + Ipv4Address::new(163, 1, 74, 3), ]) .unwrap() ) @@ -1295,9 +1295,9 @@ mod test { repr.dns_servers, Some( Vec::from_slice(&[ - Ipv4Address([163, 1, 74, 6]), - Ipv4Address([163, 1, 74, 7]), - Ipv4Address([163, 1, 74, 3]) + Ipv4Address::new(163, 1, 74, 6), + Ipv4Address::new(163, 1, 74, 7), + Ipv4Address::new(163, 1, 74, 3) ]) .unwrap() ) diff --git a/src/wire/dns.rs b/src/wire/dns.rs index 147f4a2f9..68f504f58 100644 --- a/src/wire/dns.rs +++ b/src/wire/dns.rs @@ -7,9 +7,9 @@ use core::iter::Iterator; use super::{Error, Result}; #[cfg(feature = "proto-ipv4")] -use crate::wire::Ipv4Address; +use crate::wire::{Ipv4Address, Ipv4AddressExt}; #[cfg(feature = "proto-ipv6")] -use crate::wire::Ipv6Address; +use crate::wire::{Ipv6Address, Ipv6AddressExt}; enum_with_unknown! { /// DNS OpCodes diff --git a/src/wire/icmpv6.rs b/src/wire/icmpv6.rs index 2a9e79d45..724421dea 100644 --- a/src/wire/icmpv6.rs +++ b/src/wire/icmpv6.rs @@ -847,10 +847,8 @@ mod test { use super::*; 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]); + const MOCK_IP_ADDR_1: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1); + const MOCK_IP_ADDR_2: Ipv6Address = Ipv6Address::new(0xfe80, 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, @@ -888,14 +886,8 @@ mod test { Repr::PktTooBig { mtu: 1500, header: Ipv6Repr { - src_addr: Ipv6Address([ - 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, - ]), - dst_addr: Ipv6Address([ - 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, - ]), + src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), + dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2), next_header: IpProtocol::Udp, payload_len: 12, hop_limit: 0x40, @@ -1017,8 +1009,8 @@ mod test { let repr = Repr::PktTooBig { mtu: 1280, header: Ipv6Repr { - src_addr: Default::default(), - dst_addr: Default::default(), + src_addr: Ipv6Address::UNSPECIFIED, + dst_addr: Ipv6Address::UNSPECIFIED, next_header: IpProtocol::Tcp, hop_limit: 64, payload_len: 1280, @@ -1031,8 +1023,8 @@ mod test { #[test] fn test_mtu_truncated_payload_roundtrip() { let ip_packet_repr = Ipv6Repr { - src_addr: Default::default(), - dst_addr: Default::default(), + src_addr: Ipv6Address::UNSPECIFIED, + dst_addr: Ipv6Address::UNSPECIFIED, next_header: IpProtocol::Tcp, hop_limit: 64, payload_len: IPV6_MIN_MTU - IPV6_HEADER_LEN, diff --git a/src/wire/ieee802154.rs b/src/wire/ieee802154.rs index 33fafb60e..43d656b0f 100644 --- a/src/wire/ieee802154.rs +++ b/src/wire/ieee802154.rs @@ -3,7 +3,7 @@ use core::fmt; use byteorder::{ByteOrder, LittleEndian}; use super::{Error, Result}; -use crate::wire::ipv6::Address as Ipv6Address; +use crate::wire::{Ipv6Address, Ipv6AddressExt}; enum_with_unknown! { /// IEEE 802.15.4 frame type. diff --git a/src/wire/igmp.rs b/src/wire/igmp.rs index ac1f48d2d..ba282bab4 100644 --- a/src/wire/igmp.rs +++ b/src/wire/igmp.rs @@ -5,7 +5,7 @@ use super::{Error, Result}; use crate::time::Duration; use crate::wire::ip::checksum; -use crate::wire::Ipv4Address; +use crate::wire::{Ipv4Address, Ipv4AddressExt}; enum_with_unknown! { /// Internet Group Management Protocol v1/v2 message version/type. @@ -156,7 +156,7 @@ impl + AsMut<[u8]>> Packet { #[inline] pub fn set_group_address(&mut self, addr: Ipv4Address) { let data = self.buffer.as_mut(); - data[field::GROUP_ADDRESS].copy_from_slice(addr.as_bytes()); + data[field::GROUP_ADDRESS].copy_from_slice(&addr.octets()); } /// Compute and fill in the header checksum. diff --git a/src/wire/ip.rs b/src/wire/ip.rs index 1d1c63d64..e61541cd0 100644 --- a/src/wire/ip.rs +++ b/src/wire/ip.rs @@ -4,9 +4,9 @@ use core::fmt; use super::{Error, Result}; use crate::phy::ChecksumCapabilities; #[cfg(feature = "proto-ipv4")] -use crate::wire::{Ipv4Address, Ipv4Cidr, Ipv4Packet, Ipv4Repr}; +use crate::wire::{Ipv4Address, Ipv4AddressExt, Ipv4Cidr, Ipv4Packet, Ipv4Repr}; #[cfg(feature = "proto-ipv6")] -use crate::wire::{Ipv6Address, Ipv6Cidr, Ipv6Packet, Ipv6Repr}; +use crate::wire::{Ipv6Address, Ipv6AddressExt, Ipv6Cidr, Ipv6Packet, Ipv6Repr}; /// Internet protocol version. #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] @@ -127,23 +127,13 @@ impl Address { } } - /// Return an address as a sequence of octets, in big-endian. - pub const fn as_bytes(&self) -> &[u8] { - match self { - #[cfg(feature = "proto-ipv4")] - Address::Ipv4(addr) => addr.as_bytes(), - #[cfg(feature = "proto-ipv6")] - Address::Ipv6(addr) => addr.as_bytes(), - } - } - /// Query whether the address is a valid unicast address. pub fn is_unicast(&self) -> bool { match self { #[cfg(feature = "proto-ipv4")] - Address::Ipv4(addr) => addr.is_unicast(), + Address::Ipv4(addr) => addr.x_is_unicast(), #[cfg(feature = "proto-ipv6")] - Address::Ipv6(addr) => addr.is_unicast(), + Address::Ipv6(addr) => addr.x_is_unicast(), } } @@ -180,27 +170,12 @@ impl Address { /// If `self` is a CIDR-compatible subnet mask, return `Some(prefix_len)`, /// where `prefix_len` is the number of leading zeroes. Return `None` otherwise. pub fn prefix_len(&self) -> Option { - let mut ones = true; - let mut prefix_len = 0; - for byte in self.as_bytes() { - let mut mask = 0x80; - for _ in 0..8 { - let one = *byte & mask != 0; - if ones { - // Expect 1s until first 0 - if one { - prefix_len += 1; - } else { - ones = false; - } - } else if one { - // 1 where 0 was expected - return None; - } - mask >>= 1; - } + match self { + #[cfg(feature = "proto-ipv4")] + Address::Ipv4(addr) => addr.prefix_len(), + #[cfg(feature = "proto-ipv6")] + Address::Ipv6(addr) => addr.prefix_len(), } - Some(prefix_len) } } @@ -208,8 +183,8 @@ impl Address { impl From<::core::net::IpAddr> for Address { fn from(x: ::core::net::IpAddr) -> Address { match x { - ::core::net::IpAddr::V4(ipv4) => Address::Ipv4(ipv4.into()), - ::core::net::IpAddr::V6(ipv6) => Address::Ipv6(ipv6.into()), + ::core::net::IpAddr::V4(ipv4) => Address::Ipv4(ipv4), + ::core::net::IpAddr::V6(ipv6) => Address::Ipv6(ipv6), } } } @@ -218,31 +193,17 @@ impl From
for ::core::net::IpAddr { fn from(x: Address) -> ::core::net::IpAddr { match x { #[cfg(feature = "proto-ipv4")] - Address::Ipv4(ipv4) => ::core::net::IpAddr::V4(ipv4.into()), + Address::Ipv4(ipv4) => ::core::net::IpAddr::V4(ipv4), #[cfg(feature = "proto-ipv6")] - Address::Ipv6(ipv6) => ::core::net::IpAddr::V6(ipv6.into()), + Address::Ipv6(ipv6) => ::core::net::IpAddr::V6(ipv6), } } } -#[cfg(feature = "proto-ipv4")] -impl From<::core::net::Ipv4Addr> for Address { - fn from(ipv4: ::core::net::Ipv4Addr) -> Address { - Address::Ipv4(ipv4.into()) - } -} - -#[cfg(feature = "proto-ipv6")] -impl From<::core::net::Ipv6Addr> for Address { - fn from(ipv6: ::core::net::Ipv6Addr) -> Address { - Address::Ipv6(ipv6.into()) - } -} - #[cfg(feature = "proto-ipv4")] impl From for Address { - fn from(addr: Ipv4Address) -> Self { - Address::Ipv4(addr) + fn from(ipv4: Ipv4Address) -> Address { + Address::Ipv4(ipv4) } } @@ -773,8 +734,8 @@ pub mod checksum { NetworkEndian::write_u16(&mut proto_len[2..4], length as u16); combine(&[ - data(src_addr.as_bytes()), - data(dst_addr.as_bytes()), + data(&src_addr.octets()), + data(&dst_addr.octets()), data(&proto_len[..]), ]) } @@ -791,8 +752,8 @@ pub mod checksum { NetworkEndian::write_u16(&mut proto_len[2..4], length as u16); combine(&[ - data(src_addr.as_bytes()), - data(dst_addr.as_bytes()), + data(&src_addr.octets()), + data(&dst_addr.octets()), data(&proto_len[..]), ]) } diff --git a/src/wire/ipv4.rs b/src/wire/ipv4.rs index b5f7894b3..7629a46ed 100644 --- a/src/wire/ipv4.rs +++ b/src/wire/ipv4.rs @@ -26,6 +26,12 @@ pub const MIN_MTU: usize = 576; /// [RFC 8200 § 2]: https://www.rfc-editor.org/rfc/rfc791#section-3.2 pub const ADDR_SIZE: usize = 4; +/// All multicast-capable nodes +pub const MULTICAST_ALL_SYSTEMS: Address = Address::new(224, 0, 0, 1); + +/// All multicast-capable routers +pub const MULTICAST_ALL_ROUTERS: Address = Address::new(224, 0, 0, 2); + #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Key { @@ -35,117 +41,65 @@ pub struct Key { protocol: Protocol, } -/// A four-octet IPv4 address. -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)] -pub struct Address(pub [u8; ADDR_SIZE]); - -impl Address { - /// An unspecified address. - pub const UNSPECIFIED: Address = Address([0x00; ADDR_SIZE]); - - /// The broadcast address. - pub const BROADCAST: Address = Address([0xff; ADDR_SIZE]); - - /// All multicast-capable nodes - pub const MULTICAST_ALL_SYSTEMS: Address = Address([224, 0, 0, 1]); - - /// All multicast-capable routers - pub const MULTICAST_ALL_ROUTERS: Address = Address([224, 0, 0, 2]); - - /// Construct an IPv4 address from parts. - pub const fn new(a0: u8, a1: u8, a2: u8, a3: u8) -> Address { - Address([a0, a1, a2, a3]) - } +pub use core::net::Ipv4Addr as Address; +pub(crate) trait AddressExt { /// Construct an IPv4 address from a sequence of octets, in big-endian. /// /// # Panics /// The function panics if `data` is not four octets long. - pub fn from_bytes(data: &[u8]) -> Address { - let mut bytes = [0; ADDR_SIZE]; - bytes.copy_from_slice(data); - Address(bytes) - } - - /// Return an IPv4 address as a sequence of octets, in big-endian. - pub const fn as_bytes(&self) -> &[u8] { - &self.0 - } + fn from_bytes(data: &[u8]) -> Self; /// Query whether the address is an unicast address. - pub fn is_unicast(&self) -> bool { - !(self.is_broadcast() || self.is_multicast() || self.is_unspecified()) - } - - /// Query whether the address is the broadcast address. - pub fn is_broadcast(&self) -> bool { - self.0[0..4] == [255; ADDR_SIZE] - } - - /// Query whether the address is a multicast address. - pub const fn is_multicast(&self) -> bool { - self.0[0] & 0xf0 == 224 - } - - /// Query whether the address falls into the "unspecified" range. - pub const fn is_unspecified(&self) -> bool { - self.0[0] == 0 - } - - /// Query whether the address falls into the "link-local" range. - pub fn is_link_local(&self) -> bool { - self.0[0..2] == [169, 254] - } - - /// Query whether the address falls into the "loopback" range. - pub const fn is_loopback(&self) -> bool { - self.0[0] == 127 - } - - /// Convert to an `IpAddress`. /// - /// Same as `.into()`, but works in `const`. - pub const fn into_address(self) -> super::IpAddress { - super::IpAddress::Ipv4(self) - } -} + /// `x_` prefix is to avoid a collision with the still-unstable method in `core::ip`. + fn x_is_unicast(&self) -> bool; -impl From<::core::net::Ipv4Addr> for Address { - fn from(x: ::core::net::Ipv4Addr) -> Address { - Address(x.octets()) - } + /// If `self` is a CIDR-compatible subnet mask, return `Some(prefix_len)`, + /// where `prefix_len` is the number of leading zeroes. Return `None` otherwise. + fn prefix_len(&self) -> Option; } -impl From
for ::core::net::Ipv4Addr { - fn from(Address(x): Address) -> ::core::net::Ipv4Addr { - x.into() +impl AddressExt for Address { + fn from_bytes(data: &[u8]) -> Address { + let mut bytes = [0; ADDR_SIZE]; + bytes.copy_from_slice(data); + Address::from_bits(u32::from_be_bytes(bytes)) } -} -impl fmt::Display for Address { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let bytes = self.0; - write!(f, "{}.{}.{}.{}", bytes[0], bytes[1], bytes[2], bytes[3]) + /// Query whether the address is an unicast address. + fn x_is_unicast(&self) -> bool { + !(self.is_broadcast() || self.is_multicast() || self.is_unspecified()) } -} -#[cfg(feature = "defmt")] -impl defmt::Format for Address { - fn format(&self, f: defmt::Formatter) { - defmt::write!( - f, - "{=u8}.{=u8}.{=u8}.{=u8}", - self.0[0], - self.0[1], - self.0[2], - self.0[3] - ) + fn prefix_len(&self) -> Option { + let mut ones = true; + let mut prefix_len = 0; + for byte in self.octets() { + let mut mask = 0x80; + for _ in 0..8 { + let one = byte & mask != 0; + if ones { + // Expect 1s until first 0 + if one { + prefix_len += 1; + } else { + ones = false; + } + } else if one { + // 1 where 0 was expected + return None; + } + mask >>= 1; + } + } + Some(prefix_len) } } /// A specification of an IPv4 CIDR block, containing an address and a variable-length /// subnet masking prefix length. -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)] +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] pub struct Cidr { address: Address, prefix_len: u8, @@ -166,7 +120,7 @@ impl Cidr { /// Create an IPv4 CIDR block from the given address and network mask. pub fn from_netmask(addr: Address, netmask: Address) -> Result { - let netmask = NetworkEndian::read_u32(&netmask.0[..]); + let netmask = netmask.to_bits(); if netmask.leading_zeros() == 0 && netmask.trailing_zeros() == netmask.count_zeros() { Ok(Cidr { address: addr, @@ -190,18 +144,11 @@ impl Cidr { /// Return the network mask of this IPv4 CIDR. pub const fn netmask(&self) -> Address { if self.prefix_len == 0 { - return Address([0, 0, 0, 0]); + return Address::new(0, 0, 0, 0); } let number = 0xffffffffu32 << (32 - self.prefix_len); - let data = [ - ((number >> 24) & 0xff) as u8, - ((number >> 16) & 0xff) as u8, - ((number >> 8) & 0xff) as u8, - ((number >> 0) & 0xff) as u8, - ]; - - Address(data) + Address::from_bits(number) } /// Return the broadcast address of this IPv4 CIDR. @@ -212,29 +159,15 @@ impl Cidr { return None; } - let network_number = NetworkEndian::read_u32(&network.address.0[..]); + let network_number = network.address.to_bits(); let number = network_number | 0xffffffffu32 >> network.prefix_len; - let data = [ - ((number >> 24) & 0xff) as u8, - ((number >> 16) & 0xff) as u8, - ((number >> 8) & 0xff) as u8, - ((number >> 0) & 0xff) as u8, - ]; - - Some(Address(data)) + Some(Address::from_bits(number)) } /// Return the network block of this IPv4 CIDR. pub const fn network(&self) -> Cidr { - let mask = self.netmask().0; - let network = [ - self.address.0[0] & mask[0], - self.address.0[1] & mask[1], - self.address.0[2] & mask[2], - self.address.0[3] & mask[3], - ]; Cidr { - address: Address(network), + address: Address::from_bits(self.address.to_bits() & self.netmask().to_bits()), prefix_len: self.prefix_len, } } @@ -242,15 +175,8 @@ impl Cidr { /// Query whether the subnetwork described by this IPv4 CIDR block contains /// the given address. pub fn contains_addr(&self, addr: &Address) -> bool { - // right shift by 32 is not legal - if self.prefix_len == 0 { - return true; - } - - let shift = 32 - self.prefix_len; - let self_prefix = NetworkEndian::read_u32(self.address.as_bytes()) >> shift; - let addr_prefix = NetworkEndian::read_u32(addr.as_bytes()) >> shift; - self_prefix == addr_prefix + self.address.to_bits() & self.netmask().to_bits() + == addr.to_bits() & self.netmask().to_bits() } /// Query whether the subnetwork described by this IPv4 CIDR block contains @@ -576,14 +502,14 @@ impl + AsMut<[u8]>> Packet { #[inline] pub fn set_src_addr(&mut self, value: Address) { let data = self.buffer.as_mut(); - data[field::SRC_ADDR].copy_from_slice(value.as_bytes()) + data[field::SRC_ADDR].copy_from_slice(&value.octets()) } /// Set the destination address field. #[inline] pub fn set_dst_addr(&mut self, value: Address) { let data = self.buffer.as_mut(); - data[field::DST_ADDR].copy_from_slice(value.as_bytes()) + data[field::DST_ADDR].copy_from_slice(&value.octets()) } /// Compute and fill in the header checksum. @@ -795,13 +721,13 @@ pub(crate) mod test { use super::*; #[allow(unused)] - pub(crate) const MOCK_IP_ADDR_1: Address = Address([192, 168, 1, 1]); + pub(crate) const MOCK_IP_ADDR_1: Address = Address::new(192, 168, 1, 1); #[allow(unused)] - pub(crate) const MOCK_IP_ADDR_2: Address = Address([192, 168, 1, 2]); + pub(crate) const MOCK_IP_ADDR_2: Address = Address::new(192, 168, 1, 2); #[allow(unused)] - pub(crate) const MOCK_IP_ADDR_3: Address = Address([192, 168, 1, 3]); + pub(crate) const MOCK_IP_ADDR_3: Address = Address::new(192, 168, 1, 3); #[allow(unused)] - pub(crate) const MOCK_IP_ADDR_4: Address = Address([192, 168, 1, 4]); + pub(crate) const MOCK_IP_ADDR_4: Address = Address::new(192, 168, 1, 4); #[allow(unused)] pub(crate) const MOCK_UNSPECIFIED: Address = Address::UNSPECIFIED; @@ -827,8 +753,8 @@ pub(crate) mod test { assert_eq!(packet.hop_limit(), 0x1a); assert_eq!(packet.next_header(), Protocol::Icmp); assert_eq!(packet.checksum(), 0xd56e); - assert_eq!(packet.src_addr(), Address([0x11, 0x12, 0x13, 0x14])); - assert_eq!(packet.dst_addr(), Address([0x21, 0x22, 0x23, 0x24])); + assert_eq!(packet.src_addr(), Address::new(0x11, 0x12, 0x13, 0x14)); + assert_eq!(packet.dst_addr(), Address::new(0x21, 0x22, 0x23, 0x24)); assert!(packet.verify_checksum()); assert_eq!(packet.payload(), &PAYLOAD_BYTES[..]); } @@ -849,8 +775,8 @@ pub(crate) mod test { packet.set_frag_offset(0x203 * 8); packet.set_hop_limit(0x1a); packet.set_next_header(Protocol::Icmp); - packet.set_src_addr(Address([0x11, 0x12, 0x13, 0x14])); - packet.set_dst_addr(Address([0x21, 0x22, 0x23, 0x24])); + packet.set_src_addr(Address::new(0x11, 0x12, 0x13, 0x14)); + packet.set_dst_addr(Address::new(0x21, 0x22, 0x23, 0x24)); packet.fill_checksum(); packet.payload_mut().copy_from_slice(&PAYLOAD_BYTES[..]); assert_eq!(&*packet.into_inner(), &PACKET_BYTES[..]); @@ -890,8 +816,8 @@ pub(crate) mod test { const fn packet_repr() -> Repr { Repr { - src_addr: Address([0x11, 0x12, 0x13, 0x14]), - dst_addr: Address([0x21, 0x22, 0x23, 0x24]), + src_addr: Address::new(0x11, 0x12, 0x13, 0x14), + dst_addr: Address::new(0x21, 0x22, 0x23, 0x24), next_header: Protocol::Icmp, payload_len: 4, hop_limit: 64, @@ -1017,124 +943,135 @@ pub(crate) mod test { #[test] fn test_cidr_from_netmask() { - assert!(Cidr::from_netmask(Address([0, 0, 0, 0]), Address([1, 0, 2, 0])).is_err()); - assert!(Cidr::from_netmask(Address([0, 0, 0, 0]), Address([0, 0, 0, 0])).is_err()); + assert!(Cidr::from_netmask(Address::new(0, 0, 0, 0), Address::new(1, 0, 2, 0)).is_err()); + assert!(Cidr::from_netmask(Address::new(0, 0, 0, 0), Address::new(0, 0, 0, 0)).is_err()); assert_eq!( - Cidr::from_netmask(Address([0, 0, 0, 1]), Address([255, 255, 255, 0])).unwrap(), - Cidr::new(Address([0, 0, 0, 1]), 24) + Cidr::from_netmask(Address::new(0, 0, 0, 1), Address::new(255, 255, 255, 0)).unwrap(), + Cidr::new(Address::new(0, 0, 0, 1), 24) ); assert_eq!( - Cidr::from_netmask(Address([192, 168, 0, 1]), Address([255, 255, 0, 0])).unwrap(), - Cidr::new(Address([192, 168, 0, 1]), 16) + Cidr::from_netmask(Address::new(192, 168, 0, 1), Address::new(255, 255, 0, 0)).unwrap(), + Cidr::new(Address::new(192, 168, 0, 1), 16) ); assert_eq!( - Cidr::from_netmask(Address([172, 16, 0, 1]), Address([255, 240, 0, 0])).unwrap(), - Cidr::new(Address([172, 16, 0, 1]), 12) + Cidr::from_netmask(Address::new(172, 16, 0, 1), Address::new(255, 240, 0, 0)).unwrap(), + Cidr::new(Address::new(172, 16, 0, 1), 12) ); assert_eq!( - Cidr::from_netmask(Address([255, 255, 255, 1]), Address([255, 255, 255, 0])).unwrap(), - Cidr::new(Address([255, 255, 255, 1]), 24) + Cidr::from_netmask( + Address::new(255, 255, 255, 1), + Address::new(255, 255, 255, 0) + ) + .unwrap(), + Cidr::new(Address::new(255, 255, 255, 1), 24) ); assert_eq!( - Cidr::from_netmask(Address([255, 255, 255, 255]), Address([255, 255, 255, 255])) - .unwrap(), - Cidr::new(Address([255, 255, 255, 255]), 32) + Cidr::from_netmask( + Address::new(255, 255, 255, 255), + Address::new(255, 255, 255, 255) + ) + .unwrap(), + Cidr::new(Address::new(255, 255, 255, 255), 32) ); } #[test] fn test_cidr_netmask() { assert_eq!( - Cidr::new(Address([0, 0, 0, 0]), 0).netmask(), - Address([0, 0, 0, 0]) + Cidr::new(Address::new(0, 0, 0, 0), 0).netmask(), + Address::new(0, 0, 0, 0) ); assert_eq!( - Cidr::new(Address([0, 0, 0, 1]), 24).netmask(), - Address([255, 255, 255, 0]) + Cidr::new(Address::new(0, 0, 0, 1), 24).netmask(), + Address::new(255, 255, 255, 0) ); assert_eq!( - Cidr::new(Address([0, 0, 0, 0]), 32).netmask(), - Address([255, 255, 255, 255]) + Cidr::new(Address::new(0, 0, 0, 0), 32).netmask(), + Address::new(255, 255, 255, 255) ); assert_eq!( - Cidr::new(Address([127, 0, 0, 0]), 8).netmask(), - Address([255, 0, 0, 0]) + Cidr::new(Address::new(127, 0, 0, 0), 8).netmask(), + Address::new(255, 0, 0, 0) ); assert_eq!( - Cidr::new(Address([192, 168, 0, 0]), 16).netmask(), - Address([255, 255, 0, 0]) + Cidr::new(Address::new(192, 168, 0, 0), 16).netmask(), + Address::new(255, 255, 0, 0) ); assert_eq!( - Cidr::new(Address([192, 168, 1, 1]), 16).netmask(), - Address([255, 255, 0, 0]) + Cidr::new(Address::new(192, 168, 1, 1), 16).netmask(), + Address::new(255, 255, 0, 0) ); assert_eq!( - Cidr::new(Address([192, 168, 1, 1]), 17).netmask(), - Address([255, 255, 128, 0]) + Cidr::new(Address::new(192, 168, 1, 1), 17).netmask(), + Address::new(255, 255, 128, 0) ); assert_eq!( - Cidr::new(Address([172, 16, 0, 0]), 12).netmask(), - Address([255, 240, 0, 0]) + Cidr::new(Address::new(172, 16, 0, 0), 12).netmask(), + Address::new(255, 240, 0, 0) ); assert_eq!( - Cidr::new(Address([255, 255, 255, 1]), 24).netmask(), - Address([255, 255, 255, 0]) + Cidr::new(Address::new(255, 255, 255, 1), 24).netmask(), + Address::new(255, 255, 255, 0) ); assert_eq!( - Cidr::new(Address([255, 255, 255, 255]), 32).netmask(), - Address([255, 255, 255, 255]) + Cidr::new(Address::new(255, 255, 255, 255), 32).netmask(), + Address::new(255, 255, 255, 255) ); } #[test] fn test_cidr_broadcast() { assert_eq!( - Cidr::new(Address([0, 0, 0, 0]), 0).broadcast().unwrap(), - Address([255, 255, 255, 255]) + Cidr::new(Address::new(0, 0, 0, 0), 0).broadcast().unwrap(), + Address::new(255, 255, 255, 255) ); assert_eq!( - Cidr::new(Address([0, 0, 0, 1]), 24).broadcast().unwrap(), - Address([0, 0, 0, 255]) + Cidr::new(Address::new(0, 0, 0, 1), 24).broadcast().unwrap(), + Address::new(0, 0, 0, 255) ); - assert_eq!(Cidr::new(Address([0, 0, 0, 0]), 32).broadcast(), None); + assert_eq!(Cidr::new(Address::new(0, 0, 0, 0), 32).broadcast(), None); assert_eq!( - Cidr::new(Address([127, 0, 0, 0]), 8).broadcast().unwrap(), - Address([127, 255, 255, 255]) + Cidr::new(Address::new(127, 0, 0, 0), 8) + .broadcast() + .unwrap(), + Address::new(127, 255, 255, 255) ); assert_eq!( - Cidr::new(Address([192, 168, 0, 0]), 16) + Cidr::new(Address::new(192, 168, 0, 0), 16) .broadcast() .unwrap(), - Address([192, 168, 255, 255]) + Address::new(192, 168, 255, 255) ); assert_eq!( - Cidr::new(Address([192, 168, 1, 1]), 16) + Cidr::new(Address::new(192, 168, 1, 1), 16) .broadcast() .unwrap(), - Address([192, 168, 255, 255]) + Address::new(192, 168, 255, 255) ); assert_eq!( - Cidr::new(Address([192, 168, 1, 1]), 17) + Cidr::new(Address::new(192, 168, 1, 1), 17) .broadcast() .unwrap(), - Address([192, 168, 127, 255]) + Address::new(192, 168, 127, 255) ); assert_eq!( - Cidr::new(Address([172, 16, 0, 1]), 12).broadcast().unwrap(), - Address([172, 31, 255, 255]) + Cidr::new(Address::new(172, 16, 0, 1), 12) + .broadcast() + .unwrap(), + Address::new(172, 31, 255, 255) ); assert_eq!( - Cidr::new(Address([255, 255, 255, 1]), 24) + Cidr::new(Address::new(255, 255, 255, 1), 24) .broadcast() .unwrap(), - Address([255, 255, 255, 255]) + Address::new(255, 255, 255, 255) ); assert_eq!( - Cidr::new(Address([255, 255, 255, 254]), 31).broadcast(), + Cidr::new(Address::new(255, 255, 255, 254), 31).broadcast(), None ); assert_eq!( - Cidr::new(Address([255, 255, 255, 255]), 32).broadcast(), + Cidr::new(Address::new(255, 255, 255, 255), 32).broadcast(), None ); } @@ -1142,44 +1079,44 @@ pub(crate) mod test { #[test] fn test_cidr_network() { assert_eq!( - Cidr::new(Address([0, 0, 0, 0]), 0).network(), - Cidr::new(Address([0, 0, 0, 0]), 0) + Cidr::new(Address::new(0, 0, 0, 0), 0).network(), + Cidr::new(Address::new(0, 0, 0, 0), 0) ); assert_eq!( - Cidr::new(Address([0, 0, 0, 1]), 24).network(), - Cidr::new(Address([0, 0, 0, 0]), 24) + Cidr::new(Address::new(0, 0, 0, 1), 24).network(), + Cidr::new(Address::new(0, 0, 0, 0), 24) ); assert_eq!( - Cidr::new(Address([0, 0, 0, 0]), 32).network(), - Cidr::new(Address([0, 0, 0, 0]), 32) + Cidr::new(Address::new(0, 0, 0, 0), 32).network(), + Cidr::new(Address::new(0, 0, 0, 0), 32) ); assert_eq!( - Cidr::new(Address([127, 0, 0, 0]), 8).network(), - Cidr::new(Address([127, 0, 0, 0]), 8) + Cidr::new(Address::new(127, 0, 0, 0), 8).network(), + Cidr::new(Address::new(127, 0, 0, 0), 8) ); assert_eq!( - Cidr::new(Address([192, 168, 0, 0]), 16).network(), - Cidr::new(Address([192, 168, 0, 0]), 16) + Cidr::new(Address::new(192, 168, 0, 0), 16).network(), + Cidr::new(Address::new(192, 168, 0, 0), 16) ); assert_eq!( - Cidr::new(Address([192, 168, 1, 1]), 16).network(), - Cidr::new(Address([192, 168, 0, 0]), 16) + Cidr::new(Address::new(192, 168, 1, 1), 16).network(), + Cidr::new(Address::new(192, 168, 0, 0), 16) ); assert_eq!( - Cidr::new(Address([192, 168, 1, 1]), 17).network(), - Cidr::new(Address([192, 168, 0, 0]), 17) + Cidr::new(Address::new(192, 168, 1, 1), 17).network(), + Cidr::new(Address::new(192, 168, 0, 0), 17) ); assert_eq!( - Cidr::new(Address([172, 16, 0, 1]), 12).network(), - Cidr::new(Address([172, 16, 0, 0]), 12) + Cidr::new(Address::new(172, 16, 0, 1), 12).network(), + Cidr::new(Address::new(172, 16, 0, 0), 12) ); assert_eq!( - Cidr::new(Address([255, 255, 255, 1]), 24).network(), - Cidr::new(Address([255, 255, 255, 0]), 24) + Cidr::new(Address::new(255, 255, 255, 1), 24).network(), + Cidr::new(Address::new(255, 255, 255, 0), 24) ); assert_eq!( - Cidr::new(Address([255, 255, 255, 255]), 32).network(), - Cidr::new(Address([255, 255, 255, 255]), 32) + Cidr::new(Address::new(255, 255, 255, 255), 32).network(), + Cidr::new(Address::new(255, 255, 255, 255), 32) ); } } diff --git a/src/wire/ipv6.rs b/src/wire/ipv6.rs index e13c8edf4..8dc05c51d 100644 --- a/src/wire/ipv6.rs +++ b/src/wire/ipv6.rs @@ -5,8 +5,6 @@ use core::fmt; use super::{Error, Result}; use crate::wire::ip::pretty_print_ip_payload; -#[cfg(feature = "proto-ipv4")] -use crate::wire::ipv4; pub use super::IpProtocol as Protocol; @@ -20,10 +18,25 @@ pub const MIN_MTU: usize = 1280; /// [RFC 8200 § 2]: https://www.rfc-editor.org/rfc/rfc4291#section-2 pub const ADDR_SIZE: usize = 16; -/// Size of IPv4-mapping prefix in octets. +/// The link-local [all nodes multicast address]. /// -/// [RFC 8200 § 2]: https://www.rfc-editor.org/rfc/rfc4291#section-2 -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 +/// [all nodes multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7.1 +pub const LINK_LOCAL_ALL_NODES: Address = Address::new(0xff02, 0, 0, 0, 0, 0, 0, 1); + +/// The link-local [all routers multicast address]. +/// +/// [all routers multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7.1 +pub const LINK_LOCAL_ALL_ROUTERS: Address = Address::new(0xff02, 0, 0, 0, 0, 0, 0, 2); + +/// The link-local [all MLVDv2-capable routers multicast address]. +/// +/// [all MLVDv2-capable routers multicast address]: https://tools.ietf.org/html/rfc3810#section-11 +pub const LINK_LOCAL_ALL_MLDV2_ROUTERS: Address = Address::new(0xff02, 0, 0, 0, 0, 0, 0, 0x16); + +/// The link-local [all RPL nodes multicast address]. +/// +/// [all RPL nodes multicast address]: https://www.rfc-editor.org/rfc/rfc6550.html#section-20.19 +pub const LINK_LOCAL_ALL_RPL_NODES: Address = Address::new(0xff02, 0, 0, 0, 0, 0, 0, 0x1a); /// The [scope] of an address. /// @@ -61,211 +74,92 @@ impl From for MulticastScope { } } -/// A sixteen-octet IPv6 address. -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)] -pub struct Address(pub [u8; ADDR_SIZE]); - -impl Address { - /// The [unspecified address]. - /// - /// [unspecified address]: https://tools.ietf.org/html/rfc4291#section-2.5.2 - pub const UNSPECIFIED: Address = Address([0x00; ADDR_SIZE]); +pub use core::net::Ipv6Addr as Address; - /// The link-local [all nodes multicast address]. +pub(crate) trait AddressExt { + /// Construct an IPv6 address from a sequence of octets, in big-endian. /// - /// [all nodes multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7.1 - pub const LINK_LOCAL_ALL_NODES: Address = Address([ - 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, - ]); + /// # Panics + /// The function panics if `data` is not sixteen octets long. + fn from_bytes(data: &[u8]) -> Address; - /// The link-local [all routers multicast address]. + /// Query whether the IPv6 address is an [unicast address]. /// - /// [all routers multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7.1 - pub const LINK_LOCAL_ALL_ROUTERS: Address = Address([ - 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, - ]); - - /// The link-local [all MLVDv2-capable routers multicast address]. + /// [unicast address]: https://tools.ietf.org/html/rfc4291#section-2.5 /// - /// [all MLVDv2-capable routers multicast address]: https://tools.ietf.org/html/rfc3810#section-11 - pub const LINK_LOCAL_ALL_MLDV2_ROUTERS: Address = Address([ - 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x16, - ]); + /// `x_` prefix is to avoid a collision with the still-unstable method in `core::ip`. + fn x_is_unicast(&self) -> bool; - /// The link-local [all RPL nodes multicast address]. + /// Query whether the IPv6 address is a [global unicast address]. /// - /// [all RPL nodes multicast address]: https://www.rfc-editor.org/rfc/rfc6550.html#section-20.19 - pub const LINK_LOCAL_ALL_RPL_NODES: Address = Address([ - 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1a, - ]); + /// [global unicast address]: https://datatracker.ietf.org/doc/html/rfc3587 + fn is_global_unicast(&self) -> bool; - /// The [loopback address]. + /// Query whether the IPv6 address is in the [link-local] scope. /// - /// [loopback address]: https://tools.ietf.org/html/rfc4291#section-2.5.3 - pub const LOOPBACK: Address = Address([ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, - ]); + /// [link-local]: https://tools.ietf.org/html/rfc4291#section-2.5.6 + fn is_link_local(&self) -> bool; - /// The prefix used in [IPv4-mapped addresses]. + /// Query whether the IPv6 address is a [Unique Local Address] (ULA). /// - /// [IPv4-mapped addresses]: https://www.rfc-editor.org/rfc/rfc4291#section-2.5.5.2 - pub const IPV4_MAPPED_PREFIX: [u8; IPV4_MAPPED_PREFIX_SIZE] = - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff]; - - /// Construct an IPv6 address from parts. - #[allow(clippy::too_many_arguments)] - pub const fn new( - a0: u16, - a1: u16, - a2: u16, - a3: u16, - a4: u16, - a5: u16, - a6: u16, - a7: u16, - ) -> Address { - Address([ - (a0 >> 8) as u8, - a0 as u8, - (a1 >> 8) as u8, - a1 as u8, - (a2 >> 8) as u8, - a2 as u8, - (a3 >> 8) as u8, - a3 as u8, - (a4 >> 8) as u8, - a4 as u8, - (a5 >> 8) as u8, - a5 as u8, - (a6 >> 8) as u8, - a6 as u8, - (a7 >> 8) as u8, - a7 as u8, - ]) - } - - /// Construct an IPv6 address from a sequence of octets, in big-endian. + /// [Unique Local Address]: https://tools.ietf.org/html/rfc4193 /// - /// # Panics - /// The function panics if `data` is not sixteen octets long. - pub fn from_bytes(data: &[u8]) -> Address { - let mut bytes = [0; ADDR_SIZE]; - bytes.copy_from_slice(data); - Address(bytes) - } + /// `x_` prefix is to avoid a collision with the still-unstable method in `core::ip`. + fn x_is_unique_local(&self) -> bool; - /// Construct an IPv6 address from a sequence of words, in big-endian. + /// Helper function used to mask an address given a prefix. /// /// # Panics - /// The function panics if `data` is not 8 words long. - pub fn from_parts(data: &[u16]) -> Address { - assert!(data.len() >= 8); - let mut bytes = [0; ADDR_SIZE]; - for (word_idx, chunk) in bytes.chunks_mut(2).enumerate() { - NetworkEndian::write_u16(chunk, data[word_idx]); - } - Address(bytes) - } + /// This function panics if `mask` is greater than 128. + fn mask(&self, mask: u8) -> [u8; ADDR_SIZE]; - /// Write a IPv6 address to the given slice. + /// The solicited node for the given unicast address. /// /// # Panics - /// The function panics if `data` is not 8 words long. - pub fn write_parts(&self, data: &mut [u16]) { - assert!(data.len() >= 8); - for (i, chunk) in self.0.chunks(2).enumerate() { - data[i] = NetworkEndian::read_u16(chunk); - } - } - - /// Return an IPv6 address as a sequence of octets, in big-endian. - pub const fn as_bytes(&self) -> &[u8] { - &self.0 - } - - /// Query whether the IPv6 address is an [unicast address]. - /// - /// [unicast address]: https://tools.ietf.org/html/rfc4291#section-2.5 - pub fn is_unicast(&self) -> bool { - !(self.is_multicast() || self.is_unspecified()) - } + /// This function panics if the given address is not + /// unicast. + fn solicited_node(&self) -> Address; - /// Query whether the IPv6 address is a [global unicast address]. + /// Return the scope of the address. /// - /// [global unicast address]: https://datatracker.ietf.org/doc/html/rfc3587 - pub const fn is_global_unicast(&self) -> bool { - (self.0[0] >> 5) == 0b001 - } + /// `x_` prefix is to avoid a collision with the still-unstable method in `core::ip`. + fn x_multicast_scope(&self) -> MulticastScope; - /// Query whether the IPv6 address is a [multicast address]. - /// - /// [multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7 - pub const fn is_multicast(&self) -> bool { - self.0[0] == 0xff - } + /// If `self` is a CIDR-compatible subnet mask, return `Some(prefix_len)`, + /// where `prefix_len` is the number of leading zeroes. Return `None` otherwise. + fn prefix_len(&self) -> Option; +} - /// Query whether the IPv6 address is the [unspecified address]. - /// - /// [unspecified address]: https://tools.ietf.org/html/rfc4291#section-2.5.2 - pub fn is_unspecified(&self) -> bool { - self.0 == [0x00; ADDR_SIZE] +impl AddressExt for Address { + fn from_bytes(data: &[u8]) -> Address { + let mut bytes = [0; ADDR_SIZE]; + bytes.copy_from_slice(data); + Address::from(bytes) } - /// Query whether the IPv6 address is in the [link-local] scope. - /// - /// [link-local]: https://tools.ietf.org/html/rfc4291#section-2.5.6 - pub fn is_link_local(&self) -> bool { - self.0[0..8] == [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + fn x_is_unicast(&self) -> bool { + !(self.is_multicast() || self.is_unspecified()) } - /// Query whether the IPv6 address is a [Unique Local Address] (ULA). - /// - /// [Unique Local Address]: https://tools.ietf.org/html/rfc4193 - pub fn is_unique_local(&self) -> bool { - (self.0[0] & 0b1111_1110) == 0xfc + fn is_global_unicast(&self) -> bool { + (self.octets()[0] >> 5) == 0b001 } - /// Query whether the IPv6 address is the [loopback address]. - /// - /// [loopback address]: https://tools.ietf.org/html/rfc4291#section-2.5.3 - pub fn is_loopback(&self) -> bool { - *self == Self::LOOPBACK + fn is_link_local(&self) -> bool { + self.octets()[0..8] == [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] } - /// Query whether the IPv6 address is an [IPv4 mapped IPv6 address]. - /// - /// [IPv4 mapped IPv6 address]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2 - pub fn is_ipv4_mapped(&self) -> bool { - self.0[..IPV4_MAPPED_PREFIX_SIZE] == Self::IPV4_MAPPED_PREFIX - } - - #[cfg(feature = "proto-ipv4")] - /// Convert an IPv4 mapped IPv6 address to an IPv4 address. - pub fn as_ipv4(&self) -> Option { - if self.is_ipv4_mapped() { - Some(ipv4::Address::from_bytes( - &self.0[IPV4_MAPPED_PREFIX_SIZE..], - )) - } else { - None - } + fn x_is_unique_local(&self) -> bool { + (self.octets()[0] & 0b1111_1110) == 0xfc } - /// Helper function used to mask an address given a prefix. - /// - /// # Panics - /// This function panics if `mask` is greater than 128. - pub(super) fn mask(&self, mask: u8) -> [u8; ADDR_SIZE] { + fn mask(&self, mask: u8) -> [u8; ADDR_SIZE] { assert!(mask <= 128); let mut bytes = [0u8; ADDR_SIZE]; let idx = (mask as usize) / 8; let modulus = (mask as usize) % 8; - let (first, second) = self.0.split_at(idx); + let octets = self.octets(); + let (first, second) = octets.split_at(idx); bytes[0..idx].copy_from_slice(first); if idx < ADDR_SIZE { let part = second[0]; @@ -274,28 +168,23 @@ impl Address { bytes } - /// The solicited node for the given unicast address. - /// - /// # Panics - /// This function panics if the given address is not - /// unicast. - pub fn solicited_node(&self) -> Address { - assert!(self.is_unicast()); - Address([ - 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, - self.0[13], self.0[14], self.0[15], + fn solicited_node(&self) -> Address { + assert!(self.x_is_unicast()); + let o = self.octets(); + Address::from([ + 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, o[13], + o[14], o[15], ]) } - /// Return the scope of the address. - pub(crate) fn multicast_scope(&self) -> MulticastScope { + fn x_multicast_scope(&self) -> MulticastScope { if self.is_multicast() { - return MulticastScope::from(self.as_bytes()[1] & 0b1111); + return MulticastScope::from(self.octets()[1] & 0b1111); } if self.is_link_local() { MulticastScope::LinkLocal - } else if self.is_unique_local() || self.is_global_unicast() { + } else if self.x_is_unique_local() || self.is_global_unicast() { // ULA are considered global scope // https://www.rfc-editor.org/rfc/rfc6724#section-3.1 MulticastScope::Global @@ -304,162 +193,34 @@ impl Address { } } - /// Convert to an `IpAddress`. - /// - /// Same as `.into()`, but works in `const`. - pub const fn into_address(self) -> super::IpAddress { - super::IpAddress::Ipv6(self) - } -} - -impl From<::core::net::Ipv6Addr> for Address { - fn from(x: ::core::net::Ipv6Addr) -> Address { - Address(x.octets()) - } -} - -impl From
for ::core::net::Ipv6Addr { - fn from(Address(x): Address) -> ::core::net::Ipv6Addr { - x.into() - } -} - -impl fmt::Display for Address { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.is_ipv4_mapped() { - return write!( - f, - "::ffff:{}.{}.{}.{}", - self.0[IPV4_MAPPED_PREFIX_SIZE + 0], - self.0[IPV4_MAPPED_PREFIX_SIZE + 1], - self.0[IPV4_MAPPED_PREFIX_SIZE + 2], - self.0[IPV4_MAPPED_PREFIX_SIZE + 3] - ); - } - - // The string representation of an IPv6 address should - // collapse a series of 16 bit sections that evaluate - // to 0 to "::" - // - // See https://tools.ietf.org/html/rfc4291#section-2.2 - // for details. - enum State { - Head, - HeadBody, - Tail, - TailBody, - } - let mut words = [0u16; 8]; - self.write_parts(&mut words); - let mut state = State::Head; - for word in words.iter() { - state = match (*word, &state) { - // Once a u16 equal to zero write a double colon and - // skip to the next non-zero u16. - (0, &State::Head) | (0, &State::HeadBody) => { - write!(f, "::")?; - State::Tail - } - // Continue iterating without writing any characters until - // we hit a non-zero value. - (0, &State::Tail) => State::Tail, - // When the state is Head or Tail write a u16 in hexadecimal - // without the leading colon if the value is not 0. - (_, &State::Head) => { - write!(f, "{word:x}")?; - State::HeadBody - } - (_, &State::Tail) => { - write!(f, "{word:x}")?; - State::TailBody - } - // Write the u16 with a leading colon when parsing a value - // that isn't the first in a section - (_, &State::HeadBody) | (_, &State::TailBody) => { - write!(f, ":{word:x}")?; - state - } - } - } - Ok(()) - } -} - -#[cfg(feature = "defmt")] -impl defmt::Format for Address { - fn format(&self, f: defmt::Formatter) { - if self.is_ipv4_mapped() { - return defmt::write!( - f, - "::ffff:{}.{}.{}.{}", - self.0[IPV4_MAPPED_PREFIX_SIZE + 0], - self.0[IPV4_MAPPED_PREFIX_SIZE + 1], - self.0[IPV4_MAPPED_PREFIX_SIZE + 2], - self.0[IPV4_MAPPED_PREFIX_SIZE + 3] - ); - } - - // The string representation of an IPv6 address should - // collapse a series of 16 bit sections that evaluate - // to 0 to "::" - // - // See https://tools.ietf.org/html/rfc4291#section-2.2 - // for details. - enum State { - Head, - HeadBody, - Tail, - TailBody, - } - let mut words = [0u16; 8]; - self.write_parts(&mut words); - let mut state = State::Head; - for word in words.iter() { - state = match (*word, &state) { - // Once a u16 equal to zero write a double colon and - // skip to the next non-zero u16. - (0, &State::Head) | (0, &State::HeadBody) => { - defmt::write!(f, "::"); - State::Tail - } - // Continue iterating without writing any characters until - // we hit a non-zero value. - (0, &State::Tail) => State::Tail, - // When the state is Head or Tail write a u16 in hexadecimal - // without the leading colon if the value is not 0. - (_, &State::Head) => { - defmt::write!(f, "{:x}", word); - State::HeadBody - } - (_, &State::Tail) => { - defmt::write!(f, "{:x}", word); - State::TailBody - } - // Write the u16 with a leading colon when parsing a value - // that isn't the first in a section - (_, &State::HeadBody) | (_, &State::TailBody) => { - defmt::write!(f, ":{:x}", word); - state + fn prefix_len(&self) -> Option { + let mut ones = true; + let mut prefix_len = 0; + for byte in self.octets() { + let mut mask = 0x80; + for _ in 0..8 { + let one = byte & mask != 0; + if ones { + // Expect 1s until first 0 + if one { + prefix_len += 1; + } else { + ones = false; + } + } else if one { + // 1 where 0 was expected + return None; } + mask >>= 1; } } - } -} - -#[cfg(feature = "proto-ipv4")] -/// Convert the given IPv4 address into a IPv4-mapped IPv6 address -impl From for Address { - fn from(address: ipv4::Address) -> Self { - let mut b = [0_u8; ADDR_SIZE]; - b[..Self::IPV4_MAPPED_PREFIX.len()].copy_from_slice(&Self::IPV4_MAPPED_PREFIX); - b[Self::IPV4_MAPPED_PREFIX.len()..].copy_from_slice(&address.0); - Self(b) + Some(prefix_len) } } /// A specification of an IPv6 CIDR block, containing an address and a variable-length /// subnet masking prefix length. -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)] +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] pub struct Cidr { address: Address, prefix_len: u8, @@ -470,10 +231,7 @@ impl Cidr { /// /// [solicited node prefix]: https://tools.ietf.org/html/rfc4291#section-2.7.1 pub const SOLICITED_NODE_PREFIX: Cidr = Cidr { - address: Address([ - 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, - 0x00, 0x00, - ]), + address: Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0), prefix_len: 104, }; @@ -763,14 +521,14 @@ impl + AsMut<[u8]>> Packet { #[inline] pub fn set_src_addr(&mut self, value: Address) { let data = self.buffer.as_mut(); - data[field::SRC_ADDR].copy_from_slice(value.as_bytes()); + data[field::SRC_ADDR].copy_from_slice(&value.octets()); } /// Set the destination address field. #[inline] pub fn set_dst_addr(&mut self, value: Address) { let data = self.buffer.as_mut(); - data[field::DST_ADDR].copy_from_slice(value.as_bytes()); + data[field::DST_ADDR].copy_from_slice(&value.octets()); } /// Return a mutable pointer to the payload. @@ -904,26 +662,17 @@ impl> PrettyPrint for Packet { #[cfg(test)] pub(crate) mod test { - use super::Error; - use super::{Address, Cidr}; - use super::{Packet, Protocol, Repr}; + use super::*; use crate::wire::pretty_print::PrettyPrinter; - #[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]); + pub(crate) const MOCK_IP_ADDR_1: Address = Address::new(0xfe80, 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]); + pub(crate) const MOCK_IP_ADDR_2: Address = Address::new(0xfe80, 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]); + pub(crate) const MOCK_IP_ADDR_3: Address = Address::new(0xfe80, 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]); + pub(crate) const MOCK_IP_ADDR_4: Address = Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 4); #[allow(unused)] pub(crate) const MOCK_UNSPECIFIED: Address = Address::UNSPECIFIED; @@ -933,18 +682,18 @@ pub(crate) mod test { #[test] fn test_basic_multicast() { - assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_unspecified()); - assert!(Address::LINK_LOCAL_ALL_ROUTERS.is_multicast()); - assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_link_local()); - assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_loopback()); - assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_unique_local()); - assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_global_unicast()); - assert!(!Address::LINK_LOCAL_ALL_NODES.is_unspecified()); - assert!(Address::LINK_LOCAL_ALL_NODES.is_multicast()); - assert!(!Address::LINK_LOCAL_ALL_NODES.is_link_local()); - assert!(!Address::LINK_LOCAL_ALL_NODES.is_loopback()); - assert!(!Address::LINK_LOCAL_ALL_NODES.is_unique_local()); - assert!(!Address::LINK_LOCAL_ALL_NODES.is_global_unicast()); + assert!(!LINK_LOCAL_ALL_ROUTERS.is_unspecified()); + assert!(LINK_LOCAL_ALL_ROUTERS.is_multicast()); + assert!(!LINK_LOCAL_ALL_ROUTERS.is_link_local()); + assert!(!LINK_LOCAL_ALL_ROUTERS.is_loopback()); + assert!(!LINK_LOCAL_ALL_ROUTERS.x_is_unique_local()); + assert!(!LINK_LOCAL_ALL_ROUTERS.is_global_unicast()); + assert!(!LINK_LOCAL_ALL_NODES.is_unspecified()); + assert!(LINK_LOCAL_ALL_NODES.is_multicast()); + assert!(!LINK_LOCAL_ALL_NODES.is_link_local()); + assert!(!LINK_LOCAL_ALL_NODES.is_loopback()); + assert!(!LINK_LOCAL_ALL_NODES.x_is_unique_local()); + assert!(!LINK_LOCAL_ALL_NODES.is_global_unicast()); } #[test] @@ -953,18 +702,18 @@ pub(crate) mod test { assert!(!LINK_LOCAL_ADDR.is_multicast()); assert!(LINK_LOCAL_ADDR.is_link_local()); assert!(!LINK_LOCAL_ADDR.is_loopback()); - assert!(!LINK_LOCAL_ADDR.is_unique_local()); + assert!(!LINK_LOCAL_ADDR.x_is_unique_local()); assert!(!LINK_LOCAL_ADDR.is_global_unicast()); } #[test] fn test_basic_loopback() { - assert!(!Address::LOOPBACK.is_unspecified()); - assert!(!Address::LOOPBACK.is_multicast()); - assert!(!Address::LOOPBACK.is_link_local()); - assert!(Address::LOOPBACK.is_loopback()); - assert!(!Address::LOOPBACK.is_unique_local()); - assert!(!Address::LOOPBACK.is_global_unicast()); + assert!(!Address::LOCALHOST.is_unspecified()); + assert!(!Address::LOCALHOST.is_multicast()); + assert!(!Address::LOCALHOST.is_link_local()); + assert!(Address::LOCALHOST.is_loopback()); + assert!(!Address::LOCALHOST.x_is_unique_local()); + assert!(!Address::LOCALHOST.is_global_unicast()); } #[test] @@ -973,7 +722,7 @@ pub(crate) mod test { assert!(!UNIQUE_LOCAL_ADDR.is_multicast()); assert!(!UNIQUE_LOCAL_ADDR.is_link_local()); assert!(!UNIQUE_LOCAL_ADDR.is_loopback()); - assert!(UNIQUE_LOCAL_ADDR.is_unique_local()); + assert!(UNIQUE_LOCAL_ADDR.x_is_unique_local()); assert!(!UNIQUE_LOCAL_ADDR.is_global_unicast()); } @@ -983,87 +732,10 @@ pub(crate) mod test { assert!(!GLOBAL_UNICAST_ADDR.is_multicast()); assert!(!GLOBAL_UNICAST_ADDR.is_link_local()); assert!(!GLOBAL_UNICAST_ADDR.is_loopback()); - assert!(!GLOBAL_UNICAST_ADDR.is_unique_local()); + assert!(!GLOBAL_UNICAST_ADDR.x_is_unique_local()); assert!(GLOBAL_UNICAST_ADDR.is_global_unicast()); } - #[test] - fn test_address_format() { - assert_eq!("ff02::1", format!("{}", Address::LINK_LOCAL_ALL_NODES)); - assert_eq!("fe80::1", format!("{LINK_LOCAL_ADDR}")); - assert_eq!( - "fe80::7f00:0:1", - format!( - "{}", - Address::new(0xfe80, 0, 0, 0, 0, 0x7f00, 0x0000, 0x0001) - ) - ); - assert_eq!("::", format!("{}", Address::UNSPECIFIED)); - assert_eq!("::1", format!("{}", Address::LOOPBACK)); - - #[cfg(feature = "proto-ipv4")] - assert_eq!( - "::ffff:192.168.1.1", - format!("{}", Address::from(Ipv4Address::new(192, 168, 1, 1))) - ); - } - - #[test] - fn test_new() { - assert_eq!( - Address::new(0xff02, 0, 0, 0, 0, 0, 0, 1), - Address::LINK_LOCAL_ALL_NODES - ); - assert_eq!( - Address::new(0xff02, 0, 0, 0, 0, 0, 0, 2), - Address::LINK_LOCAL_ALL_ROUTERS - ); - assert_eq!(Address::new(0, 0, 0, 0, 0, 0, 0, 1), Address::LOOPBACK); - assert_eq!(Address::new(0, 0, 0, 0, 0, 0, 0, 0), Address::UNSPECIFIED); - assert_eq!(Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), LINK_LOCAL_ADDR); - } - - #[test] - fn test_from_parts() { - assert_eq!( - Address::from_parts(&[0xff02, 0, 0, 0, 0, 0, 0, 1]), - Address::LINK_LOCAL_ALL_NODES - ); - assert_eq!( - Address::from_parts(&[0xff02, 0, 0, 0, 0, 0, 0, 2]), - Address::LINK_LOCAL_ALL_ROUTERS - ); - assert_eq!( - Address::from_parts(&[0, 0, 0, 0, 0, 0, 0, 1]), - Address::LOOPBACK - ); - assert_eq!( - Address::from_parts(&[0, 0, 0, 0, 0, 0, 0, 0]), - Address::UNSPECIFIED - ); - assert_eq!( - Address::from_parts(&[0xfe80, 0, 0, 0, 0, 0, 0, 1]), - LINK_LOCAL_ADDR - ); - } - - #[test] - fn test_write_parts() { - let mut bytes = [0u16; 8]; - { - Address::LOOPBACK.write_parts(&mut bytes); - assert_eq!(Address::LOOPBACK, Address::from_parts(&bytes)); - } - { - Address::LINK_LOCAL_ALL_ROUTERS.write_parts(&mut bytes); - assert_eq!(Address::LINK_LOCAL_ALL_ROUTERS, Address::from_parts(&bytes)); - } - { - LINK_LOCAL_ADDR.write_parts(&mut bytes); - assert_eq!(LINK_LOCAL_ADDR, Address::from_parts(&bytes)); - } - } - #[test] fn test_mask() { let addr = Address::new(0x0123, 0x4567, 0x89ab, 0, 0, 0, 0, 1); @@ -1089,35 +761,6 @@ pub(crate) mod test { ); } - #[cfg(feature = "proto-ipv4")] - #[test] - fn test_is_ipv4_mapped() { - assert!(!Address::UNSPECIFIED.is_ipv4_mapped()); - assert!(Address::from(Ipv4Address::new(192, 168, 1, 1)).is_ipv4_mapped()); - } - - #[cfg(feature = "proto-ipv4")] - #[test] - fn test_as_ipv4() { - assert_eq!(None, Address::UNSPECIFIED.as_ipv4()); - - let ipv4 = Ipv4Address::new(192, 168, 1, 1); - assert_eq!(Some(ipv4), Address::from(ipv4).as_ipv4()); - } - - #[cfg(feature = "proto-ipv4")] - #[test] - fn test_from_ipv4_address() { - assert_eq!( - Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1]), - Address::from(Ipv4Address::new(192, 168, 1, 1)) - ); - assert_eq!( - Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 222, 1, 41, 90]), - Address::from(Ipv4Address::new(222, 1, 41, 90)) - ); - } - #[test] fn test_cidr() { // fe80::1/56 @@ -1241,16 +884,19 @@ pub(crate) mod test { assert!(!cidr.contains_addr(&addr)); } - for subnet in subnets.iter().map(|&(a, p)| Cidr::new(Address(a), p)) { + for subnet in subnets.iter().map(|&(a, p)| Cidr::new(Address::from(a), p)) { assert!(cidr.contains_subnet(&subnet)); } - for subnet in not_subnets.iter().map(|&(a, p)| Cidr::new(Address(a), p)) { + for subnet in not_subnets + .iter() + .map(|&(a, p)| Cidr::new(Address::from(a), p)) + { assert!(!cidr.contains_subnet(&subnet)); } let cidr_without_prefix = Cidr::new(LINK_LOCAL_ADDR, 0); - assert!(cidr_without_prefix.contains_addr(&Address::LOOPBACK)); + assert!(cidr_without_prefix.contains_addr(&Address::LOCALHOST)); } #[test] @@ -1259,56 +905,56 @@ pub(crate) mod test { let _ = Address::from_bytes(&[0u8; 15]); } - #[test] - #[should_panic(expected = "data.len() >= 8")] - fn test_from_parts_too_long() { - let _ = Address::from_parts(&[0u16; 7]); - } - #[test] fn test_scope() { use super::*; assert_eq!( - Address::new(0xff01, 0, 0, 0, 0, 0, 0, 1).multicast_scope(), + Address::new(0xff01, 0, 0, 0, 0, 0, 0, 1).x_multicast_scope(), MulticastScope::InterfaceLocal ); assert_eq!( - Address::new(0xff02, 0, 0, 0, 0, 0, 0, 1).multicast_scope(), + Address::new(0xff02, 0, 0, 0, 0, 0, 0, 1).x_multicast_scope(), MulticastScope::LinkLocal ); assert_eq!( - Address::new(0xff03, 0, 0, 0, 0, 0, 0, 1).multicast_scope(), + Address::new(0xff03, 0, 0, 0, 0, 0, 0, 1).x_multicast_scope(), MulticastScope::Unknown ); assert_eq!( - Address::new(0xff04, 0, 0, 0, 0, 0, 0, 1).multicast_scope(), + Address::new(0xff04, 0, 0, 0, 0, 0, 0, 1).x_multicast_scope(), MulticastScope::AdminLocal ); assert_eq!( - Address::new(0xff05, 0, 0, 0, 0, 0, 0, 1).multicast_scope(), + Address::new(0xff05, 0, 0, 0, 0, 0, 0, 1).x_multicast_scope(), MulticastScope::SiteLocal ); assert_eq!( - Address::new(0xff08, 0, 0, 0, 0, 0, 0, 1).multicast_scope(), + Address::new(0xff08, 0, 0, 0, 0, 0, 0, 1).x_multicast_scope(), MulticastScope::OrganizationLocal ); assert_eq!( - Address::new(0xff0e, 0, 0, 0, 0, 0, 0, 1).multicast_scope(), + Address::new(0xff0e, 0, 0, 0, 0, 0, 0, 1).x_multicast_scope(), MulticastScope::Global ); assert_eq!( - Address::LINK_LOCAL_ALL_NODES.multicast_scope(), + LINK_LOCAL_ALL_NODES.x_multicast_scope(), MulticastScope::LinkLocal ); // For source address selection, unicast addresses also have a scope: - assert_eq!(LINK_LOCAL_ADDR.multicast_scope(), MulticastScope::LinkLocal); assert_eq!( - GLOBAL_UNICAST_ADDR.multicast_scope(), + LINK_LOCAL_ADDR.x_multicast_scope(), + MulticastScope::LinkLocal + ); + assert_eq!( + GLOBAL_UNICAST_ADDR.x_multicast_scope(), + MulticastScope::Global + ); + assert_eq!( + UNIQUE_LOCAL_ADDR.x_multicast_scope(), MulticastScope::Global ); - assert_eq!(UNIQUE_LOCAL_ADDR.multicast_scope(), MulticastScope::Global); } static REPR_PACKET_BYTES: [u8; 52] = [ @@ -1323,11 +969,8 @@ pub(crate) mod test { const fn packet_repr() -> Repr { Repr { - src_addr: Address([ - 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, - ]), - dst_addr: Address::LINK_LOCAL_ALL_NODES, + src_addr: Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), + dst_addr: LINK_LOCAL_ALL_NODES, next_header: Protocol::Udp, payload_len: 12, hop_limit: 64, @@ -1345,14 +988,8 @@ pub(crate) mod test { assert_eq!(packet.payload_len() as usize, REPR_PAYLOAD_BYTES.len()); assert_eq!(packet.next_header(), Protocol::Udp); assert_eq!(packet.hop_limit(), 0x40); - assert_eq!( - packet.src_addr(), - Address([ - 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01 - ]) - ); - assert_eq!(packet.dst_addr(), Address::LINK_LOCAL_ALL_NODES); + assert_eq!(packet.src_addr(), Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)); + assert_eq!(packet.dst_addr(), LINK_LOCAL_ALL_NODES); assert_eq!(packet.payload(), &REPR_PAYLOAD_BYTES[..]); } @@ -1374,8 +1011,8 @@ pub(crate) mod test { packet.set_payload_len(0xc); packet.set_next_header(Protocol::Udp); packet.set_hop_limit(0xfe); - packet.set_src_addr(Address::LINK_LOCAL_ALL_ROUTERS); - packet.set_dst_addr(Address::LINK_LOCAL_ALL_NODES); + packet.set_src_addr(LINK_LOCAL_ALL_ROUTERS); + packet.set_dst_addr(LINK_LOCAL_ALL_NODES); packet .payload_mut() .copy_from_slice(&REPR_PAYLOAD_BYTES[..]); diff --git a/src/wire/ipv6option.rs b/src/wire/ipv6option.rs index 998df887a..ffa2a14de 100644 --- a/src/wire/ipv6option.rs +++ b/src/wire/ipv6option.rs @@ -51,19 +51,42 @@ impl RouterAlert { pub const DATA_LEN: u8 = 2; } -enum_with_unknown! { - /// Action required when parsing the given IPv6 Extension - /// Header Option Type fails - pub enum FailureType(u8) { - /// Skip this option and continue processing the packet - Skip = 0b00000000, - /// Discard the containing packet - Discard = 0b01000000, - /// Discard the containing packet and notify the sender - DiscardSendAll = 0b10000000, - /// Discard the containing packet and only notify the sender - /// if the sender is a unicast address - DiscardSendUnicast = 0b11000000, +/// Action required when parsing the given IPv6 Extension +/// Header Option Type fails +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum FailureType { + /// Skip this option and continue processing the packet + Skip = 0b00000000, + /// Discard the containing packet + Discard = 0b01000000, + /// Discard the containing packet and notify the sender + DiscardSendAll = 0b10000000, + /// Discard the containing packet and only notify the sender + /// if the sender is a unicast address + DiscardSendUnicast = 0b11000000, +} + +impl From for FailureType { + fn from(value: u8) -> FailureType { + match value & 0b11000000 { + 0b00000000 => FailureType::Skip, + 0b01000000 => FailureType::Discard, + 0b10000000 => FailureType::DiscardSendAll, + 0b11000000 => FailureType::DiscardSendUnicast, + _ => unreachable!(), + } + } +} + +impl From for u8 { + fn from(value: FailureType) -> Self { + match value { + FailureType::Skip => 0b00000000, + FailureType::Discard => 0b01000000, + FailureType::DiscardSendAll => 0b10000000, + FailureType::DiscardSendUnicast => 0b11000000, + } } } @@ -74,7 +97,6 @@ impl fmt::Display for FailureType { FailureType::Discard => write!(f, "discard"), FailureType::DiscardSendAll => write!(f, "discard and send error"), FailureType::DiscardSendUnicast => write!(f, "discard and send error if unicast"), - FailureType::Unknown(id) => write!(f, "Unknown({id})"), } } } diff --git a/src/wire/ipv6routing.rs b/src/wire/ipv6routing.rs index a2b91e9ce..530eac6e9 100644 --- a/src/wire/ipv6routing.rs +++ b/src/wire/ipv6routing.rs @@ -1,7 +1,7 @@ use super::{Error, Result}; use core::fmt; -use crate::wire::Ipv6Address as Address; +use crate::wire::{Ipv6Address as Address, Ipv6AddressExt}; enum_with_unknown! { /// IPv6 Extension Routing Header Routing Type @@ -286,7 +286,7 @@ impl + AsMut<[u8]>> Header { /// This function may panic if this header is not the Type 2 Routing Header routing type. pub fn set_home_address(&mut self, value: Address) { let data = self.buffer.as_mut(); - data[field::HOME_ADDRESS].copy_from_slice(value.as_bytes()); + data[field::HOME_ADDRESS].copy_from_slice(&value.octets()); } } @@ -399,7 +399,7 @@ impl<'a> Repr<'a> { pub const fn buffer_len(&self) -> usize { match self { // Routing Type + Segments Left + Reserved + Home Address - Repr::Type2 { home_address, .. } => 2 + 4 + home_address.as_bytes().len(), + Repr::Type2 { home_address, .. } => 2 + 4 + home_address.octets().len(), Repr::Rpl { addresses, .. } => 2 + 4 + addresses.len(), } } @@ -484,7 +484,7 @@ mod test { // A representation of a Type 2 Routing header static REPR_TYPE2: Repr = Repr::Type2 { segments_left: 1, - home_address: Address::LOOPBACK, + home_address: Address::LOCALHOST, }; // A Source Routing Header with full IPv6 addresses in bytes @@ -552,7 +552,7 @@ mod test { let header = Header::new_unchecked(&BYTES_TYPE2[..]); assert_eq!(header.routing_type(), Type::Type2); assert_eq!(header.segments_left(), 1); - assert_eq!(header.home_address(), Address::LOOPBACK); + assert_eq!(header.home_address(), Address::LOCALHOST); let header = Header::new_unchecked(&BYTES_SRH_FULL[..]); assert_eq!(header.routing_type(), Type::Rpl); diff --git a/src/wire/mld.rs b/src/wire/mld.rs index bb5567067..058fb81ce 100644 --- a/src/wire/mld.rs +++ b/src/wire/mld.rs @@ -8,7 +8,7 @@ use byteorder::{ByteOrder, NetworkEndian}; use super::{Error, Result}; use crate::wire::icmpv6::{field, Message, Packet}; -use crate::wire::Ipv6Address; +use crate::wire::{Ipv6Address, Ipv6AddressExt}; enum_with_unknown! { /// MLDv2 Multicast Listener Report Record Type. See [RFC 3810 § 5.2.12] for @@ -110,7 +110,7 @@ impl + AsMut<[u8]>> Packet { #[inline] pub fn set_mcast_addr(&mut self, addr: Ipv6Address) { let data = self.buffer.as_mut(); - data[field::QUERY_MCAST_ADDR].copy_from_slice(addr.as_bytes()); + data[field::QUERY_MCAST_ADDR].copy_from_slice(&addr.octets()); } /// Set the Suppress Router-Side Processing flag. @@ -281,7 +281,7 @@ impl + AsRef<[u8]>> AddressRecord { pub fn set_mcast_addr(&mut self, addr: Ipv6Address) { assert!(addr.is_multicast()); let data = self.buffer.as_mut(); - data[field::RECORD_MCAST_ADDR].copy_from_slice(addr.as_bytes()); + data[field::RECORD_MCAST_ADDR].copy_from_slice(&addr.octets()); } } @@ -460,7 +460,7 @@ mod test { use super::*; use crate::phy::ChecksumCapabilities; use crate::wire::icmpv6::Message; - use crate::wire::Icmpv6Repr; + use crate::wire::{Icmpv6Repr, IPV6_LINK_LOCAL_ALL_NODES, IPV6_LINK_LOCAL_ALL_ROUTERS}; static QUERY_PACKET_BYTES: [u8; 44] = [ 0x82, 0x00, 0x73, 0x74, 0x04, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -489,7 +489,7 @@ mod test { match ty { Message::MldQuery => Icmpv6Repr::Mld(Repr::Query { max_resp_code: 0x400, - mcast_addr: Ipv6Address::LINK_LOCAL_ALL_NODES, + mcast_addr: IPV6_LINK_LOCAL_ALL_NODES, s_flag: true, qrv: 0x02, qqic: 0x12, @@ -513,14 +513,14 @@ mod test { assert_eq!(packet.msg_code(), 0); assert_eq!(packet.checksum(), 0x7374); assert_eq!(packet.max_resp_code(), 0x0400); - assert_eq!(packet.mcast_addr(), Ipv6Address::LINK_LOCAL_ALL_NODES); + assert_eq!(packet.mcast_addr(), IPV6_LINK_LOCAL_ALL_NODES); assert!(packet.s_flag()); assert_eq!(packet.qrv(), 0x02); assert_eq!(packet.qqic(), 0x12); assert_eq!(packet.num_srcs(), 0x01); assert_eq!( Ipv6Address::from_bytes(packet.payload()), - Ipv6Address::LINK_LOCAL_ALL_ROUTERS + IPV6_LINK_LOCAL_ALL_ROUTERS ); } @@ -531,19 +531,16 @@ mod test { packet.set_msg_type(Message::MldQuery); packet.set_msg_code(0); packet.set_max_resp_code(0x0400); - packet.set_mcast_addr(Ipv6Address::LINK_LOCAL_ALL_NODES); + packet.set_mcast_addr(IPV6_LINK_LOCAL_ALL_NODES); packet.set_s_flag(); packet.set_qrv(0x02); packet.set_qqic(0x12); packet.set_num_srcs(0x01); packet .payload_mut() - .copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes()); + .copy_from_slice(&IPV6_LINK_LOCAL_ALL_ROUTERS.octets()); packet.clear_reserved(); - packet.fill_checksum( - &Ipv6Address::LINK_LOCAL_ALL_NODES, - &Ipv6Address::LINK_LOCAL_ALL_ROUTERS, - ); + packet.fill_checksum(&IPV6_LINK_LOCAL_ALL_NODES, &IPV6_LINK_LOCAL_ALL_ROUTERS); assert_eq!(&*packet.into_inner(), &QUERY_PACKET_BYTES[..]); } @@ -558,10 +555,10 @@ mod test { assert_eq!(addr_rcrd.record_type(), RecordType::ModeIsInclude); assert_eq!(addr_rcrd.aux_data_len(), 0x00); assert_eq!(addr_rcrd.num_srcs(), 0x01); - assert_eq!(addr_rcrd.mcast_addr(), Ipv6Address::LINK_LOCAL_ALL_NODES); + assert_eq!(addr_rcrd.mcast_addr(), IPV6_LINK_LOCAL_ALL_NODES); assert_eq!( Ipv6Address::from_bytes(addr_rcrd.payload()), - Ipv6Address::LINK_LOCAL_ALL_ROUTERS + IPV6_LINK_LOCAL_ALL_ROUTERS ); } @@ -578,15 +575,12 @@ mod test { addr_rcrd.set_record_type(RecordType::ModeIsInclude); addr_rcrd.set_aux_data_len(0); addr_rcrd.set_num_srcs(1); - addr_rcrd.set_mcast_addr(Ipv6Address::LINK_LOCAL_ALL_NODES); + addr_rcrd.set_mcast_addr(IPV6_LINK_LOCAL_ALL_NODES); addr_rcrd .payload_mut() - .copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes()); + .copy_from_slice(&IPV6_LINK_LOCAL_ALL_ROUTERS.octets()); } - packet.fill_checksum( - &Ipv6Address::LINK_LOCAL_ALL_NODES, - &Ipv6Address::LINK_LOCAL_ALL_ROUTERS, - ); + packet.fill_checksum(&IPV6_LINK_LOCAL_ALL_NODES, &IPV6_LINK_LOCAL_ALL_ROUTERS); assert_eq!(&*packet.into_inner(), &REPORT_PACKET_BYTES[..]); } @@ -594,8 +588,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, - &Ipv6Address::LINK_LOCAL_ALL_ROUTERS, + &IPV6_LINK_LOCAL_ALL_NODES, + &IPV6_LINK_LOCAL_ALL_ROUTERS, &packet, &ChecksumCapabilities::default(), ); @@ -606,8 +600,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, - &Ipv6Address::LINK_LOCAL_ALL_ROUTERS, + &IPV6_LINK_LOCAL_ALL_NODES, + &IPV6_LINK_LOCAL_ALL_ROUTERS, &packet, &ChecksumCapabilities::default(), ); @@ -620,8 +614,8 @@ mod test { let mut packet = Packet::new_unchecked(&mut bytes[..]); let repr = create_repr(Message::MldQuery); repr.emit( - &Ipv6Address::LINK_LOCAL_ALL_NODES, - &Ipv6Address::LINK_LOCAL_ALL_ROUTERS, + &IPV6_LINK_LOCAL_ALL_NODES, + &IPV6_LINK_LOCAL_ALL_ROUTERS, &mut packet, &ChecksumCapabilities::default(), ); @@ -634,8 +628,8 @@ mod test { let mut packet = Packet::new_unchecked(&mut bytes[..]); let repr = create_repr(Message::MldReport); repr.emit( - &Ipv6Address::LINK_LOCAL_ALL_NODES, - &Ipv6Address::LINK_LOCAL_ALL_ROUTERS, + &IPV6_LINK_LOCAL_ALL_NODES, + &IPV6_LINK_LOCAL_ALL_ROUTERS, &mut packet, &ChecksumCapabilities::default(), ); diff --git a/src/wire/mod.rs b/src/wire/mod.rs index 64ac65323..a6db11c3d 100644 --- a/src/wire/mod.rs +++ b/src/wire/mod.rs @@ -188,15 +188,24 @@ pub use self::ip::{ pub use self::ipv4::{ Address as Ipv4Address, Cidr as Ipv4Cidr, Key as Ipv4FragKey, Packet as Ipv4Packet, Repr as Ipv4Repr, HEADER_LEN as IPV4_HEADER_LEN, MIN_MTU as IPV4_MIN_MTU, + MULTICAST_ALL_ROUTERS as IPV4_MULTICAST_ALL_ROUTERS, + MULTICAST_ALL_SYSTEMS as IPV4_MULTICAST_ALL_SYSTEMS, }; -#[cfg(feature = "proto-ipv6")] -pub(crate) use self::ipv6::MulticastScope as Ipv6MulticastScope; +#[cfg(feature = "proto-ipv4")] +pub(crate) use self::ipv4::AddressExt as Ipv4AddressExt; + #[cfg(feature = "proto-ipv6")] pub use self::ipv6::{ Address as Ipv6Address, Cidr as Ipv6Cidr, Packet as Ipv6Packet, Repr as Ipv6Repr, - HEADER_LEN as IPV6_HEADER_LEN, MIN_MTU as IPV6_MIN_MTU, + HEADER_LEN as IPV6_HEADER_LEN, + LINK_LOCAL_ALL_MLDV2_ROUTERS as IPV6_LINK_LOCAL_ALL_MLDV2_ROUTERS, + LINK_LOCAL_ALL_NODES as IPV6_LINK_LOCAL_ALL_NODES, + LINK_LOCAL_ALL_ROUTERS as IPV6_LINK_LOCAL_ALL_ROUTERS, + LINK_LOCAL_ALL_RPL_NODES as IPV6_LINK_LOCAL_ALL_RPL_NODES, MIN_MTU as IPV6_MIN_MTU, }; +#[cfg(feature = "proto-ipv6")] +pub(crate) use self::ipv6::{AddressExt as Ipv6AddressExt, MulticastScope as Ipv6MulticastScope}; #[cfg(feature = "proto-ipv6")] pub use self::ipv6option::{ diff --git a/src/wire/ndisc.rs b/src/wire/ndisc.rs index a71cdd61a..3c1243e3b 100644 --- a/src/wire/ndisc.rs +++ b/src/wire/ndisc.rs @@ -4,8 +4,8 @@ use byteorder::{ByteOrder, NetworkEndian}; use super::{Error, Result}; use crate::time::Duration; use crate::wire::icmpv6::{field, Message, Packet}; -use crate::wire::Ipv6Address; use crate::wire::RawHardwareAddress; +use crate::wire::{Ipv6Address, Ipv6AddressExt}; use crate::wire::{NdiscOption, NdiscOptionRepr}; use crate::wire::{NdiscPrefixInformation, NdiscRedirectedHeader}; @@ -159,7 +159,7 @@ impl + AsMut<[u8]>> Packet { #[inline] pub fn set_target_addr(&mut self, value: Ipv6Address) { let data = self.buffer.as_mut(); - data[field::TARGET_ADDR].copy_from_slice(value.as_bytes()); + data[field::TARGET_ADDR].copy_from_slice(&value.octets()); } } @@ -184,7 +184,7 @@ impl + AsMut<[u8]>> Packet { #[inline] pub fn set_dest_addr(&mut self, value: Ipv6Address) { let data = self.buffer.as_mut(); - data[field::DEST_ADDR].copy_from_slice(value.as_bytes()); + data[field::DEST_ADDR].copy_from_slice(&value.octets()); } } @@ -462,10 +462,8 @@ mod test { 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]); + const MOCK_IP_ADDR_1: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1); + const MOCK_IP_ADDR_2: Ipv6Address = Ipv6Address::new(0xfe80, 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, diff --git a/src/wire/ndiscoption.rs b/src/wire/ndiscoption.rs index 0236d4351..583d9b569 100644 --- a/src/wire/ndiscoption.rs +++ b/src/wire/ndiscoption.rs @@ -4,7 +4,7 @@ use core::fmt; use super::{Error, Result}; use crate::time::Duration; -use crate::wire::{Ipv6Address, Ipv6Packet, Ipv6Repr, MAX_HARDWARE_ADDRESS_LEN}; +use crate::wire::{Ipv6Address, Ipv6AddressExt, Ipv6Packet, Ipv6Repr, MAX_HARDWARE_ADDRESS_LEN}; use crate::wire::RawHardwareAddress; @@ -356,7 +356,7 @@ impl + AsMut<[u8]>> NdiscOption { #[inline] pub fn set_prefix(&mut self, addr: Ipv6Address) { let data = self.buffer.as_mut(); - data[field::PREFIX].copy_from_slice(addr.as_bytes()); + data[field::PREFIX].copy_from_slice(&addr.octets()); } } diff --git a/src/wire/rpl.rs b/src/wire/rpl.rs index a8b6fb582..088a8771b 100644 --- a/src/wire/rpl.rs +++ b/src/wire/rpl.rs @@ -6,7 +6,7 @@ use byteorder::{ByteOrder, NetworkEndian}; use super::{Error, Result}; use crate::wire::icmpv6::Packet; -use crate::wire::ipv6::Address; +use crate::wire::ipv6::{Address, AddressExt}; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -508,7 +508,7 @@ impl + AsMut<[u8]>> Packet { pub fn set_dao_dodag_id(&mut self, address: Option
) { match address { Some(address) => { - self.buffer.as_mut()[field::DAO_DODAG_ID].copy_from_slice(address.as_bytes()); + self.buffer.as_mut()[field::DAO_DODAG_ID].copy_from_slice(&address.octets()); self.set_dao_dodag_id_present(true); } None => { @@ -594,7 +594,7 @@ impl + AsMut<[u8]>> Packet { pub fn set_dao_ack_dodag_id(&mut self, address: Option
) { match address { Some(address) => { - self.buffer.as_mut()[field::DAO_ACK_DODAG_ID].copy_from_slice(address.as_bytes()); + self.buffer.as_mut()[field::DAO_ACK_DODAG_ID].copy_from_slice(&address.octets()); self.set_dao_ack_dodag_id_present(true); } None => { @@ -866,7 +866,7 @@ pub mod options { use byteorder::{ByteOrder, NetworkEndian}; use super::{Error, InstanceId, Result}; - use crate::wire::ipv6::Address; + use crate::wire::ipv6::{Address, AddressExt}; /// A read/write wrapper around a RPL Control Message Option. #[derive(Debug, Clone)] @@ -1497,7 +1497,7 @@ pub mod options { #[inline] pub fn set_transit_info_parent_address(&mut self, address: Address) { self.buffer.as_mut()[field::TRANSIT_INFO_PARENT_ADDRESS] - .copy_from_slice(address.as_bytes()); + .copy_from_slice(&address.octets()); } } @@ -2095,7 +2095,7 @@ pub mod options { Repr::DagMetricContainer => todo!(), Repr::RouteInformation { prefix, .. } => 2 + 6 + prefix.len(), Repr::DodagConfiguration { .. } => 2 + 14, - Repr::RplTarget { prefix, .. } => 2 + 2 + prefix.0.len(), + Repr::RplTarget { prefix, .. } => 2 + 2 + prefix.octets().len(), Repr::TransitInformation { parent_address, .. } => { 2 + 4 + if parent_address.is_some() { 16 } else { 0 } } @@ -2165,7 +2165,7 @@ pub mod options { } => { packet.clear_rpl_target_flags(); packet.set_rpl_target_prefix_length(*prefix_length); - packet.set_rpl_target_prefix(prefix.as_bytes()); + packet.set_rpl_target_prefix(&prefix.octets()); } Repr::TransitInformation { external, @@ -2616,7 +2616,7 @@ mod tests { prefix, } => { assert_eq!(prefix_length, 128); - assert_eq!(prefix.as_bytes(), &target_prefix[..]); + assert_eq!(prefix.octets(), target_prefix); } _ => unreachable!(), } @@ -2707,9 +2707,7 @@ mod tests { assert_eq!(status, 0x0); assert_eq!( dodag_id, - Some(Ipv6Address([ - 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1 - ])) + Some(Ipv6Address::new(0xfe80, 0, 0, 0, 0x0200, 0, 0, 1)) ); } _ => unreachable!(), diff --git a/src/wire/sixlowpan/iphc.rs b/src/wire/sixlowpan/iphc.rs index 5841eb738..429114128 100644 --- a/src/wire/sixlowpan/iphc.rs +++ b/src/wire/sixlowpan/iphc.rs @@ -6,7 +6,7 @@ use super::{ AddressContext, AddressMode, Error, NextHeader, Result, UnresolvedAddress, DISPATCH_IPHC_HEADER, }; -use crate::wire::{ieee802154::Address as LlAddress, ipv6, IpProtocol}; +use crate::wire::{ieee802154::Address as LlAddress, ipv6, ipv6::AddressExt, IpProtocol}; use byteorder::{ByteOrder, NetworkEndian}; mod field { @@ -526,7 +526,7 @@ impl + AsMut<[u8]>> Packet { ) -> usize { self.set_cid_field(0); self.set_sac_field(0); - let src = src_addr.as_bytes(); + let src = src_addr.octets(); if src_addr == ipv6::Address::UNSPECIFIED { self.set_sac_field(1); self.set_sam_field(0b00); @@ -574,7 +574,7 @@ impl + AsMut<[u8]>> Packet { } else { // We cannot elide anything. self.set_sam_field(0b00); - self.set_field(idx, src); + self.set_field(idx, &src); idx += 16; } @@ -593,7 +593,7 @@ impl + AsMut<[u8]>> Packet { self.set_dac_field(0); self.set_dam_field(0); self.set_m_field(0); - let dst = dst_addr.as_bytes(); + let dst = dst_addr.octets(); if dst_addr.is_multicast() { self.set_m_field(1); @@ -619,7 +619,7 @@ impl + AsMut<[u8]>> Packet { } else { self.set_dam_field(0b11); - self.set_field(idx, dst); + self.set_field(idx, &dst); idx += 16; } } else if dst_addr.is_link_local() { @@ -653,7 +653,7 @@ impl + AsMut<[u8]>> Packet { } else { self.set_dam_field(0b00); - self.set_field(idx, dst); + self.set_field(idx, &dst); idx += 16; } @@ -771,7 +771,7 @@ impl Repr { len += if self.src_addr == ipv6::Address::UNSPECIFIED { 0 } else if self.src_addr.is_link_local() { - let src = self.src_addr.as_bytes(); + let src = self.src_addr.octets(); let ll = [src[14], src[15]]; let is_eui_64 = self @@ -799,7 +799,7 @@ impl Repr { }; // Add the size of the destination header - let dst = self.dst_addr.as_bytes(); + let dst = self.dst_addr.octets(); len += if self.dst_addr.is_multicast() { if dst[1] == 0x02 && dst[2..15] == [0; 13] { 1 diff --git a/src/wire/sixlowpan/mod.rs b/src/wire/sixlowpan/mod.rs index 03a5218a0..59c13bfe2 100644 --- a/src/wire/sixlowpan/mod.rs +++ b/src/wire/sixlowpan/mod.rs @@ -6,6 +6,7 @@ use super::{Error, Result}; use crate::wire::ieee802154::Address as LlAddress; use crate::wire::ipv6; +use crate::wire::ipv6::AddressExt; use crate::wire::IpProtocol; pub mod frag; diff --git a/src/wire/sixlowpan/nhc.rs b/src/wire/sixlowpan/nhc.rs index 85e422a49..d558d1d5f 100644 --- a/src/wire/sixlowpan/nhc.rs +++ b/src/wire/sixlowpan/nhc.rs @@ -862,8 +862,8 @@ mod test { let payload = b"Hello World!"; - let src_addr = ipv6::Address::default(); - let dst_addr = ipv6::Address::default(); + let src_addr = ipv6::Address::UNSPECIFIED; + let dst_addr = ipv6::Address::UNSPECIFIED; let len = udp.header_len() + payload.len(); let mut buffer = [0u8; 127]; diff --git a/src/wire/tcp.rs b/src/wire/tcp.rs index 027e1dad9..e064182d9 100644 --- a/src/wire/tcp.rs +++ b/src/wire/tcp.rs @@ -1,5 +1,5 @@ use byteorder::{ByteOrder, NetworkEndian}; -use core::{cmp, fmt, i32, ops}; +use core::{cmp, fmt, ops}; use super::{Error, Result}; use crate::phy::ChecksumCapabilities; @@ -1192,9 +1192,9 @@ mod test { use crate::wire::Ipv4Address; #[cfg(feature = "proto-ipv4")] - const SRC_ADDR: Ipv4Address = Ipv4Address([192, 168, 1, 1]); + const SRC_ADDR: Ipv4Address = Ipv4Address::new(192, 168, 1, 1); #[cfg(feature = "proto-ipv4")] - const DST_ADDR: Ipv4Address = Ipv4Address([192, 168, 1, 2]); + const DST_ADDR: Ipv4Address = Ipv4Address::new(192, 168, 1, 2); #[cfg(feature = "proto-ipv4")] static PACKET_BYTES: [u8; 28] = [ diff --git a/src/wire/udp.rs b/src/wire/udp.rs index d7ad0d401..9d341e0ee 100644 --- a/src/wire/udp.rs +++ b/src/wire/udp.rs @@ -354,9 +354,9 @@ mod test { use crate::wire::Ipv4Address; #[cfg(feature = "proto-ipv4")] - const SRC_ADDR: Ipv4Address = Ipv4Address([192, 168, 1, 1]); + const SRC_ADDR: Ipv4Address = Ipv4Address::new(192, 168, 1, 1); #[cfg(feature = "proto-ipv4")] - const DST_ADDR: Ipv4Address = Ipv4Address([192, 168, 1, 2]); + const DST_ADDR: Ipv4Address = Ipv4Address::new(192, 168, 1, 2); #[cfg(feature = "proto-ipv4")] static PACKET_BYTES: [u8; 12] = [