diff --git a/benches/bench.rs b/benches/bench.rs index b1ddc85..943a542 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -1,22 +1,24 @@ #![feature(test)] mod wire { - use test; - #[cfg(feature = "proto-ipv6")] - use smoltcp::wire::{Ipv6Address, Ipv6Repr, Ipv6Packet}; - #[cfg(feature = "proto-ipv4")] - use smoltcp::wire::{Ipv4Address, Ipv4Repr, Ipv4Packet}; - use smoltcp::phy::{ChecksumCapabilities}; + use smoltcp::phy::ChecksumCapabilities; use smoltcp::wire::{IpAddress, IpProtocol}; - use smoltcp::wire::{TcpRepr, TcpPacket, TcpSeqNumber, TcpControl}; - use smoltcp::wire::{UdpRepr, UdpPacket}; + #[cfg(feature = "proto-ipv4")] + use smoltcp::wire::{Ipv4Address, Ipv4Packet, Ipv4Repr}; + #[cfg(feature = "proto-ipv6")] + use smoltcp::wire::{Ipv6Address, Ipv6Packet, Ipv6Repr}; + use smoltcp::wire::{TcpControl, TcpPacket, TcpRepr, TcpSeqNumber}; + use smoltcp::wire::{UdpPacket, UdpRepr}; + use 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([ + 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 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([ + 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 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])); @@ -26,42 +28,50 @@ mod wire { #[bench] #[cfg(any(feature = "proto-ipv6", feature = "proto-ipv4"))] fn bench_emit_tcp(b: &mut test::Bencher) { - static PAYLOAD_BYTES: [u8; 400] = - [0x2a; 400]; + static PAYLOAD_BYTES: [u8; 400] = [0x2a; 400]; let repr = TcpRepr { - src_port: 48896, - dst_port: 80, - seq_number: TcpSeqNumber(0x01234567), - ack_number: None, - window_len: 0x0123, - control: TcpControl::Syn, + src_port: 48896, + dst_port: 80, + seq_number: TcpSeqNumber(0x01234567), + ack_number: None, + window_len: 0x0123, + control: TcpControl::Syn, max_seg_size: None, window_scale: None, - payload: &PAYLOAD_BYTES + payload: &PAYLOAD_BYTES, }; let mut bytes = vec![0xa5; repr.buffer_len()]; b.iter(|| { let mut packet = TcpPacket::new(&mut bytes); - repr.emit(&mut packet, &SRC_ADDR, &DST_ADDR, &ChecksumCapabilities::default()); + repr.emit( + &mut packet, + &SRC_ADDR, + &DST_ADDR, + &ChecksumCapabilities::default(), + ); }); } #[bench] #[cfg(any(feature = "proto-ipv6", feature = "proto-ipv4"))] fn bench_emit_udp(b: &mut test::Bencher) { - static PAYLOAD_BYTES: [u8; 400] = - [0x2a; 400]; + static PAYLOAD_BYTES: [u8; 400] = [0x2a; 400]; let repr = UdpRepr { src_port: 48896, dst_port: 80, - payload: &PAYLOAD_BYTES + payload: &PAYLOAD_BYTES, }; let mut bytes = vec![0xa5; repr.buffer_len()]; b.iter(|| { let mut packet = UdpPacket::new(&mut bytes); - repr.emit(&mut packet, &SRC_ADDR, &DST_ADDR, &ChecksumCapabilities::default()); + repr.emit( + &mut packet, + &SRC_ADDR, + &DST_ADDR, + &ChecksumCapabilities::default(), + ); }); } @@ -69,11 +79,11 @@ 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]), - protocol: IpProtocol::Tcp, + src_addr: Ipv4Address([192, 168, 1, 1]), + dst_addr: Ipv4Address([192, 168, 1, 2]), + protocol: IpProtocol::Tcp, payload_len: 100, - hop_limit: 64 + hop_limit: 64, }; let mut bytes = vec![0xa5; repr.buffer_len()]; @@ -87,13 +97,11 @@ 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([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]), next_header: IpProtocol::Tcp, payload_len: 100, - hop_limit: 64 + hop_limit: 64, }; let mut bytes = vec![0xa5; repr.buffer_len()]; diff --git a/examples/benchmark.rs b/examples/benchmark.rs index 6527ba4..3bb23e9 100644 --- a/examples/benchmark.rs +++ b/examples/benchmark.rs @@ -2,28 +2,34 @@ mod utils; +use log::debug; use std::cmp; use std::collections::BTreeMap; -use std::sync::atomic::{Ordering, AtomicBool}; -use std::thread; use std::io::{Read, Write}; use std::net::TcpStream; use std::os::unix::io::AsRawFd; -use log::debug; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::thread; -use smoltcp::phy::{Device, Medium, wait as phy_wait}; -use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; -use smoltcp::iface::{NeighborCache, InterfaceBuilder}; +use smoltcp::iface::{InterfaceBuilder, NeighborCache}; +use smoltcp::phy::{wait as phy_wait, Device, Medium}; use smoltcp::socket::SocketSet; use smoltcp::socket::{TcpSocket, TcpSocketBuffer}; use smoltcp::time::{Duration, Instant}; +use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; const AMOUNT: usize = 1_000_000_000; -enum Client { Reader, Writer } +enum Client { + Reader, + Writer, +} fn client(kind: Client) { - let port = match kind { Client::Reader => 1234, Client::Writer => 1235 }; + let port = match kind { + Client::Reader => 1234, + Client::Writer => 1235, + }; let mut stream = TcpStream::connect(("192.168.69.1", port)).unwrap(); let mut buffer = vec![0; 1_000_000]; @@ -42,7 +48,7 @@ fn client(kind: Client) { // print!("(P:{})", result); processed += result } - Err(err) => panic!("cannot process: {}", err) + Err(err) => panic!("cannot process: {}", err), } } @@ -69,11 +75,11 @@ fn main() { let mut matches = utils::parse_options(&opts, free); let device = utils::parse_tuntap_options(&mut matches); let fd = device.as_raw_fd(); - let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false); + let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false); let mode = match matches.free[0].as_ref() { "reader" => Client::Reader, "writer" => Client::Writer, - _ => panic!("invalid mode") + _ => panic!("invalid mode"), }; thread::spawn(move || client(mode)); @@ -91,8 +97,7 @@ fn main() { let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]); let ip_addrs = [IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24)]; let medium = device.capabilities().medium; - let mut builder = InterfaceBuilder::new(device) - .ip_addrs(ip_addrs); + let mut builder = InterfaceBuilder::new(device).ip_addrs(ip_addrs); if medium == Medium::Ethernet { builder = builder .ethernet_addr(ethernet_addr) @@ -109,13 +114,12 @@ fn main() { while !CLIENT_DONE.load(Ordering::SeqCst) { let timestamp = Instant::now(); match iface.poll(&mut sockets, timestamp) { - Ok(_) => {}, + Ok(_) => {} Err(e) => { - debug!("poll error: {}",e); + debug!("poll error: {}", e); } } - // tcp:1234: emit data { let mut socket = sockets.get::(tcp1_handle); @@ -125,10 +129,12 @@ fn main() { if socket.can_send() { if processed < AMOUNT { - let length = socket.send(|buffer| { - let length = cmp::min(buffer.len(), AMOUNT - processed); - (length, length) - }).unwrap(); + let length = socket + .send(|buffer| { + let length = cmp::min(buffer.len(), AMOUNT - processed); + (length, length) + }) + .unwrap(); processed += length; } } @@ -143,10 +149,12 @@ fn main() { if socket.can_recv() { if processed < AMOUNT { - let length = socket.recv(|buffer| { - let length = cmp::min(buffer.len(), AMOUNT - processed); - (length, length) - }).unwrap(); + let length = socket + .recv(|buffer| { + let length = cmp::min(buffer.len(), AMOUNT - processed); + (length, length) + }) + .unwrap(); processed += length; } } @@ -155,7 +163,7 @@ fn main() { match iface.poll_at(&sockets, timestamp) { Some(poll_at) if timestamp < poll_at => { phy_wait(fd, Some(poll_at - timestamp)).expect("wait error"); - }, + } Some(_) => (), None => { phy_wait(fd, default_timeout).expect("wait error"); diff --git a/examples/client.rs b/examples/client.rs index 308ec99..19e1417 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -1,15 +1,15 @@ mod utils; -use std::str::{self, FromStr}; +use log::debug; use std::collections::BTreeMap; use std::os::unix::io::AsRawFd; -use log::debug; +use std::str::{self, FromStr}; -use smoltcp::phy::{Device, Medium, wait as phy_wait}; -use smoltcp::wire::{EthernetAddress, Ipv4Address, IpAddress, IpCidr}; -use smoltcp::iface::{NeighborCache, InterfaceBuilder, Routes}; +use smoltcp::iface::{InterfaceBuilder, NeighborCache, Routes}; +use smoltcp::phy::{wait as phy_wait, Device, Medium}; use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer}; use smoltcp::time::Instant; +use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address}; fn main() { utils::setup_logging(""); @@ -24,7 +24,7 @@ fn main() { let device = utils::parse_tuntap_options(&mut matches); let fd = device.as_raw_fd(); - let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false); + let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false); let address = IpAddress::from_str(&matches.free[0]).expect("invalid address format"); let port = u16::from_str(&matches.free[1]).expect("invalid port format"); @@ -40,11 +40,11 @@ fn main() { let mut routes_storage = [None; 1]; let mut routes = Routes::new(&mut routes_storage[..]); routes.add_default_ipv4_route(default_v4_gw).unwrap(); - + let medium = device.capabilities().medium; let mut builder = InterfaceBuilder::new(device) - .ip_addrs(ip_addrs) - .routes(routes); + .ip_addrs(ip_addrs) + .routes(routes); if medium == Medium::Ethernet { builder = builder .ethernet_addr(ethernet_addr) @@ -64,7 +64,7 @@ fn main() { loop { let timestamp = Instant::now(); match iface.poll(&mut sockets, timestamp) { - Ok(_) => {}, + Ok(_) => {} Err(e) => { debug!("poll error: {}", e); } @@ -76,25 +76,31 @@ fn main() { debug!("connected"); } else if !socket.is_active() && tcp_active { debug!("disconnected"); - break + break; } tcp_active = socket.is_active(); if socket.may_recv() { - let data = socket.recv(|data| { - let mut data = data.to_owned(); - if !data.is_empty() { - debug!("recv data: {:?}", - str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)")); - data = data.split(|&b| b == b'\n').collect::>().concat(); - data.reverse(); - data.extend(b"\n"); - } - (data.len(), data) - }).unwrap(); + let data = socket + .recv(|data| { + let mut data = data.to_owned(); + if !data.is_empty() { + debug!( + "recv data: {:?}", + str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)") + ); + data = data.split(|&b| b == b'\n').collect::>().concat(); + data.reverse(); + data.extend(b"\n"); + } + (data.len(), data) + }) + .unwrap(); if socket.can_send() && !data.is_empty() { - debug!("send data: {:?}", - str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)")); + debug!( + "send data: {:?}", + str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)") + ); socket.send_slice(&data[..]).unwrap(); } } else if socket.may_send() { diff --git a/examples/dhcp_client.rs b/examples/dhcp_client.rs index d274cae..57d9211 100644 --- a/examples/dhcp_client.rs +++ b/examples/dhcp_client.rs @@ -1,15 +1,18 @@ #![allow(clippy::option_map_unit_fn)] mod utils; +use log::*; use std::collections::BTreeMap; use std::os::unix::io::AsRawFd; -use log::*; -use smoltcp::{phy::{Device, Medium, wait as phy_wait}, time::Duration}; -use smoltcp::wire::{EthernetAddress, Ipv4Address, IpCidr, Ipv4Cidr}; -use smoltcp::iface::{NeighborCache, InterfaceBuilder, Interface, Routes}; -use smoltcp::socket::{SocketSet, Dhcpv4Socket, Dhcpv4Event}; +use smoltcp::iface::{Interface, InterfaceBuilder, NeighborCache, Routes}; +use smoltcp::socket::{Dhcpv4Event, Dhcpv4Socket, SocketSet}; use smoltcp::time::Instant; +use smoltcp::wire::{EthernetAddress, IpCidr, Ipv4Address, Ipv4Cidr}; +use smoltcp::{ + phy::{wait as phy_wait, Device, Medium}, + time::Duration, +}; fn main() { #[cfg(feature = "log")] @@ -22,7 +25,7 @@ fn main() { let mut matches = utils::parse_options(&opts, free); let device = utils::parse_tuntap_options(&mut matches); let fd = device.as_raw_fd(); - let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false); + let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false); let neighbor_cache = NeighborCache::new(BTreeMap::new()); let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]); @@ -32,8 +35,8 @@ fn main() { let medium = device.capabilities().medium; let mut builder = InterfaceBuilder::new(device) - .ip_addrs(ip_addrs) - .routes(routes); + .ip_addrs(ip_addrs) + .routes(routes); if medium == Medium::Ethernet { builder = builder .ethernet_addr(ethernet_addr) @@ -92,11 +95,11 @@ fn main() { } fn set_ipv4_addr(iface: &mut Interface<'_, DeviceT>, cidr: Ipv4Cidr) - where DeviceT: for<'d> Device<'d> +where + DeviceT: for<'d> Device<'d>, { iface.update_ip_addrs(|addrs| { let dest = addrs.iter_mut().next().unwrap(); *dest = IpCidr::Ipv4(cidr); }); } - diff --git a/examples/httpclient.rs b/examples/httpclient.rs index f41bb32..dafde6b 100644 --- a/examples/httpclient.rs +++ b/examples/httpclient.rs @@ -1,16 +1,16 @@ mod utils; -use std::str::{self, FromStr}; +use log::debug; use std::collections::BTreeMap; use std::os::unix::io::AsRawFd; +use std::str::{self, FromStr}; use url::Url; -use log::debug; -use smoltcp::phy::{Device, Medium, wait as phy_wait}; -use smoltcp::wire::{EthernetAddress, Ipv4Address, Ipv6Address, IpAddress, IpCidr}; -use smoltcp::iface::{NeighborCache, InterfaceBuilder, Routes}; +use smoltcp::iface::{InterfaceBuilder, NeighborCache, Routes}; +use smoltcp::phy::{wait as phy_wait, Device, Medium}; use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer}; use smoltcp::time::Instant; +use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address, Ipv6Address}; fn main() { utils::setup_logging(""); @@ -24,11 +24,10 @@ fn main() { let mut matches = utils::parse_options(&opts, free); let device = utils::parse_tuntap_options(&mut matches); let fd = device.as_raw_fd(); - let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false); + let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false); let address = IpAddress::from_str(&matches.free[0]).expect("invalid address format"); let url = Url::parse(&matches.free[1]).expect("invalid url format"); - let neighbor_cache = NeighborCache::new(BTreeMap::new()); let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; 1024]); @@ -36,9 +35,11 @@ fn main() { let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer); let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]); - let ip_addrs = [IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24), - IpCidr::new(IpAddress::v6(0xfdaa, 0, 0, 0, 0, 0, 0, 1), 64), - IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64)]; + let ip_addrs = [ + IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24), + IpCidr::new(IpAddress::v6(0xfdaa, 0, 0, 0, 0, 0, 0, 1), 64), + IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64), + ]; let default_v4_gw = Ipv4Address::new(192, 168, 69, 100); let default_v6_gw = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x100); let mut routes_storage = [None; 2]; @@ -48,8 +49,8 @@ fn main() { let medium = device.capabilities().medium; let mut builder = InterfaceBuilder::new(device) - .ip_addrs(ip_addrs) - .routes(routes); + .ip_addrs(ip_addrs) + .routes(routes); if medium == Medium::Ethernet { builder = builder .ethernet_addr(ethernet_addr) @@ -60,15 +61,19 @@ fn main() { let mut sockets = SocketSet::new(vec![]); let tcp_handle = sockets.add(tcp_socket); - enum State { Connect, Request, Response } + enum State { + Connect, + Request, + Response, + } let mut state = State::Connect; loop { let timestamp = Instant::now(); match iface.poll(&mut sockets, timestamp) { - Ok(_) => {}, + Ok(_) => {} Err(e) => { - debug!("poll error: {}",e); + debug!("poll error: {}", e); } } @@ -79,7 +84,9 @@ fn main() { State::Connect if !socket.is_active() => { debug!("connecting"); let local_port = 49152 + rand::random::() % 16384; - socket.connect((address, url.port().unwrap_or(80)), local_port).unwrap(); + socket + .connect((address, url.port().unwrap_or(80)), local_port) + .unwrap(); State::Request } State::Request if socket.may_send() => { @@ -88,22 +95,26 @@ fn main() { socket.send_slice(http_get.as_ref()).expect("cannot send"); let http_host = "Host: ".to_owned() + url.host_str().unwrap() + "\r\n"; socket.send_slice(http_host.as_ref()).expect("cannot send"); - socket.send_slice(b"Connection: close\r\n").expect("cannot send"); + socket + .send_slice(b"Connection: close\r\n") + .expect("cannot send"); socket.send_slice(b"\r\n").expect("cannot send"); State::Response } State::Response if socket.can_recv() => { - socket.recv(|data| { - println!("{}", str::from_utf8(data).unwrap_or("(invalid utf8)")); - (data.len(), ()) - }).unwrap(); + socket + .recv(|data| { + println!("{}", str::from_utf8(data).unwrap_or("(invalid utf8)")); + (data.len(), ()) + }) + .unwrap(); State::Response } State::Response if !socket.may_recv() => { debug!("received complete response"); - break + break; } - _ => state + _ => state, } } diff --git a/examples/loopback.rs b/examples/loopback.rs index 7eb6bc3..00e4651 100644 --- a/examples/loopback.rs +++ b/examples/loopback.rs @@ -7,18 +7,18 @@ mod utils; use core::str; -use log::{info, debug, error}; +use log::{debug, error, info}; +use smoltcp::iface::{InterfaceBuilder, NeighborCache}; use smoltcp::phy::{Loopback, Medium}; -use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; -use smoltcp::iface::{NeighborCache, InterfaceBuilder}; use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer}; use smoltcp::time::{Duration, Instant}; +use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; #[cfg(not(feature = "std"))] mod mock { - use smoltcp::time::{Duration, Instant}; use core::cell::Cell; + use smoltcp::time::{Duration, Instant}; #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -41,9 +41,9 @@ mod mock { #[cfg(feature = "std")] mod mock { + use smoltcp::time::{Duration, Instant}; + use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; - use std::sync::atomic::{Ordering, AtomicUsize}; - use smoltcp::time::{Duration, Instant}; // should be AtomicU64 but that's unstable #[derive(Debug, Clone)] @@ -56,7 +56,8 @@ mod mock { } pub fn advance(&self, duration: Duration) { - self.0.fetch_add(duration.total_millis() as usize, Ordering::SeqCst); + self.0 + .fetch_add(duration.total_millis() as usize, Ordering::SeqCst); } pub fn elapsed(&self) -> Instant { @@ -78,7 +79,7 @@ fn main() { utils::add_middleware_options(&mut opts, &mut free); let mut matches = utils::parse_options(&opts, free); - utils::parse_middleware_options(&mut matches, device, /*loopback=*/true) + utils::parse_middleware_options(&mut matches, device, /*loopback=*/ true) }; let mut neighbor_cache_entries = [None; 8]; @@ -86,10 +87,10 @@ fn main() { let mut ip_addrs = [IpCidr::new(IpAddress::v4(127, 0, 0, 1), 8)]; let mut iface = InterfaceBuilder::new(device) - .ethernet_addr(EthernetAddress::default()) - .neighbor_cache(neighbor_cache) - .ip_addrs(ip_addrs) - .finalize(); + .ethernet_addr(EthernetAddress::default()) + .neighbor_cache(neighbor_cache) + .ip_addrs(ip_addrs) + .finalize(); let server_socket = { // It is not strictly necessary to use a `static mut` and unsafe code here, but @@ -116,12 +117,12 @@ fn main() { let server_handle = socket_set.add(server_socket); let client_handle = socket_set.add(client_socket); - let mut did_listen = false; + let mut did_listen = false; let mut did_connect = false; let mut done = false; while !done && clock.elapsed() < Instant::from_millis(10_000) { match iface.poll(&mut socket_set, clock.elapsed()) { - Ok(_) => {}, + Ok(_) => {} Err(e) => { debug!("poll error: {}", e); } @@ -138,9 +139,10 @@ fn main() { } if socket.can_recv() { - debug!("got {:?}", socket.recv(|buffer| { - (buffer.len(), str::from_utf8(buffer).unwrap()) - })); + debug!( + "got {:?}", + socket.recv(|buffer| { (buffer.len(), str::from_utf8(buffer).unwrap()) }) + ); socket.close(); done = true; } @@ -151,8 +153,12 @@ fn main() { if !socket.is_open() { if !did_connect { debug!("connecting"); - socket.connect((IpAddress::v4(127, 0, 0, 1), 1234), - (IpAddress::Unspecified, 65000)).unwrap(); + socket + .connect( + (IpAddress::v4(127, 0, 0, 1), 1234), + (IpAddress::Unspecified, 65000), + ) + .unwrap(); did_connect = true; } } @@ -169,8 +175,8 @@ fn main() { Some(delay) => { debug!("sleeping for {} ms", delay); clock.advance(delay) - }, - None => clock.advance(Duration::from_millis(1)) + } + None => clock.advance(Duration::from_millis(1)), } } diff --git a/examples/multicast.rs b/examples/multicast.rs index 33d2426..30a368e 100644 --- a/examples/multicast.rs +++ b/examples/multicast.rs @@ -1,17 +1,20 @@ mod utils; +use log::debug; use std::collections::BTreeMap; use std::os::unix::io::AsRawFd; -use log::debug; +use smoltcp::iface::{InterfaceBuilder, NeighborCache}; use smoltcp::phy::wait as phy_wait; -use smoltcp::wire::{EthernetAddress, IpVersion, IpProtocol, IpAddress, IpCidr, Ipv4Address, - Ipv4Packet, IgmpPacket, IgmpRepr}; -use smoltcp::iface::{NeighborCache, InterfaceBuilder}; -use smoltcp::socket::{SocketSet, - RawSocket, RawSocketBuffer, RawPacketMetadata, - UdpSocket, UdpSocketBuffer, UdpPacketMetadata}; +use smoltcp::socket::{ + RawPacketMetadata, RawSocket, RawSocketBuffer, SocketSet, UdpPacketMetadata, UdpSocket, + UdpSocketBuffer, +}; use smoltcp::time::Instant; +use smoltcp::wire::{ + EthernetAddress, IgmpPacket, IgmpRepr, IpAddress, IpCidr, IpProtocol, IpVersion, Ipv4Address, + Ipv4Packet, +}; const MDNS_PORT: u16 = 5353; const MDNS_GROUP: [u8; 4] = [224, 0, 0, 251]; @@ -26,10 +29,7 @@ fn main() { let mut matches = utils::parse_options(&opts, free); let device = utils::parse_tuntap_options(&mut matches); let fd = device.as_raw_fd(); - let device = utils::parse_middleware_options(&mut matches, - device, - /*loopback=*/ - false); + let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false); let neighbor_cache = NeighborCache::new(BTreeMap::new()); let local_addr = Ipv4Address::new(192, 168, 69, 2); @@ -38,15 +38,17 @@ fn main() { let ip_addr = IpCidr::new(IpAddress::from(local_addr), 24); let mut ipv4_multicast_storage = [None; 1]; let mut iface = InterfaceBuilder::new(device) - .ethernet_addr(ethernet_addr) - .neighbor_cache(neighbor_cache) - .ip_addrs([ip_addr]) - .ipv4_multicast_groups(&mut ipv4_multicast_storage[..]) - .finalize(); + .ethernet_addr(ethernet_addr) + .neighbor_cache(neighbor_cache) + .ip_addrs([ip_addr]) + .ipv4_multicast_groups(&mut ipv4_multicast_storage[..]) + .finalize(); let now = Instant::now(); // Join a multicast group to receive mDNS traffic - iface.join_multicast_group(Ipv4Address::from_bytes(&MDNS_GROUP), now).unwrap(); + iface + .join_multicast_group(Ipv4Address::from_bytes(&MDNS_GROUP), now) + .unwrap(); let mut sockets = SocketSet::new(vec![]); @@ -55,8 +57,10 @@ fn main() { // Will not send IGMP let raw_tx_buffer = RawSocketBuffer::new(vec![], vec![]); let raw_socket = RawSocket::new( - IpVersion::Ipv4, IpProtocol::Igmp, - raw_rx_buffer, raw_tx_buffer + IpVersion::Ipv4, + IpProtocol::Igmp, + raw_rx_buffer, + raw_tx_buffer, ); let raw_handle = sockets.add(raw_socket); @@ -70,9 +74,9 @@ fn main() { loop { let timestamp = Instant::now(); match iface.poll(&mut sockets, timestamp) { - Ok(_) => {}, + Ok(_) => {} Err(e) => { - debug!("poll error: {}",e); + debug!("poll error: {}", e); } } @@ -82,7 +86,8 @@ fn main() { if socket.can_recv() { // For display purposes only - normally we wouldn't process incoming IGMP packets // in the application layer - socket.recv() + socket + .recv() .and_then(Ipv4Packet::new_checked) .and_then(|ipv4_packet| IgmpPacket::new_checked(ipv4_packet.payload())) .and_then(|igmp_packet| IgmpRepr::parse(&igmp_packet)) @@ -97,8 +102,11 @@ fn main() { } if socket.can_recv() { - socket.recv() - .map(|(data, sender)| println!("mDNS traffic: {} UDP bytes from {}", data.len(), sender)) + socket + .recv() + .map(|(data, sender)| { + println!("mDNS traffic: {} UDP bytes from {}", data.len(), sender) + }) .unwrap_or_else(|e| println!("Recv UDP error: {:?}", e)); } } diff --git a/examples/ping.rs b/examples/ping.rs index 816470c..45e327b 100644 --- a/examples/ping.rs +++ b/examples/ping.rs @@ -1,21 +1,25 @@ mod utils; -use std::str::FromStr; -use std::collections::BTreeMap; -use std::cmp; -use std::os::unix::io::AsRawFd; -use std::collections::HashMap; -use log::debug; use byteorder::{ByteOrder, NetworkEndian}; +use log::debug; +use std::cmp; +use std::collections::BTreeMap; +use std::collections::HashMap; +use std::os::unix::io::AsRawFd; +use std::str::FromStr; -use smoltcp::{phy::Medium, time::{Duration, Instant}}; -use smoltcp::phy::Device; +use smoltcp::iface::{InterfaceBuilder, NeighborCache, Routes}; use smoltcp::phy::wait as phy_wait; -use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, - Ipv6Address, Icmpv6Repr, Icmpv6Packet, - Ipv4Address, Icmpv4Repr, Icmpv4Packet}; -use smoltcp::iface::{NeighborCache, InterfaceBuilder, Routes}; -use smoltcp::socket::{SocketSet, IcmpSocket, IcmpSocketBuffer, IcmpPacketMetadata, IcmpEndpoint}; +use smoltcp::phy::Device; +use smoltcp::socket::{IcmpEndpoint, IcmpPacketMetadata, IcmpSocket, IcmpSocketBuffer, SocketSet}; +use smoltcp::wire::{ + EthernetAddress, Icmpv4Packet, Icmpv4Repr, Icmpv6Packet, Icmpv6Repr, IpAddress, IpCidr, + Ipv4Address, Ipv6Address, +}; +use smoltcp::{ + phy::Medium, + time::{Duration, Instant}, +}; macro_rules! send_icmp_ping { ( $repr_type:ident, $packet_type:ident, $ident:expr, $seq_no:expr, @@ -26,13 +30,11 @@ macro_rules! send_icmp_ping { data: &$echo_payload, }; - let icmp_payload = $socket - .send(icmp_repr.buffer_len(), $remote_addr) - .unwrap(); + let icmp_payload = $socket.send(icmp_repr.buffer_len(), $remote_addr).unwrap(); let icmp_packet = $packet_type::new_unchecked(icmp_payload); (icmp_repr, icmp_packet) - }} + }}; } macro_rules! get_icmp_pong { @@ -41,14 +43,18 @@ macro_rules! get_icmp_pong { if let $repr_type::EchoReply { seq_no, data, .. } = $repr { if let Some(_) = $waiting_queue.get(&seq_no) { let packet_timestamp_ms = NetworkEndian::read_i64(data); - println!("{} bytes from {}: icmp_seq={}, time={}ms", - data.len(), $remote_addr, seq_no, - $timestamp.total_millis() - packet_timestamp_ms); + println!( + "{} bytes from {}: icmp_seq={}, time={}ms", + data.len(), + $remote_addr, + seq_no, + $timestamp.total_millis() - packet_timestamp_ms + ); $waiting_queue.remove(&seq_no); $received += 1; } } - }} + }}; } fn main() { @@ -57,26 +63,45 @@ fn main() { let (mut opts, mut free) = utils::create_options(); utils::add_tuntap_options(&mut opts, &mut free); utils::add_middleware_options(&mut opts, &mut free); - opts.optopt("c", "count", "Amount of echo request packets to send (default: 4)", "COUNT"); - opts.optopt("i", "interval", - "Interval between successive packets sent (seconds) (default: 1)", "INTERVAL"); - opts.optopt("", "timeout", - "Maximum wait duration for an echo response packet (seconds) (default: 5)", - "TIMEOUT"); + opts.optopt( + "c", + "count", + "Amount of echo request packets to send (default: 4)", + "COUNT", + ); + opts.optopt( + "i", + "interval", + "Interval between successive packets sent (seconds) (default: 1)", + "INTERVAL", + ); + opts.optopt( + "", + "timeout", + "Maximum wait duration for an echo response packet (seconds) (default: 5)", + "TIMEOUT", + ); free.push("ADDRESS"); let mut matches = utils::parse_options(&opts, free); let device = utils::parse_tuntap_options(&mut matches); let fd = device.as_raw_fd(); - let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false); + let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false); let device_caps = device.capabilities(); - let address = IpAddress::from_str(&matches.free[0]).expect("invalid address format"); - let count = matches.opt_str("count").map(|s| usize::from_str(&s).unwrap()).unwrap_or(4); - let interval = matches.opt_str("interval") + let address = IpAddress::from_str(&matches.free[0]).expect("invalid address format"); + let count = matches + .opt_str("count") + .map(|s| usize::from_str(&s).unwrap()) + .unwrap_or(4); + let interval = matches + .opt_str("interval") .map(|s| Duration::from_secs(u64::from_str(&s).unwrap())) .unwrap_or_else(|| Duration::from_secs(1)); - let timeout = Duration::from_secs( - matches.opt_str("timeout").map(|s| u64::from_str(&s).unwrap()).unwrap_or(5) + let timeout = Duration::from_secs( + matches + .opt_str("timeout") + .map(|s| u64::from_str(&s).unwrap()) + .unwrap_or(5), ); let neighbor_cache = NeighborCache::new(BTreeMap::new()); @@ -89,9 +114,11 @@ fn main() { let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]); let src_ipv6 = IpAddress::v6(0xfdaa, 0, 0, 0, 0, 0, 0, 1); - let ip_addrs = [IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24), - IpCidr::new(src_ipv6, 64), - IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64)]; + let ip_addrs = [ + IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24), + IpCidr::new(src_ipv6, 64), + IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64), + ]; let default_v4_gw = Ipv4Address::new(192, 168, 69, 100); let default_v6_gw = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x100); let mut routes_storage = [None; 2]; @@ -101,8 +128,8 @@ fn main() { let medium = device.capabilities().medium; let mut builder = InterfaceBuilder::new(device) - .ip_addrs(ip_addrs) - .routes(routes); + .ip_addrs(ip_addrs) + .routes(routes); if medium == Medium::Ethernet { builder = builder .ethernet_addr(ethernet_addr) @@ -123,7 +150,7 @@ fn main() { loop { let timestamp = Instant::now(); match iface.poll(&mut sockets, timestamp) { - Ok(_) => {}, + Ok(_) => {} Err(e) => { debug!("poll error: {}", e); } @@ -137,25 +164,40 @@ fn main() { send_at = timestamp; } - if socket.can_send() && seq_no < count as u16 && - send_at <= timestamp { + if socket.can_send() && seq_no < count as u16 && send_at <= timestamp { NetworkEndian::write_i64(&mut echo_payload, timestamp.total_millis()); match remote_addr { IpAddress::Ipv4(_) => { let (icmp_repr, mut icmp_packet) = send_icmp_ping!( - Icmpv4Repr, Icmpv4Packet, ident, seq_no, - echo_payload, socket, remote_addr); + Icmpv4Repr, + Icmpv4Packet, + ident, + seq_no, + echo_payload, + socket, + remote_addr + ); icmp_repr.emit(&mut icmp_packet, &device_caps.checksum); - }, + } IpAddress::Ipv6(_) => { let (icmp_repr, mut icmp_packet) = send_icmp_ping!( - Icmpv6Repr, Icmpv6Packet, ident, seq_no, - echo_payload, socket, remote_addr); - icmp_repr.emit(&src_ipv6, &remote_addr, - &mut icmp_packet, &device_caps.checksum); - }, - _ => unimplemented!() + Icmpv6Repr, + Icmpv6Packet, + ident, + seq_no, + echo_payload, + socket, + remote_addr + ); + icmp_repr.emit( + &src_ipv6, + &remote_addr, + &mut icmp_packet, + &device_caps.checksum, + ); + } + _ => unimplemented!(), } waiting_queue.insert(seq_no, timestamp); @@ -171,17 +213,36 @@ fn main() { let icmp_packet = Icmpv4Packet::new_checked(&payload).unwrap(); let icmp_repr = Icmpv4Repr::parse(&icmp_packet, &device_caps.checksum).unwrap(); - get_icmp_pong!(Icmpv4Repr, icmp_repr, payload, - waiting_queue, remote_addr, timestamp, received); + get_icmp_pong!( + Icmpv4Repr, + icmp_repr, + payload, + waiting_queue, + remote_addr, + timestamp, + received + ); } IpAddress::Ipv6(_) => { let icmp_packet = Icmpv6Packet::new_checked(&payload).unwrap(); - let icmp_repr = Icmpv6Repr::parse(&remote_addr, &src_ipv6, - &icmp_packet, &device_caps.checksum).unwrap(); - get_icmp_pong!(Icmpv6Repr, icmp_repr, payload, - waiting_queue, remote_addr, timestamp, received); - }, - _ => unimplemented!() + let icmp_repr = Icmpv6Repr::parse( + &remote_addr, + &src_ipv6, + &icmp_packet, + &device_caps.checksum, + ) + .unwrap(); + get_icmp_pong!( + Icmpv6Repr, + icmp_repr, + payload, + waiting_queue, + remote_addr, + timestamp, + received + ); + } + _ => unimplemented!(), } } @@ -195,7 +256,7 @@ fn main() { }); if seq_no == count as u16 && waiting_queue.is_empty() { - break + break; } } @@ -204,7 +265,7 @@ fn main() { Some(poll_at) if timestamp < poll_at => { let resume_at = cmp::min(poll_at, send_at); phy_wait(fd, Some(resume_at - timestamp)).expect("wait error"); - }, + } Some(_) => (), None => { phy_wait(fd, Some(send_at - timestamp)).expect("wait error"); @@ -213,6 +274,10 @@ fn main() { } println!("--- {} ping statistics ---", remote_addr); - println!("{} packets transmitted, {} received, {:.0}% packet loss", - seq_no, received, 100.0 * (seq_no - received) as f64 / seq_no as f64); + println!( + "{} packets transmitted, {} received, {:.0}% packet loss", + seq_no, + received, + 100.0 * (seq_no - received) as f64 / seq_no as f64 + ); } diff --git a/examples/server.rs b/examples/server.rs index 944cde4..1db276a 100644 --- a/examples/server.rs +++ b/examples/server.rs @@ -1,18 +1,18 @@ mod utils; -use std::str; +use log::debug; use std::collections::BTreeMap; use std::fmt::Write; use std::os::unix::io::AsRawFd; -use log::debug; +use std::str; -use smoltcp::phy::{Device, Medium, wait as phy_wait}; -use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; -use smoltcp::iface::{NeighborCache, InterfaceBuilder}; +use smoltcp::iface::{InterfaceBuilder, NeighborCache}; +use smoltcp::phy::{wait as phy_wait, Device, Medium}; use smoltcp::socket::SocketSet; -use smoltcp::socket::{UdpSocket, UdpSocketBuffer, UdpPacketMetadata}; use smoltcp::socket::{TcpSocket, TcpSocketBuffer}; +use smoltcp::socket::{UdpPacketMetadata, UdpSocket, UdpSocketBuffer}; use smoltcp::time::{Duration, Instant}; +use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; fn main() { utils::setup_logging(""); @@ -24,7 +24,7 @@ fn main() { let mut matches = utils::parse_options(&opts, free); let device = utils::parse_tuntap_options(&mut matches); let fd = device.as_raw_fd(); - let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false); + let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false); let neighbor_cache = NeighborCache::new(BTreeMap::new()); @@ -52,12 +52,11 @@ fn main() { let ip_addrs = [ IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24), IpCidr::new(IpAddress::v6(0xfdaa, 0, 0, 0, 0, 0, 0, 1), 64), - IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64) + IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64), ]; let medium = device.capabilities().medium; - let mut builder = InterfaceBuilder::new(device) - .ip_addrs(ip_addrs); + let mut builder = InterfaceBuilder::new(device).ip_addrs(ip_addrs); if medium == Medium::Ethernet { builder = builder .ethernet_addr(ethernet_addr) @@ -66,7 +65,7 @@ fn main() { let mut iface = builder.finalize(); let mut sockets = SocketSet::new(vec![]); - let udp_handle = sockets.add(udp_socket); + let udp_handle = sockets.add(udp_socket); let tcp1_handle = sockets.add(tcp1_socket); let tcp2_handle = sockets.add(tcp2_socket); let tcp3_handle = sockets.add(tcp3_socket); @@ -76,7 +75,7 @@ fn main() { loop { let timestamp = Instant::now(); match iface.poll(&mut sockets, timestamp) { - Ok(_) => {}, + Ok(_) => {} Err(e) => { debug!("poll error: {}", e); } @@ -91,16 +90,21 @@ fn main() { let client = match socket.recv() { Ok((data, endpoint)) => { - debug!("udp:6969 recv data: {:?} from {}", - str::from_utf8(data).unwrap(), endpoint); + debug!( + "udp:6969 recv data: {:?} from {}", + str::from_utf8(data).unwrap(), + endpoint + ); Some(endpoint) } - Err(_) => None + Err(_) => None, }; if let Some(endpoint) = client { let data = b"hello\n"; - debug!("udp:6969 send data: {:?}", - str::from_utf8(data.as_ref()).unwrap()); + debug!( + "udp:6969 send data: {:?}", + str::from_utf8(data.as_ref()).unwrap() + ); socket.send_slice(data, endpoint).unwrap(); } } @@ -135,21 +139,27 @@ fn main() { tcp_6970_active = socket.is_active(); if socket.may_recv() { - let data = socket.recv(|buffer| { - let recvd_len = buffer.len(); - let mut data = buffer.to_owned(); - if !data.is_empty() { - debug!("tcp:6970 recv data: {:?}", - str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)")); - data = data.split(|&b| b == b'\n').collect::>().concat(); - data.reverse(); - data.extend(b"\n"); - } - (recvd_len, data) - }).unwrap(); + let data = socket + .recv(|buffer| { + let recvd_len = buffer.len(); + let mut data = buffer.to_owned(); + if !data.is_empty() { + debug!( + "tcp:6970 recv data: {:?}", + str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)") + ); + data = data.split(|&b| b == b'\n').collect::>().concat(); + data.reverse(); + data.extend(b"\n"); + } + (recvd_len, data) + }) + .unwrap(); if socket.can_send() && !data.is_empty() { - debug!("tcp:6970 send data: {:?}", - str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)")); + debug!( + "tcp:6970 send data: {:?}", + str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)") + ); socket.send_slice(&data[..]).unwrap(); } } else if socket.may_send() { @@ -168,12 +178,14 @@ fn main() { } if socket.may_recv() { - socket.recv(|buffer| { - if !buffer.is_empty() { - debug!("tcp:6971 recv {:?} octets", buffer.len()); - } - (buffer.len(), ()) - }).unwrap(); + socket + .recv(|buffer| { + if !buffer.is_empty() { + debug!("tcp:6971 recv {:?} octets", buffer.len()); + } + (buffer.len(), ()) + }) + .unwrap(); } else if socket.may_send() { socket.close(); } @@ -187,15 +199,17 @@ fn main() { } if socket.may_send() { - socket.send(|data| { - if !data.is_empty() { - debug!("tcp:6972 send {:?} octets", data.len()); - for (i, b) in data.iter_mut().enumerate() { - *b = (i % 256) as u8; + socket + .send(|data| { + if !data.is_empty() { + debug!("tcp:6972 send {:?} octets", data.len()); + for (i, b) in data.iter_mut().enumerate() { + *b = (i % 256) as u8; + } } - } - (data.len(), ()) - }).unwrap(); + (data.len(), ()) + }) + .unwrap(); } } diff --git a/examples/tcpdump.rs b/examples/tcpdump.rs index 5ca8ec6..6bd0e8a 100644 --- a/examples/tcpdump.rs +++ b/examples/tcpdump.rs @@ -1,9 +1,9 @@ +use smoltcp::phy::wait as phy_wait; +use smoltcp::phy::{Device, RawSocket, RxToken}; +use smoltcp::time::Instant; +use smoltcp::wire::{EthernetFrame, PrettyPrinter}; use std::env; use std::os::unix::io::AsRawFd; -use smoltcp::phy::wait as phy_wait; -use smoltcp::phy::{Device, RxToken, RawSocket}; -use smoltcp::wire::{PrettyPrinter, EthernetFrame}; -use smoltcp::time::Instant; fn main() { let ifname = env::args().nth(1).unwrap(); @@ -11,9 +11,14 @@ fn main() { loop { phy_wait(socket.as_raw_fd(), None).unwrap(); let (rx_token, _) = socket.receive().unwrap(); - rx_token.consume(Instant::now(), |buffer| { - println!("{}", PrettyPrinter::>::new("", &buffer)); - Ok(()) - }).unwrap(); + rx_token + .consume(Instant::now(), |buffer| { + println!( + "{}", + PrettyPrinter::>::new("", &buffer) + ); + Ok(()) + }) + .unwrap(); } } diff --git a/examples/utils.rs b/examples/utils.rs index b4687a4..9e1cfca 100644 --- a/examples/utils.rs +++ b/examples/utils.rs @@ -1,43 +1,59 @@ #![allow(dead_code)] -use std::cell::RefCell; -use std::str::{self, FromStr}; -use std::rc::Rc; -use std::io::{self, Write}; -use std::fs::File; -use std::time::{SystemTime, UNIX_EPOCH}; -use std::env; -use std::process; -#[cfg(feature = "log")] -use log::{Level, LevelFilter, trace}; #[cfg(feature = "log")] use env_logger::Builder; -use getopts::{Options, Matches}; +use getopts::{Matches, Options}; +#[cfg(feature = "log")] +use log::{trace, Level, LevelFilter}; +use std::cell::RefCell; +use std::env; +use std::fs::File; +use std::io::{self, Write}; +use std::process; +use std::rc::Rc; +use std::str::{self, FromStr}; +use std::time::{SystemTime, UNIX_EPOCH}; -use smoltcp::phy::{Device, Tracer, FaultInjector, Medium}; +use smoltcp::phy::RawSocket; #[cfg(feature = "phy-tuntap_interface")] use smoltcp::phy::TunTapInterface; -use smoltcp::phy::{PcapWriter, PcapSink, PcapMode}; -use smoltcp::phy::RawSocket; +use smoltcp::phy::{Device, FaultInjector, Medium, Tracer}; +use smoltcp::phy::{PcapMode, PcapSink, PcapWriter}; use smoltcp::time::{Duration, Instant}; #[cfg(feature = "log")] pub fn setup_logging_with_clock(filter: &str, since_startup: F) - where F: Fn() -> Instant + Send + Sync + 'static { +where + F: Fn() -> Instant + Send + Sync + 'static, +{ Builder::new() .format(move |buf, record| { let elapsed = since_startup(); let timestamp = format!("[{}]", elapsed); if record.target().starts_with("smoltcp::") { - writeln!(buf, "\x1b[0m{} ({}): {}\x1b[0m", timestamp, - record.target().replace("smoltcp::", ""), record.args()) + writeln!( + buf, + "\x1b[0m{} ({}): {}\x1b[0m", + timestamp, + record.target().replace("smoltcp::", ""), + record.args() + ) } else if record.level() == Level::Trace { let message = format!("{}", record.args()); - writeln!(buf, "\x1b[37m{} {}\x1b[0m", timestamp, - message.replace("\n", "\n ")) + writeln!( + buf, + "\x1b[37m{} {}\x1b[0m", + timestamp, + message.replace("\n", "\n ") + ) } else { - writeln!(buf, "\x1b[32m{} ({}): {}\x1b[0m", timestamp, - record.target(), record.args()) + writeln!( + buf, + "\x1b[32m{} ({}): {}\x1b[0m", + timestamp, + record.target(), + record.args() + ) } }) .filter(None, LevelFilter::Trace) @@ -48,9 +64,7 @@ pub fn setup_logging_with_clock(filter: &str, since_startup: F) #[cfg(feature = "log")] pub fn setup_logging(filter: &str) { - setup_logging_with_clock(filter, move || { - Instant::now() - }) + setup_logging_with_clock(filter, move || Instant::now()) } pub fn create_options() -> (Options, Vec<&'static str>) { @@ -67,10 +81,17 @@ pub fn parse_options(options: &Options, free: Vec<&str>) -> Matches { } Ok(matches) => { if matches.opt_present("h") || matches.free.len() != free.len() { - let brief = format!("Usage: {} [OPTION]... {}", - env::args().next().unwrap(), free.join(" ")); + let brief = format!( + "Usage: {} [OPTION]... {}", + env::args().next().unwrap(), + free.join(" ") + ); print!("{}", options.usage(&brief)); - process::exit(if matches.free.len() != free.len() { 1 } else { 0 }) + process::exit(if matches.free.len() != free.len() { + 1 + } else { + 0 + }) } matches } @@ -86,7 +107,7 @@ pub fn add_tuntap_options(opts: &mut Options, _free: &mut Vec<&str>) { pub fn parse_tuntap_options(matches: &mut Matches) -> TunTapInterface { let tun = matches.opt_str("tun"); let tap = matches.opt_str("tap"); - match(tun,tap) { + match (tun, tap) { (Some(tun), None) => TunTapInterface::new(&tun, Medium::Ip).unwrap(), (None, Some(tap)) => TunTapInterface::new(&tap, Medium::Ethernet).unwrap(), _ => panic!("You must specify exactly one of --tun or --tap"), @@ -100,32 +121,78 @@ pub fn parse_raw_socket_options(matches: &mut Matches) -> RawSocket { pub fn add_middleware_options(opts: &mut Options, _free: &mut Vec<&str>) { opts.optopt("", "pcap", "Write a packet capture file", "FILE"); - opts.optopt("", "drop-chance", "Chance of dropping a packet (%)", "CHANCE"); - opts.optopt("", "corrupt-chance", "Chance of corrupting a packet (%)", "CHANCE"); - opts.optopt("", "size-limit", "Drop packets larger than given size (octets)", "SIZE"); - opts.optopt("", "tx-rate-limit", "Drop packets after transmit rate exceeds given limit \ - (packets per interval)", "RATE"); - opts.optopt("", "rx-rate-limit", "Drop packets after transmit rate exceeds given limit \ - (packets per interval)", "RATE"); - opts.optopt("", "shaping-interval", "Sets the interval for rate limiting (ms)", "RATE"); + opts.optopt( + "", + "drop-chance", + "Chance of dropping a packet (%)", + "CHANCE", + ); + opts.optopt( + "", + "corrupt-chance", + "Chance of corrupting a packet (%)", + "CHANCE", + ); + opts.optopt( + "", + "size-limit", + "Drop packets larger than given size (octets)", + "SIZE", + ); + opts.optopt( + "", + "tx-rate-limit", + "Drop packets after transmit rate exceeds given limit \ + (packets per interval)", + "RATE", + ); + opts.optopt( + "", + "rx-rate-limit", + "Drop packets after transmit rate exceeds given limit \ + (packets per interval)", + "RATE", + ); + opts.optopt( + "", + "shaping-interval", + "Sets the interval for rate limiting (ms)", + "RATE", + ); } -pub fn parse_middleware_options(matches: &mut Matches, device: D, loopback: bool) - -> FaultInjector>>> - where D: for<'a> Device<'a> +pub fn parse_middleware_options( + matches: &mut Matches, + device: D, + loopback: bool, +) -> FaultInjector>>> +where + D: for<'a> Device<'a>, { - let drop_chance = matches.opt_str("drop-chance").map(|s| u8::from_str(&s).unwrap()) - .unwrap_or(0); - let corrupt_chance = matches.opt_str("corrupt-chance").map(|s| u8::from_str(&s).unwrap()) - .unwrap_or(0); - let size_limit = matches.opt_str("size-limit").map(|s| usize::from_str(&s).unwrap()) - .unwrap_or(0); - let tx_rate_limit = matches.opt_str("tx-rate-limit").map(|s| u64::from_str(&s).unwrap()) - .unwrap_or(0); - let rx_rate_limit = matches.opt_str("rx-rate-limit").map(|s| u64::from_str(&s).unwrap()) - .unwrap_or(0); - let shaping_interval = matches.opt_str("shaping-interval").map(|s| u64::from_str(&s).unwrap()) - .unwrap_or(0); + let drop_chance = matches + .opt_str("drop-chance") + .map(|s| u8::from_str(&s).unwrap()) + .unwrap_or(0); + let corrupt_chance = matches + .opt_str("corrupt-chance") + .map(|s| u8::from_str(&s).unwrap()) + .unwrap_or(0); + let size_limit = matches + .opt_str("size-limit") + .map(|s| usize::from_str(&s).unwrap()) + .unwrap_or(0); + let tx_rate_limit = matches + .opt_str("tx-rate-limit") + .map(|s| u64::from_str(&s).unwrap()) + .unwrap_or(0); + let rx_rate_limit = matches + .opt_str("rx-rate-limit") + .map(|s| u64::from_str(&s).unwrap()) + .unwrap_or(0); + let shaping_interval = matches + .opt_str("shaping-interval") + .map(|s| u64::from_str(&s).unwrap()) + .unwrap_or(0); let pcap_writer: Box; if let Some(pcap_filename) = matches.opt_str("pcap") { @@ -134,12 +201,19 @@ pub fn parse_middleware_options(matches: &mut Matches, device: D, loopback: b pcap_writer = Box::new(io::sink()) } - let seed = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().subsec_nanos(); + let seed = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .subsec_nanos(); let device = PcapWriter::new( device, Rc::new(RefCell::new(pcap_writer)) as Rc, - if loopback { PcapMode::TxOnly } else { PcapMode::Both }, + if loopback { + PcapMode::TxOnly + } else { + PcapMode::Both + }, ); let device = Tracer::new(device, |_timestamp, _printer| { diff --git a/src/iface/interface.rs b/src/iface/interface.rs index f4be495..0fd63ac 100644 --- a/src/iface/interface.rs +++ b/src/iface/interface.rs @@ -3,16 +3,16 @@ // and RFCs 8200 and 4861 for any IPv6 and NDISC work. use core::cmp; -use managed::{ManagedSlice, ManagedMap}; +use managed::{ManagedMap, ManagedSlice}; -use crate::{Error, Result}; -use crate::phy::{Device, DeviceCapabilities, RxToken, TxToken, Medium}; +use crate::iface::Routes; +#[cfg(feature = "medium-ethernet")] +use crate::iface::{NeighborAnswer, NeighborCache}; +use crate::phy::{Device, DeviceCapabilities, Medium, RxToken, TxToken}; +use crate::socket::*; use crate::time::{Duration, Instant}; use crate::wire::*; -use crate::socket::*; -#[cfg(feature = "medium-ethernet")] -use crate::iface::{NeighborCache, NeighborAnswer}; -use crate::iface::Routes; +use crate::{Error, Result}; /// A network interface. /// @@ -21,7 +21,7 @@ use crate::iface::Routes; /// a `&mut [T]`, or `Vec` if a heap is available. pub struct Interface<'a, DeviceT: for<'d> Device<'d>> { device: DeviceT, - inner: InterfaceInner<'a>, + inner: InterfaceInner<'a>, } /// The device independent part of an Ethernet network interface. @@ -33,41 +33,45 @@ pub struct Interface<'a, DeviceT: for<'d> Device<'d>> { /// exclusively). However, it is still possible to call methods on its `inner` field. struct InterfaceInner<'a> { #[cfg(feature = "medium-ethernet")] - neighbor_cache: Option>, + neighbor_cache: Option>, #[cfg(feature = "medium-ethernet")] - ethernet_addr: Option, - ip_addrs: ManagedSlice<'a, IpCidr>, + ethernet_addr: Option, + ip_addrs: ManagedSlice<'a, IpCidr>, #[cfg(feature = "proto-ipv4")] - any_ip: bool, - routes: Routes<'a>, + any_ip: bool, + routes: Routes<'a>, #[cfg(feature = "proto-igmp")] - ipv4_multicast_groups: ManagedMap<'a, Ipv4Address, ()>, + ipv4_multicast_groups: ManagedMap<'a, Ipv4Address, ()>, /// When to report for (all or) the next multicast group membership via IGMP #[cfg(feature = "proto-igmp")] - igmp_report_state: IgmpReportState, + igmp_report_state: IgmpReportState, } /// A builder structure used for creating a network interface. -pub struct InterfaceBuilder <'a, DeviceT: for<'d> Device<'d>> { - device: DeviceT, +pub struct InterfaceBuilder<'a, DeviceT: for<'d> Device<'d>> { + device: DeviceT, #[cfg(feature = "medium-ethernet")] - ethernet_addr: Option, + ethernet_addr: Option, #[cfg(feature = "medium-ethernet")] - neighbor_cache: Option>, - ip_addrs: ManagedSlice<'a, IpCidr>, + neighbor_cache: Option>, + ip_addrs: ManagedSlice<'a, IpCidr>, #[cfg(feature = "proto-ipv4")] - any_ip: bool, - routes: Routes<'a>, + any_ip: bool, + routes: Routes<'a>, /// Does not share storage with `ipv6_multicast_groups` to avoid IPv6 size overhead. #[cfg(feature = "proto-igmp")] - ipv4_multicast_groups: ManagedMap<'a, Ipv4Address, ()>, + ipv4_multicast_groups: ManagedMap<'a, Ipv4Address, ()>, } impl<'a, DeviceT> InterfaceBuilder<'a, DeviceT> - where DeviceT: for<'d> Device<'d> { +where + DeviceT: for<'d> Device<'d>, +{ /// Create a builder used for creating a network interface using the /// given device and address. - #[cfg_attr(feature = "medium-ethernet", doc = r##" + #[cfg_attr( + feature = "medium-ethernet", + doc = r##" # Examples ``` @@ -90,20 +94,21 @@ let iface = InterfaceBuilder::new(device) .ip_addrs(ip_addrs) .finalize(); ``` - "##)] + "## + )] pub fn new(device: DeviceT) -> Self { InterfaceBuilder { - device: device, + device: device, #[cfg(feature = "medium-ethernet")] - ethernet_addr: None, + ethernet_addr: None, #[cfg(feature = "medium-ethernet")] - neighbor_cache: None, - ip_addrs: ManagedSlice::Borrowed(&mut []), + neighbor_cache: None, + ip_addrs: ManagedSlice::Borrowed(&mut []), #[cfg(feature = "proto-ipv4")] - any_ip: false, - routes: Routes::new(ManagedMap::Borrowed(&mut [])), + any_ip: false, + routes: Routes::new(ManagedMap::Borrowed(&mut [])), #[cfg(feature = "proto-igmp")] - ipv4_multicast_groups: ManagedMap::Borrowed(&mut []), + ipv4_multicast_groups: ManagedMap::Borrowed(&mut []), } } @@ -129,7 +134,8 @@ let iface = InterfaceBuilder::new(device) /// /// [ip_addrs]: struct.Interface.html#method.ip_addrs pub fn ip_addrs(mut self, ip_addrs: T) -> Self - where T: Into> + where + T: Into>, { let ip_addrs = ip_addrs.into(); InterfaceInner::check_ip_addrs(&ip_addrs); @@ -161,7 +167,8 @@ let iface = InterfaceBuilder::new(device) /// /// [routes]: struct.Interface.html#method.routes pub fn routes(mut self, routes: T) -> InterfaceBuilder<'a, DeviceT> - where T: Into> + where + T: Into>, { self.routes = routes.into(); self @@ -179,7 +186,8 @@ let iface = InterfaceBuilder::new(device) /// [`join_multicast_group()`]: struct.Interface.html#method.join_multicast_group #[cfg(feature = "proto-igmp")] pub fn ipv4_multicast_groups(mut self, ipv4_multicast_groups: T) -> Self - where T: Into> + where + T: Into>, { self.ipv4_multicast_groups = ipv4_multicast_groups.into(); self @@ -209,13 +217,25 @@ let iface = InterfaceBuilder::new(device) #[cfg(feature = "medium-ethernet")] let (ethernet_addr, neighbor_cache) = match device_capabilities.medium { Medium::Ethernet => ( - Some(self.ethernet_addr.expect("ethernet_addr required option was not set")), - Some(self.neighbor_cache.expect("neighbor_cache required option was not set")) + Some( + self.ethernet_addr + .expect("ethernet_addr required option was not set"), + ), + Some( + self.neighbor_cache + .expect("neighbor_cache required option was not set"), + ), ), #[cfg(feature = "medium-ip")] Medium::Ip => { - assert!(self.ethernet_addr.is_none(), "ethernet_addr is set, but device medium is IP"); - assert!(self.neighbor_cache.is_none(), "neighbor_cache is set, but device medium is IP"); + assert!( + self.ethernet_addr.is_none(), + "ethernet_addr is set, but device medium is IP" + ); + assert!( + self.neighbor_cache.is_none(), + "neighbor_cache is set, but device medium is IP" + ); (None, None) } }; @@ -235,7 +255,7 @@ let iface = InterfaceBuilder::new(device) ipv4_multicast_groups: self.ipv4_multicast_groups, #[cfg(feature = "proto-igmp")] igmp_report_state: IgmpReportState::Inactive, - } + }, } } } @@ -288,27 +308,39 @@ impl<'a> IpPacket<'a> { } } - pub(crate) fn emit_payload(&self, _ip_repr: IpRepr, payload: &mut [u8], caps: &DeviceCapabilities) { + pub(crate) fn emit_payload( + &self, + _ip_repr: IpRepr, + payload: &mut [u8], + caps: &DeviceCapabilities, + ) { match self { #[cfg(feature = "proto-ipv4")] - IpPacket::Icmpv4((_, icmpv4_repr)) => - icmpv4_repr.emit(&mut Icmpv4Packet::new_unchecked(payload), &caps.checksum), + IpPacket::Icmpv4((_, icmpv4_repr)) => { + icmpv4_repr.emit(&mut Icmpv4Packet::new_unchecked(payload), &caps.checksum) + } #[cfg(feature = "proto-igmp")] - IpPacket::Igmp((_, igmp_repr)) => - igmp_repr.emit(&mut IgmpPacket::new_unchecked(payload)), + IpPacket::Igmp((_, igmp_repr)) => { + igmp_repr.emit(&mut IgmpPacket::new_unchecked(payload)) + } #[cfg(feature = "proto-ipv6")] - IpPacket::Icmpv6((_, icmpv6_repr)) => - icmpv6_repr.emit(&_ip_repr.src_addr(), &_ip_repr.dst_addr(), - &mut Icmpv6Packet::new_unchecked(payload), &caps.checksum), + IpPacket::Icmpv6((_, icmpv6_repr)) => icmpv6_repr.emit( + &_ip_repr.src_addr(), + &_ip_repr.dst_addr(), + &mut Icmpv6Packet::new_unchecked(payload), + &caps.checksum, + ), #[cfg(feature = "socket-raw")] - IpPacket::Raw((_, raw_packet)) => - payload.copy_from_slice(raw_packet), + IpPacket::Raw((_, raw_packet)) => payload.copy_from_slice(raw_packet), #[cfg(feature = "socket-udp")] - IpPacket::Udp((_, udp_repr, inner_payload)) => - udp_repr.emit(&mut UdpPacket::new_unchecked(payload), - &_ip_repr.src_addr(), &_ip_repr.dst_addr(), - inner_payload.len(), |buf| buf.copy_from_slice(inner_payload), - &caps.checksum), + IpPacket::Udp((_, udp_repr, inner_payload)) => udp_repr.emit( + &mut UdpPacket::new_unchecked(payload), + &_ip_repr.src_addr(), + &_ip_repr.dst_addr(), + inner_payload.len(), + |buf| buf.copy_from_slice(inner_payload), + &caps.checksum, + ), #[cfg(feature = "socket-tcp")] IpPacket::Tcp((_, mut tcp_repr)) => { // This is a terrible hack to make TCP performance more acceptable on systems @@ -329,17 +361,22 @@ impl<'a> IpPacket<'a> { } } - tcp_repr.emit(&mut TcpPacket::new_unchecked(payload), - &_ip_repr.src_addr(), &_ip_repr.dst_addr(), - &caps.checksum); + tcp_repr.emit( + &mut TcpPacket::new_unchecked(payload), + &_ip_repr.src_addr(), + &_ip_repr.dst_addr(), + &caps.checksum, + ); } #[cfg(feature = "socket-dhcpv4")] - IpPacket::Dhcpv4((_, udp_repr, dhcp_repr)) => - udp_repr.emit(&mut UdpPacket::new_unchecked(payload), - &_ip_repr.src_addr(), &_ip_repr.dst_addr(), - dhcp_repr.buffer_len(), - |buf| dhcp_repr.emit(&mut DhcpPacket::new_unchecked(buf)).unwrap(), - &caps.checksum), + IpPacket::Dhcpv4((_, udp_repr, dhcp_repr)) => udp_repr.emit( + &mut UdpPacket::new_unchecked(payload), + &_ip_repr.src_addr(), + &_ip_repr.dst_addr(), + dhcp_repr.buffer_len(), + |buf| dhcp_repr.emit(&mut DhcpPacket::new_unchecked(buf)).unwrap(), + &caps.checksum, + ), } } } @@ -361,20 +398,22 @@ fn icmp_reply_payload_len(len: usize, mtu: usize, header_len: usize) -> usize { enum IgmpReportState { Inactive, ToGeneralQuery { - version: IgmpVersion, - timeout: Instant, - interval: Duration, - next_index: usize + version: IgmpVersion, + timeout: Instant, + interval: Duration, + next_index: usize, }, ToSpecificQuery { - version: IgmpVersion, - timeout: Instant, - group: Ipv4Address + version: IgmpVersion, + timeout: Instant, + group: Ipv4Address, }, } impl<'a, DeviceT> Interface<'a, DeviceT> - where DeviceT: for<'d> Device<'d> { +where + DeviceT: for<'d> Device<'d>, +{ /// Get the Ethernet address of the interface. /// /// # Panics @@ -417,18 +456,24 @@ impl<'a, DeviceT> Interface<'a, DeviceT> /// /// Returns `Ok(announce_sent)` if the address was added successfully, where `annouce_sent` /// indicates whether an initial immediate announcement has been sent. - pub fn join_multicast_group>(&mut self, addr: T, _timestamp: Instant) -> Result { - + pub fn join_multicast_group>( + &mut self, + addr: T, + _timestamp: Instant, + ) -> Result { match addr.into() { #[cfg(feature = "proto-igmp")] IpAddress::Ipv4(addr) => { - let is_not_new = self.inner.ipv4_multicast_groups.insert(addr, ()) + let is_not_new = self + .inner + .ipv4_multicast_groups + .insert(addr, ()) .map_err(|_| Error::Exhausted)? .is_some(); if is_not_new { Ok(false) - } else if let Some(pkt) = - self.inner.igmp_report_packet(IgmpVersion::Version2, addr) { + } else if let Some(pkt) = self.inner.igmp_report_packet(IgmpVersion::Version2, addr) + { let cx = self.context(_timestamp); // Send initial membership report let tx_token = self.device.transmit().ok_or(Error::Exhausted)?; @@ -439,7 +484,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT> } } // Multicast is not yet implemented for other address families - _ => Err(Error::Unaddressable) + _ => Err(Error::Unaddressable), } } @@ -447,12 +492,15 @@ impl<'a, DeviceT> Interface<'a, DeviceT> /// /// Returns `Ok(leave_sent)` if the address was removed successfully, where `leave_sent` /// indicates whether an immediate leave packet has been sent. - pub fn leave_multicast_group>(&mut self, addr: T, _timestamp: Instant) -> Result { + pub fn leave_multicast_group>( + &mut self, + addr: T, + _timestamp: Instant, + ) -> Result { match addr.into() { #[cfg(feature = "proto-igmp")] IpAddress::Ipv4(addr) => { - let was_not_present = self.inner.ipv4_multicast_groups.remove(&addr) - .is_none(); + let was_not_present = self.inner.ipv4_multicast_groups.remove(&addr).is_none(); if was_not_present { Ok(false) } else if let Some(pkt) = self.inner.igmp_leave_packet(addr) { @@ -466,7 +514,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT> } } // Multicast is not yet implemented for other address families - _ => Err(Error::Unaddressable) + _ => Err(Error::Unaddressable), } } @@ -483,11 +531,13 @@ impl<'a, DeviceT> Interface<'a, DeviceT> /// Get the first IPv4 address if present. #[cfg(feature = "proto-ipv4")] pub fn ipv4_addr(&self) -> Option { - self.ip_addrs().iter() + self.ip_addrs() + .iter() .filter_map(|cidr| match cidr.address() { IpAddress::Ipv4(addr) => Some(addr), _ => None, - }).next() + }) + .next() } /// Update the IP addresses of the interface. @@ -541,7 +591,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT> let mut readiness_may_have_changed = false; loop { let processed_any = self.socket_ingress(&cx, sockets); - let emitted_any = self.socket_egress(&cx, sockets)?; + let emitted_any = self.socket_egress(&cx, sockets)?; #[cfg(feature = "proto-igmp")] self.igmp_egress(&cx, timestamp)?; @@ -549,7 +599,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT> if processed_any || emitted_any { readiness_may_have_changed = true; } else { - break + break; } } Ok(readiness_may_have_changed) @@ -566,15 +616,19 @@ impl<'a, DeviceT> Interface<'a, DeviceT> pub fn poll_at(&self, sockets: &SocketSet, timestamp: Instant) -> Option { let cx = self.context(timestamp); - sockets.iter().filter_map(|socket| { - let socket_poll_at = socket.poll_at(&cx); - match socket.meta().poll_at(socket_poll_at, |ip_addr| - self.inner.has_neighbor(&cx, &ip_addr)) { + sockets + .iter() + .filter_map(|socket| { + let socket_poll_at = socket.poll_at(&cx); + match socket.meta().poll_at(socket_poll_at, |ip_addr| { + self.inner.has_neighbor(&cx, &ip_addr) + }) { PollAt::Ingress => None, PollAt::Time(instant) => Some(instant), PollAt::Now => Some(Instant::from_millis(0)), - } - }).min() + } + }) + .min() } /// Return an _advisory wait time_ for calling [poll] the next time. @@ -587,55 +641,52 @@ impl<'a, DeviceT> Interface<'a, DeviceT> /// [Duration]: struct.Duration.html pub fn poll_delay(&self, sockets: &SocketSet, timestamp: Instant) -> Option { match self.poll_at(sockets, timestamp) { - Some(poll_at) if timestamp < poll_at => { - Some(poll_at - timestamp) - } - Some(_) => { - Some(Duration::from_millis(0)) - } - _ => None + Some(poll_at) if timestamp < poll_at => Some(poll_at - timestamp), + Some(_) => Some(Duration::from_millis(0)), + _ => None, } } fn socket_ingress(&mut self, cx: &Context, sockets: &mut SocketSet) -> bool { let mut processed_any = false; - let &mut Self { ref mut device, ref mut inner } = self; + let &mut Self { + ref mut device, + ref mut inner, + } = self; while let Some((rx_token, tx_token)) = device.receive() { if let Err(err) = rx_token.consume(cx.now, |frame| { match cx.caps.medium { #[cfg(feature = "medium-ethernet")] - Medium::Ethernet => { - match inner.process_ethernet(cx, sockets, &frame) { - Ok(response) => { - processed_any = true; - if let Some(packet) = response { - if let Err(err) = inner.dispatch(cx, tx_token, packet) { - net_debug!("Failed to send response: {}", err); - } + Medium::Ethernet => match inner.process_ethernet(cx, sockets, &frame) { + Ok(response) => { + processed_any = true; + if let Some(packet) = response { + if let Err(err) = inner.dispatch(cx, tx_token, packet) { + net_debug!("Failed to send response: {}", err); } } - Err(err) => { - net_debug!("cannot process ingress packet: {}", err); - #[cfg(not(feature = "defmt"))] - net_debug!("packet dump follows:\n{}", - PrettyPrinter::>::new("", &frame)); - } } - } + Err(err) => { + net_debug!("cannot process ingress packet: {}", err); + #[cfg(not(feature = "defmt"))] + net_debug!( + "packet dump follows:\n{}", + PrettyPrinter::>::new("", &frame) + ); + } + }, #[cfg(feature = "medium-ip")] - Medium::Ip => { - match inner.process_ip(cx, sockets, &frame) { - Ok(response) => { - processed_any = true; - if let Some(packet) = response { - if let Err(err) = inner.dispatch_ip(cx, tx_token, packet) { - net_debug!("Failed to send response: {}", err); - } + Medium::Ip => match inner.process_ip(cx, sockets, &frame) { + Ok(response) => { + processed_any = true; + if let Some(packet) = response { + if let Err(err) = inner.dispatch_ip(cx, tx_token, packet) { + net_debug!("Failed to send response: {}", err); } } - Err(err) => net_debug!("cannot process ingress packet: {}", err), } - } + Err(err) => net_debug!("cannot process ingress packet: {}", err), + }, } Ok(()) @@ -652,79 +703,88 @@ impl<'a, DeviceT> Interface<'a, DeviceT> let mut emitted_any = false; for mut socket in sockets.iter_mut() { - if !socket.meta_mut().egress_permitted(cx.now, |ip_addr| - self.inner.has_neighbor(cx, &ip_addr)) { - continue + if !socket + .meta_mut() + .egress_permitted(cx.now, |ip_addr| self.inner.has_neighbor(cx, &ip_addr)) + { + continue; } let mut neighbor_addr = None; let mut device_result = Ok(()); - let &mut Self { ref mut device, ref mut inner } = self; + let &mut Self { + ref mut device, + ref mut inner, + } = self; macro_rules! respond { - ($response:expr) => ({ + ($response:expr) => {{ let response = $response; neighbor_addr = Some(response.ip_repr().dst_addr()); let tx_token = device.transmit().ok_or(Error::Exhausted)?; device_result = inner.dispatch_ip(cx, tx_token, response); device_result - }) + }}; } - - let socket_result = - match *socket { - #[cfg(feature = "socket-raw")] - Socket::Raw(ref mut socket) => - socket.dispatch(cx, |response| - respond!(IpPacket::Raw(response))), - #[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))] - Socket::Icmp(ref mut socket) => - socket.dispatch(cx, |response| { - match response { - #[cfg(feature = "proto-ipv4")] - (IpRepr::Ipv4(ipv4_repr), IcmpRepr::Ipv4(icmpv4_repr)) => - respond!(IpPacket::Icmpv4((ipv4_repr, icmpv4_repr))), - #[cfg(feature = "proto-ipv6")] - (IpRepr::Ipv6(ipv6_repr), IcmpRepr::Ipv6(icmpv6_repr)) => - respond!(IpPacket::Icmpv6((ipv6_repr, icmpv6_repr))), - _ => Err(Error::Unaddressable) - } - }), - #[cfg(feature = "socket-udp")] - Socket::Udp(ref mut socket) => - socket.dispatch(cx, |response| - respond!(IpPacket::Udp(response))), - #[cfg(feature = "socket-tcp")] - Socket::Tcp(ref mut socket) => { - socket.dispatch(cx, |response| - respond!(IpPacket::Tcp(response))) + let socket_result = match *socket { + #[cfg(feature = "socket-raw")] + Socket::Raw(ref mut socket) => { + socket.dispatch(cx, |response| respond!(IpPacket::Raw(response))) + } + #[cfg(all( + feature = "socket-icmp", + any(feature = "proto-ipv4", feature = "proto-ipv6") + ))] + Socket::Icmp(ref mut socket) => socket.dispatch(cx, |response| match response { + #[cfg(feature = "proto-ipv4")] + (IpRepr::Ipv4(ipv4_repr), IcmpRepr::Ipv4(icmpv4_repr)) => { + respond!(IpPacket::Icmpv4((ipv4_repr, icmpv4_repr))) } - #[cfg(feature = "socket-dhcpv4")] - Socket::Dhcpv4(ref mut socket) => - // todo don't unwrap - socket.dispatch(cx, |response| - respond!(IpPacket::Dhcpv4(response))), - }; + #[cfg(feature = "proto-ipv6")] + (IpRepr::Ipv6(ipv6_repr), IcmpRepr::Ipv6(icmpv6_repr)) => { + respond!(IpPacket::Icmpv6((ipv6_repr, icmpv6_repr))) + } + _ => Err(Error::Unaddressable), + }), + #[cfg(feature = "socket-udp")] + Socket::Udp(ref mut socket) => { + socket.dispatch(cx, |response| respond!(IpPacket::Udp(response))) + } + #[cfg(feature = "socket-tcp")] + Socket::Tcp(ref mut socket) => { + socket.dispatch(cx, |response| respond!(IpPacket::Tcp(response))) + } + #[cfg(feature = "socket-dhcpv4")] + Socket::Dhcpv4(ref mut socket) => + // todo don't unwrap + { + socket.dispatch(cx, |response| respond!(IpPacket::Dhcpv4(response))) + } + }; match (device_result, socket_result) { - (Err(Error::Exhausted), _) => break, // nowhere to transmit - (Ok(()), Err(Error::Exhausted)) => (), // nothing to transmit + (Err(Error::Exhausted), _) => break, // nowhere to transmit + (Ok(()), Err(Error::Exhausted)) => (), // nothing to transmit (Err(Error::Unaddressable), _) => { // `NeighborCache` already takes care of rate limiting the neighbor discovery // requests from the socket. However, without an additional rate limiting // mechanism, we would spin on every socket that has yet to discover its // neighboor. - socket.meta_mut().neighbor_missing(cx.now, - neighbor_addr.expect("non-IP response packet")); - break + socket + .meta_mut() + .neighbor_missing(cx.now, neighbor_addr.expect("non-IP response packet")); + break; } (Err(err), _) | (_, Err(err)) => { - net_debug!("{}: cannot dispatch egress packet: {}", - socket.meta().handle, err); - return Err(err) + net_debug!( + "{}: cannot dispatch egress packet: {}", + socket.meta().handle, + err + ); + return Err(err); } - (Ok(()), Ok(())) => emitted_any = true + (Ok(()), Ok(())) => emitted_any = true, } } Ok(emitted_any) @@ -735,8 +795,11 @@ impl<'a, DeviceT> Interface<'a, DeviceT> #[cfg(feature = "proto-igmp")] fn igmp_egress(&mut self, cx: &Context, timestamp: Instant) -> Result { match self.inner.igmp_report_state { - IgmpReportState::ToSpecificQuery { version, timeout, group } - if timestamp >= timeout => { + IgmpReportState::ToSpecificQuery { + version, + timeout, + group, + } if timestamp >= timeout => { if let Some(pkt) = self.inner.igmp_report_packet(version, group) { // Send initial membership report let tx_token = self.device.transmit().ok_or(Error::Exhausted)?; @@ -746,9 +809,15 @@ impl<'a, DeviceT> Interface<'a, DeviceT> self.inner.igmp_report_state = IgmpReportState::Inactive; Ok(true) } - IgmpReportState::ToGeneralQuery { version, timeout, interval, next_index } - if timestamp >= timeout => { - let addr = self.inner.ipv4_multicast_groups + IgmpReportState::ToGeneralQuery { + version, + timeout, + interval, + next_index, + } if timestamp >= timeout => { + let addr = self + .inner + .ipv4_multicast_groups .iter() .nth(next_index) .map(|(addr, ())| *addr); @@ -763,7 +832,10 @@ impl<'a, DeviceT> Interface<'a, DeviceT> let next_timeout = (timeout + interval).max(timestamp); self.inner.igmp_report_state = IgmpReportState::ToGeneralQuery { - version, timeout: next_timeout, interval, next_index: next_index + 1 + version, + timeout: next_timeout, + interval, + next_index: next_index + 1, }; Ok(true) } @@ -774,7 +846,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT> } } } - _ => Ok(false) + _ => Ok(false), } } @@ -813,7 +885,7 @@ impl<'a> InterfaceInner<'a> { 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::LOOPBACK => { // 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..] @@ -832,13 +904,13 @@ impl<'a> InterfaceInner<'a> { /// Get the first IPv4 address of the interface. #[cfg(feature = "proto-ipv4")] pub fn ipv4_address(&self) -> Option { - self.ip_addrs.iter() - .filter_map( - |addr| match *addr { - IpCidr::Ipv4(cidr) => Some(cidr.address()), - #[cfg(feature = "proto-ipv6")] - IpCidr::Ipv6(_) => None - }) + self.ip_addrs + .iter() + .filter_map(|addr| match *addr { + IpCidr::Ipv4(cidr) => Some(cidr.address()), + #[cfg(feature = "proto-ipv6")] + IpCidr::Ipv6(_) => None, + }) .next() } @@ -849,33 +921,34 @@ impl<'a> InterfaceInner<'a> { pub fn has_multicast_group>(&self, addr: T) -> bool { match addr.into() { #[cfg(feature = "proto-igmp")] - IpAddress::Ipv4(key) => - key == Ipv4Address::MULTICAST_ALL_SYSTEMS || - self.ipv4_multicast_groups.get(&key).is_some(), - _ => - false, + IpAddress::Ipv4(key) => { + key == Ipv4Address::MULTICAST_ALL_SYSTEMS + || self.ipv4_multicast_groups.get(&key).is_some() + } + _ => false, } } #[cfg(feature = "medium-ethernet")] - fn process_ethernet<'frame, T: AsRef<[u8]>> - (&mut self, cx: &Context, sockets: &mut SocketSet, frame: &'frame T) -> - Result>> - { + fn process_ethernet<'frame, T: AsRef<[u8]>>( + &mut self, + cx: &Context, + sockets: &mut SocketSet, + frame: &'frame T, + ) -> Result>> { let eth_frame = EthernetFrame::new_checked(frame)?; // Ignore any packets not directed to our hardware address or any of the multicast groups. - if !eth_frame.dst_addr().is_broadcast() && - !eth_frame.dst_addr().is_multicast() && - eth_frame.dst_addr() != self.ethernet_addr.unwrap() + if !eth_frame.dst_addr().is_broadcast() + && !eth_frame.dst_addr().is_multicast() + && eth_frame.dst_addr() != self.ethernet_addr.unwrap() { - return Ok(None) + return Ok(None); } match eth_frame.ethertype() { #[cfg(feature = "proto-ipv4")] - EthernetProtocol::Arp => - self.process_arp(cx.now, ð_frame), + EthernetProtocol::Arp => self.process_arp(cx.now, ð_frame), #[cfg(feature = "proto-ipv4")] EthernetProtocol::Ipv4 => { let ipv4_packet = Ipv4Packet::new_checked(eth_frame.payload())?; @@ -883,25 +956,41 @@ impl<'a> InterfaceInner<'a> { // Fill the neighbor cache from IP header of unicast frames. let ip_addr = IpAddress::Ipv4(ipv4_packet.src_addr()); if self.in_same_network(&ip_addr) { - self.neighbor_cache.as_mut().unwrap().fill(ip_addr, eth_frame.src_addr(), cx.now); + self.neighbor_cache.as_mut().unwrap().fill( + ip_addr, + eth_frame.src_addr(), + cx.now, + ); } } - self.process_ipv4(cx, sockets, &ipv4_packet).map(|o| o.map(EthernetPacket::Ip)) + self.process_ipv4(cx, sockets, &ipv4_packet) + .map(|o| o.map(EthernetPacket::Ip)) } #[cfg(feature = "proto-ipv6")] EthernetProtocol::Ipv6 => { let ipv6_packet = Ipv6Packet::new_checked(eth_frame.payload())?; - if eth_frame.src_addr().is_unicast() && ipv6_packet.src_addr().is_unicast() { + if eth_frame.src_addr().is_unicast() && ipv6_packet.src_addr().is_unicast() { // Fill the neighbor cache from IP header of unicast frames. let ip_addr = IpAddress::Ipv6(ipv6_packet.src_addr()); - if self.in_same_network(&ip_addr) && - self.neighbor_cache.as_mut().unwrap().lookup(&ip_addr, cx.now).found() { - self.neighbor_cache.as_mut().unwrap().fill(ip_addr, eth_frame.src_addr(), cx.now); + if self.in_same_network(&ip_addr) + && self + .neighbor_cache + .as_mut() + .unwrap() + .lookup(&ip_addr, cx.now) + .found() + { + self.neighbor_cache.as_mut().unwrap().fill( + ip_addr, + eth_frame.src_addr(), + cx.now, + ); } } - self.process_ipv6(cx, sockets, &ipv6_packet).map(|o| o.map(EthernetPacket::Ip)) + self.process_ipv6(cx, sockets, &ipv6_packet) + .map(|o| o.map(EthernetPacket::Ip)) } // Drop all other traffic. _ => Err(Error::Unrecognized), @@ -909,10 +998,12 @@ impl<'a> InterfaceInner<'a> { } #[cfg(feature = "medium-ip")] - fn process_ip<'frame, T: AsRef<[u8]>> - (&mut self, cx: &Context, sockets: &mut SocketSet, ip_payload: &'frame T) -> - Result>> - { + fn process_ip<'frame, T: AsRef<[u8]>>( + &mut self, + cx: &Context, + sockets: &mut SocketSet, + ip_payload: &'frame T, + ) -> Result>> { match IpVersion::of_packet(ip_payload.as_ref()) { #[cfg(feature = "proto-ipv4")] Ok(IpVersion::Ipv4) => { @@ -930,10 +1021,11 @@ impl<'a> InterfaceInner<'a> { } #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))] - fn process_arp<'frame, T: AsRef<[u8]>> - (&mut self, timestamp: Instant, eth_frame: &EthernetFrame<&'frame T>) -> - Result>> - { + fn process_arp<'frame, T: AsRef<[u8]>>( + &mut self, + timestamp: Instant, + eth_frame: &EthernetFrame<&'frame T>, + ) -> Result>> { let arp_packet = ArpPacket::new_checked(eth_frame.payload())?; let arp_repr = ArpRepr::parse(&arp_packet)?; @@ -942,16 +1034,22 @@ impl<'a> InterfaceInner<'a> { // requests and replies, to minimize the chance that we have to perform // an explicit ARP request. ArpRepr::EthernetIpv4 { - operation, source_hardware_addr, source_protocol_addr, target_protocol_addr, .. + operation, + source_hardware_addr, + source_protocol_addr, + target_protocol_addr, + .. } => { if source_protocol_addr.is_unicast() && source_hardware_addr.is_unicast() { - self.neighbor_cache.as_mut().unwrap().fill(source_protocol_addr.into(), - source_hardware_addr, - timestamp); + self.neighbor_cache.as_mut().unwrap().fill( + source_protocol_addr.into(), + source_hardware_addr, + timestamp, + ); } else { // Discard packets with non-unicast source addresses. net_debug!("non-unicast source address"); - return Err(Error::Malformed) + return Err(Error::Malformed); } if operation == ArpOperation::Request && self.has_ip_addr(target_protocol_addr) { @@ -960,7 +1058,7 @@ impl<'a> InterfaceInner<'a> { source_hardware_addr: self.ethernet_addr.unwrap(), source_protocol_addr: target_protocol_addr, target_hardware_addr: source_hardware_addr, - target_protocol_addr: source_protocol_addr + target_protocol_addr: source_protocol_addr, }))) } else { Ok(None) @@ -969,14 +1067,24 @@ impl<'a> InterfaceInner<'a> { } } - #[cfg(all(any(feature = "proto-ipv4", feature = "proto-ipv6"), feature = "socket-raw"))] - fn raw_socket_filter<'frame>(&mut self, cx: &Context, sockets: &mut SocketSet, ip_repr: &IpRepr, - ip_payload: &'frame [u8]) -> bool { + #[cfg(all( + any(feature = "proto-ipv4", feature = "proto-ipv6"), + feature = "socket-raw" + ))] + fn raw_socket_filter<'frame>( + &mut self, + cx: &Context, + sockets: &mut SocketSet, + ip_repr: &IpRepr, + ip_payload: &'frame [u8], + ) -> bool { let mut handled_by_raw_socket = false; // Pass every IP packet to all raw sockets we have registered. for mut raw_socket in sockets.iter_mut().filter_map(RawSocket::downcast) { - if !raw_socket.accepts(&ip_repr) { continue } + if !raw_socket.accepts(&ip_repr) { + continue; + } match raw_socket.process(cx, &ip_repr, ip_payload) { // The packet is valid and handled by socket. @@ -991,84 +1099,101 @@ impl<'a> InterfaceInner<'a> { } #[cfg(feature = "proto-ipv6")] - fn process_ipv6<'frame, T: AsRef<[u8]> + ?Sized> - (&mut self, cx: &Context, sockets: &mut SocketSet, - ipv6_packet: &Ipv6Packet<&'frame T>) -> - Result>> { + fn process_ipv6<'frame, T: AsRef<[u8]> + ?Sized>( + &mut self, + cx: &Context, + sockets: &mut SocketSet, + ipv6_packet: &Ipv6Packet<&'frame T>, + ) -> Result>> { let ipv6_repr = Ipv6Repr::parse(&ipv6_packet)?; if !ipv6_repr.src_addr.is_unicast() { // Discard packets with non-unicast source addresses. net_debug!("non-unicast source address"); - return Err(Error::Malformed) + return Err(Error::Malformed); } let ip_payload = ipv6_packet.payload(); #[cfg(feature = "socket-raw")] - let handled_by_raw_socket = self.raw_socket_filter(cx, sockets, &ipv6_repr.into(), ip_payload); + let handled_by_raw_socket = + self.raw_socket_filter(cx, sockets, &ipv6_repr.into(), ip_payload); #[cfg(not(feature = "socket-raw"))] let handled_by_raw_socket = false; - self.process_nxt_hdr(cx, sockets, ipv6_repr, ipv6_repr.next_header, - handled_by_raw_socket, ip_payload) + self.process_nxt_hdr( + cx, + sockets, + ipv6_repr, + ipv6_repr.next_header, + handled_by_raw_socket, + ip_payload, + ) } /// Given the next header value forward the payload onto the correct process /// function. #[cfg(feature = "proto-ipv6")] - fn process_nxt_hdr<'frame> - (&mut self, cx: &Context, sockets: &mut SocketSet, ipv6_repr: Ipv6Repr, - nxt_hdr: IpProtocol, handled_by_raw_socket: bool, ip_payload: &'frame [u8]) - -> Result>> - { + fn process_nxt_hdr<'frame>( + &mut self, + cx: &Context, + sockets: &mut SocketSet, + ipv6_repr: Ipv6Repr, + nxt_hdr: IpProtocol, + handled_by_raw_socket: bool, + ip_payload: &'frame [u8], + ) -> Result>> { match nxt_hdr { - IpProtocol::Icmpv6 => - self.process_icmpv6(cx, sockets, ipv6_repr.into(), ip_payload), + IpProtocol::Icmpv6 => self.process_icmpv6(cx, sockets, ipv6_repr.into(), ip_payload), #[cfg(feature = "socket-udp")] - IpProtocol::Udp => - self.process_udp(cx, sockets, ipv6_repr.into(), handled_by_raw_socket, ip_payload), + IpProtocol::Udp => self.process_udp( + cx, + sockets, + ipv6_repr.into(), + handled_by_raw_socket, + ip_payload, + ), #[cfg(feature = "socket-tcp")] - IpProtocol::Tcp => - self.process_tcp(cx, sockets, ipv6_repr.into(), ip_payload), + IpProtocol::Tcp => self.process_tcp(cx, sockets, ipv6_repr.into(), ip_payload), - IpProtocol::HopByHop => - self.process_hopbyhop(cx, sockets, ipv6_repr, handled_by_raw_socket, ip_payload), + IpProtocol::HopByHop => { + self.process_hopbyhop(cx, sockets, ipv6_repr, handled_by_raw_socket, ip_payload) + } #[cfg(feature = "socket-raw")] - _ if handled_by_raw_socket => - Ok(None), + _ if handled_by_raw_socket => Ok(None), _ => { // Send back as much of the original payload as we can. - let payload_len = icmp_reply_payload_len(ip_payload.len(), IPV6_MIN_MTU, - ipv6_repr.buffer_len()); + let payload_len = + icmp_reply_payload_len(ip_payload.len(), IPV6_MIN_MTU, ipv6_repr.buffer_len()); let icmp_reply_repr = Icmpv6Repr::ParamProblem { reason: Icmpv6ParamProblem::UnrecognizedNxtHdr, // The offending packet is after the IPv6 header. pointer: ipv6_repr.buffer_len() as u32, header: ipv6_repr, - data: &ip_payload[0..payload_len] + data: &ip_payload[0..payload_len], }; Ok(self.icmpv6_reply(ipv6_repr, icmp_reply_repr)) - }, + } } } #[cfg(feature = "proto-ipv4")] - fn process_ipv4<'frame, T: AsRef<[u8]> + ?Sized> - (&mut self, cx: &Context, sockets: &mut SocketSet, - ipv4_packet: &Ipv4Packet<&'frame T>) -> - Result>> - { + fn process_ipv4<'frame, T: AsRef<[u8]> + ?Sized>( + &mut self, + cx: &Context, + sockets: &mut SocketSet, + ipv4_packet: &Ipv4Packet<&'frame T>, + ) -> Result>> { let ipv4_repr = Ipv4Repr::parse(&ipv4_packet, &cx.caps.checksum)?; if !self.is_unicast_v4(ipv4_repr.src_addr) { // Discard packets with non-unicast source addresses. net_debug!("non-unicast source address"); - return Err(Error::Malformed) + return Err(Error::Malformed); } let ip_repr = IpRepr::Ipv4(ipv4_repr); @@ -1079,70 +1204,74 @@ impl<'a> InterfaceInner<'a> { #[cfg(not(feature = "socket-raw"))] let handled_by_raw_socket = false; - #[cfg(feature = "socket-dhcpv4")] { if ipv4_repr.protocol == IpProtocol::Udp && self.ethernet_addr.is_some() { // First check for source and dest ports, then do `UdpRepr::parse` if they match. // This way we avoid validating the UDP checksum twice for all non-DHCP UDP packets (one here, one in `process_udp`) let udp_packet = UdpPacket::new_checked(ip_payload)?; - if udp_packet.src_port() == DHCP_SERVER_PORT && udp_packet.dst_port() == DHCP_CLIENT_PORT { - if let Some(mut dhcp_socket) = sockets.iter_mut().filter_map(Dhcpv4Socket::downcast).next() { + if udp_packet.src_port() == DHCP_SERVER_PORT + && udp_packet.dst_port() == DHCP_CLIENT_PORT + { + if let Some(mut dhcp_socket) = + sockets.iter_mut().filter_map(Dhcpv4Socket::downcast).next() + { let (src_addr, dst_addr) = (ip_repr.src_addr(), ip_repr.dst_addr()); - let udp_repr = UdpRepr::parse(&udp_packet, &src_addr, &dst_addr, &cx.caps.checksum)?; + let udp_repr = + UdpRepr::parse(&udp_packet, &src_addr, &dst_addr, &cx.caps.checksum)?; let udp_payload = udp_packet.payload(); match dhcp_socket.process(cx, &ipv4_repr, &udp_repr, udp_payload) { // The packet is valid and handled by socket. Ok(()) => return Ok(None), // The packet is malformed, or the socket buffer is full. - Err(e) => return Err(e) + Err(e) => return Err(e), } } } } } - if !self.has_ip_addr(ipv4_repr.dst_addr) && - !self.has_multicast_group(ipv4_repr.dst_addr) && - !self.is_broadcast_v4(ipv4_repr.dst_addr) { - + if !self.has_ip_addr(ipv4_repr.dst_addr) + && !self.has_multicast_group(ipv4_repr.dst_addr) + && !self.is_broadcast_v4(ipv4_repr.dst_addr) + { // 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 || - self.routes.lookup(&IpAddress::Ipv4(ipv4_repr.dst_addr), cx.now) - .map_or(true, |router_addr| !self.has_ip_addr(router_addr)) { + if !self.any_ip + || self + .routes + .lookup(&IpAddress::Ipv4(ipv4_repr.dst_addr), cx.now) + .map_or(true, |router_addr| !self.has_ip_addr(router_addr)) + { return Ok(None); } } match ipv4_repr.protocol { - IpProtocol::Icmp => - self.process_icmpv4(cx, sockets, ip_repr, ip_payload), + IpProtocol::Icmp => self.process_icmpv4(cx, sockets, ip_repr, ip_payload), #[cfg(feature = "proto-igmp")] - IpProtocol::Igmp => - self.process_igmp(cx, ipv4_repr, ip_payload), + IpProtocol::Igmp => self.process_igmp(cx, ipv4_repr, ip_payload), #[cfg(feature = "socket-udp")] - IpProtocol::Udp => - self.process_udp(cx, sockets, ip_repr, handled_by_raw_socket, ip_payload), + IpProtocol::Udp => { + self.process_udp(cx, sockets, ip_repr, handled_by_raw_socket, ip_payload) + } #[cfg(feature = "socket-tcp")] - IpProtocol::Tcp => - self.process_tcp(cx, sockets, ip_repr, ip_payload), + IpProtocol::Tcp => self.process_tcp(cx, sockets, ip_repr, ip_payload), - _ if handled_by_raw_socket => - Ok(None), + _ if handled_by_raw_socket => Ok(None), _ => { // Send back as much of the original payload as we can. - let payload_len = icmp_reply_payload_len(ip_payload.len(), IPV4_MIN_MTU, - ipv4_repr.buffer_len()); + let payload_len = + icmp_reply_payload_len(ip_payload.len(), IPV4_MIN_MTU, ipv4_repr.buffer_len()); let icmp_reply_repr = Icmpv4Repr::DstUnreachable { reason: Icmpv4DstUnreachable::ProtoUnreachable, header: ipv4_repr, - data: &ip_payload[0..payload_len] + data: &ip_payload[0..payload_len], }; Ok(self.icmpv4_reply(ipv4_repr, icmp_reply_repr)) } @@ -1153,15 +1282,16 @@ impl<'a> InterfaceInner<'a> { /// associated ipv4 addresses. #[cfg(feature = "proto-ipv4")] fn is_subnet_broadcast(&self, address: Ipv4Address) -> bool { - self.ip_addrs.iter() + self.ip_addrs + .iter() .filter_map(|own_cidr| match own_cidr { IpCidr::Ipv4(own_ip) => Some(own_ip.broadcast()?), #[cfg(feature = "proto-ipv6")] - IpCidr::Ipv6(_) => None + IpCidr::Ipv6(_) => None, }) .any(|broadcast_address| address == broadcast_address) - } - + } + /// Checks if an ipv4 address is broadcast, taking into account subnet broadcast addresses #[cfg(feature = "proto-ipv4")] fn is_broadcast_v4(&self, address: Ipv4Address) -> bool { @@ -1180,22 +1310,30 @@ impl<'a> InterfaceInner<'a> { /// Membership must not be reported immediately in order to avoid flooding the network /// after a query is broadcasted by a router; this is not currently done. #[cfg(feature = "proto-igmp")] - fn process_igmp<'frame>(&mut self, cx: &Context, ipv4_repr: Ipv4Repr, - ip_payload: &'frame [u8]) -> Result>> { + fn process_igmp<'frame>( + &mut self, + cx: &Context, + ipv4_repr: Ipv4Repr, + ip_payload: &'frame [u8], + ) -> Result>> { let igmp_packet = IgmpPacket::new_checked(ip_payload)?; let igmp_repr = IgmpRepr::parse(&igmp_packet)?; // FIXME: report membership after a delay match igmp_repr { - IgmpRepr::MembershipQuery { group_addr, version, max_resp_time } => { + IgmpRepr::MembershipQuery { + group_addr, + version, + 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 == Ipv4Address::MULTICAST_ALL_SYSTEMS + { // Are we member in any groups? if self.ipv4_multicast_groups.iter().next().is_some() { let interval = match version { - IgmpVersion::Version1 => - Duration::from_millis(100), + IgmpVersion::Version1 => Duration::from_millis(100), IgmpVersion::Version2 => { // No dependence on a random generator // (see [#24](https://github.com/m-labs/smoltcp/issues/24)) @@ -1205,7 +1343,10 @@ impl<'a> InterfaceInner<'a> { } }; self.igmp_report_state = IgmpReportState::ToGeneralQuery { - version, timeout: cx.now + interval, interval, next_index: 0 + version, + timeout: cx.now + interval, + interval, + next_index: 0, }; } } else { @@ -1214,34 +1355,46 @@ impl<'a> InterfaceInner<'a> { // Don't respond immediately let timeout = max_resp_time / 4; self.igmp_report_state = IgmpReportState::ToSpecificQuery { - version, timeout: cx.now + timeout, group: group_addr + version, + timeout: cx.now + timeout, + group: group_addr, }; } } - }, + } // Ignore membership reports IgmpRepr::MembershipReport { .. } => (), // Ignore hosts leaving groups - IgmpRepr::LeaveGroup{ .. } => (), + IgmpRepr::LeaveGroup { .. } => (), } Ok(None) } #[cfg(feature = "proto-ipv6")] - fn process_icmpv6<'frame>(&mut self, cx: &Context, _sockets: &mut SocketSet, - ip_repr: IpRepr, ip_payload: &'frame [u8]) -> Result>> - { + fn process_icmpv6<'frame>( + &mut self, + cx: &Context, + _sockets: &mut SocketSet, + ip_repr: IpRepr, + ip_payload: &'frame [u8], + ) -> Result>> { let icmp_packet = Icmpv6Packet::new_checked(ip_payload)?; - let icmp_repr = Icmpv6Repr::parse(&ip_repr.src_addr(), &ip_repr.dst_addr(), - &icmp_packet, &cx.caps.checksum)?; + let icmp_repr = Icmpv6Repr::parse( + &ip_repr.src_addr(), + &ip_repr.dst_addr(), + &icmp_packet, + &cx.caps.checksum, + )?; #[cfg(feature = "socket-icmp")] let mut handled_by_icmp_socket = false; #[cfg(all(feature = "socket-icmp", feature = "proto-ipv6"))] for mut icmp_socket in _sockets.iter_mut().filter_map(IcmpSocket::downcast) { - if !icmp_socket.accepts(cx, &ip_repr, &icmp_repr.into()) { continue } + if !icmp_socket.accepts(cx, &ip_repr, &icmp_repr.into()) { + continue; + } match icmp_socket.process(cx, &ip_repr, &icmp_repr.into()) { // The packet is valid and handled by socket. @@ -1255,15 +1408,21 @@ impl<'a> InterfaceInner<'a> { match icmp_repr { // Respond to echo requests. - Icmpv6Repr::EchoRequest { ident, seq_no, data } => { - match ip_repr { - IpRepr::Ipv6(ipv6_repr) => { - let icmp_reply_repr = Icmpv6Repr::EchoReply { ident, seq_no, data }; - Ok(self.icmpv6_reply(ipv6_repr, icmp_reply_repr)) - }, - _ => Err(Error::Unrecognized), + Icmpv6Repr::EchoRequest { + ident, + seq_no, + data, + } => match ip_repr { + IpRepr::Ipv6(ipv6_repr) => { + let icmp_reply_repr = Icmpv6Repr::EchoReply { + ident, + seq_no, + data, + }; + Ok(self.icmpv6_reply(ipv6_repr, icmp_reply_repr)) } - } + _ => Err(Error::Unrecognized), + }, // Ignore any echo replies. Icmpv6Repr::EchoReply { .. } => Ok(None), @@ -1272,7 +1431,7 @@ impl<'a> InterfaceInner<'a> { #[cfg(feature = "medium-ethernet")] Icmpv6Repr::Ndisc(repr) if ip_repr.hop_limit() == 0xff => match ip_repr { IpRepr::Ipv6(ipv6_repr) => self.process_ndisc(cx.now, ipv6_repr, repr), - _ => Ok(None) + _ => Ok(None), }, // Don't report an error if a packet with unknown type @@ -1286,56 +1445,83 @@ impl<'a> InterfaceInner<'a> { } #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv6"))] - fn process_ndisc<'frame>(&mut self, timestamp: Instant, ip_repr: Ipv6Repr, - repr: NdiscRepr<'frame>) -> Result>> { + fn process_ndisc<'frame>( + &mut self, + timestamp: Instant, + ip_repr: Ipv6Repr, + repr: NdiscRepr<'frame>, + ) -> Result>> { match repr { - NdiscRepr::NeighborAdvert { lladdr, target_addr, flags } => { + NdiscRepr::NeighborAdvert { + lladdr, + target_addr, + flags, + } => { let ip_addr = ip_repr.src_addr.into(); match lladdr { Some(lladdr) if lladdr.is_unicast() && target_addr.is_unicast() => { - if flags.contains(NdiscNeighborFlags::OVERRIDE) || - !self.neighbor_cache.as_mut().unwrap().lookup(&ip_addr, timestamp).found() { - self.neighbor_cache.as_mut().unwrap().fill(ip_addr, lladdr, timestamp) + if flags.contains(NdiscNeighborFlags::OVERRIDE) + || !self + .neighbor_cache + .as_mut() + .unwrap() + .lookup(&ip_addr, timestamp) + .found() + { + self.neighbor_cache + .as_mut() + .unwrap() + .fill(ip_addr, lladdr, timestamp) } - }, + } _ => (), } Ok(None) } - NdiscRepr::NeighborSolicit { target_addr, lladdr, .. } => { + NdiscRepr::NeighborSolicit { + target_addr, + lladdr, + .. + } => { match lladdr { - Some(lladdr) if lladdr.is_unicast() && target_addr.is_unicast() => { - self.neighbor_cache.as_mut().unwrap().fill(ip_repr.src_addr.into(), lladdr, timestamp) - }, + Some(lladdr) if lladdr.is_unicast() && target_addr.is_unicast() => self + .neighbor_cache + .as_mut() + .unwrap() + .fill(ip_repr.src_addr.into(), lladdr, timestamp), _ => (), } if self.has_solicited_node(ip_repr.dst_addr) && self.has_ip_addr(target_addr) { let advert = Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert { flags: NdiscNeighborFlags::SOLICITED, target_addr: target_addr, - lladdr: Some(self.ethernet_addr.unwrap()) + lladdr: Some(self.ethernet_addr.unwrap()), }); let ip_repr = Ipv6Repr { src_addr: target_addr, dst_addr: ip_repr.src_addr, next_header: IpProtocol::Icmpv6, hop_limit: 0xff, - payload_len: advert.buffer_len() + payload_len: advert.buffer_len(), }; Ok(Some(IpPacket::Icmpv6((ip_repr, advert)))) } else { Ok(None) } } - _ => Ok(None) + _ => Ok(None), } } #[cfg(feature = "proto-ipv6")] - fn process_hopbyhop<'frame>(&mut self, cx: &Context, sockets: &mut SocketSet, - ipv6_repr: Ipv6Repr, handled_by_raw_socket: bool, - ip_payload: &'frame [u8]) -> Result>> - { + fn process_hopbyhop<'frame>( + &mut self, + cx: &Context, + sockets: &mut SocketSet, + ipv6_repr: Ipv6Repr, + handled_by_raw_socket: bool, + ip_payload: &'frame [u8], + ) -> Result>> { let hbh_pkt = Ipv6HopByHopHeader::new_checked(ip_payload)?; let hbh_repr = Ipv6HopByHopRepr::parse(&hbh_pkt)?; for result in hbh_repr.options() { @@ -1347,7 +1533,7 @@ impl<'a> InterfaceInner<'a> { Ipv6OptionFailureType::Skip => (), Ipv6OptionFailureType::Discard => { return Ok(None); - }, + } _ => { // FIXME(dlrobertson): Send an ICMPv6 parameter problem message // here. @@ -1357,14 +1543,24 @@ impl<'a> InterfaceInner<'a> { } } } - self.process_nxt_hdr(cx, sockets, ipv6_repr, hbh_repr.next_header, - handled_by_raw_socket, &ip_payload[hbh_repr.buffer_len()..]) + self.process_nxt_hdr( + cx, + sockets, + ipv6_repr, + hbh_repr.next_header, + handled_by_raw_socket, + &ip_payload[hbh_repr.buffer_len()..], + ) } #[cfg(feature = "proto-ipv4")] - fn process_icmpv4<'frame>(&self, cx: &Context, _sockets: &mut SocketSet, ip_repr: IpRepr, - ip_payload: &'frame [u8]) -> Result>> - { + fn process_icmpv4<'frame>( + &self, + cx: &Context, + _sockets: &mut SocketSet, + ip_repr: IpRepr, + ip_payload: &'frame [u8], + ) -> Result>> { let icmp_packet = Icmpv4Packet::new_checked(ip_payload)?; let icmp_repr = Icmpv4Repr::parse(&icmp_packet, &cx.caps.checksum)?; @@ -1373,7 +1569,9 @@ impl<'a> InterfaceInner<'a> { #[cfg(all(feature = "socket-icmp", feature = "proto-ipv4"))] for mut icmp_socket in _sockets.iter_mut().filter_map(IcmpSocket::downcast) { - if !icmp_socket.accepts(cx, &ip_repr, &icmp_repr.into()) { continue } + if !icmp_socket.accepts(cx, &ip_repr, &icmp_repr.into()) { + continue; + } match icmp_socket.process(cx, &ip_repr, &icmp_repr.into()) { // The packet is valid and handled by socket. @@ -1388,13 +1586,21 @@ impl<'a> InterfaceInner<'a> { match icmp_repr { // Respond to echo requests. #[cfg(feature = "proto-ipv4")] - Icmpv4Repr::EchoRequest { ident, seq_no, data } => { - let icmp_reply_repr = Icmpv4Repr::EchoReply { ident, seq_no, data }; + Icmpv4Repr::EchoRequest { + ident, + seq_no, + data, + } => { + let icmp_reply_repr = Icmpv4Repr::EchoReply { + ident, + seq_no, + data, + }; match ip_repr { IpRepr::Ipv4(ipv4_repr) => Ok(self.icmpv4_reply(ipv4_repr, icmp_reply_repr)), _ => Err(Error::Unrecognized), } - }, + } // Ignore any echo replies. Icmpv4Repr::EchoReply { .. } => Ok(None), @@ -1410,37 +1616,38 @@ impl<'a> InterfaceInner<'a> { } #[cfg(feature = "proto-ipv4")] - fn icmpv4_reply<'frame, 'icmp: 'frame> - (&self, ipv4_repr: Ipv4Repr, icmp_repr: Icmpv4Repr<'icmp>) -> - Option> - { + fn icmpv4_reply<'frame, 'icmp: 'frame>( + &self, + ipv4_repr: Ipv4Repr, + icmp_repr: Icmpv4Repr<'icmp>, + ) -> Option> { if !self.is_unicast_v4(ipv4_repr.src_addr) { // Do not send ICMP replies to non-unicast sources None } else if self.is_unicast_v4(ipv4_repr.dst_addr) { // Reply as normal when src_addr and dst_addr are both unicast let ipv4_reply_repr = Ipv4Repr { - src_addr: ipv4_repr.dst_addr, - dst_addr: ipv4_repr.src_addr, - protocol: IpProtocol::Icmp, + src_addr: ipv4_repr.dst_addr, + dst_addr: ipv4_repr.src_addr, + protocol: IpProtocol::Icmp, payload_len: icmp_repr.buffer_len(), - hop_limit: 64 + hop_limit: 64, }; Some(IpPacket::Icmpv4((ipv4_reply_repr, icmp_repr))) } else if self.is_broadcast_v4(ipv4_repr.dst_addr) { // Only reply to broadcasts for echo replies and not other ICMP messages match icmp_repr { - Icmpv4Repr::EchoReply {..} => match self.ipv4_address() { + Icmpv4Repr::EchoReply { .. } => match self.ipv4_address() { Some(src_addr) => { let ipv4_reply_repr = Ipv4Repr { - src_addr: src_addr, - dst_addr: ipv4_repr.src_addr, - protocol: IpProtocol::Icmp, + src_addr: src_addr, + dst_addr: ipv4_repr.src_addr, + protocol: IpProtocol::Icmp, payload_len: icmp_repr.buffer_len(), - hop_limit: 64 + hop_limit: 64, }; Some(IpPacket::Icmpv4((ipv4_reply_repr, icmp_repr))) - }, + } None => None, }, _ => None, @@ -1451,17 +1658,18 @@ impl<'a> InterfaceInner<'a> { } #[cfg(feature = "proto-ipv6")] - fn icmpv6_reply<'frame, 'icmp: 'frame> - (&self, ipv6_repr: Ipv6Repr, icmp_repr: Icmpv6Repr<'icmp>) -> - Option> - { + fn icmpv6_reply<'frame, 'icmp: 'frame>( + &self, + ipv6_repr: Ipv6Repr, + icmp_repr: Icmpv6Repr<'icmp>, + ) -> Option> { if ipv6_repr.dst_addr.is_unicast() { let ipv6_reply_repr = Ipv6Repr { - src_addr: ipv6_repr.dst_addr, - dst_addr: ipv6_repr.src_addr, + src_addr: ipv6_repr.dst_addr, + dst_addr: ipv6_repr.src_addr, next_header: IpProtocol::Icmpv6, payload_len: icmp_repr.buffer_len(), - hop_limit: 64 + hop_limit: 64, }; Some(IpPacket::Icmpv6((ipv6_reply_repr, icmp_repr))) } else { @@ -1471,78 +1679,87 @@ impl<'a> InterfaceInner<'a> { } #[cfg(feature = "socket-udp")] - fn process_udp<'frame>(&self, cx: &Context, sockets: &mut SocketSet, - ip_repr: IpRepr, handled_by_raw_socket: bool, ip_payload: &'frame [u8]) -> - Result>> - { + fn process_udp<'frame>( + &self, + cx: &Context, + sockets: &mut SocketSet, + ip_repr: IpRepr, + handled_by_raw_socket: bool, + ip_payload: &'frame [u8], + ) -> Result>> { let (src_addr, dst_addr) = (ip_repr.src_addr(), ip_repr.dst_addr()); let udp_packet = UdpPacket::new_checked(ip_payload)?; let udp_repr = UdpRepr::parse(&udp_packet, &src_addr, &dst_addr, &cx.caps.checksum)?; let udp_payload = udp_packet.payload(); for mut udp_socket in sockets.iter_mut().filter_map(UdpSocket::downcast) { - if !udp_socket.accepts(&ip_repr, &udp_repr) { continue } + if !udp_socket.accepts(&ip_repr, &udp_repr) { + continue; + } match udp_socket.process(cx, &ip_repr, &udp_repr, udp_payload) { // The packet is valid and handled by socket. Ok(()) => return Ok(None), // The packet is malformed, or the socket buffer is full. - Err(e) => return Err(e) + Err(e) => return Err(e), } } // The packet wasn't handled by a socket, send an ICMP port unreachable packet. match ip_repr { #[cfg(feature = "proto-ipv4")] - IpRepr::Ipv4(_) if handled_by_raw_socket => - Ok(None), + IpRepr::Ipv4(_) if handled_by_raw_socket => Ok(None), #[cfg(feature = "proto-ipv6")] - IpRepr::Ipv6(_) if handled_by_raw_socket => - Ok(None), + IpRepr::Ipv6(_) if handled_by_raw_socket => Ok(None), #[cfg(feature = "proto-ipv4")] IpRepr::Ipv4(ipv4_repr) => { - let payload_len = icmp_reply_payload_len(ip_payload.len(), IPV4_MIN_MTU, - ipv4_repr.buffer_len()); + let payload_len = + icmp_reply_payload_len(ip_payload.len(), IPV4_MIN_MTU, ipv4_repr.buffer_len()); let icmpv4_reply_repr = Icmpv4Repr::DstUnreachable { reason: Icmpv4DstUnreachable::PortUnreachable, header: ipv4_repr, - data: &ip_payload[0..payload_len] + data: &ip_payload[0..payload_len], }; Ok(self.icmpv4_reply(ipv4_repr, icmpv4_reply_repr)) - }, + } #[cfg(feature = "proto-ipv6")] IpRepr::Ipv6(ipv6_repr) => { - let payload_len = icmp_reply_payload_len(ip_payload.len(), IPV6_MIN_MTU, - ipv6_repr.buffer_len()); + let payload_len = + icmp_reply_payload_len(ip_payload.len(), IPV6_MIN_MTU, ipv6_repr.buffer_len()); let icmpv6_reply_repr = Icmpv6Repr::DstUnreachable { reason: Icmpv6DstUnreachable::PortUnreachable, header: ipv6_repr, - data: &ip_payload[0..payload_len] + data: &ip_payload[0..payload_len], }; Ok(self.icmpv6_reply(ipv6_repr, icmpv6_reply_repr)) - }, + } IpRepr::Unspecified { .. } => Err(Error::Unaddressable), } } #[cfg(feature = "socket-tcp")] - fn process_tcp<'frame>(&self, cx: &Context, sockets: &mut SocketSet, - ip_repr: IpRepr, ip_payload: &'frame [u8]) -> - Result>> - { + fn process_tcp<'frame>( + &self, + cx: &Context, + sockets: &mut SocketSet, + ip_repr: IpRepr, + ip_payload: &'frame [u8], + ) -> Result>> { let (src_addr, dst_addr) = (ip_repr.src_addr(), ip_repr.dst_addr()); let tcp_packet = TcpPacket::new_checked(ip_payload)?; let tcp_repr = TcpRepr::parse(&tcp_packet, &src_addr, &dst_addr, &cx.caps.checksum)?; for mut tcp_socket in sockets.iter_mut().filter_map(TcpSocket::downcast) { - if !tcp_socket.accepts(&ip_repr, &tcp_repr) { continue } + if !tcp_socket.accepts(&ip_repr, &tcp_repr) { + continue; + } match tcp_socket.process(cx, &ip_repr, &tcp_repr) { // The packet is valid and handled by socket. Ok(reply) => return Ok(reply.map(IpPacket::Tcp)), // The packet is malformed, or doesn't match the socket state, // or the socket buffer is full. - Err(e) => return Err(e) + Err(e) => return Err(e), } } @@ -1551,22 +1768,26 @@ impl<'a> InterfaceInner<'a> { Ok(None) } else { // The packet wasn't handled by a socket, send a TCP RST packet. - Ok(Some(IpPacket::Tcp(TcpSocket::rst_reply(&ip_repr, &tcp_repr)))) + Ok(Some(IpPacket::Tcp(TcpSocket::rst_reply( + &ip_repr, &tcp_repr, + )))) } } #[cfg(feature = "medium-ethernet")] - fn dispatch(&mut self, cx: &Context, tx_token: Tx, - packet: EthernetPacket) -> Result<()> - where Tx: TxToken + fn dispatch(&mut self, cx: &Context, tx_token: Tx, packet: EthernetPacket) -> Result<()> + where + Tx: TxToken, { match packet { #[cfg(feature = "proto-ipv4")] EthernetPacket::Arp(arp_repr) => { - let dst_hardware_addr = - match arp_repr { - ArpRepr::EthernetIpv4 { target_hardware_addr, .. } => target_hardware_addr, - }; + let dst_hardware_addr = match arp_repr { + ArpRepr::EthernetIpv4 { + target_hardware_addr, + .. + } => target_hardware_addr, + }; self.dispatch_ethernet(cx, tx_token, arp_repr.buffer_len(), |mut frame| { frame.set_dst_addr(dst_hardware_addr); @@ -1575,17 +1796,22 @@ impl<'a> InterfaceInner<'a> { let mut packet = ArpPacket::new_unchecked(frame.payload_mut()); arp_repr.emit(&mut packet); }) - }, - EthernetPacket::Ip(packet) => { - self.dispatch_ip(cx, tx_token, packet) - }, + } + EthernetPacket::Ip(packet) => self.dispatch_ip(cx, tx_token, packet), } } #[cfg(feature = "medium-ethernet")] - fn dispatch_ethernet(&mut self, cx: &Context, tx_token: Tx, - buffer_len: usize, f: F) -> Result<()> - where Tx: TxToken, F: FnOnce(EthernetFrame<&mut [u8]>) + fn dispatch_ethernet( + &mut self, + cx: &Context, + tx_token: Tx, + buffer_len: usize, + f: F, + ) -> Result<()> + where + Tx: TxToken, + F: FnOnce(EthernetFrame<&mut [u8]>), { let tx_len = EthernetFrame::<&[u8]>::buffer_len(buffer_len); tx_token.consume(cx.now, tx_len, |tx_buffer| { @@ -1600,15 +1826,13 @@ impl<'a> InterfaceInner<'a> { } fn in_same_network(&self, addr: &IpAddress) -> bool { - self.ip_addrs - .iter() - .any(|cidr| cidr.contains_addr(addr)) + self.ip_addrs.iter().any(|cidr| cidr.contains_addr(addr)) } fn route(&self, addr: &IpAddress, timestamp: Instant) -> Result { // Send directly. if self.in_same_network(addr) || addr.is_broadcast() { - return Ok(*addr) + return Ok(*addr); } // Route via a router. @@ -1620,67 +1844,75 @@ impl<'a> InterfaceInner<'a> { fn has_neighbor(&self, cx: &Context, addr: &IpAddress) -> bool { match self.route(addr, cx.now) { - Ok(_routed_addr) => { - match cx.caps.medium { - #[cfg(feature = "medium-ethernet")] - Medium::Ethernet => self.neighbor_cache.as_ref().unwrap() - .lookup(&_routed_addr, cx.now) - .found(), - #[cfg(feature = "medium-ip")] - Medium::Ip => true, - } - } - Err(_) => false + Ok(_routed_addr) => match cx.caps.medium { + #[cfg(feature = "medium-ethernet")] + Medium::Ethernet => self + .neighbor_cache + .as_ref() + .unwrap() + .lookup(&_routed_addr, cx.now) + .found(), + #[cfg(feature = "medium-ip")] + Medium::Ip => true, + }, + Err(_) => false, } } #[cfg(feature = "medium-ethernet")] - fn lookup_hardware_addr(&mut self, cx: &Context, tx_token: Tx, - src_addr: &IpAddress, dst_addr: &IpAddress) -> - Result<(EthernetAddress, Tx)> - where Tx: TxToken + fn lookup_hardware_addr( + &mut self, + cx: &Context, + tx_token: Tx, + src_addr: &IpAddress, + dst_addr: &IpAddress, + ) -> Result<(EthernetAddress, Tx)> + where + Tx: TxToken, { if dst_addr.is_multicast() { let b = dst_addr.as_bytes(); - let hardware_addr = - match *dst_addr { - IpAddress::Unspecified => - None, - #[cfg(feature = "proto-ipv4")] - IpAddress::Ipv4(_addr) => - Some(EthernetAddress::from_bytes(&[ - 0x01, 0x00, - 0x5e, b[1] & 0x7F, - b[2], b[3], - ])), - #[cfg(feature = "proto-ipv6")] - IpAddress::Ipv6(_addr) => - Some(EthernetAddress::from_bytes(&[ - 0x33, 0x33, - b[12], b[13], - b[14], b[15], - ])), - }; + let hardware_addr = match *dst_addr { + IpAddress::Unspecified => None, + #[cfg(feature = "proto-ipv4")] + IpAddress::Ipv4(_addr) => Some(EthernetAddress::from_bytes(&[ + 0x01, + 0x00, + 0x5e, + b[1] & 0x7F, + b[2], + b[3], + ])), + #[cfg(feature = "proto-ipv6")] + IpAddress::Ipv6(_addr) => Some(EthernetAddress::from_bytes(&[ + 0x33, 0x33, b[12], b[13], b[14], b[15], + ])), + }; if let Some(hardware_addr) = hardware_addr { - return Ok((hardware_addr, tx_token)) + return Ok((hardware_addr, tx_token)); } } let dst_addr = self.route(dst_addr, cx.now)?; - match self.neighbor_cache.as_mut().unwrap().lookup(&dst_addr, cx.now) { - NeighborAnswer::Found(hardware_addr) => - return Ok((hardware_addr, tx_token)), - NeighborAnswer::RateLimited => - return Err(Error::Unaddressable), + match self + .neighbor_cache + .as_mut() + .unwrap() + .lookup(&dst_addr, cx.now) + { + NeighborAnswer::Found(hardware_addr) => return Ok((hardware_addr, tx_token)), + NeighborAnswer::RateLimited => return Err(Error::Unaddressable), NeighborAnswer::NotFound => (), } match (src_addr, dst_addr) { #[cfg(feature = "proto-ipv4")] (&IpAddress::Ipv4(src_addr), IpAddress::Ipv4(dst_addr)) => { - net_debug!("address {} not in neighbor cache, sending ARP request", - dst_addr); + net_debug!( + "address {} not in neighbor cache, sending ARP request", + dst_addr + ); let arp_repr = ArpRepr::EthernetIpv4 { operation: ArpOperation::Request, @@ -1700,8 +1932,10 @@ impl<'a> InterfaceInner<'a> { #[cfg(feature = "proto-ipv6")] (&IpAddress::Ipv6(src_addr), IpAddress::Ipv6(dst_addr)) => { - net_debug!("address {} not in neighbor cache, sending Neighbor Solicitation", - dst_addr); + net_debug!( + "address {} not in neighbor cache, sending Neighbor Solicitation", + dst_addr + ); let solicit = Icmpv6Repr::Ndisc(NdiscRepr::NeighborSolicit { target_addr: dst_addr, @@ -1714,7 +1948,7 @@ impl<'a> InterfaceInner<'a> { dst_addr: dst_addr.solicited_node(), next_header: IpProtocol::Icmpv6, payload_len: solicit.buffer_len(), - hop_limit: 0xff + hop_limit: 0xff, }, solicit, )); @@ -1722,23 +1956,30 @@ impl<'a> InterfaceInner<'a> { self.dispatch_ip(cx, tx_token, packet)?; } - _ => () + _ => (), } // The request got dispatched, limit the rate on the cache. self.neighbor_cache.as_mut().unwrap().limit_rate(cx.now); Err(Error::Unaddressable) } - fn dispatch_ip(&mut self, cx: &Context, tx_token: Tx, - packet: IpPacket) -> Result<()> { + fn dispatch_ip( + &mut self, + cx: &Context, + tx_token: Tx, + packet: IpPacket, + ) -> Result<()> { let ip_repr = packet.ip_repr().lower(&self.ip_addrs)?; match cx.caps.medium { #[cfg(feature = "medium-ethernet")] Medium::Ethernet => { - let (dst_hardware_addr, tx_token) = - self.lookup_hardware_addr(cx, tx_token, - &ip_repr.src_addr(), &ip_repr.dst_addr())?; + let (dst_hardware_addr, tx_token) = self.lookup_hardware_addr( + cx, + tx_token, + &ip_repr.src_addr(), + &ip_repr.dst_addr(), + )?; self.dispatch_ethernet(cx, tx_token, ip_repr.total_len(), |mut frame| { frame.set_dst_addr(dst_hardware_addr); @@ -1747,7 +1988,7 @@ impl<'a> InterfaceInner<'a> { IpRepr::Ipv4(_) => frame.set_ethertype(EthernetProtocol::Ipv4), #[cfg(feature = "proto-ipv6")] IpRepr::Ipv6(_) => frame.set_ethertype(EthernetProtocol::Ipv6), - _ => return + _ => return, } ip_repr.emit(frame.payload_mut(), &cx.caps.checksum); @@ -1774,22 +2015,29 @@ impl<'a> InterfaceInner<'a> { } #[cfg(feature = "proto-igmp")] - fn igmp_report_packet<'any>(&self, version: IgmpVersion, group_addr: Ipv4Address) -> Option> { + fn igmp_report_packet<'any>( + &self, + version: IgmpVersion, + group_addr: Ipv4Address, + ) -> Option> { let iface_addr = self.ipv4_address()?; let igmp_repr = IgmpRepr::MembershipReport { group_addr, version, }; - let pkt = IpPacket::Igmp((Ipv4Repr { - src_addr: iface_addr, - // Send to the group being reported - dst_addr: group_addr, - protocol: IpProtocol::Igmp, - payload_len: igmp_repr.buffer_len(), - hop_limit: 1, - // TODO: add Router Alert IPv4 header option. See - // [#183](https://github.com/m-labs/smoltcp/issues/183). - }, igmp_repr)); + let pkt = IpPacket::Igmp(( + Ipv4Repr { + src_addr: iface_addr, + // Send to the group being reported + dst_addr: group_addr, + protocol: IpProtocol::Igmp, + payload_len: igmp_repr.buffer_len(), + hop_limit: 1, + // TODO: add Router Alert IPv4 header option. See + // [#183](https://github.com/m-labs/smoltcp/issues/183). + }, + igmp_repr, + )); Some(pkt) } @@ -1797,33 +2045,36 @@ impl<'a> InterfaceInner<'a> { fn igmp_leave_packet<'any>(&self, group_addr: Ipv4Address) -> Option> { self.ipv4_address().map(|iface_addr| { let igmp_repr = IgmpRepr::LeaveGroup { group_addr }; - IpPacket::Igmp((Ipv4Repr { - src_addr: iface_addr, - dst_addr: Ipv4Address::MULTICAST_ALL_ROUTERS, - protocol: IpProtocol::Igmp, - payload_len: igmp_repr.buffer_len(), - hop_limit: 1, - }, igmp_repr)) + IpPacket::Igmp(( + Ipv4Repr { + src_addr: iface_addr, + dst_addr: Ipv4Address::MULTICAST_ALL_ROUTERS, + protocol: IpProtocol::Igmp, + payload_len: igmp_repr.buffer_len(), + hop_limit: 1, + }, + igmp_repr, + )) }) } } #[cfg(test)] mod test { + use std::collections::BTreeMap; #[cfg(feature = "proto-igmp")] use std::vec::Vec; - use std::collections::BTreeMap; use super::*; - use crate::{Result, Error}; + use crate::iface::Interface; #[cfg(feature = "medium-ethernet")] use crate::iface::NeighborCache; - use crate::iface::Interface; + use crate::phy::{ChecksumCapabilities, Loopback}; + use crate::socket::SocketSet; #[cfg(feature = "proto-igmp")] use crate::time::Instant; - use crate::socket::SocketSet; - use crate::phy::{Loopback, ChecksumCapabilities}; + use crate::{Error, Result}; #[allow(unused)] fn fill_slice(s: &mut [u8], val: u8) { @@ -1853,13 +2104,10 @@ mod test { IpCidr::new(IpAddress::v6(0xfdbe, 0, 0, 0, 0, 0, 0, 1), 64), ]; - let iface_builder = InterfaceBuilder::new(device) - .ip_addrs(ip_addrs); + let iface_builder = InterfaceBuilder::new(device).ip_addrs(ip_addrs); #[cfg(feature = "proto-igmp")] - let iface_builder = iface_builder - .ipv4_multicast_groups(BTreeMap::new()); - let iface = iface_builder - .finalize(); + let iface_builder = iface_builder.ipv4_multicast_groups(BTreeMap::new()); + let iface = iface_builder.finalize(); (iface, SocketSet::new(vec![])) } @@ -1882,10 +2130,8 @@ mod test { .neighbor_cache(NeighborCache::new(BTreeMap::new())) .ip_addrs(ip_addrs); #[cfg(feature = "proto-igmp")] - let iface_builder = iface_builder - .ipv4_multicast_groups(BTreeMap::new()); - let iface = iface_builder - .finalize(); + let iface_builder = iface_builder.ipv4_multicast_groups(BTreeMap::new()); + let iface = iface_builder.finalize(); (iface, SocketSet::new(vec![])) } @@ -1897,7 +2143,8 @@ mod test { rx.consume(timestamp, |pkt| { pkts.push(pkt.to_vec()); Ok(()) - }).unwrap(); + }) + .unwrap(); } pkts } @@ -1908,7 +2155,9 @@ mod test { impl TxToken for MockTxToken { fn consume(self, _: Instant, _: usize, _: F) -> Result - where F: FnOnce(&mut [u8]) -> Result { + where + F: FnOnce(&mut [u8]) -> Result, + { Err(Error::Unaddressable) } } @@ -1931,11 +2180,11 @@ mod test { // 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]), - dst_addr: Ipv4Address::BROADCAST, - protocol: IpProtocol::Unknown(0x0c), + src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]), + dst_addr: Ipv4Address::BROADCAST, + protocol: IpProtocol::Unknown(0x0c), payload_len: 0, - hop_limit: 0x40 + hop_limit: 0x40, }); let mut bytes = vec![0u8; 54]; @@ -1946,8 +2195,10 @@ mod test { // ICMP error response when the destination address is a // broadcast address let cx = iface.context(Instant::from_secs(0)); - assert_eq!(iface.inner.process_ipv4(&cx, &mut socket_set, &frame), - Ok(None)); + assert_eq!( + iface.inner.process_ipv4(&cx, &mut socket_set, &frame), + Ok(None) + ); } #[test] @@ -1961,11 +2212,11 @@ mod test { // this should not trigger and Destination Unreachable // response. See RFC 1122 § 3.2.2. let repr = IpRepr::Ipv6(Ipv6Repr { - src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), - dst_addr: Ipv6Address::LINK_LOCAL_ALL_NODES, + src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), + dst_addr: Ipv6Address::LINK_LOCAL_ALL_NODES, next_header: IpProtocol::Unknown(0x0c), payload_len: 0, - hop_limit: 0x40 + hop_limit: 0x40, }); let mut bytes = vec![0u8; 54]; @@ -1976,8 +2227,10 @@ mod test { // ICMP error response when the destination address is a // broadcast address let cx = iface.context(Instant::from_secs(0)); - assert_eq!(iface.inner.process_ipv6(&cx, &mut socket_set, &frame), - Ok(None)); + assert_eq!( + iface.inner.process_ipv6(&cx, &mut socket_set, &frame), + Ok(None) + ); } #[test] @@ -1988,11 +2241,11 @@ mod test { // 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]), - protocol: IpProtocol::Unknown(0x0c), + src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]), + dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]), + protocol: IpProtocol::Unknown(0x0c), payload_len: 0, - hop_limit: 0x40 + hop_limit: 0x40, }); let mut bytes = vec![0u8; 34]; @@ -2008,9 +2261,9 @@ mod test { dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]), protocol: IpProtocol::Unknown(12), payload_len: 0, - hop_limit: 64 + hop_limit: 64, }, - data: &NO_BYTES + data: &NO_BYTES, }; let expected_repr = IpPacket::Icmpv4(( @@ -2019,16 +2272,18 @@ mod test { dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]), protocol: IpProtocol::Icmp, payload_len: icmp_repr.buffer_len(), - hop_limit: 64 + hop_limit: 64, }, - icmp_repr + icmp_repr, )); // Ensure that the unknown protocol triggers an error response. // And we correctly handle no payload. let cx = iface.context(Instant::from_secs(0)); - assert_eq!(iface.inner.process_ipv4(&cx, &mut socket_set, &frame), - Ok(Some(expected_repr))); + assert_eq!( + iface.inner.process_ipv4(&cx, &mut socket_set, &frame), + Ok(Some(expected_repr)) + ); } #[test] @@ -2041,37 +2296,85 @@ mod test { }); }); - assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 168, 1, 255])), true); - assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 168, 1, 254])), false); + assert_eq!( + iface + .inner + .is_subnet_broadcast(Ipv4Address([192, 168, 1, 255])), + true + ); + assert_eq!( + iface + .inner + .is_subnet_broadcast(Ipv4Address([192, 168, 1, 254])), + false + ); iface.update_ip_addrs(|addrs| { addrs.iter_mut().next().map(|addr| { *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 23, 24]), 16)); }); }); - assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 168, 23, 255])), false); - assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 168, 23, 254])), false); - assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 168, 255, 254])), false); - assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 168, 255, 255])), true); + assert_eq!( + iface + .inner + .is_subnet_broadcast(Ipv4Address([192, 168, 23, 255])), + false + ); + assert_eq!( + iface + .inner + .is_subnet_broadcast(Ipv4Address([192, 168, 23, 254])), + false + ); + assert_eq!( + iface + .inner + .is_subnet_broadcast(Ipv4Address([192, 168, 255, 254])), + false + ); + assert_eq!( + iface + .inner + .is_subnet_broadcast(Ipv4Address([192, 168, 255, 255])), + true + ); iface.update_ip_addrs(|addrs| { addrs.iter_mut().next().map(|addr| { *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 23, 24]), 8)); }); }); - assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 23, 1, 255])), false); - assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 23, 1, 254])), false); - assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 255, 255, 254])), false); - assert_eq!(iface.inner.is_subnet_broadcast(Ipv4Address([192, 255, 255, 255])), true); + assert_eq!( + iface + .inner + .is_subnet_broadcast(Ipv4Address([192, 23, 1, 255])), + false + ); + assert_eq!( + iface + .inner + .is_subnet_broadcast(Ipv4Address([192, 23, 1, 254])), + false + ); + assert_eq!( + iface + .inner + .is_subnet_broadcast(Ipv4Address([192, 255, 255, 254])), + false + ); + assert_eq!( + iface + .inner + .is_subnet_broadcast(Ipv4Address([192, 255, 255, 255])), + true + ); } #[test] #[cfg(all(feature = "socket-udp", feature = "proto-ipv4"))] fn test_icmp_error_port_unreachable() { static UDP_PAYLOAD: [u8; 12] = [ - 0x48, 0x65, 0x6c, 0x6c, - 0x6f, 0x2c, 0x20, 0x57, - 0x6f, 0x6c, 0x64, 0x21 + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57, 0x6f, 0x6c, 0x64, 0x21, ]; let (iface, mut socket_set) = create_loopback(); @@ -2086,18 +2389,22 @@ mod test { }; let ip_repr = IpRepr::Ipv4(Ipv4Repr { - src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]), - dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]), - protocol: IpProtocol::Udp, + src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]), + dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]), + protocol: IpProtocol::Udp, payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(), - hop_limit: 64 + hop_limit: 64, }); // Emit the representations to a packet - udp_repr.emit(&mut packet_unicast, &ip_repr.src_addr(), - &ip_repr.dst_addr(), - UDP_PAYLOAD.len(), |buf| buf.copy_from_slice( &UDP_PAYLOAD), - &ChecksumCapabilities::default()); + udp_repr.emit( + &mut packet_unicast, + &ip_repr.src_addr(), + &ip_repr.dst_addr(), + UDP_PAYLOAD.len(), + |buf| buf.copy_from_slice(&UDP_PAYLOAD), + &ChecksumCapabilities::default(), + ); let data = packet_unicast.into_inner(); @@ -2110,9 +2417,9 @@ mod test { dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]), protocol: IpProtocol::Udp, payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(), - hop_limit: 64 + hop_limit: 64, }, - data: &data + data: &data, }; let expected_repr = IpPacket::Icmpv4(( Ipv4Repr { @@ -2120,42 +2427,58 @@ mod test { dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]), protocol: IpProtocol::Icmp, payload_len: icmp_repr.buffer_len(), - hop_limit: 64 + hop_limit: 64, }, - icmp_repr + icmp_repr, )); // Ensure that the unknown protocol triggers an error response. // And we correctly handle no payload. let cx = iface.context(Instant::from_secs(0)); - assert_eq!(iface.inner.process_udp(&cx, &mut socket_set, ip_repr, false, data), - Ok(Some(expected_repr))); + assert_eq!( + iface + .inner + .process_udp(&cx, &mut socket_set, ip_repr, false, data), + Ok(Some(expected_repr)) + ); let ip_repr = IpRepr::Ipv4(Ipv4Repr { - src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]), - dst_addr: Ipv4Address::BROADCAST, - protocol: IpProtocol::Udp, + src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]), + dst_addr: Ipv4Address::BROADCAST, + protocol: IpProtocol::Udp, payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(), - hop_limit: 64 + hop_limit: 64, }); // Emit the representations to a packet - udp_repr.emit(&mut packet_broadcast, &ip_repr.src_addr(), - &IpAddress::Ipv4(Ipv4Address::BROADCAST), - UDP_PAYLOAD.len(), |buf| buf.copy_from_slice( &UDP_PAYLOAD), - &ChecksumCapabilities::default()); + udp_repr.emit( + &mut packet_broadcast, + &ip_repr.src_addr(), + &IpAddress::Ipv4(Ipv4Address::BROADCAST), + UDP_PAYLOAD.len(), + |buf| buf.copy_from_slice(&UDP_PAYLOAD), + &ChecksumCapabilities::default(), + ); // Ensure that the port unreachable error does not trigger an // ICMP error response when the destination address is a // broadcast address and no socket is bound to the port. - assert_eq!(iface.inner.process_udp(&cx, &mut socket_set, ip_repr, - false, packet_broadcast.into_inner()), Ok(None)); + assert_eq!( + iface.inner.process_udp( + &cx, + &mut socket_set, + ip_repr, + false, + packet_broadcast.into_inner() + ), + Ok(None) + ); } #[test] #[cfg(feature = "socket-udp")] fn test_handle_udp_broadcast() { - use crate::socket::{UdpSocket, UdpSocketBuffer, UdpPacketMetadata}; + use crate::socket::{UdpPacketMetadata, UdpSocket, UdpSocketBuffer}; use crate::wire::IpEndpoint; static UDP_PAYLOAD: [u8; 5] = [0x48, 0x65, 0x6c, 0x6c, 0x6f]; @@ -2184,19 +2507,19 @@ mod test { #[cfg(feature = "proto-ipv6")] let ip_repr = IpRepr::Ipv6(Ipv6Repr { - src_addr: src_ip, - dst_addr: Ipv6Address::LINK_LOCAL_ALL_NODES, + src_addr: src_ip, + dst_addr: Ipv6Address::LINK_LOCAL_ALL_NODES, next_header: IpProtocol::Udp, payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(), - hop_limit: 0x40 + hop_limit: 0x40, }); #[cfg(all(not(feature = "proto-ipv6"), feature = "proto-ipv4"))] let ip_repr = IpRepr::Ipv4(Ipv4Repr { - src_addr: src_ip, - dst_addr: Ipv4Address::BROADCAST, - protocol: IpProtocol::Udp, + src_addr: src_ip, + dst_addr: Ipv4Address::BROADCAST, + protocol: IpProtocol::Udp, payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(), - hop_limit: 0x40 + hop_limit: 0x40, }); { @@ -2207,28 +2530,40 @@ mod test { assert!(socket.can_send()); } - udp_repr.emit(&mut packet, &ip_repr.src_addr(), &ip_repr.dst_addr(), - UDP_PAYLOAD.len(), |buf| buf.copy_from_slice( &UDP_PAYLOAD), - &ChecksumCapabilities::default()); + udp_repr.emit( + &mut packet, + &ip_repr.src_addr(), + &ip_repr.dst_addr(), + UDP_PAYLOAD.len(), + |buf| buf.copy_from_slice(&UDP_PAYLOAD), + &ChecksumCapabilities::default(), + ); // Packet should be handled by bound UDP socket let cx = iface.context(Instant::from_secs(0)); - assert_eq!(iface.inner.process_udp(&cx, &mut socket_set, ip_repr, false, packet.into_inner()), - Ok(None)); + assert_eq!( + iface + .inner + .process_udp(&cx, &mut socket_set, ip_repr, false, packet.into_inner()), + Ok(None) + ); { // Make sure the payload to the UDP packet processed by process_udp is // appended to the bound sockets rx_buffer let mut socket = socket_set.get::(socket_handle); assert!(socket.can_recv()); - assert_eq!(socket.recv(), Ok((&UDP_PAYLOAD[..], IpEndpoint::new(src_ip.into(), 67)))); + assert_eq!( + socket.recv(), + Ok((&UDP_PAYLOAD[..], IpEndpoint::new(src_ip.into(), 67))) + ); } } #[test] #[cfg(feature = "proto-ipv4")] fn test_handle_ipv4_broadcast() { - use crate::wire::{Ipv4Packet, Icmpv4Repr, Icmpv4Packet}; + use crate::wire::{Icmpv4Packet, Icmpv4Repr, Ipv4Packet}; let (mut iface, mut socket_set) = create_loopback(); @@ -2238,36 +2573,40 @@ mod test { // ICMPv4 echo request let icmpv4_data: [u8; 4] = [0xaa, 0x00, 0x00, 0xff]; let icmpv4_repr = Icmpv4Repr::EchoRequest { - ident: 0x1234, seq_no: 0xabcd, data: &icmpv4_data + ident: 0x1234, + seq_no: 0xabcd, + data: &icmpv4_data, }; // Send to IPv4 broadcast address let ipv4_repr = Ipv4Repr { - src_addr: src_ipv4_addr, - dst_addr: Ipv4Address::BROADCAST, - protocol: IpProtocol::Icmp, - hop_limit: 64, + src_addr: src_ipv4_addr, + dst_addr: Ipv4Address::BROADCAST, + protocol: IpProtocol::Icmp, + hop_limit: 64, payload_len: icmpv4_repr.buffer_len(), }; // Emit to ip frame - let mut bytes = vec![0u8; - ipv4_repr.buffer_len() + icmpv4_repr.buffer_len() - ]; + let mut bytes = vec![0u8; ipv4_repr.buffer_len() + icmpv4_repr.buffer_len()]; let frame = { ipv4_repr.emit( &mut Ipv4Packet::new_unchecked(&mut bytes), - &ChecksumCapabilities::default()); + &ChecksumCapabilities::default(), + ); icmpv4_repr.emit( - &mut Icmpv4Packet::new_unchecked( - &mut bytes[ipv4_repr.buffer_len()..]), - &ChecksumCapabilities::default()); + &mut Icmpv4Packet::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]), + &ChecksumCapabilities::default(), + ); Ipv4Packet::new_unchecked(&bytes) }; // Expected ICMPv4 echo reply let expected_icmpv4_repr = Icmpv4Repr::EchoReply { - ident: 0x1234, seq_no: 0xabcd, data: &icmpv4_data }; + ident: 0x1234, + seq_no: 0xabcd, + data: &icmpv4_data, + }; let expected_ipv4_repr = Ipv4Repr { src_addr: our_ipv4_addr, dst_addr: src_ipv4_addr, @@ -2278,17 +2617,19 @@ mod test { let expected_packet = IpPacket::Icmpv4((expected_ipv4_repr, expected_icmpv4_repr)); let cx = iface.context(Instant::from_secs(0)); - assert_eq!(iface.inner.process_ipv4(&cx, &mut socket_set, &frame), - Ok(Some(expected_packet))); + assert_eq!( + iface.inner.process_ipv4(&cx, &mut socket_set, &frame), + Ok(Some(expected_packet)) + ); } #[test] #[cfg(feature = "socket-udp")] fn test_icmp_reply_size() { - #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))] - use crate::wire::IPV4_MIN_MTU as MIN_MTU; #[cfg(feature = "proto-ipv6")] use crate::wire::Icmpv6DstUnreachable; + #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))] + use crate::wire::IPV4_MIN_MTU as MIN_MTU; #[cfg(feature = "proto-ipv6")] use crate::wire::IPV6_MIN_MTU as MIN_MTU; @@ -2316,16 +2657,21 @@ mod test { }; let mut bytes = vec![0xff; udp_repr.header_len() + MAX_PAYLOAD_LEN]; let mut packet = UdpPacket::new_unchecked(&mut bytes[..]); - udp_repr.emit(&mut packet, &src_addr.into(), &dst_addr.into(), - MAX_PAYLOAD_LEN, |buf| fill_slice(buf, 0x2a), - &ChecksumCapabilities::default()); + udp_repr.emit( + &mut packet, + &src_addr.into(), + &dst_addr.into(), + MAX_PAYLOAD_LEN, + |buf| fill_slice(buf, 0x2a), + &ChecksumCapabilities::default(), + ); #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))] let ip_repr = Ipv4Repr { src_addr: src_addr, dst_addr: dst_addr, protocol: IpProtocol::Udp, hop_limit: 64, - payload_len: udp_repr.header_len() + MAX_PAYLOAD_LEN + payload_len: udp_repr.header_len() + MAX_PAYLOAD_LEN, }; #[cfg(feature = "proto-ipv6")] let ip_repr = Ipv6Repr { @@ -2333,7 +2679,7 @@ mod test { dst_addr: dst_addr, next_header: IpProtocol::Udp, hop_limit: 64, - payload_len: udp_repr.header_len() + MAX_PAYLOAD_LEN + payload_len: udp_repr.header_len() + MAX_PAYLOAD_LEN, }; let payload = packet.into_inner(); @@ -2342,7 +2688,7 @@ mod test { let expected_icmp_repr = Icmpv6Repr::DstUnreachable { reason: Icmpv6DstUnreachable::PortUnreachable, header: ip_repr, - data: &payload[..MAX_PAYLOAD_LEN] + data: &payload[..MAX_PAYLOAD_LEN], }; #[cfg(feature = "proto-ipv6")] let expected_ip_repr = Ipv6Repr { @@ -2350,13 +2696,13 @@ mod test { dst_addr: src_addr, next_header: IpProtocol::Icmpv6, hop_limit: 64, - payload_len: expected_icmp_repr.buffer_len() + payload_len: expected_icmp_repr.buffer_len(), }; #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))] let expected_icmp_repr = Icmpv4Repr::DstUnreachable { reason: Icmpv4DstUnreachable::PortUnreachable, header: ip_repr, - data: &payload[..MAX_PAYLOAD_LEN] + data: &payload[..MAX_PAYLOAD_LEN], }; #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))] let expected_ip_repr = Ipv4Repr { @@ -2364,20 +2710,37 @@ mod test { dst_addr: src_addr, protocol: IpProtocol::Icmp, hop_limit: 64, - payload_len: expected_icmp_repr.buffer_len() + payload_len: expected_icmp_repr.buffer_len(), }; let cx = iface.context(Instant::from_secs(0)); // The expected packet does not exceed the IPV4_MIN_MTU - assert_eq!(expected_ip_repr.buffer_len() + expected_icmp_repr.buffer_len(), MIN_MTU); + assert_eq!( + expected_ip_repr.buffer_len() + expected_icmp_repr.buffer_len(), + MIN_MTU + ); // The expected packet and the generated packet are equal #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))] - assert_eq!(iface.inner.process_udp(&cx, &mut socket_set, ip_repr.into(), false, payload), - Ok(Some(IpPacket::Icmpv4((expected_ip_repr, expected_icmp_repr))))); + assert_eq!( + iface + .inner + .process_udp(&cx, &mut socket_set, ip_repr.into(), false, payload), + Ok(Some(IpPacket::Icmpv4(( + expected_ip_repr, + expected_icmp_repr + )))) + ); #[cfg(feature = "proto-ipv6")] - assert_eq!(iface.inner.process_udp(&cx, &mut socket_set, ip_repr.into(), false, payload), - Ok(Some(IpPacket::Icmpv6((expected_ip_repr, expected_icmp_repr))))); + assert_eq!( + iface + .inner + .process_udp(&cx, &mut socket_set, ip_repr.into(), false, payload), + Ok(Some(IpPacket::Icmpv6(( + expected_ip_repr, + expected_icmp_repr + )))) + ); } #[test] @@ -2412,19 +2775,29 @@ mod test { let cx = iface.context(Instant::from_secs(0)); // Ensure an ARP Request for us triggers an ARP Reply - assert_eq!(iface.inner.process_ethernet(&cx, &mut socket_set, frame.into_inner()), - Ok(Some(EthernetPacket::Arp(ArpRepr::EthernetIpv4 { - operation: ArpOperation::Reply, - source_hardware_addr: local_hw_addr, - source_protocol_addr: local_ip_addr, - target_hardware_addr: remote_hw_addr, - target_protocol_addr: remote_ip_addr - })))); + assert_eq!( + iface + .inner + .process_ethernet(&cx, &mut socket_set, frame.into_inner()), + Ok(Some(EthernetPacket::Arp(ArpRepr::EthernetIpv4 { + operation: ArpOperation::Reply, + source_hardware_addr: local_hw_addr, + source_protocol_addr: local_ip_addr, + target_hardware_addr: remote_hw_addr, + target_protocol_addr: remote_ip_addr + }))) + ); // Ensure the address of the requestor was entered in the cache - assert_eq!(iface.inner.lookup_hardware_addr(&cx, MockTxToken, - &IpAddress::Ipv4(local_ip_addr), &IpAddress::Ipv4(remote_ip_addr)), - Ok((remote_hw_addr, MockTxToken))); + assert_eq!( + iface.inner.lookup_hardware_addr( + &cx, + MockTxToken, + &IpAddress::Ipv4(local_ip_addr), + &IpAddress::Ipv4(remote_ip_addr) + ), + Ok((remote_hw_addr, MockTxToken)) + ); } #[test] @@ -2448,7 +2821,7 @@ mod test { dst_addr: local_ip_addr.solicited_node(), next_header: IpProtocol::Icmpv6, hop_limit: 0xff, - payload_len: solicit.buffer_len() + payload_len: solicit.buffer_len(), }); let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes); @@ -2457,16 +2830,18 @@ mod test { frame.set_ethertype(EthernetProtocol::Ipv6); { ip_repr.emit(frame.payload_mut(), &ChecksumCapabilities::default()); - solicit.emit(&remote_ip_addr.into(), &local_ip_addr.solicited_node().into(), - &mut Icmpv6Packet::new_unchecked( - &mut frame.payload_mut()[ip_repr.buffer_len()..]), - &ChecksumCapabilities::default()); + solicit.emit( + &remote_ip_addr.into(), + &local_ip_addr.solicited_node().into(), + &mut Icmpv6Packet::new_unchecked(&mut frame.payload_mut()[ip_repr.buffer_len()..]), + &ChecksumCapabilities::default(), + ); } let icmpv6_expected = Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert { flags: NdiscNeighborFlags::SOLICITED, target_addr: local_ip_addr, - lladdr: Some(local_hw_addr) + lladdr: Some(local_hw_addr), }); let ipv6_expected = Ipv6Repr { @@ -2474,19 +2849,32 @@ mod test { dst_addr: remote_ip_addr, next_header: IpProtocol::Icmpv6, hop_limit: 0xff, - payload_len: icmpv6_expected.buffer_len() + payload_len: icmpv6_expected.buffer_len(), }; let cx = iface.context(Instant::from_secs(0)); // Ensure an Neighbor Solicitation triggers a Neighbor Advertisement - assert_eq!(iface.inner.process_ethernet(&cx, &mut socket_set, frame.into_inner()), - Ok(Some(EthernetPacket::Ip(IpPacket::Icmpv6((ipv6_expected, icmpv6_expected)))))); + assert_eq!( + iface + .inner + .process_ethernet(&cx, &mut socket_set, frame.into_inner()), + Ok(Some(EthernetPacket::Ip(IpPacket::Icmpv6(( + ipv6_expected, + icmpv6_expected + ))))) + ); // Ensure the address of the requestor was entered in the cache - assert_eq!(iface.inner.lookup_hardware_addr(&cx, MockTxToken, - &IpAddress::Ipv6(local_ip_addr), &IpAddress::Ipv6(remote_ip_addr)), - Ok((remote_hw_addr, MockTxToken))); + assert_eq!( + iface.inner.lookup_hardware_addr( + &cx, + MockTxToken, + &IpAddress::Ipv6(local_ip_addr), + &IpAddress::Ipv6(remote_ip_addr) + ), + Ok((remote_hw_addr, MockTxToken)) + ); } #[test] @@ -2519,20 +2907,29 @@ mod test { let cx = iface.context(Instant::from_secs(0)); // Ensure an ARP Request for someone else does not trigger an ARP Reply - assert_eq!(iface.inner.process_ethernet(&cx, &mut socket_set, frame.into_inner()), - Ok(None)); + assert_eq!( + iface + .inner + .process_ethernet(&cx, &mut socket_set, frame.into_inner()), + Ok(None) + ); // Ensure the address of the requestor was entered in the cache - assert_eq!(iface.inner.lookup_hardware_addr(&cx, MockTxToken, - &IpAddress::Ipv4(Ipv4Address([0x7f, 0x00, 0x00, 0x01])), - &IpAddress::Ipv4(remote_ip_addr)), - Ok((remote_hw_addr, MockTxToken))); + assert_eq!( + iface.inner.lookup_hardware_addr( + &cx, + MockTxToken, + &IpAddress::Ipv4(Ipv4Address([0x7f, 0x00, 0x00, 0x01])), + &IpAddress::Ipv4(remote_ip_addr) + ), + Ok((remote_hw_addr, MockTxToken)) + ); } #[test] #[cfg(all(feature = "socket-icmp", feature = "proto-ipv4"))] fn test_icmpv4_socket() { - use crate::socket::{IcmpSocket, IcmpEndpoint, IcmpSocketBuffer, IcmpPacketMetadata}; + use crate::socket::{IcmpEndpoint, IcmpPacketMetadata, IcmpSocket, IcmpSocketBuffer}; use crate::wire::Icmpv4Packet; let (iface, mut socket_set) = create_loopback(); @@ -2557,16 +2954,20 @@ mod test { // Ensure the ident we bound to and the ident of the packet are the same. let mut bytes = [0xff; 24]; let mut packet = Icmpv4Packet::new_unchecked(&mut bytes); - let echo_repr = Icmpv4Repr::EchoRequest{ ident, seq_no, data: echo_data }; + let echo_repr = Icmpv4Repr::EchoRequest { + ident, + seq_no, + data: echo_data, + }; echo_repr.emit(&mut packet, &ChecksumCapabilities::default()); let icmp_data = &packet.into_inner()[..]; let ipv4_repr = Ipv4Repr { - src_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x02), - dst_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x01), - protocol: IpProtocol::Icmp, + src_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x02), + dst_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x01), + protocol: IpProtocol::Icmp, payload_len: 24, - hop_limit: 64 + hop_limit: 64, }; let ip_repr = IpRepr::Ipv4(ipv4_repr); @@ -2577,22 +2978,34 @@ mod test { } // Confirm we still get EchoReply from `smoltcp` even with the ICMP socket listening - let echo_reply = Icmpv4Repr::EchoReply{ ident, seq_no, data: echo_data }; + let echo_reply = Icmpv4Repr::EchoReply { + ident, + seq_no, + data: echo_data, + }; let ipv4_reply = Ipv4Repr { src_addr: ipv4_repr.dst_addr, dst_addr: ipv4_repr.src_addr, ..ipv4_repr }; let cx = iface.context(Instant::from_secs(0)); - assert_eq!(iface.inner.process_icmpv4(&cx, &mut socket_set, ip_repr, icmp_data), - Ok(Some(IpPacket::Icmpv4((ipv4_reply, echo_reply))))); + assert_eq!( + iface + .inner + .process_icmpv4(&cx, &mut socket_set, ip_repr, icmp_data), + Ok(Some(IpPacket::Icmpv4((ipv4_reply, echo_reply)))) + ); { let mut socket = socket_set.get::(socket_handle); assert!(socket.can_recv()); - assert_eq!(socket.recv(), - Ok((&icmp_data[..], - IpAddress::Ipv4(Ipv4Address::new(0x7f, 0x00, 0x00, 0x02))))); + assert_eq!( + socket.recv(), + Ok(( + &icmp_data[..], + IpAddress::Ipv4(Ipv4Address::new(0x7f, 0x00, 0x00, 0x02)) + )) + ); } } @@ -2600,15 +3013,23 @@ mod test { #[cfg(feature = "proto-ipv6")] fn test_solicited_node_addrs() { let (mut iface, _) = create_loopback(); - let mut new_addrs = vec![IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 1, 2, 0, 2), 64), - IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 3, 4, 0, 0xffff), 64)]; + let mut new_addrs = vec![ + IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 1, 2, 0, 2), 64), + IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 3, 4, 0, 0xffff), 64), + ]; iface.update_ip_addrs(|addrs| { new_addrs.extend(addrs.to_vec()); *addrs = From::from(new_addrs); }); - assert!(iface.inner.has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0x0002))); - assert!(iface.inner.has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0xffff))); - assert!(!iface.inner.has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0x0003))); + assert!(iface + .inner + .has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0x0002))); + assert!(iface + .inner + .has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0xffff))); + assert!(!iface + .inner + .has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0x0003))); } #[test] @@ -2621,11 +3042,11 @@ mod test { let payload = [0x12, 0x34, 0x56, 0x78]; let ipv6_repr = Ipv6Repr { - src_addr: remote_ip_addr, - dst_addr: Ipv6Address::LOOPBACK, + src_addr: remote_ip_addr, + dst_addr: Ipv6Address::LOOPBACK, next_header: IpProtocol::HopByHop, payload_len: 12, - hop_limit: 0x40, + hop_limit: 0x40, }; let mut bytes = vec![0; 52]; @@ -2634,8 +3055,7 @@ mod test { ip_repr.emit(&mut bytes, &ChecksumCapabilities::default()); let mut offset = ipv6_repr.buffer_len(); { - let mut hbh_pkt = - Ipv6HopByHopHeader::new_unchecked(&mut bytes[offset..]); + let mut hbh_pkt = Ipv6HopByHopHeader::new_unchecked(&mut bytes[offset..]); hbh_pkt.set_next_header(IpProtocol::Unknown(0x0c)); hbh_pkt.set_header_len(0); offset += 8; @@ -2653,38 +3073,42 @@ mod test { }; let reply_icmp_repr = Icmpv6Repr::ParamProblem { - reason: Icmpv6ParamProblem::UnrecognizedNxtHdr, + reason: Icmpv6ParamProblem::UnrecognizedNxtHdr, pointer: 40, - header: ipv6_repr, - data: &payload[..] + header: ipv6_repr, + data: &payload[..], }; let reply_ipv6_repr = Ipv6Repr { - src_addr: Ipv6Address::LOOPBACK, - dst_addr: remote_ip_addr, + src_addr: Ipv6Address::LOOPBACK, + dst_addr: remote_ip_addr, next_header: IpProtocol::Icmpv6, payload_len: reply_icmp_repr.buffer_len(), - hop_limit: 0x40, + hop_limit: 0x40, }; let cx = iface.context(Instant::from_secs(0)); // Ensure the unknown next header causes a ICMPv6 Parameter Problem // error message to be sent to the sender. - assert_eq!(iface.inner.process_ipv6(&cx, &mut socket_set, &frame), - Ok(Some(IpPacket::Icmpv6((reply_ipv6_repr, reply_icmp_repr))))); + assert_eq!( + iface.inner.process_ipv6(&cx, &mut socket_set, &frame), + Ok(Some(IpPacket::Icmpv6((reply_ipv6_repr, reply_icmp_repr)))) + ); } #[test] #[cfg(feature = "proto-igmp")] fn test_handle_igmp() { - fn recv_igmp(mut iface: &mut Interface<'_, Loopback>, timestamp: Instant) -> Vec<(Ipv4Repr, IgmpRepr)> { + fn recv_igmp( + mut iface: &mut Interface<'_, Loopback>, + timestamp: Instant, + ) -> Vec<(Ipv4Repr, IgmpRepr)> { let caps = iface.device.capabilities(); let checksum_caps = &caps.checksum; recv_all(&mut iface, timestamp) .iter() .filter_map(|frame| { - let ipv4_packet = match caps.medium { #[cfg(feature = "medium-ethernet")] Medium::Ethernet => { @@ -2692,7 +3116,7 @@ mod test { Ipv4Packet::new_checked(eth_frame.payload()).ok()? } #[cfg(feature = "medium-ip")] - Medium::Ip => Ipv4Packet::new_checked(&frame[..]).ok()? + Medium::Ip => Ipv4Packet::new_checked(&frame[..]).ok()?, }; let ipv4_repr = Ipv4Repr::parse(&ipv4_packet, &checksum_caps).ok()?; let ip_payload = ipv4_packet.payload(); @@ -2713,8 +3137,7 @@ mod test { // Join multicast groups let timestamp = Instant::now(); for group in &groups { - iface.join_multicast_group(*group, timestamp) - .unwrap(); + iface.join_multicast_group(*group, timestamp).unwrap(); } let reports = recv_igmp(&mut iface, timestamp); @@ -2722,31 +3145,32 @@ mod test { for (i, group_addr) in groups.iter().enumerate() { assert_eq!(reports[i].0.protocol, IpProtocol::Igmp); assert_eq!(reports[i].0.dst_addr, *group_addr); - assert_eq!(reports[i].1, IgmpRepr::MembershipReport { - group_addr: *group_addr, - version: IgmpVersion::Version2, - }); + assert_eq!( + reports[i].1, + IgmpRepr::MembershipReport { + group_addr: *group_addr, + version: IgmpVersion::Version2, + } + ); } // General query let timestamp = Instant::now(); const GENERAL_QUERY_BYTES: &[u8] = &[ - 0x46, 0xc0, 0x00, 0x24, 0xed, 0xb4, 0x00, 0x00, - 0x01, 0x02, 0x47, 0x43, 0xac, 0x16, 0x63, 0x04, - 0xe0, 0x00, 0x00, 0x01, 0x94, 0x04, 0x00, 0x00, - 0x11, 0x64, 0xec, 0x8f, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x46, 0xc0, 0x00, 0x24, 0xed, 0xb4, 0x00, 0x00, 0x01, 0x02, 0x47, 0x43, 0xac, 0x16, + 0x63, 0x04, 0xe0, 0x00, 0x00, 0x01, 0x94, 0x04, 0x00, 0x00, 0x11, 0x64, 0xec, 0x8f, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, ]; { // Transmit GENERAL_QUERY_BYTES into loopback let tx_token = iface.device.transmit().unwrap(); - tx_token.consume( - timestamp, GENERAL_QUERY_BYTES.len(), - |buffer| { + tx_token + .consume(timestamp, GENERAL_QUERY_BYTES.len(), |buffer| { buffer.copy_from_slice(GENERAL_QUERY_BYTES); Ok(()) - }).unwrap(); + }) + .unwrap(); } // Trigger processing until all packets received through the // loopback have been processed, including responses to @@ -2758,8 +3182,7 @@ mod test { // Leave multicast groups let timestamp = Instant::now(); for group in &groups { - iface.leave_multicast_group(*group, timestamp) - .unwrap(); + iface.leave_multicast_group(*group, timestamp).unwrap(); } let leaves = recv_igmp(&mut iface, timestamp); @@ -2774,14 +3197,18 @@ mod test { #[test] #[cfg(all(feature = "proto-ipv4", feature = "socket-raw"))] fn test_raw_socket_no_reply() { - use crate::socket::{RawSocket, RawSocketBuffer, RawPacketMetadata}; + use crate::socket::{RawPacketMetadata, RawSocket, RawSocketBuffer}; use crate::wire::{IpVersion, Ipv4Packet, UdpPacket, UdpRepr}; let (mut iface, mut socket_set) = create_loopback(); let packets = 1; - let rx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * 1]); - let tx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * packets]); + let rx_buffer = + RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * 1]); + let tx_buffer = RawSocketBuffer::new( + vec![RawPacketMetadata::EMPTY; packets], + vec![0; 48 * packets], + ); let raw_socket = RawSocket::new(IpVersion::Ipv4, IpProtocol::Udp, rx_buffer, tx_buffer); socket_set.add(raw_socket); @@ -2796,51 +3223,62 @@ mod test { }; let mut bytes = vec![0xff; udp_repr.header_len() + PAYLOAD_LEN]; let mut packet = UdpPacket::new_unchecked(&mut bytes[..]); - udp_repr.emit(&mut packet, &src_addr.into(), &dst_addr.into(), - PAYLOAD_LEN, |buf| fill_slice(buf, 0x2a), - &ChecksumCapabilities::default()); + udp_repr.emit( + &mut packet, + &src_addr.into(), + &dst_addr.into(), + PAYLOAD_LEN, + |buf| fill_slice(buf, 0x2a), + &ChecksumCapabilities::default(), + ); let ipv4_repr = Ipv4Repr { src_addr: src_addr, dst_addr: dst_addr, protocol: IpProtocol::Udp, hop_limit: 64, - payload_len: udp_repr.header_len() + PAYLOAD_LEN + payload_len: udp_repr.header_len() + PAYLOAD_LEN, }; // Emit to frame - let mut bytes = vec![0u8; - ipv4_repr.buffer_len() + udp_repr.header_len() + PAYLOAD_LEN - ]; + let mut bytes = vec![0u8; ipv4_repr.buffer_len() + udp_repr.header_len() + PAYLOAD_LEN]; let frame = { ipv4_repr.emit( &mut Ipv4Packet::new_unchecked(&mut bytes), - &ChecksumCapabilities::default()); + &ChecksumCapabilities::default(), + ); udp_repr.emit( - &mut UdpPacket::new_unchecked( - &mut bytes[ipv4_repr.buffer_len()..]), + &mut UdpPacket::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]), &src_addr.into(), &dst_addr.into(), - PAYLOAD_LEN, |buf| fill_slice(buf, 0x2a), - &ChecksumCapabilities::default()); + PAYLOAD_LEN, + |buf| fill_slice(buf, 0x2a), + &ChecksumCapabilities::default(), + ); Ipv4Packet::new_unchecked(&bytes) }; let cx = iface.context(Instant::from_millis(0)); - assert_eq!(iface.inner.process_ipv4(&cx, &mut socket_set, &frame), - Ok(None)); + assert_eq!( + iface.inner.process_ipv4(&cx, &mut socket_set, &frame), + Ok(None) + ); } #[test] #[cfg(all(feature = "proto-ipv4", feature = "socket-raw"))] fn test_raw_socket_truncated_packet() { - use crate::socket::{RawSocket, RawSocketBuffer, RawPacketMetadata}; + use crate::socket::{RawPacketMetadata, RawSocket, RawSocketBuffer}; use crate::wire::{IpVersion, Ipv4Packet, UdpPacket, UdpRepr}; let (mut iface, mut socket_set) = create_loopback(); let packets = 1; - let rx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * 1]); - let tx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * packets]); + let rx_buffer = + RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * 1]); + let tx_buffer = RawSocketBuffer::new( + vec![RawPacketMetadata::EMPTY; packets], + vec![0; 48 * packets], + ); let raw_socket = RawSocket::new(IpVersion::Ipv4, IpProtocol::Udp, rx_buffer, tx_buffer); socket_set.add(raw_socket); @@ -2855,32 +3293,37 @@ mod test { }; let mut bytes = vec![0xff; udp_repr.header_len() + PAYLOAD_LEN]; let mut packet = UdpPacket::new_unchecked(&mut bytes[..]); - udp_repr.emit(&mut packet, &src_addr.into(), &dst_addr.into(), - PAYLOAD_LEN, |buf| fill_slice(buf, 0x2a), - &ChecksumCapabilities::default()); + udp_repr.emit( + &mut packet, + &src_addr.into(), + &dst_addr.into(), + PAYLOAD_LEN, + |buf| fill_slice(buf, 0x2a), + &ChecksumCapabilities::default(), + ); let ipv4_repr = Ipv4Repr { src_addr: src_addr, dst_addr: dst_addr, protocol: IpProtocol::Udp, hop_limit: 64, - payload_len: udp_repr.header_len() + PAYLOAD_LEN + payload_len: udp_repr.header_len() + PAYLOAD_LEN, }; // Emit to frame - let mut bytes = vec![0u8; - ipv4_repr.buffer_len() + udp_repr.header_len() + PAYLOAD_LEN - ]; + let mut bytes = vec![0u8; ipv4_repr.buffer_len() + udp_repr.header_len() + PAYLOAD_LEN]; let frame = { ipv4_repr.emit( &mut Ipv4Packet::new_unchecked(&mut bytes), - &ChecksumCapabilities::default()); + &ChecksumCapabilities::default(), + ); udp_repr.emit( - &mut UdpPacket::new_unchecked( - &mut bytes[ipv4_repr.buffer_len()..]), + &mut UdpPacket::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]), &src_addr.into(), &dst_addr.into(), - PAYLOAD_LEN, |buf| fill_slice(buf, 0x2a), - &ChecksumCapabilities::default()); + PAYLOAD_LEN, + |buf| fill_slice(buf, 0x2a), + &ChecksumCapabilities::default(), + ); Ipv4Packet::new_unchecked(&bytes) }; @@ -2897,9 +3340,11 @@ mod test { #[test] #[cfg(all(feature = "proto-ipv4", feature = "socket-raw", feature = "socket-udp"))] fn test_raw_socket_with_udp_socket() { - use crate::socket::{UdpSocket, UdpSocketBuffer, UdpPacketMetadata, - RawSocket, RawSocketBuffer, RawPacketMetadata}; - use crate::wire::{IpVersion, IpEndpoint, Ipv4Packet, UdpPacket, UdpRepr}; + use crate::socket::{ + RawPacketMetadata, RawSocket, RawSocketBuffer, UdpPacketMetadata, UdpSocket, + UdpSocketBuffer, + }; + use crate::wire::{IpEndpoint, IpVersion, Ipv4Packet, UdpPacket, UdpRepr}; static UDP_PAYLOAD: [u8; 5] = [0x48, 0x65, 0x6c, 0x6c, 0x6f]; @@ -2918,9 +3363,18 @@ mod test { } let packets = 1; - let raw_rx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * 1]); - let raw_tx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * packets]); - let raw_socket = RawSocket::new(IpVersion::Ipv4, IpProtocol::Udp, raw_rx_buffer, raw_tx_buffer); + let raw_rx_buffer = + RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * 1]); + let raw_tx_buffer = RawSocketBuffer::new( + vec![RawPacketMetadata::EMPTY; packets], + vec![0; 48 * packets], + ); + let raw_socket = RawSocket::new( + IpVersion::Ipv4, + IpProtocol::Udp, + raw_rx_buffer, + raw_tx_buffer, + ); socket_set.add(raw_socket); let src_addr = Ipv4Address([127, 0, 0, 2]); @@ -2932,44 +3386,55 @@ mod test { }; let mut bytes = vec![0xff; udp_repr.header_len() + UDP_PAYLOAD.len()]; let mut packet = UdpPacket::new_unchecked(&mut bytes[..]); - udp_repr.emit(&mut packet, &src_addr.into(), &dst_addr.into(), - UDP_PAYLOAD.len(), |buf| buf.copy_from_slice( &UDP_PAYLOAD), - &ChecksumCapabilities::default()); + udp_repr.emit( + &mut packet, + &src_addr.into(), + &dst_addr.into(), + UDP_PAYLOAD.len(), + |buf| buf.copy_from_slice(&UDP_PAYLOAD), + &ChecksumCapabilities::default(), + ); let ipv4_repr = Ipv4Repr { src_addr: src_addr, dst_addr: dst_addr, protocol: IpProtocol::Udp, hop_limit: 64, - payload_len: udp_repr.header_len() + UDP_PAYLOAD.len() + payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(), }; // Emit to frame - let mut bytes = vec![0u8; - ipv4_repr.buffer_len() + udp_repr.header_len() + UDP_PAYLOAD.len() - ]; + let mut bytes = + vec![0u8; ipv4_repr.buffer_len() + udp_repr.header_len() + UDP_PAYLOAD.len()]; let frame = { ipv4_repr.emit( &mut Ipv4Packet::new_unchecked(&mut bytes), - &ChecksumCapabilities::default()); + &ChecksumCapabilities::default(), + ); udp_repr.emit( - &mut UdpPacket::new_unchecked( - &mut bytes[ipv4_repr.buffer_len()..]), + &mut UdpPacket::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]), &src_addr.into(), &dst_addr.into(), - UDP_PAYLOAD.len(), |buf| buf.copy_from_slice( &UDP_PAYLOAD), - &ChecksumCapabilities::default()); + UDP_PAYLOAD.len(), + |buf| buf.copy_from_slice(&UDP_PAYLOAD), + &ChecksumCapabilities::default(), + ); Ipv4Packet::new_unchecked(&bytes) }; let cx = iface.context(Instant::from_millis(0)); - assert_eq!(iface.inner.process_ipv4(&cx, &mut socket_set, &frame), - Ok(None)); + assert_eq!( + iface.inner.process_ipv4(&cx, &mut socket_set, &frame), + Ok(None) + ); { // Make sure the UDP socket can still receive in presence of a Raw socket that handles UDP let mut socket = socket_set.get::(udp_socket_handle); assert!(socket.can_recv()); - assert_eq!(socket.recv(), Ok((&UDP_PAYLOAD[..], IpEndpoint::new(src_addr.into(), 67)))); + assert_eq!( + socket.recv(), + Ok((&UDP_PAYLOAD[..], IpEndpoint::new(src_addr.into(), 67))) + ); } } } diff --git a/src/iface/mod.rs b/src/iface/mod.rs index 1b4f32d..18f0b12 100644 --- a/src/iface/mod.rs +++ b/src/iface/mod.rs @@ -4,18 +4,18 @@ The `iface` module deals with the *network interfaces*. It filters incoming fram provides lookup and caching of hardware addresses, and handles management packets. */ +#[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))] +mod interface; #[cfg(feature = "medium-ethernet")] mod neighbor; mod route; -#[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))] -mod interface; -#[cfg(feature = "medium-ethernet")] -pub use self::neighbor::Neighbor as Neighbor; #[cfg(feature = "medium-ethernet")] pub(crate) use self::neighbor::Answer as NeighborAnswer; #[cfg(feature = "medium-ethernet")] pub use self::neighbor::Cache as NeighborCache; +#[cfg(feature = "medium-ethernet")] +pub use self::neighbor::Neighbor; pub use self::route::{Route, Routes}; #[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))] diff --git a/src/iface/neighbor.rs b/src/iface/neighbor.rs index 2f08017..64d239c 100644 --- a/src/iface/neighbor.rs +++ b/src/iface/neighbor.rs @@ -3,8 +3,8 @@ use managed::ManagedMap; -use crate::wire::{EthernetAddress, IpAddress}; use crate::time::{Duration, Instant}; +use crate::wire::{EthernetAddress, IpAddress}; /// A cached neighbor. /// @@ -14,7 +14,7 @@ use crate::time::{Duration, Instant}; #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Neighbor { hardware_addr: EthernetAddress, - expires_at: Instant, + expires_at: Instant, } /// An answer to a neighbor cache lookup. @@ -27,7 +27,7 @@ pub(crate) enum Answer { NotFound, /// The neighbor address is not in the cache, or has expired, /// and a lookup has been made recently. - RateLimited + RateLimited, } impl Answer { @@ -61,10 +61,9 @@ impl Answer { /// ``` #[derive(Debug)] pub struct Cache<'a> { - storage: ManagedMap<'a, IpAddress, Neighbor>, + storage: ManagedMap<'a, IpAddress, Neighbor>, silent_until: Instant, - gc_threshold: usize - + gc_threshold: usize, } impl<'a> Cache<'a> { @@ -82,21 +81,32 @@ impl<'a> Cache<'a> { /// # Panics /// This function panics if `storage.len() == 0`. pub fn new(storage: T) -> Cache<'a> - where T: Into> { - + where + T: Into>, + { Cache::new_with_limit(storage, Cache::GC_THRESHOLD) } pub fn new_with_limit(storage: T, gc_threshold: usize) -> Cache<'a> - where T: Into> { + where + T: Into>, + { let mut storage = storage.into(); storage.clear(); - Cache { storage, gc_threshold, silent_until: Instant::from_millis(0) } + Cache { + storage, + gc_threshold, + silent_until: Instant::from_millis(0), + } } - pub fn fill(&mut self, protocol_addr: IpAddress, hardware_addr: EthernetAddress, - timestamp: Instant) { + pub fn fill( + &mut self, + protocol_addr: IpAddress, + hardware_addr: EthernetAddress, + timestamp: Instant, + ) { debug_assert!(protocol_addr.is_unicast()); debug_assert!(hardware_addr.is_unicast()); @@ -104,11 +114,12 @@ impl<'a> Cache<'a> { let current_storage_size = self.storage.len(); match self.storage { - ManagedMap::Borrowed(_) => (), + ManagedMap::Borrowed(_) => (), #[cfg(any(feature = "std", feature = "alloc"))] ManagedMap::Owned(ref mut map) => { if current_storage_size >= self.gc_threshold { - let new_btree_map = map.iter_mut() + let new_btree_map = map + .iter_mut() .map(|(key, value)| (*key, *value)) .filter(|(_, v)| timestamp < v.expires_at) .collect(); @@ -118,13 +129,18 @@ impl<'a> Cache<'a> { } }; let neighbor = Neighbor { - expires_at: timestamp + Self::ENTRY_LIFETIME, hardware_addr + expires_at: timestamp + Self::ENTRY_LIFETIME, + hardware_addr, }; match self.storage.insert(protocol_addr, neighbor) { Ok(Some(old_neighbor)) => { if old_neighbor.hardware_addr != hardware_addr { - net_trace!("replaced {} => {} (was {})", - protocol_addr, hardware_addr, old_neighbor.hardware_addr); + net_trace!( + "replaced {} => {} (was {})", + protocol_addr, + hardware_addr, + old_neighbor.hardware_addr + ); } } Ok(None) => { @@ -147,21 +163,23 @@ impl<'a> Cache<'a> { } // Owned maps can extend themselves. #[cfg(any(feature = "std", feature = "alloc"))] - ManagedMap::Owned(_) => unreachable!() + ManagedMap::Owned(_) => unreachable!(), }; - let _old_neighbor = - self.storage.remove(&old_protocol_addr).unwrap(); + let _old_neighbor = self.storage.remove(&old_protocol_addr).unwrap(); match self.storage.insert(protocol_addr, neighbor) { Ok(None) => { - net_trace!("filled {} => {} (evicted {} => {})", - protocol_addr, hardware_addr, - old_protocol_addr, _old_neighbor.hardware_addr); + net_trace!( + "filled {} => {} (evicted {} => {})", + protocol_addr, + hardware_addr, + old_protocol_addr, + _old_neighbor.hardware_addr + ); } // We've covered everything else above. - _ => unreachable!() + _ => unreachable!(), } - } } } @@ -171,10 +189,13 @@ impl<'a> Cache<'a> { return Answer::Found(EthernetAddress::BROADCAST); } - if let Some(&Neighbor { expires_at, hardware_addr }) = - self.storage.get(protocol_addr) { + if let Some(&Neighbor { + expires_at, + hardware_addr, + }) = self.storage.get(protocol_addr) + { if timestamp < expires_at { - return Answer::Found(hardware_addr) + return Answer::Found(hardware_addr); } } @@ -193,9 +214,8 @@ impl<'a> Cache<'a> { #[cfg(test)] mod test { use super::*; - use std::collections::BTreeMap; use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3, MOCK_IP_ADDR_4}; - + use std::collections::BTreeMap; const HADDR_A: EthernetAddress = EthernetAddress([0, 0, 0, 0, 0, 1]); const HADDR_B: EthernetAddress = EthernetAddress([0, 0, 0, 0, 0, 2]); @@ -207,17 +227,47 @@ mod test { let mut cache_storage = [Default::default(); 3]; let mut cache = Cache::new(&mut cache_storage[..]); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)).found(), false); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0)).found(), false); + assert_eq!( + cache + .lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)) + .found(), + false + ); + assert_eq!( + cache + .lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0)) + .found(), + false + ); cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0)); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), Answer::Found(HADDR_A)); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0)).found(), false); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0) + Cache::ENTRY_LIFETIME * 2).found(), - false); + assert_eq!( + cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), + Answer::Found(HADDR_A) + ); + assert_eq!( + cache + .lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0)) + .found(), + false + ); + assert_eq!( + cache + .lookup( + &MOCK_IP_ADDR_1, + Instant::from_millis(0) + Cache::ENTRY_LIFETIME * 2 + ) + .found(), + false + ); cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0)); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0)).found(), false); + assert_eq!( + cache + .lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0)) + .found(), + false + ); } #[test] @@ -226,9 +276,19 @@ mod test { let mut cache = Cache::new(&mut cache_storage[..]); cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0)); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), Answer::Found(HADDR_A)); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0) + Cache::ENTRY_LIFETIME * 2).found(), - false); + assert_eq!( + cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), + Answer::Found(HADDR_A) + ); + assert_eq!( + cache + .lookup( + &MOCK_IP_ADDR_1, + Instant::from_millis(0) + Cache::ENTRY_LIFETIME * 2 + ) + .found(), + false + ); } #[test] @@ -237,9 +297,15 @@ mod test { let mut cache = Cache::new(&mut cache_storage[..]); cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0)); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), Answer::Found(HADDR_A)); + assert_eq!( + cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), + Answer::Found(HADDR_A) + ); cache.fill(MOCK_IP_ADDR_1, HADDR_B, Instant::from_millis(0)); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), Answer::Found(HADDR_B)); + assert_eq!( + cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), + Answer::Found(HADDR_B) + ); } #[test] @@ -249,10 +315,20 @@ mod test { cache.fill(MOCK_IP_ADDR_2, HADDR_B, Instant::from_millis(50)); // Adding third item after the expiration of the previous // two should garbage collect - cache.fill(MOCK_IP_ADDR_3, HADDR_C, Instant::from_millis(50) + Cache::ENTRY_LIFETIME * 2); + cache.fill( + MOCK_IP_ADDR_3, + HADDR_C, + Instant::from_millis(50) + Cache::ENTRY_LIFETIME * 2, + ); assert_eq!(cache.storage.len(), 1); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_3, Instant::from_millis(50) + Cache::ENTRY_LIFETIME * 2), Answer::Found(HADDR_C)); + assert_eq!( + cache.lookup( + &MOCK_IP_ADDR_3, + Instant::from_millis(50) + Cache::ENTRY_LIFETIME * 2 + ), + Answer::Found(HADDR_C) + ); } #[test] @@ -263,12 +339,28 @@ mod test { cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(100)); cache.fill(MOCK_IP_ADDR_2, HADDR_B, Instant::from_millis(50)); cache.fill(MOCK_IP_ADDR_3, HADDR_C, Instant::from_millis(200)); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(1000)), Answer::Found(HADDR_B)); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_4, Instant::from_millis(1000)).found(), false); + assert_eq!( + cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(1000)), + Answer::Found(HADDR_B) + ); + assert_eq!( + cache + .lookup(&MOCK_IP_ADDR_4, Instant::from_millis(1000)) + .found(), + false + ); cache.fill(MOCK_IP_ADDR_4, HADDR_D, Instant::from_millis(300)); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(1000)).found(), false); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_4, Instant::from_millis(1000)), Answer::Found(HADDR_D)); + assert_eq!( + cache + .lookup(&MOCK_IP_ADDR_2, Instant::from_millis(1000)) + .found(), + false + ); + assert_eq!( + cache.lookup(&MOCK_IP_ADDR_4, Instant::from_millis(1000)), + Answer::Found(HADDR_D) + ); } #[test] @@ -276,10 +368,19 @@ mod test { let mut cache_storage = [Default::default(); 3]; let mut cache = Cache::new(&mut cache_storage[..]); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), Answer::NotFound); + assert_eq!( + cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), + Answer::NotFound + ); cache.limit_rate(Instant::from_millis(0)); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(100)), Answer::RateLimited); - assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(2000)), Answer::NotFound); + assert_eq!( + cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(100)), + Answer::RateLimited + ); + assert_eq!( + cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(2000)), + Answer::NotFound + ); } } diff --git a/src/iface/route.rs b/src/iface/route.rs index e37c6a1..a6704cc 100644 --- a/src/iface/route.rs +++ b/src/iface/route.rs @@ -1,13 +1,13 @@ -use managed::ManagedMap; use crate::time::Instant; use core::ops::Bound; +use managed::ManagedMap; -use crate::{Error, Result}; -use crate::wire::{IpCidr, IpAddress}; +use crate::wire::{IpAddress, IpCidr}; #[cfg(feature = "proto-ipv4")] use crate::wire::{Ipv4Address, Ipv4Cidr}; #[cfg(feature = "proto-ipv6")] use crate::wire::{Ipv6Address, Ipv6Cidr}; +use crate::{Error, Result}; /// A prefix of addresses that should be routed via a router #[derive(Debug, Clone, Copy)] @@ -70,7 +70,9 @@ impl<'a> Routes<'a> { /// Creates a routing tables. The backing storage is **not** cleared /// upon creation. pub fn new(storage: T) -> Routes<'a> - where T: Into> { + where + T: Into>, + { let storage = storage.into(); Routes { storage } } @@ -89,7 +91,7 @@ impl<'a> Routes<'a> { let route = Route::new_ipv4_gateway(gateway); match self.storage.insert(cidr, route) { Ok(route) => Ok(route), - Err((_cidr, _route)) => Err(Error::Exhausted) + Err((_cidr, _route)) => Err(Error::Exhausted), } } @@ -102,7 +104,7 @@ impl<'a> Routes<'a> { let route = Route::new_ipv6_gateway(gateway); match self.storage.insert(cidr, route) { Ok(route) => Ok(route), - Err((_cidr, _route)) => Err(Error::Exhausted) + Err((_cidr, _route)) => Err(Error::Exhausted), } } @@ -124,8 +126,7 @@ impl<'a> Routes<'a> { self.storage.remove(&cidr) } - pub(crate) fn lookup(&self, addr: &IpAddress, timestamp: Instant) -> - Option { + pub(crate) fn lookup(&self, addr: &IpAddress, timestamp: Instant) -> Option { assert!(addr.is_unicast()); let cidr = match addr { @@ -133,10 +134,14 @@ impl<'a> Routes<'a> { IpAddress::Ipv4(addr) => IpCidr::Ipv4(Ipv4Cidr::new(*addr, 32)), #[cfg(feature = "proto-ipv6")] IpAddress::Ipv6(addr) => IpCidr::Ipv6(Ipv6Cidr::new(*addr, 128)), - _ => unimplemented!() + _ => unimplemented!(), }; - for (prefix, route) in self.storage.range((Bound::Unbounded::, Bound::Included(cidr))).rev() { + for (prefix, route) in self + .storage + .range((Bound::Unbounded::, Bound::Included(cidr))) + .rev() + { // TODO: do something with route.preferred_until if let Some(expires_at) = route.expires_at { if timestamp > expires_at { @@ -159,24 +164,28 @@ 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([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 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([0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 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([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 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([0xfe, 0x80, 0, 0, 0, 0, 51, 100, 0, 0, 0, 0, 0, 0, 0, 0]), + 64, + ) } } @@ -204,25 +213,56 @@ mod test { let mut routes_storage = [None, None, None]; let mut routes = Routes::new(&mut routes_storage[..]); - assert_eq!(routes.lookup(&ADDR_1A.into(), Instant::from_millis(0)), None); - assert_eq!(routes.lookup(&ADDR_1B.into(), Instant::from_millis(0)), None); - assert_eq!(routes.lookup(&ADDR_1C.into(), Instant::from_millis(0)), None); - assert_eq!(routes.lookup(&ADDR_2A.into(), Instant::from_millis(0)), None); - assert_eq!(routes.lookup(&ADDR_2B.into(), Instant::from_millis(0)), None); + assert_eq!( + routes.lookup(&ADDR_1A.into(), Instant::from_millis(0)), + None + ); + assert_eq!( + routes.lookup(&ADDR_1B.into(), Instant::from_millis(0)), + None + ); + assert_eq!( + routes.lookup(&ADDR_1C.into(), Instant::from_millis(0)), + None + ); + assert_eq!( + routes.lookup(&ADDR_2A.into(), Instant::from_millis(0)), + None + ); + assert_eq!( + routes.lookup(&ADDR_2B.into(), Instant::from_millis(0)), + None + ); let route = Route { via_router: ADDR_1A.into(), - preferred_until: None, expires_at: None, + preferred_until: None, + expires_at: None, }; routes.update(|storage| { storage.insert(cidr_1().into(), route).unwrap(); }); - assert_eq!(routes.lookup(&ADDR_1A.into(), Instant::from_millis(0)), Some(ADDR_1A.into())); - assert_eq!(routes.lookup(&ADDR_1B.into(), Instant::from_millis(0)), Some(ADDR_1A.into())); - assert_eq!(routes.lookup(&ADDR_1C.into(), Instant::from_millis(0)), Some(ADDR_1A.into())); - assert_eq!(routes.lookup(&ADDR_2A.into(), Instant::from_millis(0)), None); - assert_eq!(routes.lookup(&ADDR_2B.into(), Instant::from_millis(0)), None); + assert_eq!( + routes.lookup(&ADDR_1A.into(), Instant::from_millis(0)), + Some(ADDR_1A.into()) + ); + assert_eq!( + routes.lookup(&ADDR_1B.into(), Instant::from_millis(0)), + Some(ADDR_1A.into()) + ); + assert_eq!( + routes.lookup(&ADDR_1C.into(), Instant::from_millis(0)), + Some(ADDR_1A.into()) + ); + assert_eq!( + routes.lookup(&ADDR_2A.into(), Instant::from_millis(0)), + None + ); + assert_eq!( + routes.lookup(&ADDR_2B.into(), Instant::from_millis(0)), + None + ); let route2 = Route { via_router: ADDR_2A.into(), @@ -233,16 +273,46 @@ mod test { storage.insert(cidr_2().into(), route2).unwrap(); }); - assert_eq!(routes.lookup(&ADDR_1A.into(), Instant::from_millis(0)), Some(ADDR_1A.into())); - assert_eq!(routes.lookup(&ADDR_1B.into(), Instant::from_millis(0)), Some(ADDR_1A.into())); - assert_eq!(routes.lookup(&ADDR_1C.into(), Instant::from_millis(0)), Some(ADDR_1A.into())); - assert_eq!(routes.lookup(&ADDR_2A.into(), Instant::from_millis(0)), Some(ADDR_2A.into())); - assert_eq!(routes.lookup(&ADDR_2B.into(), Instant::from_millis(0)), Some(ADDR_2A.into())); + assert_eq!( + routes.lookup(&ADDR_1A.into(), Instant::from_millis(0)), + Some(ADDR_1A.into()) + ); + assert_eq!( + routes.lookup(&ADDR_1B.into(), Instant::from_millis(0)), + Some(ADDR_1A.into()) + ); + assert_eq!( + routes.lookup(&ADDR_1C.into(), Instant::from_millis(0)), + Some(ADDR_1A.into()) + ); + assert_eq!( + routes.lookup(&ADDR_2A.into(), Instant::from_millis(0)), + Some(ADDR_2A.into()) + ); + assert_eq!( + routes.lookup(&ADDR_2B.into(), Instant::from_millis(0)), + Some(ADDR_2A.into()) + ); - assert_eq!(routes.lookup(&ADDR_1A.into(), Instant::from_millis(10)), Some(ADDR_1A.into())); - assert_eq!(routes.lookup(&ADDR_1B.into(), Instant::from_millis(10)), Some(ADDR_1A.into())); - assert_eq!(routes.lookup(&ADDR_1C.into(), Instant::from_millis(10)), Some(ADDR_1A.into())); - assert_eq!(routes.lookup(&ADDR_2A.into(), Instant::from_millis(10)), Some(ADDR_2A.into())); - assert_eq!(routes.lookup(&ADDR_2B.into(), Instant::from_millis(10)), Some(ADDR_2A.into())); + assert_eq!( + routes.lookup(&ADDR_1A.into(), Instant::from_millis(10)), + Some(ADDR_1A.into()) + ); + assert_eq!( + routes.lookup(&ADDR_1B.into(), Instant::from_millis(10)), + Some(ADDR_1A.into()) + ); + assert_eq!( + routes.lookup(&ADDR_1C.into(), Instant::from_millis(10)), + Some(ADDR_1A.into()) + ); + assert_eq!( + routes.lookup(&ADDR_2A.into(), Instant::from_millis(10)), + Some(ADDR_2A.into()) + ); + assert_eq!( + routes.lookup(&ADDR_2B.into(), Instant::from_millis(10)), + Some(ADDR_2A.into()) + ); } } diff --git a/src/lib.rs b/src/lib.rs index 4c8e93f..c0fd0fa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,12 @@ #![cfg_attr(not(any(test, feature = "std")), no_std)] #![deny(unsafe_code)] -#![cfg_attr(all(any(feature = "proto-ipv4", feature = "proto-ipv6"), feature = "medium-ethernet"), deny(unused))] +#![cfg_attr( + all( + any(feature = "proto-ipv4", feature = "proto-ipv6"), + feature = "medium-ethernet" + ), + deny(unused) +)] //! The _smoltcp_ library is built in a layered structure, with the layers corresponding //! to the levels of API abstraction. Only the highest layers would be used by a typical @@ -107,10 +113,7 @@ compile_error!("If you enable the socket feature, you must enable at least one o #[cfg(all( feature = "socket", - not(any( - feature = "medium-ethernet", - feature = "medium-ip", - )) + not(any(feature = "medium-ethernet", feature = "medium-ip",)) ))] compile_error!("If you enable the socket feature, you must enable at least one of the following features: medium-ip, medium-ethernet"); @@ -123,13 +126,13 @@ use core::fmt; mod macros; mod parsers; -pub mod storage; -pub mod phy; -pub mod wire; pub mod iface; +pub mod phy; #[cfg(feature = "socket")] pub mod socket; +pub mod storage; pub mod time; +pub mod wire; /// The error type for the networking stack. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -178,16 +181,16 @@ pub type Result = core::result::Result; impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Error::Exhausted => write!(f, "buffer space exhausted"), - Error::Illegal => write!(f, "illegal operation"), + Error::Exhausted => write!(f, "buffer space exhausted"), + Error::Illegal => write!(f, "illegal operation"), Error::Unaddressable => write!(f, "unaddressable destination"), - Error::Finished => write!(f, "operation finished"), - Error::Truncated => write!(f, "truncated packet"), - Error::Checksum => write!(f, "checksum error"), - Error::Unrecognized => write!(f, "unrecognized packet"), - Error::Fragmented => write!(f, "fragmented packet"), - Error::Malformed => write!(f, "malformed packet"), - Error::Dropped => write!(f, "dropped by socket"), + Error::Finished => write!(f, "operation finished"), + Error::Truncated => write!(f, "truncated packet"), + Error::Checksum => write!(f, "checksum error"), + Error::Unrecognized => write!(f, "unrecognized packet"), + Error::Fragmented => write!(f, "fragmented packet"), + Error::Malformed => write!(f, "malformed packet"), + Error::Dropped => write!(f, "dropped by socket"), } } } diff --git a/src/macros.rs b/src/macros.rs index 28e49ee..3dc8305 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,4 +1,3 @@ - #[cfg(feature = "log")] macro_rules! net_log { (trace, $($arg:expr),*) => { log::trace!($($arg),*); }; diff --git a/src/parsers.rs b/src/parsers.rs index 136e58b..bc6175e 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -1,7 +1,10 @@ -#![cfg_attr(not(all(feature = "proto-ipv6", feature = "proto-ipv4")), allow(dead_code))] +#![cfg_attr( + not(all(feature = "proto-ipv6", feature = "proto-ipv4")), + allow(dead_code) +)] -use core::str::FromStr; use core::result; +use core::str::FromStr; #[cfg(feature = "medium-ethernet")] use crate::wire::EthernetAddress; @@ -15,14 +18,14 @@ type Result = result::Result; struct Parser<'a> { data: &'a [u8], - pos: usize + pos: usize, } impl<'a> Parser<'a> { fn new(data: &'a str) -> Parser<'a> { Parser { data: data.as_bytes(), - pos: 0 + pos: 0, } } @@ -40,12 +43,14 @@ impl<'a> Parser<'a> { self.pos += 1; Ok(chr) } - None => Err(()) + None => Err(()), } } fn try_do(&mut self, f: F) -> Option - where F: FnOnce(&mut Parser<'a>) -> Result { + where + F: FnOnce(&mut Parser<'a>) -> Result, + { let pos = self.pos; match f(self) { Ok(res) => Some(res), @@ -65,7 +70,9 @@ impl<'a> Parser<'a> { } fn until_eof(&mut self, f: F) -> Result - where F: FnOnce(&mut Parser<'a>) -> Result { + where + F: FnOnce(&mut Parser<'a>) -> Result, + { let res = f(self)?; self.accept_eof()?; Ok(res) @@ -99,8 +106,7 @@ impl<'a> Parser<'a> { } } - fn accept_number(&mut self, max_digits: usize, max_value: u32, - hex: bool) -> Result { + fn accept_number(&mut self, max_digits: usize, max_value: u32, hex: bool) -> Result { let mut value = self.accept_digit(hex)? as u32; for _ in 1..max_digits { match self.try_do(|p| p.accept_digit(hex)) { @@ -108,7 +114,7 @@ impl<'a> Parser<'a> { value *= if hex { 16 } else { 10 }; value += digit as u32; } - None => break + None => break, } } if value < max_value { @@ -133,10 +139,10 @@ impl<'a> Parser<'a> { #[cfg(feature = "medium-ethernet")] fn accept_mac(&mut self) -> Result { if let Some(mac) = self.try_do(|p| p.accept_mac_joined_with(b'-')) { - return Ok(mac) + return Ok(mac); } if let Some(mac) = self.try_do(|p| p.accept_mac_joined_with(b':')) { - return Ok(mac) + return Ok(mac); } Err(()) } @@ -154,9 +160,13 @@ impl<'a> Parser<'a> { } #[cfg(feature = "proto-ipv6")] - fn accept_ipv6_part(&mut self, (head, tail): (&mut [u16; 8], &mut [u16; 6]), - (head_idx, tail_idx): (&mut usize, &mut usize), - mut use_tail: bool, is_cidr: bool) -> Result<()> { + fn accept_ipv6_part( + &mut self, + (head, tail): (&mut [u16; 8], &mut [u16; 6]), + (head_idx, tail_idx): (&mut usize, &mut usize), + mut use_tail: bool, + is_cidr: bool, + ) -> Result<()> { let double_colon = match self.try_do(|p| p.accept_str(b"::")) { Some(_) if !use_tail && *head_idx < 7 => { // Found a double colon. Start filling out the @@ -164,7 +174,7 @@ impl<'a> Parser<'a> { // this is the last character we can parse. use_tail = true; true - }, + } Some(_) => { // This is a bad address. Only one double colon is // allowed and an address is only 128 bits. @@ -193,21 +203,20 @@ impl<'a> Parser<'a> { }); } Ok(()) - }, + } Some(part) if *tail_idx < 6 => { // Valid u16 to be added to the address tail[*tail_idx] = part as u16; *tail_idx += 1; - if *tail_idx == 1 && tail[0] == 0xffff - && head[0..8] == [0, 0, 0, 0, 0, 0, 0, 0] { + if *tail_idx == 1 && tail[0] == 0xffff && head[0..8] == [0, 0, 0, 0, 0, 0, 0, 0] { self.try_do(|p| { p.accept_char(b':')?; p.accept_ipv4_mapped_ipv6_part(tail, tail_idx) }); } Ok(()) - }, + } Some(_) => { // Tail or head section is too long Err(()) @@ -259,7 +268,12 @@ impl<'a> Parser<'a> { let (mut addr, mut tail) = ([0u16; 8], [0u16; 6]); let (mut head_idx, mut tail_idx) = (0, 0); - self.accept_ipv6_part((&mut addr, &mut tail), (&mut head_idx, &mut tail_idx), false, is_cidr)?; + self.accept_ipv6_part( + (&mut addr, &mut tail), + (&mut head_idx, &mut tail_idx), + false, + is_cidr, + )?; // We need to copy the tail portion (the portion following the "::") to the // end of the address. @@ -290,14 +304,14 @@ impl<'a> Parser<'a> { #[allow(clippy::single_match)] match self.try_do(|p| p.accept_ipv4()) { Some(ipv4) => return Ok(IpAddress::Ipv4(ipv4)), - None => () + None => (), } #[cfg(feature = "proto-ipv6")] #[allow(clippy::single_match)] match self.try_do(|p| p.accept_ipv6(false)) { Some(ipv6) => return Ok(IpAddress::Ipv6(ipv6)), - None => () + None => (), } Err(()) @@ -314,7 +328,10 @@ impl<'a> Parser<'a> { self.accept_number(5, 65535, false)? }; - Ok(IpEndpoint { addr: IpAddress::Ipv4(ip), port: port as u16 }) + Ok(IpEndpoint { + addr: IpAddress::Ipv4(ip), + port: port as u16, + }) } #[cfg(feature = "proto-ipv6")] @@ -326,10 +343,16 @@ impl<'a> Parser<'a> { self.accept_char(b':')?; let port = self.accept_number(5, 65535, false)?; - Ok(IpEndpoint { addr: IpAddress::Ipv6(ip), port: port as u16 }) + Ok(IpEndpoint { + addr: IpAddress::Ipv6(ip), + port: port as u16, + }) } else { let ip = self.accept_ipv6(false)?; - Ok(IpEndpoint { addr: IpAddress::Ipv6(ip), port: 0 }) + Ok(IpEndpoint { + addr: IpAddress::Ipv6(ip), + port: 0, + }) } } @@ -338,14 +361,14 @@ impl<'a> Parser<'a> { #[allow(clippy::single_match)] match self.try_do(|p| p.accept_ipv4_endpoint()) { Some(ipv4) => return Ok(ipv4), - None => () + None => (), } #[cfg(feature = "proto-ipv6")] #[allow(clippy::single_match)] match self.try_do(|p| p.accept_ipv6_endpoint()) { Some(ipv6) => return Ok(ipv6), - None => () + None => (), } Err(()) @@ -431,14 +454,14 @@ impl FromStr for IpCidr { #[allow(clippy::single_match)] match Ipv4Cidr::from_str(s) { Ok(cidr) => return Ok(IpCidr::Ipv4(cidr)), - Err(_) => () + Err(_) => (), } #[cfg(feature = "proto-ipv6")] #[allow(clippy::single_match)] match Ipv6Cidr::from_str(s) { Ok(cidr) => return Ok(IpCidr::Ipv6(cidr)), - Err(_) => () + Err(_) => (), } Err(()) @@ -465,29 +488,40 @@ mod test { if let Ok(cidr) = cidr { assert_eq!($from_str(&format!("{}", cidr)), Ok(cidr)); - assert_eq!(IpCidr::from_str(&format!("{}", cidr)), - Ok($variant(cidr))); + assert_eq!(IpCidr::from_str(&format!("{}", cidr)), Ok($variant(cidr))); } } - } + }; } #[test] #[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))] fn test_mac() { assert_eq!(EthernetAddress::from_str(""), Err(())); - assert_eq!(EthernetAddress::from_str("02:00:00:00:00:00"), - Ok(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x00]))); - assert_eq!(EthernetAddress::from_str("01:23:45:67:89:ab"), - Ok(EthernetAddress([0x01, 0x23, 0x45, 0x67, 0x89, 0xab]))); - assert_eq!(EthernetAddress::from_str("cd:ef:10:00:00:00"), - Ok(EthernetAddress([0xcd, 0xef, 0x10, 0x00, 0x00, 0x00]))); - assert_eq!(EthernetAddress::from_str("00:00:00:ab:cd:ef"), - Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef]))); - assert_eq!(EthernetAddress::from_str("00-00-00-ab-cd-ef"), - Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef]))); - assert_eq!(EthernetAddress::from_str("AB-CD-EF-00-00-00"), - Ok(EthernetAddress([0xab, 0xcd, 0xef, 0x00, 0x00, 0x00]))); + assert_eq!( + EthernetAddress::from_str("02:00:00:00:00:00"), + Ok(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x00])) + ); + assert_eq!( + EthernetAddress::from_str("01:23:45:67:89:ab"), + Ok(EthernetAddress([0x01, 0x23, 0x45, 0x67, 0x89, 0xab])) + ); + assert_eq!( + EthernetAddress::from_str("cd:ef:10:00:00:00"), + Ok(EthernetAddress([0xcd, 0xef, 0x10, 0x00, 0x00, 0x00])) + ); + assert_eq!( + EthernetAddress::from_str("00:00:00:ab:cd:ef"), + Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef])) + ); + assert_eq!( + EthernetAddress::from_str("00-00-00-ab-cd-ef"), + Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef])) + ); + assert_eq!( + EthernetAddress::from_str("AB-CD-EF-00-00-00"), + Ok(EthernetAddress([0xab, 0xcd, 0xef, 0x00, 0x00, 0x00])) + ); assert_eq!(EthernetAddress::from_str("100:00:00:00:00:00"), Err(())); assert_eq!(EthernetAddress::from_str("002:00:00:00:00:00"), Err(())); assert_eq!(EthernetAddress::from_str("02:00:00:00:00:000"), Err(())); @@ -498,10 +532,14 @@ mod 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("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(())); @@ -515,73 +553,87 @@ mod test { 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))); + 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(())); + 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(())); + 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(())); + 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(())); + 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(())); + assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1"), Err(())); // Long number - assert_eq!(Ipv6Address::from_str("::000001"), - Err(())); + 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]))); + 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(())); + 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(())); + 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(())); + 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(())); + 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])))); + assert_eq!( + IpAddress::from_str("1.2.3.4"), + Ok(IpAddress::Ipv4(Ipv4Address([1, 2, 3, 4]))) + ); assert_eq!(IpAddress::from_str("x"), Err(())); } @@ -589,8 +641,12 @@ mod test { #[cfg(feature = "proto-ipv6")] fn test_ip_ipv6() { assert_eq!(IpAddress::from_str(""), Err(())); - assert_eq!(IpAddress::from_str("fe80::1"), - Ok(IpAddress::Ipv6(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)))); + assert_eq!( + IpAddress::from_str("fe80::1"), + Ok(IpAddress::Ipv6(Ipv6Address::new( + 0xfe80, 0, 0, 0, 0, 0, 0, 1 + ))) + ); assert_eq!(IpAddress::from_str("x"), Err(())); } @@ -598,14 +654,22 @@ mod test { #[cfg(feature = "proto-ipv4")] fn test_cidr_ipv4() { let tests = [ - ("127.0.0.1/8", - Ok(Ipv4Cidr::new(Ipv4Address([127, 0, 0, 1]), 8u8))), - ("192.168.1.1/24", - Ok(Ipv4Cidr::new(Ipv4Address([192, 168, 1, 1]), 24u8))), - ("8.8.8.8/32", - Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 32u8))), - ("8.8.8.8/0", - Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 0u8))), + ( + "127.0.0.1/8", + Ok(Ipv4Cidr::new(Ipv4Address([127, 0, 0, 1]), 8u8)), + ), + ( + "192.168.1.1/24", + Ok(Ipv4Cidr::new(Ipv4Address([192, 168, 1, 1]), 24u8)), + ), + ( + "8.8.8.8/32", + Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 32u8)), + ), + ( + "8.8.8.8/0", + Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 0u8)), + ), ("", Err(())), ("1", Err(())), ("127.0.0.1", Err(())), @@ -622,22 +686,32 @@ mod test { #[cfg(feature = "proto-ipv6")] fn test_cidr_ipv6() { let tests = [ - ("fe80::1/64", - Ok(Ipv6Cidr::new(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64u8))), - ("fe80::/64", - Ok(Ipv6Cidr::new(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0), 64u8))), - ("::1/128", - Ok(Ipv6Cidr::new(Ipv6Address::LOOPBACK, 128u8))), - ("::/128", - Ok(Ipv6Cidr::new(Ipv6Address::UNSPECIFIED, 128u8))), - ("fe80:0:0:0:0:0:0:1/64", - Ok(Ipv6Cidr::new(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64u8))), - ("fe80:0:0:0:0:0:0:1|64", - Err(())), - ("fe80::|64", - Err(())), - ("fe80::1::/64", - Err(())) + ( + "fe80::1/64", + Ok(Ipv6Cidr::new( + Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), + 64u8, + )), + ), + ( + "fe80::/64", + Ok(Ipv6Cidr::new( + Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0), + 64u8, + )), + ), + ("::1/128", Ok(Ipv6Cidr::new(Ipv6Address::LOOPBACK, 128u8))), + ("::/128", Ok(Ipv6Cidr::new(Ipv6Address::UNSPECIFIED, 128u8))), + ( + "fe80:0:0:0:0:0:0:1/64", + Ok(Ipv6Cidr::new( + Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), + 64u8, + )), + ), + ("fe80:0:0:0:0:0:0:1|64", Err(())), + ("fe80::|64", Err(())), + ("fe80::1::/64", Err(())), ]; check_cidr_test_array!(tests, Ipv6Cidr::from_str, IpCidr::Ipv6); } @@ -649,11 +723,17 @@ mod test { assert_eq!(IpEndpoint::from_str("x"), Err(())); assert_eq!( IpEndpoint::from_str("127.0.0.1"), - Ok(IpEndpoint { addr: IpAddress::v4(127, 0, 0, 1), port: 0 }) + Ok(IpEndpoint { + addr: IpAddress::v4(127, 0, 0, 1), + port: 0 + }) ); assert_eq!( IpEndpoint::from_str("127.0.0.1:12345"), - Ok(IpEndpoint { addr: IpAddress::v4(127, 0, 0, 1), port: 12345 }) + Ok(IpEndpoint { + addr: IpAddress::v4(127, 0, 0, 1), + port: 12345 + }) ); } @@ -664,11 +744,17 @@ mod test { assert_eq!(IpEndpoint::from_str("x"), Err(())); assert_eq!( IpEndpoint::from_str("fe80::1"), - Ok(IpEndpoint { addr: IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), port: 0 }) + Ok(IpEndpoint { + addr: IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), + port: 0 + }) ); assert_eq!( IpEndpoint::from_str("[fe80::1]:12345"), - Ok(IpEndpoint { addr: IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), port: 12345 }) + Ok(IpEndpoint { + addr: IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), + port: 12345 + }) ); } } diff --git a/src/phy/fault_injector.rs b/src/phy/fault_injector.rs index 8c2e4aa..49cc7ca 100644 --- a/src/phy/fault_injector.rs +++ b/src/phy/fault_injector.rs @@ -1,8 +1,8 @@ use core::cell::RefCell; -use crate::{Error, Result}; -use crate::phy::{self, DeviceCapabilities, Device}; +use crate::phy::{self, Device, DeviceCapabilities}; use crate::time::{Duration, Instant}; +use crate::{Error, Result}; // We use our own RNG to stay compatible with #![no_std]. // The use of the RNG below has a slight bias, but it doesn't matter. @@ -22,21 +22,21 @@ const MTU: usize = 1536; #[cfg_attr(feature = "defmt", derive(defmt::Format))] struct Config { corrupt_pct: u8, - drop_pct: u8, + drop_pct: u8, reorder_pct: u8, - max_size: usize, + max_size: usize, max_tx_rate: u64, max_rx_rate: u64, - interval: Duration, + interval: Duration, } #[derive(Debug, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] struct State { - rng_seed: u32, + rng_seed: u32, refilled_at: Instant, - tx_bucket: u64, - rx_bucket: u64, + tx_bucket: u64, + rx_bucket: u64, } impl State { @@ -48,7 +48,7 @@ impl State { let buffer = buffer.as_mut(); // We introduce a single bitflip, as the most likely, and the hardest to detect, error. let index = (xorshift32(&mut self.rng_seed) as usize) % buffer.len(); - let bit = 1 << (xorshift32(&mut self.rng_seed) % 8) as u8; + let bit = 1 << (xorshift32(&mut self.rng_seed) % 8) as u8; buffer[index] ^= bit; } @@ -61,7 +61,9 @@ impl State { } fn maybe_transmit(&mut self, config: &Config, timestamp: Instant) -> bool { - if config.max_tx_rate == 0 { return true } + if config.max_tx_rate == 0 { + return true; + } self.refill(config, timestamp); if self.tx_bucket > 0 { @@ -73,7 +75,9 @@ impl State { } fn maybe_receive(&mut self, config: &Config, timestamp: Instant) -> bool { - if config.max_rx_rate == 0 { return true } + if config.max_rx_rate == 0 { + return true; + } self.refill(config, timestamp); if self.rx_bucket > 0 { @@ -92,19 +96,19 @@ impl State { /// or hardware limitations (such as a limited number or size of usable network buffers). #[derive(Debug)] pub struct FaultInjector Device<'a>> { - inner: D, - state: RefCell, - config: Config, + inner: D, + state: RefCell, + config: Config, } impl Device<'a>> FaultInjector { /// Create a fault injector device, using the given random number generator seed. pub fn new(inner: D, seed: u32) -> FaultInjector { let state = State { - rng_seed: seed, + rng_seed: seed, refilled_at: Instant::from_millis(0), - tx_bucket: 0, - rx_bucket: 0, + tx_bucket: 0, + rx_bucket: 0, }; FaultInjector { inner: inner, @@ -153,7 +157,9 @@ impl Device<'a>> FaultInjector { /// # Panics /// This function panics if the probability is not between 0% and 100%. pub fn set_corrupt_chance(&mut self, pct: u8) { - if pct > 100 { panic!("percentage out of range") } + if pct > 100 { + panic!("percentage out of range") + } self.config.corrupt_pct = pct } @@ -162,7 +168,9 @@ impl Device<'a>> FaultInjector { /// # Panics /// This function panics if the probability is not between 0% and 100%. pub fn set_drop_chance(&mut self, pct: u8) { - if pct > 100 { panic!("percentage out of range") } + if pct > 100 { + panic!("percentage out of range") + } self.config.drop_pct = pct } @@ -189,7 +197,8 @@ impl Device<'a>> FaultInjector { } impl<'a, D> Device<'a> for FaultInjector - where D: for<'b> Device<'b>, +where + D: for<'b> Device<'b>, { type RxToken = RxToken<'a, >::RxToken>; type TxToken = TxToken<'a, >::TxToken>; @@ -203,60 +212,78 @@ impl<'a, D> Device<'a> for FaultInjector } fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { - let &mut Self { ref mut inner, ref state, config } = self; + let &mut Self { + ref mut inner, + ref state, + config, + } = self; inner.receive().map(|(rx_token, tx_token)| { let rx = RxToken { - state: &state, - config: config, - token: rx_token, + state: &state, + config: config, + token: rx_token, corrupt: [0; MTU], }; let tx = TxToken { - state: &state, - config: config, - token: tx_token, - junk: [0; MTU], + state: &state, + config: config, + token: tx_token, + junk: [0; MTU], }; (rx, tx) }) } fn transmit(&'a mut self) -> Option { - let &mut Self { ref mut inner, ref state, config } = self; + let &mut Self { + ref mut inner, + ref state, + config, + } = self; inner.transmit().map(|token| TxToken { - state: &state, + state: &state, config: config, token: token, - junk: [0; MTU], + junk: [0; MTU], }) } } #[doc(hidden)] pub struct RxToken<'a, Rx: phy::RxToken> { - state: &'a RefCell, - config: Config, - token: Rx, + state: &'a RefCell, + config: Config, + token: Rx, corrupt: [u8; MTU], } impl<'a, Rx: phy::RxToken> phy::RxToken for RxToken<'a, Rx> { fn consume(self, timestamp: Instant, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result + where + F: FnOnce(&mut [u8]) -> Result, { if self.state.borrow_mut().maybe(self.config.drop_pct) { net_trace!("rx: randomly dropping a packet"); - return Err(Error::Exhausted) + return Err(Error::Exhausted); } - if !self.state.borrow_mut().maybe_receive(&self.config, timestamp) { + if !self + .state + .borrow_mut() + .maybe_receive(&self.config, timestamp) + { net_trace!("rx: dropping a packet because of rate limiting"); - return Err(Error::Exhausted) + return Err(Error::Exhausted); } - let Self { token, config, state, mut corrupt } = self; + let Self { + token, + config, + state, + mut corrupt, + } = self; token.consume(timestamp, |buffer| { if config.max_size > 0 && buffer.as_ref().len() > config.max_size { net_trace!("rx: dropping a packet that is too large"); - return Err(Error::Exhausted) + return Err(Error::Exhausted); } if state.borrow_mut().maybe(config.corrupt_pct) { net_trace!("rx: randomly corrupting a packet"); @@ -273,15 +300,16 @@ impl<'a, Rx: phy::RxToken> phy::RxToken for RxToken<'a, Rx> { #[doc(hidden)] pub struct TxToken<'a, Tx: phy::TxToken> { - state: &'a RefCell, + state: &'a RefCell, config: Config, - token: Tx, - junk: [u8; MTU], + token: Tx, + junk: [u8; MTU], } impl<'a, Tx: phy::TxToken> phy::TxToken for TxToken<'a, Tx> { fn consume(mut self, timestamp: Instant, len: usize, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result + where + F: FnOnce(&mut [u8]) -> Result, { let drop = if self.state.borrow_mut().maybe(self.config.drop_pct) { net_trace!("tx: randomly dropping a packet"); @@ -289,7 +317,11 @@ impl<'a, Tx: phy::TxToken> phy::TxToken for TxToken<'a, Tx> { } else if self.config.max_size > 0 && len > self.config.max_size { net_trace!("tx: dropping a packet that is too large"); true - } else if !self.state.borrow_mut().maybe_transmit(&self.config, timestamp) { + } else if !self + .state + .borrow_mut() + .maybe_transmit(&self.config, timestamp) + { net_trace!("tx: dropping a packet because of rate limiting"); true } else { @@ -300,7 +332,12 @@ impl<'a, Tx: phy::TxToken> phy::TxToken for TxToken<'a, Tx> { return f(&mut self.junk[..len]); } - let Self { token, state, config, .. } = self; + let Self { + token, + state, + config, + .. + } = self; token.consume(timestamp, len, |mut buf| { if state.borrow_mut().maybe(config.corrupt_pct) { net_trace!("tx: corrupting a packet"); diff --git a/src/phy/fuzz_injector.rs b/src/phy/fuzz_injector.rs index 5e2023b..b22b912 100644 --- a/src/phy/fuzz_injector.rs +++ b/src/phy/fuzz_injector.rs @@ -1,6 +1,6 @@ -use crate::Result; -use crate::phy::{self, DeviceCapabilities, Device}; +use crate::phy::{self, Device, DeviceCapabilities}; use crate::time::Instant; +use crate::Result; // This could be fixed once associated consts are stable. const MTU: usize = 1536; @@ -20,7 +20,7 @@ pub trait Fuzzer { #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct FuzzInjector Device<'a>, FTx: Fuzzer, FRx: Fuzzer> { - inner: D, + inner: D, fuzz_tx: FTx, fuzz_rx: FRx, } @@ -29,7 +29,11 @@ pub struct FuzzInjector Device<'a>, FTx: Fuzzer, FRx: Fuzzer> { impl Device<'a>, FTx: Fuzzer, FRx: Fuzzer> FuzzInjector { /// Create a fuzz injector device. pub fn new(inner: D, fuzz_tx: FTx, fuzz_rx: FRx) -> FuzzInjector { - FuzzInjector { inner, fuzz_tx, fuzz_rx } + FuzzInjector { + inner, + fuzz_tx, + fuzz_rx, + } } /// Return the underlying device, consuming the fuzz injector. @@ -39,9 +43,10 @@ impl Device<'a>, FTx: Fuzzer, FRx: Fuzzer> FuzzInjector } impl<'a, D, FTx, FRx> Device<'a> for FuzzInjector - where D: for<'b> Device<'b>, - FTx: Fuzzer + 'a, - FRx: Fuzzer + 'a +where + D: for<'b> Device<'b>, + FTx: Fuzzer + 'a, + FRx: Fuzzer + 'a, { type RxToken = RxToken<'a, >::RxToken, FRx>; type TxToken = TxToken<'a, >::TxToken, FTx>; @@ -55,38 +60,47 @@ impl<'a, D, FTx, FRx> Device<'a> for FuzzInjector } fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { - let &mut Self { ref mut inner, ref fuzz_rx, ref fuzz_tx } = self; + let &mut Self { + ref mut inner, + ref fuzz_rx, + ref fuzz_tx, + } = self; inner.receive().map(|(rx_token, tx_token)| { let rx = RxToken { fuzzer: fuzz_rx, - token: rx_token, + token: rx_token, }; let tx = TxToken { fuzzer: fuzz_tx, - token: tx_token, + token: tx_token, }; (rx, tx) }) } fn transmit(&'a mut self) -> Option { - let &mut Self { ref mut inner, fuzz_rx: _, ref fuzz_tx } = self; + let &mut Self { + ref mut inner, + fuzz_rx: _, + ref fuzz_tx, + } = self; inner.transmit().map(|token| TxToken { fuzzer: fuzz_tx, - token: token, + token: token, }) } } #[doc(hidden)] -pub struct RxToken<'a, Rx: phy::RxToken, F: Fuzzer + 'a>{ +pub struct RxToken<'a, Rx: phy::RxToken, F: Fuzzer + 'a> { fuzzer: &'a F, - token: Rx, + token: Rx, } impl<'a, Rx: phy::RxToken, FRx: Fuzzer> phy::RxToken for RxToken<'a, Rx, FRx> { fn consume(self, timestamp: Instant, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result + where + F: FnOnce(&mut [u8]) -> Result, { let Self { fuzzer, token } = self; token.consume(timestamp, |buffer| { @@ -99,12 +113,13 @@ impl<'a, Rx: phy::RxToken, FRx: Fuzzer> phy::RxToken for RxToken<'a, Rx, FRx> { #[doc(hidden)] pub struct TxToken<'a, Tx: phy::TxToken, F: Fuzzer + 'a> { fuzzer: &'a F, - token: Tx, + token: Tx, } impl<'a, Tx: phy::TxToken, FTx: Fuzzer> phy::TxToken for TxToken<'a, Tx, FTx> { fn consume(self, timestamp: Instant, len: usize, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result + where + F: FnOnce(&mut [u8]) -> Result, { let Self { fuzzer, token } = self; token.consume(timestamp, len, |mut buf| { diff --git a/src/phy/loopback.rs b/src/phy/loopback.rs index c44c97c..9b39aed 100644 --- a/src/phy/loopback.rs +++ b/src/phy/loopback.rs @@ -1,12 +1,12 @@ -use alloc::vec::Vec; #[cfg(not(feature = "rust-1_28"))] use alloc::collections::VecDeque; +use alloc::vec::Vec; #[cfg(feature = "rust-1_28")] use alloc::VecDeque; -use crate::Result; use crate::phy::{self, Device, DeviceCapabilities, Medium}; use crate::time::Instant; +use crate::Result; /// A loopback device. #[derive(Debug)] @@ -44,7 +44,9 @@ impl<'a> Device<'a> for Loopback { fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { self.queue.pop_front().map(move |buffer| { let rx = RxToken { buffer }; - let tx = TxToken { queue: &mut self.queue }; + let tx = TxToken { + queue: &mut self.queue, + }; (rx, tx) }) } @@ -63,7 +65,8 @@ pub struct RxToken { impl phy::RxToken for RxToken { fn consume(mut self, _timestamp: Instant, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result + where + F: FnOnce(&mut [u8]) -> Result, { f(&mut self.buffer) } @@ -76,7 +79,8 @@ pub struct TxToken<'a> { impl<'a> phy::TxToken for TxToken<'a> { fn consume(self, _timestamp: Instant, len: usize, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result + where + F: FnOnce(&mut [u8]) -> Result, { let mut buffer = Vec::new(); buffer.resize(len, 0); diff --git a/src/phy/mod.rs b/src/phy/mod.rs index 50cd774..c156d58 100644 --- a/src/phy/mod.rs +++ b/src/phy/mod.rs @@ -11,7 +11,9 @@ and implementations of it: [TunTapInterface](struct.TunTapInterface.html), to transmit and receive frames on the host OS. */ -#![cfg_attr(feature = "medium-ethernet", doc = r##" +#![cfg_attr( + feature = "medium-ethernet", + doc = r##" # Examples An implementation of the [Device](trait.Device.html) trait for a simple hardware @@ -84,37 +86,50 @@ impl<'a> phy::TxToken for StmPhyTxToken<'a> { } } ``` -"##)] +"## +)] -use crate::Result; use crate::time::Instant; +use crate::Result; -#[cfg(all(any(feature = "phy-raw_socket", feature = "phy-tuntap_interface"), unix))] +#[cfg(all( + any(feature = "phy-raw_socket", feature = "phy-tuntap_interface"), + unix +))] mod sys; -mod tracer; mod fault_injector; mod fuzz_injector; -mod pcap_writer; #[cfg(any(feature = "std", feature = "alloc"))] mod loopback; +mod pcap_writer; #[cfg(all(feature = "phy-raw_socket", unix))] mod raw_socket; -#[cfg(all(feature = "phy-tuntap_interface", any(target_os = "linux", target_os = "android")))] +mod tracer; +#[cfg(all( + feature = "phy-tuntap_interface", + any(target_os = "linux", target_os = "android") +))] mod tuntap_interface; -#[cfg(all(any(feature = "phy-raw_socket", feature = "phy-tuntap_interface"), unix))] +#[cfg(all( + any(feature = "phy-raw_socket", feature = "phy-tuntap_interface"), + unix +))] pub use self::sys::wait; -pub use self::tracer::Tracer; pub use self::fault_injector::FaultInjector; -pub use self::fuzz_injector::{Fuzzer, FuzzInjector}; -pub use self::pcap_writer::{PcapLinkType, PcapMode, PcapSink, PcapWriter}; +pub use self::fuzz_injector::{FuzzInjector, Fuzzer}; #[cfg(any(feature = "std", feature = "alloc"))] pub use self::loopback::Loopback; +pub use self::pcap_writer::{PcapLinkType, PcapMode, PcapSink, PcapWriter}; #[cfg(all(feature = "phy-raw_socket", unix))] pub use self::raw_socket::RawSocket; -#[cfg(all(feature = "phy-tuntap_interface", any(target_os = "linux", target_os = "android")))] +pub use self::tracer::Tracer; +#[cfg(all( + feature = "phy-tuntap_interface", + any(target_os = "linux", target_os = "android") +))] pub use self::tuntap_interface::TunTapInterface; /// A description of checksum behavior for a particular protocol. @@ -142,7 +157,7 @@ impl Checksum { pub fn rx(&self) -> bool { match *self { Checksum::Both | Checksum::Rx => true, - _ => false + _ => false, } } @@ -150,7 +165,7 @@ impl Checksum { pub fn tx(&self) -> bool { match *self { Checksum::Both | Checksum::Tx => true, - _ => false + _ => false, } } } @@ -234,7 +249,9 @@ impl DeviceCapabilities { pub fn ip_mtu(&self) -> usize { match self.medium { #[cfg(feature = "medium-ethernet")] - Medium::Ethernet => self.max_transmission_unit - crate::wire::EthernetFrame::<&[u8]>::header_len(), + Medium::Ethernet => { + self.max_transmission_unit - crate::wire::EthernetFrame::<&[u8]>::header_len() + } #[cfg(feature = "medium-ip")] Medium::Ip => self.max_transmission_unit, } @@ -260,7 +277,6 @@ pub enum Medium { Ip, } - impl Default for Medium { fn default() -> Medium { #[cfg(feature = "medium-ethernet")] @@ -306,7 +322,8 @@ pub trait RxToken { /// The timestamp must be a number of milliseconds, monotonically increasing since an /// arbitrary moment in time, such as system startup. fn consume(self, timestamp: Instant, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result; + where + F: FnOnce(&mut [u8]) -> Result; } /// A token to transmit a single network packet. @@ -321,5 +338,6 @@ pub trait TxToken { /// The timestamp must be a number of milliseconds, monotonically increasing since an /// arbitrary moment in time, such as system startup. fn consume(self, timestamp: Instant, len: usize, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result; + where + F: FnOnce(&mut [u8]) -> Result; } diff --git a/src/phy/pcap_writer.rs b/src/phy/pcap_writer.rs index a2226bb..2834e93 100644 --- a/src/phy/pcap_writer.rs +++ b/src/phy/pcap_writer.rs @@ -1,13 +1,13 @@ +use byteorder::{ByteOrder, NativeEndian}; +use phy::Medium; #[cfg(feature = "std")] use std::cell::RefCell; #[cfg(feature = "std")] use std::io::Write; -use byteorder::{ByteOrder, NativeEndian}; -use phy::Medium; -use crate::Result; -use crate::phy::{self, DeviceCapabilities, Device}; +use crate::phy::{self, Device, DeviceCapabilities}; use crate::time::Instant; +use crate::Result; enum_with_unknown! { /// Captured packet header type. @@ -28,7 +28,7 @@ pub enum PcapMode { /// Capture only received packets. RxOnly, /// Capture only transmitted packets. - TxOnly + TxOnly, } /// A packet capture sink. @@ -54,12 +54,12 @@ pub trait PcapSink { /// /// This method may be overridden e.g. if special synchronization is necessary. fn global_header(&self, link_type: PcapLinkType) { - self.write_u32(0xa1b2c3d4); // magic number - self.write_u16(2); // major version - self.write_u16(4); // minor version - self.write_u32(0); // timezone (= UTC) - self.write_u32(0); // accuracy (not used) - self.write_u32(65535); // maximum packet length + self.write_u32(0xa1b2c3d4); // magic number + self.write_u16(2); // major version + self.write_u16(4); // minor version + self.write_u32(0); // timezone (= UTC) + self.write_u32(0); // accuracy (not used) + self.write_u32(65535); // maximum packet length self.write_u32(link_type.into()); // link-layer header type } @@ -72,10 +72,10 @@ pub trait PcapSink { fn packet_header(&self, timestamp: Instant, length: usize) { assert!(length <= 65535); - self.write_u32(timestamp.secs() as u32); // timestamp seconds - self.write_u32(timestamp.millis() as u32); // timestamp microseconds - self.write_u32(length as u32); // captured length - self.write_u32(length as u32); // original length + self.write_u32(timestamp.secs() as u32); // timestamp seconds + self.write_u32(timestamp.millis() as u32); // timestamp microseconds + self.write_u32(length as u32); // captured length + self.write_u32(length as u32); // original length } /// Write the libpcap packet header followed by packet data into the sink. @@ -121,12 +121,13 @@ impl PcapSink for RefCell { #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PcapWriter - where D: for<'a> Device<'a>, - S: PcapSink + Clone, +where + D: for<'a> Device<'a>, + S: PcapSink + Clone, { lower: D, - sink: S, - mode: PcapMode, + sink: S, + mode: PcapMode, } impl Device<'a>, S: PcapSink + Clone> PcapWriter { @@ -145,27 +146,49 @@ impl Device<'a>, S: PcapSink + Clone> PcapWriter { } impl<'a, D, S> Device<'a> for PcapWriter - where D: for<'b> Device<'b>, - S: PcapSink + Clone + 'a, +where + D: for<'b> Device<'b>, + S: PcapSink + Clone + 'a, { type RxToken = RxToken<>::RxToken, S>; type TxToken = TxToken<>::TxToken, S>; - fn capabilities(&self) -> DeviceCapabilities { self.lower.capabilities() } + fn capabilities(&self) -> DeviceCapabilities { + self.lower.capabilities() + } fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { - let &mut Self { ref mut lower, ref sink, mode, .. } = self; + let &mut Self { + ref mut lower, + ref sink, + mode, + .. + } = self; lower.receive().map(|(rx_token, tx_token)| { - let rx = RxToken { token: rx_token, sink: sink.clone(), mode }; - let tx = TxToken { token: tx_token, sink: sink.clone(), mode }; + let rx = RxToken { + token: rx_token, + sink: sink.clone(), + mode, + }; + let tx = TxToken { + token: tx_token, + sink: sink.clone(), + mode, + }; (rx, tx) }) } fn transmit(&'a mut self) -> Option { - let &mut Self { ref mut lower, ref sink, mode } = self; - lower.transmit().map(|token| { - TxToken { token, sink: sink.clone(), mode } + let &mut Self { + ref mut lower, + ref sink, + mode, + } = self; + lower.transmit().map(|token| TxToken { + token, + sink: sink.clone(), + mode, }) } } @@ -173,8 +196,8 @@ impl<'a, D, S> Device<'a> for PcapWriter #[doc(hidden)] pub struct RxToken { token: Rx, - sink: S, - mode: PcapMode, + sink: S, + mode: PcapMode, } impl phy::RxToken for RxToken { @@ -182,9 +205,8 @@ impl phy::RxToken for RxToken { let Self { token, sink, mode } = self; token.consume(timestamp, |buffer| { match mode { - PcapMode::Both | PcapMode::RxOnly => - sink.packet(timestamp, buffer.as_ref()), - PcapMode::TxOnly => () + PcapMode::Both | PcapMode::RxOnly => sink.packet(timestamp, buffer.as_ref()), + PcapMode::TxOnly => (), } f(buffer) }) @@ -194,21 +216,21 @@ impl phy::RxToken for RxToken { #[doc(hidden)] pub struct TxToken { token: Tx, - sink: S, - mode: PcapMode + sink: S, + mode: PcapMode, } impl phy::TxToken for TxToken { fn consume(self, timestamp: Instant, len: usize, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result + where + F: FnOnce(&mut [u8]) -> Result, { let Self { token, sink, mode } = self; token.consume(timestamp, len, |buffer| { let result = f(buffer); match mode { - PcapMode::Both | PcapMode::TxOnly => - sink.packet(timestamp, &buffer), - PcapMode::RxOnly => () + PcapMode::Both | PcapMode::TxOnly => sink.packet(timestamp, &buffer), + PcapMode::RxOnly => (), }; result }) diff --git a/src/phy/raw_socket.rs b/src/phy/raw_socket.rs index b4d4e68..4c12635 100644 --- a/src/phy/raw_socket.rs +++ b/src/phy/raw_socket.rs @@ -1,18 +1,18 @@ use std::cell::RefCell; -use std::vec::Vec; -use std::rc::Rc; use std::io; -use std::os::unix::io::{RawFd, AsRawFd}; +use std::os::unix::io::{AsRawFd, RawFd}; +use std::rc::Rc; +use std::vec::Vec; -use crate::Result; -use crate::phy::{self, sys, DeviceCapabilities, Device, Medium}; +use crate::phy::{self, sys, Device, DeviceCapabilities, Medium}; use crate::time::Instant; +use crate::Result; /// A socket that captures or transmits the complete frame. #[derive(Debug)] pub struct RawSocket { - lower: Rc>, - mtu: usize + lower: Rc>, + mtu: usize, } impl AsRawFd for RawSocket { @@ -32,7 +32,7 @@ impl RawSocket { let mtu = lower.interface_mtu()?; Ok(RawSocket { lower: Rc::new(RefCell::new(lower)), - mtu: mtu + mtu: mtu, }) } } @@ -56,13 +56,13 @@ impl<'a> Device<'a> for RawSocket { Ok(size) => { buffer.resize(size, 0); let rx = RxToken { buffer }; - let tx = TxToken { lower: self.lower.clone() }; + let tx = TxToken { + lower: self.lower.clone(), + }; Some((rx, tx)) } - Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => { - None - } - Err(err) => panic!("{}", err) + Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => None, + Err(err) => panic!("{}", err), } } @@ -75,12 +75,13 @@ impl<'a> Device<'a> for RawSocket { #[doc(hidden)] pub struct RxToken { - buffer: Vec + buffer: Vec, } impl phy::RxToken for RxToken { fn consume(mut self, _timestamp: Instant, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result + where + F: FnOnce(&mut [u8]) -> Result, { f(&mut self.buffer[..]) } @@ -88,12 +89,13 @@ impl phy::RxToken for RxToken { #[doc(hidden)] pub struct TxToken { - lower: Rc>, + lower: Rc>, } impl phy::TxToken for TxToken { fn consume(self, _timestamp: Instant, len: usize, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result + where + F: FnOnce(&mut [u8]) -> Result, { let mut lower = self.lower.borrow_mut(); let mut buffer = vec![0; len]; diff --git a/src/phy/sys/bpf.rs b/src/phy/sys/bpf.rs index 0c1c519..4999f16 100644 --- a/src/phy/sys/bpf.rs +++ b/src/phy/sys/bpf.rs @@ -4,8 +4,8 @@ use std::os::unix::io::{AsRawFd, RawFd}; use libc; -use crate::wire::ETHERNET_HEADER_LEN; use super::{ifreq, ifreq_for}; +use crate::wire::ETHERNET_HEADER_LEN; /// set interface #[cfg(any(target_os = "macos", target_os = "openbsd"))] diff --git a/src/phy/sys/linux.rs b/src/phy/sys/linux.rs index d42d83f..58d819c 100644 --- a/src/phy/sys/linux.rs +++ b/src/phy/sys/linux.rs @@ -1,10 +1,10 @@ #![allow(unused)] -pub const SIOCGIFMTU: libc::c_ulong = 0x8921; +pub const SIOCGIFMTU: libc::c_ulong = 0x8921; pub const SIOCGIFINDEX: libc::c_ulong = 0x8933; -pub const ETH_P_ALL: libc::c_short = 0x0003; +pub const ETH_P_ALL: libc::c_short = 0x0003; -pub const TUNSETIFF: libc::c_ulong = 0x400454CA; -pub const IFF_TUN: libc::c_int = 0x0001; -pub const IFF_TAP: libc::c_int = 0x0002; -pub const IFF_NO_PI: libc::c_int = 0x1000; +pub const TUNSETIFF: libc::c_ulong = 0x400454CA; +pub const IFF_TUN: libc::c_int = 0x0001; +pub const IFF_TAP: libc::c_int = 0x0002; +pub const IFF_NO_PI: libc::c_int = 0x1000; diff --git a/src/phy/sys/mod.rs b/src/phy/sys/mod.rs index 8021879..3f42301 100644 --- a/src/phy/sys/mod.rs +++ b/src/phy/sys/mod.rs @@ -1,25 +1,45 @@ #![allow(unsafe_code)] -use std::{mem, ptr, io}; -use std::os::unix::io::RawFd; use crate::time::Duration; +use std::os::unix::io::RawFd; +use std::{io, mem, ptr}; #[cfg(any(target_os = "linux", target_os = "android"))] #[path = "linux.rs"] mod imp; -#[cfg(all(feature = "phy-raw_socket", any(target_os = "linux", target_os = "android")))] -pub mod raw_socket; -#[cfg(all(feature = "phy-raw_socket", not(any(target_os = "linux", target_os = "android")), unix))] +#[cfg(all( + feature = "phy-raw_socket", + not(any(target_os = "linux", target_os = "android")), + unix +))] pub mod bpf; -#[cfg(all(feature = "phy-tuntap_interface", any(target_os = "linux", target_os = "android")))] +#[cfg(all( + feature = "phy-raw_socket", + any(target_os = "linux", target_os = "android") +))] +pub mod raw_socket; +#[cfg(all( + feature = "phy-tuntap_interface", + any(target_os = "linux", target_os = "android") +))] pub mod tuntap_interface; -#[cfg(all(feature = "phy-raw_socket", any(target_os = "linux", target_os = "android")))] -pub use self::raw_socket::RawSocketDesc; -#[cfg(all(feature = "phy-raw_socket", not(any(target_os = "linux", target_os = "android")), unix))] +#[cfg(all( + feature = "phy-raw_socket", + not(any(target_os = "linux", target_os = "android")), + unix +))] pub use self::bpf::BpfDevice as RawSocketDesc; -#[cfg(all(feature = "phy-tuntap_interface", any(target_os = "linux", target_os = "android")))] +#[cfg(all( + feature = "phy-raw_socket", + any(target_os = "linux", target_os = "android") +))] +pub use self::raw_socket::RawSocketDesc; +#[cfg(all( + feature = "phy-tuntap_interface", + any(target_os = "linux", target_os = "android") +))] pub use self::tuntap_interface::TunTapInterfaceDesc; /// Wait until given file descriptor becomes readable, but no longer than given timeout. @@ -44,35 +64,51 @@ pub fn wait(fd: RawFd, duration: Option) -> io::Result<()> { exceptfds.assume_init() }; - let mut timeout = libc::timeval { tv_sec: 0, tv_usec: 0 }; - let timeout_ptr = - if let Some(duration) = duration { - timeout.tv_sec = duration.secs() as libc::time_t; - timeout.tv_usec = (duration.millis() * 1_000) as libc::suseconds_t; - &mut timeout as *mut _ - } else { - ptr::null_mut() - }; + let mut timeout = libc::timeval { + tv_sec: 0, + tv_usec: 0, + }; + let timeout_ptr = if let Some(duration) = duration { + timeout.tv_sec = duration.secs() as libc::time_t; + timeout.tv_usec = (duration.millis() * 1_000) as libc::suseconds_t; + &mut timeout as *mut _ + } else { + ptr::null_mut() + }; - let res = libc::select(fd + 1, &mut readfds, &mut writefds, &mut exceptfds, timeout_ptr); - if res == -1 { return Err(io::Error::last_os_error()) } + let res = libc::select( + fd + 1, + &mut readfds, + &mut writefds, + &mut exceptfds, + timeout_ptr, + ); + if res == -1 { + return Err(io::Error::last_os_error()); + } Ok(()) } } -#[cfg(all(any(feature = "phy-tuntap_interface", feature = "phy-raw_socket"), unix))] +#[cfg(all( + any(feature = "phy-tuntap_interface", feature = "phy-raw_socket"), + unix +))] #[repr(C)] #[derive(Debug)] struct ifreq { ifr_name: [libc::c_char; libc::IF_NAMESIZE], - ifr_data: libc::c_int /* ifr_ifindex or ifr_mtu */ + ifr_data: libc::c_int, /* ifr_ifindex or ifr_mtu */ } -#[cfg(all(any(feature = "phy-tuntap_interface", feature = "phy-raw_socket"), unix))] +#[cfg(all( + any(feature = "phy-tuntap_interface", feature = "phy-raw_socket"), + unix +))] fn ifreq_for(name: &str) -> ifreq { let mut ifreq = ifreq { ifr_name: [0; libc::IF_NAMESIZE], - ifr_data: 0 + ifr_data: 0, }; for (i, byte) in name.as_bytes().iter().enumerate() { ifreq.ifr_name[i] = *byte as libc::c_char @@ -80,13 +116,20 @@ fn ifreq_for(name: &str) -> ifreq { ifreq } -#[cfg(all(any(target_os = "linux", target_os = "android"), - any(feature = "phy-tuntap_interface", feature = "phy-raw_socket")))] -fn ifreq_ioctl(lower: libc::c_int, ifreq: &mut ifreq, - cmd: libc::c_ulong) -> io::Result { +#[cfg(all( + any(target_os = "linux", target_os = "android"), + any(feature = "phy-tuntap_interface", feature = "phy-raw_socket") +))] +fn ifreq_ioctl( + lower: libc::c_int, + ifreq: &mut ifreq, + cmd: libc::c_ulong, +) -> io::Result { unsafe { let res = libc::ioctl(lower, cmd as _, ifreq as *mut ifreq); - if res == -1 { return Err(io::Error::last_os_error()) } + if res == -1 { + return Err(io::Error::last_os_error()); + } } Ok(ifreq.ifr_data) diff --git a/src/phy/sys/raw_socket.rs b/src/phy/sys/raw_socket.rs index f45662c..8d28b82 100644 --- a/src/phy/sys/raw_socket.rs +++ b/src/phy/sys/raw_socket.rs @@ -1,12 +1,12 @@ -use std::{mem, io}; -use std::os::unix::io::{RawFd, AsRawFd}; use super::*; use crate::wire::EthernetFrame; +use std::os::unix::io::{AsRawFd, RawFd}; +use std::{io, mem}; #[derive(Debug)] pub struct RawSocketDesc { lower: libc::c_int, - ifreq: ifreq + ifreq: ifreq, } impl AsRawFd for RawSocketDesc { @@ -18,41 +18,51 @@ impl AsRawFd for RawSocketDesc { impl RawSocketDesc { pub fn new(name: &str) -> io::Result { let lower = unsafe { - let lower = libc::socket(libc::AF_PACKET, libc::SOCK_RAW | libc::SOCK_NONBLOCK, - imp::ETH_P_ALL.to_be() as i32); - if lower == -1 { return Err(io::Error::last_os_error()) } + let lower = libc::socket( + libc::AF_PACKET, + libc::SOCK_RAW | libc::SOCK_NONBLOCK, + imp::ETH_P_ALL.to_be() as i32, + ); + if lower == -1 { + return Err(io::Error::last_os_error()); + } lower }; Ok(RawSocketDesc { lower: lower, - ifreq: ifreq_for(name) + ifreq: ifreq_for(name), }) } pub fn interface_mtu(&mut self) -> io::Result { // SIOCGIFMTU returns the IP MTU (typically 1500 bytes.) // smoltcp counts the entire Ethernet packet in the MTU, so add the Ethernet header size to it. - let ip_mtu = ifreq_ioctl(self.lower, &mut self.ifreq, imp::SIOCGIFMTU).map(|mtu| mtu as usize)?; + let ip_mtu = + ifreq_ioctl(self.lower, &mut self.ifreq, imp::SIOCGIFMTU).map(|mtu| mtu as usize)?; Ok(ip_mtu + EthernetFrame::<&[u8]>::header_len()) } pub fn bind_interface(&mut self) -> io::Result<()> { let sockaddr = libc::sockaddr_ll { - sll_family: libc::AF_PACKET as u16, + sll_family: libc::AF_PACKET as u16, sll_protocol: imp::ETH_P_ALL.to_be() as u16, - sll_ifindex: ifreq_ioctl(self.lower, &mut self.ifreq, imp::SIOCGIFINDEX)?, - sll_hatype: 1, - sll_pkttype: 0, - sll_halen: 6, - sll_addr: [0; 8] + sll_ifindex: ifreq_ioctl(self.lower, &mut self.ifreq, imp::SIOCGIFINDEX)?, + sll_hatype: 1, + sll_pkttype: 0, + sll_halen: 6, + sll_addr: [0; 8], }; unsafe { - let res = libc::bind(self.lower, - &sockaddr as *const libc::sockaddr_ll as *const libc::sockaddr, - mem::size_of::() as u32); - if res == -1 { return Err(io::Error::last_os_error()) } + let res = libc::bind( + self.lower, + &sockaddr as *const libc::sockaddr_ll as *const libc::sockaddr, + mem::size_of::() as u32, + ); + if res == -1 { + return Err(io::Error::last_os_error()); + } } Ok(()) @@ -60,18 +70,30 @@ impl RawSocketDesc { pub fn recv(&mut self, buffer: &mut [u8]) -> io::Result { unsafe { - let len = libc::recv(self.lower, buffer.as_mut_ptr() as *mut libc::c_void, - buffer.len(), 0); - if len == -1 { return Err(io::Error::last_os_error()) } + let len = libc::recv( + self.lower, + buffer.as_mut_ptr() as *mut libc::c_void, + buffer.len(), + 0, + ); + if len == -1 { + return Err(io::Error::last_os_error()); + } Ok(len as usize) } } pub fn send(&mut self, buffer: &[u8]) -> io::Result { unsafe { - let len = libc::send(self.lower, buffer.as_ptr() as *const libc::c_void, - buffer.len(), 0); - if len == -1 { Err(io::Error::last_os_error()).unwrap() } + let len = libc::send( + self.lower, + buffer.as_ptr() as *const libc::c_void, + buffer.len(), + 0, + ); + if len == -1 { + Err(io::Error::last_os_error()).unwrap() + } Ok(len as usize) } } @@ -79,6 +101,8 @@ impl RawSocketDesc { impl Drop for RawSocketDesc { fn drop(&mut self) { - unsafe { libc::close(self.lower); } + unsafe { + libc::close(self.lower); + } } } diff --git a/src/phy/sys/tuntap_interface.rs b/src/phy/sys/tuntap_interface.rs index 6b42980..54b9c36 100644 --- a/src/phy/sys/tuntap_interface.rs +++ b/src/phy/sys/tuntap_interface.rs @@ -1,7 +1,7 @@ -use std::io; -use std::os::unix::io::{RawFd, AsRawFd}; use super::*; use crate::{phy::Medium, wire::EthernetFrame}; +use std::io; +use std::os::unix::io::{AsRawFd, RawFd}; #[derive(Debug)] pub struct TunTapInterfaceDesc { @@ -19,9 +19,13 @@ impl AsRawFd for TunTapInterfaceDesc { impl TunTapInterfaceDesc { pub fn new(name: &str, medium: Medium) -> io::Result { let lower = unsafe { - let lower = libc::open("/dev/net/tun\0".as_ptr() as *const libc::c_char, - libc::O_RDWR | libc::O_NONBLOCK); - if lower == -1 { return Err(io::Error::last_os_error()) } + let lower = libc::open( + "/dev/net/tun\0".as_ptr() as *const libc::c_char, + libc::O_RDWR | libc::O_NONBLOCK, + ); + if lower == -1 { + return Err(io::Error::last_os_error()); + } lower }; @@ -46,13 +50,17 @@ impl TunTapInterfaceDesc { pub fn interface_mtu(&mut self) -> io::Result { let lower = unsafe { let lower = libc::socket(libc::AF_INET, libc::SOCK_DGRAM, libc::IPPROTO_IP); - if lower == -1 { return Err(io::Error::last_os_error()) } + if lower == -1 { + return Err(io::Error::last_os_error()); + } lower }; let ip_mtu = ifreq_ioctl(lower, &mut self.ifreq, imp::SIOCGIFMTU).map(|mtu| mtu as usize); - unsafe { libc::close(lower); } + unsafe { + libc::close(lower); + } // Propagate error after close, to ensure we always close. let ip_mtu = ip_mtu?; @@ -71,18 +79,28 @@ impl TunTapInterfaceDesc { pub fn recv(&mut self, buffer: &mut [u8]) -> io::Result { unsafe { - let len = libc::read(self.lower, buffer.as_mut_ptr() as *mut libc::c_void, - buffer.len()); - if len == -1 { return Err(io::Error::last_os_error()) } + let len = libc::read( + self.lower, + buffer.as_mut_ptr() as *mut libc::c_void, + buffer.len(), + ); + if len == -1 { + return Err(io::Error::last_os_error()); + } Ok(len as usize) } } pub fn send(&mut self, buffer: &[u8]) -> io::Result { unsafe { - let len = libc::write(self.lower, buffer.as_ptr() as *const libc::c_void, - buffer.len()); - if len == -1 { Err(io::Error::last_os_error()).unwrap() } + let len = libc::write( + self.lower, + buffer.as_ptr() as *const libc::c_void, + buffer.len(), + ); + if len == -1 { + Err(io::Error::last_os_error()).unwrap() + } Ok(len as usize) } } @@ -90,6 +108,8 @@ impl TunTapInterfaceDesc { impl Drop for TunTapInterfaceDesc { fn drop(&mut self) { - unsafe { libc::close(self.lower); } + unsafe { + libc::close(self.lower); + } } } diff --git a/src/phy/tracer.rs b/src/phy/tracer.rs index 8a5e377..d5b8991 100644 --- a/src/phy/tracer.rs +++ b/src/phy/tracer.rs @@ -1,8 +1,11 @@ use core::fmt; -use crate::{Result, wire::pretty_print::{PrettyIndent, PrettyPrint}}; -use crate::phy::{self, DeviceCapabilities, Device, Medium}; +use crate::phy::{self, Device, DeviceCapabilities, Medium}; use crate::time::Instant; +use crate::{ + wire::pretty_print::{PrettyIndent, PrettyPrint}, + Result, +}; /// A tracer device. /// @@ -10,7 +13,7 @@ use crate::time::Instant; /// using the provided writer function, and then passes them to another /// device. pub struct Tracer Device<'a>> { - inner: D, + inner: D, writer: fn(Instant, Packet), } @@ -42,50 +45,78 @@ impl Device<'a>> Tracer { } impl<'a, D> Device<'a> for Tracer - where D: for<'b> Device<'b>, +where + D: for<'b> Device<'b>, { type RxToken = RxToken<>::RxToken>; type TxToken = TxToken<>::TxToken>; - fn capabilities(&self) -> DeviceCapabilities { self.inner.capabilities() } + fn capabilities(&self) -> DeviceCapabilities { + self.inner.capabilities() + } fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { - let &mut Self { ref mut inner, writer, .. } = self; + let &mut Self { + ref mut inner, + writer, + .. + } = self; let medium = inner.capabilities().medium; inner.receive().map(|(rx_token, tx_token)| { - let rx = RxToken { token: rx_token, writer, medium }; - let tx = TxToken { token: tx_token, writer, medium }; + let rx = RxToken { + token: rx_token, + writer, + medium, + }; + let tx = TxToken { + token: tx_token, + writer, + medium, + }; (rx, tx) }) } fn transmit(&'a mut self) -> Option { - let &mut Self { ref mut inner, writer } = self; + let &mut Self { + ref mut inner, + writer, + } = self; let medium = inner.capabilities().medium; - inner.transmit().map(|tx_token| { - TxToken { token: tx_token, medium, writer } + inner.transmit().map(|tx_token| TxToken { + token: tx_token, + medium, + writer, }) } } #[doc(hidden)] pub struct RxToken { - token: Rx, - writer: fn(Instant, Packet), - medium: Medium, + token: Rx, + writer: fn(Instant, Packet), + medium: Medium, } impl phy::RxToken for RxToken { fn consume(self, timestamp: Instant, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result + where + F: FnOnce(&mut [u8]) -> Result, { - let Self { token, writer, medium } = self; + let Self { + token, + writer, + medium, + } = self; token.consume(timestamp, |buffer| { - writer(timestamp, Packet{ - buffer, - medium, - prefix: "<- ", - }); + writer( + timestamp, + Packet { + buffer, + medium, + prefix: "<- ", + }, + ); f(buffer) }) } @@ -93,23 +124,31 @@ impl phy::RxToken for RxToken { #[doc(hidden)] pub struct TxToken { - token: Tx, - writer: fn(Instant, Packet), - medium: Medium, + token: Tx, + writer: fn(Instant, Packet), + medium: Medium, } impl phy::TxToken for TxToken { fn consume(self, timestamp: Instant, len: usize, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result + where + F: FnOnce(&mut [u8]) -> Result, { - let Self { token, writer, medium } = self; + let Self { + token, + writer, + medium, + } = self; token.consume(timestamp, len, |buffer| { let result = f(buffer); - writer(timestamp, Packet{ - buffer, - medium, - prefix: "-> ", - }); + writer( + timestamp, + Packet { + buffer, + medium, + prefix: "-> ", + }, + ); result }) } @@ -126,15 +165,31 @@ impl<'a> fmt::Display for Packet<'a> { let mut indent = PrettyIndent::new(self.prefix); match self.medium { #[cfg(feature = "medium-ethernet")] - Medium::Ethernet => crate::wire::EthernetFrame::<&'static [u8]>::pretty_print(&self.buffer, f, &mut indent), + Medium::Ethernet => crate::wire::EthernetFrame::<&'static [u8]>::pretty_print( + &self.buffer, + f, + &mut indent, + ), #[cfg(feature = "medium-ip")] Medium::Ip => match crate::wire::IpVersion::of_packet(&self.buffer) { #[cfg(feature = "proto-ipv4")] - Ok(crate::wire::IpVersion::Ipv4) => crate::wire::Ipv4Packet::<&'static [u8]>::pretty_print(&self.buffer, f, &mut indent), + Ok(crate::wire::IpVersion::Ipv4) => { + crate::wire::Ipv4Packet::<&'static [u8]>::pretty_print( + &self.buffer, + f, + &mut indent, + ) + } #[cfg(feature = "proto-ipv6")] - Ok(crate::wire::IpVersion::Ipv6) => crate::wire::Ipv6Packet::<&'static [u8]>::pretty_print(&self.buffer, f, &mut indent), - _ => f.write_str("unrecognized IP version") - } + Ok(crate::wire::IpVersion::Ipv6) => { + crate::wire::Ipv6Packet::<&'static [u8]>::pretty_print( + &self.buffer, + f, + &mut indent, + ) + } + _ => f.write_str("unrecognized IP version"), + }, } } -} \ No newline at end of file +} diff --git a/src/phy/tuntap_interface.rs b/src/phy/tuntap_interface.rs index cfd4f2d..6792a7b 100644 --- a/src/phy/tuntap_interface.rs +++ b/src/phy/tuntap_interface.rs @@ -1,18 +1,18 @@ use std::cell::RefCell; -use std::vec::Vec; -use std::rc::Rc; use std::io; -use std::os::unix::io::{RawFd, AsRawFd}; +use std::os::unix::io::{AsRawFd, RawFd}; +use std::rc::Rc; +use std::vec::Vec; -use crate::Result; -use crate::phy::{self, sys, DeviceCapabilities, Device, Medium}; +use crate::phy::{self, sys, Device, DeviceCapabilities, Medium}; use crate::time::Instant; +use crate::Result; /// A virtual TUN (IP) or TAP (Ethernet) interface. #[derive(Debug)] pub struct TunTapInterface { - lower: Rc>, - mtu: usize, + lower: Rc>, + mtu: usize, medium: Medium, } @@ -59,13 +59,13 @@ impl<'a> Device<'a> for TunTapInterface { Ok(size) => { buffer.resize(size, 0); let rx = RxToken { buffer }; - let tx = TxToken { lower: self.lower.clone() }; + let tx = TxToken { + lower: self.lower.clone(), + }; Some((rx, tx)) } - Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => { - None - } - Err(err) => panic!("{}", err) + Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => None, + Err(err) => panic!("{}", err), } } @@ -78,12 +78,13 @@ impl<'a> Device<'a> for TunTapInterface { #[doc(hidden)] pub struct RxToken { - buffer: Vec + buffer: Vec, } impl phy::RxToken for RxToken { fn consume(mut self, _timestamp: Instant, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result + where + F: FnOnce(&mut [u8]) -> Result, { f(&mut self.buffer[..]) } @@ -96,7 +97,8 @@ pub struct TxToken { impl phy::TxToken for TxToken { fn consume(self, _timestamp: Instant, len: usize, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result + where + F: FnOnce(&mut [u8]) -> Result, { let mut lower = self.lower.borrow_mut(); let mut buffer = vec![0; len]; diff --git a/src/socket/dhcpv4.rs b/src/socket/dhcpv4.rs index 7caa16e..97711e6 100644 --- a/src/socket/dhcpv4.rs +++ b/src/socket/dhcpv4.rs @@ -1,12 +1,12 @@ -use crate::{Error, Result}; -use crate::wire::{IpProtocol, IpAddress, - Ipv4Cidr, Ipv4Address, Ipv4Repr, - UdpRepr, UDP_HEADER_LEN, - DhcpPacket, DhcpRepr, DhcpMessageType, DHCP_CLIENT_PORT, DHCP_SERVER_PORT, DHCP_MAX_DNS_SERVER_COUNT}; -use crate::wire::dhcpv4::{field as dhcpv4_field}; -use crate::socket::{SocketMeta, Context}; -use crate::time::{Instant, Duration}; use crate::socket::SocketHandle; +use crate::socket::{Context, SocketMeta}; +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, +}; +use crate::{Error, Result}; use super::{PollAt, Socket}; @@ -31,7 +31,7 @@ const PARAMETER_REQUEST_LIST: &[u8] = &[ #[derive(Debug, Eq, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Config { - /// IP address + /// IP address pub address: Ipv4Cidr, /// Router address, also known as default gateway. Does not necessarily /// match the DHCP server's address. @@ -133,7 +133,7 @@ impl Dhcpv4Socket { pub fn new() -> Self { Dhcpv4Socket { meta: SocketMeta::default(), - state: ClientState::Discovering(DiscoverState{ + state: ClientState::Discovering(DiscoverState { retry_at: Instant::from_millis(0), }), config_changed: true, @@ -159,7 +159,13 @@ impl Dhcpv4Socket { PollAt::Time(t) } - pub(crate) fn process(&mut self, cx: &Context, ip_repr: &Ipv4Repr, repr: &UdpRepr, payload: &[u8]) -> Result<()> { + pub(crate) fn process( + &mut self, + cx: &Context, + ip_repr: &Ipv4Repr, + repr: &UdpRepr, + payload: &[u8], + ) -> Result<()> { let src_ip = ip_repr.src_addr; // This is enforced in interface.rs. @@ -179,25 +185,37 @@ impl Dhcpv4Socket { return Ok(()); } }; - if dhcp_repr.client_hardware_address != cx.ethernet_address.unwrap() { return Ok(()) } - if dhcp_repr.transaction_id != self.transaction_id { return Ok(()) } + if dhcp_repr.client_hardware_address != cx.ethernet_address.unwrap() { + return Ok(()); + } + if dhcp_repr.transaction_id != self.transaction_id { + return Ok(()); + } let server_identifier = match dhcp_repr.server_identifier { Some(server_identifier) => server_identifier, None => { - net_debug!("DHCP ignoring {:?} because missing server_identifier", dhcp_repr.message_type); + net_debug!( + "DHCP ignoring {:?} because missing server_identifier", + dhcp_repr.message_type + ); return Ok(()); } }; - net_debug!("DHCP recv {:?} from {} ({})", dhcp_repr.message_type, src_ip, server_identifier); - - match (&mut self.state, dhcp_repr.message_type){ + net_debug!( + "DHCP recv {:?} from {} ({})", + dhcp_repr.message_type, + src_ip, + server_identifier + ); + + match (&mut self.state, dhcp_repr.message_type) { (ClientState::Discovering(_state), DhcpMessageType::Offer) => { if !dhcp_repr.your_ip.is_unicast() { net_debug!("DHCP ignoring OFFER because your_ip is not unicast"); - return Ok(()) + return Ok(()); } - + self.state = ClientState::Requesting(RequestState { retry_at: cx.now, retry: 0, @@ -205,13 +223,15 @@ impl Dhcpv4Socket { address: src_ip, identifier: server_identifier, }, - requested_ip: dhcp_repr.your_ip // use the offered ip + requested_ip: dhcp_repr.your_ip, // use the offered ip }); } (ClientState::Requesting(state), DhcpMessageType::Ack) => { - if let Some((config, renew_at, expires_at)) = Self::parse_ack(cx.now, &dhcp_repr, self.max_lease_duration) { + if let Some((config, renew_at, expires_at)) = + Self::parse_ack(cx.now, &dhcp_repr, self.max_lease_duration) + { self.config_changed = true; - self.state = ClientState::Renewing(RenewState{ + self.state = ClientState::Renewing(RenewState { server: state.server, config, renew_at, @@ -223,7 +243,9 @@ impl Dhcpv4Socket { self.reset(); } (ClientState::Renewing(state), DhcpMessageType::Ack) => { - if let Some((config, renew_at, expires_at)) = Self::parse_ack(cx.now, &dhcp_repr, self.max_lease_duration) { + if let Some((config, renew_at, expires_at)) = + Self::parse_ack(cx.now, &dhcp_repr, self.max_lease_duration) + { state.renew_at = renew_at; state.expires_at = expires_at; if state.config != config { @@ -236,19 +258,26 @@ impl Dhcpv4Socket { self.reset(); } _ => { - net_debug!("DHCP ignoring {:?}: unexpected in current state", dhcp_repr.message_type); + net_debug!( + "DHCP ignoring {:?}: unexpected in current state", + dhcp_repr.message_type + ); } } Ok(()) } - fn parse_ack(now: Instant, dhcp_repr: &DhcpRepr, max_lease_duration: Option) -> Option<(Config, Instant, Instant)> { + fn parse_ack( + now: Instant, + dhcp_repr: &DhcpRepr, + max_lease_duration: Option, + ) -> Option<(Config, Instant, Instant)> { let subnet_mask = match dhcp_repr.subnet_mask { Some(subnet_mask) => subnet_mask, None => { net_debug!("DHCP ignoring ACK because missing subnet_mask"); - return None + return None; } }; @@ -256,16 +285,19 @@ impl Dhcpv4Socket { Some(prefix_len) => prefix_len, None => { net_debug!("DHCP ignoring ACK because subnet_mask is not a valid mask"); - return None + return None; } }; if !dhcp_repr.your_ip.is_unicast() { net_debug!("DHCP ignoring ACK because your_ip is not unicast"); - return None + return None; } - let mut lease_duration = dhcp_repr.lease_duration.map(|d| Duration::from_secs(d as _)).unwrap_or(DEFAULT_LEASE_DURATION); + let mut lease_duration = dhcp_repr + .lease_duration + .map(|d| Duration::from_secs(d as _)) + .unwrap_or(DEFAULT_LEASE_DURATION); if let Some(max_lease_duration) = max_lease_duration { lease_duration = lease_duration.min(max_lease_duration); } @@ -276,7 +308,7 @@ impl Dhcpv4Socket { if let Some(received) = dhcp_repr.dns_servers { let mut i = 0; for addr in received.iter() { - if let Some(addr) = addr{ + if let Some(addr) = addr { if addr.is_unicast() { // This can never be out-of-bounds since both arrays have length DHCP_MAX_DNS_SERVER_COUNT dns_servers[i] = Some(*addr); @@ -285,10 +317,10 @@ impl Dhcpv4Socket { } } } - let config = Config{ + let config = Config { address: Ipv4Cidr::new(dhcp_repr.your_ip, prefix_len), router: dhcp_repr.router, - dns_servers: dns_servers + dns_servers: dns_servers, }; // RFC 2131 indicates clients should renew a lease halfway through its expiration. @@ -299,9 +331,10 @@ impl Dhcpv4Socket { } pub(crate) fn dispatch(&mut self, cx: &Context, emit: F) -> Result<()> - where F: FnOnce((Ipv4Repr, UdpRepr, DhcpRepr)) -> Result<()> { - - // note: Dhcpv4Socket is only usable in ethernet mediums, so the + where + F: FnOnce((Ipv4Repr, UdpRepr, DhcpRepr)) -> Result<()>, + { + // note: Dhcpv4Socket is only usable in ethernet mediums, so the // unwrap can never fail. let ethernet_addr = cx.ethernet_address.unwrap(); @@ -337,7 +370,7 @@ impl Dhcpv4Socket { src_port: DHCP_CLIENT_PORT, dst_port: DHCP_SERVER_PORT, }; - + let mut ipv4_repr = Ipv4Repr { src_addr: Ipv4Address::UNSPECIFIED, dst_addr: Ipv4Address::BROADCAST, @@ -349,11 +382,15 @@ impl Dhcpv4Socket { match &mut self.state { ClientState::Discovering(state) => { if cx.now < state.retry_at { - return Err(Error::Exhausted) + return Err(Error::Exhausted); } // send packet - net_debug!("DHCP send DISCOVER to {}: {:?}", ipv4_repr.dst_addr, dhcp_repr); + net_debug!( + "DHCP send DISCOVER to {}: {:?}", + ipv4_repr.dst_addr, + dhcp_repr + ); ipv4_repr.payload_len = udp_repr.header_len() + dhcp_repr.buffer_len(); emit((ipv4_repr, udp_repr, dhcp_repr))?; @@ -364,14 +401,14 @@ impl Dhcpv4Socket { } ClientState::Requesting(state) => { if cx.now < state.retry_at { - return Err(Error::Exhausted) + return Err(Error::Exhausted); } if state.retry >= REQUEST_RETRIES { net_debug!("DHCP request retries exceeded, restarting discovery"); self.reset(); // return Ok so we get polled again - return Ok(()) + return Ok(()); } dhcp_repr.message_type = DhcpMessageType::Request; @@ -379,7 +416,11 @@ impl Dhcpv4Socket { dhcp_repr.requested_ip = Some(state.requested_ip); dhcp_repr.server_identifier = Some(state.server.identifier); - net_debug!("DHCP send request to {}: {:?}", ipv4_repr.dst_addr, dhcp_repr); + net_debug!( + "DHCP send request to {}: {:?}", + ipv4_repr.dst_addr, + dhcp_repr + ); ipv4_repr.payload_len = udp_repr.header_len() + dhcp_repr.buffer_len(); emit((ipv4_repr, udp_repr, dhcp_repr))?; @@ -395,11 +436,11 @@ impl Dhcpv4Socket { net_debug!("DHCP lease expired"); self.reset(); // return Ok so we get polled again - return Ok(()) + return Ok(()); } - + if cx.now < state.renew_at { - return Err(Error::Exhausted) + return Err(Error::Exhausted); } ipv4_repr.src_addr = state.config.address.address(); @@ -411,7 +452,7 @@ impl Dhcpv4Socket { net_debug!("DHCP send renew to {}: {:?}", ipv4_repr.dst_addr, dhcp_repr); ipv4_repr.payload_len = udp_repr.header_len() + dhcp_repr.buffer_len(); emit((ipv4_repr, udp_repr, dhcp_repr))?; - + // In both RENEWING and REBINDING states, if the client receives no // response to its DHCPREQUEST message, the client SHOULD wait one-half // of the remaining time until T2 (in RENEWING state) and one-half of @@ -440,7 +481,7 @@ impl Dhcpv4Socket { if let ClientState::Renewing(_) = &self.state { self.config_changed = true; } - self.state = ClientState::Discovering(DiscoverState{ + self.state = ClientState::Discovering(DiscoverState { retry_at: Instant::from_millis(0), }); } diff --git a/src/socket/icmp.rs b/src/socket/icmp.rs index 39c8b58..90f2516 100644 --- a/src/socket/icmp.rs +++ b/src/socket/icmp.rs @@ -2,20 +2,20 @@ use core::cmp; #[cfg(feature = "async")] use core::task::Waker; -use crate::{Error, Result}; use crate::phy::ChecksumCapabilities; -use crate::socket::{Socket, SocketMeta, SocketHandle, PollAt, Context}; -use crate::storage::{PacketBuffer, PacketMetadata}; #[cfg(feature = "async")] use crate::socket::WakerRegistration; +use crate::socket::{Context, PollAt, Socket, SocketHandle, SocketMeta}; +use crate::storage::{PacketBuffer, PacketMetadata}; +use crate::{Error, Result}; -#[cfg(feature = "proto-ipv4")] -use crate::wire::{Ipv4Address, Ipv4Repr, Icmpv4Packet, Icmpv4Repr}; -#[cfg(feature = "proto-ipv6")] -use crate::wire::{Ipv6Address, Ipv6Repr, Icmpv6Packet, Icmpv6Repr}; use crate::wire::IcmpRepr; -use crate::wire::{UdpPacket, UdpRepr}; +#[cfg(feature = "proto-ipv4")] +use crate::wire::{Icmpv4Packet, Icmpv4Repr, Ipv4Address, Ipv4Repr}; +#[cfg(feature = "proto-ipv6")] +use crate::wire::{Icmpv6Packet, Icmpv6Repr, Ipv6Address, Ipv6Repr}; use crate::wire::{IpAddress, IpEndpoint, IpProtocol, IpRepr}; +use crate::wire::{UdpPacket, UdpRepr}; /// Type of endpoint to bind the ICMP socket to. See [IcmpSocket::bind] for /// more details. @@ -26,7 +26,7 @@ use crate::wire::{IpAddress, IpEndpoint, IpProtocol, IpRepr}; pub enum Endpoint { Unspecified, Ident(u16), - Udp(IpEndpoint) + Udp(IpEndpoint), } impl Endpoint { @@ -34,13 +34,15 @@ impl Endpoint { match *self { Endpoint::Ident(_) => true, Endpoint::Udp(endpoint) => endpoint.port != 0, - Endpoint::Unspecified => false + Endpoint::Unspecified => false, } } } impl Default for Endpoint { - fn default() -> Endpoint { Endpoint::Unspecified } + fn default() -> Endpoint { + Endpoint::Unspecified + } } /// An ICMP packet metadata. @@ -64,7 +66,7 @@ pub struct IcmpSocket<'a> { rx_buffer: IcmpSocketBuffer<'a>, tx_buffer: IcmpSocketBuffer<'a>, /// The endpoint this socket is communicating with - endpoint: Endpoint, + endpoint: Endpoint, /// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets. hop_limit: Option, #[cfg(feature = "async")] @@ -75,13 +77,12 @@ pub struct IcmpSocket<'a> { impl<'a> IcmpSocket<'a> { /// Create an ICMP socket with the given buffers. - pub fn new(rx_buffer: IcmpSocketBuffer<'a>, - tx_buffer: IcmpSocketBuffer<'a>) -> IcmpSocket<'a> { + pub fn new(rx_buffer: IcmpSocketBuffer<'a>, tx_buffer: IcmpSocketBuffer<'a>) -> IcmpSocket<'a> { IcmpSocket { - meta: SocketMeta::default(), + meta: SocketMeta::default(), rx_buffer: rx_buffer, tx_buffer: tx_buffer, - endpoint: Endpoint::default(), + endpoint: Endpoint::default(), hop_limit: None, #[cfg(feature = "async")] rx_waker: WakerRegistration::new(), @@ -219,7 +220,9 @@ impl<'a> IcmpSocket<'a> { return Err(Error::Unaddressable); } - if self.is_open() { return Err(Error::Illegal) } + if self.is_open() { + return Err(Error::Illegal); + } self.endpoint = endpoint; @@ -282,13 +285,17 @@ impl<'a> IcmpSocket<'a> { /// size, and `Err(Error::Unaddressable)` if the remote address is unspecified. pub fn send(&mut self, size: usize, endpoint: IpAddress) -> Result<&mut [u8]> { if endpoint.is_unspecified() { - return Err(Error::Unaddressable) + return Err(Error::Unaddressable); } let packet_buf = self.tx_buffer.enqueue(size, endpoint)?; - net_trace!("{}:{}: buffer to send {} octets", - self.meta.handle, endpoint, size); + net_trace!( + "{}:{}: buffer to send {} octets", + self.meta.handle, + endpoint, + size + ); Ok(packet_buf) } @@ -308,8 +315,12 @@ impl<'a> IcmpSocket<'a> { pub fn recv(&mut self) -> Result<(&[u8], IpAddress)> { let (endpoint, packet_buf) = self.rx_buffer.dequeue()?; - net_trace!("{}:{}: receive {} buffered octets", - self.meta.handle, endpoint, packet_buf.len()); + net_trace!( + "{}:{}: receive {} buffered octets", + self.meta.handle, + endpoint, + packet_buf.len() + ); Ok((packet_buf, endpoint)) } @@ -332,19 +343,33 @@ impl<'a> IcmpSocket<'a> { // accept Destination Unreachable messages with the data containing // a UDP packet send from the local port we are bound to. #[cfg(feature = "proto-ipv4")] - (&Endpoint::Udp(endpoint), &IcmpRepr::Ipv4(Icmpv4Repr::DstUnreachable { data, .. })) - if endpoint.addr.is_unspecified() || endpoint.addr == ip_repr.dst_addr() => { + ( + &Endpoint::Udp(endpoint), + &IcmpRepr::Ipv4(Icmpv4Repr::DstUnreachable { data, .. }), + ) if endpoint.addr.is_unspecified() || endpoint.addr == ip_repr.dst_addr() => { let packet = UdpPacket::new_unchecked(data); - match UdpRepr::parse(&packet, &ip_repr.src_addr(), &ip_repr.dst_addr(), &cx.caps.checksum) { + match UdpRepr::parse( + &packet, + &ip_repr.src_addr(), + &ip_repr.dst_addr(), + &cx.caps.checksum, + ) { Ok(repr) => endpoint.port == repr.src_port, Err(_) => false, } } #[cfg(feature = "proto-ipv6")] - (&Endpoint::Udp(endpoint), &IcmpRepr::Ipv6(Icmpv6Repr::DstUnreachable { data, .. })) - if endpoint.addr.is_unspecified() || endpoint.addr == ip_repr.dst_addr() => { + ( + &Endpoint::Udp(endpoint), + &IcmpRepr::Ipv6(Icmpv6Repr::DstUnreachable { data, .. }), + ) if endpoint.addr.is_unspecified() || endpoint.addr == ip_repr.dst_addr() => { let packet = UdpPacket::new_unchecked(data); - match UdpRepr::parse(&packet, &ip_repr.src_addr(), &ip_repr.dst_addr(), &cx.caps.checksum) { + match UdpRepr::parse( + &packet, + &ip_repr.src_addr(), + &ip_repr.dst_addr(), + &cx.caps.checksum, + ) { Ok(repr) => endpoint.port == repr.src_port, Err(_) => false, } @@ -353,44 +378,70 @@ impl<'a> IcmpSocket<'a> { // Echo Request/Reply with the identifier field matching the endpoint // port. #[cfg(feature = "proto-ipv4")] - (&Endpoint::Ident(bound_ident), - &IcmpRepr::Ipv4(Icmpv4Repr::EchoRequest { ident, .. })) | - (&Endpoint::Ident(bound_ident), - &IcmpRepr::Ipv4(Icmpv4Repr::EchoReply { ident, .. })) => - ident == bound_ident, + ( + &Endpoint::Ident(bound_ident), + &IcmpRepr::Ipv4(Icmpv4Repr::EchoRequest { ident, .. }), + ) + | ( + &Endpoint::Ident(bound_ident), + &IcmpRepr::Ipv4(Icmpv4Repr::EchoReply { ident, .. }), + ) => ident == bound_ident, #[cfg(feature = "proto-ipv6")] - (&Endpoint::Ident(bound_ident), - &IcmpRepr::Ipv6(Icmpv6Repr::EchoRequest { ident, .. })) | - (&Endpoint::Ident(bound_ident), - &IcmpRepr::Ipv6(Icmpv6Repr::EchoReply { ident, .. })) => - ident == bound_ident, + ( + &Endpoint::Ident(bound_ident), + &IcmpRepr::Ipv6(Icmpv6Repr::EchoRequest { ident, .. }), + ) + | ( + &Endpoint::Ident(bound_ident), + &IcmpRepr::Ipv6(Icmpv6Repr::EchoReply { ident, .. }), + ) => ident == bound_ident, _ => false, } } - pub(crate) fn process(&mut self, _cx: &Context, ip_repr: &IpRepr, icmp_repr: &IcmpRepr) -> Result<()> { + pub(crate) fn process( + &mut self, + _cx: &Context, + ip_repr: &IpRepr, + icmp_repr: &IcmpRepr, + ) -> Result<()> { match *icmp_repr { #[cfg(feature = "proto-ipv4")] IcmpRepr::Ipv4(ref icmp_repr) => { - let packet_buf = self.rx_buffer.enqueue(icmp_repr.buffer_len(), - ip_repr.src_addr())?; - icmp_repr.emit(&mut Icmpv4Packet::new_unchecked(packet_buf), - &ChecksumCapabilities::default()); + let packet_buf = self + .rx_buffer + .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())?; + icmp_repr.emit( + &mut Icmpv4Packet::new_unchecked(packet_buf), + &ChecksumCapabilities::default(), + ); - net_trace!("{}:{}: receiving {} octets", - self.meta.handle, icmp_repr.buffer_len(), packet_buf.len()); - }, + net_trace!( + "{}:{}: receiving {} octets", + self.meta.handle, + icmp_repr.buffer_len(), + packet_buf.len() + ); + } #[cfg(feature = "proto-ipv6")] IcmpRepr::Ipv6(ref icmp_repr) => { - let packet_buf = self.rx_buffer.enqueue(icmp_repr.buffer_len(), - ip_repr.src_addr())?; - icmp_repr.emit(&ip_repr.src_addr(), &ip_repr.dst_addr(), - &mut Icmpv6Packet::new_unchecked(packet_buf), - &ChecksumCapabilities::default()); + let packet_buf = self + .rx_buffer + .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())?; + icmp_repr.emit( + &ip_repr.src_addr(), + &ip_repr.dst_addr(), + &mut Icmpv6Packet::new_unchecked(packet_buf), + &ChecksumCapabilities::default(), + ); - net_trace!("{}:{}: receiving {} octets", - self.meta.handle, icmp_repr.buffer_len(), packet_buf.len()); - }, + net_trace!( + "{}:{}: receiving {} octets", + self.meta.handle, + icmp_repr.buffer_len(), + packet_buf.len() + ); + } } #[cfg(feature = "async")] @@ -400,42 +451,52 @@ impl<'a> IcmpSocket<'a> { } pub(crate) fn dispatch(&mut self, _cx: &Context, emit: F) -> Result<()> - where F: FnOnce((IpRepr, IcmpRepr)) -> Result<()> + where + F: FnOnce((IpRepr, IcmpRepr)) -> Result<()>, { - let handle = self.meta.handle; + let handle = self.meta.handle; let hop_limit = self.hop_limit.unwrap_or(64); self.tx_buffer.dequeue_with(|remote_endpoint, packet_buf| { - net_trace!("{}:{}: sending {} octets", - handle, remote_endpoint, packet_buf.len()); + net_trace!( + "{}:{}: sending {} octets", + handle, + remote_endpoint, + packet_buf.len() + ); match *remote_endpoint { #[cfg(feature = "proto-ipv4")] IpAddress::Ipv4(ipv4_addr) => { let packet = Icmpv4Packet::new_unchecked(&*packet_buf); let repr = Icmpv4Repr::parse(&packet, &ChecksumCapabilities::ignored())?; let ip_repr = IpRepr::Ipv4(Ipv4Repr { - src_addr: Ipv4Address::default(), - dst_addr: ipv4_addr, - protocol: IpProtocol::Icmp, + src_addr: Ipv4Address::default(), + dst_addr: ipv4_addr, + protocol: IpProtocol::Icmp, payload_len: repr.buffer_len(), - hop_limit: hop_limit, + hop_limit: hop_limit, }); emit((ip_repr, IcmpRepr::Ipv4(repr))) - }, + } #[cfg(feature = "proto-ipv6")] IpAddress::Ipv6(ipv6_addr) => { let packet = Icmpv6Packet::new_unchecked(&*packet_buf); let src_addr = Ipv6Address::default(); - let repr = Icmpv6Repr::parse(&src_addr.into(), &ipv6_addr.into(), &packet, &ChecksumCapabilities::ignored())?; + let repr = Icmpv6Repr::parse( + &src_addr.into(), + &ipv6_addr.into(), + &packet, + &ChecksumCapabilities::ignored(), + )?; let ip_repr = IpRepr::Ipv6(Ipv6Repr { - src_addr: src_addr, - dst_addr: ipv6_addr, + src_addr: src_addr, + dst_addr: ipv6_addr, next_header: IpProtocol::Icmpv6, payload_len: repr.buffer_len(), - hop_limit: hop_limit, + hop_limit: hop_limit, }); emit((ip_repr, IcmpRepr::Ipv6(repr))) - }, - _ => Err(Error::Unaddressable) + } + _ => Err(Error::Unaddressable), } })?; @@ -462,20 +523,25 @@ impl<'a> Into> for IcmpSocket<'a> { #[cfg(test)] mod tests_common { + pub use super::*; pub use crate::phy::DeviceCapabilities; pub use crate::wire::IpAddress; - pub use super::*; pub fn buffer(packets: usize) -> IcmpSocketBuffer<'static> { - IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY; packets], vec![0; 66 * packets]) + IcmpSocketBuffer::new( + vec![IcmpPacketMetadata::EMPTY; packets], + vec![0; 66 * packets], + ) } - pub fn socket(rx_buffer: IcmpSocketBuffer<'static>, - tx_buffer: IcmpSocketBuffer<'static>) -> IcmpSocket<'static> { + pub fn socket( + rx_buffer: IcmpSocketBuffer<'static>, + tx_buffer: IcmpSocketBuffer<'static>, + ) -> IcmpSocket<'static> { IcmpSocket::new(rx_buffer, tx_buffer) } - pub const LOCAL_PORT: u16 = 53; + pub const LOCAL_PORT: u16 = 53; pub static UDP_REPR: UdpRepr = UdpRepr { src_port: 53, @@ -492,13 +558,16 @@ mod test_ipv4 { use crate::wire::Icmpv4DstUnreachable; const REMOTE_IPV4: Ipv4Address = Ipv4Address([0x7f, 0x00, 0x00, 0x02]); - const LOCAL_IPV4: Ipv4Address = Ipv4Address([0x7f, 0x00, 0x00, 0x01]); - const LOCAL_END_V4: IpEndpoint = IpEndpoint { addr: IpAddress::Ipv4(LOCAL_IPV4), port: LOCAL_PORT }; + const LOCAL_IPV4: Ipv4Address = Ipv4Address([0x7f, 0x00, 0x00, 0x01]); + const LOCAL_END_V4: IpEndpoint = IpEndpoint { + addr: IpAddress::Ipv4(LOCAL_IPV4), + port: LOCAL_PORT, + }; static ECHOV4_REPR: Icmpv4Repr = Icmpv4Repr::EchoRequest { - ident: 0x1234, - seq_no: 0x5678, - data: &[0xff; 16] + ident: 0x1234, + seq_no: 0x5678, + data: &[0xff; 16], }; static LOCAL_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr { @@ -506,7 +575,7 @@ mod test_ipv4 { dst_addr: REMOTE_IPV4, protocol: IpProtocol::Icmp, payload_len: 24, - hop_limit: 0x40 + hop_limit: 0x40, }); static REMOTE_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr { @@ -514,14 +583,16 @@ mod test_ipv4 { dst_addr: LOCAL_IPV4, protocol: IpProtocol::Icmp, payload_len: 24, - hop_limit: 0x40 + hop_limit: 0x40, }); #[test] fn test_send_unaddressable() { let mut socket = socket(buffer(0), buffer(1)); - assert_eq!(socket.send_slice(b"abcdef", IpAddress::default()), - Err(Error::Unaddressable)); + assert_eq!( + socket.send_slice(b"abcdef", IpAddress::default()), + Err(Error::Unaddressable) + ); assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV4.into()), Ok(())); } @@ -530,34 +601,51 @@ mod test_ipv4 { let mut socket = socket(buffer(0), buffer(1)); let checksum = ChecksumCapabilities::default(); - assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), - Err(Error::Exhausted)); + assert_eq!( + socket.dispatch(&Context::DUMMY, |_| unreachable!()), + Err(Error::Exhausted) + ); // This buffer is too long - assert_eq!(socket.send_slice(&[0xff; 67], REMOTE_IPV4.into()), Err(Error::Truncated)); + assert_eq!( + socket.send_slice(&[0xff; 67], REMOTE_IPV4.into()), + Err(Error::Truncated) + ); assert!(socket.can_send()); let mut bytes = [0xff; 24]; let mut packet = Icmpv4Packet::new_unchecked(&mut bytes); ECHOV4_REPR.emit(&mut packet, &checksum); - assert_eq!(socket.send_slice(&packet.into_inner()[..], REMOTE_IPV4.into()), Ok(())); - assert_eq!(socket.send_slice(b"123456", REMOTE_IPV4.into()), Err(Error::Exhausted)); + assert_eq!( + socket.send_slice(&packet.into_inner()[..], REMOTE_IPV4.into()), + Ok(()) + ); + assert_eq!( + socket.send_slice(b"123456", REMOTE_IPV4.into()), + Err(Error::Exhausted) + ); assert!(!socket.can_send()); - assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| { - assert_eq!(ip_repr, LOCAL_IPV4_REPR); - assert_eq!(icmp_repr, ECHOV4_REPR.into()); + assert_eq!( + socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| { + assert_eq!(ip_repr, LOCAL_IPV4_REPR); + assert_eq!(icmp_repr, ECHOV4_REPR.into()); + Err(Error::Unaddressable) + }), Err(Error::Unaddressable) - }), Err(Error::Unaddressable)); + ); // buffer is not taken off of the tx queue due to the error assert!(!socket.can_send()); - assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| { - assert_eq!(ip_repr, LOCAL_IPV4_REPR); - assert_eq!(icmp_repr, ECHOV4_REPR.into()); + assert_eq!( + socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| { + assert_eq!(ip_repr, LOCAL_IPV4_REPR); + assert_eq!(icmp_repr, ECHOV4_REPR.into()); + Ok(()) + }), Ok(()) - }), Ok(())); + ); // buffer is taken off of the queue this time assert!(socket.can_send()); } @@ -573,17 +661,26 @@ mod test_ipv4 { s.set_hop_limit(Some(0x2a)); - assert_eq!(s.send_slice(&packet.into_inner()[..], REMOTE_IPV4.into()), Ok(())); - assert_eq!(s.dispatch(&Context::DUMMY, |(ip_repr, _)| { - assert_eq!(ip_repr, IpRepr::Ipv4(Ipv4Repr { - src_addr: Ipv4Address::UNSPECIFIED, - dst_addr: REMOTE_IPV4, - protocol: IpProtocol::Icmp, - payload_len: ECHOV4_REPR.buffer_len(), - hop_limit: 0x2a, - })); + assert_eq!( + s.send_slice(&packet.into_inner()[..], REMOTE_IPV4.into()), Ok(()) - }), Ok(())); + ); + assert_eq!( + s.dispatch(&Context::DUMMY, |(ip_repr, _)| { + assert_eq!( + ip_repr, + IpRepr::Ipv4(Ipv4Repr { + src_addr: Ipv4Address::UNSPECIFIED, + dst_addr: REMOTE_IPV4, + protocol: IpProtocol::Icmp, + payload_len: ECHOV4_REPR.buffer_len(), + hop_limit: 0x2a, + }) + ); + Ok(()) + }), + Ok(()) + ); } #[test] @@ -602,13 +699,17 @@ mod test_ipv4 { let data = &packet.into_inner()[..]; assert!(socket.accepts(&Context::DUMMY, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into())); - assert_eq!(socket.process(&Context::DUMMY, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()), - Ok(())); + assert_eq!( + socket.process(&Context::DUMMY, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()), + Ok(()) + ); assert!(socket.can_recv()); assert!(socket.accepts(&Context::DUMMY, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into())); - assert_eq!(socket.process(&Context::DUMMY, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()), - Err(Error::Exhausted)); + assert_eq!( + socket.process(&Context::DUMMY, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()), + Err(Error::Exhausted) + ); assert_eq!(socket.recv(), Ok((&data[..], REMOTE_IPV4.into()))); assert!(!socket.can_recv()); @@ -623,9 +724,9 @@ mod test_ipv4 { let mut bytes = [0xff; 20]; let mut packet = Icmpv4Packet::new_unchecked(&mut bytes); let icmp_repr = Icmpv4Repr::EchoRequest { - ident: 0x4321, + ident: 0x4321, seq_no: 0x5678, - data: &[0xff; 16] + data: &[0xff; 16], }; icmp_repr.emit(&mut packet, &checksum); @@ -649,7 +750,8 @@ mod test_ipv4 { &LOCAL_IPV4.into(), UDP_PAYLOAD.len(), |buf| buf.copy_from_slice(UDP_PAYLOAD), - &checksum); + &checksum, + ); let data = &packet.into_inner()[..]; @@ -660,16 +762,16 @@ mod test_ipv4 { dst_addr: REMOTE_IPV4, protocol: IpProtocol::Icmp, payload_len: 12, - hop_limit: 0x40 + hop_limit: 0x40, }, - data: data + data: data, }; let ip_repr = IpRepr::Unspecified { src_addr: REMOTE_IPV4.into(), dst_addr: LOCAL_IPV4.into(), protocol: IpProtocol::Icmp, payload_len: icmp_repr.buffer_len(), - hop_limit: 0x40 + hop_limit: 0x40, }; assert!(!socket.can_recv()); @@ -677,14 +779,19 @@ mod test_ipv4 { // Ensure we can accept ICMP error response to the bound // UDP port assert!(socket.accepts(&Context::DUMMY, &ip_repr, &icmp_repr.into())); - assert_eq!(socket.process(&Context::DUMMY, &ip_repr, &icmp_repr.into()), - Ok(())); + assert_eq!( + socket.process(&Context::DUMMY, &ip_repr, &icmp_repr.into()), + Ok(()) + ); assert!(socket.can_recv()); let mut bytes = [0x00; 46]; let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]); icmp_repr.emit(&mut packet, &checksum); - assert_eq!(socket.recv(), Ok((&packet.into_inner()[..], REMOTE_IPV4.into()))); + assert_eq!( + socket.recv(), + Ok((&packet.into_inner()[..], REMOTE_IPV4.into())) + ); assert!(!socket.can_recv()); } } @@ -695,15 +802,18 @@ mod test_ipv6 { use crate::wire::Icmpv6DstUnreachable; - const REMOTE_IPV6: Ipv6Address = Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1]); - const LOCAL_IPV6: Ipv6Address = Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2]); - const LOCAL_END_V6: IpEndpoint = IpEndpoint { addr: IpAddress::Ipv6(LOCAL_IPV6), port: LOCAL_PORT }; + const REMOTE_IPV6: Ipv6Address = + Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); + const LOCAL_IPV6: Ipv6Address = + Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]); + const LOCAL_END_V6: IpEndpoint = IpEndpoint { + addr: IpAddress::Ipv6(LOCAL_IPV6), + port: LOCAL_PORT, + }; static ECHOV6_REPR: Icmpv6Repr = Icmpv6Repr::EchoRequest { - ident: 0x1234, - seq_no: 0x5678, - data: &[0xff; 16] + ident: 0x1234, + seq_no: 0x5678, + data: &[0xff; 16], }; static LOCAL_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr { @@ -711,7 +821,7 @@ mod test_ipv6 { dst_addr: REMOTE_IPV6, next_header: IpProtocol::Icmpv6, payload_len: 24, - hop_limit: 0x40 + hop_limit: 0x40, }); static REMOTE_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr { @@ -719,14 +829,16 @@ mod test_ipv6 { dst_addr: LOCAL_IPV6, next_header: IpProtocol::Icmpv6, payload_len: 24, - hop_limit: 0x40 + hop_limit: 0x40, }); #[test] fn test_send_unaddressable() { let mut socket = socket(buffer(0), buffer(1)); - assert_eq!(socket.send_slice(b"abcdef", IpAddress::default()), - Err(Error::Unaddressable)); + assert_eq!( + socket.send_slice(b"abcdef", IpAddress::default()), + Err(Error::Unaddressable) + ); assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV6.into()), Ok(())); } @@ -735,34 +847,56 @@ mod test_ipv6 { let mut socket = socket(buffer(0), buffer(1)); let checksum = ChecksumCapabilities::default(); - assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), - Err(Error::Exhausted)); + assert_eq!( + socket.dispatch(&Context::DUMMY, |_| unreachable!()), + Err(Error::Exhausted) + ); // This buffer is too long - assert_eq!(socket.send_slice(&[0xff; 67], REMOTE_IPV6.into()), Err(Error::Truncated)); + assert_eq!( + socket.send_slice(&[0xff; 67], REMOTE_IPV6.into()), + Err(Error::Truncated) + ); assert!(socket.can_send()); let mut bytes = vec![0xff; 24]; let mut packet = Icmpv6Packet::new_unchecked(&mut bytes); - ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum); + ECHOV6_REPR.emit( + &LOCAL_IPV6.into(), + &REMOTE_IPV6.into(), + &mut packet, + &checksum, + ); - assert_eq!(socket.send_slice(&packet.into_inner()[..], REMOTE_IPV6.into()), Ok(())); - assert_eq!(socket.send_slice(b"123456", REMOTE_IPV6.into()), Err(Error::Exhausted)); + assert_eq!( + socket.send_slice(&packet.into_inner()[..], REMOTE_IPV6.into()), + Ok(()) + ); + assert_eq!( + socket.send_slice(b"123456", REMOTE_IPV6.into()), + Err(Error::Exhausted) + ); assert!(!socket.can_send()); - assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| { - assert_eq!(ip_repr, LOCAL_IPV6_REPR); - assert_eq!(icmp_repr, ECHOV6_REPR.into()); + assert_eq!( + socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| { + assert_eq!(ip_repr, LOCAL_IPV6_REPR); + assert_eq!(icmp_repr, ECHOV6_REPR.into()); + Err(Error::Unaddressable) + }), Err(Error::Unaddressable) - }), Err(Error::Unaddressable)); + ); // buffer is not taken off of the tx queue due to the error assert!(!socket.can_send()); - assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| { - assert_eq!(ip_repr, LOCAL_IPV6_REPR); - assert_eq!(icmp_repr, ECHOV6_REPR.into()); + assert_eq!( + socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| { + assert_eq!(ip_repr, LOCAL_IPV6_REPR); + assert_eq!(icmp_repr, ECHOV6_REPR.into()); + Ok(()) + }), Ok(()) - }), Ok(())); + ); // buffer is taken off of the queue this time assert!(socket.can_send()); } @@ -774,21 +908,35 @@ mod test_ipv6 { let mut bytes = vec![0xff; 24]; let mut packet = Icmpv6Packet::new_unchecked(&mut bytes); - ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum); + ECHOV6_REPR.emit( + &LOCAL_IPV6.into(), + &REMOTE_IPV6.into(), + &mut packet, + &checksum, + ); s.set_hop_limit(Some(0x2a)); - assert_eq!(s.send_slice(&packet.into_inner()[..], REMOTE_IPV6.into()), Ok(())); - assert_eq!(s.dispatch(&Context::DUMMY, |(ip_repr, _)| { - assert_eq!(ip_repr, IpRepr::Ipv6(Ipv6Repr { - src_addr: Ipv6Address::UNSPECIFIED, - dst_addr: REMOTE_IPV6, - next_header: IpProtocol::Icmpv6, - payload_len: ECHOV6_REPR.buffer_len(), - hop_limit: 0x2a, - })); + assert_eq!( + s.send_slice(&packet.into_inner()[..], REMOTE_IPV6.into()), Ok(()) - }), Ok(())); + ); + assert_eq!( + s.dispatch(&Context::DUMMY, |(ip_repr, _)| { + assert_eq!( + ip_repr, + IpRepr::Ipv6(Ipv6Repr { + src_addr: Ipv6Address::UNSPECIFIED, + dst_addr: REMOTE_IPV6, + next_header: IpProtocol::Icmpv6, + payload_len: ECHOV6_REPR.buffer_len(), + hop_limit: 0x2a, + }) + ); + Ok(()) + }), + Ok(()) + ); } #[test] @@ -803,17 +951,26 @@ mod test_ipv6 { let mut bytes = [0xff; 24]; let mut packet = Icmpv6Packet::new_unchecked(&mut bytes); - ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum); + ECHOV6_REPR.emit( + &LOCAL_IPV6.into(), + &REMOTE_IPV6.into(), + &mut packet, + &checksum, + ); let data = &packet.into_inner()[..]; assert!(socket.accepts(&Context::DUMMY, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into())); - assert_eq!(socket.process(&Context::DUMMY, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()), - Ok(())); + assert_eq!( + socket.process(&Context::DUMMY, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()), + Ok(()) + ); assert!(socket.can_recv()); assert!(socket.accepts(&Context::DUMMY, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into())); - assert_eq!(socket.process(&Context::DUMMY, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()), - Err(Error::Exhausted)); + assert_eq!( + socket.process(&Context::DUMMY, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()), + Err(Error::Exhausted) + ); assert_eq!(socket.recv(), Ok((&data[..], REMOTE_IPV6.into()))); assert!(!socket.can_recv()); @@ -828,11 +985,16 @@ mod test_ipv6 { let mut bytes = [0xff; 20]; let mut packet = Icmpv6Packet::new_unchecked(&mut bytes); let icmp_repr = Icmpv6Repr::EchoRequest { - ident: 0x4321, + ident: 0x4321, seq_no: 0x5678, - data: &[0xff; 16] + data: &[0xff; 16], }; - icmp_repr.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum); + icmp_repr.emit( + &LOCAL_IPV6.into(), + &REMOTE_IPV6.into(), + &mut packet, + &checksum, + ); // Ensure that a packet with an identifier that isn't the bound // ID is not accepted @@ -854,7 +1016,8 @@ mod test_ipv6 { &LOCAL_IPV6.into(), UDP_PAYLOAD.len(), |buf| buf.copy_from_slice(UDP_PAYLOAD), - &checksum); + &checksum, + ); let data = &packet.into_inner()[..]; @@ -865,16 +1028,16 @@ mod test_ipv6 { dst_addr: REMOTE_IPV6, next_header: IpProtocol::Icmpv6, payload_len: 12, - hop_limit: 0x40 + hop_limit: 0x40, }, - data: data + data: data, }; let ip_repr = IpRepr::Unspecified { src_addr: REMOTE_IPV6.into(), dst_addr: LOCAL_IPV6.into(), protocol: IpProtocol::Icmpv6, payload_len: icmp_repr.buffer_len(), - hop_limit: 0x40 + hop_limit: 0x40, }; assert!(!socket.can_recv()); @@ -882,14 +1045,24 @@ mod test_ipv6 { // Ensure we can accept ICMP error response to the bound // UDP port assert!(socket.accepts(&Context::DUMMY, &ip_repr, &icmp_repr.into())); - assert_eq!(socket.process(&Context::DUMMY, &ip_repr, &icmp_repr.into()), - Ok(())); + assert_eq!( + socket.process(&Context::DUMMY, &ip_repr, &icmp_repr.into()), + Ok(()) + ); assert!(socket.can_recv()); let mut bytes = [0x00; 66]; let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]); - icmp_repr.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum); - assert_eq!(socket.recv(), Ok((&packet.into_inner()[..], REMOTE_IPV6.into()))); + icmp_repr.emit( + &LOCAL_IPV6.into(), + &REMOTE_IPV6.into(), + &mut packet, + &checksum, + ); + assert_eq!( + socket.recv(), + Ok((&packet.into_inner()[..], REMOTE_IPV6.into())) + ); assert!(!socket.can_recv()); } } diff --git a/src/socket/meta.rs b/src/socket/meta.rs index fe6873b..3d490db 100644 --- a/src/socket/meta.rs +++ b/src/socket/meta.rs @@ -1,6 +1,6 @@ -use crate::wire::IpAddress; -use crate::socket::{SocketHandle, PollAt}; +use crate::socket::{PollAt, SocketHandle}; use crate::time::{Duration, Instant}; +use crate::wire::IpAddress; /// Neighbor dependency. /// @@ -16,7 +16,7 @@ enum NeighborState { Waiting { neighbor: IpAddress, silent_until: Instant, - } + }, } impl Default for NeighborState { @@ -36,7 +36,7 @@ pub struct Meta { /// Mainly useful for debug output. pub(crate) handle: SocketHandle, /// See [NeighborState](struct.NeighborState.html). - neighbor_state: NeighborState, + neighbor_state: NeighborState, } impl Meta { @@ -46,34 +46,41 @@ impl Meta { /// See also `iface::NeighborCache::SILENT_TIME`. pub(crate) const DISCOVERY_SILENT_TIME: Duration = Duration { millis: 3_000 }; - pub(crate) fn poll_at(&self, socket_poll_at: PollAt, has_neighbor: F) -> PollAt - where F: Fn(IpAddress) -> bool + pub(crate) fn poll_at(&self, socket_poll_at: PollAt, has_neighbor: F) -> PollAt + where + F: Fn(IpAddress) -> bool, { match self.neighbor_state { - NeighborState::Active => - socket_poll_at, - NeighborState::Waiting { neighbor, .. } - if has_neighbor(neighbor) => - socket_poll_at, - NeighborState::Waiting { silent_until, .. } => - PollAt::Time(silent_until) + NeighborState::Active => socket_poll_at, + NeighborState::Waiting { neighbor, .. } if has_neighbor(neighbor) => socket_poll_at, + NeighborState::Waiting { silent_until, .. } => PollAt::Time(silent_until), } } pub(crate) fn egress_permitted(&mut self, timestamp: Instant, has_neighbor: F) -> bool - where F: Fn(IpAddress) -> bool + where + F: Fn(IpAddress) -> bool, { match self.neighbor_state { - NeighborState::Active => - true, - NeighborState::Waiting { neighbor, silent_until } => { + NeighborState::Active => true, + NeighborState::Waiting { + neighbor, + silent_until, + } => { if has_neighbor(neighbor) { - net_trace!("{}: neighbor {} discovered, unsilencing", - self.handle, neighbor); + net_trace!( + "{}: neighbor {} discovered, unsilencing", + self.handle, + neighbor + ); self.neighbor_state = NeighborState::Active; true } else if timestamp >= silent_until { - net_trace!("{}: neighbor {} silence timer expired, rediscovering", self.handle, neighbor); + net_trace!( + "{}: neighbor {} silence timer expired, rediscovering", + self.handle, + neighbor + ); true } else { false @@ -83,10 +90,15 @@ impl Meta { } pub(crate) fn neighbor_missing(&mut self, timestamp: Instant, neighbor: IpAddress) { - net_trace!("{}: neighbor {} missing, silencing until t+{}", - self.handle, neighbor, Self::DISCOVERY_SILENT_TIME); + net_trace!( + "{}: neighbor {} missing, silencing until t+{}", + self.handle, + neighbor, + Self::DISCOVERY_SILENT_TIME + ); self.neighbor_state = NeighborState::Waiting { - neighbor, silent_until: timestamp + Self::DISCOVERY_SILENT_TIME + neighbor, + silent_until: timestamp + Self::DISCOVERY_SILENT_TIME, }; } } diff --git a/src/socket/mod.rs b/src/socket/mod.rs index 1c01efb..b37c228 100644 --- a/src/socket/mod.rs +++ b/src/socket/mod.rs @@ -14,19 +14,22 @@ size for a buffer, allocate it, and let the networking stack use it. use crate::phy::DeviceCapabilities; use crate::time::Instant; +#[cfg(feature = "socket-dhcpv4")] +mod dhcpv4; +#[cfg(all( + feature = "socket-icmp", + any(feature = "proto-ipv4", feature = "proto-ipv6") +))] +mod icmp; mod meta; #[cfg(feature = "socket-raw")] mod raw; -#[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))] -mod icmp; -#[cfg(feature = "socket-udp")] -mod udp; +mod ref_; +mod set; #[cfg(feature = "socket-tcp")] mod tcp; -#[cfg(feature = "socket-dhcpv4")] -mod dhcpv4; -mod set; -mod ref_; +#[cfg(feature = "socket-udp")] +mod udp; #[cfg(feature = "async")] mod waker; @@ -36,30 +39,24 @@ pub(crate) use self::meta::Meta as SocketMeta; pub(crate) use self::waker::WakerRegistration; #[cfg(feature = "socket-raw")] -pub use self::raw::{RawPacketMetadata, - RawSocketBuffer, - RawSocket}; +pub use self::raw::{RawPacketMetadata, RawSocket, RawSocketBuffer}; -#[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))] -pub use self::icmp::{IcmpPacketMetadata, - IcmpSocketBuffer, - Endpoint as IcmpEndpoint, - IcmpSocket}; +#[cfg(all( + feature = "socket-icmp", + any(feature = "proto-ipv4", feature = "proto-ipv6") +))] +pub use self::icmp::{Endpoint as IcmpEndpoint, IcmpPacketMetadata, IcmpSocket, IcmpSocketBuffer}; #[cfg(feature = "socket-udp")] -pub use self::udp::{UdpPacketMetadata, - UdpSocketBuffer, - UdpSocket}; +pub use self::udp::{UdpPacketMetadata, UdpSocket, UdpSocketBuffer}; #[cfg(feature = "socket-tcp")] -pub use self::tcp::{SocketBuffer as TcpSocketBuffer, - State as TcpState, - TcpSocket}; +pub use self::tcp::{SocketBuffer as TcpSocketBuffer, State as TcpState, TcpSocket}; #[cfg(feature = "socket-dhcpv4")] -pub use self::dhcpv4::{Dhcpv4Socket, Config as Dhcpv4Config, Event as Dhcpv4Event}; +pub use self::dhcpv4::{Config as Dhcpv4Config, Dhcpv4Socket, Event as Dhcpv4Event}; -pub use self::set::{Set as SocketSet, Item as SocketSetItem, Handle as SocketHandle}; +pub use self::set::{Handle as SocketHandle, Item as SocketSetItem, Set as SocketSet}; pub use self::set::{Iter as SocketSetIter, IterMut as SocketSetIterMut}; pub use self::ref_::Ref as SocketRef; @@ -91,7 +88,10 @@ pub(crate) enum PollAt { pub enum Socket<'a> { #[cfg(feature = "socket-raw")] Raw(RawSocket<'a>), - #[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))] + #[cfg(all( + feature = "socket-icmp", + any(feature = "proto-ipv4", feature = "proto-ipv6") + ))] Icmp(IcmpSocket<'a>), #[cfg(feature = "socket-udp")] Udp(UdpSocket<'a>), @@ -152,15 +152,13 @@ impl<'a> SocketSession for Socket<'a> { /// A conversion trait for network sockets. pub trait AnySocket<'a>: SocketSession + Sized { - fn downcast<'c>(socket_ref: SocketRef<'c, Socket<'a>>) -> - Option>; + fn downcast<'c>(socket_ref: SocketRef<'c, Socket<'a>>) -> Option>; } macro_rules! from_socket { ($socket:ty, $variant:ident) => { impl<'a> AnySocket<'a> for $socket { - fn downcast<'c>(ref_: SocketRef<'c, Socket<'a>>) -> - Option> { + fn downcast<'c>(ref_: SocketRef<'c, Socket<'a>>) -> Option> { if let Socket::$variant(ref mut socket) = SocketRef::into_inner(ref_) { Some(SocketRef::new(socket)) } else { @@ -168,12 +166,15 @@ macro_rules! from_socket { } } } - } + }; } #[cfg(feature = "socket-raw")] from_socket!(RawSocket<'a>, Raw); -#[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))] +#[cfg(all( + feature = "socket-icmp", + any(feature = "proto-ipv4", feature = "proto-ipv6") +))] from_socket!(IcmpSocket<'a>, Icmp); #[cfg(feature = "socket-udp")] from_socket!(UdpSocket<'a>, Udp); @@ -193,14 +194,13 @@ pub(crate) struct Context { #[cfg(test)] impl Context { - pub(crate) const DUMMY: Context = Context { caps: DeviceCapabilities { #[cfg(feature = "medium-ethernet")] medium: crate::phy::Medium::Ethernet, #[cfg(not(feature = "medium-ethernet"))] medium: crate::phy::Medium::Ip, - checksum: crate::phy::ChecksumCapabilities{ + checksum: crate::phy::ChecksumCapabilities { #[cfg(feature = "proto-ipv4")] icmpv4: crate::phy::Checksum::Both, #[cfg(feature = "proto-ipv6")] @@ -216,7 +216,6 @@ impl Context { max_transmission_unit: 1500, }, ethernet_address: None, - now: Instant{millis: 0}, + now: Instant { millis: 0 }, }; - -} \ No newline at end of file +} diff --git a/src/socket/raw.rs b/src/socket/raw.rs index 0baa702..bf149c7 100644 --- a/src/socket/raw.rs +++ b/src/socket/raw.rs @@ -2,18 +2,18 @@ use core::cmp::min; #[cfg(feature = "async")] use core::task::Waker; -use crate::{Error, Result}; use crate::phy::ChecksumCapabilities; -use crate::socket::{Socket, SocketMeta, SocketHandle, PollAt, Context}; -use crate::storage::{PacketBuffer, PacketMetadata}; #[cfg(feature = "async")] use crate::socket::WakerRegistration; +use crate::socket::{Context, PollAt, Socket, SocketHandle, SocketMeta}; +use crate::storage::{PacketBuffer, PacketMetadata}; +use crate::{Error, Result}; -use crate::wire::{IpVersion, IpRepr, IpProtocol}; +use crate::wire::{IpProtocol, IpRepr, IpVersion}; #[cfg(feature = "proto-ipv4")] -use crate::wire::{Ipv4Repr, Ipv4Packet}; +use crate::wire::{Ipv4Packet, Ipv4Repr}; #[cfg(feature = "proto-ipv6")] -use crate::wire::{Ipv6Repr, Ipv6Packet}; +use crate::wire::{Ipv6Packet, Ipv6Repr}; /// A UDP packet metadata. pub type RawPacketMetadata = PacketMetadata<()>; @@ -28,10 +28,10 @@ pub type RawSocketBuffer<'a> = PacketBuffer<'a, ()>; #[derive(Debug)] pub struct RawSocket<'a> { pub(crate) meta: SocketMeta, - ip_version: IpVersion, + ip_version: IpVersion, ip_protocol: IpProtocol, - rx_buffer: RawSocketBuffer<'a>, - tx_buffer: RawSocketBuffer<'a>, + rx_buffer: RawSocketBuffer<'a>, + tx_buffer: RawSocketBuffer<'a>, #[cfg(feature = "async")] rx_waker: WakerRegistration, #[cfg(feature = "async")] @@ -41,9 +41,12 @@ pub struct RawSocket<'a> { impl<'a> RawSocket<'a> { /// Create a raw IP socket bound to the given IP version and datagram protocol, /// with the given buffers. - pub fn new(ip_version: IpVersion, ip_protocol: IpProtocol, - rx_buffer: RawSocketBuffer<'a>, - tx_buffer: RawSocketBuffer<'a>) -> RawSocket<'a> { + pub fn new( + ip_version: IpVersion, + ip_protocol: IpProtocol, + rx_buffer: RawSocketBuffer<'a>, + tx_buffer: RawSocketBuffer<'a>, + ) -> RawSocket<'a> { RawSocket { meta: SocketMeta::default(), ip_version, @@ -61,12 +64,12 @@ impl<'a> RawSocket<'a> { /// /// The waker is woken on state changes that might affect the return value /// of `recv` method calls, such as receiving data, or the socket closing. - /// + /// /// Notes: /// /// - Only one waker can be registered at a time. If another waker was previously registered, /// it is overwritten and will no longer be woken. - /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes. + /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes. /// - "Spurious wakes" are allowed: a wake doesn't guarantee the result of `recv` has /// necessarily changed. #[cfg(feature = "async")] @@ -79,12 +82,12 @@ impl<'a> RawSocket<'a> { /// The waker is woken on state changes that might affect the return value /// of `send` method calls, such as space becoming available in the transmit /// buffer, or the socket closing. - /// + /// /// Notes: /// /// - Only one waker can be registered at a time. If another waker was previously registered, /// it is overwritten and will no longer be woken. - /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes. + /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes. /// - "Spurious wakes" are allowed: a wake doesn't guarantee the result of `send` has /// necessarily changed. #[cfg(feature = "async")] @@ -160,9 +163,13 @@ impl<'a> RawSocket<'a> { pub fn send(&mut self, size: usize) -> Result<&mut [u8]> { let packet_buf = self.tx_buffer.enqueue(size, ())?; - net_trace!("{}:{}:{}: buffer to send {} octets", - self.meta.handle, self.ip_version, self.ip_protocol, - packet_buf.len()); + net_trace!( + "{}:{}:{}: buffer to send {} octets", + self.meta.handle, + self.ip_version, + self.ip_protocol, + packet_buf.len() + ); Ok(packet_buf) } @@ -183,9 +190,13 @@ impl<'a> RawSocket<'a> { pub fn recv(&mut self) -> Result<&[u8]> { let ((), packet_buf) = self.rx_buffer.dequeue()?; - net_trace!("{}:{}:{}: receive {} buffered octets", - self.meta.handle, self.ip_version, self.ip_protocol, - packet_buf.len()); + net_trace!( + "{}:{}:{}: receive {} buffered octets", + self.meta.handle, + self.ip_version, + self.ip_protocol, + packet_buf.len() + ); Ok(packet_buf) } @@ -200,8 +211,12 @@ impl<'a> RawSocket<'a> { } pub(crate) fn accepts(&self, ip_repr: &IpRepr) -> bool { - if ip_repr.version() != self.ip_version { return false } - if ip_repr.protocol() != self.ip_protocol { return false } + if ip_repr.version() != self.ip_version { + return false; + } + if ip_repr.protocol() != self.ip_protocol { + return false; + } true } @@ -210,14 +225,18 @@ impl<'a> RawSocket<'a> { debug_assert!(self.accepts(ip_repr)); let header_len = ip_repr.buffer_len(); - let total_len = header_len + payload.len(); + let total_len = header_len + payload.len(); let packet_buf = self.rx_buffer.enqueue(total_len, ())?; ip_repr.emit(&mut packet_buf[..header_len], &cx.caps.checksum); packet_buf[header_len..].copy_from_slice(payload); - net_trace!("{}:{}:{}: receiving {} octets", - self.meta.handle, self.ip_version, self.ip_protocol, - packet_buf.len()); + net_trace!( + "{}:{}:{}: receiving {} octets", + self.meta.handle, + self.ip_version, + self.ip_protocol, + packet_buf.len() + ); #[cfg(feature = "async")] self.rx_waker.wake(); @@ -226,14 +245,21 @@ impl<'a> RawSocket<'a> { } pub(crate) fn dispatch(&mut self, cx: &Context, emit: F) -> Result<()> - where F: FnOnce((IpRepr, &[u8])) -> Result<()> { - fn prepare<'a>(protocol: IpProtocol, buffer: &'a mut [u8], - _checksum_caps: &ChecksumCapabilities) -> Result<(IpRepr, &'a [u8])> { + where + F: FnOnce((IpRepr, &[u8])) -> Result<()>, + { + fn prepare<'a>( + protocol: IpProtocol, + buffer: &'a mut [u8], + _checksum_caps: &ChecksumCapabilities, + ) -> Result<(IpRepr, &'a [u8])> { match IpVersion::of_packet(buffer)? { #[cfg(feature = "proto-ipv4")] IpVersion::Ipv4 => { let mut packet = Ipv4Packet::new_checked(buffer)?; - if packet.protocol() != protocol { return Err(Error::Unaddressable) } + if packet.protocol() != protocol { + return Err(Error::Unaddressable); + } if _checksum_caps.ipv4.tx() { packet.fill_checksum(); } else { @@ -249,7 +275,9 @@ impl<'a> RawSocket<'a> { #[cfg(feature = "proto-ipv6")] IpVersion::Ipv6 => { let packet = Ipv6Packet::new_checked(buffer)?; - if packet.next_header() != protocol { return Err(Error::Unaddressable) } + if packet.next_header() != protocol { + return Err(Error::Unaddressable); + } let packet = Ipv6Packet::new_unchecked(&*packet.into_inner()); let ipv6_repr = Ipv6Repr::parse(&packet)?; Ok((IpRepr::Ipv6(ipv6_repr), packet.payload())) @@ -258,21 +286,29 @@ impl<'a> RawSocket<'a> { } } - let handle = self.meta.handle; + let handle = self.meta.handle; let ip_protocol = self.ip_protocol; - let ip_version = self.ip_version; + let ip_version = self.ip_version; self.tx_buffer.dequeue_with(|&mut (), packet_buf| { match prepare(ip_protocol, packet_buf, &cx.caps.checksum) { Ok((ip_repr, raw_packet)) => { - net_trace!("{}:{}:{}: sending {} octets", - handle, ip_version, ip_protocol, - ip_repr.buffer_len() + raw_packet.len()); + net_trace!( + "{}:{}:{}: sending {} octets", + handle, + ip_version, + ip_protocol, + ip_repr.buffer_len() + raw_packet.len() + ); emit((ip_repr, raw_packet)) } Err(error) => { - net_debug!("{}:{}:{}: dropping outgoing packet ({})", - handle, ip_version, ip_protocol, - error); + net_debug!( + "{}:{}:{}: dropping outgoing packet ({})", + handle, + ip_version, + ip_protocol, + error + ); // Return Ok(()) so the packet is dequeued. Ok(()) } @@ -302,26 +338,34 @@ impl<'a> Into> for RawSocket<'a> { #[cfg(test)] mod test { + use super::*; use crate::wire::IpRepr; #[cfg(feature = "proto-ipv4")] use crate::wire::{Ipv4Address, Ipv4Repr}; #[cfg(feature = "proto-ipv6")] use crate::wire::{Ipv6Address, Ipv6Repr}; - use super::*; fn buffer(packets: usize) -> RawSocketBuffer<'static> { - RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * packets]) + RawSocketBuffer::new( + vec![RawPacketMetadata::EMPTY; packets], + vec![0; 48 * packets], + ) } #[cfg(feature = "proto-ipv4")] mod ipv4_locals { use super::*; - pub fn socket(rx_buffer: RawSocketBuffer<'static>, - tx_buffer: RawSocketBuffer<'static>) - -> RawSocket<'static> { - RawSocket::new(IpVersion::Ipv4, IpProtocol::Unknown(IP_PROTO), - rx_buffer, tx_buffer) + pub fn socket( + rx_buffer: RawSocketBuffer<'static>, + tx_buffer: RawSocketBuffer<'static>, + ) -> RawSocket<'static> { + RawSocket::new( + IpVersion::Ipv4, + IpProtocol::Unknown(IP_PROTO), + rx_buffer, + tx_buffer, + ) } pub const IP_PROTO: u8 = 63; @@ -330,60 +374,54 @@ mod test { dst_addr: Ipv4Address([10, 0, 0, 2]), protocol: IpProtocol::Unknown(IP_PROTO), payload_len: 4, - hop_limit: 64 + hop_limit: 64, }); pub const PACKET_BYTES: [u8; 24] = [ - 0x45, 0x00, 0x00, 0x18, - 0x00, 0x00, 0x40, 0x00, - 0x40, 0x3f, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x01, - 0x0a, 0x00, 0x00, 0x02, - 0xaa, 0x00, 0x00, 0xff - ]; - pub const PACKET_PAYLOAD: [u8; 4] = [ - 0xaa, 0x00, 0x00, 0xff + 0x45, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x00, 0x40, 0x3f, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x01, 0x0a, 0x00, 0x00, 0x02, 0xaa, 0x00, 0x00, 0xff, ]; + pub const PACKET_PAYLOAD: [u8; 4] = [0xaa, 0x00, 0x00, 0xff]; } #[cfg(feature = "proto-ipv6")] mod ipv6_locals { use super::*; - pub fn socket(rx_buffer: RawSocketBuffer<'static>, - tx_buffer: RawSocketBuffer<'static>) - -> RawSocket<'static> { - RawSocket::new(IpVersion::Ipv6, IpProtocol::Unknown(IP_PROTO), - rx_buffer, tx_buffer) + pub fn socket( + rx_buffer: RawSocketBuffer<'static>, + tx_buffer: RawSocketBuffer<'static>, + ) -> RawSocket<'static> { + RawSocket::new( + IpVersion::Ipv6, + IpProtocol::Unknown(IP_PROTO), + rx_buffer, + tx_buffer, + ) } 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([ + 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, + ]), next_header: IpProtocol::Unknown(IP_PROTO), payload_len: 4, - hop_limit: 64 + hop_limit: 64, }); pub const PACKET_BYTES: [u8; 44] = [ - 0x60, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x3f, 0x40, - 0xfe, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0xfe, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, - 0xaa, 0x00, 0x00, 0xff + 0x60, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3f, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xaa, 0x00, + 0x00, 0xff, ]; - pub const PACKET_PAYLOAD: [u8; 4] = [ - 0xaa, 0x00, 0x00, 0xff - ]; + pub const PACKET_PAYLOAD: [u8; 4] = [0xaa, 0x00, 0x00, 0xff]; } macro_rules! reusable_ip_specific_tests { @@ -402,25 +440,33 @@ mod test { let mut socket = $socket(buffer(0), buffer(1)); assert!(socket.can_send()); - assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), - Err(Error::Exhausted)); + assert_eq!( + socket.dispatch(&Context::DUMMY, |_| unreachable!()), + Err(Error::Exhausted) + ); assert_eq!(socket.send_slice(&$packet[..]), Ok(())); assert_eq!(socket.send_slice(b""), Err(Error::Exhausted)); assert!(!socket.can_send()); - assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, ip_payload)| { - assert_eq!(ip_repr, $hdr); - assert_eq!(ip_payload, &$payload); + assert_eq!( + socket.dispatch(&Context::DUMMY, |(ip_repr, ip_payload)| { + assert_eq!(ip_repr, $hdr); + assert_eq!(ip_payload, &$payload); + Err(Error::Unaddressable) + }), Err(Error::Unaddressable) - }), Err(Error::Unaddressable)); + ); assert!(!socket.can_send()); - assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, ip_payload)| { - assert_eq!(ip_repr, $hdr); - assert_eq!(ip_payload, &$payload); + assert_eq!( + socket.dispatch(&Context::DUMMY, |(ip_repr, ip_payload)| { + assert_eq!(ip_repr, $hdr); + assert_eq!(ip_payload, &$payload); + Ok(()) + }), Ok(()) - }), Ok(())); + ); assert!(socket.can_send()); } @@ -444,20 +490,32 @@ mod test { buffer[..$packet.len()].copy_from_slice(&$packet[..]); assert!(socket.accepts(&$hdr)); - assert_eq!(socket.process(&Context::DUMMY, &$hdr, &buffer), Err(Error::Truncated)); + assert_eq!( + socket.process(&Context::DUMMY, &$hdr, &buffer), + Err(Error::Truncated) + ); } } - } + }; } #[cfg(feature = "proto-ipv4")] - reusable_ip_specific_tests!(ipv4, ipv4_locals::socket, ipv4_locals::HEADER_REPR, - ipv4_locals::PACKET_BYTES, ipv4_locals::PACKET_PAYLOAD); + reusable_ip_specific_tests!( + ipv4, + ipv4_locals::socket, + ipv4_locals::HEADER_REPR, + ipv4_locals::PACKET_BYTES, + ipv4_locals::PACKET_PAYLOAD + ); #[cfg(feature = "proto-ipv6")] - reusable_ip_specific_tests!(ipv6, ipv6_locals::socket, ipv6_locals::HEADER_REPR, - ipv6_locals::PACKET_BYTES, ipv6_locals::PACKET_PAYLOAD); - + reusable_ip_specific_tests!( + ipv6, + ipv6_locals::socket, + ipv6_locals::HEADER_REPR, + ipv6_locals::PACKET_BYTES, + ipv6_locals::PACKET_PAYLOAD + ); #[test] #[cfg(feature = "proto-ipv4")] @@ -470,15 +528,13 @@ mod test { Ipv4Packet::new_unchecked(&mut wrong_version).set_version(6); assert_eq!(socket.send_slice(&wrong_version[..]), Ok(())); - assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), - Ok(())); + assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), Ok(())); let mut wrong_protocol = ipv4_locals::PACKET_BYTES; Ipv4Packet::new_unchecked(&mut wrong_protocol).set_protocol(IpProtocol::Tcp); assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(())); - assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), - Ok(())); + assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), Ok(())); } #[cfg(feature = "proto-ipv6")] { @@ -488,15 +544,13 @@ mod test { Ipv6Packet::new_unchecked(&mut wrong_version[..]).set_version(4); assert_eq!(socket.send_slice(&wrong_version[..]), Ok(())); - assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), - Ok(())); + assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), Ok(())); let mut wrong_protocol = ipv6_locals::PACKET_BYTES; Ipv6Packet::new_unchecked(&mut wrong_protocol[..]).set_next_header(IpProtocol::Tcp); assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(())); - assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), - Ok(())); + assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), Ok(())); } } @@ -512,13 +566,25 @@ mod test { assert_eq!(socket.recv(), Err(Error::Exhausted)); assert!(socket.accepts(&ipv4_locals::HEADER_REPR)); - assert_eq!(socket.process(&Context::DUMMY, &ipv4_locals::HEADER_REPR, &ipv4_locals::PACKET_PAYLOAD), - Ok(())); + assert_eq!( + socket.process( + &Context::DUMMY, + &ipv4_locals::HEADER_REPR, + &ipv4_locals::PACKET_PAYLOAD + ), + Ok(()) + ); assert!(socket.can_recv()); assert!(socket.accepts(&ipv4_locals::HEADER_REPR)); - assert_eq!(socket.process(&Context::DUMMY, &ipv4_locals::HEADER_REPR, &ipv4_locals::PACKET_PAYLOAD), - Err(Error::Exhausted)); + assert_eq!( + socket.process( + &Context::DUMMY, + &ipv4_locals::HEADER_REPR, + &ipv4_locals::PACKET_PAYLOAD + ), + Err(Error::Exhausted) + ); assert_eq!(socket.recv(), Ok(&cksumd_packet[..])); assert!(!socket.can_recv()); } @@ -529,13 +595,25 @@ mod test { assert_eq!(socket.recv(), Err(Error::Exhausted)); assert!(socket.accepts(&ipv6_locals::HEADER_REPR)); - assert_eq!(socket.process(&Context::DUMMY, &ipv6_locals::HEADER_REPR, &ipv6_locals::PACKET_PAYLOAD), - Ok(())); + assert_eq!( + socket.process( + &Context::DUMMY, + &ipv6_locals::HEADER_REPR, + &ipv6_locals::PACKET_PAYLOAD + ), + Ok(()) + ); assert!(socket.can_recv()); assert!(socket.accepts(&ipv6_locals::HEADER_REPR)); - assert_eq!(socket.process(&Context::DUMMY, &ipv6_locals::HEADER_REPR, &ipv6_locals::PACKET_PAYLOAD), - Err(Error::Exhausted)); + assert_eq!( + socket.process( + &Context::DUMMY, + &ipv6_locals::HEADER_REPR, + &ipv6_locals::PACKET_PAYLOAD + ), + Err(Error::Exhausted) + ); assert_eq!(socket.recv(), Ok(&ipv6_locals::PACKET_BYTES[..])); assert!(!socket.can_recv()); } @@ -545,16 +623,24 @@ mod test { fn test_doesnt_accept_wrong_proto() { #[cfg(feature = "proto-ipv4")] { - let socket = RawSocket::new(IpVersion::Ipv4, - IpProtocol::Unknown(ipv4_locals::IP_PROTO+1), buffer(1), buffer(1)); + let socket = RawSocket::new( + IpVersion::Ipv4, + IpProtocol::Unknown(ipv4_locals::IP_PROTO + 1), + buffer(1), + buffer(1), + ); assert!(!socket.accepts(&ipv4_locals::HEADER_REPR)); #[cfg(feature = "proto-ipv6")] assert!(!socket.accepts(&ipv6_locals::HEADER_REPR)); } #[cfg(feature = "proto-ipv6")] { - let socket = RawSocket::new(IpVersion::Ipv6, - IpProtocol::Unknown(ipv6_locals::IP_PROTO+1), buffer(1), buffer(1)); + let socket = RawSocket::new( + IpVersion::Ipv6, + IpProtocol::Unknown(ipv6_locals::IP_PROTO + 1), + buffer(1), + buffer(1), + ); assert!(!socket.accepts(&ipv6_locals::HEADER_REPR)); #[cfg(feature = "proto-ipv4")] assert!(!socket.accepts(&ipv4_locals::HEADER_REPR)); diff --git a/src/socket/ref_.rs b/src/socket/ref_.rs index 3a52a77..93992c9 100644 --- a/src/socket/ref_.rs +++ b/src/socket/ref_.rs @@ -1,6 +1,5 @@ use core::ops::{Deref, DerefMut}; - /// A trait for tracking a socket usage session. /// /// Allows implementation of custom drop logic that runs only if the socket was changed @@ -13,7 +12,10 @@ pub trait Session { #[cfg(feature = "socket-raw")] impl<'a> Session for crate::socket::RawSocket<'a> {} -#[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))] +#[cfg(all( + feature = "socket-icmp", + any(feature = "proto-ipv4", feature = "proto-ipv6") +))] impl<'a> Session for crate::socket::IcmpSocket<'a> {} #[cfg(feature = "socket-udp")] impl<'a> Session for crate::socket::UdpSocket<'a> {} @@ -41,7 +43,9 @@ impl<'a, T: Session + 'a> Ref<'a, T> { /// /// [into_inner]: #method.into_inner pub fn new(socket: &'a mut T) -> Self { - Ref { socket: Some(socket) } + Ref { + socket: Some(socket), + } } /// Unwrap a smart pointer to a socket. diff --git a/src/socket/set.rs b/src/socket/set.rs index 74af317..cdfd757 100644 --- a/src/socket/set.rs +++ b/src/socket/set.rs @@ -1,9 +1,9 @@ use core::{fmt, slice}; use managed::ManagedSlice; -use crate::socket::{Socket, SocketRef, AnySocket}; #[cfg(feature = "socket-tcp")] use crate::socket::TcpState; +use crate::socket::{AnySocket, Socket, SocketRef}; /// An item of a socket set. /// @@ -12,7 +12,7 @@ use crate::socket::TcpState; #[derive(Debug)] pub struct Item<'a> { socket: Socket<'a>, - refs: usize + refs: usize, } /// A handle, identifying a socket in a set. @@ -31,13 +31,15 @@ impl fmt::Display for Handle { /// The lifetime `'a` is used when storing a `Socket<'a>`. #[derive(Debug)] pub struct Set<'a> { - sockets: ManagedSlice<'a, Option>> + sockets: ManagedSlice<'a, Option>>, } impl<'a> Set<'a> { /// Create a socket set using the provided storage. pub fn new(sockets: SocketsT) -> Set<'a> - where SocketsT: Into>>> { + where + SocketsT: Into>>>, + { let sockets = sockets.into(); Set { sockets } } @@ -47,10 +49,10 @@ impl<'a> Set<'a> { /// # Panics /// This function panics if the storage is fixed-size (not a `Vec`) and is full. pub fn add(&mut self, socket: T) -> Handle - where T: Into> + where + T: Into>, { - fn put<'a>(index: usize, slot: &mut Option>, - mut socket: Socket<'a>) -> Handle { + fn put<'a>(index: usize, slot: &mut Option>, mut socket: Socket<'a>) -> Handle { net_trace!("[{}]: adding", index); let handle = Handle(index); socket.meta_mut().handle = handle; @@ -62,7 +64,7 @@ impl<'a> Set<'a> { for (index, slot) in self.sockets.iter_mut().enumerate() { if slot.is_none() { - return put(index, slot, socket) + return put(index, slot, socket); } } @@ -86,11 +88,9 @@ impl<'a> Set<'a> { /// or the socket has the wrong type. pub fn get>(&mut self, handle: Handle) -> SocketRef { match self.sockets[handle.0].as_mut() { - Some(item) => { - T::downcast(SocketRef::new(&mut item.socket)) - .expect("handle refers to a socket of a wrong type") - } - None => panic!("handle does not refer to a valid socket") + Some(item) => T::downcast(SocketRef::new(&mut item.socket)) + .expect("handle refers to a socket of a wrong type"), + None => panic!("handle does not refer to a valid socket"), } } @@ -102,7 +102,7 @@ impl<'a> Set<'a> { net_trace!("[{}]: removing", handle.0); match self.sockets[handle.0].take() { Some(item) => item.socket, - None => panic!("handle does not refer to a valid socket") + None => panic!("handle does not refer to a valid socket"), } } @@ -124,10 +124,12 @@ impl<'a> Set<'a> { /// or if the reference count is already zero. pub fn release(&mut self, handle: Handle) { let refs = &mut self.sockets[handle.0] - .as_mut() - .expect("handle does not refer to a valid socket") - .refs; - if *refs == 0 { panic!("decreasing reference count past zero") } + .as_mut() + .expect("handle does not refer to a valid socket") + .refs; + if *refs == 0 { + panic!("decreasing reference count past zero") + } *refs -= 1 } @@ -138,27 +140,31 @@ impl<'a> Set<'a> { pub fn prune(&mut self) { for (index, item) in self.sockets.iter_mut().enumerate() { let mut may_remove = false; - if let Some(Item { refs: 0, ref mut socket }) = *item { + if let Some(Item { + refs: 0, + ref mut socket, + }) = *item + { match *socket { #[cfg(feature = "socket-raw")] - Socket::Raw(_) => - may_remove = true, - #[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))] - Socket::Icmp(_) => - may_remove = true, + Socket::Raw(_) => may_remove = true, + #[cfg(all( + feature = "socket-icmp", + any(feature = "proto-ipv4", feature = "proto-ipv6") + ))] + Socket::Icmp(_) => may_remove = true, #[cfg(feature = "socket-udp")] - Socket::Udp(_) => - may_remove = true, + Socket::Udp(_) => may_remove = true, #[cfg(feature = "socket-tcp")] - Socket::Tcp(ref mut socket) => + Socket::Tcp(ref mut socket) => { if socket.state() == TcpState::Closed { may_remove = true } else { socket.close() - }, + } + } #[cfg(feature = "socket-dhcpv4")] - Socket::Dhcpv4(_) => - may_remove = true, + Socket::Dhcpv4(_) => may_remove = true, } } if may_remove { @@ -170,12 +176,16 @@ impl<'a> Set<'a> { /// Iterate every socket in this set. pub fn iter<'d>(&'d self) -> Iter<'d, 'a> { - Iter { lower: self.sockets.iter() } + Iter { + lower: self.sockets.iter(), + } } /// Iterate every socket in this set, as SocketRef. pub fn iter_mut<'d>(&'d mut self) -> IterMut<'d, 'a> { - IterMut { lower: self.sockets.iter_mut() } + IterMut { + lower: self.sockets.iter_mut(), + } } } @@ -184,7 +194,7 @@ impl<'a> Set<'a> { /// This struct is created by the [iter](struct.SocketSet.html#method.iter) /// on [socket sets](struct.SocketSet.html). pub struct Iter<'a, 'b: 'a> { - lower: slice::Iter<'a, Option>> + lower: slice::Iter<'a, Option>>, } impl<'a, 'b: 'a> Iterator for Iter<'a, 'b> { @@ -193,7 +203,7 @@ impl<'a, 'b: 'a> Iterator for Iter<'a, 'b> { fn next(&mut self) -> Option { while let Some(item_opt) = self.lower.next() { if let Some(item) = item_opt.as_ref() { - return Some(&item.socket) + return Some(&item.socket); } } None @@ -214,7 +224,7 @@ impl<'a, 'b: 'a> Iterator for IterMut<'a, 'b> { fn next(&mut self) -> Option { while let Some(item_opt) = self.lower.next() { if let Some(item) = item_opt.as_mut() { - return Some(SocketRef::new(&mut item.socket)) + return Some(SocketRef::new(&mut item.socket)); } } None diff --git a/src/socket/tcp.rs b/src/socket/tcp.rs index 35e60eb..dc8ccea 100644 --- a/src/socket/tcp.rs +++ b/src/socket/tcp.rs @@ -2,17 +2,19 @@ // the parts of RFC 1122 that discuss TCP. Consult RFC 7414 when implementing // a new feature. -use core::{cmp, fmt, mem}; #[cfg(feature = "async")] use core::task::Waker; +use core::{cmp, fmt, mem}; -use crate::{Error, Result}; -use crate::time::{Duration, Instant}; -use crate::socket::{Socket, SocketMeta, SocketHandle, PollAt, Context}; -use crate::storage::{Assembler, RingBuffer}; #[cfg(feature = "async")] use crate::socket::WakerRegistration; -use crate::wire::{IpProtocol, IpRepr, IpAddress, IpEndpoint, TcpSeqNumber, TcpRepr, TcpControl, TCP_HEADER_LEN}; +use crate::socket::{Context, PollAt, Socket, SocketHandle, SocketMeta}; +use crate::storage::{Assembler, RingBuffer}; +use crate::time::{Duration, Instant}; +use crate::wire::{ + IpAddress, IpEndpoint, IpProtocol, IpRepr, TcpControl, TcpRepr, TcpSeqNumber, TCP_HEADER_LEN, +}; +use crate::{Error, Result}; /// A TCP socket ring buffer. pub type SocketBuffer<'a> = RingBuffer<'a, u8>; @@ -33,23 +35,23 @@ pub enum State { CloseWait, Closing, LastAck, - TimeWait + TimeWait, } impl fmt::Display for State { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - State::Closed => write!(f, "CLOSED"), - State::Listen => write!(f, "LISTEN"), - State::SynSent => write!(f, "SYN-SENT"), + State::Closed => write!(f, "CLOSED"), + State::Listen => write!(f, "LISTEN"), + State::SynSent => write!(f, "SYN-SENT"), State::SynReceived => write!(f, "SYN-RECEIVED"), State::Established => write!(f, "ESTABLISHED"), - State::FinWait1 => write!(f, "FIN-WAIT-1"), - State::FinWait2 => write!(f, "FIN-WAIT-2"), - State::CloseWait => write!(f, "CLOSE-WAIT"), - State::Closing => write!(f, "CLOSING"), - State::LastAck => write!(f, "LAST-ACK"), - State::TimeWait => write!(f, "TIME-WAIT") + State::FinWait1 => write!(f, "FIN-WAIT-1"), + State::FinWait2 => write!(f, "FIN-WAIT-2"), + State::CloseWait => write!(f, "CLOSE-WAIT"), + State::Closing => write!(f, "CLOSING"), + State::LastAck => write!(f, "LAST-ACK"), + State::TimeWait => write!(f, "TIME-WAIT"), } } } @@ -103,17 +105,27 @@ impl RttEstimator { fn sample(&mut self, new_rtt: u32) { // "Congestion Avoidance and Control", Van Jacobson, Michael J. Karels, 1988 self.rtt = (self.rtt * 7 + new_rtt + 7) / 8; - let diff = (self.rtt as i32 - new_rtt as i32 ).abs() as u32; + let diff = (self.rtt as i32 - new_rtt as i32).abs() as u32; self.deviation = (self.deviation * 3 + diff + 3) / 4; - + self.rto_count = 0; let rto = self.retransmission_timeout().millis(); - net_trace!("rtte: sample={:?} rtt={:?} dev={:?} rto={:?}", new_rtt, self.rtt, self.deviation, rto); + net_trace!( + "rtte: sample={:?} rtt={:?} dev={:?} rto={:?}", + new_rtt, + self.rtt, + self.deviation, + rto + ); } fn on_send(&mut self, timestamp: Instant, seq: TcpSeqNumber) { - if self.max_seq_sent.map(|max_seq_sent| seq > max_seq_sent).unwrap_or(true) { + if self + .max_seq_sent + .map(|max_seq_sent| seq > max_seq_sent) + .unwrap_or(true) + { self.max_seq_sent = Some(seq); if self.timestamp.is_none() { self.timestamp = Some((timestamp, seq)); @@ -145,9 +157,14 @@ impl RttEstimator { // all packets sent would incur a retransmit. To avoid this, force an estimate // increase if we see 3 consecutive retransmissions without any successful sample. self.rto_count = 0; - self.rtt = RTTE_MAX_RTO.min(self.rtt*2); + self.rtt = RTTE_MAX_RTO.min(self.rtt * 2); let rto = self.retransmission_timeout().millis(); - net_trace!("rtte: too many retransmissions, increasing: rtt={:?} dev={:?} rto={:?}", self.rtt, self.deviation, rto); + net_trace!( + "rtte: too many retransmissions, increasing: rtt={:?} dev={:?} rto={:?}", + self.rtt, + self.deviation, + rto + ); } } } @@ -160,59 +177,60 @@ enum Timer { }, Retransmit { expires_at: Instant, - delay: Duration + delay: Duration, }, FastRetransmit, Close { - expires_at: Instant - } + expires_at: Instant, + }, } const ACK_DELAY_DEFAULT: Duration = Duration { millis: 10 }; -const CLOSE_DELAY: Duration = Duration { millis: 10_000 }; +const CLOSE_DELAY: Duration = Duration { millis: 10_000 }; impl Default for Timer { fn default() -> Timer { - Timer::Idle { keep_alive_at: None } + Timer::Idle { + keep_alive_at: None, + } } } impl Timer { fn should_keep_alive(&self, timestamp: Instant) -> bool { match *self { - Timer::Idle { keep_alive_at: Some(keep_alive_at) } - if timestamp >= keep_alive_at => { - true - } - _ => false + Timer::Idle { + keep_alive_at: Some(keep_alive_at), + } if timestamp >= keep_alive_at => true, + _ => false, } } fn should_retransmit(&self, timestamp: Instant) -> Option { match *self { - Timer::Retransmit { expires_at, delay } - if timestamp >= expires_at => { + Timer::Retransmit { expires_at, delay } if timestamp >= expires_at => { Some(timestamp - expires_at + delay) - }, + } Timer::FastRetransmit => Some(Duration::from_millis(0)), - _ => None + _ => None, } } fn should_close(&self, timestamp: Instant) -> bool { match *self { - Timer::Close { expires_at } - if timestamp >= expires_at => { - true - } - _ => false + Timer::Close { expires_at } if timestamp >= expires_at => true, + _ => false, } } fn poll_at(&self) -> PollAt { match *self { - Timer::Idle { keep_alive_at: Some(keep_alive_at) } => PollAt::Time(keep_alive_at), - Timer::Idle { keep_alive_at: None } => PollAt::Ingress, + Timer::Idle { + keep_alive_at: Some(keep_alive_at), + } => PollAt::Time(keep_alive_at), + Timer::Idle { + keep_alive_at: None, + } => PollAt::Ingress, Timer::Retransmit { expires_at, .. } => PollAt::Time(expires_at), Timer::FastRetransmit => PollAt::Now, Timer::Close { expires_at } => PollAt::Time(expires_at), @@ -221,12 +239,15 @@ impl Timer { fn set_for_idle(&mut self, timestamp: Instant, interval: Option) { *self = Timer::Idle { - keep_alive_at: interval.map(|interval| timestamp + interval) + keep_alive_at: interval.map(|interval| timestamp + interval), } } fn set_keep_alive(&mut self) { - if let Timer::Idle { ref mut keep_alive_at } = *self { + if let Timer::Idle { + ref mut keep_alive_at, + } = *self + { if keep_alive_at.is_none() { *keep_alive_at = Some(Instant::from_millis(0)) } @@ -234,7 +255,10 @@ impl Timer { } fn rewind_keep_alive(&mut self, timestamp: Instant, interval: Option) { - if let Timer::Idle { ref mut keep_alive_at } = *self { + if let Timer::Idle { + ref mut keep_alive_at, + } = *self + { *keep_alive_at = interval.map(|interval| timestamp + interval) } } @@ -244,18 +268,17 @@ impl Timer { Timer::Idle { .. } | Timer::FastRetransmit { .. } => { *self = Timer::Retransmit { expires_at: timestamp + delay, - delay: delay, + delay: delay, } } - Timer::Retransmit { expires_at, delay } - if timestamp >= expires_at => { + Timer::Retransmit { expires_at, delay } if timestamp >= expires_at => { *self = Timer::Retransmit { expires_at: timestamp + delay, - delay: delay * 2 + delay: delay * 2, } } Timer::Retransmit { .. } => (), - Timer::Close { .. } => () + Timer::Close { .. } => (), } } @@ -265,13 +288,13 @@ impl Timer { fn set_for_close(&mut self, timestamp: Instant) { *self = Timer::Close { - expires_at: timestamp + CLOSE_DELAY + expires_at: timestamp + CLOSE_DELAY, } } fn is_retransmit(&self) -> bool { match *self { - Timer::Retransmit {..} | Timer::FastRetransmit => true, + Timer::Retransmit { .. } | Timer::FastRetransmit => true, _ => false, } } @@ -286,27 +309,27 @@ impl Timer { #[derive(Debug)] pub struct TcpSocket<'a> { pub(crate) meta: SocketMeta, - state: State, - timer: Timer, - rtte: RttEstimator, - assembler: Assembler, - rx_buffer: SocketBuffer<'a>, + state: State, + timer: Timer, + rtte: RttEstimator, + assembler: Assembler, + rx_buffer: SocketBuffer<'a>, rx_fin_received: bool, - tx_buffer: SocketBuffer<'a>, + tx_buffer: SocketBuffer<'a>, /// Interval after which, if no inbound packets are received, the connection is aborted. - timeout: Option, + timeout: Option, /// Interval at which keep-alive packets will be sent. - keep_alive: Option, + keep_alive: Option, /// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets. - hop_limit: Option, + hop_limit: Option, /// Address passed to listen(). Listen address is set when listen() is called and /// used every time the socket is reset back to the LISTEN state. - listen_address: IpAddress, + listen_address: IpAddress, /// Current local endpoint. This is used for both filtering the incoming packets and /// setting the source address. When listening or initiating connection on/from /// an unspecified address, this field is updated with the chosen source address before /// any packets are sent. - local_endpoint: IpEndpoint, + local_endpoint: IpEndpoint, /// Current remote endpoint. This is used for both filtering the incoming packets and /// setting the destination address. If the remote endpoint is unspecified, it means that /// aborting the connection will not send an RST, and, in TIME-WAIT state, will not @@ -314,10 +337,10 @@ pub struct TcpSocket<'a> { remote_endpoint: IpEndpoint, /// The sequence number corresponding to the beginning of the transmit buffer. /// I.e. an ACK(local_seq_no+n) packet removes n bytes from the transmit buffer. - local_seq_no: TcpSeqNumber, + local_seq_no: TcpSeqNumber, /// The sequence number corresponding to the beginning of the receive buffer. /// I.e. userspace reading n bytes adds n to remote_seq_no. - remote_seq_no: TcpSeqNumber, + remote_seq_no: TcpSeqNumber, /// The last sequence number sent. /// I.e. in an idle socket, local_seq_no+tx_buffer.len(). remote_last_seq: TcpSeqNumber, @@ -331,15 +354,15 @@ pub struct TcpSocket<'a> { remote_win_shift: u8, /// The remote window size, relative to local_seq_no /// I.e. we're allowed to send octets until local_seq_no+remote_win_len - remote_win_len: usize, + remote_win_len: usize, /// The receive window scaling factor for remotes which support RFC 1323, None if unsupported. remote_win_scale: Option, /// Whether or not the remote supports selective ACK as described in RFC 2018. remote_has_sack: bool, /// The maximum number of data octets that the remote side may receive. - remote_mss: usize, + remote_mss: usize, /// The timestamp of the last packet received. - remote_last_ts: Option, + remote_last_ts: Option, /// The sequence number of the last packet recived, used for sACK local_rx_last_seq: Option, /// The ACK number of the last packet recived. @@ -349,7 +372,7 @@ pub struct TcpSocket<'a> { local_rx_dup_acks: u8, /// Duration for Delayed ACK. If None no ACKs will be delayed. - ack_delay: Option, + ack_delay: Option, /// Delayed ack timer. If set, packets containing exclusively /// ACK or window updates (ie, no data) won't be sent until expiry. ack_delay_until: Option, @@ -361,7 +384,6 @@ pub struct TcpSocket<'a> { rx_waker: WakerRegistration, #[cfg(feature = "async")] tx_waker: WakerRegistration, - } const DEFAULT_MSS: usize = 536; @@ -370,7 +392,9 @@ impl<'a> TcpSocket<'a> { #[allow(unused_comparisons)] // small usize platforms always pass rx_capacity check /// Create a socket using the given buffers. pub fn new(rx_buffer: T, tx_buffer: T) -> TcpSocket<'a> - where T: Into> { + where + T: Into>, + { let (rx_buffer, tx_buffer) = (rx_buffer.into(), tx_buffer.into()); let rx_capacity = rx_buffer.capacity(); @@ -381,39 +405,38 @@ impl<'a> TcpSocket<'a> { if rx_capacity > (1 << 30) { panic!("receiving buffer too large, cannot exceed 1 GiB") } - let rx_cap_log2 = mem::size_of::() * 8 - - rx_capacity.leading_zeros() as usize; + let rx_cap_log2 = mem::size_of::() * 8 - rx_capacity.leading_zeros() as usize; TcpSocket { - meta: SocketMeta::default(), - state: State::Closed, - timer: Timer::default(), - rtte: RttEstimator::default(), - assembler: Assembler::new(rx_buffer.capacity()), - tx_buffer: tx_buffer, - rx_buffer: rx_buffer, + meta: SocketMeta::default(), + state: State::Closed, + timer: Timer::default(), + rtte: RttEstimator::default(), + assembler: Assembler::new(rx_buffer.capacity()), + tx_buffer: tx_buffer, + rx_buffer: rx_buffer, rx_fin_received: false, - timeout: None, - keep_alive: None, - hop_limit: None, - listen_address: IpAddress::default(), - local_endpoint: IpEndpoint::default(), + timeout: None, + keep_alive: None, + hop_limit: None, + listen_address: IpAddress::default(), + local_endpoint: IpEndpoint::default(), remote_endpoint: IpEndpoint::default(), - local_seq_no: INITIAL_SEQ_NO, - remote_seq_no: TcpSeqNumber::default(), + local_seq_no: INITIAL_SEQ_NO, + remote_seq_no: TcpSeqNumber::default(), remote_last_seq: TcpSeqNumber::default(), remote_last_ack: None, remote_last_win: 0, - remote_win_len: 0, + remote_win_len: 0, remote_win_shift: rx_cap_log2.saturating_sub(16) as u8, remote_win_scale: None, remote_has_sack: false, - remote_mss: DEFAULT_MSS, - remote_last_ts: None, + remote_mss: DEFAULT_MSS, + remote_last_ts: None, local_rx_last_ack: None, local_rx_last_seq: None, local_rx_dup_acks: 0, - ack_delay: Some(ACK_DELAY_DEFAULT), + ack_delay: Some(ACK_DELAY_DEFAULT), ack_delay_until: None, nagle: true, @@ -428,12 +451,12 @@ impl<'a> TcpSocket<'a> { /// /// The waker is woken on state changes that might affect the return value /// of `recv` method calls, such as receiving data, or the socket closing. - /// + /// /// Notes: /// /// - Only one waker can be registered at a time. If another waker was previously registered, /// it is overwritten and will no longer be woken. - /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes. + /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes. /// - "Spurious wakes" are allowed: a wake doesn't guarantee the result of `recv` has /// necessarily changed. #[cfg(feature = "async")] @@ -446,12 +469,12 @@ impl<'a> TcpSocket<'a> { /// The waker is woken on state changes that might affect the return value /// of `send` method calls, such as space becoming available in the transmit /// buffer, or the socket closing. - /// + /// /// Notes: /// /// - Only one waker can be registered at a time. If another waker was previously registered, /// it is overwritten and will no longer be woken. - /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes. + /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes. /// - "Spurious wakes" are allowed: a wake doesn't guarantee the result of `send` has /// necessarily changed. #[cfg(feature = "async")] @@ -492,8 +515,10 @@ impl<'a> TcpSocket<'a> { /// #[inline] fn scaled_window(&self) -> u16 { - cmp::min(self.rx_buffer.window() >> self.remote_win_shift as usize, - (1 << 16) - 1) as u16 + cmp::min( + self.rx_buffer.window() >> self.remote_win_shift as usize, + (1 << 16) - 1, + ) as u16 } /// Set the timeout duration. @@ -520,10 +545,10 @@ impl<'a> TcpSocket<'a> { /// Enable or disable Nagle's Algorithm. /// - /// Also known as "tinygram prevention". By default, it is enabled. + /// Also known as "tinygram prevention". By default, it is enabled. /// Disabling it is equivalent to Linux's TCP_NODELAY flag. /// - /// When enabled, Nagle's Algorithm prevents sending segments smaller than MSS if + /// When enabled, Nagle's Algorithm prevents sending segments smaller than MSS if /// there is data in flight (sent but not acknowledged). In other words, it ensures /// at most only one segment smaller than MSS is in flight at a time. /// @@ -608,33 +633,33 @@ impl<'a> TcpSocket<'a> { } fn reset(&mut self) { - let rx_cap_log2 = mem::size_of::() * 8 - - self.rx_buffer.capacity().leading_zeros() as usize; + let rx_cap_log2 = + mem::size_of::() * 8 - self.rx_buffer.capacity().leading_zeros() as usize; - self.state = State::Closed; - self.timer = Timer::default(); - self.rtte = RttEstimator::default(); - self.assembler = Assembler::new(self.rx_buffer.capacity()); + self.state = State::Closed; + self.timer = Timer::default(); + self.rtte = RttEstimator::default(); + self.assembler = Assembler::new(self.rx_buffer.capacity()); self.tx_buffer.clear(); self.rx_buffer.clear(); self.rx_fin_received = false; - self.keep_alive = None; - self.timeout = None; - self.hop_limit = None; - self.listen_address = IpAddress::default(); - self.local_endpoint = IpEndpoint::default(); + self.keep_alive = None; + self.timeout = None; + self.hop_limit = None; + self.listen_address = IpAddress::default(); + self.local_endpoint = IpEndpoint::default(); self.remote_endpoint = IpEndpoint::default(); - self.local_seq_no = INITIAL_SEQ_NO; - self.remote_seq_no = TcpSeqNumber::default(); + self.local_seq_no = INITIAL_SEQ_NO; + self.remote_seq_no = TcpSeqNumber::default(); self.remote_last_seq = TcpSeqNumber::default(); self.remote_last_ack = None; self.remote_last_win = 0; - self.remote_win_len = 0; + self.remote_win_len = 0; self.remote_win_scale = None; self.remote_win_shift = rx_cap_log2.saturating_sub(16) as u8; - self.remote_mss = DEFAULT_MSS; - self.remote_last_ts = None; - self.ack_delay = Some(ACK_DELAY_DEFAULT); + self.remote_mss = DEFAULT_MSS; + self.remote_last_ts = None; + self.ack_delay = Some(ACK_DELAY_DEFAULT); self.ack_delay_until = None; self.nagle = true; @@ -651,15 +676,21 @@ impl<'a> TcpSocket<'a> { /// (see [is_open](#method.is_open)), and `Err(Error::Unaddressable)` /// if the port in the given endpoint is zero. pub fn listen(&mut self, local_endpoint: T) -> Result<()> - where T: Into { + where + T: Into, + { let local_endpoint = local_endpoint.into(); - if local_endpoint.port == 0 { return Err(Error::Unaddressable) } + if local_endpoint.port == 0 { + return Err(Error::Unaddressable); + } - if self.is_open() { return Err(Error::Illegal) } + if self.is_open() { + return Err(Error::Illegal); + } self.reset(); - self.listen_address = local_endpoint.addr; - self.local_endpoint = local_endpoint; + self.listen_address = local_endpoint.addr; + self.local_endpoint = local_endpoint; self.remote_endpoint = IpEndpoint::default(); self.set_state(State::Listen); Ok(()) @@ -680,13 +711,22 @@ impl<'a> TcpSocket<'a> { /// It also returns an error if the local or remote port is zero, or if the remote address /// is unspecified. pub fn connect(&mut self, remote_endpoint: T, local_endpoint: U) -> Result<()> - where T: Into, U: Into { + where + T: Into, + U: Into, + { let remote_endpoint = remote_endpoint.into(); - let local_endpoint = local_endpoint.into(); + let local_endpoint = local_endpoint.into(); - if self.is_open() { return Err(Error::Illegal) } - if !remote_endpoint.is_specified() { return Err(Error::Unaddressable) } - if local_endpoint.port == 0 { return Err(Error::Unaddressable) } + if self.is_open() { + return Err(Error::Illegal); + } + if !remote_endpoint.is_specified() { + return Err(Error::Unaddressable); + } + if local_endpoint.port == 0 { + return Err(Error::Unaddressable); + } // If local address is not provided, use an unspecified address but a specified protocol. // This lets us lower IpRepr later to determine IP header size and calculate MSS, @@ -695,15 +735,18 @@ impl<'a> TcpSocket<'a> { IpAddress::Unspecified => remote_endpoint.addr.to_unspecified(), ip => ip, }; - let local_endpoint = IpEndpoint { addr: local_addr, ..local_endpoint }; + let local_endpoint = IpEndpoint { + addr: local_addr, + ..local_endpoint + }; // Carry over the local sequence number. let local_seq_no = self.local_seq_no; self.reset(); - self.local_endpoint = local_endpoint; + self.local_endpoint = local_endpoint; self.remote_endpoint = remote_endpoint; - self.local_seq_no = local_seq_no; + self.local_seq_no = local_seq_no; self.remote_last_seq = local_seq_no; self.set_state(State::SynSent); Ok(()) @@ -717,23 +760,23 @@ impl<'a> TcpSocket<'a> { pub fn close(&mut self) { match self.state { // In the LISTEN state there is no established connection. - State::Listen => - self.set_state(State::Closed), + State::Listen => self.set_state(State::Closed), // In the SYN-SENT state the remote endpoint is not yet synchronized and, upon // receiving an RST, will abort the connection. - State::SynSent => - self.set_state(State::Closed), + State::SynSent => self.set_state(State::Closed), // In the SYN-RECEIVED, ESTABLISHED and CLOSE-WAIT states the transmit half // of the connection is open, and needs to be explicitly closed with a FIN. - State::SynReceived | State::Established => - self.set_state(State::FinWait1), - State::CloseWait => - self.set_state(State::LastAck), + State::SynReceived | State::Established => self.set_state(State::FinWait1), + State::CloseWait => self.set_state(State::LastAck), // In the FIN-WAIT-1, FIN-WAIT-2, CLOSING, LAST-ACK, TIME-WAIT and CLOSED states, // the transmit half of the connection is already closed, and no further // action is needed. - State::FinWait1 | State::FinWait2 | State::Closing | - State::TimeWait | State::LastAck | State::Closed => () + State::FinWait1 + | State::FinWait2 + | State::Closing + | State::TimeWait + | State::LastAck + | State::Closed => (), } } @@ -755,7 +798,7 @@ impl<'a> TcpSocket<'a> { pub fn is_listening(&self) -> bool { match self.state { State::Listen => true, - _ => false + _ => false, } } @@ -772,7 +815,7 @@ impl<'a> TcpSocket<'a> { match self.state { State::Closed => false, State::TimeWait => false, - _ => true + _ => true, } } @@ -794,7 +837,7 @@ impl<'a> TcpSocket<'a> { State::Closed => false, State::TimeWait => false, State::Listen => false, - _ => true + _ => true, } } @@ -814,7 +857,7 @@ impl<'a> TcpSocket<'a> { // In CLOSE-WAIT, the remote endpoint has closed our receive half of the connection // but we still can transmit indefinitely. State::CloseWait => true, - _ => false + _ => false, } } @@ -835,7 +878,7 @@ impl<'a> TcpSocket<'a> { State::FinWait1 | State::FinWait2 => true, // If we have something in the receive buffer, we can receive that. _ if !self.rx_buffer.is_empty() => true, - _ => false + _ => false, } } @@ -843,7 +886,9 @@ impl<'a> TcpSocket<'a> { /// (see [may_send](#method.may_send), and the transmit buffer is not full. #[inline] pub fn can_send(&self) -> bool { - if !self.may_send() { return false } + if !self.may_send() { + return false; + } !self.tx_buffer.is_full() } @@ -864,27 +909,40 @@ impl<'a> TcpSocket<'a> { /// (see [may_recv](#method.may_recv), and the receive buffer is not empty. #[inline] pub fn can_recv(&self) -> bool { - if !self.may_recv() { return false } + if !self.may_recv() { + return false; + } !self.rx_buffer.is_empty() } fn send_impl<'b, F, R>(&'b mut self, f: F) -> Result - where F: FnOnce(&'b mut SocketBuffer<'a>) -> (usize, R) { - if !self.may_send() { return Err(Error::Illegal) } + where + F: FnOnce(&'b mut SocketBuffer<'a>) -> (usize, R), + { + if !self.may_send() { + return Err(Error::Illegal); + } // The connection might have been idle for a long time, and so remote_last_ts // would be far in the past. Unless we clear it here, we'll abort the connection // down over in dispatch() by erroneously detecting it as timed out. - if self.tx_buffer.is_empty() { self.remote_last_ts = None } + if self.tx_buffer.is_empty() { + self.remote_last_ts = None + } let _old_length = self.tx_buffer.len(); let (size, result) = f(&mut self.tx_buffer); if size > 0 { #[cfg(any(test, feature = "verbose"))] - net_trace!("{}:{}:{}: tx buffer: enqueueing {} octets (now {})", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - size, _old_length + size); + net_trace!( + "{}:{}:{}: tx buffer: enqueueing {} octets (now {})", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + size, + _old_length + size + ); } Ok(result) } @@ -895,10 +953,10 @@ impl<'a> TcpSocket<'a> { /// This function returns `Err(Error::Illegal)` if the transmit half of /// the connection is not open; see [may_send](#method.may_send). pub fn send<'b, F, R>(&'b mut self, f: F) -> Result - where F: FnOnce(&'b mut [u8]) -> (usize, R) { - self.send_impl(|tx_buffer| { - tx_buffer.enqueue_many_with(f) - }) + where + F: FnOnce(&'b mut [u8]) -> (usize, R), + { + self.send_impl(|tx_buffer| tx_buffer.enqueue_many_with(f)) } /// Enqueue a sequence of octets to be sent, and fill it from a slice. @@ -920,16 +978,18 @@ impl<'a> TcpSocket<'a> { // another (stale) SYN. (We do not support TCP Fast Open.) if !self.may_recv() { if self.rx_fin_received { - return Err(Error::Finished) + return Err(Error::Finished); } - return Err(Error::Illegal) + return Err(Error::Illegal); } Ok(()) } fn recv_impl<'b, F, R>(&'b mut self, f: F) -> Result - where F: FnOnce(&'b mut SocketBuffer<'a>) -> (usize, R) { + where + F: FnOnce(&'b mut SocketBuffer<'a>) -> (usize, R), + { self.recv_error_check()?; let _old_length = self.rx_buffer.len(); @@ -937,9 +997,14 @@ impl<'a> TcpSocket<'a> { self.remote_seq_no += size; if size > 0 { #[cfg(any(test, feature = "verbose"))] - net_trace!("{}:{}:{}: rx buffer: dequeueing {} octets (now {})", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - size, _old_length - size); + net_trace!( + "{}:{}:{}: rx buffer: dequeueing {} octets (now {})", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + size, + _old_length - size + ); } Ok(result) } @@ -955,10 +1020,10 @@ impl<'a> TcpSocket<'a> { /// In all other cases, `Err(Error::Illegal)` is returned and previously received data (if any) /// may be incomplete (truncated). pub fn recv<'b, F, R>(&'b mut self, f: F) -> Result - where F: FnOnce(&'b mut [u8]) -> (usize, R) { - self.recv_impl(|rx_buffer| { - rx_buffer.dequeue_many_with(f) - }) + where + F: FnOnce(&'b mut [u8]) -> (usize, R), + { + self.recv_impl(|rx_buffer| rx_buffer.dequeue_many_with(f)) } /// Dequeue a sequence of received octets, and fill a slice from it. @@ -984,9 +1049,13 @@ impl<'a> TcpSocket<'a> { let buffer = self.rx_buffer.get_allocated(0, size); if !buffer.is_empty() { #[cfg(any(test, feature = "verbose"))] - net_trace!("{}:{}:{}: rx buffer: peeking at {} octets", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - buffer.len()); + net_trace!( + "{}:{}:{}: rx buffer: peeking at {} octets", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + buffer.len() + ); } Ok(buffer) } @@ -1021,13 +1090,22 @@ impl<'a> TcpSocket<'a> { fn set_state(&mut self, state: State) { if self.state != state { if self.remote_endpoint.addr.is_unspecified() { - net_trace!("{}:{}: state={}=>{}", - self.meta.handle, self.local_endpoint, - self.state, state); + net_trace!( + "{}:{}: state={}=>{}", + self.meta.handle, + self.local_endpoint, + self.state, + state + ); } else { - net_trace!("{}:{}:{}: state={}=>{}", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - self.state, state); + net_trace!( + "{}:{}:{}: state={}=>{}", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + self.state, + state + ); } } @@ -1045,24 +1123,24 @@ impl<'a> TcpSocket<'a> { pub(crate) fn reply(ip_repr: &IpRepr, repr: &TcpRepr) -> (IpRepr, TcpRepr<'static>) { let reply_repr = TcpRepr { - src_port: repr.dst_port, - dst_port: repr.src_port, - control: TcpControl::None, - seq_number: TcpSeqNumber(0), - ack_number: None, - window_len: 0, + src_port: repr.dst_port, + dst_port: repr.src_port, + control: TcpControl::None, + seq_number: TcpSeqNumber(0), + ack_number: None, + window_len: 0, window_scale: None, max_seg_size: None, sack_permitted: false, - sack_ranges: [None, None, None], - payload: &[] + sack_ranges: [None, None, None], + payload: &[], }; let ip_reply_repr = IpRepr::Unspecified { - src_addr: ip_repr.dst_addr(), - dst_addr: ip_repr.src_addr(), - protocol: IpProtocol::Tcp, + src_addr: ip_repr.dst_addr(), + dst_addr: ip_repr.src_addr(), + protocol: IpProtocol::Tcp, payload_len: reply_repr.buffer_len(), - hop_limit: 64 + hop_limit: 64, }; (ip_reply_repr, reply_repr) } @@ -1112,8 +1190,9 @@ impl<'a> TcpSocket<'a> { reply_repr.sack_ranges[0] = None; if let Some(last_seg_seq) = self.local_rx_last_seq.map(|s| s.0 as u32) { - reply_repr.sack_ranges[0] = self.assembler.iter_data( - reply_repr.ack_number.map(|s| s.0 as usize).unwrap_or(0)) + reply_repr.sack_ranges[0] = self + .assembler + .iter_data(reply_repr.ack_number.map(|s| s.0 as usize).unwrap_or(0)) .map(|(left, right)| (left as u32, right as u32)) .find(|(left, right)| *left <= last_seg_seq && *right >= last_seg_seq); } @@ -1126,8 +1205,9 @@ impl<'a> TcpSocket<'a> { // through those, that is currently infeasable. Instead, we offer the range with // the lowest sequence number (if one exists) to hint at what segments would // most quickly advance the acknowledgement number. - reply_repr.sack_ranges[0] = self.assembler.iter_data( - reply_repr.ack_number.map(|s| s.0 as usize).unwrap_or(0)) + reply_repr.sack_ranges[0] = self + .assembler + .iter_data(reply_repr.ack_number.map(|s| s.0 as usize).unwrap_or(0)) .map(|(left, right)| (left as u32, right as u32)) .next(); } @@ -1139,29 +1219,46 @@ impl<'a> TcpSocket<'a> { } pub(crate) fn accepts(&self, ip_repr: &IpRepr, repr: &TcpRepr) -> bool { - if self.state == State::Closed { return false } + if self.state == State::Closed { + return false; + } // If we're still listening for SYNs and the packet has an ACK, it cannot // be destined to this socket, but another one may well listen on the same // local endpoint. - if self.state == State::Listen && repr.ack_number.is_some() { return false } + if self.state == State::Listen && repr.ack_number.is_some() { + return false; + } // Reject packets with a wrong destination. - if self.local_endpoint.port != repr.dst_port { return false } - if !self.local_endpoint.addr.is_unspecified() && - self.local_endpoint.addr != ip_repr.dst_addr() { return false } + if self.local_endpoint.port != repr.dst_port { + return false; + } + if !self.local_endpoint.addr.is_unspecified() + && self.local_endpoint.addr != ip_repr.dst_addr() + { + return false; + } // Reject packets from a source to which we aren't connected. - if self.remote_endpoint.port != 0 && - self.remote_endpoint.port != repr.src_port { return false } - if !self.remote_endpoint.addr.is_unspecified() && - self.remote_endpoint.addr != ip_repr.src_addr() { return false } + if self.remote_endpoint.port != 0 && self.remote_endpoint.port != repr.src_port { + return false; + } + if !self.remote_endpoint.addr.is_unspecified() + && self.remote_endpoint.addr != ip_repr.src_addr() + { + return false; + } true } - pub(crate) fn process(&mut self, cx: &Context, ip_repr: &IpRepr, repr: &TcpRepr) -> - Result)>> { + pub(crate) fn process( + &mut self, + cx: &Context, + ip_repr: &IpRepr, + repr: &TcpRepr, + ) -> Result)>> { debug_assert!(self.accepts(ip_repr, repr)); // Consider how much the sequence number space differs from the transmit buffer space. @@ -1172,7 +1269,7 @@ impl<'a> TcpSocket<'a> { State::FinWait1 | State::LastAck | State::Closing => (false, true), // In all other states we've already got acknowledgemetns for // all of the control flags we sent. - _ => (false, false) + _ => (false, false), }; let control_len = (sent_syn as usize) + (sent_fin as usize); @@ -1180,56 +1277,124 @@ impl<'a> TcpSocket<'a> { match (self.state, repr) { // An RST received in response to initial SYN is acceptable if it acknowledges // the initial SYN. - (State::SynSent, &TcpRepr { - control: TcpControl::Rst, ack_number: None, .. - }) => { - net_debug!("{}:{}:{}: unacceptable RST (expecting RST|ACK) \ + ( + State::SynSent, + &TcpRepr { + control: TcpControl::Rst, + ack_number: None, + .. + }, + ) => { + net_debug!( + "{}:{}:{}: unacceptable RST (expecting RST|ACK) \ in response to initial SYN", - self.meta.handle, self.local_endpoint, self.remote_endpoint); - return Err(Error::Dropped) + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); + return Err(Error::Dropped); } - (State::SynSent, &TcpRepr { - control: TcpControl::Rst, ack_number: Some(ack_number), .. - }) => { + ( + State::SynSent, + &TcpRepr { + control: TcpControl::Rst, + ack_number: Some(ack_number), + .. + }, + ) => { if ack_number != self.local_seq_no + 1 { - net_debug!("{}:{}:{}: unacceptable RST|ACK in response to initial SYN", - self.meta.handle, self.local_endpoint, self.remote_endpoint); - return Err(Error::Dropped) + net_debug!( + "{}:{}:{}: unacceptable RST|ACK in response to initial SYN", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); + return Err(Error::Dropped); } } // Any other RST need only have a valid sequence number. - (_, &TcpRepr { control: TcpControl::Rst, .. }) => (), + ( + _, + &TcpRepr { + control: TcpControl::Rst, + .. + }, + ) => (), // The initial SYN cannot contain an acknowledgement. - (State::Listen, &TcpRepr { ack_number: None, .. }) => (), + ( + State::Listen, + &TcpRepr { + ack_number: None, .. + }, + ) => (), // This case is handled above. - (State::Listen, &TcpRepr { ack_number: Some(_), .. }) => unreachable!(), + ( + State::Listen, + &TcpRepr { + ack_number: Some(_), + .. + }, + ) => unreachable!(), // Every packet after the initial SYN must be an acknowledgement. - (_, &TcpRepr { ack_number: None, .. }) => { - net_debug!("{}:{}:{}: expecting an ACK", - self.meta.handle, self.local_endpoint, self.remote_endpoint); - return Err(Error::Dropped) + ( + _, + &TcpRepr { + ack_number: None, .. + }, + ) => { + net_debug!( + "{}:{}:{}: expecting an ACK", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); + return Err(Error::Dropped); } // Any ACK in the SYN-SENT state must have the SYN flag set. - (State::SynSent, &TcpRepr { - control: TcpControl::None, ack_number: Some(_), .. - }) => { - net_debug!("{}:{}:{}: expecting a SYN|ACK", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + ( + State::SynSent, + &TcpRepr { + control: TcpControl::None, + ack_number: Some(_), + .. + }, + ) => { + net_debug!( + "{}:{}:{}: expecting a SYN|ACK", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); self.abort(); - return Err(Error::Dropped) + return Err(Error::Dropped); } // SYN|ACK in the SYN-SENT state must have the exact ACK number. - (State::SynSent, &TcpRepr { - control: TcpControl::Syn, ack_number: Some(ack_number), .. - }) => { + ( + State::SynSent, + &TcpRepr { + control: TcpControl::Syn, + ack_number: Some(ack_number), + .. + }, + ) => { if ack_number != self.local_seq_no + 1 { - net_debug!("{}:{}:{}: unacceptable SYN|ACK in response to initial SYN", - self.meta.handle, self.local_endpoint, self.remote_endpoint); - return Err(Error::Dropped) + net_debug!( + "{}:{}:{}: unacceptable SYN|ACK in response to initial SYN", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); + return Err(Error::Dropped); } } // Every acknowledgement must be for transmitted but unacknowledged data. - (_, &TcpRepr { ack_number: Some(ack_number), .. }) => { + ( + _, + &TcpRepr { + ack_number: Some(ack_number), + .. + }, + ) => { let unacknowledged = self.tx_buffer.len() + control_len; // Acceptable ACK range (both inclusive) @@ -1237,53 +1402,80 @@ impl<'a> TcpSocket<'a> { let ack_max = self.local_seq_no + unacknowledged; if ack_number < ack_min { - net_debug!("{}:{}:{}: duplicate ACK ({} not in {}...{})", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - ack_number, ack_min, ack_max); - return Err(Error::Dropped) + net_debug!( + "{}:{}:{}: duplicate ACK ({} not in {}...{})", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + ack_number, + ack_min, + ack_max + ); + return Err(Error::Dropped); } if ack_number > ack_max { - net_debug!("{}:{}:{}: unacceptable ACK ({} not in {}...{})", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - ack_number, ack_min, ack_max); - return Ok(Some(self.ack_reply(ip_repr, &repr))) + net_debug!( + "{}:{}:{}: unacceptable ACK ({} not in {}...{})", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + ack_number, + ack_min, + ack_max + ); + return Ok(Some(self.ack_reply(ip_repr, &repr))); } } } - let window_start = self.remote_seq_no + self.rx_buffer.len(); - let window_end = self.remote_seq_no + self.rx_buffer.capacity(); + let window_start = self.remote_seq_no + self.rx_buffer.len(); + let window_end = self.remote_seq_no + self.rx_buffer.capacity(); let segment_start = repr.seq_number; - let segment_end = repr.seq_number + repr.segment_len(); + let segment_end = repr.seq_number + repr.segment_len(); let payload_offset; match self.state { // In LISTEN and SYN-SENT states, we have not yet synchronized with the remote end. - State::Listen | State::SynSent => - payload_offset = 0, + State::Listen | State::SynSent => payload_offset = 0, // In all other states, segments must occupy a valid portion of the receive window. _ => { let mut segment_in_window = true; if window_start == window_end && segment_start != segment_end { - net_debug!("{}:{}:{}: non-zero-length segment with zero receive window, \ + net_debug!( + "{}:{}:{}: non-zero-length segment with zero receive window, \ will only send an ACK", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); segment_in_window = false; } if segment_start == segment_end && segment_end == window_start - 1 { - net_debug!("{}:{}:{}: received a keep-alive or window probe packet, \ + net_debug!( + "{}:{}:{}: received a keep-alive or window probe packet, \ will send an ACK", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); segment_in_window = false; - } else if !((window_start <= segment_start && segment_start <= window_end) && - (window_start <= segment_end && segment_end <= window_end)) { - net_debug!("{}:{}:{}: segment not in receive window \ + } else if !((window_start <= segment_start && segment_start <= window_end) + && (window_start <= segment_end && segment_end <= window_end)) + { + net_debug!( + "{}:{}:{}: segment not in receive window \ ({}..{} not intersecting {}..{}), will send challenge ACK", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - segment_start, segment_end, window_start, window_end); + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + segment_start, + segment_end, + window_start, + window_end + ); segment_in_window = false; } @@ -1298,7 +1490,7 @@ impl<'a> TcpSocket<'a> { self.timer.set_for_close(cx.now); } - return Ok(Some(self.ack_reply(ip_repr, &repr))) + return Ok(Some(self.ack_reply(ip_repr, &repr))); } } } @@ -1319,8 +1511,12 @@ impl<'a> TcpSocket<'a> { // space if all of that data is acknowledged. if sent_fin && self.tx_buffer.len() + 1 == ack_len { ack_len -= 1; - net_trace!("{}:{}:{}: received ACK of FIN", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_trace!( + "{}:{}:{}: received ACK of FIN", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); ack_of_fin = true; } @@ -1341,38 +1537,44 @@ impl<'a> TcpSocket<'a> { // Validate and update the state. match (self.state, control) { // RSTs are not accepted in the LISTEN state. - (State::Listen, TcpControl::Rst) => - return Err(Error::Dropped), + (State::Listen, TcpControl::Rst) => return Err(Error::Dropped), // RSTs in SYN-RECEIVED flip the socket back to the LISTEN state. (State::SynReceived, TcpControl::Rst) => { - net_trace!("{}:{}:{}: received RST", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_trace!( + "{}:{}:{}: received RST", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); self.local_endpoint.addr = self.listen_address; - self.remote_endpoint = IpEndpoint::default(); + self.remote_endpoint = IpEndpoint::default(); self.set_state(State::Listen); - return Ok(None) + return Ok(None); } // RSTs in any other state close the socket. (_, TcpControl::Rst) => { - net_trace!("{}:{}:{}: received RST", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_trace!( + "{}:{}:{}: received RST", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); self.set_state(State::Closed); - self.local_endpoint = IpEndpoint::default(); + self.local_endpoint = IpEndpoint::default(); self.remote_endpoint = IpEndpoint::default(); - return Ok(None) + return Ok(None); } // SYN packets in the LISTEN state change it to SYN-RECEIVED. (State::Listen, TcpControl::Syn) => { - net_trace!("{}:{}: received SYN", - self.meta.handle, self.local_endpoint); - self.local_endpoint = IpEndpoint::new(ip_repr.dst_addr(), repr.dst_port); + net_trace!("{}:{}: received SYN", self.meta.handle, self.local_endpoint); + self.local_endpoint = IpEndpoint::new(ip_repr.dst_addr(), repr.dst_port); self.remote_endpoint = IpEndpoint::new(ip_repr.src_addr(), repr.src_port); // FIXME: use something more secure here - self.local_seq_no = TcpSeqNumber(-repr.seq_number.0); - self.remote_seq_no = repr.seq_number + 1; + self.local_seq_no = TcpSeqNumber(-repr.seq_number.0); + self.remote_seq_no = repr.seq_number + 1; self.remote_last_seq = self.local_seq_no; self.remote_has_sack = repr.sack_permitted; if let Some(max_seg_size) = repr.max_seg_size { @@ -1397,7 +1599,7 @@ impl<'a> TcpSocket<'a> { // It's not obvious from RFC 793 that this is permitted, but // 7th and 8th steps in the "SEGMENT ARRIVES" event describe this behavior. (State::SynReceived, TcpControl::Fin) => { - self.remote_seq_no += 1; + self.remote_seq_no += 1; self.rx_fin_received = true; self.set_state(State::CloseWait); self.timer.set_for_idle(cx.now, self.keep_alive); @@ -1405,10 +1607,14 @@ impl<'a> TcpSocket<'a> { // SYN|ACK packets in the SYN-SENT state change it to ESTABLISHED. (State::SynSent, TcpControl::Syn) => { - net_trace!("{}:{}:{}: received SYN|ACK", - self.meta.handle, self.local_endpoint, self.remote_endpoint); - self.local_endpoint = IpEndpoint::new(ip_repr.dst_addr(), repr.dst_port); - self.remote_seq_no = repr.seq_number + 1; + net_trace!( + "{}:{}:{}: received SYN|ACK", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); + self.local_endpoint = IpEndpoint::new(ip_repr.dst_addr(), repr.dst_port); + self.remote_seq_no = repr.seq_number + 1; self.remote_last_seq = self.local_seq_no + 1; self.remote_last_ack = Some(repr.seq_number); self.remote_win_scale = repr.window_scale; @@ -1430,11 +1636,11 @@ impl<'a> TcpSocket<'a> { if !self.timer.is_retransmit() || ack_len != 0 { self.timer.set_for_idle(cx.now, self.keep_alive); } - }, + } // FIN packets in ESTABLISHED state indicate the remote side has closed. (State::Established, TcpControl::Fin) => { - self.remote_seq_no += 1; + self.remote_seq_no += 1; self.rx_fin_received = true; self.set_state(State::CloseWait); self.timer.set_for_idle(cx.now, self.keep_alive); @@ -1452,7 +1658,7 @@ impl<'a> TcpSocket<'a> { // FIN packets in FIN-WAIT-1 state change it to CLOSING, or to TIME-WAIT // if they also acknowledge our FIN. (State::FinWait1, TcpControl::Fin) => { - self.remote_seq_no += 1; + self.remote_seq_no += 1; self.rx_fin_received = true; if ack_of_fin { self.set_state(State::TimeWait); @@ -1470,7 +1676,7 @@ impl<'a> TcpSocket<'a> { // FIN packets in FIN-WAIT-2 state change it to TIME-WAIT. (State::FinWait2, TcpControl::Fin) => { - self.remote_seq_no += 1; + self.remote_seq_no += 1; self.rx_fin_received = true; self.set_state(State::TimeWait); self.timer.set_for_close(cx.now); @@ -1496,7 +1702,7 @@ impl<'a> TcpSocket<'a> { if ack_of_fin { // Clear the remote endpoint, or we'll send an RST there. self.set_state(State::Closed); - self.local_endpoint = IpEndpoint::default(); + self.local_endpoint = IpEndpoint::default(); self.remote_endpoint = IpEndpoint::default(); } else { self.timer.set_for_idle(cx.now, self.keep_alive); @@ -1504,9 +1710,14 @@ impl<'a> TcpSocket<'a> { } _ => { - net_debug!("{}:{}:{}: unexpected packet {}", - self.meta.handle, self.local_endpoint, self.remote_endpoint, repr); - return Err(Error::Dropped) + net_debug!( + "{}:{}:{}: unexpected packet {}", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + repr + ); + return Err(Error::Dropped); } } @@ -1524,9 +1735,14 @@ impl<'a> TcpSocket<'a> { if ack_len > 0 { // Dequeue acknowledged octets. debug_assert!(self.tx_buffer.len() >= ack_len); - net_trace!("{}:{}:{}: tx buffer: dequeueing {} octets (now {})", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - ack_len, self.tx_buffer.len() - ack_len); + net_trace!( + "{}:{}:{}: tx buffer: dequeueing {} octets (now {})", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + ack_len, + self.tx_buffer.len() - ack_len + ); self.tx_buffer.dequeue_allocated(ack_len); // There's new room available in tx_buffer, wake the waiting task if any. @@ -1546,29 +1762,48 @@ impl<'a> TcpSocket<'a> { // Duplicate ACK if payload empty and ACK doesn't move send window -> // Increment duplicate ACK count and set for retransmit if we just recived // the third duplicate ACK - Some(ref last_rx_ack) if - repr.payload.is_empty() && - *last_rx_ack == ack_number && - ack_number < self.remote_last_seq => { + Some(ref last_rx_ack) + if repr.payload.is_empty() + && *last_rx_ack == ack_number + && ack_number < self.remote_last_seq => + { // Increment duplicate ACK count self.local_rx_dup_acks = self.local_rx_dup_acks.saturating_add(1); - net_debug!("{}:{}:{}: received duplicate ACK for seq {} (duplicate nr {}{})", - self.meta.handle, self.local_endpoint, self.remote_endpoint, ack_number, - self.local_rx_dup_acks, if self.local_rx_dup_acks == u8::max_value() { "+" } else { "" }); + net_debug!( + "{}:{}:{}: received duplicate ACK for seq {} (duplicate nr {}{})", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + ack_number, + self.local_rx_dup_acks, + if self.local_rx_dup_acks == u8::max_value() { + "+" + } else { + "" + } + ); if self.local_rx_dup_acks == 3 { self.timer.set_for_fast_retransmit(); - net_debug!("{}:{}:{}: started fast retransmit", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_debug!( + "{}:{}:{}: started fast retransmit", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); } - }, + } // No duplicate ACK -> Reset state and update last recived ACK _ => { if self.local_rx_dup_acks > 0 { self.local_rx_dup_acks = 0; - net_debug!("{}:{}:{}: reset duplicate ACK count", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_debug!( + "{}:{}:{}: reset duplicate ACK count", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); } self.local_rx_last_ack = Some(ack_number); } @@ -1587,7 +1822,9 @@ impl<'a> TcpSocket<'a> { } let payload_len = repr.payload.len(); - if payload_len == 0 { return Ok(None) } + if payload_len == 0 { + return Ok(None); + } let assembler_was_empty = self.assembler.is_empty(); @@ -1596,25 +1833,41 @@ impl<'a> TcpSocket<'a> { Ok(()) => { debug_assert!(self.assembler.total_size() == self.rx_buffer.capacity()); // Place payload octets into the buffer. - net_trace!("{}:{}:{}: rx buffer: receiving {} octets at offset {}", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - payload_len, payload_offset); - self.rx_buffer.write_unallocated(payload_offset, repr.payload); + net_trace!( + "{}:{}:{}: rx buffer: receiving {} octets at offset {}", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + payload_len, + payload_offset + ); + self.rx_buffer + .write_unallocated(payload_offset, repr.payload); } Err(_) => { - net_debug!("{}:{}:{}: assembler: too many holes to add {} octets at offset {}", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - payload_len, payload_offset); - return Err(Error::Dropped) + net_debug!( + "{}:{}:{}: assembler: too many holes to add {} octets at offset {}", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + payload_len, + payload_offset + ); + return Err(Error::Dropped); } } if let Some(contig_len) = self.assembler.remove_front() { debug_assert!(self.assembler.total_size() == self.rx_buffer.capacity()); // Enqueue the contiguous data octets in front of the buffer. - net_trace!("{}:{}:{}: rx buffer: enqueueing {} octets (now {})", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - contig_len, self.rx_buffer.len() + contig_len); + net_trace!( + "{}:{}:{}: rx buffer: enqueueing {} octets (now {})", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + contig_len, + self.rx_buffer.len() + contig_len + ); self.rx_buffer.enqueue_unallocated(contig_len); // There's new data in rx_buffer, notify waiting task if any. @@ -1624,9 +1877,13 @@ impl<'a> TcpSocket<'a> { if !self.assembler.is_empty() { // Print the ranges recorded in the assembler. - net_trace!("{}:{}:{}: assembler: {}", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - self.assembler); + net_trace!( + "{}:{}:{}: assembler: {}", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + self.assembler + ); } // Handle delayed acks @@ -1634,8 +1891,11 @@ impl<'a> TcpSocket<'a> { if self.ack_to_transmit() || self.window_to_update() { self.ack_delay_until = match self.ack_delay_until { None => { - net_trace!("{}:{}:{}: starting delayed ack timer", - self.meta.handle, self.local_endpoint, self.remote_endpoint + net_trace!( + "{}:{}:{}: starting delayed ack timer", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint ); Some(cx.now + ack_delay) @@ -1644,8 +1904,11 @@ impl<'a> TcpSocket<'a> { // for at least every second segment". // For now, we send an ACK every second received packet, full-sized or not. Some(_) => { - net_trace!("{}:{}:{}: delayed ack timer already started, forcing expiry", - self.meta.handle, self.local_endpoint, self.remote_endpoint + net_trace!( + "{}:{}:{}: delayed ack timer already started, forcing expiry", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint ); None } @@ -1660,8 +1923,12 @@ impl<'a> TcpSocket<'a> { // Note that we change the transmitter state here. // This is fine because smoltcp assumes that it can always transmit zero or one // packets for every packet it receives. - net_trace!("{}:{}:{}: ACKing incoming segment", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_trace!( + "{}:{}:{}: ACKing incoming segment", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); Ok(Some(self.ack_reply(ip_repr, &repr))) } else { Ok(None) @@ -1670,10 +1937,8 @@ impl<'a> TcpSocket<'a> { fn timed_out(&self, timestamp: Instant) -> bool { match (self.remote_last_ts, self.timeout) { - (Some(remote_last_ts), Some(timeout)) => - timestamp >= remote_last_ts + timeout, - (_, _) => - false + (Some(remote_last_ts), Some(timeout)) => timestamp >= remote_last_ts + timeout, + (_, _) => false, } } @@ -1696,7 +1961,8 @@ impl<'a> TcpSocket<'a> { let data_in_flight = self.remote_last_seq != self.local_seq_no; // max sequence number we can send. - let max_send_seq = self.local_seq_no + core::cmp::min(self.remote_win_len, self.tx_buffer.len()); + let max_send_seq = + self.local_seq_no + core::cmp::min(self.remote_win_len, self.tx_buffer.len()); // Max amount of octets we can send. let max_send = if max_send_seq >= self.remote_last_seq { @@ -1726,8 +1992,7 @@ impl<'a> TcpSocket<'a> { // 1. We have unsent data that fits in the remote window. // 2. We have no unsent data. // This condition matches only if #2, because #1 is already covered by can_data and we're ORing them. - let can_fin = - want_fin && self.remote_last_seq == self.local_seq_no + self.tx_buffer.len(); + let can_fin = want_fin && self.remote_last_seq == self.local_seq_no + self.tx_buffer.len(); can_send || can_fin } @@ -1749,15 +2014,22 @@ impl<'a> TcpSocket<'a> { fn window_to_update(&self) -> bool { match self.state { - State::SynSent | State::SynReceived | State::Established | State::FinWait1 | State::FinWait2 => - self.scaled_window() > self.remote_last_win, + State::SynSent + | State::SynReceived + | State::Established + | State::FinWait1 + | State::FinWait2 => self.scaled_window() > self.remote_last_win, _ => false, } } pub(crate) fn dispatch(&mut self, cx: &Context, emit: F) -> Result<()> - where F: FnOnce((IpRepr, TcpRepr)) -> Result<()> { - if !self.remote_endpoint.is_specified() { return Err(Error::Exhausted) } + where + F: FnOnce((IpRepr, TcpRepr)) -> Result<()>, + { + if !self.remote_endpoint.is_specified() { + return Err(Error::Exhausted); + } if self.remote_last_ts.is_none() { // We get here in exactly two cases: @@ -1773,15 +2045,23 @@ impl<'a> TcpSocket<'a> { // Check if any state needs to be changed because of a timer. if self.timed_out(cx.now) { // If a timeout expires, we should abort the connection. - net_debug!("{}:{}:{}: timeout exceeded", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_debug!( + "{}:{}:{}: timeout exceeded", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); self.set_state(State::Closed); } else if !self.seq_to_transmit(cx) { if let Some(retransmit_delta) = self.timer.should_retransmit(cx.now) { // If a retransmit timer expired, we should resend data starting at the last ACK. - net_debug!("{}:{}:{}: retransmitting at t+{}", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - retransmit_delta); + net_debug!( + "{}:{}:{}: retransmitting at t+{}", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + retransmit_delta + ); self.remote_last_seq = self.local_seq_no; self.rtte.on_retransmit(); } @@ -1790,62 +2070,91 @@ impl<'a> TcpSocket<'a> { // Decide whether we're sending a packet. if self.seq_to_transmit(cx) { // If we have data to transmit and it fits into partner's window, do it. - net_trace!("{}:{}:{}: outgoing segment will send data or flags", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_trace!( + "{}:{}:{}: outgoing segment will send data or flags", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); } else if self.ack_to_transmit() && self.delayed_ack_expired(cx.now) { // If we have data to acknowledge, do it. - net_trace!("{}:{}:{}: outgoing segment will acknowledge", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_trace!( + "{}:{}:{}: outgoing segment will acknowledge", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); } else if self.window_to_update() && self.delayed_ack_expired(cx.now) { // If we have window length increase to advertise, do it. - net_trace!("{}:{}:{}: outgoing segment will update window", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_trace!( + "{}:{}:{}: outgoing segment will update window", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); } else if self.state == State::Closed { // If we need to abort the connection, do it. - net_trace!("{}:{}:{}: outgoing segment will abort connection", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_trace!( + "{}:{}:{}: outgoing segment will abort connection", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); } else if self.timer.should_retransmit(cx.now).is_some() { // If we have packets to retransmit, do it. - net_trace!("{}:{}:{}: retransmit timer expired", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_trace!( + "{}:{}:{}: retransmit timer expired", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); } else if self.timer.should_keep_alive(cx.now) { // If we need to transmit a keep-alive packet, do it. - net_trace!("{}:{}:{}: keep-alive timer expired", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_trace!( + "{}:{}:{}: keep-alive timer expired", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); } else if self.timer.should_close(cx.now) { // If we have spent enough time in the TIME-WAIT state, close the socket. - net_trace!("{}:{}:{}: TIME-WAIT timer expired", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_trace!( + "{}:{}:{}: TIME-WAIT timer expired", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); self.reset(); - return Err(Error::Exhausted) + return Err(Error::Exhausted); } else { - return Err(Error::Exhausted) + return Err(Error::Exhausted); } // Construct the lowered IP representation. // We might need this to calculate the MSS, so do it early. let mut ip_repr = IpRepr::Unspecified { - src_addr: self.local_endpoint.addr, - dst_addr: self.remote_endpoint.addr, - protocol: IpProtocol::Tcp, - hop_limit: self.hop_limit.unwrap_or(64), - payload_len: 0 - }.lower(&[])?; + src_addr: self.local_endpoint.addr, + dst_addr: self.remote_endpoint.addr, + protocol: IpProtocol::Tcp, + hop_limit: self.hop_limit.unwrap_or(64), + payload_len: 0, + } + .lower(&[])?; // Construct the basic TCP representation, an empty ACK packet. // We'll adjust this to be more specific as needed. let mut repr = TcpRepr { - src_port: self.local_endpoint.port, - dst_port: self.remote_endpoint.port, - control: TcpControl::None, - seq_number: self.remote_last_seq, - ack_number: Some(self.remote_seq_no + self.rx_buffer.len()), - window_len: self.scaled_window(), + src_port: self.local_endpoint.port, + dst_port: self.remote_endpoint.port, + control: TcpControl::None, + seq_number: self.remote_last_seq, + ack_number: Some(self.remote_seq_no + self.rx_buffer.len()), + window_len: self.scaled_window(), window_scale: None, max_seg_size: None, sack_permitted: false, - sack_ranges: [None, None, None], - payload: &[] + sack_ranges: [None, None, None], + payload: &[], }; match self.state { @@ -1863,21 +2172,24 @@ impl<'a> TcpSocket<'a> { State::SynSent | State::SynReceived => { repr.control = TcpControl::Syn; // window len must NOT be scaled in SYNs. - repr.window_len = self.rx_buffer.window().min((1<<16)-1) as u16; + repr.window_len = self.rx_buffer.window().min((1 << 16) - 1) as u16; if self.state == State::SynSent { repr.ack_number = None; repr.window_scale = Some(self.remote_win_shift); repr.sack_permitted = true; } else { repr.sack_permitted = self.remote_has_sack; - repr.window_scale = self.remote_win_scale.map( - |_| self.remote_win_shift); + repr.window_scale = self.remote_win_scale.map(|_| self.remote_win_shift); } } // We transmit data in all states where we may have data in the buffer, // or the transmit half of the connection is still open. - State::Established | State::FinWait1 | State::Closing | State::CloseWait | State::LastAck => { + State::Established + | State::FinWait1 + | State::Closing + | State::CloseWait + | State::LastAck => { // Extract as much data as the remote side can receive in this packet // from the transmit buffer. @@ -1911,11 +2223,13 @@ impl<'a> TcpSocket<'a> { // flags, depending on whether the transmit half of the connection is open. if offset + repr.payload.len() == self.tx_buffer.len() { match self.state { - State::FinWait1 | State::LastAck | State::Closing => - repr.control = TcpControl::Fin, - State::Established | State::CloseWait if !repr.payload.is_empty() => - repr.control = TcpControl::Psh, - _ => () + State::FinWait1 | State::LastAck | State::Closing => { + repr.control = TcpControl::Fin + } + State::Established | State::CloseWait if !repr.payload.is_empty() => { + repr.control = TcpControl::Psh + } + _ => (), } } } @@ -1931,7 +2245,7 @@ impl<'a> TcpSocket<'a> { let is_keep_alive; if self.timer.should_keep_alive(cx.now) && repr.is_empty() { repr.seq_number = repr.seq_number - 1; - repr.payload = b"\x00"; // RFC 1122 says we should do this + repr.payload = b"\x00"; // RFC 1122 says we should do this is_keep_alive = true; } else { is_keep_alive = false; @@ -1939,27 +2253,39 @@ impl<'a> TcpSocket<'a> { // Trace a summary of what will be sent. if is_keep_alive { - net_trace!("{}:{}:{}: sending a keep-alive", - self.meta.handle, self.local_endpoint, self.remote_endpoint); + net_trace!( + "{}:{}:{}: sending a keep-alive", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint + ); } else if !repr.payload.is_empty() { - net_trace!("{}:{}:{}: tx buffer: sending {} octets at offset {}", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - repr.payload.len(), self.remote_last_seq - self.local_seq_no); + net_trace!( + "{}:{}:{}: tx buffer: sending {} octets at offset {}", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + repr.payload.len(), + self.remote_last_seq - self.local_seq_no + ); } if repr.control != TcpControl::None || repr.payload.is_empty() { - let flags = - match (repr.control, repr.ack_number) { - (TcpControl::Syn, None) => "SYN", - (TcpControl::Syn, Some(_)) => "SYN|ACK", - (TcpControl::Fin, Some(_)) => "FIN|ACK", - (TcpControl::Rst, Some(_)) => "RST|ACK", - (TcpControl::Psh, Some(_)) => "PSH|ACK", - (TcpControl::None, Some(_)) => "ACK", - _ => "" - }; - net_trace!("{}:{}:{}: sending {}", - self.meta.handle, self.local_endpoint, self.remote_endpoint, - flags); + let flags = match (repr.control, repr.ack_number) { + (TcpControl::Syn, None) => "SYN", + (TcpControl::Syn, Some(_)) => "SYN|ACK", + (TcpControl::Fin, Some(_)) => "FIN|ACK", + (TcpControl::Rst, Some(_)) => "RST|ACK", + (TcpControl::Psh, Some(_)) => "PSH|ACK", + (TcpControl::None, Some(_)) => "ACK", + _ => "", + }; + net_trace!( + "{}:{}:{}: sending {}", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint, + flags + ); } if repr.control == TcpControl::Syn { @@ -1984,8 +2310,11 @@ impl<'a> TcpSocket<'a> { // Reset delayed-ack timer if self.ack_delay_until.is_some() { - net_trace!("{}:{}:{}: stop delayed ack timer", - self.meta.handle, self.local_endpoint, self.remote_endpoint + net_trace!( + "{}:{}:{}: stop delayed ack timer", + self.meta.handle, + self.local_endpoint, + self.remote_endpoint ); self.ack_delay_until = None; @@ -1993,7 +2322,9 @@ impl<'a> TcpSocket<'a> { // Leave the rest of the state intact if sending a keep-alive packet, since those // carry a fake segment. - if is_keep_alive { return Ok(()) } + if is_keep_alive { + return Ok(()); + } // We've sent a packet successfully, so we can update the internal state now. self.remote_last_seq = repr.seq_number + repr.segment_len(); @@ -2001,18 +2332,20 @@ impl<'a> TcpSocket<'a> { self.remote_last_win = repr.window_len; if repr.segment_len() > 0 { - self.rtte.on_send(cx.now, repr.seq_number + repr.segment_len()); + self.rtte + .on_send(cx.now, repr.seq_number + repr.segment_len()); } if !self.seq_to_transmit(cx) && repr.segment_len() > 0 { // If we've transmitted all data we could (and there was something at all, // data or flag, to transmit, not just an ACK), wind up the retransmit timer. - self.timer.set_for_retransmit(cx.now, self.rtte.retransmission_timeout()); + self.timer + .set_for_retransmit(cx.now, self.rtte.retransmission_timeout()); } if self.state == State::Closed { // When aborting a connection, forget about it after sending a single RST packet. - self.local_endpoint = IpEndpoint::default(); + self.local_endpoint = IpEndpoint::default(); self.remote_endpoint = IpEndpoint::default(); } @@ -2053,7 +2386,8 @@ impl<'a> TcpSocket<'a> { // We wait for the earliest of our timers to fire. *[self.timer.poll_at(), timeout_poll_at, delayed_ack_poll_at] .iter() - .min().unwrap_or(&PollAt::Ingress) + .min() + .unwrap_or(&PollAt::Ingress) } } } @@ -2077,52 +2411,68 @@ impl<'a> fmt::Write for TcpSocket<'a> { #[cfg(test)] mod test { + use super::*; + use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3, MOCK_UNSPECIFIED}; + use crate::wire::{IpAddress, IpCidr, IpRepr}; use core::i32; use std::vec::Vec; - use crate::wire::{IpAddress, IpRepr, IpCidr}; - use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3, MOCK_UNSPECIFIED}; - use super::*; // =========================================================================================// // Constants // =========================================================================================// - const LOCAL_PORT: u16 = 80; - const REMOTE_PORT: u16 = 49500; - const LOCAL_END: IpEndpoint = IpEndpoint { addr: MOCK_IP_ADDR_1, port: LOCAL_PORT }; - const REMOTE_END: IpEndpoint = IpEndpoint { addr: MOCK_IP_ADDR_2, port: REMOTE_PORT }; - const LOCAL_SEQ: TcpSeqNumber = TcpSeqNumber(10000); - const REMOTE_SEQ: TcpSeqNumber = TcpSeqNumber(-10000); + const LOCAL_PORT: u16 = 80; + const REMOTE_PORT: u16 = 49500; + const LOCAL_END: IpEndpoint = IpEndpoint { + addr: MOCK_IP_ADDR_1, + port: LOCAL_PORT, + }; + const REMOTE_END: IpEndpoint = IpEndpoint { + addr: MOCK_IP_ADDR_2, + port: REMOTE_PORT, + }; + const LOCAL_SEQ: TcpSeqNumber = TcpSeqNumber(10000); + const REMOTE_SEQ: TcpSeqNumber = TcpSeqNumber(-10000); const SEND_IP_TEMPL: IpRepr = IpRepr::Unspecified { - src_addr: MOCK_IP_ADDR_1, dst_addr: MOCK_IP_ADDR_2, - protocol: IpProtocol::Tcp, payload_len: 20, - hop_limit: 64 + src_addr: MOCK_IP_ADDR_1, + dst_addr: MOCK_IP_ADDR_2, + protocol: IpProtocol::Tcp, + payload_len: 20, + hop_limit: 64, }; const SEND_TEMPL: TcpRepr<'static> = TcpRepr { - src_port: REMOTE_PORT, dst_port: LOCAL_PORT, + src_port: REMOTE_PORT, + dst_port: LOCAL_PORT, control: TcpControl::None, - seq_number: TcpSeqNumber(0), ack_number: Some(TcpSeqNumber(0)), - window_len: 256, window_scale: None, + seq_number: TcpSeqNumber(0), + ack_number: Some(TcpSeqNumber(0)), + window_len: 256, + window_scale: None, max_seg_size: None, sack_permitted: false, sack_ranges: [None, None, None], - payload: &[] + payload: &[], }; const _RECV_IP_TEMPL: IpRepr = IpRepr::Unspecified { - src_addr: MOCK_IP_ADDR_1, dst_addr: MOCK_IP_ADDR_2, - protocol: IpProtocol::Tcp, payload_len: 20, - hop_limit: 64 + src_addr: MOCK_IP_ADDR_1, + dst_addr: MOCK_IP_ADDR_2, + protocol: IpProtocol::Tcp, + payload_len: 20, + hop_limit: 64, }; - const RECV_TEMPL: TcpRepr<'static> = TcpRepr { - src_port: LOCAL_PORT, dst_port: REMOTE_PORT, + const RECV_TEMPL: TcpRepr<'static> = TcpRepr { + src_port: LOCAL_PORT, + dst_port: REMOTE_PORT, control: TcpControl::None, - seq_number: TcpSeqNumber(0), ack_number: Some(TcpSeqNumber(0)), - window_len: 64, window_scale: None, + seq_number: TcpSeqNumber(0), + ack_number: Some(TcpSeqNumber(0)), + window_len: 64, + window_scale: None, max_seg_size: None, sack_permitted: false, sack_ranges: [None, None, None], - payload: &[] + payload: &[], }; #[cfg(feature = "proto-ipv6")] @@ -2134,14 +2484,17 @@ mod test { // Helper functions // =========================================================================================// - fn send(socket: &mut TcpSocket, timestamp: Instant, repr: &TcpRepr) -> - Result>> { + fn send( + socket: &mut TcpSocket, + timestamp: Instant, + repr: &TcpRepr, + ) -> Result>> { let ip_repr = IpRepr::Unspecified { - src_addr: MOCK_IP_ADDR_2, - dst_addr: MOCK_IP_ADDR_1, - protocol: IpProtocol::Tcp, + src_addr: MOCK_IP_ADDR_2, + dst_addr: MOCK_IP_ADDR_1, + protocol: IpProtocol::Tcp, payload_len: repr.buffer_len(), - hop_limit: 64 + hop_limit: 64, }; net_trace!("send: {}", repr); @@ -2155,12 +2508,14 @@ mod test { Ok(Some(repr)) } Ok(None) => Ok(None), - Err(err) => Err(err) + Err(err) => Err(err), } } fn recv(socket: &mut TcpSocket, timestamp: Instant, mut f: F) - where F: FnMut(Result) { + where + F: FnMut(Result), + { let mut cx = Context::DUMMY.clone(); cx.now = timestamp; let result = socket.dispatch(&cx, |(ip_repr, tcp_repr)| { @@ -2176,7 +2531,7 @@ mod test { }); match result { Ok(()) => (), - Err(e) => f(Err(e)) + Err(e) => f(Err(e)), } } @@ -2212,20 +2567,20 @@ mod test { } macro_rules! sanity { - ($socket1:expr, $socket2:expr) => ({ + ($socket1:expr, $socket2:expr) => {{ let (s1, s2) = ($socket1, $socket2); - assert_eq!(s1.state, s2.state, "state"); - assert_eq!(s1.listen_address, s2.listen_address, "listen_address"); - assert_eq!(s1.local_endpoint, s2.local_endpoint, "local_endpoint"); - assert_eq!(s1.remote_endpoint, s2.remote_endpoint, "remote_endpoint"); - assert_eq!(s1.local_seq_no, s2.local_seq_no, "local_seq_no"); - assert_eq!(s1.remote_seq_no, s2.remote_seq_no, "remote_seq_no"); - assert_eq!(s1.remote_last_seq, s2.remote_last_seq, "remote_last_seq"); - assert_eq!(s1.remote_last_ack, s2.remote_last_ack, "remote_last_ack"); - assert_eq!(s1.remote_last_win, s2.remote_last_win, "remote_last_win"); - assert_eq!(s1.remote_win_len, s2.remote_win_len, "remote_win_len"); - assert_eq!(s1.timer, s2.timer, "timer"); - }) + assert_eq!(s1.state, s2.state, "state"); + assert_eq!(s1.listen_address, s2.listen_address, "listen_address"); + assert_eq!(s1.local_endpoint, s2.local_endpoint, "local_endpoint"); + assert_eq!(s1.remote_endpoint, s2.remote_endpoint, "remote_endpoint"); + assert_eq!(s1.local_seq_no, s2.local_seq_no, "local_seq_no"); + assert_eq!(s1.remote_seq_no, s2.remote_seq_no, "remote_seq_no"); + assert_eq!(s1.remote_last_seq, s2.remote_last_seq, "remote_last_seq"); + assert_eq!(s1.remote_last_ack, s2.remote_last_ack, "remote_last_ack"); + assert_eq!(s1.remote_last_win, s2.remote_last_win, "remote_last_win"); + assert_eq!(s1.remote_win_len, s2.remote_win_len, "remote_win_len"); + assert_eq!(s1.timer, s2.timer, "timer"); + }}; } #[cfg(feature = "log")] @@ -2242,8 +2597,7 @@ mod test { println!("{}", record.args()); } - fn flush(&self) { - } + fn flush(&self) {} } // If it fails, that just means we've already set it to the same value. @@ -2268,18 +2622,15 @@ mod test { socket } - fn socket_syn_received_with_buffer_sizes( - tx_len: usize, - rx_len: usize - ) -> TcpSocket<'static> { + fn socket_syn_received_with_buffer_sizes(tx_len: usize, rx_len: usize) -> TcpSocket<'static> { let mut s = socket_with_buffer_sizes(tx_len, rx_len); - s.state = State::SynReceived; - s.local_endpoint = LOCAL_END; + s.state = State::SynReceived; + s.local_endpoint = LOCAL_END; s.remote_endpoint = REMOTE_END; - s.local_seq_no = LOCAL_SEQ; - s.remote_seq_no = REMOTE_SEQ + 1; + s.local_seq_no = LOCAL_SEQ; + s.remote_seq_no = REMOTE_SEQ + 1; s.remote_last_seq = LOCAL_SEQ; - s.remote_win_len = 256; + s.remote_win_len = 256; s } @@ -2287,15 +2638,12 @@ mod test { socket_syn_received_with_buffer_sizes(64, 64) } - fn socket_syn_sent_with_buffer_sizes( - tx_len: usize, - rx_len: usize - ) -> TcpSocket<'static> { + fn socket_syn_sent_with_buffer_sizes(tx_len: usize, rx_len: usize) -> TcpSocket<'static> { let mut s = socket_with_buffer_sizes(tx_len, rx_len); - s.state = State::SynSent; - s.local_endpoint = IpEndpoint::new(MOCK_UNSPECIFIED, LOCAL_PORT); + s.state = State::SynSent; + s.local_endpoint = IpEndpoint::new(MOCK_UNSPECIFIED, LOCAL_PORT); s.remote_endpoint = REMOTE_END; - s.local_seq_no = LOCAL_SEQ; + s.local_seq_no = LOCAL_SEQ; s.remote_last_seq = LOCAL_SEQ; s } @@ -2306,18 +2654,18 @@ mod test { fn socket_syn_sent_with_local_ipendpoint(local: IpEndpoint) -> TcpSocket<'static> { let mut s = socket(); - s.state = State::SynSent; - s.local_endpoint = local; + s.state = State::SynSent; + s.local_endpoint = local; s.remote_endpoint = REMOTE_END; - s.local_seq_no = LOCAL_SEQ; + s.local_seq_no = LOCAL_SEQ; s.remote_last_seq = LOCAL_SEQ; s } fn socket_established_with_buffer_sizes(tx_len: usize, rx_len: usize) -> TcpSocket<'static> { let mut s = socket_syn_received_with_buffer_sizes(tx_len, rx_len); - s.state = State::Established; - s.local_seq_no = LOCAL_SEQ + 1; + s.state = State::Established; + s.local_seq_no = LOCAL_SEQ + 1; s.remote_last_seq = LOCAL_SEQ + 1; s.remote_last_ack = Some(REMOTE_SEQ + 1); s.remote_last_win = 64; @@ -2330,65 +2678,73 @@ mod test { fn socket_fin_wait_1() -> TcpSocket<'static> { let mut s = socket_established(); - s.state = State::FinWait1; + s.state = State::FinWait1; s } fn socket_fin_wait_2() -> TcpSocket<'static> { let mut s = socket_fin_wait_1(); - s.state = State::FinWait2; - s.local_seq_no = LOCAL_SEQ + 1 + 1; + s.state = State::FinWait2; + s.local_seq_no = LOCAL_SEQ + 1 + 1; s.remote_last_seq = LOCAL_SEQ + 1 + 1; s } fn socket_closing() -> TcpSocket<'static> { let mut s = socket_fin_wait_1(); - s.state = State::Closing; + s.state = State::Closing; s.remote_last_seq = LOCAL_SEQ + 1 + 1; - s.remote_seq_no = REMOTE_SEQ + 1 + 1; + s.remote_seq_no = REMOTE_SEQ + 1 + 1; s } fn socket_time_wait(from_closing: bool) -> TcpSocket<'static> { let mut s = socket_fin_wait_2(); - s.state = State::TimeWait; - s.remote_seq_no = REMOTE_SEQ + 1 + 1; + s.state = State::TimeWait; + s.remote_seq_no = REMOTE_SEQ + 1 + 1; if from_closing { s.remote_last_ack = Some(REMOTE_SEQ + 1 + 1); } - s.timer = Timer::Close { expires_at: Instant::from_secs(1) + CLOSE_DELAY }; + s.timer = Timer::Close { + expires_at: Instant::from_secs(1) + CLOSE_DELAY, + }; s } fn socket_close_wait() -> TcpSocket<'static> { let mut s = socket_established(); - s.state = State::CloseWait; - s.remote_seq_no = REMOTE_SEQ + 1 + 1; + s.state = State::CloseWait; + s.remote_seq_no = REMOTE_SEQ + 1 + 1; s.remote_last_ack = Some(REMOTE_SEQ + 1 + 1); s } fn socket_last_ack() -> TcpSocket<'static> { let mut s = socket_close_wait(); - s.state = State::LastAck; + s.state = State::LastAck; s } fn socket_recved() -> TcpSocket<'static> { let mut s = socket_established(); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abcdef"[..], - ..SEND_TEMPL - }); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 6), - window_len: 58, - ..RECV_TEMPL - }]); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abcdef"[..], + ..SEND_TEMPL + } + ); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 6), + window_len: 58, + ..RECV_TEMPL + }] + ); s } @@ -2432,47 +2788,59 @@ mod test { // =========================================================================================// fn socket_listen() -> TcpSocket<'static> { let mut s = socket(); - s.state = State::Listen; - s.local_endpoint = IpEndpoint::new(IpAddress::default(), LOCAL_PORT); + s.state = State::Listen; + s.local_endpoint = IpEndpoint::new(IpAddress::default(), LOCAL_PORT); s } #[test] fn test_listen_sack_option() { let mut s = socket_listen(); - send!(s, TcpRepr { - control: TcpControl::Syn, - seq_number: REMOTE_SEQ, - ack_number: None, - sack_permitted: false, - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: None, + sack_permitted: false, + ..SEND_TEMPL + } + ); assert!(!s.remote_has_sack); - recv!(s, [TcpRepr { - control: TcpControl::Syn, - seq_number: LOCAL_SEQ, - ack_number: Some(REMOTE_SEQ + 1), - max_seg_size: Some(BASE_MSS), - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + control: TcpControl::Syn, + seq_number: LOCAL_SEQ, + ack_number: Some(REMOTE_SEQ + 1), + max_seg_size: Some(BASE_MSS), + ..RECV_TEMPL + }] + ); let mut s = socket_listen(); - send!(s, TcpRepr { - control: TcpControl::Syn, - seq_number: REMOTE_SEQ, - ack_number: None, - sack_permitted: true, - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: None, + sack_permitted: true, + ..SEND_TEMPL + } + ); assert!(s.remote_has_sack); - recv!(s, [TcpRepr { - control: TcpControl::Syn, - seq_number: LOCAL_SEQ, - ack_number: Some(REMOTE_SEQ + 1), - max_seg_size: Some(BASE_MSS), - sack_permitted: true, - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + control: TcpControl::Syn, + seq_number: LOCAL_SEQ, + ack_number: Some(REMOTE_SEQ + 1), + max_seg_size: Some(BASE_MSS), + sack_permitted: true, + ..RECV_TEMPL + }] + ); } #[test] @@ -2493,25 +2861,31 @@ mod test { ] { let mut s = socket_with_buffer_sizes(64, *buffer_size); s.state = State::Listen; - s.local_endpoint = IpEndpoint::new(IpAddress::default(), LOCAL_PORT); + s.local_endpoint = IpEndpoint::new(IpAddress::default(), LOCAL_PORT); assert_eq!(s.remote_win_shift, *shift_amt); - send!(s, TcpRepr { - control: TcpControl::Syn, - seq_number: REMOTE_SEQ, - ack_number: None, - window_scale: Some(0), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: None, + window_scale: Some(0), + ..SEND_TEMPL + } + ); assert_eq!(s.remote_win_shift, *shift_amt); - 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(*shift_amt), - window_len: cmp::min(*buffer_size, 65535) as u16, - ..RECV_TEMPL - }]); + 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(*shift_amt), + window_len: cmp::min(*buffer_size, 65535) as u16, + ..RECV_TEMPL + }] + ); } } @@ -2538,12 +2912,15 @@ mod test { #[test] fn test_listen_syn() { let mut s = socket_listen(); - send!(s, TcpRepr { - control: TcpControl::Syn, - seq_number: REMOTE_SEQ, - ack_number: None, - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: None, + ..SEND_TEMPL + } + ); sanity!(s, socket_syn_received()); } @@ -2565,12 +2942,16 @@ mod test { #[test] fn test_listen_rst() { let mut s = socket_listen(); - send!(s, TcpRepr { - control: TcpControl::Rst, - seq_number: REMOTE_SEQ, - ack_number: None, - ..SEND_TEMPL - }, Err(Error::Dropped)); + send!( + s, + TcpRepr { + control: TcpControl::Rst, + seq_number: REMOTE_SEQ, + ack_number: None, + ..SEND_TEMPL + }, + Err(Error::Dropped) + ); } #[test] @@ -2587,18 +2968,24 @@ mod test { #[test] fn test_syn_received_ack() { let mut s = socket_syn_received(); - recv!(s, [TcpRepr { - control: TcpControl::Syn, - seq_number: LOCAL_SEQ, - ack_number: Some(REMOTE_SEQ + 1), - max_seg_size: Some(BASE_MSS), - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + recv!( + s, + [TcpRepr { + control: TcpControl::Syn, + seq_number: LOCAL_SEQ, + ack_number: Some(REMOTE_SEQ + 1), + max_seg_size: Some(BASE_MSS), + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Established); sanity!(s, socket_established()); } @@ -2606,81 +2993,111 @@ mod test { #[test] fn test_syn_received_fin() { let mut s = socket_syn_received(); - recv!(s, [TcpRepr { - control: TcpControl::Syn, - seq_number: LOCAL_SEQ, - ack_number: Some(REMOTE_SEQ + 1), - max_seg_size: Some(BASE_MSS), - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abcdef"[..], - ..SEND_TEMPL - }); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 6 + 1), - window_len: 58, - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + control: TcpControl::Syn, + seq_number: LOCAL_SEQ, + ack_number: Some(REMOTE_SEQ + 1), + max_seg_size: Some(BASE_MSS), + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abcdef"[..], + ..SEND_TEMPL + } + ); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 6 + 1), + window_len: 58, + ..RECV_TEMPL + }] + ); assert_eq!(s.state, State::CloseWait); - sanity!(s, TcpSocket { - remote_last_ack: Some(REMOTE_SEQ + 1 + 6 + 1), - remote_last_win: 58, - ..socket_close_wait() - }); + sanity!( + s, + TcpSocket { + remote_last_ack: Some(REMOTE_SEQ + 1 + 6 + 1), + remote_last_win: 58, + ..socket_close_wait() + } + ); } #[test] fn test_syn_received_rst() { let mut s = socket_syn_received(); - recv!(s, [TcpRepr { - control: TcpControl::Syn, - seq_number: LOCAL_SEQ, - ack_number: Some(REMOTE_SEQ + 1), - max_seg_size: Some(BASE_MSS), - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - control: TcpControl::Rst, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ), - ..SEND_TEMPL - }); + recv!( + s, + [TcpRepr { + control: TcpControl::Syn, + seq_number: LOCAL_SEQ, + ack_number: Some(REMOTE_SEQ + 1), + max_seg_size: Some(BASE_MSS), + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + control: TcpControl::Rst, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Listen); - assert_eq!(s.local_endpoint, IpEndpoint::new(IpAddress::Unspecified, LOCAL_END.port)); + assert_eq!( + s.local_endpoint, + IpEndpoint::new(IpAddress::Unspecified, LOCAL_END.port) + ); assert_eq!(s.remote_endpoint, IpEndpoint::default()); } #[test] fn test_syn_received_no_window_scaling() { let mut s = socket_listen(); - send!(s, TcpRepr { - control: TcpControl::Syn, - seq_number: REMOTE_SEQ, - ack_number: None, - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: None, + ..SEND_TEMPL + } + ); assert_eq!(s.state(), State::SynReceived); assert_eq!(s.local_endpoint(), LOCAL_END); assert_eq!(s.remote_endpoint(), REMOTE_END); - recv!(s, [TcpRepr { - control: TcpControl::Syn, - seq_number: LOCAL_SEQ, - ack_number: Some(REMOTE_SEQ + 1), - max_seg_size: Some(BASE_MSS), - window_scale: None, - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - window_scale: None, - ..SEND_TEMPL - }); + recv!( + s, + [TcpRepr { + control: TcpControl::Syn, + seq_number: LOCAL_SEQ, + ack_number: Some(REMOTE_SEQ + 1), + max_seg_size: Some(BASE_MSS), + window_scale: None, + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + window_scale: None, + ..SEND_TEMPL + } + ); assert_eq!(s.remote_win_shift, 0); assert_eq!(s.remote_win_scale, None); } @@ -2689,30 +3106,39 @@ mod test { fn test_syn_received_window_scaling() { for scale in 0..14 { let mut s = socket_listen(); - send!(s, TcpRepr { - control: TcpControl::Syn, - seq_number: REMOTE_SEQ, - ack_number: None, - window_scale: Some(scale), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: None, + window_scale: Some(scale), + ..SEND_TEMPL + } + ); assert_eq!(s.state(), State::SynReceived); assert_eq!(s.local_endpoint(), LOCAL_END); assert_eq!(s.remote_endpoint(), REMOTE_END); - 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 - }]); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - window_scale: None, - ..SEND_TEMPL - }); + 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 + }] + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + window_scale: None, + ..SEND_TEMPL + } + ); assert_eq!(s.remote_win_scale, Some(scale)); } } @@ -2731,15 +3157,24 @@ mod test { #[test] fn test_connect_validation() { let mut s = socket(); - assert_eq!(s.connect((IpAddress::Unspecified, 80), LOCAL_END), - Err(Error::Unaddressable)); - assert_eq!(s.connect(REMOTE_END, (MOCK_UNSPECIFIED, 0)), - Err(Error::Unaddressable)); - assert_eq!(s.connect((MOCK_UNSPECIFIED, 0), LOCAL_END), - Err(Error::Unaddressable)); - assert_eq!(s.connect((IpAddress::Unspecified, 80), LOCAL_END), - Err(Error::Unaddressable)); - s.connect(REMOTE_END, LOCAL_END).expect("Connect failed with valid parameters"); + assert_eq!( + s.connect((IpAddress::Unspecified, 80), LOCAL_END), + Err(Error::Unaddressable) + ); + assert_eq!( + s.connect(REMOTE_END, (MOCK_UNSPECIFIED, 0)), + Err(Error::Unaddressable) + ); + assert_eq!( + s.connect((MOCK_UNSPECIFIED, 0), LOCAL_END), + Err(Error::Unaddressable) + ); + assert_eq!( + s.connect((IpAddress::Unspecified, 80), LOCAL_END), + Err(Error::Unaddressable) + ); + s.connect(REMOTE_END, LOCAL_END) + .expect("Connect failed with valid parameters"); assert_eq!(s.local_endpoint(), LOCAL_END); assert_eq!(s.remote_endpoint(), REMOTE_END); } @@ -2749,58 +3184,65 @@ mod test { let mut s = socket(); s.local_seq_no = LOCAL_SEQ; s.connect(REMOTE_END, LOCAL_END.port).unwrap(); - assert_eq!(s.local_endpoint, IpEndpoint::new(MOCK_UNSPECIFIED, LOCAL_END.port)); - 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 - }]); - send!(s, TcpRepr { - control: TcpControl::Syn, - seq_number: REMOTE_SEQ, - ack_number: Some(LOCAL_SEQ + 1), - max_seg_size: Some(BASE_MSS - 80), - window_scale: Some(0), - ..SEND_TEMPL - }); + assert_eq!( + s.local_endpoint, + IpEndpoint::new(MOCK_UNSPECIFIED, LOCAL_END.port) + ); + 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 + }] + ); + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: Some(LOCAL_SEQ + 1), + max_seg_size: Some(BASE_MSS - 80), + window_scale: Some(0), + ..SEND_TEMPL + } + ); assert_eq!(s.local_endpoint, LOCAL_END); } #[test] fn test_connect_unspecified_local() { let mut s = socket(); - assert_eq!(s.connect(REMOTE_END, (MOCK_UNSPECIFIED, 80)), - Ok(())); + assert_eq!(s.connect(REMOTE_END, (MOCK_UNSPECIFIED, 80)), Ok(())); s.abort(); - assert_eq!(s.connect(REMOTE_END, (IpAddress::Unspecified, 80)), - Ok(())); + assert_eq!(s.connect(REMOTE_END, (IpAddress::Unspecified, 80)), Ok(())); s.abort(); } #[test] fn test_connect_specified_local() { let mut s = socket(); - assert_eq!(s.connect(REMOTE_END, (MOCK_IP_ADDR_2, 80)), - Ok(())); + assert_eq!(s.connect(REMOTE_END, (MOCK_IP_ADDR_2, 80)), Ok(())); } #[test] fn test_connect_twice() { let mut s = socket(); - assert_eq!(s.connect(REMOTE_END, (IpAddress::Unspecified, 80)), - Ok(())); - assert_eq!(s.connect(REMOTE_END, (IpAddress::Unspecified, 80)), - Err(Error::Illegal)); + assert_eq!(s.connect(REMOTE_END, (IpAddress::Unspecified, 80)), Ok(())); + assert_eq!( + s.connect(REMOTE_END, (IpAddress::Unspecified, 80)), + Err(Error::Illegal) + ); } #[test] fn test_syn_sent_sanity() { let mut s = socket(); - s.local_seq_no = LOCAL_SEQ; + s.local_seq_no = LOCAL_SEQ; s.connect(REMOTE_END, LOCAL_END).unwrap(); sanity!(s, socket_syn_sent_with_local_ipendpoint(LOCAL_END)); } @@ -2808,28 +3250,37 @@ mod test { #[test] fn test_syn_sent_syn_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 - }]); - send!(s, TcpRepr { - control: TcpControl::Syn, - seq_number: REMOTE_SEQ, - ack_number: Some(LOCAL_SEQ + 1), - max_seg_size: Some(BASE_MSS - 80), - window_scale: Some(0), - ..SEND_TEMPL - }); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - ..RECV_TEMPL - }]); + 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 + }] + ); + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: Some(LOCAL_SEQ + 1), + max_seg_size: Some(BASE_MSS - 80), + window_scale: Some(0), + ..SEND_TEMPL + } + ); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + ..RECV_TEMPL + }] + ); recv!(s, time 1000, Err(Error::Exhausted)); assert_eq!(s.state, State::Established); sanity!(s, socket_established()); @@ -2838,70 +3289,92 @@ mod test { #[test] fn test_syn_sent_syn_ack_not_incremented() { 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 - }]); - send!(s, TcpRepr { - control: TcpControl::Syn, - seq_number: REMOTE_SEQ, - ack_number: Some(LOCAL_SEQ), // WRONG - max_seg_size: Some(BASE_MSS - 80), - window_scale: Some(0), - ..SEND_TEMPL - }, Err(Error::Dropped)); + 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 + }] + ); + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: Some(LOCAL_SEQ), // WRONG + max_seg_size: Some(BASE_MSS - 80), + window_scale: Some(0), + ..SEND_TEMPL + }, + Err(Error::Dropped) + ); assert_eq!(s.state, State::SynSent); } #[test] fn test_syn_sent_rst() { let mut s = socket_syn_sent(); - send!(s, TcpRepr { - control: TcpControl::Rst, - seq_number: REMOTE_SEQ, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Rst, + seq_number: REMOTE_SEQ, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Closed); } #[test] fn test_syn_sent_rst_no_ack() { let mut s = socket_syn_sent(); - send!(s, TcpRepr { - control: TcpControl::Rst, - seq_number: REMOTE_SEQ, - ack_number: None, - ..SEND_TEMPL - }, Err(Error::Dropped)); + send!( + s, + TcpRepr { + control: TcpControl::Rst, + seq_number: REMOTE_SEQ, + ack_number: None, + ..SEND_TEMPL + }, + Err(Error::Dropped) + ); assert_eq!(s.state, State::SynSent); } #[test] fn test_syn_sent_rst_bad_ack() { let mut s = socket_syn_sent(); - send!(s, TcpRepr { - control: TcpControl::Rst, - seq_number: REMOTE_SEQ, - ack_number: Some(TcpSeqNumber(1234)), - ..SEND_TEMPL - }, Err(Error::Dropped)); + send!( + s, + TcpRepr { + control: TcpControl::Rst, + seq_number: REMOTE_SEQ, + ack_number: Some(TcpSeqNumber(1234)), + ..SEND_TEMPL + }, + Err(Error::Dropped) + ); assert_eq!(s.state, State::SynSent); } #[test] fn test_syn_sent_bad_ack() { let mut s = socket_syn_sent(); - send!(s, TcpRepr { - control: TcpControl::None, - ack_number: Some(TcpSeqNumber(1)), - ..SEND_TEMPL - }, Err(Error::Dropped)); + send!( + s, + TcpRepr { + control: TcpControl::None, + ack_number: Some(TcpSeqNumber(1)), + ..SEND_TEMPL + }, + Err(Error::Dropped) + ); assert_eq!(s.state, State::Closed); } @@ -2932,43 +3405,52 @@ mod test { s.local_seq_no = LOCAL_SEQ; assert_eq!(s.remote_win_shift, *shift_amt); s.connect(REMOTE_END, LOCAL_END).unwrap(); - recv!(s, [TcpRepr { - control: TcpControl::Syn, - seq_number: LOCAL_SEQ, - ack_number: None, - max_seg_size: Some(BASE_MSS), - window_scale: Some(*shift_amt), - window_len: cmp::min(*buffer_size, 65535) as u16, - sack_permitted: true, - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + control: TcpControl::Syn, + seq_number: LOCAL_SEQ, + ack_number: None, + max_seg_size: Some(BASE_MSS), + window_scale: Some(*shift_amt), + window_len: cmp::min(*buffer_size, 65535) as u16, + sack_permitted: true, + ..RECV_TEMPL + }] + ); } } #[test] fn test_syn_sent_syn_ack_no_window_scaling() { let mut s = socket_syn_sent_with_buffer_sizes(1048576, 1048576); - recv!(s, [TcpRepr { - control: TcpControl::Syn, - seq_number: LOCAL_SEQ, - ack_number: None, - max_seg_size: Some(BASE_MSS), - // scaling does NOT apply to the window value in SYN packets - window_len: 65535, - window_scale: Some(5), - sack_permitted: true, - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + control: TcpControl::Syn, + seq_number: LOCAL_SEQ, + ack_number: None, + max_seg_size: Some(BASE_MSS), + // scaling does NOT apply to the window value in SYN packets + window_len: 65535, + window_scale: Some(5), + sack_permitted: true, + ..RECV_TEMPL + }] + ); assert_eq!(s.remote_win_shift, 5); - send!(s, TcpRepr { - control: TcpControl::Syn, - seq_number: REMOTE_SEQ, - ack_number: Some(LOCAL_SEQ + 1), - max_seg_size: Some(BASE_MSS - 80), - window_scale: None, - window_len: 42, - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: Some(LOCAL_SEQ + 1), + max_seg_size: Some(BASE_MSS - 80), + window_scale: None, + window_len: 42, + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Established); assert_eq!(s.remote_win_shift, 0); assert_eq!(s.remote_win_scale, None); @@ -2978,24 +3460,30 @@ mod test { #[test] fn test_syn_sent_syn_ack_window_scaling() { 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 - }]); - send!(s, TcpRepr { - control: TcpControl::Syn, - seq_number: REMOTE_SEQ, - ack_number: Some(LOCAL_SEQ + 1), - max_seg_size: Some(BASE_MSS - 80), - window_scale: Some(7), - window_len: 42, - ..SEND_TEMPL - }); + 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 + }] + ); + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: Some(LOCAL_SEQ + 1), + max_seg_size: Some(BASE_MSS - 80), + window_scale: Some(7), + window_len: 42, + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Established); assert_eq!(s.remote_win_scale, Some(7)); // scaling does NOT apply to the window value in SYN packets @@ -3009,18 +3497,24 @@ mod test { #[test] fn test_established_recv() { let mut s = socket_established(); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abcdef"[..], - ..SEND_TEMPL - }); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 6), - window_len: 58, - ..RECV_TEMPL - }]); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abcdef"[..], + ..SEND_TEMPL + } + ); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 6), + window_len: 58, + ..RECV_TEMPL + }] + ); assert_eq!(s.rx_buffer.dequeue_many(6), &b"abcdef"[..]); } @@ -3037,25 +3531,34 @@ mod test { let mut segment: Vec = Vec::with_capacity(500); // move the last ack to 5000 by sending ten of them - for _ in 0..50 { segment.extend_from_slice(b"abcdefghij") } + for _ in 0..50 { + segment.extend_from_slice(b"abcdefghij") + } for offset in (0..5000).step_by(500) { - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + offset, - ack_number: Some(LOCAL_SEQ + 1), - payload: &segment, - ..SEND_TEMPL - }); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + offset + 500), - window_len: 3500, - ..RECV_TEMPL - }]); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + offset, + ack_number: Some(LOCAL_SEQ + 1), + payload: &segment, + ..SEND_TEMPL + } + ); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + offset + 500), + window_len: 3500, + ..RECV_TEMPL + }] + ); s.recv(|data| { assert_eq!(data.len(), 500); assert_eq!(data, segment.as_slice()); (500, ()) - }).unwrap(); + }) + .unwrap(); } assert_eq!(s.remote_last_win, 3500); (s, segment) @@ -3088,21 +3591,29 @@ mod test { // 8500 5000 5500 9000 // for offset in (500..3500).step_by(500) { - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + offset + 5000, - ack_number: Some(LOCAL_SEQ + 1), - payload: &segment, - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 5000), - window_len: 4000, - sack_ranges: [ - Some((REMOTE_SEQ.0 as u32 + 1 + 5500, - REMOTE_SEQ.0 as u32 + 1 + 5500 + offset as u32)), - None, None], - ..RECV_TEMPL - }))); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + offset + 5000, + ack_number: Some(LOCAL_SEQ + 1), + payload: &segment, + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 5000), + window_len: 4000, + sack_ranges: [ + Some(( + REMOTE_SEQ.0 as u32 + 1 + 5500, + REMOTE_SEQ.0 as u32 + 1 + 5500 + offset as u32 + )), + None, + None + ], + ..RECV_TEMPL + })) + ); } } @@ -3119,24 +3630,32 @@ mod test { // Create a TCP segment that will mostly fill an IP frame. let mut segment: Vec = Vec::with_capacity(1400); - for _ in 0..100 { segment.extend_from_slice(b"abcdefghijklmn") } + for _ in 0..100 { + segment.extend_from_slice(b"abcdefghijklmn") + } assert_eq!(segment.len(), 1400); // Send the frame - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &segment, - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &segment, + ..SEND_TEMPL + } + ); // Ensure that the received window size is shifted right by 2. - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1400), - window_len: 65185, - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1400), + window_len: 65185, + ..RECV_TEMPL + }] + ); } #[test] @@ -3144,32 +3663,44 @@ mod test { let mut s = socket_established(); // First roundtrip after establishing. s.send_slice(b"abcdef").unwrap(); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"abcdef"[..], - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"abcdef"[..], + ..RECV_TEMPL + }] + ); assert_eq!(s.tx_buffer.len(), 6); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1 + 6), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1 + 6), + ..SEND_TEMPL + } + ); assert_eq!(s.tx_buffer.len(), 0); // Second roundtrip. s.send_slice(b"foobar").unwrap(); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 6, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"foobar"[..], - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1 + 6 + 6), - ..SEND_TEMPL - }); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 6, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"foobar"[..], + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1 + 6 + 6), + ..SEND_TEMPL + } + ); assert_eq!(s.tx_buffer.len(), 0); } @@ -3178,19 +3709,25 @@ mod test { let mut s = socket_established(); s.set_nagle_enabled(false); s.send_slice(b"abcdef").unwrap(); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"abcdef"[..], - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"abcdef"[..], + ..RECV_TEMPL + }] + ); s.send_slice(b"foobar").unwrap(); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 6, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"foobar"[..], - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 6, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"foobar"[..], + ..RECV_TEMPL + }] + ); } #[test] @@ -3203,12 +3740,15 @@ mod test { let mut s = socket_established(); s.remote_win_len = 16; s.send_slice(&data[..]).unwrap(); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - payload: &data[0..16], - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &data[0..16], + ..RECV_TEMPL + }] + ); } #[test] @@ -3217,42 +3757,56 @@ mod test { // 6 octets fit on the remote side's window, so we send them. s.send_slice(b"abcdef").unwrap(); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"abcdef"[..], - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"abcdef"[..], + ..RECV_TEMPL + }] + ); assert_eq!(s.tx_buffer.len(), 6); - println!("local_seq_no={} remote_win_len={} remote_last_seq={}", s.local_seq_no, s.remote_win_len, s.remote_last_seq); + println!( + "local_seq_no={} remote_win_len={} remote_last_seq={}", + s.local_seq_no, s.remote_win_len, s.remote_last_seq + ); // - Peer doesn't ack them yet // - Sends data so we need to reply with an ACK // - ...AND and sends a window announcement that SHRINKS the window, so data we've // previously sent is now outside the window. Yes, this is allowed by TCP. - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - window_len: 3, - payload: &b"xyzxyz"[..], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + window_len: 3, + payload: &b"xyzxyz"[..], + ..SEND_TEMPL + } + ); assert_eq!(s.tx_buffer.len(), 6); - println!("local_seq_no={} remote_win_len={} remote_last_seq={}", s.local_seq_no, s.remote_win_len, s.remote_last_seq); + println!( + "local_seq_no={} remote_win_len={} remote_last_seq={}", + s.local_seq_no, s.remote_win_len, s.remote_last_seq + ); // More data should not get sent since it doesn't fit in the window s.send_slice(b"foobar").unwrap(); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 6, - ack_number: Some(REMOTE_SEQ + 1 + 6), - window_len: 64 - 6, - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 6, + ack_number: Some(REMOTE_SEQ + 1 + 6), + window_len: 64 - 6, + ..RECV_TEMPL + }] + ); } - #[test] fn test_established_send_wrap() { let mut s = socket_established(); @@ -3271,33 +3825,45 @@ mod test { #[test] fn test_established_no_ack() { let mut s = socket_established(); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: None, - ..SEND_TEMPL - }, Err(Error::Dropped)); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: None, + ..SEND_TEMPL + }, + Err(Error::Dropped) + ); } #[test] fn test_established_bad_ack() { let mut s = socket_established(); // Already acknowledged data. - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(TcpSeqNumber(LOCAL_SEQ.0 - 1)), - ..SEND_TEMPL - }, Err(Error::Dropped)); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(TcpSeqNumber(LOCAL_SEQ.0 - 1)), + ..SEND_TEMPL + }, + Err(Error::Dropped) + ); assert_eq!(s.local_seq_no, LOCAL_SEQ + 1); // Data not yet transmitted. - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 10), - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - ..RECV_TEMPL - }))); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 10), + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + ..RECV_TEMPL + })) + ); assert_eq!(s.local_seq_no, LOCAL_SEQ + 1); } @@ -3305,32 +3871,42 @@ mod test { fn test_established_bad_seq() { let mut s = socket_established(); // Data outside of receive window. - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 256, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - ..RECV_TEMPL - }))); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 256, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + ..RECV_TEMPL + })) + ); assert_eq!(s.remote_seq_no, REMOTE_SEQ + 1); } #[test] fn test_established_fin() { let mut s = socket_established(); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - ..RECV_TEMPL - }]); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + ..RECV_TEMPL + }] + ); assert_eq!(s.state, State::CloseWait); sanity!(s, socket_close_wait()); } @@ -3338,29 +3914,37 @@ mod test { #[test] fn test_established_fin_after_missing() { let mut s = socket_established(); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1 + 6, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"123456"[..], - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - ..RECV_TEMPL - }))); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1 + 6, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"123456"[..], + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + ..RECV_TEMPL + })) + ); assert_eq!(s.state, State::Established); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abcdef"[..], - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 6 + 6), - window_len: 52, - ..RECV_TEMPL - }))); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abcdef"[..], + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 6 + 6), + window_len: 52, + ..RECV_TEMPL + })) + ); assert_eq!(s.state, State::Established); } @@ -3368,42 +3952,54 @@ mod test { fn test_established_send_fin() { let mut s = socket_established(); s.send_slice(b"abcdef").unwrap(); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::CloseWait); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - payload: &b"abcdef"[..], - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + payload: &b"abcdef"[..], + ..RECV_TEMPL + }] + ); } #[test] fn test_established_rst() { let mut s = socket_established(); - send!(s, TcpRepr { - control: TcpControl::Rst, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Rst, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Closed); } #[test] fn test_established_rst_no_ack() { let mut s = socket_established(); - send!(s, TcpRepr { - control: TcpControl::Rst, - seq_number: REMOTE_SEQ + 1, - ack_number: None, - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Rst, + seq_number: REMOTE_SEQ + 1, + ack_number: None, + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Closed); } @@ -3420,55 +4016,68 @@ mod test { let mut s = socket_established(); s.abort(); assert_eq!(s.state, State::Closed); - recv!(s, [TcpRepr { - control: TcpControl::Rst, - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + control: TcpControl::Rst, + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + ..RECV_TEMPL + }] + ); } #[test] fn test_established_rst_bad_seq() { let mut s = socket_established(); - send!(s, TcpRepr { - control: TcpControl::Rst, - seq_number: REMOTE_SEQ, // Wrong seq - ack_number: None, - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - ..RECV_TEMPL - }))); + send!( + s, + TcpRepr { + control: TcpControl::Rst, + seq_number: REMOTE_SEQ, // Wrong seq + ack_number: None, + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + ..RECV_TEMPL + })) + ); assert_eq!(s.state, State::Established); // Send something to advance seq by 1 - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, // correct seq - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"a"[..], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, // correct seq + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"a"[..], + ..SEND_TEMPL + } + ); // Send wrong rst again, check that the challenge ack is correctly updated // The ack number must be updated even if we don't call dispatch on the socket // See https://github.com/smoltcp-rs/smoltcp/issues/338 - send!(s, TcpRepr { - control: TcpControl::Rst, - seq_number: REMOTE_SEQ, // Wrong seq - ack_number: None, - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 2), // this has changed - window_len: 63, - ..RECV_TEMPL - }))); + send!( + s, + TcpRepr { + control: TcpControl::Rst, + seq_number: REMOTE_SEQ, // Wrong seq + ack_number: None, + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 2), // this has changed + window_len: 63, + ..RECV_TEMPL + })) + ); } - // =========================================================================================// // Tests for the FIN-WAIT-1 state. // =========================================================================================// @@ -3476,17 +4085,23 @@ mod test { #[test] fn test_fin_wait_1_fin_ack() { let mut s = socket_fin_wait_1(); - recv!(s, [TcpRepr { - control: TcpControl::Fin, - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1 + 1), - ..SEND_TEMPL - }); + recv!( + s, + [TcpRepr { + control: TcpControl::Fin, + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1 + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::FinWait2); sanity!(s, socket_fin_wait_2()); } @@ -3494,18 +4109,24 @@ mod test { #[test] fn test_fin_wait_1_fin_fin() { let mut s = socket_fin_wait_1(); - recv!(s, [TcpRepr { - control: TcpControl::Fin, - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + recv!( + s, + [TcpRepr { + control: TcpControl::Fin, + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Closing); sanity!(s, socket_closing()); } @@ -3516,34 +4137,44 @@ mod test { s.remote_win_len = 6; s.send_slice(b"abcdef123456").unwrap(); s.close(); - recv!(s, Ok(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"abcdef"[..], - ..RECV_TEMPL - })); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1 + 6), - ..SEND_TEMPL - }); + recv!( + s, + Ok(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"abcdef"[..], + ..RECV_TEMPL + }) + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1 + 6), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::FinWait1); } #[test] fn test_fin_wait_1_recv() { let mut s = socket_fin_wait_1(); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abc"[..], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::FinWait1); s.recv(|data| { assert_eq!(data, b"abc"); (3, ()) - }).unwrap(); + }) + .unwrap(); } #[test] @@ -3573,22 +4204,29 @@ mod test { #[test] fn test_fin_wait_2_recv() { let mut s = socket_fin_wait_2(); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1 + 1), - payload: &b"abc"[..], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1 + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::FinWait2); s.recv(|data| { assert_eq!(data, b"abc"); (3, ()) - }).unwrap(); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 1, - ack_number: Some(REMOTE_SEQ + 1 + 3), - ..RECV_TEMPL - }]); + }) + .unwrap(); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 1, + ack_number: Some(REMOTE_SEQ + 1 + 3), + ..RECV_TEMPL + }] + ); } #[test] @@ -3605,11 +4243,14 @@ mod test { #[test] fn test_closing_ack_fin() { let mut s = socket_closing(); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + ..RECV_TEMPL + }] + ); send!(s, time 1_000, TcpRepr { seq_number: REMOTE_SEQ + 1 + 1, ack_number: Some(LOCAL_SEQ + 1 + 1), @@ -3633,11 +4274,14 @@ mod test { #[test] fn test_time_wait_from_fin_wait_2_ack() { let mut s = socket_time_wait(false); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + ..RECV_TEMPL + }] + ); } #[test] @@ -3656,11 +4300,14 @@ mod test { #[test] fn test_time_wait_retransmit() { let mut s = socket_time_wait(false); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + ..RECV_TEMPL + }] + ); send!(s, time 5_000, TcpRepr { control: TcpControl::Fin, seq_number: REMOTE_SEQ + 1, @@ -3671,17 +4318,25 @@ mod test { ack_number: Some(REMOTE_SEQ + 1 + 1), ..RECV_TEMPL }))); - assert_eq!(s.timer, Timer::Close { expires_at: Instant::from_secs(5) + CLOSE_DELAY }); + assert_eq!( + s.timer, + Timer::Close { + expires_at: Instant::from_secs(5) + CLOSE_DELAY + } + ); } #[test] fn test_time_wait_timeout() { let mut s = socket_time_wait(false); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + ..RECV_TEMPL + }] + ); assert_eq!(s.state, State::TimeWait); recv!(s, time 60_000, Err(Error::Exhausted)); assert_eq!(s.state, State::Closed); @@ -3695,17 +4350,23 @@ mod test { fn test_close_wait_ack() { let mut s = socket_close_wait(); s.send_slice(b"abcdef").unwrap(); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - payload: &b"abcdef"[..], - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 1, - ack_number: Some(LOCAL_SEQ + 1 + 6), - ..SEND_TEMPL - }); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + payload: &b"abcdef"[..], + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 1, + ack_number: Some(LOCAL_SEQ + 1 + 6), + ..SEND_TEMPL + } + ); } #[test] @@ -3722,46 +4383,61 @@ mod test { #[test] fn test_last_ack_fin_ack() { let mut s = socket_last_ack(); - recv!(s, [TcpRepr { - control: TcpControl::Fin, - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + control: TcpControl::Fin, + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + ..RECV_TEMPL + }] + ); assert_eq!(s.state, State::LastAck); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 1, - ack_number: Some(LOCAL_SEQ + 1 + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 1, + ack_number: Some(LOCAL_SEQ + 1 + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Closed); } #[test] fn test_last_ack_ack_not_of_fin() { let mut s = socket_last_ack(); - recv!(s, [TcpRepr { - control: TcpControl::Fin, - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + control: TcpControl::Fin, + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + ..RECV_TEMPL + }] + ); assert_eq!(s.state, State::LastAck); // ACK received that doesn't ack the FIN: socket should stay in LastAck. - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::LastAck); // ACK received of fin: socket should change to Closed. - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 1, - ack_number: Some(LOCAL_SEQ + 1 + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 1, + ack_number: Some(LOCAL_SEQ + 1 + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Closed); } @@ -3779,34 +4455,44 @@ mod test { #[test] fn test_listen() { let mut s = socket(); - s.listen(IpEndpoint::new(IpAddress::default(), LOCAL_PORT)).unwrap(); + s.listen(IpEndpoint::new(IpAddress::default(), LOCAL_PORT)) + .unwrap(); assert_eq!(s.state, State::Listen); } #[test] fn test_three_way_handshake() { let mut s = socket_listen(); - send!(s, TcpRepr { - control: TcpControl::Syn, - seq_number: REMOTE_SEQ, - ack_number: None, - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: None, + ..SEND_TEMPL + } + ); assert_eq!(s.state(), State::SynReceived); assert_eq!(s.local_endpoint(), LOCAL_END); assert_eq!(s.remote_endpoint(), REMOTE_END); - recv!(s, [TcpRepr { - control: TcpControl::Syn, - seq_number: LOCAL_SEQ, - ack_number: Some(REMOTE_SEQ + 1), - max_seg_size: Some(BASE_MSS), - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + recv!( + s, + [TcpRepr { + control: TcpControl::Syn, + seq_number: LOCAL_SEQ, + ack_number: Some(REMOTE_SEQ + 1), + max_seg_size: Some(BASE_MSS), + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state(), State::Established); assert_eq!(s.local_seq_no, LOCAL_SEQ + 1); assert_eq!(s.remote_seq_no, REMOTE_SEQ + 1); @@ -3815,31 +4501,43 @@ mod test { #[test] fn test_remote_close() { let mut s = socket_established(); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::CloseWait); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + ..RECV_TEMPL + }] + ); s.close(); assert_eq!(s.state, State::LastAck); - recv!(s, [TcpRepr { - control: TcpControl::Fin, - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 1, - ack_number: Some(LOCAL_SEQ + 1 + 1), - ..SEND_TEMPL - }); + recv!( + s, + [TcpRepr { + control: TcpControl::Fin, + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 1, + ack_number: Some(LOCAL_SEQ + 1 + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Closed); } @@ -3848,30 +4546,42 @@ mod test { let mut s = socket_established(); s.close(); assert_eq!(s.state, State::FinWait1); - recv!(s, [TcpRepr { - control: TcpControl::Fin, - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1 + 1), - ..SEND_TEMPL - }); + recv!( + s, + [TcpRepr { + control: TcpControl::Fin, + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1 + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::FinWait2); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1 + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1 + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::TimeWait); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + ..RECV_TEMPL + }] + ); } #[test] @@ -3879,30 +4589,43 @@ mod test { let mut s = socket_established(); s.close(); assert_eq!(s.state, State::FinWait1); - recv!(s, [TcpRepr { // due to reordering, this is logically located... - control: TcpControl::Fin, - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + recv!( + s, + [TcpRepr { + // due to reordering, this is logically located... + control: TcpControl::Fin, + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Closing); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + ..RECV_TEMPL + }] + ); // ... at this point - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 1, - ack_number: Some(LOCAL_SEQ + 1 + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 1, + ack_number: Some(LOCAL_SEQ + 1 + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::TimeWait); recv!(s, []); } @@ -3912,24 +4635,33 @@ mod test { let mut s = socket_established(); s.close(); assert_eq!(s.state, State::FinWait1); - recv!(s, [TcpRepr { - control: TcpControl::Fin, - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1 + 1), - ..SEND_TEMPL - }); + recv!( + s, + [TcpRepr { + control: TcpControl::Fin, + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1 + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::TimeWait); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + ..RECV_TEMPL + }] + ); } #[test] @@ -3939,28 +4671,37 @@ mod test { assert_eq!(s.state, State::FinWait1); // Socket receives FIN before it has a chance to send its own FIN - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Closing); // FIN + ack-of-FIN - recv!(s, [TcpRepr { - control: TcpControl::Fin, - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + control: TcpControl::Fin, + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + ..RECV_TEMPL + }] + ); assert_eq!(s.state, State::Closing); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 1, - ack_number: Some(LOCAL_SEQ + 1 + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 1, + ack_number: Some(LOCAL_SEQ + 1 + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::TimeWait); recv!(s, []); } @@ -3973,29 +4714,38 @@ mod test { assert_eq!(s.state, State::FinWait1); // Socket receives FIN before it has a chance to send its own data+FIN - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Closing); // data + FIN + ack-of-FIN - recv!(s, [TcpRepr { - control: TcpControl::Fin, - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - payload: &b"abcdef"[..], - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + control: TcpControl::Fin, + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + payload: &b"abcdef"[..], + ..RECV_TEMPL + }] + ); assert_eq!(s.state, State::Closing); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 1, - ack_number: Some(LOCAL_SEQ + 1 + 6 + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 1, + ack_number: Some(LOCAL_SEQ + 1 + 6 + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::TimeWait); recv!(s, []); } @@ -4005,13 +4755,16 @@ mod test { let mut s = socket_established(); s.send_slice(b"abcdef").unwrap(); s.close(); - recv!(s, [TcpRepr { - control: TcpControl::Fin, - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"abcdef"[..], - ..RECV_TEMPL - }]) + recv!( + s, + [TcpRepr { + control: TcpControl::Fin, + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"abcdef"[..], + ..RECV_TEMPL + }] + ) } #[test] @@ -4020,19 +4773,25 @@ mod test { s.send_slice(b"abcdef").unwrap(); s.close(); assert_eq!(s.state, State::FinWait1); - recv!(s, [TcpRepr { - control: TcpControl::Fin, - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"abcdef"[..], - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1 + 6 + 1), - ..SEND_TEMPL - }); + recv!( + s, + [TcpRepr { + control: TcpControl::Fin, + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"abcdef"[..], + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1 + 6 + 1), + ..SEND_TEMPL + } + ); } #[test] @@ -4041,30 +4800,42 @@ mod test { s.send_slice(b"abcdef").unwrap(); s.close(); assert_eq!(s.state, State::FinWait1); - recv!(s, [TcpRepr { - control: TcpControl::Fin, - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"abcdef"[..], - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1 + 6 + 1), - ..SEND_TEMPL - }); + recv!( + s, + [TcpRepr { + control: TcpControl::Fin, + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"abcdef"[..], + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1 + 6 + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::FinWait2); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1 + 6 + 1), - ..SEND_TEMPL - }); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 6 + 1, - ack_number: Some(REMOTE_SEQ + 1 + 1), - ..RECV_TEMPL - }]); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1 + 6 + 1), + ..SEND_TEMPL + } + ); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 6 + 1, + ack_number: Some(REMOTE_SEQ + 1 + 1), + ..RECV_TEMPL + }] + ); assert_eq!(s.state, State::TimeWait); } @@ -4076,17 +4847,21 @@ mod test { fn test_duplicate_seq_ack() { let mut s = socket_recved(); // remote retransmission - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abcdef"[..], - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 6), - window_len: 58, - ..RECV_TEMPL - }))); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abcdef"[..], + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 6), + window_len: 58, + ..RECV_TEMPL + })) + ); } #[test] @@ -4166,19 +4941,25 @@ mod test { max_seg_size: Some(BASE_MSS), ..RECV_TEMPL })); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); assert_eq!(s.state(), State::Established); s.send_slice(b"abcdef").unwrap(); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"abcdef"[..], - ..RECV_TEMPL - }]) + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"abcdef"[..], + ..RECV_TEMPL + }] + ) } #[test] @@ -4195,11 +4976,14 @@ mod test { // Retransmit timer is on because all data was sent assert_eq!(s.tx_buffer.len(), 3); // ACK nothing new - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); // Retransmit recv!(s, time 4000, Ok(TcpRepr { seq_number: LOCAL_SEQ + 1, @@ -4486,45 +5270,61 @@ mod test { })); // Normal ACK of previously recieved segment - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); // First duplicate - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); // Second duplicate - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); - assert_eq!(s.local_rx_dup_acks, 2, - "duplicate ACK counter is not set"); + assert_eq!(s.local_rx_dup_acks, 2, "duplicate ACK counter is not set"); // This packet has content, hence should not be detected // as a duplicate ACK and should reset the duplicate ACK count - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"xxxxxx"[..], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"xxxxxx"[..], + ..SEND_TEMPL + } + ); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 3, - ack_number: Some(REMOTE_SEQ + 1 + 6), - window_len: 58, - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 3, + ack_number: Some(REMOTE_SEQ + 1 + 6), + window_len: 58, + ..RECV_TEMPL + }] + ); - assert_eq!(s.local_rx_dup_acks, 0, - "duplicate ACK counter is not reset when reciving data"); + assert_eq!( + s.local_rx_dup_acks, 0, + "duplicate ACK counter is not reset when reciving data" + ); } #[test] @@ -4546,8 +5346,10 @@ mod test { ..SEND_TEMPL }); - assert_eq!(s.local_rx_dup_acks, 0, - "duplicate ACK counter is set but wound not transmit data"); + assert_eq!( + s.local_rx_dup_acks, 0, + "duplicate ACK counter is set but wound not transmit data" + ); // Send a long string of text divided into several packets // because of small remote_mss @@ -4598,8 +5400,10 @@ mod test { ..SEND_TEMPL }); - assert_eq!(s.local_rx_dup_acks, 0, - "duplicate ACK counter is not reset when reciving ACK which updates send window"); + assert_eq!( + s.local_rx_dup_acks, 0, + "duplicate ACK counter is not reset when reciving ACK which updates send window" + ); // ACK all recived segments send!(s, time 1120, TcpRepr { @@ -4648,7 +5452,11 @@ mod test { ack_number: Some(LOCAL_SEQ + 1), ..SEND_TEMPL }); - assert_eq!(s.local_rx_dup_acks, u8::max_value(), "duplicate ACK count should not overflow but saturate"); + assert_eq!( + s.local_rx_dup_acks, + u8::max_value(), + "duplicate ACK count should not overflow but saturate" + ); } // =========================================================================================// @@ -4659,54 +5467,72 @@ mod test { fn test_maximum_segment_size() { let mut s = socket_listen(); s.tx_buffer = SocketBuffer::new(vec![0; 32767]); - send!(s, TcpRepr { - control: TcpControl::Syn, - seq_number: REMOTE_SEQ, - ack_number: None, - max_seg_size: Some(1000), - ..SEND_TEMPL - }); - recv!(s, [TcpRepr { - control: TcpControl::Syn, - seq_number: LOCAL_SEQ, - ack_number: Some(REMOTE_SEQ + 1), - max_seg_size: Some(BASE_MSS), - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - window_len: 32767, - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Syn, + seq_number: REMOTE_SEQ, + ack_number: None, + max_seg_size: Some(1000), + ..SEND_TEMPL + } + ); + recv!( + s, + [TcpRepr { + control: TcpControl::Syn, + seq_number: LOCAL_SEQ, + ack_number: Some(REMOTE_SEQ + 1), + max_seg_size: Some(BASE_MSS), + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + window_len: 32767, + ..SEND_TEMPL + } + ); s.send_slice(&[0; 1200][..]).unwrap(); - recv!(s, Ok(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - payload: &[0; 1000][..], - ..RECV_TEMPL - })); + recv!( + s, + Ok(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &[0; 1000][..], + ..RECV_TEMPL + }) + ); } #[test] fn test_close_wait_no_window_update() { let mut s = socket_established(); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &[1,2,3,4], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &[1, 2, 3, 4], + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::CloseWait); // we ack the FIN, with the reduced window size. - recv!(s, Ok(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 6), - window_len: 60, - ..RECV_TEMPL - })); + recv!( + s, + Ok(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 6), + window_len: 60, + ..RECV_TEMPL + }) + ); let rx_buf = &mut [0; 32]; assert_eq!(s.recv_slice(rx_buf), Ok(4)); @@ -4718,22 +5544,28 @@ mod test { #[test] fn test_time_wait_no_window_update() { let mut s = socket_fin_wait_2(); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 2), - payload: &[1,2,3,4], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 2), + payload: &[1, 2, 3, 4], + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::TimeWait); // we ack the FIN, with the reduced window size. - recv!(s, Ok(TcpRepr { - seq_number: LOCAL_SEQ + 2, - ack_number: Some(REMOTE_SEQ + 6), - window_len: 60, - ..RECV_TEMPL - })); + recv!( + s, + Ok(TcpRepr { + seq_number: LOCAL_SEQ + 2, + ack_number: Some(REMOTE_SEQ + 6), + window_len: 60, + ..RECV_TEMPL + }) + ); let rx_buf = &mut [0; 32]; assert_eq!(s.recv_slice(rx_buf), Ok(4)); @@ -4771,19 +5603,25 @@ mod test { #[test] fn test_psh_receive() { let mut s = socket_established(); - send!(s, TcpRepr { - control: TcpControl::Psh, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abcdef"[..], - ..SEND_TEMPL - }); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 6), - window_len: 58, - ..RECV_TEMPL - }]); + send!( + s, + TcpRepr { + control: TcpControl::Psh, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abcdef"[..], + ..SEND_TEMPL + } + ); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 6), + window_len: 58, + ..RECV_TEMPL + }] + ); } #[test] @@ -4791,29 +5629,39 @@ mod test { let mut s = socket_established(); s.rx_buffer = SocketBuffer::new(vec![0; 6]); s.assembler = Assembler::new(s.rx_buffer.capacity()); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abcdef"[..], - ..SEND_TEMPL - }); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 6), - window_len: 0, - ..RECV_TEMPL - }]); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 6, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"123456"[..], - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 6), - window_len: 0, - ..RECV_TEMPL - }))); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abcdef"[..], + ..SEND_TEMPL + } + ); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 6), + window_len: 0, + ..RECV_TEMPL + }] + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 6, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"123456"[..], + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 6), + window_len: 0, + ..RECV_TEMPL + })) + ); } #[test] @@ -4821,23 +5669,30 @@ mod test { let mut s = socket_established(); s.rx_buffer = SocketBuffer::new(vec![0; 6]); s.assembler = Assembler::new(s.rx_buffer.capacity()); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abcdef"[..], - ..SEND_TEMPL - }); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 6), - window_len: 0, - ..RECV_TEMPL - }]); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abcdef"[..], + ..SEND_TEMPL + } + ); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 6), + window_len: 0, + ..RECV_TEMPL + }] + ); recv!(s, time 0, Err(Error::Exhausted)); s.recv(|buffer| { assert_eq!(&buffer[..3], b"abc"); (3, ()) - }).unwrap(); + }) + .unwrap(); recv!(s, time 0, Ok(TcpRepr { seq_number: LOCAL_SEQ + 1, ack_number: Some(REMOTE_SEQ + 1 + 6), @@ -4848,7 +5703,8 @@ mod test { s.recv(|buffer| { assert_eq!(buffer, b"def"); (buffer.len(), ()) - }).unwrap(); + }) + .unwrap(); recv!(s, time 0, Ok(TcpRepr { seq_number: LOCAL_SEQ + 1, ack_number: Some(REMOTE_SEQ + 1 + 6), @@ -4862,22 +5718,29 @@ mod test { let mut s = socket_established(); s.remote_mss = 6; s.send_slice(b"abcdef123456!@#$%^").unwrap(); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"abcdef"[..], - ..RECV_TEMPL - }, TcpRepr { - seq_number: LOCAL_SEQ + 1 + 6, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"123456"[..], - ..RECV_TEMPL - }, TcpRepr { - seq_number: LOCAL_SEQ + 1 + 6 + 6, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"!@#$%^"[..], - ..RECV_TEMPL - }]); + recv!( + s, + [ + TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"abcdef"[..], + ..RECV_TEMPL + }, + TcpRepr { + seq_number: LOCAL_SEQ + 1 + 6, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"123456"[..], + ..RECV_TEMPL + }, + TcpRepr { + seq_number: LOCAL_SEQ + 1 + 6 + 6, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"!@#$%^"[..], + ..RECV_TEMPL + } + ] + ); } #[test] @@ -4885,58 +5748,71 @@ mod test { let mut s = socket_established(); s.rx_buffer = SocketBuffer::new(vec![0; 6]); s.assembler = Assembler::new(s.rx_buffer.capacity()); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abc"[..], - ..SEND_TEMPL - }); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 3), - window_len: 3, - ..RECV_TEMPL - }]); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + } + ); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 3), + window_len: 3, + ..RECV_TEMPL + }] + ); // Test that `dispatch` updates `remote_last_win` assert_eq!(s.remote_last_win, s.rx_buffer.window() as u16); - s.recv(|buffer| { - (buffer.len(), ()) - }).unwrap(); + s.recv(|buffer| (buffer.len(), ())).unwrap(); assert!(s.window_to_update()); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 3), - window_len: 6, - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 3), + window_len: 6, + ..RECV_TEMPL + }] + ); assert_eq!(s.remote_last_win, s.rx_buffer.window() as u16); // Provoke immediate ACK to test that `process` updates `remote_last_win` - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 6, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"def"[..], - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 3), - window_len: 6, - ..RECV_TEMPL - }))); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 3, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abc"[..], - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 9), - window_len: 0, - ..RECV_TEMPL - }))); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 6, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"def"[..], + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 3), + window_len: 6, + ..RECV_TEMPL + })) + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 3, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 9), + window_len: 0, + ..RECV_TEMPL + })) + ); assert_eq!(s.remote_last_win, s.rx_buffer.window() as u16); - s.recv(|buffer| { - (buffer.len(), ()) - }).unwrap(); + s.recv(|buffer| (buffer.len(), ())).unwrap(); assert!(s.window_to_update()); } @@ -4967,7 +5843,10 @@ mod test { ..RECV_TEMPL })); assert_eq!(s.state, State::SynSent); - assert_eq!(s.poll_at(&Context::DUMMY), PollAt::Time(Instant::from_millis(250))); + assert_eq!( + s.poll_at(&Context::DUMMY), + PollAt::Time(Instant::from_millis(250)) + ); recv!(s, time 250, Ok(TcpRepr { control: TcpControl::Rst, seq_number: LOCAL_SEQ + 1, @@ -4983,7 +5862,10 @@ mod test { let mut s = socket_established(); s.set_timeout(Some(Duration::from_millis(1000))); recv!(s, time 250, Err(Error::Exhausted)); - assert_eq!(s.poll_at(&Context::DUMMY), PollAt::Time(Instant::from_millis(1250))); + assert_eq!( + s.poll_at(&Context::DUMMY), + PollAt::Time(Instant::from_millis(1250)) + ); s.send_slice(b"abcdef").unwrap(); assert_eq!(s.poll_at(&Context::DUMMY), PollAt::Now); recv!(s, time 255, Ok(TcpRepr { @@ -4992,14 +5874,20 @@ mod test { payload: &b"abcdef"[..], ..RECV_TEMPL })); - assert_eq!(s.poll_at(&Context::DUMMY), PollAt::Time(Instant::from_millis(955))); + assert_eq!( + s.poll_at(&Context::DUMMY), + PollAt::Time(Instant::from_millis(955)) + ); recv!(s, time 955, Ok(TcpRepr { seq_number: LOCAL_SEQ + 1, ack_number: Some(REMOTE_SEQ + 1), payload: &b"abcdef"[..], ..RECV_TEMPL })); - assert_eq!(s.poll_at(&Context::DUMMY), PollAt::Time(Instant::from_millis(1255))); + assert_eq!( + s.poll_at(&Context::DUMMY), + PollAt::Time(Instant::from_millis(1255)) + ); recv!(s, time 1255, Ok(TcpRepr { control: TcpControl::Rst, seq_number: LOCAL_SEQ + 1 + 6, @@ -5021,13 +5909,19 @@ mod test { ..RECV_TEMPL })); recv!(s, time 100, Err(Error::Exhausted)); - assert_eq!(s.poll_at(&Context::DUMMY), PollAt::Time(Instant::from_millis(150))); + assert_eq!( + s.poll_at(&Context::DUMMY), + PollAt::Time(Instant::from_millis(150)) + ); send!(s, time 105, TcpRepr { seq_number: REMOTE_SEQ + 1, ack_number: Some(LOCAL_SEQ + 1), ..SEND_TEMPL }); - assert_eq!(s.poll_at(&Context::DUMMY), PollAt::Time(Instant::from_millis(155))); + assert_eq!( + s.poll_at(&Context::DUMMY), + PollAt::Time(Instant::from_millis(155)) + ); recv!(s, time 155, Ok(TcpRepr { seq_number: LOCAL_SEQ, ack_number: Some(REMOTE_SEQ + 1), @@ -5035,7 +5929,10 @@ mod test { ..RECV_TEMPL })); recv!(s, time 155, Err(Error::Exhausted)); - assert_eq!(s.poll_at(&Context::DUMMY), PollAt::Time(Instant::from_millis(205))); + assert_eq!( + s.poll_at(&Context::DUMMY), + PollAt::Time(Instant::from_millis(205)) + ); recv!(s, time 200, Err(Error::Exhausted)); recv!(s, time 205, Ok(TcpRepr { control: TcpControl::Rst, @@ -5108,15 +6005,19 @@ mod test { #[test] fn test_responds_to_keep_alive() { let mut s = socket_established(); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - ..RECV_TEMPL - }))); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + ..RECV_TEMPL + })) + ); } #[test] @@ -5133,7 +6034,10 @@ mod test { ..RECV_TEMPL })); - assert_eq!(s.poll_at(&Context::DUMMY), PollAt::Time(Instant::from_millis(100))); + assert_eq!( + s.poll_at(&Context::DUMMY), + PollAt::Time(Instant::from_millis(100)) + ); recv!(s, time 95, Err(Error::Exhausted)); recv!(s, time 100, Ok(TcpRepr { seq_number: LOCAL_SEQ, @@ -5142,7 +6046,10 @@ mod test { ..RECV_TEMPL })); - assert_eq!(s.poll_at(&Context::DUMMY), PollAt::Time(Instant::from_millis(200))); + assert_eq!( + s.poll_at(&Context::DUMMY), + PollAt::Time(Instant::from_millis(200)) + ); recv!(s, time 195, Err(Error::Exhausted)); recv!(s, time 200, Ok(TcpRepr { seq_number: LOCAL_SEQ, @@ -5156,7 +6063,10 @@ mod test { ack_number: Some(LOCAL_SEQ + 1), ..SEND_TEMPL }); - assert_eq!(s.poll_at(&Context::DUMMY), PollAt::Time(Instant::from_millis(350))); + assert_eq!( + s.poll_at(&Context::DUMMY), + PollAt::Time(Instant::from_millis(350)) + ); recv!(s, time 345, Err(Error::Exhausted)); recv!(s, time 350, Ok(TcpRepr { seq_number: LOCAL_SEQ, @@ -5175,10 +6085,13 @@ mod test { let mut s = socket_syn_received(); s.set_hop_limit(Some(0x2a)); - assert_eq!(s.dispatch(&Context::DUMMY, |(ip_repr, _)| { - assert_eq!(ip_repr.hop_limit(), 0x2a); + assert_eq!( + s.dispatch(&Context::DUMMY, |(ip_repr, _)| { + assert_eq!(ip_repr.hop_limit(), 0x2a); + Ok(()) + }), Ok(()) - }), Ok(())); + ); } #[test] @@ -5195,35 +6108,45 @@ mod test { #[test] fn test_out_of_order() { let mut s = socket_established(); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 3, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"def"[..], - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - ..RECV_TEMPL - }))); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 3, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"def"[..], + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + ..RECV_TEMPL + })) + ); s.recv(|buffer| { assert_eq!(buffer, b""); (buffer.len(), ()) - }).unwrap(); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abcdef"[..], - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 6), - window_len: 58, - ..RECV_TEMPL - }))); + }) + .unwrap(); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abcdef"[..], + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 6), + window_len: 58, + ..RECV_TEMPL + })) + ); s.recv(|buffer| { assert_eq!(buffer, b"abcdef"); (buffer.len(), ()) - }).unwrap(); + }) + .unwrap(); } #[test] @@ -5231,22 +6154,29 @@ mod test { let mut s = socket_established(); s.rx_buffer = SocketBuffer::new(vec![0; 6]); s.assembler = Assembler::new(s.rx_buffer.capacity()); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abc"[..], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + } + ); s.recv(|buffer| { assert_eq!(buffer, b"abc"); (buffer.len(), ()) - }).unwrap(); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 3, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"defghi"[..], - ..SEND_TEMPL - }); + }) + .unwrap(); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 3, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"defghi"[..], + ..SEND_TEMPL + } + ); let mut data = [0; 6]; assert_eq!(s.recv_slice(&mut data[..]), Ok(6)); assert_eq!(data, &b"defghi"[..]); @@ -5264,18 +6194,24 @@ mod test { // "abcdef" not contiguous in tx buffer assert_eq!(s.send_slice(b"abcdef"), Ok(6)); - recv!(s, Ok(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"yyyabc"[..], - ..RECV_TEMPL - })); - recv!(s, Ok(TcpRepr { - seq_number: LOCAL_SEQ + 1 + 6, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"def"[..], - ..RECV_TEMPL - })); + recv!( + s, + Ok(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"yyyabc"[..], + ..RECV_TEMPL + }) + ); + recv!( + s, + Ok(TcpRepr { + seq_number: LOCAL_SEQ + 1 + 6, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"def"[..], + ..RECV_TEMPL + }) + ); } // =========================================================================================// @@ -5285,93 +6221,115 @@ mod test { #[test] fn test_rx_close_fin() { let mut s = socket_established(); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abc"[..], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + } + ); s.recv(|data| { assert_eq!(data, b"abc"); (3, ()) - }).unwrap(); + }) + .unwrap(); assert_eq!(s.recv(|_| (0, ())), Err(Error::Finished)); } #[test] fn test_rx_close_fin_in_fin_wait_1() { let mut s = socket_fin_wait_1(); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abc"[..], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::Closing); s.recv(|data| { assert_eq!(data, b"abc"); (3, ()) - }).unwrap(); + }) + .unwrap(); assert_eq!(s.recv(|_| (0, ())), Err(Error::Finished)); } #[test] fn test_rx_close_fin_in_fin_wait_2() { let mut s = socket_fin_wait_2(); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1 + 1), - payload: &b"abc"[..], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1 + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + } + ); assert_eq!(s.state, State::TimeWait); s.recv(|data| { assert_eq!(data, b"abc"); (3, ()) - }).unwrap(); + }) + .unwrap(); assert_eq!(s.recv(|_| (0, ())), Err(Error::Finished)); } - - #[test] fn test_rx_close_fin_with_hole() { let mut s = socket_established(); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abc"[..], - ..SEND_TEMPL - }); - send!(s, TcpRepr { - control: TcpControl::Fin, - seq_number: REMOTE_SEQ + 1 + 6, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"ghi"[..], - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 3), - window_len: 61, - ..RECV_TEMPL - }))); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + } + ); + send!( + s, + TcpRepr { + control: TcpControl::Fin, + seq_number: REMOTE_SEQ + 1 + 6, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"ghi"[..], + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 3), + window_len: 61, + ..RECV_TEMPL + })) + ); s.recv(|data| { assert_eq!(data, b"abc"); (3, ()) - }).unwrap(); + }) + .unwrap(); s.recv(|data| { assert_eq!(data, b""); (0, ()) - }).unwrap(); - send!(s, TcpRepr { - control: TcpControl::Rst, - seq_number: REMOTE_SEQ + 1 + 9, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + }) + .unwrap(); + send!( + s, + TcpRepr { + control: TcpControl::Rst, + seq_number: REMOTE_SEQ + 1 + 9, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); // Error must be `Illegal` even if we've received a FIN, // because we are missing data. assert_eq!(s.recv(|_| (0, ())), Err(Error::Illegal)); @@ -5380,55 +6338,73 @@ mod test { #[test] fn test_rx_close_rst() { let mut s = socket_established(); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abc"[..], - ..SEND_TEMPL - }); - send!(s, TcpRepr { - control: TcpControl::Rst, - seq_number: REMOTE_SEQ + 1 + 3, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + } + ); + send!( + s, + TcpRepr { + control: TcpControl::Rst, + seq_number: REMOTE_SEQ + 1 + 3, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); s.recv(|data| { assert_eq!(data, b"abc"); (3, ()) - }).unwrap(); + }) + .unwrap(); assert_eq!(s.recv(|_| (0, ())), Err(Error::Illegal)); } #[test] fn test_rx_close_rst_with_hole() { let mut s = socket_established(); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abc"[..], - ..SEND_TEMPL - }); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 6, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"ghi"[..], - ..SEND_TEMPL - }, Ok(Some(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 3), - window_len: 61, - ..RECV_TEMPL - }))); - send!(s, TcpRepr { - control: TcpControl::Rst, - seq_number: REMOTE_SEQ + 1 + 9, - ack_number: Some(LOCAL_SEQ + 1), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + } + ); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 6, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"ghi"[..], + ..SEND_TEMPL + }, + Ok(Some(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 3), + window_len: 61, + ..RECV_TEMPL + })) + ); + send!( + s, + TcpRepr { + control: TcpControl::Rst, + seq_number: REMOTE_SEQ + 1 + 9, + ack_number: Some(LOCAL_SEQ + 1), + ..SEND_TEMPL + } + ); s.recv(|data| { assert_eq!(data, b"abc"); (3, ()) - }).unwrap(); + }) + .unwrap(); assert_eq!(s.recv(|_| (0, ())), Err(Error::Illegal)); } @@ -5440,12 +6416,15 @@ mod test { fn test_delayed_ack() { let mut s = socket_established(); 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"[..], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + } + ); // No ACK is immediately sent. recv!(s, Err(Error::Exhausted)); @@ -5463,18 +6442,22 @@ mod test { fn test_delayed_ack_win() { let mut s = socket_established(); 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"[..], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + } + ); // Reading the data off the buffer should cause a window update. s.recv(|data| { assert_eq!(data, b"abc"); (3, ()) - }).unwrap(); + }) + .unwrap(); // However, no ACK or window update is immediately sent. recv!(s, Err(Error::Exhausted)); @@ -5491,58 +6474,74 @@ mod test { fn test_delayed_ack_reply() { let mut s = socket_established(); 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"[..], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + } + ); s.recv(|data| { assert_eq!(data, b"abc"); (3, ()) - }).unwrap(); + }) + .unwrap(); s.send_slice(&b"xyz"[..]).unwrap(); // Writing data to the socket causes ACK to not be delayed, // because it is immediately sent with the data. - recv!(s, Ok(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 3), - payload: &b"xyz"[..], - ..RECV_TEMPL - })); + recv!( + s, + Ok(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 3), + payload: &b"xyz"[..], + ..RECV_TEMPL + }) + ); } #[test] fn test_delayed_ack_every_second_packet() { let mut s = socket_established(); 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"[..], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"abc"[..], + ..SEND_TEMPL + } + ); // No ACK is immediately sent. recv!(s, Err(Error::Exhausted)); - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1 + 3, - ack_number: Some(LOCAL_SEQ + 1), - payload: &b"def"[..], - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1 + 3, + ack_number: Some(LOCAL_SEQ + 1), + payload: &b"def"[..], + ..SEND_TEMPL + } + ); // Every 2nd packet, ACK is sent without delay. - recv!(s, Ok(TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1 + 6), - window_len: 58, - ..RECV_TEMPL - })); + recv!( + s, + Ok(TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1 + 6), + window_len: 58, + ..RECV_TEMPL + }) + ); } // =========================================================================================// @@ -5555,45 +6554,60 @@ mod test { s.remote_mss = 6; s.send_slice(b"abcdef").unwrap(); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"abcdef"[..], - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"abcdef"[..], + ..RECV_TEMPL + }] + ); // If there's data in flight, full segments get sent. s.send_slice(b"foobar").unwrap(); - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 6, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"foobar"[..], - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 6, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"foobar"[..], + ..RECV_TEMPL + }] + ); s.send_slice(b"aaabbbccc").unwrap(); // If there's data in flight, not-full segments don't get sent. - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 6 + 6, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"aaabbb"[..], - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 6 + 6, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"aaabbb"[..], + ..RECV_TEMPL + }] + ); // Data gets ACKd, so there's no longer data in flight - send!(s, TcpRepr { - seq_number: REMOTE_SEQ + 1, - ack_number: Some(LOCAL_SEQ + 1 + 6 + 6 + 6), - ..SEND_TEMPL - }); + send!( + s, + TcpRepr { + seq_number: REMOTE_SEQ + 1, + ack_number: Some(LOCAL_SEQ + 1 + 6 + 6 + 6), + ..SEND_TEMPL + } + ); // Now non-full segment gets sent. - recv!(s, [TcpRepr { - seq_number: LOCAL_SEQ + 1 + 6 + 6 + 6, - ack_number: Some(REMOTE_SEQ + 1), - payload: &b"ccc"[..], - ..RECV_TEMPL - }]); + recv!( + s, + [TcpRepr { + seq_number: LOCAL_SEQ + 1 + 6 + 6 + 6, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"ccc"[..], + ..RECV_TEMPL + }] + ); } // =========================================================================================// @@ -5609,7 +6623,7 @@ mod test { let tcp_repr = TcpRepr { seq_number: REMOTE_SEQ + 1, ack_number: Some(LOCAL_SEQ + 1), - dst_port: LOCAL_PORT + 1, + dst_port: LOCAL_PORT + 1, ..SEND_TEMPL }; assert!(!s.accepts(&SEND_IP_TEMPL, &tcp_repr)); @@ -5617,7 +6631,7 @@ mod test { let tcp_repr = TcpRepr { seq_number: REMOTE_SEQ + 1, ack_number: Some(LOCAL_SEQ + 1), - src_port: REMOTE_PORT + 1, + src_port: REMOTE_PORT + 1, ..SEND_TEMPL }; assert!(!s.accepts(&SEND_IP_TEMPL, &tcp_repr)); @@ -5630,34 +6644,34 @@ mod test { let tcp_repr = TcpRepr { seq_number: REMOTE_SEQ + 1, ack_number: Some(LOCAL_SEQ + 1), - payload: &b"abcdef"[..], + payload: &b"abcdef"[..], ..SEND_TEMPL }; let ip_repr = IpRepr::Unspecified { - src_addr: MOCK_IP_ADDR_2, - dst_addr: MOCK_IP_ADDR_1, - protocol: IpProtocol::Tcp, + src_addr: MOCK_IP_ADDR_2, + dst_addr: MOCK_IP_ADDR_1, + protocol: IpProtocol::Tcp, payload_len: tcp_repr.buffer_len(), - hop_limit: 64 + hop_limit: 64, }; assert!(s.accepts(&ip_repr, &tcp_repr)); let ip_repr_wrong_src = IpRepr::Unspecified { - src_addr: MOCK_IP_ADDR_3, - dst_addr: MOCK_IP_ADDR_1, - protocol: IpProtocol::Tcp, + src_addr: MOCK_IP_ADDR_3, + dst_addr: MOCK_IP_ADDR_1, + protocol: IpProtocol::Tcp, payload_len: tcp_repr.buffer_len(), - hop_limit: 64 + hop_limit: 64, }; assert!(!s.accepts(&ip_repr_wrong_src, &tcp_repr)); let ip_repr_wrong_dst = IpRepr::Unspecified { - src_addr: MOCK_IP_ADDR_2, - dst_addr: MOCK_IP_ADDR_3, - protocol: IpProtocol::Tcp, + src_addr: MOCK_IP_ADDR_2, + dst_addr: MOCK_IP_ADDR_3, + protocol: IpProtocol::Tcp, payload_len: tcp_repr.buffer_len(), - hop_limit: 64 + hop_limit: 64, }; assert!(!s.accepts(&ip_repr_wrong_dst, &tcp_repr)); } @@ -5674,12 +6688,18 @@ mod test { r.set_for_retransmit(Instant::from_millis(1000), RTO); assert_eq!(r.should_retransmit(Instant::from_millis(1000)), None); assert_eq!(r.should_retransmit(Instant::from_millis(1050)), None); - assert_eq!(r.should_retransmit(Instant::from_millis(1101)), Some(Duration::from_millis(101))); + assert_eq!( + r.should_retransmit(Instant::from_millis(1101)), + Some(Duration::from_millis(101)) + ); r.set_for_retransmit(Instant::from_millis(1101), RTO); assert_eq!(r.should_retransmit(Instant::from_millis(1101)), None); assert_eq!(r.should_retransmit(Instant::from_millis(1150)), None); assert_eq!(r.should_retransmit(Instant::from_millis(1200)), None); - assert_eq!(r.should_retransmit(Instant::from_millis(1301)), Some(Duration::from_millis(300))); + assert_eq!( + r.should_retransmit(Instant::from_millis(1301)), + Some(Duration::from_millis(300)) + ); r.set_for_idle(Instant::from_millis(1301), None); assert_eq!(r.should_retransmit(Instant::from_millis(1350)), None); } @@ -5692,9 +6712,8 @@ mod test { let mut r = RttEstimator::default(); let rtos = &[ - 751, 766, 755, 731, 697, 656, 613, 567, - 523, 484, 445, 411, 378, 350, 322, 299, - 280, 261, 243, 229, 215, 206, 197, 188 + 751, 766, 755, 731, 697, 656, 613, 567, 523, 484, 445, 411, 378, 350, 322, 299, 280, + 261, 243, 229, 215, 206, 197, 188, ]; for &rto in rtos { @@ -5702,5 +6721,4 @@ mod test { assert_eq!(r.retransmission_timeout(), Duration::from_millis(rto)); } } - } diff --git a/src/socket/udp.rs b/src/socket/udp.rs index 7503711..ee57c37 100644 --- a/src/socket/udp.rs +++ b/src/socket/udp.rs @@ -2,12 +2,12 @@ use core::cmp::min; #[cfg(feature = "async")] use core::task::Waker; -use crate::{Error, Result}; -use crate::socket::{Socket, SocketMeta, SocketHandle, PollAt, Context}; -use crate::storage::{PacketBuffer, PacketMetadata}; -use crate::wire::{IpProtocol, IpRepr, IpEndpoint, UdpRepr}; #[cfg(feature = "async")] use crate::socket::WakerRegistration; +use crate::socket::{Context, PollAt, Socket, SocketHandle, SocketMeta}; +use crate::storage::{PacketBuffer, PacketMetadata}; +use crate::wire::{IpEndpoint, IpProtocol, IpRepr, UdpRepr}; +use crate::{Error, Result}; /// A UDP packet metadata. pub type UdpPacketMetadata = PacketMetadata; @@ -22,7 +22,7 @@ pub type UdpSocketBuffer<'a> = PacketBuffer<'a, IpEndpoint>; #[derive(Debug)] pub struct UdpSocket<'a> { pub(crate) meta: SocketMeta, - endpoint: IpEndpoint, + endpoint: IpEndpoint, rx_buffer: UdpSocketBuffer<'a>, tx_buffer: UdpSocketBuffer<'a>, /// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets. @@ -35,11 +35,10 @@ pub struct UdpSocket<'a> { impl<'a> UdpSocket<'a> { /// Create an UDP socket with the given buffers. - pub fn new(rx_buffer: UdpSocketBuffer<'a>, - tx_buffer: UdpSocketBuffer<'a>) -> UdpSocket<'a> { + pub fn new(rx_buffer: UdpSocketBuffer<'a>, tx_buffer: UdpSocketBuffer<'a>) -> UdpSocket<'a> { UdpSocket { - meta: SocketMeta::default(), - endpoint: IpEndpoint::default(), + meta: SocketMeta::default(), + endpoint: IpEndpoint::default(), rx_buffer: rx_buffer, tx_buffer: tx_buffer, hop_limit: None, @@ -131,9 +130,13 @@ impl<'a> UdpSocket<'a> { /// if the port in the given endpoint is zero. pub fn bind>(&mut self, endpoint: T) -> Result<()> { let endpoint = endpoint.into(); - if endpoint.port == 0 { return Err(Error::Unaddressable) } + if endpoint.port == 0 { + return Err(Error::Unaddressable); + } - if self.is_open() { return Err(Error::Illegal) } + if self.is_open() { + return Err(Error::Illegal); + } self.endpoint = endpoint; @@ -212,13 +215,22 @@ impl<'a> UdpSocket<'a> { /// and `Err(Error::Truncated)` if there is not enough transmit buffer capacity /// to ever send this packet. pub fn send(&mut self, size: usize, endpoint: IpEndpoint) -> Result<&mut [u8]> { - if self.endpoint.port == 0 { return Err(Error::Unaddressable) } - if !endpoint.is_specified() { return Err(Error::Unaddressable) } + if self.endpoint.port == 0 { + return Err(Error::Unaddressable); + } + if !endpoint.is_specified() { + return Err(Error::Unaddressable); + } let payload_buf = self.tx_buffer.enqueue(size, endpoint)?; - net_trace!("{}:{}:{}: buffer to send {} octets", - self.meta.handle, self.endpoint, endpoint, size); + net_trace!( + "{}:{}:{}: buffer to send {} octets", + self.meta.handle, + self.endpoint, + endpoint, + size + ); Ok(payload_buf) } @@ -237,9 +249,13 @@ impl<'a> UdpSocket<'a> { pub fn recv(&mut self) -> Result<(&[u8], IpEndpoint)> { let (endpoint, payload_buf) = self.rx_buffer.dequeue()?; - net_trace!("{}:{}:{}: receive {} buffered octets", - self.meta.handle, self.endpoint, - endpoint, payload_buf.len()); + net_trace!( + "{}:{}:{}: receive {} buffered octets", + self.meta.handle, + self.endpoint, + endpoint, + payload_buf.len() + ); Ok((payload_buf, endpoint)) } @@ -263,10 +279,14 @@ impl<'a> UdpSocket<'a> { let handle = self.meta.handle; let endpoint = self.endpoint; self.rx_buffer.peek().map(|(remote_endpoint, payload_buf)| { - net_trace!("{}:{}:{}: peek {} buffered octets", - handle, endpoint, - remote_endpoint, payload_buf.len()); - (payload_buf, remote_endpoint) + net_trace!( + "{}:{}:{}: peek {} buffered octets", + handle, + endpoint, + remote_endpoint, + payload_buf.len() + ); + (payload_buf, remote_endpoint) }) } @@ -284,26 +304,46 @@ impl<'a> UdpSocket<'a> { } pub(crate) fn accepts(&self, ip_repr: &IpRepr, repr: &UdpRepr) -> bool { - if self.endpoint.port != repr.dst_port { return false } - if !self.endpoint.addr.is_unspecified() && - self.endpoint.addr != ip_repr.dst_addr() && - !ip_repr.dst_addr().is_broadcast() && - !ip_repr.dst_addr().is_multicast() { return false } + if self.endpoint.port != repr.dst_port { + return false; + } + if !self.endpoint.addr.is_unspecified() + && self.endpoint.addr != ip_repr.dst_addr() + && !ip_repr.dst_addr().is_broadcast() + && !ip_repr.dst_addr().is_multicast() + { + return false; + } true } - pub(crate) fn process(&mut self, _cx: &Context, ip_repr: &IpRepr, repr: &UdpRepr, payload: &[u8]) -> Result<()> { + pub(crate) fn process( + &mut self, + _cx: &Context, + ip_repr: &IpRepr, + repr: &UdpRepr, + payload: &[u8], + ) -> Result<()> { debug_assert!(self.accepts(ip_repr, repr)); let size = payload.len(); - let endpoint = IpEndpoint { addr: ip_repr.src_addr(), port: repr.src_port }; - self.rx_buffer.enqueue(size, endpoint)?.copy_from_slice(payload); + let endpoint = IpEndpoint { + addr: ip_repr.src_addr(), + port: repr.src_port, + }; + self.rx_buffer + .enqueue(size, endpoint)? + .copy_from_slice(payload); - net_trace!("{}:{}:{}: receiving {} octets", - self.meta.handle, self.endpoint, - endpoint, size); + net_trace!( + "{}:{}:{}: receiving {} octets", + self.meta.handle, + self.endpoint, + endpoint, + size + ); #[cfg(feature = "async")] self.rx_waker.wake(); @@ -312,29 +352,36 @@ impl<'a> UdpSocket<'a> { } pub(crate) fn dispatch(&mut self, _cx: &Context, emit: F) -> Result<()> - where F: FnOnce((IpRepr, UdpRepr, &[u8])) -> Result<()> { - let handle = self.handle(); - let endpoint = self.endpoint; + where + F: FnOnce((IpRepr, UdpRepr, &[u8])) -> Result<()>, + { + let handle = self.handle(); + let endpoint = self.endpoint; let hop_limit = self.hop_limit.unwrap_or(64); - self.tx_buffer.dequeue_with(|remote_endpoint, payload_buf| { - net_trace!("{}:{}:{}: sending {} octets", - handle, endpoint, - endpoint, payload_buf.len()); + self.tx_buffer + .dequeue_with(|remote_endpoint, payload_buf| { + net_trace!( + "{}:{}:{}: sending {} octets", + handle, + endpoint, + endpoint, + payload_buf.len() + ); - let repr = UdpRepr { - src_port: endpoint.port, - dst_port: remote_endpoint.port, - }; - let ip_repr = IpRepr::Unspecified { - src_addr: endpoint.addr, - dst_addr: remote_endpoint.addr, - protocol: IpProtocol::Udp, - payload_len: repr.header_len() + payload_buf.len(), - hop_limit: hop_limit, - }; - emit((ip_repr, repr, payload_buf)) - })?; + let repr = UdpRepr { + src_port: endpoint.port, + dst_port: remote_endpoint.port, + }; + let ip_repr = IpRepr::Unspecified { + src_addr: endpoint.addr, + dst_addr: remote_endpoint.addr, + protocol: IpProtocol::Udp, + payload_len: repr.header_len() + payload_buf.len(), + hop_limit: hop_limit, + }; + emit((ip_repr, repr, payload_buf)) + })?; #[cfg(feature = "async")] self.tx_waker.wake(); @@ -359,29 +406,39 @@ impl<'a> Into> for UdpSocket<'a> { #[cfg(test)] mod test { - use crate::wire::{IpAddress, IpRepr, UdpRepr}; + use super::*; + use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3}; #[cfg(feature = "proto-ipv4")] use crate::wire::Ipv4Repr; #[cfg(feature = "proto-ipv6")] use crate::wire::Ipv6Repr; - use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3}; - use super::*; + use crate::wire::{IpAddress, IpRepr, UdpRepr}; fn buffer(packets: usize) -> UdpSocketBuffer<'static> { - UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY; packets], vec![0; 16 * packets]) + UdpSocketBuffer::new( + vec![UdpPacketMetadata::EMPTY; packets], + vec![0; 16 * packets], + ) } - fn socket(rx_buffer: UdpSocketBuffer<'static>, - tx_buffer: UdpSocketBuffer<'static>) - -> UdpSocket<'static> { + fn socket( + rx_buffer: UdpSocketBuffer<'static>, + tx_buffer: UdpSocketBuffer<'static>, + ) -> UdpSocket<'static> { UdpSocket::new(rx_buffer, tx_buffer) } - const LOCAL_PORT: u16 = 53; - const REMOTE_PORT: u16 = 49500; + const LOCAL_PORT: u16 = 53; + const REMOTE_PORT: u16 = 49500; - pub const LOCAL_END: IpEndpoint = IpEndpoint { addr: MOCK_IP_ADDR_1, port: LOCAL_PORT }; - pub const REMOTE_END: IpEndpoint = IpEndpoint { addr: MOCK_IP_ADDR_2, port: REMOTE_PORT }; + pub const LOCAL_END: IpEndpoint = IpEndpoint { + addr: MOCK_IP_ADDR_1, + port: LOCAL_PORT, + }; + pub const REMOTE_END: IpEndpoint = IpEndpoint { + addr: MOCK_IP_ADDR_2, + port: REMOTE_PORT, + }; pub const LOCAL_IP_REPR: IpRepr = IpRepr::Unspecified { src_addr: MOCK_IP_ADDR_1, @@ -411,7 +468,7 @@ mod test { dst_addr: dst, protocol: IpProtocol::Udp, payload_len: 8 + 6, - hop_limit: 64 + hop_limit: 64, }), #[cfg(feature = "proto-ipv6")] (IpAddress::Ipv6(src), IpAddress::Ipv6(dst)) => IpRepr::Ipv6(Ipv6Repr { @@ -419,9 +476,9 @@ mod test { dst_addr: dst, next_header: IpProtocol::Udp, payload_len: 8 + 6, - hop_limit: 64 + hop_limit: 64, }), - _ => unreachable!() + _ => unreachable!(), } } @@ -448,14 +505,31 @@ mod test { #[test] fn test_send_unaddressable() { let mut socket = socket(buffer(0), buffer(1)); - assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Err(Error::Unaddressable)); + assert_eq!( + socket.send_slice(b"abcdef", REMOTE_END), + Err(Error::Unaddressable) + ); assert_eq!(socket.bind(LOCAL_PORT), Ok(())); - assert_eq!(socket.send_slice(b"abcdef", - IpEndpoint { addr: IpAddress::Unspecified, ..REMOTE_END }), - Err(Error::Unaddressable)); - assert_eq!(socket.send_slice(b"abcdef", - IpEndpoint { port: 0, ..REMOTE_END }), - Err(Error::Unaddressable)); + assert_eq!( + socket.send_slice( + b"abcdef", + IpEndpoint { + addr: IpAddress::Unspecified, + ..REMOTE_END + } + ), + Err(Error::Unaddressable) + ); + assert_eq!( + socket.send_slice( + b"abcdef", + IpEndpoint { + port: 0, + ..REMOTE_END + } + ), + Err(Error::Unaddressable) + ); assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Ok(())); } @@ -465,27 +539,38 @@ mod test { assert_eq!(socket.bind(LOCAL_END), Ok(())); assert!(socket.can_send()); - assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), - Err(Error::Exhausted)); + assert_eq!( + socket.dispatch(&Context::DUMMY, |_| unreachable!()), + Err(Error::Exhausted) + ); assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Ok(())); - assert_eq!(socket.send_slice(b"123456", REMOTE_END), Err(Error::Exhausted)); + assert_eq!( + socket.send_slice(b"123456", REMOTE_END), + Err(Error::Exhausted) + ); assert!(!socket.can_send()); - assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, udp_repr, payload)| { - assert_eq!(ip_repr, LOCAL_IP_REPR); - assert_eq!(udp_repr, LOCAL_UDP_REPR); - assert_eq!(payload, PAYLOAD); + assert_eq!( + socket.dispatch(&Context::DUMMY, |(ip_repr, udp_repr, payload)| { + assert_eq!(ip_repr, LOCAL_IP_REPR); + assert_eq!(udp_repr, LOCAL_UDP_REPR); + assert_eq!(payload, PAYLOAD); + Err(Error::Unaddressable) + }), Err(Error::Unaddressable) - }), Err(Error::Unaddressable)); + ); assert!(!socket.can_send()); - assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, udp_repr, payload)| { - assert_eq!(ip_repr, LOCAL_IP_REPR); - assert_eq!(udp_repr, LOCAL_UDP_REPR); - assert_eq!(payload, PAYLOAD); + assert_eq!( + socket.dispatch(&Context::DUMMY, |(ip_repr, udp_repr, payload)| { + assert_eq!(ip_repr, LOCAL_IP_REPR); + assert_eq!(udp_repr, LOCAL_UDP_REPR); + assert_eq!(payload, PAYLOAD); + Ok(()) + }), Ok(()) - }), Ok(())); + ); assert!(socket.can_send()); } @@ -498,13 +583,27 @@ mod test { assert_eq!(socket.recv(), Err(Error::Exhausted)); assert!(socket.accepts(&remote_ip_repr(), &REMOTE_UDP_REPR)); - assert_eq!(socket.process(&Context::DUMMY, &remote_ip_repr(), &REMOTE_UDP_REPR, PAYLOAD), - Ok(())); + assert_eq!( + socket.process( + &Context::DUMMY, + &remote_ip_repr(), + &REMOTE_UDP_REPR, + PAYLOAD + ), + Ok(()) + ); assert!(socket.can_recv()); assert!(socket.accepts(&remote_ip_repr(), &REMOTE_UDP_REPR)); - assert_eq!(socket.process(&Context::DUMMY, &remote_ip_repr(), &REMOTE_UDP_REPR, PAYLOAD), - Err(Error::Exhausted)); + assert_eq!( + socket.process( + &Context::DUMMY, + &remote_ip_repr(), + &REMOTE_UDP_REPR, + PAYLOAD + ), + Err(Error::Exhausted) + ); assert_eq!(socket.recv(), Ok((&b"abcdef"[..], REMOTE_END))); assert!(!socket.can_recv()); } @@ -516,8 +615,15 @@ mod test { assert_eq!(socket.peek(), Err(Error::Exhausted)); - assert_eq!(socket.process(&Context::DUMMY, &remote_ip_repr(), &REMOTE_UDP_REPR, PAYLOAD), - Ok(())); + assert_eq!( + socket.process( + &Context::DUMMY, + &remote_ip_repr(), + &REMOTE_UDP_REPR, + PAYLOAD + ), + Ok(()) + ); assert_eq!(socket.peek(), Ok((&b"abcdef"[..], &REMOTE_END))); assert_eq!(socket.recv(), Ok((&b"abcdef"[..], REMOTE_END))); assert_eq!(socket.peek(), Err(Error::Exhausted)); @@ -529,8 +635,15 @@ mod test { assert_eq!(socket.bind(LOCAL_PORT), Ok(())); assert!(socket.accepts(&remote_ip_repr(), &REMOTE_UDP_REPR)); - assert_eq!(socket.process(&Context::DUMMY, &remote_ip_repr(), &REMOTE_UDP_REPR, PAYLOAD), - Ok(())); + assert_eq!( + socket.process( + &Context::DUMMY, + &remote_ip_repr(), + &REMOTE_UDP_REPR, + PAYLOAD + ), + Ok(()) + ); let mut slice = [0; 4]; assert_eq!(socket.recv_slice(&mut slice[..]), Ok((4, REMOTE_END))); @@ -542,8 +655,15 @@ mod test { let mut socket = socket(buffer(1), buffer(0)); assert_eq!(socket.bind(LOCAL_PORT), Ok(())); - assert_eq!(socket.process(&Context::DUMMY, &remote_ip_repr(), &REMOTE_UDP_REPR, PAYLOAD), - Ok(())); + assert_eq!( + socket.process( + &Context::DUMMY, + &remote_ip_repr(), + &REMOTE_UDP_REPR, + PAYLOAD + ), + Ok(()) + ); let mut slice = [0; 4]; assert_eq!(socket.peek_slice(&mut slice[..]), Ok((4, &REMOTE_END))); @@ -560,16 +680,22 @@ mod test { s.set_hop_limit(Some(0x2a)); assert_eq!(s.send_slice(b"abcdef", REMOTE_END), Ok(())); - assert_eq!(s.dispatch(&Context::DUMMY, |(ip_repr, _, _)| { - assert_eq!(ip_repr, IpRepr::Unspecified{ - src_addr: MOCK_IP_ADDR_1, - dst_addr: MOCK_IP_ADDR_2, - protocol: IpProtocol::Udp, - payload_len: 8 + 6, - hop_limit: 0x2a, - }); + assert_eq!( + s.dispatch(&Context::DUMMY, |(ip_repr, _, _)| { + assert_eq!( + ip_repr, + IpRepr::Unspecified { + src_addr: MOCK_IP_ADDR_1, + dst_addr: MOCK_IP_ADDR_2, + protocol: IpProtocol::Udp, + payload_len: 8 + 6, + hop_limit: 0x2a, + } + ); + Ok(()) + }), Ok(()) - }), Ok(())); + ); } #[test] @@ -593,7 +719,7 @@ mod test { dst_addr: dst, protocol: IpProtocol::Udp, payload_len: 8 + 6, - hop_limit: 64 + hop_limit: 64, }), #[cfg(feature = "proto-ipv6")] (IpAddress::Ipv6(src), IpAddress::Ipv6(dst)) => IpRepr::Ipv6(Ipv6Repr { @@ -601,9 +727,9 @@ mod test { dst_addr: dst, next_header: IpProtocol::Udp, payload_len: 8 + 6, - hop_limit: 64 + hop_limit: 64, }), - _ => unreachable!() + _ => unreachable!(), } } @@ -623,8 +749,11 @@ mod test { assert_eq!(socket.bind(LOCAL_END), Ok(())); let too_large = b"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefx"; - assert_eq!(socket.send_slice(too_large, REMOTE_END), Err(Error::Truncated)); - assert_eq!(socket.send_slice(&too_large[..16*4], REMOTE_END), Ok(())); + assert_eq!( + socket.send_slice(too_large, REMOTE_END), + Err(Error::Truncated) + ); + assert_eq!(socket.send_slice(&too_large[..16 * 4], REMOTE_END), Ok(())); } #[test] @@ -637,7 +766,10 @@ mod test { src_port: REMOTE_PORT, dst_port: LOCAL_PORT, }; - assert_eq!(socket.process(&Context::DUMMY, &remote_ip_repr(), &repr, &[]), Ok(())); + assert_eq!( + socket.process(&Context::DUMMY, &remote_ip_repr(), &repr, &[]), + Ok(()) + ); assert_eq!(socket.recv(), Ok((&[][..], REMOTE_END))); } diff --git a/src/socket/waker.rs b/src/socket/waker.rs index 4dfb44b..4f42197 100644 --- a/src/socket/waker.rs +++ b/src/socket/waker.rs @@ -30,4 +30,4 @@ impl WakerRegistration { pub fn wake(&mut self) { self.waker.take().map(|w| w.wake()); } -} \ No newline at end of file +} diff --git a/src/storage/assembler.rs b/src/storage/assembler.rs index 1eb97bc..316beed 100644 --- a/src/storage/assembler.rs +++ b/src/storage/assembler.rs @@ -8,29 +8,44 @@ pub struct TooManyHolesError; #[cfg_attr(feature = "defmt", derive(defmt::Format))] struct Contig { hole_size: usize, - data_size: usize + data_size: usize, } impl fmt::Display for Contig { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.has_hole() { write!(f, "({})", self.hole_size)?; } - if self.has_hole() && self.has_data() { write!(f, " ")?; } - if self.has_data() { write!(f, "{}", self.data_size)?; } + if self.has_hole() { + write!(f, "({})", self.hole_size)?; + } + if self.has_hole() && self.has_data() { + write!(f, " ")?; + } + if self.has_data() { + write!(f, "{}", self.data_size)?; + } Ok(()) } } impl Contig { fn empty() -> Contig { - Contig { hole_size: 0, data_size: 0 } + Contig { + hole_size: 0, + data_size: 0, + } } fn hole(size: usize) -> Contig { - Contig { hole_size: size, data_size: 0 } + Contig { + hole_size: size, + data_size: 0, + } } fn hole_and_data(hole_size: usize, data_size: usize) -> Contig { - Contig { hole_size, data_size } + Contig { + hole_size, + data_size, + } } fn has_hole(&self) -> bool { @@ -66,10 +81,10 @@ impl Contig { } } -#[cfg(feature = "std")] -use std::boxed::Box; #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::boxed::Box; +#[cfg(feature = "std")] +use std::boxed::Box; #[cfg(any(feature = "std", feature = "alloc"))] const CONTIG_COUNT: usize = 32; @@ -93,7 +108,9 @@ impl fmt::Display for Assembler { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[ ")?; for contig in self.contigs.iter() { - if contig.is_empty() { break } + if contig.is_empty() { + break; + } write!(f, "{} ", contig)?; } write!(f, "]")?; @@ -115,10 +132,7 @@ impl Assembler { /// FIXME(whitequark): remove this once I'm certain enough that the assembler works well. #[allow(dead_code)] pub(crate) fn total_size(&self) -> usize { - self.contigs - .iter() - .map(|contig| contig.total_size()) - .sum() + self.contigs.iter().map(|contig| contig.total_size()).sum() } fn front(&self) -> Contig { @@ -143,7 +157,7 @@ impl Assembler { self.contigs[i] = self.contigs[i + 1]; if !self.contigs[i].has_data() { self.contigs[i + 1] = Contig::empty(); - return &mut self.contigs[i] + return &mut self.contigs[i]; } } @@ -156,7 +170,9 @@ impl Assembler { fn add_contig_at(&mut self, at: usize) -> Result<&mut Contig, TooManyHolesError> { debug_assert!(!self.contigs[at].is_empty()); - if !self.back().is_empty() { return Err(TooManyHolesError) } + if !self.back().is_empty() { + return Err(TooManyHolesError); + } for i in (at + 1..self.contigs.len()).rev() { self.contigs[i] = self.contigs[i - 1]; @@ -201,11 +217,11 @@ impl Assembler { // The range being added covers a part of the hole but not of the data // in this contig, add a new contig containing the range. { - let inserted = self.add_contig_at(index)?; - *inserted = Contig::hole_and_data(offset, size); + let inserted = self.add_contig_at(index)?; + *inserted = Contig::hole_and_data(offset, size); } // Previous contigs[index] got moved to contigs[index+1] - self.contigs[index+1].shrink_hole_by(offset + size); + self.contigs[index + 1].shrink_hole_by(offset + size); index += 2; } else { unreachable!() @@ -215,7 +231,7 @@ impl Assembler { if offset >= contig.total_size() { offset = offset.saturating_sub(contig.total_size()); } else { - size = (offset + size).saturating_sub(contig.total_size()); + size = (offset + size).saturating_sub(contig.total_size()); offset = 0; } } @@ -258,7 +274,7 @@ pub struct AssemblerIter<'a> { offset: usize, index: usize, left: usize, - right: usize + right: usize, } impl<'a> AssemblerIter<'a> { @@ -268,7 +284,7 @@ impl<'a> AssemblerIter<'a> { offset: offset, index: 0, left: 0, - right: 0 + right: 0, } } } @@ -297,8 +313,8 @@ impl<'a> Iterator for AssemblerIter<'a> { #[cfg(test)] mod test { - use std::vec::Vec; use super::*; + use std::vec::Vec; impl From> for Assembler { fn from(vec: Vec<(usize, usize)>) -> Assembler { @@ -307,7 +323,10 @@ mod test { #[cfg(any(feature = "std", feature = "alloc"))] let mut contigs = Box::new([Contig::empty(); CONTIG_COUNT]); for (i, &(hole_size, data_size)) in vec.iter().enumerate() { - contigs[i] = Contig { hole_size, data_size }; + contigs[i] = Contig { + hole_size, + data_size, + }; } Assembler { contigs } } @@ -412,9 +431,9 @@ mod test { #[test] fn test_rejected_add_keeps_state() { - let mut assr = Assembler::new(CONTIG_COUNT*20); - for c in 1..=CONTIG_COUNT-1 { - assert_eq!(assr.add(c*10, 3), Ok(())); + let mut assr = Assembler::new(CONTIG_COUNT * 20); + for c in 1..=CONTIG_COUNT - 1 { + assert_eq!(assr.add(c * 10, 3), Ok(())); } // Maximum of allowed holes is reached let assr_before = assr.clone(); @@ -440,7 +459,6 @@ mod test { let mut assr = contigs![(0, 4), (4, 4)]; assert_eq!(assr.remove_front(), Some(4)); assert_eq!(assr, contigs![(4, 4), (4, 0)]); - } #[test] diff --git a/src/storage/mod.rs b/src/storage/mod.rs index 8b9fbe6..7e11502 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -6,12 +6,12 @@ or `alloc` crates being available, and heap-allocated memory. */ mod assembler; -mod ring_buffer; mod packet_buffer; +mod ring_buffer; pub use self::assembler::Assembler; -pub use self::ring_buffer::RingBuffer; pub use self::packet_buffer::{PacketBuffer, PacketMetadata}; +pub use self::ring_buffer::RingBuffer; /// A trait for setting a value to a known state. /// diff --git a/src/storage/packet_buffer.rs b/src/storage/packet_buffer.rs index b35d0ab..5bb1681 100644 --- a/src/storage/packet_buffer.rs +++ b/src/storage/packet_buffer.rs @@ -1,31 +1,34 @@ use managed::ManagedSlice; -use crate::{Error, Result}; use crate::storage::RingBuffer; +use crate::{Error, Result}; /// Size and header of a packet. #[derive(Debug, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PacketMetadata { - size: usize, - header: Option + size: usize, + header: Option, } impl PacketMetadata { /// Empty packet description. - pub const EMPTY: PacketMetadata = PacketMetadata { size: 0, header: None }; + pub const EMPTY: PacketMetadata = PacketMetadata { + size: 0, + header: None, + }; fn padding(size: usize) -> PacketMetadata { PacketMetadata { - size: size, - header: None + size: size, + header: None, } } fn packet(size: usize, header: H) -> PacketMetadata { PacketMetadata { - size: size, - header: Some(header) + size: size, + header: Some(header), } } @@ -36,9 +39,9 @@ impl PacketMetadata { /// An UDP packet ring buffer. #[derive(Debug)] -pub struct PacketBuffer<'a, H: 'a> { +pub struct PacketBuffer<'a, H: 'a> { metadata_ring: RingBuffer<'a, PacketMetadata>, - payload_ring: RingBuffer<'a, u8>, + payload_ring: RingBuffer<'a, u8>, } impl<'a, H> PacketBuffer<'a, H> { @@ -47,12 +50,13 @@ impl<'a, H> PacketBuffer<'a, H> { /// Metadata storage limits the maximum _number_ of packets in the buffer and payload /// storage limits the maximum _total size_ of packets. pub fn new(metadata_storage: MS, payload_storage: PS) -> PacketBuffer<'a, H> - where MS: Into>>, - PS: Into>, + where + MS: Into>>, + PS: Into>, { PacketBuffer { metadata_ring: RingBuffer::new(metadata_storage), - payload_ring: RingBuffer::new(payload_storage), + payload_ring: RingBuffer::new(payload_storage), } } @@ -75,25 +79,25 @@ impl<'a, H> PacketBuffer<'a, H> { /// does not have enough spare payload space. pub fn enqueue(&mut self, size: usize, header: H) -> Result<&mut [u8]> { if self.payload_ring.capacity() < size { - return Err(Error::Truncated) + return Err(Error::Truncated); } if self.metadata_ring.is_full() { - return Err(Error::Exhausted) + return Err(Error::Exhausted); } let window = self.payload_ring.window(); let contig_window = self.payload_ring.contiguous_window(); if window < size { - return Err(Error::Exhausted) + return Err(Error::Exhausted); } else if contig_window < size { if window - contig_window < size { // The buffer length is larger than the current contiguous window // and is larger than the contiguous window will be after adding // the padding necessary to circle around to the beginning of the // ring buffer. - return Err(Error::Exhausted) + return Err(Error::Exhausted); } else { // Add padding to the end of the ring buffer so that the // contiguous window is at the beginning of the ring buffer. @@ -110,7 +114,10 @@ impl<'a, H> PacketBuffer<'a, H> { } fn dequeue_padding(&mut self) { - let Self { ref mut metadata_ring, ref mut payload_ring } = *self; + let Self { + ref mut metadata_ring, + ref mut payload_ring, + } = *self; let _ = metadata_ring.dequeue_one_with(|metadata| { if metadata.is_padding() { @@ -125,22 +132,32 @@ impl<'a, H> PacketBuffer<'a, H> { /// Call `f` with a single packet from the buffer, and dequeue the packet if `f` /// returns successfully, or return `Err(Error::Exhausted)` if the buffer is empty. pub fn dequeue_with<'c, R, F>(&'c mut self, f: F) -> Result - where F: FnOnce(&mut H, &'c mut [u8]) -> Result { + where + F: FnOnce(&mut H, &'c mut [u8]) -> Result, + { self.dequeue_padding(); - let Self { ref mut metadata_ring, ref mut payload_ring } = *self; + let Self { + ref mut metadata_ring, + ref mut payload_ring, + } = *self; metadata_ring.dequeue_one_with(move |metadata| { - let PacketMetadata { ref mut header, size } = *metadata; + let PacketMetadata { + ref mut header, + size, + } = *metadata; - payload_ring.dequeue_many_with(|payload_buf| { - debug_assert!(payload_buf.len() >= size); + payload_ring + .dequeue_many_with(|payload_buf| { + debug_assert!(payload_buf.len() >= size); - match f(header.as_mut().unwrap(), &mut payload_buf[..size]) { - Ok(val) => (size, Ok(val)), - Err(err) => (0, Err(err)), - } - }).1 + match f(header.as_mut().unwrap(), &mut payload_buf[..size]) { + Ok(val) => (size, Ok(val)), + Err(err) => (0, Err(err)), + } + }) + .1 }) } @@ -149,7 +166,10 @@ impl<'a, H> PacketBuffer<'a, H> { pub fn dequeue(&mut self) -> Result<(H, &mut [u8])> { self.dequeue_padding(); - let PacketMetadata { ref mut header, size } = *self.metadata_ring.dequeue_one()?; + let PacketMetadata { + ref mut header, + size, + } = *self.metadata_ring.dequeue_one()?; let payload_buf = self.payload_ring.dequeue_many(size); debug_assert!(payload_buf.len() == size); @@ -164,7 +184,10 @@ impl<'a, H> PacketBuffer<'a, H> { self.dequeue_padding(); if let Some(metadata) = self.metadata_ring.get_allocated(0, 1).first() { - Ok((metadata.header.as_ref().unwrap(), self.payload_ring.get_allocated(0, metadata.size))) + Ok(( + metadata.header.as_ref().unwrap(), + self.payload_ring.get_allocated(0, metadata.size), + )) } else { Err(Error::Exhausted) } @@ -193,8 +216,7 @@ mod test { use super::*; fn buffer() -> PacketBuffer<'static, ()> { - PacketBuffer::new(vec![PacketMetadata::EMPTY; 4], - vec![0u8; 16]) + PacketBuffer::new(vec![PacketMetadata::EMPTY; 4], vec![0u8; 16]) } #[test] @@ -237,7 +259,10 @@ mod test { let mut buffer = buffer(); assert!(buffer.enqueue(12, ()).is_ok()); assert!(buffer.dequeue().is_ok()); - buffer.enqueue(12, ()).unwrap().copy_from_slice(b"abcdefghijkl"); + buffer + .enqueue(12, ()) + .unwrap() + .copy_from_slice(b"abcdefghijkl"); } #[test] @@ -250,13 +275,17 @@ mod test { assert_eq!(buffer.metadata_ring.len(), 3); assert!(buffer.dequeue().is_ok()); - assert!(buffer.dequeue_with(|_, _| Err(Error::Unaddressable) as Result<()>).is_err()); + assert!(buffer + .dequeue_with(|_, _| Err(Error::Unaddressable) as Result<()>) + .is_err()); assert_eq!(buffer.metadata_ring.len(), 1); - assert!(buffer.dequeue_with(|&mut (), payload| { - assert_eq!(payload, &b"abcd"[..]); - Ok(()) - }).is_ok()); + assert!(buffer + .dequeue_with(|&mut (), payload| { + assert_eq!(payload, &b"abcd"[..]); + Ok(()) + }) + .is_ok()); assert_eq!(buffer.metadata_ring.len(), 0); } diff --git a/src/storage/ring_buffer.rs b/src/storage/ring_buffer.rs index 063c9f3..e802ad1 100644 --- a/src/storage/ring_buffer.rs +++ b/src/storage/ring_buffer.rs @@ -4,8 +4,8 @@ use core::cmp; use managed::ManagedSlice; -use crate::{Error, Result}; use crate::storage::Resettable; +use crate::{Error, Result}; /// A ring buffer. /// @@ -25,7 +25,7 @@ use crate::storage::Resettable; pub struct RingBuffer<'a, T: 'a> { storage: ManagedSlice<'a, T>, read_at: usize, - length: usize, + length: usize, } impl<'a, T: 'a> RingBuffer<'a, T> { @@ -33,19 +33,20 @@ impl<'a, T: 'a> RingBuffer<'a, T> { /// /// During creation, every element in `storage` is reset. pub fn new(storage: S) -> RingBuffer<'a, T> - where S: Into>, + where + S: Into>, { RingBuffer { storage: storage.into(), read_at: 0, - length: 0, + length: 0, } } /// Clear the ring buffer. pub fn clear(&mut self) { self.read_at = 0; - self.length = 0; + self.length = 0; } /// Return the maximum number of elements in the ring buffer. @@ -55,7 +56,9 @@ impl<'a, T: 'a> RingBuffer<'a, T> { /// Clear the ring buffer, and reset every element. pub fn reset(&mut self) - where T: Resettable { + where + T: Resettable, + { self.clear(); for elem in self.storage.iter_mut() { elem.reset(); @@ -112,8 +115,12 @@ impl<'a, T: 'a> RingBuffer<'a, T> { /// Call `f` with a single buffer element, and enqueue the element if `f` /// returns successfully, or return `Err(Error::Exhausted)` if the buffer is full. pub fn enqueue_one_with<'b, R, F>(&'b mut self, f: F) -> Result - where F: FnOnce(&'b mut T) -> Result { - if self.is_full() { return Err(Error::Exhausted) } + where + F: FnOnce(&'b mut T) -> Result, + { + if self.is_full() { + return Err(Error::Exhausted); + } let index = self.get_idx_unchecked(self.length); match f(&mut self.storage[index]) { @@ -121,7 +128,7 @@ impl<'a, T: 'a> RingBuffer<'a, T> { self.length += 1; Ok(result) } - Err(error) => Err(error) + Err(error) => Err(error), } } @@ -136,8 +143,12 @@ impl<'a, T: 'a> RingBuffer<'a, T> { /// Call `f` with a single buffer element, and dequeue the element if `f` /// returns successfully, or return `Err(Error::Exhausted)` if the buffer is empty. pub fn dequeue_one_with<'b, R, F>(&'b mut self, f: F) -> Result - where F: FnOnce(&'b mut T) -> Result { - if self.is_empty() { return Err(Error::Exhausted) } + where + F: FnOnce(&'b mut T) -> Result, + { + if self.is_empty() { + return Err(Error::Exhausted); + } let next_at = self.get_idx_unchecked(1); match f(&mut self.storage[self.read_at]) { @@ -146,7 +157,7 @@ impl<'a, T: 'a> RingBuffer<'a, T> { self.read_at = next_at; Ok(result) } - Err(error) => Err(error) + Err(error) => Err(error), } } @@ -169,7 +180,9 @@ impl<'a, T: 'a> RingBuffer<'a, T> { /// This function panics if the amount of elements returned by `f` is larger /// than the size of the slice passed into it. pub fn enqueue_many_with<'b, R, F>(&'b mut self, f: F) -> (usize, R) - where F: FnOnce(&'b mut [T]) -> (usize, R) { + where + F: FnOnce(&'b mut [T]) -> (usize, R), + { if self.length == 0 { // Ring is currently empty. Reset `read_at` to optimize // for contiguous space. @@ -194,14 +207,17 @@ impl<'a, T: 'a> RingBuffer<'a, T> { self.enqueue_many_with(|buf| { let size = cmp::min(size, buf.len()); (size, &mut buf[..size]) - }).1 + }) + .1 } /// Enqueue as many elements from the given slice into the buffer as possible, /// and return the amount of elements that could fit. // #[must_use] pub fn enqueue_slice(&mut self, data: &[T]) -> usize - where T: Copy { + where + T: Copy, + { let (size_1, data) = self.enqueue_many_with(|buf| { let size = cmp::min(buf.len(), data.len()); buf[..size].copy_from_slice(&data[..size]); @@ -222,7 +238,9 @@ impl<'a, T: 'a> RingBuffer<'a, T> { /// This function panics if the amount of elements returned by `f` is larger /// than the size of the slice passed into it. pub fn dequeue_many_with<'b, R, F>(&'b mut self, f: F) -> (usize, R) - where F: FnOnce(&'b mut [T]) -> (usize, R) { + where + F: FnOnce(&'b mut [T]) -> (usize, R), + { let capacity = self.capacity(); let max_size = cmp::min(self.len(), capacity - self.read_at); let (size, result) = f(&mut self.storage[self.read_at..self.read_at + max_size]); @@ -246,14 +264,17 @@ impl<'a, T: 'a> RingBuffer<'a, T> { self.dequeue_many_with(|buf| { let size = cmp::min(size, buf.len()); (size, &mut buf[..size]) - }).1 + }) + .1 } /// Dequeue as many elements from the buffer into the given slice as possible, /// and return the amount of elements that could fit. // #[must_use] pub fn dequeue_slice(&mut self, data: &mut [T]) -> usize - where T: Copy { + where + T: Copy, + { let (size_1, data) = self.dequeue_many_with(|buf| { let size = cmp::min(buf.len(), data.len()); data[..size].copy_from_slice(&buf[..size]); @@ -277,13 +298,19 @@ impl<'a, T: 'a> RingBuffer<'a, T> { pub fn get_unallocated(&mut self, offset: usize, mut size: usize) -> &mut [T] { let start_at = self.get_idx(self.length + offset); // We can't access past the end of unallocated data. - if offset > self.window() { return &mut [] } + if offset > self.window() { + return &mut []; + } // We can't enqueue more than there is free space. let clamped_window = self.window() - offset; - if size > clamped_window { size = clamped_window } + if size > clamped_window { + size = clamped_window + } // We can't contiguously enqueue past the end of the storage. let until_end = self.capacity() - start_at; - if size > until_end { size = until_end } + if size > until_end { + size = until_end + } &mut self.storage[start_at..start_at + size] } @@ -293,7 +320,9 @@ impl<'a, T: 'a> RingBuffer<'a, T> { /// the amount written. // #[must_use] pub fn write_unallocated(&mut self, offset: usize, data: &[T]) -> usize - where T: Copy { + where + T: Copy, + { let (size_1, offset, data) = { let slice = self.get_unallocated(offset, data.len()); let slice_len = slice.len(); @@ -324,13 +353,19 @@ impl<'a, T: 'a> RingBuffer<'a, T> { pub fn get_allocated(&self, offset: usize, mut size: usize) -> &[T] { let start_at = self.get_idx(offset); // We can't read past the end of the allocated data. - if offset > self.length { return &mut [] } + if offset > self.length { + return &mut []; + } // We can't read more than we have allocated. let clamped_length = self.length - offset; - if size > clamped_length { size = clamped_length } + if size > clamped_length { + size = clamped_length + } // We can't contiguously dequeue past the end of the storage. let until_end = self.capacity() - start_at; - if size > until_end { size = until_end } + if size > until_end { + size = until_end + } &self.storage[start_at..start_at + size] } @@ -340,7 +375,9 @@ impl<'a, T: 'a> RingBuffer<'a, T> { /// the amount read. // #[must_use] pub fn read_allocated(&mut self, offset: usize, data: &mut [T]) -> usize - where T: Copy { + where + T: Copy, + { let (size_1, offset, data) = { let slice = self.get_allocated(offset, data.len()); data[..slice.len()].copy_from_slice(slice); @@ -402,8 +439,10 @@ mod test { #[test] fn test_buffer_enqueue_dequeue_one_with() { let mut ring = RingBuffer::new(vec![0; 5]); - assert_eq!(ring.dequeue_one_with(|_| unreachable!()) as Result<()>, - Err(Error::Exhausted)); + assert_eq!( + ring.dequeue_one_with(|_| unreachable!()) as Result<()>, + Err(Error::Exhausted) + ); ring.enqueue_one_with(Ok).unwrap(); assert!(!ring.is_empty()); @@ -414,15 +453,19 @@ mod test { assert!(!ring.is_empty()); } assert!(ring.is_full()); - assert_eq!(ring.enqueue_one_with(|_| unreachable!()) as Result<()>, - Err(Error::Exhausted)); + assert_eq!( + ring.enqueue_one_with(|_| unreachable!()) as Result<()>, + Err(Error::Exhausted) + ); for i in 0..5 { assert_eq!(ring.dequeue_one_with(|e| Ok(*e)).unwrap(), i); assert!(!ring.is_full()); } - assert_eq!(ring.dequeue_one_with(|_| unreachable!()) as Result<()>, - Err(Error::Exhausted)); + assert_eq!( + ring.dequeue_one_with(|_| unreachable!()) as Result<()>, + Err(Error::Exhausted) + ); assert!(ring.is_empty()); } @@ -454,11 +497,14 @@ mod test { fn test_buffer_enqueue_many_with() { let mut ring = RingBuffer::new(vec![b'.'; 12]); - assert_eq!(ring.enqueue_many_with(|buf| { - assert_eq!(buf.len(), 12); - buf[0..2].copy_from_slice(b"ab"); + assert_eq!( + ring.enqueue_many_with(|buf| { + assert_eq!(buf.len(), 12); + buf[0..2].copy_from_slice(b"ab"); + (2, true) + }), (2, true) - }), (2, true)); + ); assert_eq!(ring.len(), 2); assert_eq!(&ring.storage[..], b"ab.........."); @@ -545,12 +591,15 @@ mod test { assert_eq!(ring.enqueue_slice(b"abcdefghijkl"), 12); - assert_eq!(ring.dequeue_many_with(|buf| { - assert_eq!(buf.len(), 12); - assert_eq!(buf, b"abcdefghijkl"); - buf[..4].copy_from_slice(b"...."); + assert_eq!( + ring.dequeue_many_with(|buf| { + assert_eq!(buf.len(), 12); + assert_eq!(buf, b"abcdefghijkl"); + buf[..4].copy_from_slice(b"...."); + (4, true) + }), (4, true) - }), (4, true)); + ); assert_eq!(ring.len(), 8); assert_eq!(&ring.storage[..], b"....efghijkl"); @@ -679,7 +728,7 @@ mod test { let mut ring = RingBuffer::new(vec![b'.'; 12]); assert_eq!(ring.get_allocated(16, 4), b""); - assert_eq!(ring.get_allocated(0, 4), b""); + assert_eq!(ring.get_allocated(0, 4), b""); ring.enqueue_slice(b"abcd"); assert_eq!(ring.get_allocated(0, 8), b"abcd"); @@ -711,7 +760,6 @@ mod test { let mut data = [0; 6]; assert_eq!(ring.read_allocated(6, &mut data[..]), 3); assert_eq!(&data[..], b"mno\x00\x00\x00"); - } #[test] diff --git a/src/time.rs b/src/time.rs index 724f804..ebf13d3 100644 --- a/src/time.rs +++ b/src/time.rs @@ -10,7 +10,7 @@ absolute and relative time. [Duration]: struct.Duration.html */ -use core::{ops, fmt}; +use core::{fmt, ops}; /// A representation of an absolute time value. /// @@ -30,12 +30,16 @@ pub struct Instant { impl Instant { /// Create a new `Instant` from a number of milliseconds. pub fn from_millis>(millis: T) -> Instant { - Instant { millis: millis.into() } + Instant { + millis: millis.into(), + } } /// Create a new `Instant` from a number of seconds. pub fn from_secs>(secs: T) -> Instant { - Instant { millis: secs.into() * 1000 } + Instant { + millis: secs.into() * 1000, + } } /// Create a new `Instant` from the current [std::time::SystemTime]. @@ -79,7 +83,8 @@ impl From<::std::time::Instant> for Instant { #[cfg(feature = "std")] impl From<::std::time::SystemTime> for Instant { fn from(other: ::std::time::SystemTime) -> Instant { - let n = other.duration_since(::std::time::UNIX_EPOCH) + let n = other + .duration_since(::std::time::UNIX_EPOCH) .expect("start time must not be before the unix epoch"); Self::from_millis(n.as_secs() as i64 * 1000 + n.subsec_millis() as i64) } @@ -149,7 +154,9 @@ impl Duration { /// Create a new `Instant` from a number of seconds. pub const fn from_secs(secs: u64) -> Duration { - Duration { millis: secs * 1000 } + Duration { + millis: secs * 1000, + } } /// The fractional number of milliseconds in this `Duration`. @@ -193,14 +200,19 @@ impl ops::Sub for Duration { fn sub(self, rhs: Duration) -> Duration { Duration::from_millis( - self.millis.checked_sub(rhs.total_millis()).expect("overflow when subtracting durations")) + self.millis + .checked_sub(rhs.total_millis()) + .expect("overflow when subtracting durations"), + ) } } impl ops::SubAssign for Duration { fn sub_assign(&mut self, rhs: Duration) { - self.millis = self.millis.checked_sub( - rhs.total_millis()).expect("overflow when subtracting durations"); + self.millis = self + .millis + .checked_sub(rhs.total_millis()) + .expect("overflow when subtracting durations"); } } @@ -234,7 +246,7 @@ impl ops::DivAssign for Duration { impl ops::Shl for Duration { type Output = Duration; - + fn shl(self, rhs: u32) -> Duration { Duration::from_millis(self.millis << rhs) } @@ -248,7 +260,7 @@ impl ops::ShlAssign for Duration { impl ops::Shr for Duration { type Output = Duration; - + fn shr(self, rhs: u32) -> Duration { Duration::from_millis(self.millis >> rhs) } @@ -262,17 +274,13 @@ impl ops::ShrAssign for Duration { impl From<::core::time::Duration> for Duration { fn from(other: ::core::time::Duration) -> Duration { - Duration::from_millis( - other.as_secs() * 1000 + other.subsec_millis() as u64 - ) + Duration::from_millis(other.as_secs() * 1000 + other.subsec_millis() as u64) } } impl Into<::core::time::Duration> for Duration { fn into(self) -> ::core::time::Duration { - ::core::time::Duration::from_millis( - self.total_millis() - ) + ::core::time::Duration::from_millis(self.total_millis()) } } @@ -283,9 +291,15 @@ mod test { #[test] fn test_instant_ops() { // std::ops::Add - assert_eq!(Instant::from_millis(4) + Duration::from_millis(6), Instant::from_millis(10)); + assert_eq!( + Instant::from_millis(4) + Duration::from_millis(6), + Instant::from_millis(10) + ); // std::ops::Sub - assert_eq!(Instant::from_millis(7) - Duration::from_millis(5), Instant::from_millis(2)); + assert_eq!( + Instant::from_millis(7) - Duration::from_millis(5), + Instant::from_millis(2) + ); } #[test] @@ -306,19 +320,30 @@ mod test { #[cfg(feature = "std")] fn test_instant_conversions() { let mut epoc: ::std::time::SystemTime = Instant::from_millis(0).into(); - assert_eq!(Instant::from(::std::time::UNIX_EPOCH), - Instant::from_millis(0)); + assert_eq!( + Instant::from(::std::time::UNIX_EPOCH), + Instant::from_millis(0) + ); assert_eq!(epoc, ::std::time::UNIX_EPOCH); epoc = Instant::from_millis(2085955200i64 * 1000).into(); - assert_eq!(epoc, ::std::time::UNIX_EPOCH + ::std::time::Duration::from_secs(2085955200)); + assert_eq!( + epoc, + ::std::time::UNIX_EPOCH + ::std::time::Duration::from_secs(2085955200) + ); } #[test] fn test_duration_ops() { // std::ops::Add - assert_eq!(Duration::from_millis(40) + Duration::from_millis(2), Duration::from_millis(42)); + assert_eq!( + Duration::from_millis(40) + Duration::from_millis(2), + Duration::from_millis(42) + ); // std::ops::Sub - assert_eq!(Duration::from_millis(555) - Duration::from_millis(42), Duration::from_millis(513)); + assert_eq!( + Duration::from_millis(555) - Duration::from_millis(42), + Duration::from_millis(513) + ); // std::ops::Mul assert_eq!(Duration::from_millis(13) * 22, Duration::from_millis(286)); // std::ops::Div diff --git a/src/wire/arp.rs b/src/wire/arp.rs index 3bf3947..48d64ca 100644 --- a/src/wire/arp.rs +++ b/src/wire/arp.rs @@ -1,5 +1,5 @@ -use core::fmt; use byteorder::{ByteOrder, NetworkEndian}; +use core::fmt; use crate::{Error, Result}; @@ -24,7 +24,7 @@ enum_with_unknown! { #[derive(Debug, PartialEq, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { - buffer: T + buffer: T, } mod field { @@ -34,9 +34,9 @@ mod field { pub const HTYPE: Field = 0..2; pub const PTYPE: Field = 2..4; - pub const HLEN: usize = 4; - pub const PLEN: usize = 5; - pub const OPER: Field = 6..8; + pub const HLEN: usize = 4; + pub const PLEN: usize = 5; + pub const OPER: Field = 6..8; #[inline] pub fn SHA(hardware_len: u8, _protocol_len: u8) -> Field { @@ -263,7 +263,7 @@ pub enum Repr { source_hardware_addr: EthernetAddress, source_protocol_addr: Ipv4Address, target_hardware_addr: EthernetAddress, - target_protocol_addr: Ipv4Address + target_protocol_addr: Ipv4Address, }, } @@ -271,22 +271,20 @@ impl Repr { /// Parse an Address Resolution Protocol packet and return a high-level representation, /// or return `Err(Error::Unrecognized)` if the packet is not recognized. pub fn parse>(packet: &Packet) -> Result { - match (packet.hardware_type(), packet.protocol_type(), - packet.hardware_len(), packet.protocol_len()) { - (Hardware::Ethernet, Protocol::Ipv4, 6, 4) => { - Ok(Repr::EthernetIpv4 { - operation: packet.operation(), - source_hardware_addr: - EthernetAddress::from_bytes(packet.source_hardware_addr()), - source_protocol_addr: - Ipv4Address::from_bytes(packet.source_protocol_addr()), - target_hardware_addr: - EthernetAddress::from_bytes(packet.target_hardware_addr()), - target_protocol_addr: - Ipv4Address::from_bytes(packet.target_protocol_addr()) - }) - }, - _ => Err(Error::Unrecognized) + match ( + packet.hardware_type(), + packet.protocol_type(), + packet.hardware_len(), + packet.protocol_len(), + ) { + (Hardware::Ethernet, Protocol::Ipv4, 6, 4) => Ok(Repr::EthernetIpv4 { + operation: packet.operation(), + source_hardware_addr: EthernetAddress::from_bytes(packet.source_hardware_addr()), + source_protocol_addr: Ipv4Address::from_bytes(packet.source_protocol_addr()), + target_hardware_addr: EthernetAddress::from_bytes(packet.target_hardware_addr()), + target_protocol_addr: Ipv4Address::from_bytes(packet.target_protocol_addr()), + }), + _ => Err(Error::Unrecognized), } } @@ -302,8 +300,10 @@ impl Repr { match *self { Repr::EthernetIpv4 { operation, - source_hardware_addr, source_protocol_addr, - target_hardware_addr, target_protocol_addr + source_hardware_addr, + source_protocol_addr, + target_hardware_addr, + target_protocol_addr, } => { packet.set_hardware_type(Hardware::Ethernet); packet.set_protocol_type(Protocol::Ipv4); @@ -314,7 +314,7 @@ impl Repr { packet.set_source_protocol_addr(source_protocol_addr.as_bytes()); packet.set_target_hardware_addr(target_hardware_addr.as_bytes()); packet.set_target_protocol_addr(target_protocol_addr.as_bytes()); - }, + } } } } @@ -325,13 +325,23 @@ impl> fmt::Display for Packet { Ok(repr) => write!(f, "{}", repr), _ => { write!(f, "ARP (unrecognized)")?; - write!(f, " htype={:?} ptype={:?} hlen={:?} plen={:?} op={:?}", - self.hardware_type(), self.protocol_type(), - self.hardware_len(), self.protocol_len(), - self.operation())?; - write!(f, " sha={:?} spa={:?} tha={:?} tpa={:?}", - self.source_hardware_addr(), self.source_protocol_addr(), - self.target_hardware_addr(), self.target_protocol_addr())?; + write!( + f, + " htype={:?} ptype={:?} hlen={:?} plen={:?} op={:?}", + self.hardware_type(), + self.protocol_type(), + self.hardware_len(), + self.protocol_len(), + self.operation() + )?; + write!( + f, + " sha={:?} spa={:?} tha={:?} tpa={:?}", + self.source_hardware_addr(), + self.source_protocol_addr(), + self.target_hardware_addr(), + self.target_protocol_addr() + )?; Ok(()) } } @@ -343,26 +353,36 @@ impl fmt::Display for Repr { match *self { Repr::EthernetIpv4 { operation, - source_hardware_addr, source_protocol_addr, - target_hardware_addr, target_protocol_addr + source_hardware_addr, + source_protocol_addr, + target_hardware_addr, + target_protocol_addr, } => { - write!(f, "ARP type=Ethernet+IPv4 src={}/{} tgt={}/{} op={:?}", - source_hardware_addr, source_protocol_addr, - target_hardware_addr, target_protocol_addr, - operation) - }, + write!( + f, + "ARP type=Ethernet+IPv4 src={}/{} tgt={}/{} op={:?}", + source_hardware_addr, + source_protocol_addr, + target_hardware_addr, + target_protocol_addr, + operation + ) + } } } } -use crate::wire::pretty_print::{PrettyPrint, PrettyIndent}; +use crate::wire::pretty_print::{PrettyIndent, PrettyPrint}; impl> PrettyPrint for Packet { - fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter, - indent: &mut PrettyIndent) -> fmt::Result { + fn pretty_print( + buffer: &dyn AsRef<[u8]>, + f: &mut fmt::Formatter, + indent: &mut PrettyIndent, + ) -> fmt::Result { match Packet::new_checked(buffer) { Err(err) => write!(f, "{}({})", indent, err), - Ok(packet) => write!(f, "{}{}", indent, packet) + Ok(packet) => write!(f, "{}{}", indent, packet), } } } @@ -371,16 +391,10 @@ impl> PrettyPrint for Packet { mod test { use super::*; - static PACKET_BYTES: [u8; 28] = - [0x00, 0x01, - 0x08, 0x00, - 0x06, - 0x04, - 0x00, 0x01, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x21, 0x22, 0x23, 0x24, - 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x41, 0x42, 0x43, 0x44]; + static PACKET_BYTES: [u8; 28] = [ + 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x21, + 0x22, 0x23, 0x24, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x41, 0x42, 0x43, 0x44, + ]; #[test] fn test_deconstruct() { @@ -390,9 +404,15 @@ mod test { assert_eq!(packet.hardware_len(), 6); assert_eq!(packet.protocol_len(), 4); assert_eq!(packet.operation(), Operation::Request); - assert_eq!(packet.source_hardware_addr(), &[0x11, 0x12, 0x13, 0x14, 0x15, 0x16]); + assert_eq!( + packet.source_hardware_addr(), + &[0x11, 0x12, 0x13, 0x14, 0x15, 0x16] + ); assert_eq!(packet.source_protocol_addr(), &[0x21, 0x22, 0x23, 0x24]); - assert_eq!(packet.target_hardware_addr(), &[0x31, 0x32, 0x33, 0x34, 0x35, 0x36]); + assert_eq!( + packet.target_hardware_addr(), + &[0x31, 0x32, 0x33, 0x34, 0x35, 0x36] + ); assert_eq!(packet.target_protocol_addr(), &[0x41, 0x42, 0x43, 0x44]); } @@ -415,14 +435,14 @@ mod test { fn packet_repr() -> Repr { Repr::EthernetIpv4 { operation: Operation::Request, - source_hardware_addr: - EthernetAddress::from_bytes(&[0x11, 0x12, 0x13, 0x14, 0x15, 0x16]), - source_protocol_addr: - Ipv4Address::from_bytes(&[0x21, 0x22, 0x23, 0x24]), - target_hardware_addr: - EthernetAddress::from_bytes(&[0x31, 0x32, 0x33, 0x34, 0x35, 0x36]), - target_protocol_addr: - Ipv4Address::from_bytes(&[0x41, 0x42, 0x43, 0x44]) + source_hardware_addr: EthernetAddress::from_bytes(&[ + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + ]), + source_protocol_addr: Ipv4Address::from_bytes(&[0x21, 0x22, 0x23, 0x24]), + target_hardware_addr: EthernetAddress::from_bytes(&[ + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + ]), + target_protocol_addr: Ipv4Address::from_bytes(&[0x41, 0x42, 0x43, 0x44]), } } diff --git a/src/wire/dhcpv4.rs b/src/wire/dhcpv4.rs index 8cb1c11..cbb5f1e 100644 --- a/src/wire/dhcpv4.rs +++ b/src/wire/dhcpv4.rs @@ -2,9 +2,9 @@ use byteorder::{ByteOrder, NetworkEndian}; -use crate::{Error, Result}; -use crate::wire::{EthernetAddress, Ipv4Address}; use crate::wire::arp::Hardware; +use crate::wire::{EthernetAddress, Ipv4Address}; +use crate::{Error, Result}; pub const SERVER_PORT: u16 = 67; pub const CLIENT_PORT: u16 = 68; @@ -37,8 +37,11 @@ enum_with_unknown! { impl MessageType { fn opcode(&self) -> OpCode { match *self { - MessageType::Discover | MessageType::Inform | MessageType::Request | - MessageType::Decline | MessageType::Release => OpCode::Request, + MessageType::Discover + | MessageType::Inform + | MessageType::Request + | MessageType::Decline + | MessageType::Release => OpCode::Request, MessageType::Offer | MessageType::Ack | MessageType::Nak => OpCode::Reply, MessageType::Unknown(_) => OpCode::Unknown(0), } @@ -59,7 +62,7 @@ pub enum DhcpOption<'a> { Router(Ipv4Address), SubnetMask(Ipv4Address), MaximumDhcpMessageSize(u16), - Other { kind: u8, data: &'a [u8] } + Other { kind: u8, data: &'a [u8] }, } impl<'a> DhcpOption<'a> { @@ -81,12 +84,10 @@ impl<'a> DhcpOption<'a> { skip_len = length + 2; let data = buffer.get(2..skip_len).ok_or(Error::Truncated)?; match (kind, length) { - (field::OPT_END, _) | - (field::OPT_PAD, _) => - unreachable!(), + (field::OPT_END, _) | (field::OPT_PAD, _) => unreachable!(), (field::OPT_DHCP_MESSAGE_TYPE, 1) => { option = DhcpOption::MessageType(MessageType::from(data[0])); - }, + } (field::OPT_REQUESTED_IP, 4) => { option = DhcpOption::RequestedIp(Ipv4Address::from_bytes(data)); } @@ -95,7 +96,8 @@ impl<'a> DhcpOption<'a> { if hardware_type != Hardware::Ethernet { return Err(Error::Unrecognized); } - option = DhcpOption::ClientIdentifier(EthernetAddress::from_bytes(&data[1..])); + option = + DhcpOption::ClientIdentifier(EthernetAddress::from_bytes(&data[1..])); } (field::OPT_SERVER_IDENTIFIER, 4) => { option = DhcpOption::ServerIdentifier(Ipv4Address::from_bytes(data)); @@ -107,13 +109,20 @@ impl<'a> DhcpOption<'a> { option = DhcpOption::SubnetMask(Ipv4Address::from_bytes(data)); } (field::OPT_MAX_DHCP_MESSAGE_SIZE, 2) => { - option = DhcpOption::MaximumDhcpMessageSize(u16::from_be_bytes([data[0], data[1]])); + option = DhcpOption::MaximumDhcpMessageSize(u16::from_be_bytes([ + data[0], data[1], + ])); } (field::OPT_IP_LEASE_TIME, 4) => { - option = DhcpOption::IpLeaseTime(u32::from_be_bytes([data[0], data[1], data[2], data[3]])) + option = DhcpOption::IpLeaseTime(u32::from_be_bytes([ + data[0], data[1], data[2], data[3], + ])) } (_, _) => { - option = DhcpOption::Other { kind: kind, data: data }; + option = DhcpOption::Other { + kind: kind, + data: data, + }; } } } @@ -126,20 +135,14 @@ impl<'a> DhcpOption<'a> { &DhcpOption::EndOfList => 1, &DhcpOption::Pad => 1, &DhcpOption::MessageType(_) => 3, - &DhcpOption::ClientIdentifier(eth_addr) => { - 3 + eth_addr.as_bytes().len() - } - &DhcpOption::RequestedIp(ip) | - &DhcpOption::ServerIdentifier(ip) | - &DhcpOption::Router(ip) | - &DhcpOption::SubnetMask(ip) => { - 2 + ip.as_bytes().len() - }, - &DhcpOption::MaximumDhcpMessageSize(_) => { - 4 - } + &DhcpOption::ClientIdentifier(eth_addr) => 3 + eth_addr.as_bytes().len(), + &DhcpOption::RequestedIp(ip) + | &DhcpOption::ServerIdentifier(ip) + | &DhcpOption::Router(ip) + | &DhcpOption::SubnetMask(ip) => 2 + ip.as_bytes().len(), + &DhcpOption::MaximumDhcpMessageSize(_) => 4, &DhcpOption::IpLeaseTime(_) => 6, - &DhcpOption::Other { data, .. } => 2 + data.len() + &DhcpOption::Other { data, .. } => 2 + data.len(), } } @@ -168,19 +171,19 @@ impl<'a> DhcpOption<'a> { buffer[2] = u16::from(Hardware::Ethernet) as u8; buffer[3..9].copy_from_slice(eth_addr.as_bytes()); } - DhcpOption::RequestedIp(ip) => { + DhcpOption::RequestedIp(ip) => { buffer[0] = field::OPT_REQUESTED_IP; buffer[2..6].copy_from_slice(ip.as_bytes()); } - DhcpOption::ServerIdentifier(ip) => { + DhcpOption::ServerIdentifier(ip) => { buffer[0] = field::OPT_SERVER_IDENTIFIER; buffer[2..6].copy_from_slice(ip.as_bytes()); } - DhcpOption::Router(ip) => { + DhcpOption::Router(ip) => { buffer[0] = field::OPT_ROUTER; buffer[2..6].copy_from_slice(ip.as_bytes()); } - DhcpOption::SubnetMask(mask) => { + DhcpOption::SubnetMask(mask) => { buffer[0] = field::OPT_SUBNET_MASK; buffer[2..6].copy_from_slice(mask.as_bytes()); } @@ -192,7 +195,10 @@ impl<'a> DhcpOption<'a> { buffer[0] = field::OPT_IP_LEASE_TIME; buffer[2..6].copy_from_slice(&lease_time.to_be_bytes()[..]); } - DhcpOption::Other { kind, data: provided } => { + DhcpOption::Other { + kind, + data: provided, + } => { buffer[0] = kind; buffer[2..skip_length].copy_from_slice(provided); } @@ -207,7 +213,7 @@ impl<'a> DhcpOption<'a> { #[derive(Debug, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { - buffer: T + buffer: T, } pub(crate) mod field { @@ -691,7 +697,7 @@ pub struct Repr<'a> { /// The maximum size dhcp packet the interface can receive pub max_size: Option, /// The DHCP IP lease duration, specified in seconds. - pub lease_duration: Option + pub lease_duration: Option, } impl<'a> Repr<'a> { @@ -700,22 +706,39 @@ impl<'a> Repr<'a> { let mut len = field::OPTIONS.start; // message type and end-of-options options len += 3 + 1; - if self.requested_ip.is_some() { len += 6; } - if self.client_identifier.is_some() { len += 9; } - if self.server_identifier.is_some() { len += 6; } - if self.max_size.is_some() { len += 4; } - if self.router.is_some() { len += 6; } - if self.subnet_mask.is_some() { len += 6; } - if self.lease_duration.is_some() { len += 6; } - if let Some(list) = self.parameter_request_list { len += list.len() + 2; } + if self.requested_ip.is_some() { + len += 6; + } + if self.client_identifier.is_some() { + len += 9; + } + if self.server_identifier.is_some() { + len += 6; + } + if self.max_size.is_some() { + len += 4; + } + if self.router.is_some() { + len += 6; + } + if self.subnet_mask.is_some() { + len += 6; + } + if self.lease_duration.is_some() { + len += 6; + } + if let Some(list) = self.parameter_request_list { + len += list.len() + 2; + } len } /// Parse a DHCP packet and return a high-level representation. pub fn parse(packet: &Packet<&'a T>) -> Result - where T: AsRef<[u8]> + ?Sized { - + where + T: AsRef<[u8]> + ?Sized, + { let transaction_id = packet.transaction_id(); let client_hardware_address = packet.client_hardware_address(); let client_ip = packet.client_ip(); @@ -753,12 +776,12 @@ impl<'a> Repr<'a> { let (next_options, option) = DhcpOption::parse(options)?; match option { DhcpOption::EndOfList => break, - DhcpOption::Pad => {}, + DhcpOption::Pad => {} DhcpOption::MessageType(value) => { if value.opcode() == packet.opcode() { message_type = Ok(value); } - }, + } DhcpOption::RequestedIp(ip) => { requested_ip = Some(ip); } @@ -773,24 +796,30 @@ impl<'a> Repr<'a> { } DhcpOption::SubnetMask(mask) => { subnet_mask = Some(mask); - }, + } DhcpOption::MaximumDhcpMessageSize(size) => { max_size = Some(size); } DhcpOption::IpLeaseTime(duration) => { lease_duration = Some(duration); } - DhcpOption::Other {kind: field::OPT_PARAMETER_REQUEST_LIST, data} => { + DhcpOption::Other { + kind: field::OPT_PARAMETER_REQUEST_LIST, + data, + } => { parameter_request_list = Some(data); } - DhcpOption::Other {kind: field::OPT_DOMAIN_NAME_SERVER, data} => { + DhcpOption::Other { + kind: field::OPT_DOMAIN_NAME_SERVER, + data, + } => { let mut servers = [None; MAX_DNS_SERVER_COUNT]; for (server, chunk) in servers.iter_mut().zip(data.chunks(4)) { *server = Some(Ipv4Address::from_bytes(chunk)); } dns_servers = Some(servers); } - DhcpOption::Other {..} => {} + DhcpOption::Other { .. } => {} } options = next_options; } @@ -798,9 +827,21 @@ impl<'a> Repr<'a> { let broadcast = packet.broadcast_flag(); Ok(Repr { - transaction_id, client_hardware_address, client_ip, your_ip, server_ip, relay_agent_ip, - broadcast, requested_ip, server_identifier, router, - subnet_mask, client_identifier, parameter_request_list, dns_servers, max_size, + transaction_id, + client_hardware_address, + client_ip, + your_ip, + server_ip, + relay_agent_ip, + broadcast, + requested_ip, + server_identifier, + router, + subnet_mask, + client_identifier, + parameter_request_list, + dns_servers, + max_size, lease_duration, message_type: message_type?, }) @@ -809,7 +850,9 @@ impl<'a> Repr<'a> { /// Emit a high-level representation into a Dynamic Host /// Configuration Protocol packet. pub fn emit(&self, packet: &mut Packet<&mut T>) -> Result<()> - where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized { + where + T: AsRef<[u8]> + AsMut<[u8]> + ?Sized, + { packet.set_sname_and_boot_file_to_zero(); packet.set_opcode(self.message_type.opcode()); packet.set_hardware_type(Hardware::Ethernet); @@ -850,7 +893,11 @@ impl<'a> Repr<'a> { options = DhcpOption::IpLeaseTime(duration).emit(options); } if let Some(list) = self.parameter_request_list { - options = DhcpOption::Other{ kind: field::OPT_PARAMETER_REQUEST_LIST, data: list }.emit(options); + options = DhcpOption::Other { + kind: field::OPT_PARAMETER_REQUEST_LIST, + data: list, + } + .emit(options); } DhcpOption::EndOfList.emit(options); } @@ -861,75 +908,80 @@ impl<'a> Repr<'a> { #[cfg(test)] mod test { - use crate::wire::Ipv4Address; use super::*; + use crate::wire::Ipv4Address; const MAGIC_COOKIE: u32 = 0x63825363; static DISCOVER_BYTES: &[u8] = &[ - 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x3d, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x82, 0x01, - 0xfc, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, - 0x35, 0x01, 0x01, 0x3d, 0x07, 0x01, 0x00, 0x0b, 0x82, 0x01, 0xfc, 0x42, 0x32, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x39, 0x2, 0x5, 0xdc, 0x37, 0x04, 0x01, 0x03, 0x06, 0x2a, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x3d, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, + 0x82, 0x01, 0xfc, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, + 0x35, 0x01, 0x01, 0x3d, 0x07, 0x01, 0x00, 0x0b, 0x82, 0x01, 0xfc, 0x42, 0x32, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x39, 0x2, 0x5, 0xdc, 0x37, 0x04, 0x01, 0x03, 0x06, 0x2a, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; static ACK_DNS_SERVER_BYTES: &[u8] = &[ - 0x02, 0x01, 0x06, 0x00, 0xcc, 0x34, 0x75, 0xab, 0x00, 0x00, 0x80, 0x00, 0x0a, 0xff, 0x06, 0x91, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xff, 0x06, 0xfe, 0x34, 0x17, 0xeb, 0xc9, - 0xaa, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, - 0x35, 0x01, 0x05, 0x36, 0x04, 0xa3, 0x01, 0x4a, 0x16, 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, 0x2b, - 0x05, 0xdc, 0x03, 0x4e, 0x41, 0x50, 0x0f, 0x15, 0x6e, 0x61, 0x74, 0x2e, 0x70, 0x68, 0x79, 0x73, - 0x69, 0x63, 0x73, 0x2e, 0x6f, 0x78, 0x2e, 0x61, 0x63, 0x2e, 0x75, 0x6b, 0x00, 0x03, 0x04, 0x0a, - 0xff, 0x06, 0xfe, 0x06, 0x10, 0xa3, 0x01, 0x4a, 0x06, 0xa3, 0x01, 0x4a, 0x07, 0xa3, 0x01, 0x4a, - 0x03, 0xa3, 0x01, 0x4a, 0x04, 0x2c, 0x10, 0xa3, 0x01, 0x4a, 0x03, 0xa3, 0x01, 0x4a, 0x04, 0xa3, - 0x01, 0x4a, 0x06, 0xa3, 0x01, 0x4a, 0x07, 0x2e, 0x01, 0x08, 0xff + 0x02, 0x01, 0x06, 0x00, 0xcc, 0x34, 0x75, 0xab, 0x00, 0x00, 0x80, 0x00, 0x0a, 0xff, 0x06, + 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xff, 0x06, 0xfe, 0x34, 0x17, + 0xeb, 0xc9, 0xaa, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, + 0x35, 0x01, 0x05, 0x36, 0x04, 0xa3, 0x01, 0x4a, 0x16, 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, + 0x2b, 0x05, 0xdc, 0x03, 0x4e, 0x41, 0x50, 0x0f, 0x15, 0x6e, 0x61, 0x74, 0x2e, 0x70, 0x68, + 0x79, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x6f, 0x78, 0x2e, 0x61, 0x63, 0x2e, 0x75, 0x6b, 0x00, + 0x03, 0x04, 0x0a, 0xff, 0x06, 0xfe, 0x06, 0x10, 0xa3, 0x01, 0x4a, 0x06, 0xa3, 0x01, 0x4a, + 0x07, 0xa3, 0x01, 0x4a, 0x03, 0xa3, 0x01, 0x4a, 0x04, 0x2c, 0x10, 0xa3, 0x01, 0x4a, 0x03, + 0xa3, 0x01, 0x4a, 0x04, 0xa3, 0x01, 0x4a, 0x06, 0xa3, 0x01, 0x4a, 0x07, 0x2e, 0x01, 0x08, + 0xff, ]; static ACK_LEASE_TIME_BYTES: &[u8] = &[ - 0x02, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0a, 0x22, 0x10, 0x0b, 0x0a, 0x22, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x91, 0x62, 0xd2, - 0xa8, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, - 0x35, 0x01, 0x05, 0x36, 0x04, 0x0a, 0x22, 0x10, 0x0a, 0x33, 0x04, 0x00, 0x00, 0x02, 0x56, 0x01, - 0x04, 0xff, 0xff, 0xff, 0x00, 0x03, 0x04, 0x0a, 0x22, 0x10, 0x0a, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0a, 0x22, 0x10, 0x0b, 0x0a, 0x22, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x91, + 0x62, 0xd2, 0xa8, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, + 0x35, 0x01, 0x05, 0x36, 0x04, 0x0a, 0x22, 0x10, 0x0a, 0x33, 0x04, 0x00, 0x00, 0x02, 0x56, + 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, 0x03, 0x04, 0x0a, 0x22, 0x10, 0x0a, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; const IP_NULL: Ipv4Address = Ipv4Address([0, 0, 0, 0]); @@ -971,9 +1023,13 @@ mod test { assert_eq!(options.len(), 6 + 1 + 7); let (options, client_id) = DhcpOption::parse(options).unwrap(); - assert_eq!(client_id, DhcpOption::Other { - kind: field::OPT_PARAMETER_REQUEST_LIST, data: &[1, 3, 6, 42] - }); + assert_eq!( + client_id, + DhcpOption::Other { + kind: field::OPT_PARAMETER_REQUEST_LIST, + data: &[1, 3, 6, 42] + } + ); assert_eq!(options.len(), 1 + 7); let (options, client_id) = DhcpOption::parse(options).unwrap(); @@ -1007,7 +1063,8 @@ mod test { options = DhcpOption::RequestedIp(IP_NULL).emit(options); options = DhcpOption::MaximumDhcpMessageSize(DHCP_SIZE).emit(options); let option = DhcpOption::Other { - kind: field::OPT_PARAMETER_REQUEST_LIST, data: &[1, 3, 6, 42], + kind: field::OPT_PARAMETER_REQUEST_LIST, + data: &[1, 3, 6, 42], }; options = option.emit(options); DhcpOption::EndOfList.emit(options); @@ -1106,7 +1163,10 @@ mod test { let rest = dhcp_option.emit(&mut bytes); assert_eq!(rest.len(), 0); } - assert_eq!(&bytes[0..2], &[field::OPT_PARAMETER_REQUEST_LIST, DATA.len() as u8]); + assert_eq!( + &bytes[0..2], + &[field::OPT_PARAMETER_REQUEST_LIST, DATA.len() as u8] + ); assert_eq!(&bytes[2..], DATA); } @@ -1118,10 +1178,14 @@ mod test { // The packet described by ACK_BYTES advertises 4 DNS servers // Here we ensure that we correctly parse the first 3 into our fixed // length-3 array (see issue #305) - assert_eq!(repr.dns_servers, Some([ - Some(Ipv4Address([163, 1, 74, 6])), - Some(Ipv4Address([163, 1, 74, 7])), - Some(Ipv4Address([163, 1, 74, 3]))])); + assert_eq!( + repr.dns_servers, + Some([ + Some(Ipv4Address([163, 1, 74, 6])), + Some(Ipv4Address([163, 1, 74, 7])), + Some(Ipv4Address([163, 1, 74, 3])) + ]) + ); } #[test] diff --git a/src/wire/ethernet.rs b/src/wire/ethernet.rs index f530942..0e48d21 100644 --- a/src/wire/ethernet.rs +++ b/src/wire/ethernet.rs @@ -1,5 +1,5 @@ -use core::fmt; use byteorder::{ByteOrder, NetworkEndian}; +use core::fmt; use crate::{Error, Result}; @@ -17,8 +17,8 @@ impl fmt::Display for EtherType { match *self { EtherType::Ipv4 => write!(f, "IPv4"), EtherType::Ipv6 => write!(f, "IPv6"), - EtherType::Arp => write!(f, "ARP"), - EtherType::Unknown(id) => write!(f, "0x{:04x}", id) + EtherType::Arp => write!(f, "ARP"), + EtherType::Unknown(id) => write!(f, "0x{:04x}", id), } } } @@ -49,8 +49,7 @@ impl Address { /// Query whether the address is an unicast address. pub fn is_unicast(&self) -> bool { - !(self.is_broadcast() || - self.is_multicast()) + !(self.is_broadcast() || self.is_multicast()) } /// Query whether this address is the broadcast address. @@ -72,8 +71,11 @@ impl Address { impl fmt::Display for Address { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let bytes = self.0; - write!(f, "{:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}", - bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]) + write!( + f, + "{:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}", + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5] + ) } } @@ -81,16 +83,16 @@ impl fmt::Display for Address { #[derive(Debug, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Frame> { - buffer: T + buffer: T, } mod field { use crate::wire::field::*; - pub const DESTINATION: Field = 0..6; - pub const SOURCE: Field = 6..12; - pub const ETHERTYPE: Field = 12..14; - pub const PAYLOAD: Rest = 14..; + pub const DESTINATION: Field = 0..6; + pub const SOURCE: Field = 6..12; + pub const ETHERTYPE: Field = 12..14; + pub const PAYLOAD: Rest = 14..; } /// The Ethernet header length @@ -209,19 +211,27 @@ impl> AsRef<[u8]> for Frame { impl> fmt::Display for Frame { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "EthernetII src={} dst={} type={}", - self.src_addr(), self.dst_addr(), self.ethertype()) + write!( + f, + "EthernetII src={} dst={} type={}", + self.src_addr(), + self.dst_addr(), + self.ethertype() + ) } } -use crate::wire::pretty_print::{PrettyPrint, PrettyIndent}; +use crate::wire::pretty_print::{PrettyIndent, PrettyPrint}; impl> PrettyPrint for Frame { - fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter, - indent: &mut PrettyIndent) -> fmt::Result { + fn pretty_print( + buffer: &dyn AsRef<[u8]>, + f: &mut fmt::Formatter, + indent: &mut PrettyIndent, + ) -> fmt::Result { let frame = match Frame::new_checked(buffer) { - Err(err) => return write!(f, "{}({})", indent, err), - Ok(frame) => frame + Err(err) => return write!(f, "{}({})", indent, err), + Ok(frame) => frame, }; write!(f, "{}{}", indent, frame)?; @@ -241,7 +251,7 @@ impl> PrettyPrint for Frame { indent.increase(f)?; super::Ipv6Packet::<&[u8]>::pretty_print(&frame.payload(), f, indent) } - _ => Ok(()) + _ => Ok(()), } } } @@ -250,9 +260,9 @@ impl> PrettyPrint for Frame { #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Repr { - pub src_addr: Address, - pub dst_addr: Address, - pub ethertype: EtherType, + pub src_addr: Address, + pub dst_addr: Address, + pub ethertype: EtherType, } impl Repr { @@ -300,32 +310,32 @@ mod test_ipv4 { // Tests that are valid only with "proto-ipv4" use super::*; - static FRAME_BYTES: [u8; 64] = - [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x08, 0x00, - 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff]; + static FRAME_BYTES: [u8; 64] = [ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x08, 0x00, 0xaa, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + ]; - static PAYLOAD_BYTES: [u8; 50] = - [0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff]; + static PAYLOAD_BYTES: [u8; 50] = [ + 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, + ]; #[test] fn test_deconstruct() { let frame = Frame::new_unchecked(&FRAME_BYTES[..]); - assert_eq!(frame.dst_addr(), Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06])); - assert_eq!(frame.src_addr(), Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16])); + assert_eq!( + frame.dst_addr(), + Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]) + ); + assert_eq!( + frame.src_addr(), + Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16]) + ); assert_eq!(frame.ethertype(), EtherType::Ipv4); assert_eq!(frame.payload(), &PAYLOAD_BYTES[..]); } @@ -348,28 +358,30 @@ mod test_ipv6 { // Tests that are valid only with "proto-ipv6" use super::*; - static FRAME_BYTES: [u8; 54] = - [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x86, 0xdd, - 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]; + static FRAME_BYTES: [u8; 54] = [ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x86, 0xdd, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + ]; - static PAYLOAD_BYTES: [u8; 40] = - [0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]; + static PAYLOAD_BYTES: [u8; 40] = [ + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + ]; #[test] fn test_deconstruct() { let frame = Frame::new_unchecked(&FRAME_BYTES[..]); - assert_eq!(frame.dst_addr(), Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06])); - assert_eq!(frame.src_addr(), Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16])); + assert_eq!( + frame.dst_addr(), + Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]) + ); + assert_eq!( + frame.src_addr(), + Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16]) + ); assert_eq!(frame.ethertype(), EtherType::Ipv6); assert_eq!(frame.payload(), &PAYLOAD_BYTES[..]); } diff --git a/src/wire/icmpv4.rs b/src/wire/icmpv4.rs index ddabb3f..7964ee3 100644 --- a/src/wire/icmpv4.rs +++ b/src/wire/icmpv4.rs @@ -1,10 +1,10 @@ -use core::{cmp, fmt}; use byteorder::{ByteOrder, NetworkEndian}; +use core::{cmp, fmt}; -use crate::{Error, Result}; use crate::phy::ChecksumCapabilities; use crate::wire::ip::checksum; use crate::wire::{Ipv4Packet, Ipv4Repr}; +use crate::{Error, Result}; enum_with_unknown! { /// Internet protocol control message type. @@ -35,17 +35,17 @@ enum_with_unknown! { impl fmt::Display for Message { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Message::EchoReply => write!(f, "echo reply"), + Message::EchoReply => write!(f, "echo reply"), Message::DstUnreachable => write!(f, "destination unreachable"), - Message::Redirect => write!(f, "message redirect"), - Message::EchoRequest => write!(f, "echo request"), - Message::RouterAdvert => write!(f, "router advertisement"), - Message::RouterSolicit => write!(f, "router solicitation"), - Message::TimeExceeded => write!(f, "time exceeded"), - Message::ParamProblem => write!(f, "parameter problem"), - Message::Timestamp => write!(f, "timestamp"), + Message::Redirect => write!(f, "message redirect"), + Message::EchoRequest => write!(f, "echo request"), + Message::RouterAdvert => write!(f, "router advertisement"), + Message::RouterSolicit => write!(f, "router solicitation"), + Message::TimeExceeded => write!(f, "time exceeded"), + Message::ParamProblem => write!(f, "parameter problem"), + Message::Timestamp => write!(f, "timestamp"), Message::TimestampReply => write!(f, "timestamp reply"), - Message::Unknown(id) => write!(f, "{}", id) + Message::Unknown(id) => write!(f, "{}", id), } } } @@ -91,40 +91,25 @@ enum_with_unknown! { impl fmt::Display for DstUnreachable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - DstUnreachable::NetUnreachable => - write!(f, "destination network unreachable"), - DstUnreachable::HostUnreachable => - write!(f, "destination host unreachable"), - DstUnreachable::ProtoUnreachable => - write!(f, "destination protocol unreachable"), - DstUnreachable::PortUnreachable => - write!(f, "destination port unreachable"), - DstUnreachable::FragRequired => - write!(f, "fragmentation required, and DF flag set"), - DstUnreachable::SrcRouteFailed => - write!(f, "source route failed"), - DstUnreachable::DstNetUnknown => - write!(f, "destination network unknown"), - DstUnreachable::DstHostUnknown => - write!(f, "destination host unknown"), - DstUnreachable::SrcHostIsolated => - write!(f, "source host isolated"), - DstUnreachable::NetProhibited => - write!(f, "network administratively prohibited"), - DstUnreachable::HostProhibited => - write!(f, "host administratively prohibited"), - DstUnreachable::NetUnreachToS => - write!(f, "network unreachable for ToS"), - DstUnreachable::HostUnreachToS => - write!(f, "host unreachable for ToS"), - DstUnreachable::CommProhibited => - write!(f, "communication administratively prohibited"), - DstUnreachable::HostPrecedViol => - write!(f, "host precedence violation"), - DstUnreachable::PrecedCutoff => - write!(f, "precedence cutoff in effect"), - DstUnreachable::Unknown(id) => - write!(f, "{}", id) + DstUnreachable::NetUnreachable => write!(f, "destination network unreachable"), + DstUnreachable::HostUnreachable => write!(f, "destination host unreachable"), + DstUnreachable::ProtoUnreachable => write!(f, "destination protocol unreachable"), + DstUnreachable::PortUnreachable => write!(f, "destination port unreachable"), + DstUnreachable::FragRequired => write!(f, "fragmentation required, and DF flag set"), + DstUnreachable::SrcRouteFailed => write!(f, "source route failed"), + DstUnreachable::DstNetUnknown => write!(f, "destination network unknown"), + DstUnreachable::DstHostUnknown => write!(f, "destination host unknown"), + DstUnreachable::SrcHostIsolated => write!(f, "source host isolated"), + DstUnreachable::NetProhibited => write!(f, "network administratively prohibited"), + DstUnreachable::HostProhibited => write!(f, "host administratively prohibited"), + DstUnreachable::NetUnreachToS => write!(f, "network unreachable for ToS"), + DstUnreachable::HostUnreachToS => write!(f, "host unreachable for ToS"), + DstUnreachable::CommProhibited => { + write!(f, "communication administratively prohibited") + } + DstUnreachable::HostPrecedViol => write!(f, "host precedence violation"), + DstUnreachable::PrecedCutoff => write!(f, "precedence cutoff in effect"), + DstUnreachable::Unknown(id) => write!(f, "{}", id), } } } @@ -169,17 +154,17 @@ enum_with_unknown! { #[derive(Debug, PartialEq, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { - buffer: T + buffer: T, } mod field { use crate::wire::field::*; - pub const TYPE: usize = 0; - pub const CODE: usize = 1; - pub const CHECKSUM: Field = 2..4; + pub const TYPE: usize = 0; + pub const CODE: usize = 1; + pub const CHECKSUM: Field = 2..4; - pub const UNUSED: Field = 4..8; + pub const UNUSED: Field = 4..8; pub const ECHO_IDENT: Field = 4..6; pub const ECHO_SEQNO: Field = 6..8; @@ -268,10 +253,10 @@ impl> Packet { /// The result depends on the value of the message type field. pub fn header_len(&self) -> usize { match self.msg_type() { - Message::EchoRequest => field::ECHO_SEQNO.end, - Message::EchoReply => field::ECHO_SEQNO.end, + Message::EchoRequest => field::ECHO_SEQNO.end, + Message::EchoReply => field::ECHO_SEQNO.end, Message::DstUnreachable => field::UNUSED.end, - _ => field::UNUSED.end // make a conservative assumption + _ => field::UNUSED.end, // make a conservative assumption } } @@ -280,7 +265,9 @@ impl> Packet { /// # Fuzzing /// This function always returns `true` when fuzzing. pub fn verify_checksum(&self) -> bool { - if cfg!(fuzzing) { return true } + if cfg!(fuzzing) { + return true; + } let data = self.buffer.as_ref(); checksum::data(data) == !0 @@ -371,47 +358,49 @@ impl> AsRef<[u8]> for Packet { #[non_exhaustive] pub enum Repr<'a> { EchoRequest { - ident: u16, + ident: u16, seq_no: u16, - data: &'a [u8] + data: &'a [u8], }, EchoReply { - ident: u16, + ident: u16, seq_no: u16, - data: &'a [u8] + data: &'a [u8], }, DstUnreachable { reason: DstUnreachable, header: Ipv4Repr, - data: &'a [u8] + data: &'a [u8], }, } impl<'a> Repr<'a> { /// Parse an Internet Control Message Protocol version 4 packet and return /// a high-level representation. - pub fn parse(packet: &Packet<&'a T>, checksum_caps: &ChecksumCapabilities) - -> Result> - where T: AsRef<[u8]> + ?Sized { + pub fn parse( + packet: &Packet<&'a T>, + checksum_caps: &ChecksumCapabilities, + ) -> Result> + where + T: AsRef<[u8]> + ?Sized, + { // Valid checksum is expected. - if checksum_caps.icmpv4.rx() && !packet.verify_checksum() { return Err(Error::Checksum) } + if checksum_caps.icmpv4.rx() && !packet.verify_checksum() { + return Err(Error::Checksum); + } match (packet.msg_type(), packet.msg_code()) { - (Message::EchoRequest, 0) => { - Ok(Repr::EchoRequest { - ident: packet.echo_ident(), - seq_no: packet.echo_seq_no(), - data: packet.data() - }) - }, + (Message::EchoRequest, 0) => Ok(Repr::EchoRequest { + ident: packet.echo_ident(), + seq_no: packet.echo_seq_no(), + data: packet.data(), + }), - (Message::EchoReply, 0) => { - Ok(Repr::EchoReply { - ident: packet.echo_ident(), - seq_no: packet.echo_seq_no(), - data: packet.data() - }) - }, + (Message::EchoReply, 0) => Ok(Repr::EchoReply { + ident: packet.echo_ident(), + seq_no: packet.echo_seq_no(), + data: packet.data(), + }), (Message::DstUnreachable, code) => { let ip_packet = Ipv4Packet::new_checked(packet.data())?; @@ -419,7 +408,9 @@ impl<'a> Repr<'a> { let payload = &packet.data()[ip_packet.header_len() as usize..]; // RFC 792 requires exactly eight bytes to be returned. // We allow more, since there isn't a reason not to, but require at least eight. - if payload.len() < 8 { return Err(Error::Truncated) } + if payload.len() < 8 { + return Err(Error::Truncated); + } Ok(Repr::DstUnreachable { reason: DstUnreachable::from(code), @@ -428,22 +419,21 @@ impl<'a> Repr<'a> { dst_addr: ip_packet.dst_addr(), protocol: ip_packet.protocol(), payload_len: payload.len(), - hop_limit: ip_packet.hop_limit() + hop_limit: ip_packet.hop_limit(), }, - data: payload + data: payload, }) } - _ => Err(Error::Unrecognized) + _ => Err(Error::Unrecognized), } } /// Return the length of a packet that will be emitted from this high-level representation. pub fn buffer_len(&self) -> usize { match self { - &Repr::EchoRequest { data, .. } | - &Repr::EchoReply { data, .. } => { + &Repr::EchoRequest { data, .. } | &Repr::EchoReply { data, .. } => { field::ECHO_SEQNO.end + data.len() - }, + } &Repr::DstUnreachable { header, data, .. } => { field::UNUSED.end + header.buffer_len() + data.len() } @@ -453,28 +443,42 @@ impl<'a> Repr<'a> { /// Emit a high-level representation into an Internet Control Message Protocol version 4 /// packet. pub fn emit(&self, packet: &mut Packet<&mut T>, checksum_caps: &ChecksumCapabilities) - where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized { + where + T: AsRef<[u8]> + AsMut<[u8]> + ?Sized, + { packet.set_msg_code(0); match *self { - Repr::EchoRequest { ident, seq_no, data } => { + Repr::EchoRequest { + ident, + seq_no, + data, + } => { packet.set_msg_type(Message::EchoRequest); packet.set_msg_code(0); packet.set_echo_ident(ident); packet.set_echo_seq_no(seq_no); let data_len = cmp::min(packet.data_mut().len(), data.len()); packet.data_mut()[..data_len].copy_from_slice(&data[..data_len]) - }, + } - Repr::EchoReply { ident, seq_no, data } => { + Repr::EchoReply { + ident, + seq_no, + data, + } => { packet.set_msg_type(Message::EchoReply); packet.set_msg_code(0); packet.set_echo_ident(ident); packet.set_echo_seq_no(seq_no); let data_len = cmp::min(packet.data_mut().len(), data.len()); packet.data_mut()[..data_len].copy_from_slice(&data[..data_len]) - }, + } - Repr::DstUnreachable { reason, header, data } => { + Repr::DstUnreachable { + reason, + header, + data, + } => { packet.set_msg_type(Message::DstUnreachable); packet.set_msg_code(reason.into()); @@ -503,9 +507,10 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> { write!(f, "ICMPv4 ({})", err)?; write!(f, " type={:?}", self.msg_type())?; match self.msg_type() { - Message::DstUnreachable => - write!(f, " code={:?}", DstUnreachable::from(self.msg_code())), - _ => write!(f, " code={}", self.msg_code()) + Message::DstUnreachable => { + write!(f, " code={:?}", DstUnreachable::from(self.msg_code())) + } + _ => write!(f, " code={}", self.msg_code()), } } } @@ -515,27 +520,46 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> { impl<'a> fmt::Display for Repr<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Repr::EchoRequest { ident, seq_no, data } => - write!(f, "ICMPv4 echo request id={} seq={} len={}", - ident, seq_no, data.len()), - Repr::EchoReply { ident, seq_no, data } => - write!(f, "ICMPv4 echo reply id={} seq={} len={}", - ident, seq_no, data.len()), - Repr::DstUnreachable { reason, .. } => - write!(f, "ICMPv4 destination unreachable ({})", - reason), + Repr::EchoRequest { + ident, + seq_no, + data, + } => write!( + f, + "ICMPv4 echo request id={} seq={} len={}", + ident, + seq_no, + data.len() + ), + Repr::EchoReply { + ident, + seq_no, + data, + } => write!( + f, + "ICMPv4 echo reply id={} seq={} len={}", + ident, + seq_no, + data.len() + ), + Repr::DstUnreachable { reason, .. } => { + write!(f, "ICMPv4 destination unreachable ({})", reason) + } } } } -use crate::wire::pretty_print::{PrettyPrint, PrettyIndent}; +use crate::wire::pretty_print::{PrettyIndent, PrettyPrint}; impl> PrettyPrint for Packet { - fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter, - indent: &mut PrettyIndent) -> fmt::Result { + fn pretty_print( + buffer: &dyn AsRef<[u8]>, + f: &mut fmt::Formatter, + indent: &mut PrettyIndent, + ) -> fmt::Result { let packet = match Packet::new_checked(buffer) { - Err(err) => return write!(f, "{}({})", indent, err), - Ok(packet) => packet + Err(err) => return write!(f, "{}({})", indent, err), + Ok(packet) => packet, }; write!(f, "{}{}", indent, packet)?; @@ -544,7 +568,7 @@ impl> PrettyPrint for Packet { indent.increase(f)?; super::Ipv4Packet::<&[u8]>::pretty_print(&packet.data(), f, indent) } - _ => Ok(()) + _ => Ok(()), } } } @@ -553,13 +577,11 @@ impl> PrettyPrint for Packet { mod test { use super::*; - static ECHO_PACKET_BYTES: [u8; 12] = - [0x08, 0x00, 0x8e, 0xfe, - 0x12, 0x34, 0xab, 0xcd, - 0xaa, 0x00, 0x00, 0xff]; + static ECHO_PACKET_BYTES: [u8; 12] = [ + 0x08, 0x00, 0x8e, 0xfe, 0x12, 0x34, 0xab, 0xcd, 0xaa, 0x00, 0x00, 0xff, + ]; - static ECHO_DATA_BYTES: [u8; 4] = - [0xaa, 0x00, 0x00, 0xff]; + static ECHO_DATA_BYTES: [u8; 4] = [0xaa, 0x00, 0x00, 0xff]; #[test] fn test_echo_deconstruct() { @@ -590,7 +612,7 @@ mod test { Repr::EchoRequest { ident: 0x1234, seq_no: 0xabcd, - data: &ECHO_DATA_BYTES + data: &ECHO_DATA_BYTES, } } @@ -612,8 +634,7 @@ mod test { #[test] fn test_check_len() { - let bytes = [0x0b, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00]; + let bytes = [0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Packet::new_checked(&[]), Err(Error::Truncated)); assert_eq!(Packet::new_checked(&bytes[..4]), Err(Error::Truncated)); assert!(Packet::new_checked(&bytes[..]).is_ok()); diff --git a/src/wire/icmpv6.rs b/src/wire/icmpv6.rs index 5ab01db..395509b 100644 --- a/src/wire/icmpv6.rs +++ b/src/wire/icmpv6.rs @@ -1,13 +1,13 @@ -use core::{cmp, fmt}; use byteorder::{ByteOrder, NetworkEndian}; +use core::{cmp, fmt}; -use crate::{Error, Result}; use crate::phy::ChecksumCapabilities; use crate::wire::ip::checksum; -use crate::wire::{IpAddress, IpProtocol, Ipv6Packet, Ipv6Repr}; use crate::wire::MldRepr; #[cfg(feature = "medium-ethernet")] use crate::wire::NdiscRepr; +use crate::wire::{IpAddress, IpProtocol, Ipv6Packet, Ipv6Repr}; +use crate::{Error, Result}; enum_with_unknown! { /// Internet protocol control message type. @@ -57,8 +57,11 @@ impl Message { /// [NDISC]: https://tools.ietf.org/html/rfc4861 pub fn is_ndisc(&self) -> bool { match *self { - Message::RouterSolicit | Message::RouterAdvert | Message::NeighborSolicit | - Message::NeighborAdvert | Message::Redirect => true, + Message::RouterSolicit + | Message::RouterAdvert + | Message::NeighborSolicit + | Message::NeighborAdvert + | Message::Redirect => true, _ => false, } } @@ -78,20 +81,20 @@ impl Message { impl fmt::Display for Message { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Message::DstUnreachable => write!(f, "destination unreachable"), - Message::PktTooBig => write!(f, "packet too big"), - Message::TimeExceeded => write!(f, "time exceeded"), - Message::ParamProblem => write!(f, "parameter problem"), - Message::EchoReply => write!(f, "echo reply"), - Message::EchoRequest => write!(f, "echo request"), - Message::RouterSolicit => write!(f, "router solicitation"), - Message::RouterAdvert => write!(f, "router advertisement"), + Message::DstUnreachable => write!(f, "destination unreachable"), + Message::PktTooBig => write!(f, "packet too big"), + Message::TimeExceeded => write!(f, "time exceeded"), + Message::ParamProblem => write!(f, "parameter problem"), + Message::EchoReply => write!(f, "echo reply"), + Message::EchoRequest => write!(f, "echo request"), + Message::RouterSolicit => write!(f, "router solicitation"), + Message::RouterAdvert => write!(f, "router advertisement"), Message::NeighborSolicit => write!(f, "neighbor solicitation"), - Message::NeighborAdvert => write!(f, "neighbor advert"), - Message::Redirect => write!(f, "redirect"), - Message::MldQuery => write!(f, "multicast listener query"), - Message::MldReport => write!(f, "multicast listener report"), - Message::Unknown(id) => write!(f, "{}", id) + Message::NeighborAdvert => write!(f, "neighbor advert"), + Message::Redirect => write!(f, "redirect"), + Message::MldQuery => write!(f, "multicast listener query"), + Message::MldReport => write!(f, "multicast listener report"), + Message::Unknown(id) => write!(f, "{}", id), } } } @@ -119,22 +122,19 @@ enum_with_unknown! { impl fmt::Display for DstUnreachable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - DstUnreachable::NoRoute => - write!(f, "no route to destination"), - DstUnreachable::AdminProhibit => - write!(f, "communication with destination administratively prohibited"), - DstUnreachable::BeyondScope => - write!(f, "beyond scope of source address"), - DstUnreachable::AddrUnreachable => - write!(f, "address unreachable"), - DstUnreachable::PortUnreachable => - write!(f, "port unreachable"), - DstUnreachable::FailedPolicy => - write!(f, "source address failed ingress/egress policy"), - DstUnreachable::RejectRoute => - write!(f, "reject route to destination"), - DstUnreachable::Unknown(id) => - write!(f, "{}", id) + DstUnreachable::NoRoute => write!(f, "no route to destination"), + DstUnreachable::AdminProhibit => write!( + f, + "communication with destination administratively prohibited" + ), + DstUnreachable::BeyondScope => write!(f, "beyond scope of source address"), + DstUnreachable::AddrUnreachable => write!(f, "address unreachable"), + DstUnreachable::PortUnreachable => write!(f, "port unreachable"), + DstUnreachable::FailedPolicy => { + write!(f, "source address failed ingress/egress policy") + } + DstUnreachable::RejectRoute => write!(f, "reject route to destination"), + DstUnreachable::Unknown(id) => write!(f, "{}", id), } } } @@ -154,14 +154,10 @@ enum_with_unknown! { impl fmt::Display for ParamProblem { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - ParamProblem::ErroneousHdrField => - write!(f, "erroneous header field."), - ParamProblem::UnrecognizedNxtHdr => - write!(f, "unrecognized next header type."), - ParamProblem::UnrecognizedOption => - write!(f, "unrecognized IPv6 option."), - ParamProblem::Unknown(id) => - write!(f, "{}", id) + ParamProblem::ErroneousHdrField => write!(f, "erroneous header field."), + ParamProblem::UnrecognizedNxtHdr => write!(f, "unrecognized next header type."), + ParamProblem::UnrecognizedOption => write!(f, "unrecognized IPv6 option."), + ParamProblem::Unknown(id) => write!(f, "{}", id), } } } @@ -179,12 +175,9 @@ enum_with_unknown! { impl fmt::Display for TimeExceeded { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - TimeExceeded::HopLimitExceeded => - write!(f, "hop limit exceeded in transit"), - TimeExceeded::FragReassemExceeded => - write!(f, "fragment reassembly time exceeded"), - TimeExceeded::Unknown(id) => - write!(f, "{}", id) + TimeExceeded::HopLimitExceeded => write!(f, "hop limit exceeded in transit"), + TimeExceeded::FragReassemExceeded => write!(f, "fragment reassembly time exceeded"), + TimeExceeded::Unknown(id) => write!(f, "{}", id), } } } @@ -193,7 +186,7 @@ impl fmt::Display for TimeExceeded { #[derive(Debug, PartialEq, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { - pub(super) buffer: T + pub(super) buffer: T, } // Ranges and constants describing key boundaries in the ICMPv6 header. @@ -201,54 +194,54 @@ pub(super) mod field { use crate::wire::field::*; // ICMPv6: See https://tools.ietf.org/html/rfc4443 - pub const TYPE: usize = 0; - pub const CODE: usize = 1; - pub const CHECKSUM: Field = 2..4; + pub const TYPE: usize = 0; + pub const CODE: usize = 1; + pub const CHECKSUM: Field = 2..4; - pub const UNUSED: Field = 4..8; - pub const MTU: Field = 4..8; - pub const POINTER: Field = 4..8; - pub const ECHO_IDENT: Field = 4..6; - pub const ECHO_SEQNO: Field = 6..8; + pub const UNUSED: Field = 4..8; + pub const MTU: Field = 4..8; + pub const POINTER: Field = 4..8; + pub const ECHO_IDENT: Field = 4..6; + pub const ECHO_SEQNO: Field = 6..8; - pub const HEADER_END: usize = 8; + pub const HEADER_END: usize = 8; // NDISC: See https://tools.ietf.org/html/rfc4861 // Router Advertisement message offsets - pub const CUR_HOP_LIMIT: usize = 4; - pub const ROUTER_FLAGS: usize = 5; - pub const ROUTER_LT: Field = 6..8; - pub const REACHABLE_TM: Field = 8..12; - pub const RETRANS_TM: Field = 12..16; + pub const CUR_HOP_LIMIT: usize = 4; + pub const ROUTER_FLAGS: usize = 5; + pub const ROUTER_LT: Field = 6..8; + pub const REACHABLE_TM: Field = 8..12; + pub const RETRANS_TM: Field = 12..16; // Neighbor Solicitation message offsets - pub const TARGET_ADDR: Field = 8..24; + pub const TARGET_ADDR: Field = 8..24; // Neighbor Advertisement message offsets - pub const NEIGH_FLAGS: usize = 4; + pub const NEIGH_FLAGS: usize = 4; // Redirected Header message offsets - pub const DEST_ADDR: Field = 24..40; + pub const DEST_ADDR: Field = 24..40; // MLD: // - https://tools.ietf.org/html/rfc3810 // - https://tools.ietf.org/html/rfc3810 // Multicast Listener Query message - pub const MAX_RESP_CODE: Field = 4..6; - pub const QUERY_RESV: Field = 6..8; - pub const QUERY_MCAST_ADDR: Field = 8..24; - pub const SQRV: usize = 24; - pub const QQIC: usize = 25; - pub const QUERY_NUM_SRCS: Field = 26..28; + pub const MAX_RESP_CODE: Field = 4..6; + pub const QUERY_RESV: Field = 6..8; + pub const QUERY_MCAST_ADDR: Field = 8..24; + pub const SQRV: usize = 24; + pub const QQIC: usize = 25; + pub const QUERY_NUM_SRCS: Field = 26..28; // Multicast Listener Report Message - pub const RECORD_RESV: Field = 4..6; - pub const NR_MCAST_RCRDS: Field = 6..8; + pub const RECORD_RESV: Field = 4..6; + pub const NR_MCAST_RCRDS: Field = 6..8; // Multicast Address Record Offsets - pub const RECORD_TYPE: usize = 0; - pub const AUX_DATA_LEN: usize = 1; - pub const RECORD_NUM_SRCS: Field = 2..4; + pub const RECORD_TYPE: usize = 0; + pub const AUX_DATA_LEN: usize = 1; + pub const RECORD_NUM_SRCS: Field = 2..4; pub const RECORD_MCAST_ADDR: Field = 4..20; } @@ -333,29 +326,28 @@ impl> Packet { NetworkEndian::read_u32(&data[field::POINTER]) } - /// Return the header length. The result depends on the value of /// the message type field. pub fn header_len(&self) -> usize { match self.msg_type() { - Message::DstUnreachable => field::UNUSED.end, - Message::PktTooBig => field::MTU.end, - Message::TimeExceeded => field::UNUSED.end, - Message::ParamProblem => field::POINTER.end, - Message::EchoRequest => field::ECHO_SEQNO.end, - Message::EchoReply => field::ECHO_SEQNO.end, - Message::RouterSolicit => field::UNUSED.end, - Message::RouterAdvert => field::RETRANS_TM.end, + Message::DstUnreachable => field::UNUSED.end, + Message::PktTooBig => field::MTU.end, + Message::TimeExceeded => field::UNUSED.end, + Message::ParamProblem => field::POINTER.end, + Message::EchoRequest => field::ECHO_SEQNO.end, + Message::EchoReply => field::ECHO_SEQNO.end, + Message::RouterSolicit => field::UNUSED.end, + Message::RouterAdvert => field::RETRANS_TM.end, Message::NeighborSolicit => field::TARGET_ADDR.end, - Message::NeighborAdvert => field::TARGET_ADDR.end, - Message::Redirect => field::DEST_ADDR.end, - Message::MldQuery => field::QUERY_NUM_SRCS.end, - Message::MldReport => field::NR_MCAST_RCRDS.end, + Message::NeighborAdvert => field::TARGET_ADDR.end, + Message::Redirect => field::DEST_ADDR.end, + Message::MldQuery => field::QUERY_NUM_SRCS.end, + Message::MldReport => field::NR_MCAST_RCRDS.end, // For packets that are not included in RFC 4443, do not // include the last 32 bits of the ICMPv6 header in // `header_bytes`. This must be done so that these bytes // can be accessed in the `payload`. - _ => field::CHECKSUM.end + _ => field::CHECKSUM.end, } } @@ -364,13 +356,14 @@ impl> Packet { /// # Fuzzing /// This function always returns `true` when fuzzing. pub fn verify_checksum(&self, src_addr: &IpAddress, dst_addr: &IpAddress) -> bool { - if cfg!(fuzzing) { return true } + if cfg!(fuzzing) { + return true; + } let data = self.buffer.as_ref(); checksum::combine(&[ - checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Icmpv6, - data.len() as u32), - checksum::data(data) + checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Icmpv6, data.len() as u32), + checksum::data(data), ]) == !0 } } @@ -409,16 +402,18 @@ impl + AsMut<[u8]>> Packet { #[inline] pub fn clear_reserved(&mut self) { match self.msg_type() { - Message::RouterSolicit | Message::NeighborSolicit | - Message::NeighborAdvert | Message::Redirect => { + Message::RouterSolicit + | Message::NeighborSolicit + | Message::NeighborAdvert + | Message::Redirect => { let data = self.buffer.as_mut(); NetworkEndian::write_u32(&mut data[field::UNUSED], 0); - }, + } Message::MldQuery => { let data = self.buffer.as_mut(); NetworkEndian::write_u16(&mut data[field::QUERY_RESV], 0); data[field::SQRV] &= 0xf; - }, + } Message::MldReport => { let data = self.buffer.as_mut(); NetworkEndian::write_u16(&mut data[field::RECORD_RESV], 0); @@ -479,9 +474,8 @@ impl + AsMut<[u8]>> Packet { let checksum = { let data = self.buffer.as_ref(); !checksum::combine(&[ - checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Icmpv6, - data.len() as u32), - checksum::data(data) + checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Icmpv6, data.len() as u32), + checksum::data(data), ]) }; self.set_checksum(checksum) @@ -510,33 +504,33 @@ pub enum Repr<'a> { DstUnreachable { reason: DstUnreachable, header: Ipv6Repr, - data: &'a [u8] + data: &'a [u8], }, PktTooBig { mtu: u32, header: Ipv6Repr, - data: &'a [u8] + data: &'a [u8], }, TimeExceeded { reason: TimeExceeded, header: Ipv6Repr, - data: &'a [u8] + data: &'a [u8], }, ParamProblem { - reason: ParamProblem, + reason: ParamProblem, pointer: u32, - header: Ipv6Repr, - data: &'a [u8] + header: Ipv6Repr, + data: &'a [u8], }, EchoRequest { - ident: u16, + ident: u16, seq_no: u16, - data: &'a [u8] + data: &'a [u8], }, EchoReply { - ident: u16, + ident: u16, seq_no: u16, - data: &'a [u8] + data: &'a [u8], }, #[cfg(feature = "medium-ethernet")] Ndisc(NdiscRepr<'a>), @@ -546,29 +540,37 @@ pub enum Repr<'a> { impl<'a> Repr<'a> { /// Parse an Internet Control Message Protocol version 6 packet and return /// a high-level representation. - pub fn parse(src_addr: &IpAddress, dst_addr: &IpAddress, - packet: &Packet<&'a T>, checksum_caps: &ChecksumCapabilities) - -> Result> - where T: AsRef<[u8]> + ?Sized { - fn create_packet_from_payload<'a, T>(packet: &Packet<&'a T>) - -> Result<(&'a [u8], Ipv6Repr)> - where T: AsRef<[u8]> + ?Sized { + pub fn parse( + src_addr: &IpAddress, + dst_addr: &IpAddress, + packet: &Packet<&'a T>, + checksum_caps: &ChecksumCapabilities, + ) -> Result> + where + T: AsRef<[u8]> + ?Sized, + { + fn create_packet_from_payload<'a, T>(packet: &Packet<&'a T>) -> Result<(&'a [u8], Ipv6Repr)> + where + T: AsRef<[u8]> + ?Sized, + { let ip_packet = Ipv6Packet::new_checked(packet.payload())?; let payload = &packet.payload()[ip_packet.header_len() as usize..]; - if payload.len() < 8 { return Err(Error::Truncated) } + if payload.len() < 8 { + return Err(Error::Truncated); + } let repr = Ipv6Repr { src_addr: ip_packet.src_addr(), dst_addr: ip_packet.dst_addr(), next_header: ip_packet.next_header(), payload_len: payload.len(), - hop_limit: ip_packet.hop_limit() + hop_limit: ip_packet.hop_limit(), }; Ok((payload, repr)) } // Valid checksum is expected. if checksum_caps.icmpv6.rx() && !packet.verify_checksum(src_addr, dst_addr) { - return Err(Error::Checksum) + return Err(Error::Checksum); } match (packet.msg_type(), packet.msg_code()) { @@ -577,85 +579,80 @@ impl<'a> Repr<'a> { Ok(Repr::DstUnreachable { reason: DstUnreachable::from(code), header: repr, - data: payload + data: payload, }) - }, + } (Message::PktTooBig, 0) => { let (payload, repr) = create_packet_from_payload(packet)?; Ok(Repr::PktTooBig { mtu: packet.pkt_too_big_mtu(), header: repr, - data: payload + data: payload, }) - }, + } (Message::TimeExceeded, code) => { let (payload, repr) = create_packet_from_payload(packet)?; Ok(Repr::TimeExceeded { reason: TimeExceeded::from(code), header: repr, - data: payload + data: payload, }) - }, + } (Message::ParamProblem, code) => { let (payload, repr) = create_packet_from_payload(packet)?; Ok(Repr::ParamProblem { reason: ParamProblem::from(code), pointer: packet.param_problem_ptr(), header: repr, - data: payload + data: payload, }) - }, - (Message::EchoRequest, 0) => { - Ok(Repr::EchoRequest { - ident: packet.echo_ident(), - seq_no: packet.echo_seq_no(), - data: packet.payload() - }) - }, - (Message::EchoReply, 0) => { - Ok(Repr::EchoReply { - ident: packet.echo_ident(), - seq_no: packet.echo_seq_no(), - data: packet.payload() - }) - }, + } + (Message::EchoRequest, 0) => Ok(Repr::EchoRequest { + ident: packet.echo_ident(), + seq_no: packet.echo_seq_no(), + data: packet.payload(), + }), + (Message::EchoReply, 0) => Ok(Repr::EchoReply { + ident: packet.echo_ident(), + seq_no: packet.echo_seq_no(), + data: packet.payload(), + }), #[cfg(feature = "medium-ethernet")] - (msg_type, 0) if msg_type.is_ndisc() => { - NdiscRepr::parse(packet).map(Repr::Ndisc) - }, - (msg_type, 0) if msg_type.is_mld() => { - MldRepr::parse(packet).map(Repr::Mld) - }, - _ => Err(Error::Unrecognized) + (msg_type, 0) if msg_type.is_ndisc() => NdiscRepr::parse(packet).map(Repr::Ndisc), + (msg_type, 0) if msg_type.is_mld() => MldRepr::parse(packet).map(Repr::Mld), + _ => Err(Error::Unrecognized), } } /// Return the length of a packet that will be emitted from this high-level representation. pub fn buffer_len(&self) -> usize { match self { - &Repr::DstUnreachable { header, data, .. } | &Repr::PktTooBig { header, data, .. } | - &Repr::TimeExceeded { header, data, .. } | &Repr::ParamProblem { header, data, .. } => { + &Repr::DstUnreachable { header, data, .. } + | &Repr::PktTooBig { header, data, .. } + | &Repr::TimeExceeded { header, data, .. } + | &Repr::ParamProblem { header, data, .. } => { field::UNUSED.end + header.buffer_len() + data.len() } - &Repr::EchoRequest { data, .. } | - &Repr::EchoReply { data, .. } => { + &Repr::EchoRequest { data, .. } | &Repr::EchoReply { data, .. } => { field::ECHO_SEQNO.end + data.len() - }, + } #[cfg(feature = "medium-ethernet")] - &Repr::Ndisc(ndisc) => { - ndisc.buffer_len() - }, - &Repr::Mld(mld) => { - mld.buffer_len() - }, + &Repr::Ndisc(ndisc) => ndisc.buffer_len(), + &Repr::Mld(mld) => mld.buffer_len(), } } /// Emit a high-level representation into an Internet Control Message Protocol version 6 /// packet. - pub fn emit(&self, src_addr: &IpAddress, dst_addr: &IpAddress, - packet: &mut Packet<&mut T>, checksum_caps: &ChecksumCapabilities) - where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized { + pub fn emit( + &self, + src_addr: &IpAddress, + dst_addr: &IpAddress, + packet: &mut Packet<&mut T>, + checksum_caps: &ChecksumCapabilities, + ) where + T: AsRef<[u8]> + AsMut<[u8]> + ?Sized, + { fn emit_contained_packet(buffer: &mut [u8], header: Ipv6Repr, data: &[u8]) { let mut ip_packet = Ipv6Packet::new_unchecked(buffer); header.emit(&mut ip_packet); @@ -664,12 +661,16 @@ impl<'a> Repr<'a> { } match *self { - Repr::DstUnreachable { reason, header, data } => { + Repr::DstUnreachable { + reason, + header, + data, + } => { packet.set_msg_type(Message::DstUnreachable); packet.set_msg_code(reason.into()); emit_contained_packet(packet.payload_mut(), header, &data); - }, + } Repr::PktTooBig { mtu, header, data } => { packet.set_msg_type(Message::PktTooBig); @@ -677,49 +678,62 @@ impl<'a> Repr<'a> { packet.set_pkt_too_big_mtu(mtu); emit_contained_packet(packet.payload_mut(), header, &data); - }, + } - Repr::TimeExceeded { reason, header, data } => { + Repr::TimeExceeded { + reason, + header, + data, + } => { packet.set_msg_type(Message::TimeExceeded); packet.set_msg_code(reason.into()); emit_contained_packet(packet.payload_mut(), header, &data); - }, + } - Repr::ParamProblem { reason, pointer, header, data } => { + Repr::ParamProblem { + reason, + pointer, + header, + data, + } => { packet.set_msg_type(Message::ParamProblem); packet.set_msg_code(reason.into()); packet.set_param_problem_ptr(pointer); emit_contained_packet(packet.payload_mut(), header, &data); - }, + } - Repr::EchoRequest { ident, seq_no, data } => { + Repr::EchoRequest { + ident, + seq_no, + data, + } => { packet.set_msg_type(Message::EchoRequest); packet.set_msg_code(0); packet.set_echo_ident(ident); packet.set_echo_seq_no(seq_no); let data_len = cmp::min(packet.payload_mut().len(), data.len()); packet.payload_mut()[..data_len].copy_from_slice(&data[..data_len]) - }, + } - Repr::EchoReply { ident, seq_no, data } => { + Repr::EchoReply { + ident, + seq_no, + data, + } => { packet.set_msg_type(Message::EchoReply); packet.set_msg_code(0); packet.set_echo_ident(ident); packet.set_echo_seq_no(seq_no); let data_len = cmp::min(packet.payload_mut().len(), data.len()); packet.payload_mut()[..data_len].copy_from_slice(&data[..data_len]) - }, + } #[cfg(feature = "medium-ethernet")] - Repr::Ndisc(ndisc) => { - ndisc.emit(packet) - }, + Repr::Ndisc(ndisc) => ndisc.emit(packet), - Repr::Mld(mld) => { - mld.emit(packet) - }, + Repr::Mld(mld) => mld.emit(packet), } if checksum_caps.icmpv6.tx() { @@ -733,60 +747,39 @@ impl<'a> Repr<'a> { #[cfg(test)] mod test { - use crate::wire::{Ipv6Address, Ipv6Repr, IpProtocol}; - use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2}; use super::*; + use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2}; + use crate::wire::{IpProtocol, Ipv6Address, Ipv6Repr}; - static ECHO_PACKET_BYTES: [u8; 12] = - [0x80, 0x00, 0x19, 0xb3, - 0x12, 0x34, 0xab, 0xcd, - 0xaa, 0x00, 0x00, 0xff]; + static ECHO_PACKET_BYTES: [u8; 12] = [ + 0x80, 0x00, 0x19, 0xb3, 0x12, 0x34, 0xab, 0xcd, 0xaa, 0x00, 0x00, 0xff, + ]; - static ECHO_PACKET_PAYLOAD: [u8; 4] = - [0xaa, 0x00, 0x00, 0xff]; + static ECHO_PACKET_PAYLOAD: [u8; 4] = [0xaa, 0x00, 0x00, 0xff]; - static PKT_TOO_BIG_BYTES: [u8; 60] = - [0x02, 0x00, 0x0f, 0xc9, - 0x00, 0x00, 0x05, 0xdc, - 0x60, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x11, 0x40, - 0xfe, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0xfe, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, - 0xbf, 0x00, 0x00, 0x35, - 0x00, 0x0c, 0x12, 0x4d, - 0xaa, 0x00, 0x00, 0xff]; + static PKT_TOO_BIG_BYTES: [u8; 60] = [ + 0x02, 0x00, 0x0f, 0xc9, 0x00, 0x00, 0x05, 0xdc, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x11, + 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0xbf, 0x00, 0x00, 0x35, 0x00, 0x0c, 0x12, 0x4d, 0xaa, 0x00, 0x00, 0xff, + ]; - static PKT_TOO_BIG_IP_PAYLOAD: [u8; 52] = - [0x60, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x11, 0x40, - 0xfe, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0xfe, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, - 0xbf, 0x00, 0x00, 0x35, - 0x00, 0x0c, 0x12, 0x4d, - 0xaa, 0x00, 0x00, 0xff]; + static PKT_TOO_BIG_IP_PAYLOAD: [u8; 52] = [ + 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x11, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xbf, 0x00, 0x00, 0x35, 0x00, + 0x0c, 0x12, 0x4d, 0xaa, 0x00, 0x00, 0xff, + ]; - static PKT_TOO_BIG_UDP_PAYLOAD: [u8; 12] = - [0xbf, 0x00, 0x00, 0x35, - 0x00, 0x0c, 0x12, 0x4d, - 0xaa, 0x00, 0x00, 0xff]; + static PKT_TOO_BIG_UDP_PAYLOAD: [u8; 12] = [ + 0xbf, 0x00, 0x00, 0x35, 0x00, 0x0c, 0x12, 0x4d, 0xaa, 0x00, 0x00, 0xff, + ]; fn echo_packet_repr() -> Repr<'static> { Repr::EchoRequest { ident: 0x1234, seq_no: 0xabcd, - data: &ECHO_PACKET_PAYLOAD + data: &ECHO_PACKET_PAYLOAD, } } @@ -794,17 +787,17 @@ 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([ + 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, + ]), next_header: IpProtocol::Udp, payload_len: 12, - hop_limit: 0x40 + hop_limit: 0x40, }, data: &PKT_TOO_BIG_UDP_PAYLOAD, } @@ -819,7 +812,10 @@ mod test { assert_eq!(packet.echo_ident(), 0x1234); assert_eq!(packet.echo_seq_no(), 0xabcd); assert_eq!(packet.payload(), &ECHO_PACKET_PAYLOAD[..]); - assert_eq!(packet.verify_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2), true); + assert_eq!( + packet.verify_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2), + true + ); assert!(!packet.msg_type().is_error()); } @@ -831,7 +827,9 @@ mod test { packet.set_msg_code(0); packet.set_echo_ident(0x1234); packet.set_echo_seq_no(0xabcd); - packet.payload_mut().copy_from_slice(&ECHO_PACKET_PAYLOAD[..]); + packet + .payload_mut() + .copy_from_slice(&ECHO_PACKET_PAYLOAD[..]); packet.fill_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2); assert_eq!(&packet.into_inner()[..], &ECHO_PACKET_BYTES[..]); } @@ -839,8 +837,13 @@ mod test { #[test] fn test_echo_repr_parse() { let packet = Packet::new_unchecked(&ECHO_PACKET_BYTES[..]); - let repr = Repr::parse(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2, - &packet, &ChecksumCapabilities::default()).unwrap(); + let repr = Repr::parse( + &MOCK_IP_ADDR_1, + &MOCK_IP_ADDR_2, + &packet, + &ChecksumCapabilities::default(), + ) + .unwrap(); assert_eq!(repr, echo_packet_repr()); } @@ -849,8 +852,12 @@ mod test { let repr = echo_packet_repr(); let mut bytes = vec![0xa5; repr.buffer_len()]; let mut packet = Packet::new_unchecked(&mut bytes); - repr.emit(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2, - &mut packet, &ChecksumCapabilities::default()); + repr.emit( + &MOCK_IP_ADDR_1, + &MOCK_IP_ADDR_2, + &mut packet, + &ChecksumCapabilities::default(), + ); assert_eq!(&packet.into_inner()[..], &ECHO_PACKET_BYTES[..]); } @@ -862,7 +869,10 @@ mod test { assert_eq!(packet.checksum(), 0x0fc9); assert_eq!(packet.pkt_too_big_mtu(), 1500); assert_eq!(packet.payload(), &PKT_TOO_BIG_IP_PAYLOAD[..]); - assert_eq!(packet.verify_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2), true); + assert_eq!( + packet.verify_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2), + true + ); assert!(packet.msg_type().is_error()); } @@ -873,7 +883,9 @@ mod test { packet.set_msg_type(Message::PktTooBig); packet.set_msg_code(0); packet.set_pkt_too_big_mtu(1500); - packet.payload_mut().copy_from_slice(&PKT_TOO_BIG_IP_PAYLOAD[..]); + packet + .payload_mut() + .copy_from_slice(&PKT_TOO_BIG_IP_PAYLOAD[..]); packet.fill_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2); assert_eq!(&packet.into_inner()[..], &PKT_TOO_BIG_BYTES[..]); } @@ -881,8 +893,13 @@ mod test { #[test] fn test_too_big_repr_parse() { let packet = Packet::new_unchecked(&PKT_TOO_BIG_BYTES[..]); - let repr = Repr::parse(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2, - &packet, &ChecksumCapabilities::default()).unwrap(); + let repr = Repr::parse( + &MOCK_IP_ADDR_1, + &MOCK_IP_ADDR_2, + &packet, + &ChecksumCapabilities::default(), + ) + .unwrap(); assert_eq!(repr, too_big_packet_repr()); } @@ -891,8 +908,12 @@ mod test { let repr = too_big_packet_repr(); let mut bytes = vec![0xa5; repr.buffer_len()]; let mut packet = Packet::new_unchecked(&mut bytes); - repr.emit(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2, - &mut packet, &ChecksumCapabilities::default()); + repr.emit( + &MOCK_IP_ADDR_1, + &MOCK_IP_ADDR_2, + &mut packet, + &ChecksumCapabilities::default(), + ); assert_eq!(&packet.into_inner()[..], &PKT_TOO_BIG_BYTES[..]); } } diff --git a/src/wire/igmp.rs b/src/wire/igmp.rs index 3c6da88..2a11772 100644 --- a/src/wire/igmp.rs +++ b/src/wire/igmp.rs @@ -1,9 +1,9 @@ -use core::fmt; use byteorder::{ByteOrder, NetworkEndian}; +use core::fmt; -use crate::{Error, Result}; -use crate::wire::ip::checksum; use crate::time::Duration; +use crate::wire::ip::checksum; +use crate::{Error, Result}; use crate::wire::Ipv4Address; @@ -202,7 +202,8 @@ impl Repr { /// Parse an Internet Group Management Protocol v1/v2 packet and return /// a high-level representation. pub fn parse(packet: &Packet<&T>) -> Result - where T: AsRef<[u8]> + ?Sized + where + T: AsRef<[u8]> + ?Sized, { // Check if the address is 0.0.0.0 or multicast let addr = packet.group_addr(); @@ -226,13 +227,13 @@ impl Repr { version, }) } - Message::MembershipReportV2 => { - Ok(Repr::MembershipReport { - group_addr: packet.group_addr(), - version: IgmpVersion::Version2, - }) - } - Message::LeaveGroup => Ok(Repr::LeaveGroup { group_addr: packet.group_addr() }), + Message::MembershipReportV2 => Ok(Repr::MembershipReport { + group_addr: packet.group_addr(), + version: IgmpVersion::Version2, + }), + Message::LeaveGroup => Ok(Repr::LeaveGroup { + group_addr: packet.group_addr(), + }), Message::MembershipReportV1 => { // for backwards compatibility with IGMPv1 Ok(Repr::MembershipReport { @@ -252,20 +253,21 @@ impl Repr { /// Emit a high-level representation into an Internet Group Management Protocol v2 packet. pub fn emit(&self, packet: &mut Packet<&mut T>) - where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized + where + T: AsRef<[u8]> + AsMut<[u8]> + ?Sized, { match *self { Repr::MembershipQuery { max_resp_time, group_addr, - version + version, } => { packet.set_msg_type(Message::MembershipQuery); match version { - IgmpVersion::Version1 => - packet.set_max_resp_code(0), - IgmpVersion::Version2 => - packet.set_max_resp_code(duration_to_max_resp_code(max_resp_time)), + IgmpVersion::Version1 => packet.set_max_resp_code(0), + IgmpVersion::Version2 => { + packet.set_max_resp_code(duration_to_max_resp_code(max_resp_time)) + } } packet.set_group_address(group_addr); } @@ -336,20 +338,21 @@ impl<'a> fmt::Display for Repr { group_addr, version, } => { - write!(f, - "IGMP membership query max_resp_time={} group_addr={} version={:?}", - max_resp_time, - group_addr, - version) + write!( + f, + "IGMP membership query max_resp_time={} group_addr={} version={:?}", + max_resp_time, group_addr, version + ) } Repr::MembershipReport { group_addr, version, } => { - write!(f, - "IGMP membership report group_addr={} version={:?}", - group_addr, - version) + write!( + f, + "IGMP membership report group_addr={} version={:?}", + group_addr, version + ) } Repr::LeaveGroup { group_addr } => { write!(f, "IGMP leave group group_addr={})", group_addr) @@ -361,10 +364,11 @@ impl<'a> fmt::Display for Repr { use crate::wire::pretty_print::{PrettyIndent, PrettyPrint}; impl> PrettyPrint for Packet { - fn pretty_print(buffer: &dyn AsRef<[u8]>, - f: &mut fmt::Formatter, - indent: &mut PrettyIndent) - -> fmt::Result { + fn pretty_print( + buffer: &dyn AsRef<[u8]>, + f: &mut fmt::Formatter, + indent: &mut PrettyIndent, + ) -> fmt::Result { match Packet::new_checked(buffer) { Err(err) => writeln!(f, "{}({})", indent, err), Ok(packet) => writeln!(f, "{}{}", indent, packet), @@ -376,7 +380,6 @@ impl> PrettyPrint for Packet { mod test { use super::*; - static LEAVE_PACKET_BYTES: [u8; 8] = [0x17, 0x00, 0x02, 0x69, 0xe0, 0x00, 0x06, 0x96]; static REPORT_PACKET_BYTES: [u8; 8] = [0x16, 0x00, 0x08, 0xda, 0xe1, 0x00, 0x00, 0x25]; @@ -386,8 +389,10 @@ mod test { assert_eq!(packet.msg_type(), Message::LeaveGroup); assert_eq!(packet.max_resp_code(), 0); assert_eq!(packet.checksum(), 0x269); - assert_eq!(packet.group_addr(), - Ipv4Address::from_bytes(&[224, 0, 6, 150])); + assert_eq!( + packet.group_addr(), + Ipv4Address::from_bytes(&[224, 0, 6, 150]) + ); assert_eq!(packet.verify_checksum(), true); } @@ -397,8 +402,10 @@ mod test { assert_eq!(packet.msg_type(), Message::MembershipReportV2); assert_eq!(packet.max_resp_code(), 0); assert_eq!(packet.checksum(), 0x08da); - assert_eq!(packet.group_addr(), - Ipv4Address::from_bytes(&[225, 0, 0, 37])); + assert_eq!( + packet.group_addr(), + Ipv4Address::from_bytes(&[225, 0, 0, 37]) + ); assert_eq!(packet.verify_checksum(), true); } @@ -437,9 +444,7 @@ mod test { #[test] fn duration_to_max_resp_time_max() { for duration in 31744..65536 { - let time = duration_to_max_resp_code( - Duration::from_millis(duration * 100) - ); + let time = duration_to_max_resp_code(Duration::from_millis(duration * 100)); assert_eq!(time, 0xFF); } } diff --git a/src/wire/ip.rs b/src/wire/ip.rs index 67a25e3..3462841 100644 --- a/src/wire/ip.rs +++ b/src/wire/ip.rs @@ -1,12 +1,12 @@ -use core::fmt; use core::convert::From; +use core::fmt; -use crate::{Error, Result}; use crate::phy::ChecksumCapabilities; #[cfg(feature = "proto-ipv4")] -use crate::wire::{Ipv4Address, Ipv4Packet, Ipv4Repr, Ipv4Cidr}; +use crate::wire::{Ipv4Address, Ipv4Cidr, Ipv4Packet, Ipv4Repr}; #[cfg(feature = "proto-ipv6")] use crate::wire::{Ipv6Address, Ipv6Cidr, Ipv6Packet, Ipv6Repr}; +use crate::{Error, Result}; /// Internet protocol version. #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] @@ -31,7 +31,7 @@ impl Version { 4 => Ok(Version::Ipv4), #[cfg(feature = "proto-ipv6")] 6 => Ok(Version::Ipv6), - _ => Err(Error::Unrecognized) + _ => Err(Error::Unrecognized), } } } @@ -67,17 +67,17 @@ enum_with_unknown! { impl fmt::Display for Protocol { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Protocol::HopByHop => write!(f, "Hop-by-Hop"), - Protocol::Icmp => write!(f, "ICMP"), - Protocol::Igmp => write!(f, "IGMP"), - Protocol::Tcp => write!(f, "TCP"), - Protocol::Udp => write!(f, "UDP"), - Protocol::Ipv6Route => write!(f, "IPv6-Route"), - Protocol::Ipv6Frag => write!(f, "IPv6-Frag"), - Protocol::Icmpv6 => write!(f, "ICMPv6"), - Protocol::Ipv6NoNxt => write!(f, "IPv6-NoNxt"), - Protocol::Ipv6Opts => write!(f, "IPv6-Opts"), - Protocol::Unknown(id) => write!(f, "0x{:02x}", id) + Protocol::HopByHop => write!(f, "Hop-by-Hop"), + Protocol::Icmp => write!(f, "ICMP"), + Protocol::Igmp => write!(f, "IGMP"), + Protocol::Tcp => write!(f, "TCP"), + Protocol::Udp => write!(f, "UDP"), + Protocol::Ipv6Route => write!(f, "IPv6-Route"), + Protocol::Ipv6Frag => write!(f, "IPv6-Frag"), + Protocol::Icmpv6 => write!(f, "ICMPv6"), + Protocol::Ipv6NoNxt => write!(f, "IPv6-NoNxt"), + Protocol::Ipv6Opts => write!(f, "IPv6-Opts"), + Protocol::Unknown(id) => write!(f, "0x{:02x}", id), } } } @@ -107,74 +107,73 @@ impl Address { /// Create an address wrapping an IPv6 address with the given octets. #[cfg(feature = "proto-ipv6")] #[allow(clippy::too_many_arguments)] - pub fn v6(a0: u16, a1: u16, a2: u16, a3: u16, - a4: u16, a5: u16, a6: u16, a7: u16) -> Address { + pub fn v6(a0: u16, a1: u16, a2: u16, a3: u16, a4: u16, a5: u16, a6: u16, a7: u16) -> Address { Address::Ipv6(Ipv6Address::new(a0, a1, a2, a3, a4, a5, a6, a7)) } /// Return an address as a sequence of octets, in big-endian. pub fn as_bytes(&self) -> &[u8] { match *self { - Address::Unspecified => &[], + Address::Unspecified => &[], #[cfg(feature = "proto-ipv4")] - Address::Ipv4(ref addr) => addr.as_bytes(), + Address::Ipv4(ref addr) => addr.as_bytes(), #[cfg(feature = "proto-ipv6")] - Address::Ipv6(ref addr) => addr.as_bytes(), + Address::Ipv6(ref addr) => addr.as_bytes(), } } /// Query whether the address is a valid unicast address. pub fn is_unicast(&self) -> bool { match *self { - Address::Unspecified => false, + Address::Unspecified => false, #[cfg(feature = "proto-ipv4")] - Address::Ipv4(addr) => addr.is_unicast(), + Address::Ipv4(addr) => addr.is_unicast(), #[cfg(feature = "proto-ipv6")] - Address::Ipv6(addr) => addr.is_unicast(), + Address::Ipv6(addr) => addr.is_unicast(), } } /// Query whether the address is a valid multicast address. pub fn is_multicast(&self) -> bool { match *self { - Address::Unspecified => false, + Address::Unspecified => false, #[cfg(feature = "proto-ipv4")] - Address::Ipv4(addr) => addr.is_multicast(), + Address::Ipv4(addr) => addr.is_multicast(), #[cfg(feature = "proto-ipv6")] - Address::Ipv6(addr) => addr.is_multicast(), + Address::Ipv6(addr) => addr.is_multicast(), } } /// Query whether the address is the broadcast address. pub fn is_broadcast(&self) -> bool { match *self { - Address::Unspecified => false, + Address::Unspecified => false, #[cfg(feature = "proto-ipv4")] - Address::Ipv4(addr) => addr.is_broadcast(), + Address::Ipv4(addr) => addr.is_broadcast(), #[cfg(feature = "proto-ipv6")] - Address::Ipv6(_) => false, + Address::Ipv6(_) => false, } } /// Query whether the address falls into the "unspecified" range. pub fn is_unspecified(&self) -> bool { match *self { - Address::Unspecified => true, + Address::Unspecified => true, #[cfg(feature = "proto-ipv4")] - Address::Ipv4(addr) => addr.is_unspecified(), + Address::Ipv4(addr) => addr.is_unspecified(), #[cfg(feature = "proto-ipv6")] - Address::Ipv6(addr) => addr.is_unspecified(), + Address::Ipv6(addr) => addr.is_unspecified(), } } /// Return an unspecified address that has the same IP version as `self`. pub fn to_unspecified(&self) -> Address { match *self { - Address::Unspecified => Address::Unspecified, + Address::Unspecified => Address::Unspecified, #[cfg(feature = "proto-ipv4")] - Address::Ipv4(_) => Address::Ipv4(Ipv4Address::UNSPECIFIED), + Address::Ipv4(_) => Address::Ipv4(Ipv4Address::UNSPECIFIED), #[cfg(feature = "proto-ipv6")] - Address::Ipv6(_) => Address::Ipv6(Ipv6Address::UNSPECIFIED), + Address::Ipv6(_) => Address::Ipv6(Ipv6Address::UNSPECIFIED), } } @@ -196,7 +195,7 @@ impl Address { } } else if one { // 1 where 0 was expected - return None + return None; } mask >>= 1; } @@ -252,11 +251,11 @@ impl From for Address { impl fmt::Display for Address { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Address::Unspecified => write!(f, "*"), + Address::Unspecified => write!(f, "*"), #[cfg(feature = "proto-ipv4")] - Address::Ipv4(addr) => write!(f, "{}", addr), + Address::Ipv4(addr) => write!(f, "{}", addr), #[cfg(feature = "proto-ipv6")] - Address::Ipv6(addr) => write!(f, "{}", addr), + Address::Ipv6(addr) => write!(f, "{}", addr), } } } @@ -265,11 +264,11 @@ impl fmt::Display for Address { impl defmt::Format for Address { fn format(&self, f: defmt::Formatter) { match self { - &Address::Unspecified => defmt::write!(f, "{:?}", "*"), + &Address::Unspecified => defmt::write!(f, "{:?}", "*"), #[cfg(feature = "proto-ipv4")] - &Address::Ipv4(addr) => defmt::write!(f, "{:?}", addr), + &Address::Ipv4(addr) => defmt::write!(f, "{:?}", addr), #[cfg(feature = "proto-ipv6")] - &Address::Ipv6(addr) => defmt::write!(f, "{:?}", addr), + &Address::Ipv6(addr) => defmt::write!(f, "{:?}", addr), } } } @@ -297,8 +296,9 @@ impl Cidr { Address::Ipv4(addr) => Cidr::Ipv4(Ipv4Cidr::new(addr, prefix_len)), #[cfg(feature = "proto-ipv6")] Address::Ipv6(addr) => Cidr::Ipv6(Ipv6Cidr::new(addr, prefix_len)), - Address::Unspecified => - panic!("a CIDR block cannot be based on an unspecified address"), + Address::Unspecified => { + panic!("a CIDR block cannot be based on an unspecified address") + } } } @@ -306,9 +306,9 @@ impl Cidr { pub fn address(&self) -> Address { match *self { #[cfg(feature = "proto-ipv4")] - Cidr::Ipv4(cidr) => Address::Ipv4(cidr.address()), + Cidr::Ipv4(cidr) => Address::Ipv4(cidr.address()), #[cfg(feature = "proto-ipv6")] - Cidr::Ipv6(cidr) => Address::Ipv6(cidr.address()), + Cidr::Ipv6(cidr) => Address::Ipv6(cidr.address()), } } @@ -316,9 +316,9 @@ impl Cidr { pub fn prefix_len(&self) -> u8 { match *self { #[cfg(feature = "proto-ipv4")] - Cidr::Ipv4(cidr) => cidr.prefix_len(), + Cidr::Ipv4(cidr) => cidr.prefix_len(), #[cfg(feature = "proto-ipv6")] - Cidr::Ipv6(cidr) => cidr.prefix_len(), + Cidr::Ipv6(cidr) => cidr.prefix_len(), } } @@ -327,18 +327,17 @@ impl Cidr { pub fn contains_addr(&self, addr: &Address) -> bool { match (self, addr) { #[cfg(feature = "proto-ipv4")] - (&Cidr::Ipv4(ref cidr), &Address::Ipv4(ref addr)) => - cidr.contains_addr(addr), + (&Cidr::Ipv4(ref cidr), &Address::Ipv4(ref addr)) => cidr.contains_addr(addr), #[cfg(feature = "proto-ipv6")] - (&Cidr::Ipv6(ref cidr), &Address::Ipv6(ref addr)) => - cidr.contains_addr(addr), + (&Cidr::Ipv6(ref cidr), &Address::Ipv6(ref addr)) => cidr.contains_addr(addr), #[cfg(all(feature = "proto-ipv6", feature = "proto-ipv4"))] - (&Cidr::Ipv4(_), &Address::Ipv6(_)) | (&Cidr::Ipv6(_), &Address::Ipv4(_)) => - false, + (&Cidr::Ipv4(_), &Address::Ipv6(_)) | (&Cidr::Ipv6(_), &Address::Ipv4(_)) => false, (_, &Address::Unspecified) => - // a fully unspecified address covers both IPv4 and IPv6, - // and no CIDR block can do that. - false, + // a fully unspecified address covers both IPv4 and IPv6, + // and no CIDR block can do that. + { + false + } } } @@ -347,14 +346,11 @@ impl Cidr { pub fn contains_subnet(&self, subnet: &Cidr) -> bool { match (self, subnet) { #[cfg(feature = "proto-ipv4")] - (&Cidr::Ipv4(ref cidr), &Cidr::Ipv4(ref other)) => - cidr.contains_subnet(other), + (&Cidr::Ipv4(ref cidr), &Cidr::Ipv4(ref other)) => cidr.contains_subnet(other), #[cfg(feature = "proto-ipv6")] - (&Cidr::Ipv6(ref cidr), &Cidr::Ipv6(ref other)) => - cidr.contains_subnet(other), + (&Cidr::Ipv6(ref cidr), &Cidr::Ipv6(ref other)) => cidr.contains_subnet(other), #[cfg(all(feature = "proto-ipv6", feature = "proto-ipv4"))] - (&Cidr::Ipv4(_), &Cidr::Ipv6(_)) | (&Cidr::Ipv6(_), &Cidr::Ipv4(_)) => - false, + (&Cidr::Ipv4(_), &Cidr::Ipv6(_)) | (&Cidr::Ipv6(_), &Cidr::Ipv4(_)) => false, } } } @@ -377,9 +373,9 @@ impl fmt::Display for Cidr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { #[cfg(feature = "proto-ipv4")] - Cidr::Ipv4(cidr) => write!(f, "{}", cidr), + Cidr::Ipv4(cidr) => write!(f, "{}", cidr), #[cfg(feature = "proto-ipv6")] - Cidr::Ipv6(cidr) => write!(f, "{}", cidr), + Cidr::Ipv6(cidr) => write!(f, "{}", cidr), } } } @@ -389,9 +385,9 @@ impl defmt::Format for Cidr { fn format(&self, f: defmt::Formatter) { match self { #[cfg(feature = "proto-ipv4")] - &Cidr::Ipv4(cidr) => defmt::write!(f, "{:?}", cidr), + &Cidr::Ipv4(cidr) => defmt::write!(f, "{:?}", cidr), #[cfg(feature = "proto-ipv6")] - &Cidr::Ipv6(cidr) => defmt::write!(f, "{:?}", cidr), + &Cidr::Ipv6(cidr) => defmt::write!(f, "{:?}", cidr), } } } @@ -402,12 +398,15 @@ impl defmt::Format for Cidr { #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)] pub struct Endpoint { pub addr: Address, - pub port: u16 + pub port: u16, } impl Endpoint { /// An endpoint with unspecified address and port. - pub const UNSPECIFIED: Endpoint = Endpoint { addr: Address::Unspecified, port: 0 }; + pub const UNSPECIFIED: Endpoint = Endpoint { + addr: Address::Unspecified, + port: 0, + }; /// Create an endpoint address from given address and port. pub fn new(addr: Address, port: u16) -> Endpoint { @@ -465,13 +464,19 @@ impl defmt::Format for Endpoint { impl From for Endpoint { fn from(port: u16) -> Endpoint { - Endpoint { addr: Address::Unspecified, port } + Endpoint { + addr: Address::Unspecified, + port, + } } } impl> From<(T, u16)> for Endpoint { fn from((addr, port): (T, u16)) -> Endpoint { - Endpoint { addr: addr.into(), port } + Endpoint { + addr: addr.into(), + port, + } } } @@ -485,11 +490,11 @@ impl> From<(T, u16)> for Endpoint { #[non_exhaustive] pub enum Repr { Unspecified { - src_addr: Address, - dst_addr: Address, - protocol: Protocol, + src_addr: Address, + dst_addr: Address, + protocol: Protocol, payload_len: usize, - hop_limit: u8 + hop_limit: u8, }, #[cfg(feature = "proto-ipv4")] Ipv4(Ipv4Repr), @@ -570,25 +575,31 @@ impl Repr { /// Set the payload length. pub fn set_payload_len(&mut self, length: usize) { match *self { - Repr::Unspecified { ref mut payload_len, .. } => - *payload_len = length, + Repr::Unspecified { + ref mut payload_len, + .. + } => *payload_len = length, #[cfg(feature = "proto-ipv4")] - Repr::Ipv4(Ipv4Repr { ref mut payload_len, .. }) => - *payload_len = length, + Repr::Ipv4(Ipv4Repr { + ref mut payload_len, + .. + }) => *payload_len = length, #[cfg(feature = "proto-ipv6")] - Repr::Ipv6(Ipv6Repr { ref mut payload_len, .. }) => - *payload_len = length, + Repr::Ipv6(Ipv6Repr { + ref mut payload_len, + .. + }) => *payload_len = length, } } /// Return the TTL value. pub fn hop_limit(&self) -> u8 { match *self { - Repr::Unspecified { hop_limit, .. } => hop_limit, + Repr::Unspecified { hop_limit, .. } => hop_limit, #[cfg(feature = "proto-ipv4")] Repr::Ipv4(Ipv4Repr { hop_limit, .. }) => hop_limit, #[cfg(feature = "proto-ipv6")] - Repr::Ipv6(Ipv6Repr { hop_limit, ..}) => hop_limit, + Repr::Ipv6(Ipv6Repr { hop_limit, .. }) => hop_limit, } } @@ -607,15 +618,15 @@ impl Repr { $ipty(addr) => { $iprepr.src_addr = addr; return Ok($reprty($iprepr)); - }, - _ => () + } + _ => (), } } Err(Error::Unaddressable) } else { Ok($reprty($iprepr)) } - } + }; } match self { @@ -623,12 +634,16 @@ impl Repr { &Repr::Unspecified { src_addr: src_addr @ Address::Unspecified, dst_addr: Address::Ipv4(dst_addr), - protocol, payload_len, hop_limit - } | - &Repr::Unspecified { + protocol, + payload_len, + hop_limit, + } + | &Repr::Unspecified { src_addr: src_addr @ Address::Ipv4(_), dst_addr: Address::Ipv4(dst_addr), - protocol, payload_len, hop_limit + protocol, + payload_len, + hop_limit, } if src_addr.is_unspecified() => { let mut src_addr = if let Address::Ipv4(src_ipv4_addr) = src_addr { Some(src_ipv4_addr) @@ -642,8 +657,11 @@ impl Repr { } } Ok(Repr::Ipv4(Ipv4Repr { - src_addr: src_addr.ok_or(Error::Unaddressable)?, - dst_addr, protocol, payload_len, hop_limit + src_addr: src_addr.ok_or(Error::Unaddressable)?, + dst_addr, + protocol, + payload_len, + hop_limit, })) } @@ -651,12 +669,16 @@ impl Repr { &Repr::Unspecified { src_addr: src_addr @ Address::Unspecified, dst_addr: Address::Ipv6(dst_addr), - protocol, payload_len, hop_limit - } | - &Repr::Unspecified { + protocol, + payload_len, + hop_limit, + } + | &Repr::Unspecified { src_addr: src_addr @ Address::Ipv6(_), dst_addr: Address::Ipv6(dst_addr), - protocol, payload_len, hop_limit + protocol, + payload_len, + hop_limit, } if src_addr.is_unspecified() => { let mut src_addr = if let Address::Ipv6(src_ipv6_addr) = src_addr { Some(src_ipv6_addr) @@ -670,9 +692,11 @@ impl Repr { } } Ok(Repr::Ipv6(Ipv6Repr { - src_addr: src_addr.ok_or(Error::Unaddressable)?, + src_addr: src_addr.ok_or(Error::Unaddressable)?, next_header: protocol, - dst_addr, payload_len, hop_limit + dst_addr, + payload_len, + hop_limit, })) } @@ -680,41 +704,45 @@ impl Repr { &Repr::Unspecified { src_addr: Address::Ipv4(src_addr), dst_addr: Address::Ipv4(dst_addr), - protocol, payload_len, hop_limit - } => { - Ok(Repr::Ipv4(Ipv4Repr { - src_addr: src_addr, - dst_addr: dst_addr, - protocol: protocol, - payload_len: payload_len, hop_limit - })) - } + protocol, + payload_len, + hop_limit, + } => Ok(Repr::Ipv4(Ipv4Repr { + src_addr: src_addr, + dst_addr: dst_addr, + protocol: protocol, + payload_len: payload_len, + hop_limit, + })), #[cfg(feature = "proto-ipv6")] &Repr::Unspecified { src_addr: Address::Ipv6(src_addr), dst_addr: Address::Ipv6(dst_addr), - protocol, payload_len, hop_limit - } => { - Ok(Repr::Ipv6(Ipv6Repr { - src_addr: src_addr, - dst_addr: dst_addr, - next_header: protocol, - payload_len: payload_len, - hop_limit: hop_limit - })) - } + protocol, + payload_len, + hop_limit, + } => Ok(Repr::Ipv6(Ipv6Repr { + src_addr: src_addr, + dst_addr: dst_addr, + next_header: protocol, + payload_len: payload_len, + hop_limit: hop_limit, + })), #[cfg(feature = "proto-ipv4")] - &Repr::Ipv4(mut repr) => - resolve_unspecified!(Repr::Ipv4, Address::Ipv4, repr, fallback_src_addrs), + &Repr::Ipv4(mut repr) => { + resolve_unspecified!(Repr::Ipv4, Address::Ipv4, repr, fallback_src_addrs) + } #[cfg(feature = "proto-ipv6")] - &Repr::Ipv6(mut repr) => - resolve_unspecified!(Repr::Ipv6, Address::Ipv6, repr, fallback_src_addrs), + &Repr::Ipv6(mut repr) => { + resolve_unspecified!(Repr::Ipv6, Address::Ipv6, repr, fallback_src_addrs) + } - &Repr::Unspecified { .. } => - panic!("source and destination IP address families do not match"), + &Repr::Unspecified { .. } => { + panic!("source and destination IP address families do not match") + } } } @@ -724,14 +752,11 @@ impl Repr { /// This function panics if invoked on an unspecified representation. pub fn buffer_len(&self) -> usize { match *self { - Repr::Unspecified { .. } => - panic!("unspecified IP representation"), + Repr::Unspecified { .. } => panic!("unspecified IP representation"), #[cfg(feature = "proto-ipv4")] - Repr::Ipv4(repr) => - repr.buffer_len(), + Repr::Ipv4(repr) => repr.buffer_len(), #[cfg(feature = "proto-ipv6")] - Repr::Ipv6(repr) => - repr.buffer_len(), + Repr::Ipv6(repr) => repr.buffer_len(), } } @@ -739,16 +764,17 @@ impl Repr { /// /// # Panics /// This function panics if invoked on an unspecified representation. - pub fn emit + AsMut<[u8]>>(&self, buffer: T, _checksum_caps: &ChecksumCapabilities) { + pub fn emit + AsMut<[u8]>>( + &self, + buffer: T, + _checksum_caps: &ChecksumCapabilities, + ) { match *self { - Repr::Unspecified { .. } => - panic!("unspecified IP representation"), + Repr::Unspecified { .. } => panic!("unspecified IP representation"), #[cfg(feature = "proto-ipv4")] - Repr::Ipv4(repr) => - repr.emit(&mut Ipv4Packet::new_unchecked(buffer), &_checksum_caps), + Repr::Ipv4(repr) => repr.emit(&mut Ipv4Packet::new_unchecked(buffer), &_checksum_caps), #[cfg(feature = "proto-ipv6")] - Repr::Ipv6(repr) => - repr.emit(&mut Ipv6Packet::new_unchecked(buffer)), + Repr::Ipv6(repr) => repr.emit(&mut Ipv6Packet::new_unchecked(buffer)), } } @@ -816,8 +842,12 @@ pub mod checksum { } /// Compute an IP pseudo header checksum. - pub fn pseudo_header(src_addr: &Address, dst_addr: &Address, - protocol: Protocol, length: u32) -> u16 { + pub fn pseudo_header( + src_addr: &Address, + dst_addr: &Address, + protocol: Protocol, + length: u32, + ) -> u16 { match (src_addr, dst_addr) { #[cfg(feature = "proto-ipv4")] (&Address::Ipv4(src_addr), &Address::Ipv4(dst_addr)) => { @@ -828,9 +858,9 @@ pub mod checksum { combine(&[ data(src_addr.as_bytes()), data(dst_addr.as_bytes()), - data(&proto_len[..]) + data(&proto_len[..]), ]) - }, + } #[cfg(feature = "proto-ipv6")] (&Address::Ipv6(src_addr), &Address::Ipv6(dst_addr)) => { @@ -840,12 +870,14 @@ pub mod checksum { combine(&[ data(src_addr.as_bytes()), data(dst_addr.as_bytes()), - data(&proto_len[..]) + data(&proto_len[..]), ]) } - _ => panic!("Unexpected pseudo header addresses: {}, {}", - src_addr, dst_addr) + _ => panic!( + "Unexpected pseudo header addresses: {}, {}", + src_addr, dst_addr + ), } } @@ -861,14 +893,18 @@ pub mod checksum { use crate::wire::pretty_print::PrettyIndent; -pub fn pretty_print_ip_payload>(f: &mut fmt::Formatter, indent: &mut PrettyIndent, - ip_repr: T, payload: &[u8]) -> fmt::Result { - #[cfg(feature = "proto-ipv4")] - use crate::wire::Icmpv4Packet; +pub fn pretty_print_ip_payload>( + f: &mut fmt::Formatter, + indent: &mut PrettyIndent, + ip_repr: T, + payload: &[u8], +) -> fmt::Result { #[cfg(feature = "proto-ipv4")] use super::pretty_print::PrettyPrint; - use crate::wire::{TcpPacket, TcpRepr, UdpPacket, UdpRepr}; use crate::wire::ip::checksum::format_checksum; + #[cfg(feature = "proto-ipv4")] + use crate::wire::Icmpv4Packet; + use crate::wire::{TcpPacket, TcpRepr, UdpPacket, UdpRepr}; let checksum_caps = ChecksumCapabilities::ignored(); let repr = ip_repr.into(); @@ -883,13 +919,23 @@ pub fn pretty_print_ip_payload>(f: &mut fmt::Formatter, indent: &m match UdpPacket::<&[u8]>::new_checked(payload) { Err(err) => write!(f, "{}({})", indent, err), Ok(udp_packet) => { - match UdpRepr::parse(&udp_packet, &repr.src_addr(), - &repr.dst_addr(), &checksum_caps) { + match UdpRepr::parse( + &udp_packet, + &repr.src_addr(), + &repr.dst_addr(), + &checksum_caps, + ) { Err(err) => write!(f, "{}{} ({})", indent, udp_packet, err), Ok(udp_repr) => { - write!(f, "{}{} len={}", indent, udp_repr, udp_packet.payload().len())?; - let valid = udp_packet.verify_checksum(&repr.src_addr(), - &repr.dst_addr()); + write!( + f, + "{}{} len={}", + indent, + udp_repr, + udp_packet.payload().len() + )?; + let valid = + udp_packet.verify_checksum(&repr.src_addr(), &repr.dst_addr()); format_checksum(f, valid) } } @@ -901,20 +947,24 @@ pub fn pretty_print_ip_payload>(f: &mut fmt::Formatter, indent: &m match TcpPacket::<&[u8]>::new_checked(payload) { Err(err) => write!(f, "{}({})", indent, err), Ok(tcp_packet) => { - match TcpRepr::parse(&tcp_packet, &repr.src_addr(), - &repr.dst_addr(), &checksum_caps) { + match TcpRepr::parse( + &tcp_packet, + &repr.src_addr(), + &repr.dst_addr(), + &checksum_caps, + ) { Err(err) => write!(f, "{}{} ({})", indent, tcp_packet, err), Ok(tcp_repr) => { write!(f, "{}{}", indent, tcp_repr)?; - let valid = tcp_packet.verify_checksum(&repr.src_addr(), - &repr.dst_addr()); + let valid = + tcp_packet.verify_checksum(&repr.src_addr(), &repr.dst_addr()); format_checksum(f, valid) } } } } } - _ => Ok(()) + _ => Ok(()), } } @@ -923,17 +973,21 @@ pub(crate) mod test { #![allow(unused)] #[cfg(feature = "proto-ipv6")] - pub(crate) const MOCK_IP_ADDR_1: IpAddress = IpAddress::Ipv6(Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1])); + pub(crate) const MOCK_IP_ADDR_1: IpAddress = IpAddress::Ipv6(Ipv6Address([ + 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + ])); #[cfg(feature = "proto-ipv6")] - pub(crate) const MOCK_IP_ADDR_2: IpAddress = IpAddress::Ipv6(Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2])); + pub(crate) const MOCK_IP_ADDR_2: IpAddress = IpAddress::Ipv6(Ipv6Address([ + 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + ])); #[cfg(feature = "proto-ipv6")] - pub(crate) const MOCK_IP_ADDR_3: IpAddress = IpAddress::Ipv6(Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3])); + pub(crate) const MOCK_IP_ADDR_3: IpAddress = IpAddress::Ipv6(Ipv6Address([ + 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + ])); #[cfg(feature = "proto-ipv6")] - pub(crate) const MOCK_IP_ADDR_4: IpAddress = IpAddress::Ipv6(Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4])); + pub(crate) const MOCK_IP_ADDR_4: IpAddress = IpAddress::Ipv6(Ipv6Address([ + 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + ])); #[cfg(feature = "proto-ipv6")] pub(crate) const MOCK_UNSPECIFIED: IpAddress = IpAddress::Ipv6(Ipv6Address::UNSPECIFIED); @@ -948,9 +1002,8 @@ pub(crate) mod test { #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))] pub(crate) const MOCK_UNSPECIFIED: IpAddress = IpAddress::Ipv4(Ipv4Address::UNSPECIFIED); - use super::*; - use crate::wire::{IpAddress, IpProtocol,IpCidr}; + use crate::wire::{IpAddress, IpCidr, IpProtocol}; #[cfg(feature = "proto-ipv4")] use crate::wire::{Ipv4Address, Ipv4Repr}; @@ -969,124 +1022,132 @@ pub(crate) mod test { let payload_len = 10; assert_eq!( - Repr::Unspecified{ - src_addr: $ip_addr(ip_addr_a), - dst_addr: $ip_addr(ip_addr_b), - protocol: proto, + Repr::Unspecified { + src_addr: $ip_addr(ip_addr_a), + dst_addr: $ip_addr(ip_addr_b), + protocol: proto, hop_limit: 0x2a, payload_len, - }.lower(&[]), - Ok($ip_repr($repr{ - src_addr: ip_addr_a, - dst_addr: ip_addr_b, - $nxthdr: proto, + } + .lower(&[]), + Ok($ip_repr($repr { + src_addr: ip_addr_a, + dst_addr: ip_addr_b, + $nxthdr: proto, hop_limit: 0x2a, payload_len })) ); assert_eq!( - Repr::Unspecified{ - src_addr: IpAddress::Unspecified, - dst_addr: $ip_addr(ip_addr_b), - protocol: proto, + Repr::Unspecified { + src_addr: IpAddress::Unspecified, + dst_addr: $ip_addr(ip_addr_b), + protocol: proto, hop_limit: 64, payload_len - }.lower(&[]), + } + .lower(&[]), Err(Error::Unaddressable) ); assert_eq!( - Repr::Unspecified{ - src_addr: IpAddress::Unspecified, - dst_addr: $ip_addr(ip_addr_b), - protocol: proto, + Repr::Unspecified { + src_addr: IpAddress::Unspecified, + dst_addr: $ip_addr(ip_addr_b), + protocol: proto, hop_limit: 64, payload_len - }.lower(&[IpCidr::new($ip_addr(ip_addr_a), 24)]), - Ok($ip_repr($repr{ - src_addr: ip_addr_a, - dst_addr: ip_addr_b, - $nxthdr: proto, + } + .lower(&[IpCidr::new($ip_addr(ip_addr_a), 24)]), + Ok($ip_repr($repr { + src_addr: ip_addr_a, + dst_addr: ip_addr_b, + $nxthdr: proto, hop_limit: 64, payload_len })) ); assert_eq!( - Repr::Unspecified{ - src_addr: $ip_addr($unspecified), - dst_addr: $ip_addr(ip_addr_b), - protocol: proto, + Repr::Unspecified { + src_addr: $ip_addr($unspecified), + dst_addr: $ip_addr(ip_addr_b), + protocol: proto, hop_limit: 64, payload_len - }.lower(&[IpCidr::new($ip_addr(ip_addr_a), 24)]), - Ok($ip_repr($repr{ - src_addr: ip_addr_a, - dst_addr: ip_addr_b, - $nxthdr: proto, + } + .lower(&[IpCidr::new($ip_addr(ip_addr_a), 24)]), + Ok($ip_repr($repr { + src_addr: ip_addr_a, + dst_addr: ip_addr_b, + $nxthdr: proto, hop_limit: 64, payload_len })) ); assert_eq!( - Repr::Unspecified{ - src_addr: $ip_addr($unspecified), - dst_addr: $ip_addr(ip_addr_b), - protocol: proto, + Repr::Unspecified { + src_addr: $ip_addr($unspecified), + dst_addr: $ip_addr(ip_addr_b), + protocol: proto, hop_limit: 64, payload_len - }.lower(&[]), - Ok($ip_repr($repr{ - src_addr: $unspecified, - dst_addr: ip_addr_b, - $nxthdr: proto, + } + .lower(&[]), + Ok($ip_repr($repr { + src_addr: $unspecified, + dst_addr: ip_addr_b, + $nxthdr: proto, hop_limit: 64, payload_len })) ); assert_eq!( - $ip_repr($repr{ - src_addr: ip_addr_a, - dst_addr: ip_addr_b, - $nxthdr: proto, + $ip_repr($repr { + src_addr: ip_addr_a, + dst_addr: ip_addr_b, + $nxthdr: proto, hop_limit: 255, payload_len - }).lower(&[]), - Ok($ip_repr($repr{ - src_addr: ip_addr_a, - dst_addr: ip_addr_b, - $nxthdr: proto, + }) + .lower(&[]), + Ok($ip_repr($repr { + src_addr: ip_addr_a, + dst_addr: ip_addr_b, + $nxthdr: proto, hop_limit: 255, payload_len })) ); assert_eq!( - $ip_repr($repr{ - src_addr: $unspecified, - dst_addr: ip_addr_b, - $nxthdr: proto, + $ip_repr($repr { + src_addr: $unspecified, + dst_addr: ip_addr_b, + $nxthdr: proto, hop_limit: 255, payload_len - }).lower(&[]), + }) + .lower(&[]), Err(Error::Unaddressable) ); assert_eq!( - $ip_repr($repr{ - src_addr: $unspecified, - dst_addr: ip_addr_b, - $nxthdr: proto, + $ip_repr($repr { + src_addr: $unspecified, + dst_addr: ip_addr_b, + $nxthdr: proto, hop_limit: 64, payload_len - }).lower(&[IpCidr::new($ip_addr(ip_addr_a), 24)]), - Ok($ip_repr($repr{ - src_addr: ip_addr_a, - dst_addr: ip_addr_b, - $nxthdr: proto, + }) + .lower(&[IpCidr::new($ip_addr(ip_addr_a), 24)]), + Ok($ip_repr($repr { + src_addr: ip_addr_a, + dst_addr: ip_addr_b, + $nxthdr: proto, hop_limit: 64, payload_len })) @@ -1095,15 +1156,31 @@ pub(crate) mod test { } }; (ipv4 $addr_bytes_a:expr, $addr_bytes_b:expr) => { - generate_common_tests!(ipv4, Ipv4Repr, Repr::Ipv4, IpAddress::Ipv4, - Ipv4Address::from_bytes, protocol, $addr_bytes_a, - $addr_bytes_b, Ipv4Address::UNSPECIFIED); + generate_common_tests!( + ipv4, + Ipv4Repr, + Repr::Ipv4, + IpAddress::Ipv4, + Ipv4Address::from_bytes, + protocol, + $addr_bytes_a, + $addr_bytes_b, + Ipv4Address::UNSPECIFIED + ); }; (ipv6 $addr_bytes_a:expr, $addr_bytes_b:expr) => { - generate_common_tests!(ipv6, Ipv6Repr, Repr::Ipv6, IpAddress::Ipv6, - Ipv6Address::from_bytes, next_header, $addr_bytes_a, - $addr_bytes_b, Ipv6Address::UNSPECIFIED); - } + generate_common_tests!( + ipv6, + Ipv6Repr, + Repr::Ipv6, + IpAddress::Ipv6, + Ipv6Address::from_bytes, + next_header, + $addr_bytes_a, + $addr_bytes_b, + Ipv6Address::UNSPECIFIED + ); + }; } #[cfg(feature = "proto-ipv4")] @@ -1121,12 +1198,13 @@ pub(crate) mod test { #[should_panic(expected = "source and destination IP address families do not match")] fn test_lower_between_families() { Repr::Unspecified { - src_addr: Address::Ipv6(Ipv6Address::UNSPECIFIED), - dst_addr: Address::Ipv4(Ipv4Address::UNSPECIFIED), - protocol: IpProtocol::Icmpv6, + src_addr: Address::Ipv6(Ipv6Address::UNSPECIFIED), + dst_addr: Address::Ipv4(Ipv4Address::UNSPECIFIED), + protocol: IpProtocol::Icmpv6, hop_limit: 0xff, - payload_len: 0 - }.lower(&[]); + payload_len: 0, + } + .lower(&[]); } #[test] @@ -1138,10 +1216,7 @@ pub(crate) mod test { #[cfg(feature = "proto-ipv4")] fn to_prefix_len_ipv4() { fn test_eq>(prefix_len: u8, mask: A) { - assert_eq!( - Some(prefix_len), - mask.into().to_prefix_len() - ); + assert_eq!(Some(prefix_len), mask.into().to_prefix_len()); } test_eq(0, Ipv4Address::new(0, 0, 0, 0)); @@ -1181,25 +1256,36 @@ pub(crate) mod test { #[cfg(feature = "proto-ipv4")] fn to_prefix_len_ipv4_error() { - assert_eq!(None, IpAddress::from(Ipv4Address::new(255,255,255,1)).to_prefix_len()); + assert_eq!( + None, + IpAddress::from(Ipv4Address::new(255, 255, 255, 1)).to_prefix_len() + ); } #[test] #[cfg(feature = "proto-ipv6")] fn to_prefix_len_ipv6() { fn test_eq>(prefix_len: u8, mask: A) { - assert_eq!( - Some(prefix_len), - mask.into().to_prefix_len() - ); + assert_eq!(Some(prefix_len), mask.into().to_prefix_len()); } test_eq(0, Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, 0)); - test_eq(128, Ipv6Address::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff)); + test_eq( + 128, + Ipv6Address::new( + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + ), + ); } #[cfg(feature = "proto-ipv6")] fn to_prefix_len_ipv6_error() { - assert_eq!(None, IpAddress::from(Ipv6Address::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0, 1)).to_prefix_len()); + assert_eq!( + None, + IpAddress::from(Ipv6Address::new( + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0, 1 + )) + .to_prefix_len() + ); } } diff --git a/src/wire/ipv4.rs b/src/wire/ipv4.rs index 221d656..bdadc99 100644 --- a/src/wire/ipv4.rs +++ b/src/wire/ipv4.rs @@ -1,9 +1,9 @@ -use core::fmt; use byteorder::{ByteOrder, NetworkEndian}; +use core::fmt; -use crate::{Error, Result}; use crate::phy::ChecksumCapabilities; use crate::wire::ip::{checksum, pretty_print_ip_payload}; +use crate::{Error, Result}; pub use super::IpProtocol as Protocol; @@ -27,10 +27,10 @@ pub struct Address(pub [u8; 4]); impl Address { /// An unspecified address. - pub const UNSPECIFIED: Address = Address([0x00; 4]); + pub const UNSPECIFIED: Address = Address([0x00; 4]); /// The broadcast address. - pub const BROADCAST: Address = Address([0xff; 4]); + pub const BROADCAST: Address = Address([0xff; 4]); /// All multicast-capable nodes pub const MULTICAST_ALL_SYSTEMS: Address = Address([224, 0, 0, 1]); @@ -60,9 +60,7 @@ impl Address { /// Query whether the address is an unicast address. pub fn is_unicast(&self) -> bool { - !(self.is_broadcast() || - self.is_multicast() || - self.is_unspecified()) + !(self.is_broadcast() || self.is_multicast() || self.is_unspecified()) } /// Query whether the address is the broadcast address. @@ -115,7 +113,14 @@ impl fmt::Display for Address { #[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]) + defmt::write!( + f, + "{=u8}.{=u8}.{=u8}.{=u8}", + self.0[0], + self.0[1], + self.0[2], + self.0[3] + ) } } @@ -123,7 +128,7 @@ impl defmt::Format for Address { /// subnet masking prefix length. #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)] pub struct Cidr { - address: Address, + address: Address, prefix_len: u8, } @@ -137,14 +142,20 @@ impl Cidr { // Replace with const panic (or assert) when stabilized // see: https://github.com/rust-lang/rust/issues/51999 ["Prefix length should be <= 32"][(prefix_len > 32) as usize]; - Cidr { address, prefix_len } + Cidr { + address, + prefix_len, + } } /// 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[..]); if netmask.leading_zeros() == 0 && netmask.trailing_zeros() == netmask.count_zeros() { - Ok(Cidr { address: addr, prefix_len: netmask.count_ones() as u8 }) + Ok(Cidr { + address: addr, + prefix_len: netmask.count_ones() as u8, + }) } else { Err(Error::Illegal) } @@ -170,8 +181,8 @@ impl Cidr { let data = [ ((number >> 24) & 0xff) as u8, ((number >> 16) & 0xff) as u8, - ((number >> 8) & 0xff) as u8, - ((number >> 0) & 0xff) as u8, + ((number >> 8) & 0xff) as u8, + ((number >> 0) & 0xff) as u8, ]; Address(data) @@ -190,8 +201,8 @@ impl Cidr { let data = [ ((number >> 24) & 0xff) as u8, ((number >> 16) & 0xff) as u8, - ((number >> 8) & 0xff) as u8, - ((number >> 0) & 0xff) as u8, + ((number >> 8) & 0xff) as u8, + ((number >> 0) & 0xff) as u8, ]; Some(Address(data)) @@ -206,14 +217,19 @@ impl Cidr { self.address.0[2] & mask[2], self.address.0[3] & mask[3], ]; - Cidr { address: Address(network), prefix_len: self.prefix_len } + Cidr { + address: Address(network), + prefix_len: self.prefix_len, + } } /// 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 } + if self.prefix_len == 0 { + return true; + } let shift = 32 - self.prefix_len; let self_prefix = NetworkEndian::read_u32(self.address.as_bytes()) >> shift; @@ -245,18 +261,18 @@ impl defmt::Format for Cidr { #[derive(Debug, PartialEq, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { - buffer: T + buffer: T, } mod field { use crate::wire::field::*; - pub const VER_IHL: usize = 0; + pub const VER_IHL: usize = 0; pub const DSCP_ECN: usize = 1; - pub const LENGTH: Field = 2..4; - pub const IDENT: Field = 4..6; - pub const FLG_OFF: Field = 6..8; - pub const TTL: usize = 8; + pub const LENGTH: Field = 2..4; + pub const IDENT: Field = 4..6; + pub const FLG_OFF: Field = 6..8; + pub const TTL: usize = 8; pub const PROTOCOL: usize = 9; pub const CHECKSUM: Field = 10..12; pub const SRC_ADDR: Field = 12..16; @@ -265,7 +281,6 @@ mod field { pub const HEADER_LEN: usize = field::DST_ADDR.end; - impl> Packet { /// Imbue a raw octet buffer with IPv4 packet structure. pub fn new_unchecked(buffer: T) -> Packet { @@ -414,7 +429,9 @@ impl> Packet { /// # Fuzzing /// This function always returns `true` when fuzzing. pub fn verify_checksum(&self) -> bool { - if cfg!(fuzzing) { return true } + if cfg!(fuzzing) { + return true; + } let data = self.buffer.as_ref(); checksum::data(&data[..self.header_len() as usize]) == !0 @@ -572,36 +589,46 @@ impl> AsRef<[u8]> for Packet { #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Repr { - pub src_addr: Address, - pub dst_addr: Address, - pub protocol: Protocol, + pub src_addr: Address, + pub dst_addr: Address, + pub protocol: Protocol, pub payload_len: usize, - pub hop_limit: u8 + pub hop_limit: u8, } impl Repr { /// Parse an Internet Protocol version 4 packet and return a high-level representation. - pub fn parse + ?Sized>(packet: &Packet<&T>, - checksum_caps: &ChecksumCapabilities) -> Result { + pub fn parse + ?Sized>( + packet: &Packet<&T>, + checksum_caps: &ChecksumCapabilities, + ) -> Result { // Version 4 is expected. - if packet.version() != 4 { return Err(Error::Malformed) } + if packet.version() != 4 { + return Err(Error::Malformed); + } // Valid checksum is expected. - if checksum_caps.ipv4.rx() && !packet.verify_checksum() { return Err(Error::Checksum) } + if checksum_caps.ipv4.rx() && !packet.verify_checksum() { + return Err(Error::Checksum); + } // We do not support fragmentation. - if packet.more_frags() || packet.frag_offset() != 0 { return Err(Error::Fragmented) } + if packet.more_frags() || packet.frag_offset() != 0 { + return Err(Error::Fragmented); + } // Since the packet is not fragmented, it must include the entire payload. let payload_len = packet.total_len() as usize - packet.header_len() as usize; - if packet.payload().len() < payload_len { return Err(Error::Truncated) } + if packet.payload().len() < payload_len { + return Err(Error::Truncated); + } // All DSCP values are acceptable, since they are of no concern to receiving endpoint. // All ECN values are acceptable, since ECN requires opt-in from both endpoints. // All TTL values are acceptable, since we do not perform routing. Ok(Repr { - src_addr: packet.src_addr(), - dst_addr: packet.dst_addr(), - protocol: packet.protocol(), + src_addr: packet.src_addr(), + dst_addr: packet.dst_addr(), + protocol: packet.protocol(), payload_len: payload_len, - hop_limit: packet.hop_limit() + hop_limit: packet.hop_limit(), }) } @@ -612,7 +639,11 @@ impl Repr { } /// Emit a high-level representation into an Internet Protocol version 4 packet. - pub fn emit + AsMut<[u8]>>(&self, packet: &mut Packet, checksum_caps: &ChecksumCapabilities) { + pub fn emit + AsMut<[u8]>>( + &self, + packet: &mut Packet, + checksum_caps: &ChecksumCapabilities, + ) { packet.set_version(4); packet.set_header_len(field::DST_ADDR.end as u8); packet.set_dscp(0); @@ -645,8 +676,14 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> { Ok(repr) => write!(f, "{}", repr), Err(err) => { write!(f, "IPv4 ({})", err)?; - write!(f, " src={} dst={} proto={} hop_limit={}", - self.src_addr(), self.dst_addr(), self.protocol(), self.hop_limit())?; + write!( + f, + " src={} dst={} proto={} hop_limit={}", + self.src_addr(), + self.dst_addr(), + self.protocol(), + self.hop_limit() + )?; if self.version() != 4 { write!(f, " ver={}", self.version())?; } @@ -680,32 +717,36 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> { impl fmt::Display for Repr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "IPv4 src={} dst={} proto={}", - self.src_addr, self.dst_addr, self.protocol) + write!( + f, + "IPv4 src={} dst={} proto={}", + self.src_addr, self.dst_addr, self.protocol + ) } } -use crate::wire::pretty_print::{PrettyPrint, PrettyIndent}; +use crate::wire::pretty_print::{PrettyIndent, PrettyPrint}; impl> PrettyPrint for Packet { - fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter, - indent: &mut PrettyIndent) -> fmt::Result { + fn pretty_print( + buffer: &dyn AsRef<[u8]>, + f: &mut fmt::Formatter, + indent: &mut PrettyIndent, + ) -> fmt::Result { use crate::wire::ip::checksum::format_checksum; let checksum_caps = ChecksumCapabilities::ignored(); let (ip_repr, payload) = match Packet::new_checked(buffer) { Err(err) => return write!(f, "{}({})", indent, err), - Ok(ip_packet) => { - match Repr::parse(&ip_packet, &checksum_caps) { - Err(_) => return Ok(()), - Ok(ip_repr) => { - write!(f, "{}{}", indent, ip_repr)?; - format_checksum(f, ip_packet.verify_checksum())?; - (ip_repr, ip_packet.payload()) - } + Ok(ip_packet) => match Repr::parse(&ip_packet, &checksum_caps) { + Err(_) => return Ok(()), + Ok(ip_repr) => { + write!(f, "{}{}", indent, ip_repr)?; + format_checksum(f, ip_packet.verify_checksum())?; + (ip_repr, ip_packet.payload()) } - } + }, }; pretty_print_ip_payload(f, indent, ip_repr, payload) @@ -716,20 +757,12 @@ impl> PrettyPrint for Packet { mod test { use super::*; - static PACKET_BYTES: [u8; 30] = - [0x45, 0x00, 0x00, 0x1e, - 0x01, 0x02, 0x62, 0x03, - 0x1a, 0x01, 0xd5, 0x6e, - 0x11, 0x12, 0x13, 0x14, - 0x21, 0x22, 0x23, 0x24, - 0xaa, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff]; + static PACKET_BYTES: [u8; 30] = [ + 0x45, 0x00, 0x00, 0x1e, 0x01, 0x02, 0x62, 0x03, 0x1a, 0x01, 0xd5, 0x6e, 0x11, 0x12, 0x13, + 0x14, 0x21, 0x22, 0x23, 0x24, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + ]; - static PAYLOAD_BYTES: [u8; 10] = - [0xaa, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff]; + static PAYLOAD_BYTES: [u8; 10] = [0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff]; #[test] fn test_deconstruct() { @@ -781,10 +814,14 @@ mod test { bytes.extend(&PACKET_BYTES[..]); bytes.push(0); - assert_eq!(Packet::new_unchecked(&bytes).payload().len(), - PAYLOAD_BYTES.len()); - assert_eq!(Packet::new_unchecked(&mut bytes).payload_mut().len(), - PAYLOAD_BYTES.len()); + assert_eq!( + Packet::new_unchecked(&bytes).payload().len(), + PAYLOAD_BYTES.len() + ); + assert_eq!( + Packet::new_unchecked(&mut bytes).payload_mut().len(), + PAYLOAD_BYTES.len() + ); } #[test] @@ -793,28 +830,23 @@ mod test { bytes.extend(&PACKET_BYTES[..]); Packet::new_unchecked(&mut bytes).set_total_len(128); - assert_eq!(Packet::new_checked(&bytes).unwrap_err(), - Error::Truncated); + assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error::Truncated); } - static REPR_PACKET_BYTES: [u8; 24] = - [0x45, 0x00, 0x00, 0x18, - 0x00, 0x00, 0x40, 0x00, - 0x40, 0x01, 0xd2, 0x79, - 0x11, 0x12, 0x13, 0x14, - 0x21, 0x22, 0x23, 0x24, - 0xaa, 0x00, 0x00, 0xff]; + static REPR_PACKET_BYTES: [u8; 24] = [ + 0x45, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x00, 0x40, 0x01, 0xd2, 0x79, 0x11, 0x12, 0x13, + 0x14, 0x21, 0x22, 0x23, 0x24, 0xaa, 0x00, 0x00, 0xff, + ]; - static REPR_PAYLOAD_BYTES: [u8; 4] = - [0xaa, 0x00, 0x00, 0xff]; + static REPR_PAYLOAD_BYTES: [u8; 4] = [0xaa, 0x00, 0x00, 0xff]; fn packet_repr() -> Repr { Repr { - src_addr: Address([0x11, 0x12, 0x13, 0x14]), - dst_addr: Address([0x21, 0x22, 0x23, 0x24]), - protocol: Protocol::Icmp, + src_addr: Address([0x11, 0x12, 0x13, 0x14]), + dst_addr: Address([0x21, 0x22, 0x23, 0x24]), + protocol: Protocol::Icmp, payload_len: 4, - hop_limit: 64 + hop_limit: 64, } } @@ -833,7 +865,10 @@ mod test { packet.set_version(6); packet.fill_checksum(); let packet = Packet::new_unchecked(&*packet.into_inner()); - assert_eq!(Repr::parse(&packet, &ChecksumCapabilities::default()), Err(Error::Malformed)); + assert_eq!( + Repr::parse(&packet, &ChecksumCapabilities::default()), + Err(Error::Malformed) + ); } #[test] @@ -876,28 +911,34 @@ mod test { let cidr = Cidr::new(Address::new(192, 168, 1, 10), 24); let inside_subnet = [ - [192, 168, 1, 0], [192, 168, 1, 1], - [192, 168, 1, 2], [192, 168, 1, 10], - [192, 168, 1, 127], [192, 168, 1, 255], + [192, 168, 1, 0], + [192, 168, 1, 1], + [192, 168, 1, 2], + [192, 168, 1, 10], + [192, 168, 1, 127], + [192, 168, 1, 255], ]; let outside_subnet = [ - [192, 168, 0, 0], [127, 0, 0, 1], - [192, 168, 2, 0], [192, 168, 0, 255], - [ 0, 0, 0, 0], [255, 255, 255, 255], + [192, 168, 0, 0], + [127, 0, 0, 1], + [192, 168, 2, 0], + [192, 168, 0, 255], + [0, 0, 0, 0], + [255, 255, 255, 255], ]; let subnets = [ - ([192, 168, 1, 0], 32), - ([192, 168, 1, 255], 24), - ([192, 168, 1, 10], 30), + ([192, 168, 1, 0], 32), + ([192, 168, 1, 255], 24), + ([192, 168, 1, 10], 30), ]; let not_subnets = [ - ([192, 168, 1, 10], 23), - ([127, 0, 0, 1], 8), - ([192, 168, 1, 0], 0), - ([192, 168, 0, 255], 32), + ([192, 168, 1, 10], 23), + ([127, 0, 0, 1], 8), + ([192, 168, 1, 0], 0), + ([192, 168, 0, 255], 32), ]; for addr in inside_subnet.iter().map(|a| Address::from_bytes(a)) { @@ -908,13 +949,17 @@ mod test { assert!(!cidr.contains_addr(&addr)); } - for subnet in subnets.iter().map( - |&(a, p)| Cidr::new(Address::new(a[0], a[1], a[2], a[3]), p)) { + for subnet in subnets + .iter() + .map(|&(a, p)| Cidr::new(Address::new(a[0], a[1], a[2], a[3]), p)) + { assert!(cidr.contains_subnet(&subnet)); } - for subnet in not_subnets.iter().map( - |&(a, p)| Cidr::new(Address::new(a[0], a[1], a[2], a[3]), p)) { + for subnet in not_subnets + .iter() + .map(|&(a, p)| Cidr::new(Address::new(a[0], a[1], a[2], a[3]), p)) + { assert!(!cidr.contains_subnet(&subnet)); } @@ -924,94 +969,175 @@ mod test { #[test] fn test_cidr_from_netmask() { - assert_eq!(Cidr::from_netmask(Address([0, 0, 0, 0]), Address([1, 0, 2, 0])).is_err(), - true); - assert_eq!(Cidr::from_netmask(Address([0, 0, 0, 0]), Address([0, 0, 0, 0])).is_err(), - true); - assert_eq!(Cidr::from_netmask(Address([0, 0, 0, 1]), Address([255, 255, 255, 0])).unwrap(), - Cidr::new(Address([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)); - assert_eq!(Cidr::from_netmask(Address([172, 16, 0, 1]), Address([255, 240, 0, 0])).unwrap(), - Cidr::new(Address([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)); - assert_eq!(Cidr::from_netmask(Address([255, 255, 255, 255]), Address([255, 255, 255, 255])).unwrap(), - Cidr::new(Address([255, 255, 255, 255]), 32)); + assert_eq!( + Cidr::from_netmask(Address([0, 0, 0, 0]), Address([1, 0, 2, 0])).is_err(), + true + ); + assert_eq!( + Cidr::from_netmask(Address([0, 0, 0, 0]), Address([0, 0, 0, 0])).is_err(), + true + ); + assert_eq!( + Cidr::from_netmask(Address([0, 0, 0, 1]), Address([255, 255, 255, 0])).unwrap(), + Cidr::new(Address([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) + ); + assert_eq!( + Cidr::from_netmask(Address([172, 16, 0, 1]), Address([255, 240, 0, 0])).unwrap(), + Cidr::new(Address([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) + ); + assert_eq!( + Cidr::from_netmask(Address([255, 255, 255, 255]), Address([255, 255, 255, 255])) + .unwrap(), + Cidr::new(Address([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])); - assert_eq!(Cidr::new(Address([0, 0, 0, 1]), 24).netmask(), - Address([255, 255, 255, 0])); - assert_eq!(Cidr::new(Address([0, 0, 0, 0]), 32).netmask(), - Address([255, 255, 255, 255])); - assert_eq!(Cidr::new(Address([127, 0, 0, 0]), 8).netmask(), - Address([255, 0, 0, 0])); - assert_eq!(Cidr::new(Address([192, 168, 0, 0]), 16).netmask(), - Address([255, 255, 0, 0])); - assert_eq!(Cidr::new(Address([192, 168, 1, 1]), 16).netmask(), - Address([255, 255, 0, 0])); - assert_eq!(Cidr::new(Address([192, 168, 1, 1]), 17).netmask(), - Address([255, 255, 128, 0])); - assert_eq!(Cidr::new(Address([172, 16, 0, 0]), 12).netmask(), - Address([255, 240, 0, 0])); - assert_eq!(Cidr::new(Address([255, 255, 255, 1]), 24).netmask(), - Address([255, 255, 255, 0])); - assert_eq!(Cidr::new(Address([255, 255, 255, 255]), 32).netmask(), - Address([255, 255, 255, 255])); + assert_eq!( + Cidr::new(Address([0, 0, 0, 0]), 0).netmask(), + Address([0, 0, 0, 0]) + ); + assert_eq!( + Cidr::new(Address([0, 0, 0, 1]), 24).netmask(), + Address([255, 255, 255, 0]) + ); + assert_eq!( + Cidr::new(Address([0, 0, 0, 0]), 32).netmask(), + Address([255, 255, 255, 255]) + ); + assert_eq!( + Cidr::new(Address([127, 0, 0, 0]), 8).netmask(), + Address([255, 0, 0, 0]) + ); + assert_eq!( + Cidr::new(Address([192, 168, 0, 0]), 16).netmask(), + Address([255, 255, 0, 0]) + ); + assert_eq!( + Cidr::new(Address([192, 168, 1, 1]), 16).netmask(), + Address([255, 255, 0, 0]) + ); + assert_eq!( + Cidr::new(Address([192, 168, 1, 1]), 17).netmask(), + Address([255, 255, 128, 0]) + ); + assert_eq!( + Cidr::new(Address([172, 16, 0, 0]), 12).netmask(), + Address([255, 240, 0, 0]) + ); + assert_eq!( + Cidr::new(Address([255, 255, 255, 1]), 24).netmask(), + Address([255, 255, 255, 0]) + ); + assert_eq!( + Cidr::new(Address([255, 255, 255, 255]), 32).netmask(), + Address([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])); - assert_eq!(Cidr::new(Address([0, 0, 0, 1]), 24).broadcast().unwrap(), - Address([0, 0, 0, 255])); - assert_eq!(Cidr::new(Address([0, 0, 0, 0]), 32).broadcast(), - None); - assert_eq!(Cidr::new(Address([127, 0, 0, 0]), 8).broadcast().unwrap(), - Address([127, 255, 255, 255])); - assert_eq!(Cidr::new(Address([192, 168, 0, 0]), 16).broadcast().unwrap(), - Address([192, 168, 255, 255])); - assert_eq!(Cidr::new(Address([192, 168, 1, 1]), 16).broadcast().unwrap(), - Address([192, 168, 255, 255])); - assert_eq!(Cidr::new(Address([192, 168, 1, 1]), 17).broadcast().unwrap(), - Address([192, 168, 127, 255])); - assert_eq!(Cidr::new(Address([172, 16, 0, 1]), 12).broadcast().unwrap(), - Address([172, 31, 255, 255])); - assert_eq!(Cidr::new(Address([255, 255, 255, 1]), 24).broadcast().unwrap(), - Address([255, 255, 255, 255])); - assert_eq!(Cidr::new(Address([255, 255, 255, 254]), 31).broadcast(), - None); - assert_eq!(Cidr::new(Address([255, 255, 255, 255]), 32).broadcast(), - None); - + assert_eq!( + Cidr::new(Address([0, 0, 0, 0]), 0).broadcast().unwrap(), + Address([255, 255, 255, 255]) + ); + assert_eq!( + Cidr::new(Address([0, 0, 0, 1]), 24).broadcast().unwrap(), + Address([0, 0, 0, 255]) + ); + assert_eq!(Cidr::new(Address([0, 0, 0, 0]), 32).broadcast(), None); + assert_eq!( + Cidr::new(Address([127, 0, 0, 0]), 8).broadcast().unwrap(), + Address([127, 255, 255, 255]) + ); + assert_eq!( + Cidr::new(Address([192, 168, 0, 0]), 16) + .broadcast() + .unwrap(), + Address([192, 168, 255, 255]) + ); + assert_eq!( + Cidr::new(Address([192, 168, 1, 1]), 16) + .broadcast() + .unwrap(), + Address([192, 168, 255, 255]) + ); + assert_eq!( + Cidr::new(Address([192, 168, 1, 1]), 17) + .broadcast() + .unwrap(), + Address([192, 168, 127, 255]) + ); + assert_eq!( + Cidr::new(Address([172, 16, 0, 1]), 12).broadcast().unwrap(), + Address([172, 31, 255, 255]) + ); + assert_eq!( + Cidr::new(Address([255, 255, 255, 1]), 24) + .broadcast() + .unwrap(), + Address([255, 255, 255, 255]) + ); + assert_eq!( + Cidr::new(Address([255, 255, 255, 254]), 31).broadcast(), + None + ); + assert_eq!( + Cidr::new(Address([255, 255, 255, 255]), 32).broadcast(), + None + ); } #[test] fn test_cidr_network() { - assert_eq!(Cidr::new(Address([0, 0, 0, 0]), 0).network(), - Cidr::new(Address([0, 0, 0, 0]), 0)); - assert_eq!(Cidr::new(Address([0, 0, 0, 1]), 24).network(), - Cidr::new(Address([0, 0, 0, 0]), 24)); - assert_eq!(Cidr::new(Address([0, 0, 0, 0]), 32).network(), - Cidr::new(Address([0, 0, 0, 0]), 32)); - assert_eq!(Cidr::new(Address([127, 0, 0, 0]), 8).network(), - Cidr::new(Address([127, 0, 0, 0]), 8)); - assert_eq!(Cidr::new(Address([192, 168, 0, 0]), 16).network(), - Cidr::new(Address([192, 168, 0, 0]), 16)); - assert_eq!(Cidr::new(Address([192, 168, 1, 1]), 16).network(), - Cidr::new(Address([192, 168, 0, 0]), 16)); - assert_eq!(Cidr::new(Address([192, 168, 1, 1]), 17).network(), - Cidr::new(Address([192, 168, 0, 0]), 17)); - assert_eq!(Cidr::new(Address([172, 16, 0, 1]), 12).network(), - Cidr::new(Address([172, 16, 0, 0]), 12)); - assert_eq!(Cidr::new(Address([255, 255, 255, 1]), 24).network(), - Cidr::new(Address([255, 255, 255, 0]), 24)); - assert_eq!(Cidr::new(Address([255, 255, 255, 255]), 32).network(), - Cidr::new(Address([255, 255, 255, 255]), 32)); + assert_eq!( + Cidr::new(Address([0, 0, 0, 0]), 0).network(), + Cidr::new(Address([0, 0, 0, 0]), 0) + ); + assert_eq!( + Cidr::new(Address([0, 0, 0, 1]), 24).network(), + Cidr::new(Address([0, 0, 0, 0]), 24) + ); + assert_eq!( + Cidr::new(Address([0, 0, 0, 0]), 32).network(), + Cidr::new(Address([0, 0, 0, 0]), 32) + ); + assert_eq!( + Cidr::new(Address([127, 0, 0, 0]), 8).network(), + Cidr::new(Address([127, 0, 0, 0]), 8) + ); + assert_eq!( + Cidr::new(Address([192, 168, 0, 0]), 16).network(), + Cidr::new(Address([192, 168, 0, 0]), 16) + ); + assert_eq!( + Cidr::new(Address([192, 168, 1, 1]), 16).network(), + Cidr::new(Address([192, 168, 0, 0]), 16) + ); + assert_eq!( + Cidr::new(Address([192, 168, 1, 1]), 17).network(), + Cidr::new(Address([192, 168, 0, 0]), 17) + ); + assert_eq!( + Cidr::new(Address([172, 16, 0, 1]), 12).network(), + Cidr::new(Address([172, 16, 0, 0]), 12) + ); + assert_eq!( + Cidr::new(Address([255, 255, 255, 1]), 24).network(), + Cidr::new(Address([255, 255, 255, 0]), 24) + ); + assert_eq!( + Cidr::new(Address([255, 255, 255, 255]), 32).network(), + Cidr::new(Address([255, 255, 255, 255]), 32) + ); } } diff --git a/src/wire/ipv6.rs b/src/wire/ipv6.rs index 575219c..cb00586 100644 --- a/src/wire/ipv6.rs +++ b/src/wire/ipv6.rs @@ -1,12 +1,12 @@ #![deny(missing_docs)] -use core::fmt; use byteorder::{ByteOrder, NetworkEndian}; +use core::fmt; -use crate::{Error, Result}; use crate::wire::ip::pretty_print_ip_payload; #[cfg(feature = "proto-ipv4")] use crate::wire::ipv4; +use crate::{Error, Result}; pub use super::IpProtocol as Protocol; @@ -29,28 +29,30 @@ impl Address { /// 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_NODES: Address = - Address([0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]); + pub const LINK_LOCAL_ALL_NODES: Address = Address([ + 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, + ]); /// The link-local [all nodes multicast address]. /// /// [all nodes 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]); + 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 [loopback address]. /// /// [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]); + pub const LOOPBACK: Address = Address([ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, + ]); /// Construct an IPv6 address from parts. #[allow(clippy::too_many_arguments)] - pub fn new(a0: u16, a1: u16, a2: u16, a3: u16, - a4: u16, a5: u16, a6: u16, a7: u16) -> Address { + pub fn new(a0: u16, a1: u16, a2: u16, a3: u16, a4: u16, a5: u16, a6: u16, a7: u16) -> Address { let mut addr = [0u8; 16]; NetworkEndian::write_u16(&mut addr[0..2], a0); NetworkEndian::write_u16(&mut addr[2..4], a1); @@ -127,8 +129,7 @@ impl Address { /// /// [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] + self.0[0..8] == [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] } /// Query whether the IPv6 address is the [loopback address]. @@ -149,7 +150,9 @@ impl Address { /// Convert an IPv4 mapped IPv6 address to an IPv4 address. pub fn as_ipv4(&self) -> Option { if self.is_ipv4_mapped() { - Some(ipv4::Address::new(self.0[12], self.0[13], self.0[14], self.0[15])) + Some(ipv4::Address::new( + self.0[12], self.0[13], self.0[14], self.0[15], + )) } else { None } @@ -180,8 +183,10 @@ impl Address { /// unicast. pub fn solicited_node(&self) -> Address { assert!(self.is_unicast()); - let mut bytes = [0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + let mut bytes = [ + 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + ]; bytes[14..].copy_from_slice(&self.0[14..]); Address(bytes) } @@ -204,7 +209,11 @@ impl From
for ::std::net::Ipv6Addr { 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[12], self.0[13], self.0[14], self.0[15]) + return write!( + f, + "::ffff:{}.{}.{}.{}", + self.0[12], self.0[13], self.0[14], self.0[15] + ); } // The string representation of an IPv6 address should @@ -217,7 +226,7 @@ impl fmt::Display for Address { Head, HeadBody, Tail, - TailBody + TailBody, } let mut words = [0u16; 8]; self.write_parts(&mut words); @@ -229,7 +238,7 @@ impl fmt::Display for Address { (0, &State::Head) | (0, &State::HeadBody) => { write!(f, "::")?; State::Tail - }, + } // Continue iterating without writing any characters until // we hit anothing non-zero value. (0, &State::Tail) => State::Tail, @@ -238,11 +247,11 @@ impl fmt::Display for Address { (_, &State::Head) => { write!(f, "{:x}", word)?; State::HeadBody - }, + } (_, &State::Tail) => { 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) => { @@ -260,8 +269,9 @@ impl fmt::Display for Address { impl From for Address { fn from(address: ipv4::Address) -> Self { let octets = address.0; - Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, - octets[0], octets[1], octets[2], octets[3]]) + Address([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, octets[0], octets[1], octets[2], octets[3], + ]) } } @@ -270,7 +280,7 @@ impl From for Address { #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Cidr { - address: Address, + address: Address, prefix_len: u8, } @@ -278,12 +288,13 @@ impl Cidr { /// The [solicited node prefix]. /// /// [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]), - prefix_len: 104 - }; + 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, + ]), + prefix_len: 104, + }; /// Create an IPv6 CIDR block from the given address and prefix length. /// @@ -291,7 +302,10 @@ impl Cidr { /// This function panics if the prefix length is larger than 128. pub fn new(address: Address, prefix_len: u8) -> Cidr { assert!(prefix_len <= 128); - Cidr { address, prefix_len } + Cidr { + address, + prefix_len, + } } /// Return the address of this IPv6 CIDR block. @@ -308,7 +322,9 @@ impl Cidr { /// the given address. pub fn contains_addr(&self, addr: &Address) -> bool { // right shift by 128 is not legal - if self.prefix_len == 0 { return true } + if self.prefix_len == 0 { + return true; + } let shift = 128 - self.prefix_len; self.address.mask(shift) == addr.mask(shift) @@ -332,7 +348,7 @@ impl fmt::Display for Cidr { #[derive(Debug, PartialEq, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { - buffer: T + buffer: T, } // Ranges and constants describing the IPv6 header @@ -367,17 +383,17 @@ mod field { pub const VER_TC_FLOW: Field = 0..4; // 16-bit value representing the length of the payload. // Note: Options are included in this length. - pub const LENGTH: Field = 4..6; + pub const LENGTH: Field = 4..6; // 8-bit value identifying the type of header following this // one. Note: The same numbers are used in IPv4. - pub const NXT_HDR: usize = 6; + pub const NXT_HDR: usize = 6; // 8-bit value decremented by each node that forwards this // packet. The packet is discarded when the value is 0. - pub const HOP_LIMIT: usize = 7; + pub const HOP_LIMIT: usize = 7; // IPv6 address of the source node. - pub const SRC_ADDR: Field = 8..24; + pub const SRC_ADDR: Field = 8..24; // IPv6 address of the destination node. - pub const DST_ADDR: Field = 24..40; + pub const DST_ADDR: Field = 24..40; } /// Length of an IPv6 header. @@ -602,15 +618,15 @@ impl> AsRef<[u8]> for Packet { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Repr { /// IPv6 address of the source node. - pub src_addr: Address, + pub src_addr: Address, /// IPv6 address of the destination node. - pub dst_addr: Address, + pub dst_addr: Address, /// Protocol contained in the next header. pub next_header: Protocol, /// Length of the payload including the extension headers. pub payload_len: usize, /// The 8-bit hop limit field. - pub hop_limit: u8 + pub hop_limit: u8, } impl Repr { @@ -618,13 +634,15 @@ impl Repr { pub fn parse + ?Sized>(packet: &Packet<&T>) -> Result { // Ensure basic accessors will work packet.check_len()?; - if packet.version() != 6 { return Err(Error::Malformed); } + if packet.version() != 6 { + return Err(Error::Malformed); + } Ok(Repr { - src_addr: packet.src_addr(), - dst_addr: packet.dst_addr(), + src_addr: packet.src_addr(), + dst_addr: packet.dst_addr(), next_header: packet.next_header(), payload_len: packet.payload_len() as usize, - hop_limit: packet.hop_limit() + hop_limit: packet.hop_limit(), }) } @@ -651,29 +669,33 @@ impl Repr { impl fmt::Display for Repr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "IPv6 src={} dst={} nxt_hdr={} hop_limit={}", - self.src_addr, self.dst_addr, self.next_header, self.hop_limit) + write!( + f, + "IPv6 src={} dst={} nxt_hdr={} hop_limit={}", + self.src_addr, self.dst_addr, self.next_header, self.hop_limit + ) } } -use crate::wire::pretty_print::{PrettyPrint, PrettyIndent}; +use crate::wire::pretty_print::{PrettyIndent, PrettyPrint}; // TODO: This is very similar to the implementation for IPv4. Make // a way to have less copy and pasted code here. impl> PrettyPrint for Packet { - fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter, - indent: &mut PrettyIndent) -> fmt::Result { + fn pretty_print( + buffer: &dyn AsRef<[u8]>, + f: &mut fmt::Formatter, + indent: &mut PrettyIndent, + ) -> fmt::Result { let (ip_repr, payload) = match Packet::new_checked(buffer) { Err(err) => return write!(f, "{}({})", indent, err), - Ok(ip_packet) => { - match Repr::parse(&ip_packet) { - Err(_) => return Ok(()), - Ok(ip_repr) => { - write!(f, "{}{}", indent, ip_repr)?; - (ip_repr, ip_packet.payload()) - } + Ok(ip_packet) => match Repr::parse(&ip_packet) { + Err(_) => return Ok(()), + Ok(ip_repr) => { + write!(f, "{}{}", indent, ip_repr)?; + (ip_repr, ip_packet.payload()) } - } + }, }; pretty_print_ip_payload(f, indent, ip_repr, payload) @@ -682,18 +704,18 @@ impl> PrettyPrint for Packet { #[cfg(test)] mod test { - use crate::Error; use super::{Address, Cidr}; use super::{Packet, Protocol, Repr}; - use crate::wire::pretty_print::{PrettyPrinter}; + use crate::wire::pretty_print::PrettyPrinter; + use crate::Error; #[cfg(feature = "proto-ipv4")] use crate::wire::ipv4::Address as Ipv4Address; - static LINK_LOCAL_ADDR: Address = Address([0xfe, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01]); + static LINK_LOCAL_ADDR: Address = Address([ + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, + ]); #[test] fn test_basic_multicast() { assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_unspecified()); @@ -724,48 +746,62 @@ mod test { #[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)); + 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)))); + 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); + 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); + 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] @@ -788,18 +824,36 @@ mod test { #[test] fn test_mask() { let addr = Address::new(0x0123, 0x4567, 0x89ab, 0, 0, 0, 0, 1); - assert_eq!(addr.mask(11), [0x01, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); - assert_eq!(addr.mask(15), [0x01, 0x22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); - assert_eq!(addr.mask(26), [0x01, 0x23, 0x45, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); - assert_eq!(addr.mask(128), [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); - assert_eq!(addr.mask(127), [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + assert_eq!( + addr.mask(11), + [0x01, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ); + assert_eq!( + addr.mask(15), + [0x01, 0x22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ); + assert_eq!( + addr.mask(26), + [0x01, 0x23, 0x45, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ); + assert_eq!( + addr.mask(128), + [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] + ); + assert_eq!( + addr.mask(127), + [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ); } #[cfg(feature = "proto-ipv4")] #[test] fn test_is_ipv4_mapped() { assert_eq!(false, Address::UNSPECIFIED.is_ipv4_mapped()); - assert_eq!(true, Address::from(Ipv4Address::new(192, 168, 1, 1)).is_ipv4_mapped()); + assert_eq!( + true, + Address::from(Ipv4Address::new(192, 168, 1, 1)).is_ipv4_mapped() + ); } #[cfg(feature = "proto-ipv4")] @@ -814,10 +868,14 @@ mod test { #[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))); + 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] @@ -825,52 +883,96 @@ mod test { let cidr = Cidr::new(LINK_LOCAL_ADDR, 64); let inside_subnet = [ - [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02], - [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88], - [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], - [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff] + [ + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, + ], + [ + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x77, 0x88, + ], + [ + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + ], + [ + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, + ], ]; let outside_subnet = [ - [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], - [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], - [0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], - [0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02] + [ + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, + ], + [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, + ], + [ + 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, + ], + [ + 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, + ], ]; let subnets = [ - ([0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], - 65), - ([0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], - 128), - ([0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78], - 96) + ( + [ + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, + ], + 65, + ), + ( + [ + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, + ], + 128, + ), + ( + [ + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, + 0x34, 0x56, 0x78, + ], + 96, + ), ]; let not_subnets = [ - ([0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], - 63), - ([0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], - 64), - ([0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], - 65), - ([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], - 128) + ( + [ + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, + ], + 63, + ), + ( + [ + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, + ], + 64, + ), + ( + [ + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, + ], + 65, + ), + ( + [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, + ], + 128, + ), ]; for addr in inside_subnet.iter().map(|a| Address::from_bytes(a)) { @@ -881,13 +983,11 @@ 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(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(a), p)) { assert!(!cidr.contains_subnet(&subnet)); } @@ -907,33 +1007,26 @@ mod test { let _ = Address::from_parts(&[0u16; 7]); } - static REPR_PACKET_BYTES: [u8; 52] = [0x60, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x11, 0x40, - 0xfe, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x02, - 0x00, 0x0c, 0x02, 0x4e, - 0xff, 0xff, 0xff, 0xff]; - static REPR_PAYLOAD_BYTES: [u8; 12] = [0x00, 0x01, 0x00, 0x02, - 0x00, 0x0c, 0x02, 0x4e, - 0xff, 0xff, 0xff, 0xff]; + static REPR_PACKET_BYTES: [u8; 52] = [ + 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x11, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x0c, 0x02, 0x4e, 0xff, 0xff, 0xff, 0xff, + ]; + static REPR_PAYLOAD_BYTES: [u8; 12] = [ + 0x00, 0x01, 0x00, 0x02, 0x00, 0x0c, 0x02, 0x4e, 0xff, 0xff, 0xff, 0xff, + ]; 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([ + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, + ]), + dst_addr: Address::LINK_LOCAL_ALL_NODES, next_header: Protocol::Udp, payload_len: 12, - hop_limit: 64 + hop_limit: 64, } } @@ -948,10 +1041,13 @@ 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.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.payload(), &REPR_PAYLOAD_BYTES[..]); } @@ -976,15 +1072,14 @@ mod test { packet.set_hop_limit(0xfe); packet.set_src_addr(Address::LINK_LOCAL_ALL_ROUTERS); packet.set_dst_addr(Address::LINK_LOCAL_ALL_NODES); - packet.payload_mut().copy_from_slice(&REPR_PAYLOAD_BYTES[..]); + packet + .payload_mut() + .copy_from_slice(&REPR_PAYLOAD_BYTES[..]); let mut expected_bytes = [ - 0x69, 0x95, 0x43, 0x21, 0x00, 0x0c, 0x11, 0xfe, - 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 + 0x69, 0x95, 0x43, 0x21, 0x00, 0x0c, 0x11, 0xfe, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; let start = expected_bytes.len() - REPR_PAYLOAD_BYTES.len(); expected_bytes[start..].copy_from_slice(&REPR_PAYLOAD_BYTES[..]); @@ -998,10 +1093,14 @@ mod test { bytes.extend(&REPR_PACKET_BYTES[..]); bytes.push(0); - assert_eq!(Packet::new_unchecked(&bytes).payload().len(), - REPR_PAYLOAD_BYTES.len()); - assert_eq!(Packet::new_unchecked(&mut bytes).payload_mut().len(), - REPR_PAYLOAD_BYTES.len()); + assert_eq!( + Packet::new_unchecked(&bytes).payload().len(), + REPR_PAYLOAD_BYTES.len() + ); + assert_eq!( + Packet::new_unchecked(&mut bytes).payload_mut().len(), + REPR_PAYLOAD_BYTES.len() + ); } #[test] @@ -1010,8 +1109,7 @@ mod test { bytes.extend(&REPR_PACKET_BYTES[..]); Packet::new_unchecked(&mut bytes).set_payload_len(0x80); - assert_eq!(Packet::new_checked(&bytes).unwrap_err(), - Error::Truncated); + assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error::Truncated); } #[test] @@ -1063,7 +1161,12 @@ mod test { #[test] fn test_pretty_print() { - assert_eq!(format!("{}", PrettyPrinter::>::new("\n", &&REPR_PACKET_BYTES[..])), - "\nIPv6 src=fe80::1 dst=ff02::1 nxt_hdr=UDP hop_limit=64\n \\ UDP src=1 dst=2 len=4"); + assert_eq!( + format!( + "{}", + PrettyPrinter::>::new("\n", &&REPR_PACKET_BYTES[..]) + ), + "\nIPv6 src=fe80::1 dst=ff02::1 nxt_hdr=UDP hop_limit=64\n \\ UDP src=1 dst=2 len=4" + ); } } diff --git a/src/wire/ipv6fragment.rs b/src/wire/ipv6fragment.rs index ffa3936..36ccdfe 100644 --- a/src/wire/ipv6fragment.rs +++ b/src/wire/ipv6fragment.rs @@ -1,5 +1,5 @@ -use core::fmt; use crate::{Error, Result}; +use core::fmt; use byteorder::{ByteOrder, NetworkEndian}; @@ -9,7 +9,7 @@ pub use super::IpProtocol as Protocol; #[derive(Debug, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Header> { - buffer: T + buffer: T, } // Format of the Fragment Header @@ -25,13 +25,13 @@ mod field { use crate::wire::field::*; // 8-bit identifier of the header immediately following this header. - pub const NXT_HDR: usize = 0; + pub const NXT_HDR: usize = 0; // 8-bit reserved field. - pub const RESERVED: usize = 1; + pub const RESERVED: usize = 1; // 16-bit field containing the fragment offset, reserved and more fragments values. - pub const FR_OF_M: Field = 2..4; + pub const FR_OF_M: Field = 2..4; // 32-bit field identifying the fragmented packet - pub const IDENT: Field = 4..8; + pub const IDENT: Field = 4..8; } impl> Header { @@ -170,17 +170,19 @@ pub struct Repr { pub more_frags: bool, /// The identification for every packet that is fragmented. pub ident: u32, - } impl Repr { /// Parse an IPv6 Fragment Header and return a high-level representation. - pub fn parse(header: &Header<&T>) -> Result where T: AsRef<[u8]> + ?Sized { + pub fn parse(header: &Header<&T>) -> Result + where + T: AsRef<[u8]> + ?Sized, + { Ok(Repr { next_header: header.next_header(), frag_offset: header.frag_offset(), more_frags: header.more_frags(), - ident: header.ident() + ident: header.ident(), }) } @@ -202,8 +204,11 @@ impl Repr { impl<'a> fmt::Display for Repr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "IPv6 Fragment next_hdr={} offset={} more={} ident={}", - self.next_header, self.frag_offset, self.more_frags, self.ident) + write!( + f, + "IPv6 Fragment next_hdr={} offset={} more={} ident={}", + self.next_header, self.frag_offset, self.more_frags, self.ident + ) } } @@ -212,21 +217,23 @@ mod test { use super::*; // A Fragment Header with more fragments remaining - static BYTES_HEADER_MORE_FRAG: [u8; 8] = [0x6, 0x0, 0x0, 0x1, - 0x0, 0x0, 0x30, 0x39]; + static BYTES_HEADER_MORE_FRAG: [u8; 8] = [0x6, 0x0, 0x0, 0x1, 0x0, 0x0, 0x30, 0x39]; // A Fragment Header with no more fragments remaining - static BYTES_HEADER_LAST_FRAG: [u8; 8] = [0x6, 0x0, 0xa, 0x0, - 0x0, 0x1, 0x9, 0x32]; + static BYTES_HEADER_LAST_FRAG: [u8; 8] = [0x6, 0x0, 0xa, 0x0, 0x0, 0x1, 0x9, 0x32]; #[test] fn test_check_len() { // less than 8 bytes - assert_eq!(Err(Error::Truncated), - Header::new_unchecked(&BYTES_HEADER_MORE_FRAG[..7]).check_len()); + assert_eq!( + Err(Error::Truncated), + Header::new_unchecked(&BYTES_HEADER_MORE_FRAG[..7]).check_len() + ); // valid - assert_eq!(Ok(()), - Header::new_unchecked(&BYTES_HEADER_MORE_FRAG).check_len()); + assert_eq!( + Ok(()), + Header::new_unchecked(&BYTES_HEADER_MORE_FRAG).check_len() + ); } #[test] @@ -248,24 +255,48 @@ mod test { fn test_repr_parse_valid() { let header = Header::new_unchecked(&BYTES_HEADER_MORE_FRAG); let repr = Repr::parse(&header).unwrap(); - assert_eq!(repr, - Repr{ next_header: Protocol::Tcp, frag_offset: 0, more_frags: true, ident: 12345 }); + assert_eq!( + repr, + Repr { + next_header: Protocol::Tcp, + frag_offset: 0, + more_frags: true, + ident: 12345 + } + ); let header = Header::new_unchecked(&BYTES_HEADER_LAST_FRAG); let repr = Repr::parse(&header).unwrap(); - assert_eq!(repr, - Repr{ next_header: Protocol::Tcp, frag_offset: 320, more_frags: false, ident: 67890 }); + assert_eq!( + repr, + Repr { + next_header: Protocol::Tcp, + frag_offset: 320, + more_frags: false, + ident: 67890 + } + ); } #[test] fn test_repr_emit() { - let repr = Repr{ next_header: Protocol::Tcp, frag_offset: 0, more_frags: true, ident: 12345 }; + let repr = Repr { + next_header: Protocol::Tcp, + frag_offset: 0, + more_frags: true, + ident: 12345, + }; let mut bytes = [0u8; 8]; let mut header = Header::new_unchecked(&mut bytes); repr.emit(&mut header); assert_eq!(header.into_inner(), &BYTES_HEADER_MORE_FRAG[0..8]); - let repr = Repr{ next_header: Protocol::Tcp, frag_offset: 320, more_frags: false, ident: 67890 }; + let repr = Repr { + next_header: Protocol::Tcp, + frag_offset: 320, + more_frags: false, + ident: 67890, + }; let mut bytes = [0u8; 8]; let mut header = Header::new_unchecked(&mut bytes); repr.emit(&mut header); diff --git a/src/wire/ipv6hopbyhop.rs b/src/wire/ipv6hopbyhop.rs index dde76ae..97b8685 100644 --- a/src/wire/ipv6hopbyhop.rs +++ b/src/wire/ipv6hopbyhop.rs @@ -1,14 +1,14 @@ -use core::fmt; use crate::{Error, Result}; +use core::fmt; -use crate::wire::ipv6option::Ipv6OptionsIterator; pub use super::IpProtocol as Protocol; +use crate::wire::ipv6option::Ipv6OptionsIterator; /// A read/write wrapper around an IPv6 Hop-by-Hop Options Header. #[derive(Debug, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Header> { - buffer: T + buffer: T, } // Format of the Hop-by-Hop Options Header @@ -31,13 +31,13 @@ mod field { use crate::wire::field::*; // Minimum size of the header. - pub const MIN_HEADER_SIZE: usize = 8; + pub const MIN_HEADER_SIZE: usize = 8; // 8-bit identifier of the header immediately following this header. - pub const NXT_HDR: usize = 0; + pub const NXT_HDR: usize = 0; // 8-bit unsigned integer. Length of the OPTIONS field in 8-octet units, // not including the first 8 octets. - pub const LENGTH: usize = 1; + pub const LENGTH: usize = 1; // Variable-length field. Option-Type-specific data. // // Length of the header is in 8-octet units, not including the first 8 octets. The first two @@ -111,7 +111,7 @@ impl> Header { impl<'a, T: AsRef<[u8]> + ?Sized> Header<&'a T> { /// Return the option data. #[inline] - pub fn options(&self) -> &'a[u8] { + pub fn options(&self) -> &'a [u8] { let data = self.buffer.as_ref(); &data[field::OPTIONS(data[field::LENGTH])] } @@ -163,18 +163,21 @@ pub struct Repr<'a> { /// The type of header immediately following the Hop-by-Hop Options header. pub next_header: Protocol, /// Length of the Hop-by-Hop Options header in 8-octet units, not including the first 8 octets. - pub length: u8, + pub length: u8, /// The options contained in the Hop-by-Hop Options header. - pub options: &'a [u8] + pub options: &'a [u8], } impl<'a> Repr<'a> { /// Parse an IPv6 Hop-by-Hop Options Header and return a high-level representation. - pub fn parse(header: &Header<&'a T>) -> Result> where T: AsRef<[u8]> + ?Sized { + pub fn parse(header: &Header<&'a T>) -> Result> + where + T: AsRef<[u8]> + ?Sized, + { Ok(Repr { next_header: header.next_header(), length: header.header_len(), - options: header.options() + options: header.options(), }) } @@ -199,7 +202,11 @@ impl<'a> Repr<'a> { impl<'a> fmt::Display for Repr<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "IPv6 Hop-by-Hop Options next_hdr={} length={} ", self.next_header, self.length) + write!( + f, + "IPv6 Hop-by-Hop Options next_hdr={} length={} ", + self.next_header, self.length + ) } } @@ -208,36 +215,43 @@ mod test { use super::*; // A Hop-by-Hop Option header with a PadN option of option data length 4. - static REPR_PACKET_PAD4: [u8; 8] = [0x6, 0x0, 0x1, 0x4, - 0x0, 0x0, 0x0, 0x0]; + static REPR_PACKET_PAD4: [u8; 8] = [0x6, 0x0, 0x1, 0x4, 0x0, 0x0, 0x0, 0x0]; // A Hop-by-Hop Option header with a PadN option of option data length 12. - static REPR_PACKET_PAD12: [u8; 16] = [0x06, 0x1, 0x1, 0x12, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0]; + static REPR_PACKET_PAD12: [u8; 16] = [ + 0x06, 0x1, 0x1, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ]; #[test] fn test_check_len() { // zero byte buffer - assert_eq!(Err(Error::Truncated), - Header::new_unchecked(&REPR_PACKET_PAD4[..0]).check_len()); + assert_eq!( + Err(Error::Truncated), + Header::new_unchecked(&REPR_PACKET_PAD4[..0]).check_len() + ); // no length field - assert_eq!(Err(Error::Truncated), - Header::new_unchecked(&REPR_PACKET_PAD4[..1]).check_len()); + assert_eq!( + Err(Error::Truncated), + Header::new_unchecked(&REPR_PACKET_PAD4[..1]).check_len() + ); // less than 8 bytes - assert_eq!(Err(Error::Truncated), - Header::new_unchecked(&REPR_PACKET_PAD4[..7]).check_len()); + assert_eq!( + Err(Error::Truncated), + Header::new_unchecked(&REPR_PACKET_PAD4[..7]).check_len() + ); // valid - assert_eq!(Ok(()), - Header::new_unchecked(&REPR_PACKET_PAD4).check_len()); + assert_eq!(Ok(()), Header::new_unchecked(&REPR_PACKET_PAD4).check_len()); // valid - assert_eq!(Ok(()), - Header::new_unchecked(&REPR_PACKET_PAD12).check_len()); + assert_eq!( + Ok(()), + Header::new_unchecked(&REPR_PACKET_PAD12).check_len() + ); // length field value greater than number of bytes let header: [u8; 8] = [0x06, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]; - assert_eq!(Err(Error::Truncated), - Header::new_unchecked(&header).check_len()); + assert_eq!( + Err(Error::Truncated), + Header::new_unchecked(&header).check_len() + ); } #[test] @@ -259,19 +273,27 @@ mod test { bytes.extend(&REPR_PACKET_PAD4[..]); bytes.push(0); - assert_eq!(Header::new_unchecked(&bytes).options().len(), - REPR_PACKET_PAD4[2..].len()); - assert_eq!(Header::new_unchecked(&mut bytes).options_mut().len(), - REPR_PACKET_PAD4[2..].len()); + assert_eq!( + Header::new_unchecked(&bytes).options().len(), + REPR_PACKET_PAD4[2..].len() + ); + assert_eq!( + Header::new_unchecked(&mut bytes).options_mut().len(), + REPR_PACKET_PAD4[2..].len() + ); let mut bytes = vec![]; bytes.extend(&REPR_PACKET_PAD12[..]); bytes.push(0); - assert_eq!(Header::new_unchecked(&bytes).options().len(), - REPR_PACKET_PAD12[2..].len()); - assert_eq!(Header::new_unchecked(&mut bytes).options_mut().len(), - REPR_PACKET_PAD12[2..].len()); + assert_eq!( + Header::new_unchecked(&bytes).options().len(), + REPR_PACKET_PAD12[2..].len() + ); + assert_eq!( + Header::new_unchecked(&mut bytes).options_mut().len(), + REPR_PACKET_PAD12[2..].len() + ); } #[test] @@ -295,26 +317,44 @@ mod test { fn test_repr_parse_valid() { let header = Header::new_unchecked(&REPR_PACKET_PAD4); let repr = Repr::parse(&header).unwrap(); - assert_eq!(repr, Repr { - next_header: Protocol::Tcp, length: 0, options: &REPR_PACKET_PAD4[2..] - }); + assert_eq!( + repr, + Repr { + next_header: Protocol::Tcp, + length: 0, + options: &REPR_PACKET_PAD4[2..] + } + ); let header = Header::new_unchecked(&REPR_PACKET_PAD12); let repr = Repr::parse(&header).unwrap(); - assert_eq!(repr, Repr { - next_header: Protocol::Tcp, length: 1, options: &REPR_PACKET_PAD12[2..] - }); + assert_eq!( + repr, + Repr { + next_header: Protocol::Tcp, + length: 1, + options: &REPR_PACKET_PAD12[2..] + } + ); } #[test] fn test_repr_emit() { - let repr = Repr{ next_header: Protocol::Tcp, length: 0, options: &REPR_PACKET_PAD4[2..] }; + let repr = Repr { + next_header: Protocol::Tcp, + length: 0, + options: &REPR_PACKET_PAD4[2..], + }; let mut bytes = [0u8; 8]; let mut header = Header::new_unchecked(&mut bytes); repr.emit(&mut header); assert_eq!(header.into_inner(), &REPR_PACKET_PAD4[..]); - let repr = Repr{ next_header: Protocol::Tcp, length: 1, options: &REPR_PACKET_PAD12[2..] }; + let repr = Repr { + next_header: Protocol::Tcp, + length: 1, + options: &REPR_PACKET_PAD12[2..], + }; let mut bytes = [0u8; 16]; let mut header = Header::new_unchecked(&mut bytes); repr.emit(&mut header); diff --git a/src/wire/ipv6option.rs b/src/wire/ipv6option.rs index adab8f4..e22a8aa 100644 --- a/src/wire/ipv6option.rs +++ b/src/wire/ipv6option.rs @@ -1,5 +1,5 @@ -use core::fmt; use crate::{Error, Result}; +use core::fmt; enum_with_unknown! { /// IPv6 Extension Header Option Type @@ -14,9 +14,9 @@ enum_with_unknown! { impl fmt::Display for Type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Type::Pad1 => write!(f, "Pad1"), - Type::PadN => write!(f, "PadN"), - Type::Unknown(id) => write!(f, "{}", id) + Type::Pad1 => write!(f, "Pad1"), + Type::PadN => write!(f, "PadN"), + Type::Unknown(id) => write!(f, "{}", id), } } } @@ -40,11 +40,11 @@ enum_with_unknown! { impl fmt::Display for FailureType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - FailureType::Skip => write!(f, "skip"), - FailureType::Discard => write!(f, "discard"), - FailureType::DiscardSendAll => write!(f, "discard and send error"), + FailureType::Skip => write!(f, "skip"), + 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), + FailureType::Unknown(id) => write!(f, "Unknown({})", id), } } } @@ -60,7 +60,7 @@ impl From for FailureType { #[derive(Debug, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Ipv6Option> { - buffer: T + buffer: T, } // Format of Option @@ -77,9 +77,9 @@ mod field { use crate::wire::field::*; // 8-bit identifier of the type of option. - pub const TYPE: usize = 0; + pub const TYPE: usize = 0; // 8-bit unsigned integer. Length of the DATA field of this option, in octets. - pub const LENGTH: usize = 1; + pub const LENGTH: usize = 1; // Variable-length field. Option-Type-specific data. pub fn DATA(length: u8) -> Field { 2..length as usize + 2 @@ -221,27 +221,26 @@ pub enum Repr<'a> { Pad1, PadN(u8), Unknown { - type_: Type, + type_: Type, length: u8, - data: &'a [u8] + data: &'a [u8], }, } impl<'a> Repr<'a> { /// Parse an IPv6 Extension Header Option and return a high-level representation. - pub fn parse(opt: &Ipv6Option<&'a T>) -> Result> where T: AsRef<[u8]> + ?Sized { + pub fn parse(opt: &Ipv6Option<&'a T>) -> Result> + where + T: AsRef<[u8]> + ?Sized, + { match opt.option_type() { - Type::Pad1 => - Ok(Repr::Pad1), - Type::PadN => - Ok(Repr::PadN(opt.data_len())), - unknown_type @ Type::Unknown(_) => { - Ok(Repr::Unknown { - type_: unknown_type, - length: opt.data_len(), - data: opt.data(), - }) - } + Type::Pad1 => Ok(Repr::Pad1), + Type::PadN => Ok(Repr::PadN(opt.data_len())), + unknown_type @ Type::Unknown(_) => Ok(Repr::Unknown { + type_: unknown_type, + length: opt.data_len(), + data: opt.data(), + }), } } @@ -249,18 +248,15 @@ impl<'a> Repr<'a> { pub fn buffer_len(&self) -> usize { match *self { Repr::Pad1 => 1, - Repr::PadN(length) => - field::DATA(length).end, - Repr::Unknown{ length, .. } => - field::DATA(length).end, + Repr::PadN(length) => field::DATA(length).end, + Repr::Unknown { length, .. } => field::DATA(length).end, } } /// Emit a high-level representation into an IPv6 Extension Header Option. pub fn emit + AsMut<[u8]> + ?Sized>(&self, opt: &mut Ipv6Option<&'a mut T>) { match *self { - Repr::Pad1 => - opt.set_option_type(Type::Pad1), + Repr::Pad1 => opt.set_option_type(Type::Pad1), Repr::PadN(len) => { opt.set_option_type(Type::PadN); opt.set_data_len(len); @@ -269,7 +265,11 @@ impl<'a> Repr<'a> { *x = 0 } } - Repr::Unknown{ type_, length, data } => { + Repr::Unknown { + type_, + length, + data, + } => { opt.set_option_type(type_); opt.set_data_len(length); opt.data_mut().copy_from_slice(&data[..length as usize]); @@ -285,7 +285,7 @@ pub struct Ipv6OptionsIterator<'a> { pos: usize, length: usize, data: &'a [u8], - hit_error: bool + hit_error: bool, } impl<'a> Ipv6OptionsIterator<'a> { @@ -301,7 +301,8 @@ impl<'a> Ipv6OptionsIterator<'a> { Ipv6OptionsIterator { pos: 0, hit_error: false, - length, data + length, + data, } } } @@ -314,18 +315,16 @@ impl<'a> Iterator for Ipv6OptionsIterator<'a> { // If we still have data to parse and we have not previously // hit an error, attempt to parse the next option. match Ipv6Option::new_checked(&self.data[self.pos..]) { - Ok(hdr) => { - match Repr::parse(&hdr) { - Ok(repr) => { - self.pos += repr.buffer_len(); - Some(Ok(repr)) - } - Err(e) => { - self.hit_error = true; - Some(Err(e)) - } + Ok(hdr) => match Repr::parse(&hdr) { + Ok(repr) => { + self.pos += repr.buffer_len(); + Some(Ok(repr)) } - } + Err(e) => { + self.hit_error = true; + Some(Err(e)) + } + }, Err(e) => { self.hit_error = true; Some(Err(e)) @@ -343,12 +342,9 @@ impl<'a> fmt::Display for Repr<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "IPv6 Option ")?; match *self { - Repr::Pad1 => - write!(f, "{} ", Type::Pad1), - Repr::PadN(len) => - write!(f, "{} length={} ", Type::PadN, len), - Repr::Unknown{ type_, length, .. } => - write!(f, "{} length={} ", type_, length), + Repr::Pad1 => write!(f, "{} ", Type::Pad1), + Repr::PadN(len) => write!(f, "{} length={} ", Type::PadN, len), + Repr::Unknown { type_, length, .. } => write!(f, "{} length={} ", type_, length), } } } @@ -357,35 +353,49 @@ impl<'a> fmt::Display for Repr<'a> { mod test { use super::*; - static IPV6OPTION_BYTES_PAD1: [u8; 1] = [0x0]; - static IPV6OPTION_BYTES_PADN: [u8; 3] = [0x1, 0x1, 0x0]; + static IPV6OPTION_BYTES_PAD1: [u8; 1] = [0x0]; + static IPV6OPTION_BYTES_PADN: [u8; 3] = [0x1, 0x1, 0x0]; static IPV6OPTION_BYTES_UNKNOWN: [u8; 5] = [0xff, 0x3, 0x0, 0x0, 0x0]; #[test] fn test_check_len() { let bytes = [0u8]; // zero byte buffer - assert_eq!(Err(Error::Truncated), - Ipv6Option::new_unchecked(&bytes[..0]).check_len()); + assert_eq!( + Err(Error::Truncated), + Ipv6Option::new_unchecked(&bytes[..0]).check_len() + ); // pad1 - assert_eq!(Ok(()), - Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_PAD1).check_len()); + assert_eq!( + Ok(()), + Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_PAD1).check_len() + ); // padn with truncated data - assert_eq!(Err(Error::Truncated), - Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_PADN[..2]).check_len()); + assert_eq!( + Err(Error::Truncated), + Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_PADN[..2]).check_len() + ); // padn - assert_eq!(Ok(()), - Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_PADN).check_len()); + assert_eq!( + Ok(()), + Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_PADN).check_len() + ); // unknown option type with truncated data - assert_eq!(Err(Error::Truncated), - Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN[..4]).check_len()); - assert_eq!(Err(Error::Truncated), - Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN[..1]).check_len()); + assert_eq!( + Err(Error::Truncated), + Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN[..4]).check_len() + ); + assert_eq!( + Err(Error::Truncated), + Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN[..1]).check_len() + ); // unknown type - assert_eq!(Ok(()), - Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN).check_len()); + assert_eq!( + Ok(()), + Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN).check_len() + ); } #[test] @@ -402,7 +412,7 @@ mod test { assert_eq!(opt.option_type(), Type::Pad1); // two octets of padding - let bytes: [u8; 2] = [0x1, 0x0]; + let bytes: [u8; 2] = [0x1, 0x0]; let opt = Ipv6Option::new_unchecked(&bytes); assert_eq!(opt.option_type(), Type::PadN); assert_eq!(opt.data_len(), 0); @@ -414,14 +424,14 @@ mod test { assert_eq!(opt.data(), &[0]); // extra bytes in buffer - let bytes: [u8; 10] = [0x1, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff]; + let bytes: [u8; 10] = [0x1, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff]; let opt = Ipv6Option::new_unchecked(&bytes); assert_eq!(opt.option_type(), Type::PadN); assert_eq!(opt.data_len(), 7); assert_eq!(opt.data(), &[0, 0, 0, 0, 0, 0, 0]); // unrecognized option - let bytes: [u8; 1] = [0xff]; + let bytes: [u8; 1] = [0xff]; let opt = Ipv6Option::new_unchecked(&bytes); assert_eq!(opt.option_type(), Type::Unknown(255)); @@ -447,7 +457,14 @@ mod test { let data = [0u8; 3]; let opt = Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN); let unknown = Repr::parse(&opt).unwrap(); - assert_eq!(unknown, Repr::Unknown { type_: Type::Unknown(255), length: 3, data: &data }); + assert_eq!( + unknown, + Repr::Unknown { + type_: Type::Unknown(255), + length: 3, + data: &data + } + ); } #[test] @@ -465,7 +482,11 @@ mod test { assert_eq!(opt.into_inner(), &IPV6OPTION_BYTES_PADN); let data = [0u8; 3]; - let repr = Repr::Unknown { type_: Type::Unknown(255), length: 3, data: &data }; + let repr = Repr::Unknown { + type_: Type::Unknown(255), + length: 3, + data: &data, + }; let mut bytes = [254u8; 5]; // don't assume bytes are initialized to zero let mut opt = Ipv6Option::new_unchecked(&mut bytes); repr.emit(&mut opt); @@ -488,10 +509,10 @@ mod test { #[test] fn test_options_iter() { - let options = [0x00, 0x01, 0x01, 0x00, - 0x01, 0x02, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x11, - 0x00, 0x01, 0x08, 0x00]; + let options = [ + 0x00, 0x01, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, 0x00, 0x01, + 0x08, 0x00, + ]; let mut iterator = Ipv6OptionsIterator::new(&options, 0); assert_eq!(iterator.next(), None); @@ -504,8 +525,14 @@ mod test { (2, Ok(Repr::PadN(2))) => continue, (3, Ok(Repr::PadN(0))) => continue, (4, Ok(Repr::Pad1)) => continue, - (5, Ok(Repr::Unknown { type_: Type::Unknown(0x11), length: 0, .. })) => - continue, + ( + 5, + Ok(Repr::Unknown { + type_: Type::Unknown(0x11), + length: 0, + .. + }), + ) => continue, (6, Err(Error::Truncated)) => continue, (i, res) => panic!("Unexpected option `{:?}` at index {}", res, i), } diff --git a/src/wire/ipv6routing.rs b/src/wire/ipv6routing.rs index a00e44b..fdb155a 100644 --- a/src/wire/ipv6routing.rs +++ b/src/wire/ipv6routing.rs @@ -1,5 +1,5 @@ -use core::fmt; use crate::{Error, Result}; +use core::fmt; use crate::wire::IpProtocol as Protocol; use crate::wire::Ipv6Address as Address; @@ -37,14 +37,14 @@ enum_with_unknown! { impl fmt::Display for Type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Type::Type0 => write!(f, "Type0"), - Type::Nimrod => write!(f, "Nimrod"), - Type::Type2 => write!(f, "Type2"), - Type::Rpl => write!(f, "Rpl"), - Type::Experiment1 => write!(f, "Experiment1"), - Type::Experiment2 => write!(f, "Experiment2"), - Type::Reserved => write!(f, "Reserved"), - Type::Unknown(id) => write!(f, "{}", id) + Type::Type0 => write!(f, "Type0"), + Type::Nimrod => write!(f, "Nimrod"), + Type::Type2 => write!(f, "Type2"), + Type::Rpl => write!(f, "Rpl"), + Type::Experiment1 => write!(f, "Experiment1"), + Type::Experiment2 => write!(f, "Experiment2"), + Type::Reserved => write!(f, "Reserved"), + Type::Unknown(id) => write!(f, "{}", id), } } } @@ -53,7 +53,7 @@ impl fmt::Display for Type { #[derive(Debug, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Header> { - buffer: T + buffer: T, } // Format of the Routing Header @@ -76,15 +76,15 @@ mod field { use crate::wire::field::*; // Minimum size of the header. - pub const MIN_HEADER_SIZE: usize = 4; + pub const MIN_HEADER_SIZE: usize = 4; // 8-bit identifier of the header immediately following this header. - pub const NXT_HDR: usize = 0; + pub const NXT_HDR: usize = 0; // 8-bit unsigned integer. Length of the DATA field in 8-octet units, // not including the first 8 octets. - pub const LENGTH: usize = 1; + pub const LENGTH: usize = 1; // 8-bit identifier of a particular Routing header variant. - pub const TYPE: usize = 2; + pub const TYPE: usize = 2; // 8-bit unsigned integer. The number of route segments remaining. pub const SEG_LEFT: usize = 3; // Variable-length field. Routing-Type-specific data. @@ -130,9 +130,9 @@ mod field { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // 8-bit field containing the CmprI and CmprE values. - pub const CMPR: usize = 4; + pub const CMPR: usize = 4; // 8-bit field containing the Pad value. - pub const PAD: usize = 5; + pub const PAD: usize = 5; // Variable length field containing addresses pub fn ADDRESSES(length_field: u8) -> Field { let data = DATA(length_field); @@ -234,7 +234,6 @@ impl> Header { data[field::CMPR] >> 4 } - /// Return the number of prefix octects elided from the last address (`addresses[n]`). /// /// # Panics @@ -316,7 +315,7 @@ impl + AsMut<[u8]>> Header { data[7] = 0; } - _ => panic!("Unrecognized routing type when clearing reserved fields.") + _ => panic!("Unrecognized routing type when clearing reserved fields."), } } } @@ -395,59 +394,57 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Header<&'a T> { pub enum Repr<'a> { Type2 { /// The type of header immediately following the Routing header. - next_header: Protocol, + next_header: Protocol, /// Length of the Routing header in 8-octet units, not including the first 8 octets. - length: u8, + length: u8, /// Number of route segments remaining. - segments_left: u8, + segments_left: u8, /// The home address of the destination mobile node. home_address: Address, }, Rpl { /// The type of header immediately following the Routing header. - next_header: Protocol, + next_header: Protocol, /// Length of the Routing header in 8-octet units, not including the first 8 octets. - length: u8, + length: u8, /// Number of route segments remaining. - segments_left: u8, + segments_left: u8, /// Number of prefix octets from each segment, except the last segment, that are elided. - cmpr_i: u8, + cmpr_i: u8, /// Number of prefix octets from the last segment that are elided. - cmpr_e: u8, + cmpr_e: u8, /// Number of octets that are used for padding after `address[n]` at the end of the /// RPL Source Route Header. - pad: u8, + pad: u8, /// Vector of addresses, numbered 1 to `n`. - addresses: &'a[u8], + addresses: &'a [u8], }, } - impl<'a> Repr<'a> { /// Parse an IPv6 Routing Header and return a high-level representation. - pub fn parse(header: &'a Header<&'a T>) -> Result> where T: AsRef<[u8]> + ?Sized { + pub fn parse(header: &'a Header<&'a T>) -> Result> + where + T: AsRef<[u8]> + ?Sized, + { match header.routing_type() { - Type::Type2 => { - Ok(Repr::Type2 { - next_header: header.next_header(), - length: header.header_len(), - segments_left: header.segments_left(), - home_address: header.home_address(), - }) - } - Type::Rpl => { - Ok(Repr::Rpl { - next_header: header.next_header(), - length: header.header_len(), - segments_left: header.segments_left(), - cmpr_i: header.cmpr_i(), - cmpr_e: header.cmpr_e(), - pad: header.pad(), - addresses: header.addresses(), - }) - } + Type::Type2 => Ok(Repr::Type2 { + next_header: header.next_header(), + length: header.header_len(), + segments_left: header.segments_left(), + home_address: header.home_address(), + }), + Type::Rpl => Ok(Repr::Rpl { + next_header: header.next_header(), + length: header.header_len(), + segments_left: header.segments_left(), + cmpr_i: header.cmpr_i(), + cmpr_e: header.cmpr_e(), + pad: header.pad(), + addresses: header.addresses(), + }), - _ => Err(Error::Unrecognized) + _ => Err(Error::Unrecognized), } } @@ -455,16 +452,19 @@ impl<'a> Repr<'a> { /// representation. pub fn buffer_len(&self) -> usize { match self { - &Repr::Rpl { length, .. } | &Repr::Type2 { length, .. } => { - field::DATA(length).end - } + &Repr::Rpl { length, .. } | &Repr::Type2 { length, .. } => field::DATA(length).end, } } /// Emit a high-level representation into an IPv6 Routing Header. pub fn emit + AsMut<[u8]> + ?Sized>(&self, header: &mut Header<&mut T>) { match *self { - Repr::Type2 { next_header, length, segments_left, home_address } => { + Repr::Type2 { + next_header, + length, + segments_left, + home_address, + } => { header.set_next_header(next_header); header.set_header_len(length); header.set_routing_type(Type::Type2); @@ -472,7 +472,15 @@ impl<'a> Repr<'a> { header.clear_reserved(); header.set_home_address(home_address); } - Repr::Rpl { next_header, length, segments_left, cmpr_i, cmpr_e, pad, addresses } => { + Repr::Rpl { + next_header, + length, + segments_left, + cmpr_i, + cmpr_e, + pad, + addresses, + } => { header.set_next_header(next_header); header.set_header_len(length); header.set_routing_type(Type::Rpl); @@ -490,11 +498,31 @@ impl<'a> Repr<'a> { impl<'a> fmt::Display for Repr<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Repr::Type2 { next_header, length, segments_left, home_address } => { - write!(f, "IPv6 Routing next_hdr={} length={} type={} seg_left={} home_address={}", - next_header, length, Type::Type2, segments_left, home_address) + Repr::Type2 { + next_header, + length, + segments_left, + home_address, + } => { + write!( + f, + "IPv6 Routing next_hdr={} length={} type={} seg_left={} home_address={}", + next_header, + length, + Type::Type2, + segments_left, + home_address + ) } - Repr::Rpl { next_header, length, segments_left, cmpr_i, cmpr_e, pad, .. } => { + Repr::Rpl { + next_header, + length, + segments_left, + cmpr_i, + cmpr_e, + pad, + .. + } => { write!(f, "IPv6 Routing next_hdr={} length={} type={} seg_left={} cmpr_i={} cmpr_e={} pad={}", next_header, length, Type::Rpl, segments_left, cmpr_i, cmpr_e, pad) } @@ -507,12 +535,10 @@ mod test { use super::*; // A Type 2 Routing Header - static BYTES_TYPE2: [u8; 24] = [0x6, 0x2, 0x2, 0x1, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1]; + static BYTES_TYPE2: [u8; 24] = [ + 0x6, 0x2, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, + ]; // A representation of a Type 2 Routing header static REPR_TYPE2: Repr = Repr::Type2 { @@ -523,16 +549,11 @@ mod test { }; // A Source Routing Header with full IPv6 addresses in bytes - static BYTES_SRH_FULL: [u8; 40] = [0x6, 0x4, 0x3, 0x2, - 0x0, 0x0, 0x0, 0x0, - 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, - 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0x1]; + static BYTES_SRH_FULL: [u8; 40] = [ + 0x6, 0x4, 0x3, 0x2, 0x0, 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3, 0x1, + ]; // A representation of a Source Routing Header with full IPv6 addresses static REPR_SRH_FULL: Repr = Repr::Rpl { @@ -542,21 +563,16 @@ mod test { cmpr_i: 0, cmpr_e: 0, pad: 0, - addresses: &[0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, - 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0x1] + addresses: &[ + 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x1, + ], }; // A Source Routing Header with elided IPv6 addresses in bytes - static BYTES_SRH_ELIDED: [u8; 16] = [0x6, 0x1, 0x3, 0x2, - 0xfe, 0x50, 0x0, 0x0, - 0x2, 0x3, 0x1, 0x0, - 0x0, 0x0, 0x0, 0x0]; + static BYTES_SRH_ELIDED: [u8; 16] = [ + 0x6, 0x1, 0x3, 0x2, 0xfe, 0x50, 0x0, 0x0, 0x2, 0x3, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, + ]; // A representation of a Source Routing Header with elided IPv6 addresses static REPR_SRH_ELIDED: Repr = Repr::Rpl { @@ -566,20 +582,37 @@ mod test { cmpr_i: 15, cmpr_e: 14, pad: 5, - addresses: &[0x2, 0x3, 0x1, 0x0, - 0x0, 0x0, 0x0, 0x0] + addresses: &[0x2, 0x3, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0], }; #[test] fn test_check_len() { // less than min header size - assert_eq!(Err(Error::Truncated), Header::new(&BYTES_TYPE2[..3]).check_len()); - assert_eq!(Err(Error::Truncated), Header::new(&BYTES_SRH_FULL[..3]).check_len()); - assert_eq!(Err(Error::Truncated), Header::new(&BYTES_SRH_ELIDED[..3]).check_len()); + assert_eq!( + Err(Error::Truncated), + Header::new(&BYTES_TYPE2[..3]).check_len() + ); + assert_eq!( + Err(Error::Truncated), + Header::new(&BYTES_SRH_FULL[..3]).check_len() + ); + assert_eq!( + Err(Error::Truncated), + Header::new(&BYTES_SRH_ELIDED[..3]).check_len() + ); // less than specfied length field - assert_eq!(Err(Error::Truncated), Header::new(&BYTES_TYPE2[..23]).check_len()); - assert_eq!(Err(Error::Truncated), Header::new(&BYTES_SRH_FULL[..39]).check_len()); - assert_eq!(Err(Error::Truncated), Header::new(&BYTES_SRH_ELIDED[..11]).check_len()); + assert_eq!( + Err(Error::Truncated), + Header::new(&BYTES_TYPE2[..23]).check_len() + ); + assert_eq!( + Err(Error::Truncated), + Header::new(&BYTES_SRH_FULL[..39]).check_len() + ); + assert_eq!( + Err(Error::Truncated), + Header::new(&BYTES_SRH_ELIDED[..11]).check_len() + ); // valid assert_eq!(Ok(()), Header::new(&BYTES_TYPE2[..]).check_len()); assert_eq!(Ok(()), Header::new(&BYTES_SRH_FULL[..]).check_len()); diff --git a/src/wire/mld.rs b/src/wire/mld.rs index eb2a329..a859092 100644 --- a/src/wire/mld.rs +++ b/src/wire/mld.rs @@ -6,9 +6,9 @@ use byteorder::{ByteOrder, NetworkEndian}; -use crate::{Error, Result}; use crate::wire::icmpv6::{field, Message, Packet}; use crate::wire::Ipv6Address; +use crate::{Error, Result}; enum_with_unknown! { /// MLDv2 Multicast Listener Report Record Type. See [RFC 3810 § 5.2.12] for @@ -168,7 +168,7 @@ impl + AsMut<[u8]>> Packet { #[derive(Debug, PartialEq, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AddressRecord> { - buffer: T + buffer: T, } impl> AddressRecord { @@ -305,58 +305,61 @@ pub enum Repr<'a> { qrv: u8, qqic: u8, num_srcs: u16, - data: &'a [u8] + data: &'a [u8], }, Report { nr_mcast_addr_rcrds: u16, - data: &'a [u8] - } + data: &'a [u8], + }, } impl<'a> Repr<'a> { /// Parse an MLDv2 packet and return a high-level representation. pub fn parse(packet: &Packet<&'a T>) -> Result> - where T: AsRef<[u8]> + ?Sized { + where + T: AsRef<[u8]> + ?Sized, + { match packet.msg_type() { - Message::MldQuery => { - Ok(Repr::Query { - max_resp_code: packet.max_resp_code(), - mcast_addr: packet.mcast_addr(), - s_flag: packet.s_flag(), - qrv: packet.qrv(), - qqic: packet.qqic(), - num_srcs: packet.num_srcs(), - data: packet.payload() - }) - }, - Message::MldReport => { - Ok(Repr::Report { - nr_mcast_addr_rcrds: packet.nr_mcast_addr_rcrds(), - data: packet.payload() - }) - }, - _ => Err(Error::Unrecognized) + Message::MldQuery => Ok(Repr::Query { + max_resp_code: packet.max_resp_code(), + mcast_addr: packet.mcast_addr(), + s_flag: packet.s_flag(), + qrv: packet.qrv(), + qqic: packet.qqic(), + num_srcs: packet.num_srcs(), + data: packet.payload(), + }), + Message::MldReport => Ok(Repr::Report { + nr_mcast_addr_rcrds: packet.nr_mcast_addr_rcrds(), + data: packet.payload(), + }), + _ => Err(Error::Unrecognized), } } /// Return the length of a packet that will be emitted from this high-level representation. pub fn buffer_len(&self) -> usize { match self { - Repr::Query { .. } => { - field::QUERY_NUM_SRCS.end - } - Repr::Report { .. } => { - field::NR_MCAST_RCRDS.end - } + Repr::Query { .. } => field::QUERY_NUM_SRCS.end, + Repr::Report { .. } => field::NR_MCAST_RCRDS.end, } } /// Emit a high-level representation into an MLDv2 packet. pub fn emit(&self, packet: &mut Packet<&mut T>) - where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized { + where + T: AsRef<[u8]> + AsMut<[u8]> + ?Sized, + { match self { - Repr::Query { max_resp_code, mcast_addr, s_flag, - qrv, qqic, num_srcs, data } => { + Repr::Query { + max_resp_code, + mcast_addr, + s_flag, + qrv, + qqic, + num_srcs, + data, + } => { packet.set_msg_type(Message::MldQuery); packet.set_msg_code(0); packet.clear_reserved(); @@ -371,8 +374,11 @@ impl<'a> Repr<'a> { packet.set_qqic(*qqic); packet.set_num_srcs(*num_srcs); packet.payload_mut().copy_from_slice(&data[..]); - }, - Repr::Report { nr_mcast_addr_rcrds, data } => { + } + Repr::Report { + nr_mcast_addr_rcrds, + data, + } => { packet.set_msg_type(Message::MldReport); packet.set_msg_code(0); packet.clear_reserved(); @@ -385,74 +391,49 @@ impl<'a> Repr<'a> { #[cfg(test)] mod test { - use crate::phy::ChecksumCapabilities; - use crate::wire::Icmpv6Repr; - use crate::wire::icmpv6::Message; use super::*; + use crate::phy::ChecksumCapabilities; + use crate::wire::icmpv6::Message; + use crate::wire::Icmpv6Repr; - static QUERY_PACKET_BYTES: [u8; 44] = - [0x82, 0x00, 0x73, 0x74, - 0x04, 0x00, 0x00, 0x00, - 0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0x0a, 0x12, 0x00, 0x01, - 0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02]; + static QUERY_PACKET_BYTES: [u8; 44] = [ + 0x82, 0x00, 0x73, 0x74, 0x04, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x12, 0x00, 0x01, 0xff, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + ]; - static QUERY_PACKET_PAYLOAD: [u8; 16] = - [0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02]; + static QUERY_PACKET_PAYLOAD: [u8; 16] = [ + 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, + ]; - static REPORT_PACKET_BYTES: [u8; 44] = - [0x8f, 0x00, 0x73, 0x85, - 0x00, 0x00, 0x00, 0x01, - 0x01, 0x00, 0x00, 0x01, - 0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02]; - - static REPORT_PACKET_PAYLOAD: [u8; 36] = - [0x01, 0x00, 0x00, 0x01, - 0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02]; + static REPORT_PACKET_BYTES: [u8; 44] = [ + 0x8f, 0x00, 0x73, 0x85, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + ]; + static REPORT_PACKET_PAYLOAD: [u8; 36] = [ + 0x01, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + ]; fn create_repr<'a>(ty: Message) -> Icmpv6Repr<'a> { match ty { - Message::MldQuery => { - Icmpv6Repr::Mld(Repr::Query { - max_resp_code: 0x400, - mcast_addr: Ipv6Address::LINK_LOCAL_ALL_NODES, - s_flag: true, - qrv: 0x02, - qqic: 0x12, - num_srcs: 0x01, - data: &QUERY_PACKET_PAYLOAD - }) - }, - Message::MldReport => { - Icmpv6Repr::Mld(Repr::Report { - nr_mcast_addr_rcrds: 1, - data: &REPORT_PACKET_PAYLOAD - }) - }, + Message::MldQuery => Icmpv6Repr::Mld(Repr::Query { + max_resp_code: 0x400, + mcast_addr: Ipv6Address::LINK_LOCAL_ALL_NODES, + s_flag: true, + qrv: 0x02, + qqic: 0x12, + num_srcs: 0x01, + data: &QUERY_PACKET_PAYLOAD, + }), + Message::MldReport => Icmpv6Repr::Mld(Repr::Report { + nr_mcast_addr_rcrds: 1, + data: &REPORT_PACKET_PAYLOAD, + }), _ => { panic!("Message type must be a MLDv2 message type"); } @@ -471,8 +452,10 @@ mod test { 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); + assert_eq!( + Ipv6Address::from_bytes(packet.payload()), + Ipv6Address::LINK_LOCAL_ALL_ROUTERS + ); } #[test] @@ -487,10 +470,14 @@ mod test { 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()); + packet + .payload_mut() + .copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes()); packet.clear_reserved(); - packet.fill_checksum(&Ipv6Address::LINK_LOCAL_ALL_NODES.into(), - &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into()); + packet.fill_checksum( + &Ipv6Address::LINK_LOCAL_ALL_NODES.into(), + &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(), + ); assert_eq!(&packet.into_inner()[..], &QUERY_PACKET_BYTES[..]); } @@ -506,8 +493,10 @@ mod test { 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!(Ipv6Address::from_bytes(addr_rcrd.payload()), - Ipv6Address::LINK_LOCAL_ALL_ROUTERS); + assert_eq!( + Ipv6Address::from_bytes(addr_rcrd.payload()), + Ipv6Address::LINK_LOCAL_ALL_ROUTERS + ); } #[test] @@ -524,31 +513,38 @@ mod test { 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.payload_mut() + addr_rcrd + .payload_mut() .copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes()); } - packet.fill_checksum(&Ipv6Address::LINK_LOCAL_ALL_NODES.into(), - &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into()); + packet.fill_checksum( + &Ipv6Address::LINK_LOCAL_ALL_NODES.into(), + &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(), + ); assert_eq!(&packet.into_inner()[..], &REPORT_PACKET_BYTES[..]); } #[test] fn test_query_repr_parse() { let packet = Packet::new_unchecked(&QUERY_PACKET_BYTES[..]); - let repr = Icmpv6Repr::parse(&Ipv6Address::LINK_LOCAL_ALL_NODES.into(), - &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(), - &packet, - &ChecksumCapabilities::default()); + let repr = Icmpv6Repr::parse( + &Ipv6Address::LINK_LOCAL_ALL_NODES.into(), + &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(), + &packet, + &ChecksumCapabilities::default(), + ); assert_eq!(repr, Ok(create_repr(Message::MldQuery))); } #[test] fn test_report_repr_parse() { let packet = Packet::new_unchecked(&REPORT_PACKET_BYTES[..]); - let repr = Icmpv6Repr::parse(&Ipv6Address::LINK_LOCAL_ALL_NODES.into(), - &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(), - &packet, - &ChecksumCapabilities::default()); + let repr = Icmpv6Repr::parse( + &Ipv6Address::LINK_LOCAL_ALL_NODES.into(), + &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(), + &packet, + &ChecksumCapabilities::default(), + ); assert_eq!(repr, Ok(create_repr(Message::MldReport))); } @@ -557,10 +553,12 @@ mod test { let mut bytes = [0x2a; 44]; let mut packet = Packet::new_unchecked(&mut bytes[..]); let repr = create_repr(Message::MldQuery); - repr.emit(&Ipv6Address::LINK_LOCAL_ALL_NODES.into(), - &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(), - &mut packet, - &ChecksumCapabilities::default()); + repr.emit( + &Ipv6Address::LINK_LOCAL_ALL_NODES.into(), + &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(), + &mut packet, + &ChecksumCapabilities::default(), + ); assert_eq!(&packet.into_inner()[..], &QUERY_PACKET_BYTES[..]); } @@ -569,10 +567,12 @@ mod test { let mut bytes = [0x2a; 44]; let mut packet = Packet::new_unchecked(&mut bytes[..]); let repr = create_repr(Message::MldReport); - repr.emit(&Ipv6Address::LINK_LOCAL_ALL_NODES.into(), - &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(), - &mut packet, - &ChecksumCapabilities::default()); + repr.emit( + &Ipv6Address::LINK_LOCAL_ALL_NODES.into(), + &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(), + &mut packet, + &ChecksumCapabilities::default(), + ); assert_eq!(&packet.into_inner()[..], &REPORT_PACKET_BYTES[..]); } } diff --git a/src/wire/mod.rs b/src/wire/mod.rs index 7a7f39c..e1dc18d 100644 --- a/src/wire/mod.rs +++ b/src/wire/mod.rs @@ -72,161 +72,136 @@ let mut buffer = vec![0; repr.buffer_len() + repr.payload_len]; mod field { pub type Field = ::core::ops::Range; - pub type Rest = ::core::ops::RangeFrom; + pub type Rest = ::core::ops::RangeFrom; } pub mod pretty_print; -#[cfg(feature = "medium-ethernet")] -mod ethernet; #[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))] mod arp; +#[cfg(feature = "proto-dhcpv4")] +pub(crate) mod dhcpv4; +#[cfg(feature = "medium-ethernet")] +mod ethernet; +#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))] +mod icmp; +#[cfg(feature = "proto-ipv4")] +mod icmpv4; +#[cfg(feature = "proto-ipv6")] +mod icmpv6; +#[cfg(feature = "proto-igmp")] +mod igmp; pub(crate) mod ip; #[cfg(feature = "proto-ipv4")] mod ipv4; #[cfg(feature = "proto-ipv6")] mod ipv6; #[cfg(feature = "proto-ipv6")] -mod ipv6option; +mod ipv6fragment; #[cfg(feature = "proto-ipv6")] mod ipv6hopbyhop; #[cfg(feature = "proto-ipv6")] -mod ipv6fragment; +mod ipv6option; #[cfg(feature = "proto-ipv6")] mod ipv6routing; -#[cfg(feature = "proto-ipv4")] -mod icmpv4; #[cfg(feature = "proto-ipv6")] -mod icmpv6; -#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))] -mod icmp; -#[cfg(feature = "proto-igmp")] -mod igmp; +mod mld; #[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))] mod ndisc; #[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))] mod ndiscoption; -#[cfg(feature = "proto-ipv6")] -mod mld; -mod udp; mod tcp; -#[cfg(feature = "proto-dhcpv4")] -pub(crate) mod dhcpv4; +mod udp; pub use self::pretty_print::PrettyPrinter; #[cfg(feature = "medium-ethernet")] -pub use self::ethernet::{EtherType as EthernetProtocol, - Address as EthernetAddress, - Frame as EthernetFrame, - HEADER_LEN as ETHERNET_HEADER_LEN, - Repr as EthernetRepr}; +pub use self::ethernet::{ + Address as EthernetAddress, EtherType as EthernetProtocol, Frame as EthernetFrame, + Repr as EthernetRepr, HEADER_LEN as ETHERNET_HEADER_LEN, +}; #[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))] -pub use self::arp::{Hardware as ArpHardware, - Operation as ArpOperation, - Packet as ArpPacket, - Repr as ArpRepr}; +pub use self::arp::{ + Hardware as ArpHardware, Operation as ArpOperation, Packet as ArpPacket, Repr as ArpRepr, +}; -pub use self::ip::{Version as IpVersion, - Protocol as IpProtocol, - Address as IpAddress, - Endpoint as IpEndpoint, - Repr as IpRepr, - Cidr as IpCidr}; +pub use self::ip::{ + Address as IpAddress, Cidr as IpCidr, Endpoint as IpEndpoint, Protocol as IpProtocol, + Repr as IpRepr, Version as IpVersion, +}; #[cfg(feature = "proto-ipv4")] -pub use self::ipv4::{Address as Ipv4Address, - Packet as Ipv4Packet, - Repr as Ipv4Repr, - Cidr as Ipv4Cidr, - HEADER_LEN as IPV4_HEADER_LEN, - MIN_MTU as IPV4_MIN_MTU}; +pub use self::ipv4::{ + Address as Ipv4Address, Cidr as Ipv4Cidr, Packet as Ipv4Packet, Repr as Ipv4Repr, + HEADER_LEN as IPV4_HEADER_LEN, MIN_MTU as IPV4_MIN_MTU, +}; #[cfg(feature = "proto-ipv6")] -pub use self::ipv6::{Address as Ipv6Address, - Packet as Ipv6Packet, - Repr as Ipv6Repr, - Cidr as Ipv6Cidr, - HEADER_LEN as IPV6_HEADER_LEN, - MIN_MTU as IPV6_MIN_MTU}; +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, +}; #[cfg(feature = "proto-ipv6")] -pub use self::ipv6option::{Ipv6Option, - Repr as Ipv6OptionRepr, - Type as Ipv6OptionType, - FailureType as Ipv6OptionFailureType}; +pub use self::ipv6option::{ + FailureType as Ipv6OptionFailureType, Ipv6Option, Repr as Ipv6OptionRepr, + Type as Ipv6OptionType, +}; #[cfg(feature = "proto-ipv6")] -pub use self::ipv6hopbyhop::{Header as Ipv6HopByHopHeader, - Repr as Ipv6HopByHopRepr}; +pub use self::ipv6hopbyhop::{Header as Ipv6HopByHopHeader, Repr as Ipv6HopByHopRepr}; #[cfg(feature = "proto-ipv6")] -pub use self::ipv6fragment::{Header as Ipv6FragmentHeader, - Repr as Ipv6FragmentRepr}; +pub use self::ipv6fragment::{Header as Ipv6FragmentHeader, Repr as Ipv6FragmentRepr}; #[cfg(feature = "proto-ipv6")] -pub use self::ipv6routing::{Header as Ipv6RoutingHeader, - Repr as Ipv6RoutingRepr}; +pub use self::ipv6routing::{Header as Ipv6RoutingHeader, Repr as Ipv6RoutingRepr}; #[cfg(feature = "proto-ipv4")] -pub use self::icmpv4::{Message as Icmpv4Message, - DstUnreachable as Icmpv4DstUnreachable, - Redirect as Icmpv4Redirect, - TimeExceeded as Icmpv4TimeExceeded, - ParamProblem as Icmpv4ParamProblem, - Packet as Icmpv4Packet, - Repr as Icmpv4Repr}; +pub use self::icmpv4::{ + DstUnreachable as Icmpv4DstUnreachable, Message as Icmpv4Message, Packet as Icmpv4Packet, + ParamProblem as Icmpv4ParamProblem, Redirect as Icmpv4Redirect, Repr as Icmpv4Repr, + TimeExceeded as Icmpv4TimeExceeded, +}; #[cfg(feature = "proto-igmp")] -pub use self::igmp::{Packet as IgmpPacket, - Repr as IgmpRepr, - IgmpVersion}; +pub use self::igmp::{IgmpVersion, Packet as IgmpPacket, Repr as IgmpRepr}; #[cfg(feature = "proto-ipv6")] -pub use self::icmpv6::{Message as Icmpv6Message, - DstUnreachable as Icmpv6DstUnreachable, - TimeExceeded as Icmpv6TimeExceeded, - ParamProblem as Icmpv6ParamProblem, - Packet as Icmpv6Packet, - Repr as Icmpv6Repr}; +pub use self::icmpv6::{ + DstUnreachable as Icmpv6DstUnreachable, Message as Icmpv6Message, Packet as Icmpv6Packet, + ParamProblem as Icmpv6ParamProblem, Repr as Icmpv6Repr, TimeExceeded as Icmpv6TimeExceeded, +}; #[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))] pub use self::icmp::Repr as IcmpRepr; +#[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))] +pub use self::ndisc::{ + NeighborFlags as NdiscNeighborFlags, Repr as NdiscRepr, RouterFlags as NdiscRouterFlags, +}; #[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))] -pub use self::ndisc::{Repr as NdiscRepr, - RouterFlags as NdiscRouterFlags, - NeighborFlags as NdiscNeighborFlags}; - -#[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))] -pub use self::ndiscoption::{NdiscOption, - Repr as NdiscOptionRepr, - Type as NdiscOptionType, - PrefixInformation as NdiscPrefixInformation, - RedirectedHeader as NdiscRedirectedHeader, - PrefixInfoFlags as NdiscPrefixInfoFlags}; +pub use self::ndiscoption::{ + NdiscOption, PrefixInfoFlags as NdiscPrefixInfoFlags, + PrefixInformation as NdiscPrefixInformation, RedirectedHeader as NdiscRedirectedHeader, + Repr as NdiscOptionRepr, Type as NdiscOptionType, +}; #[cfg(feature = "proto-ipv6")] -pub use self::mld::{AddressRecord as MldAddressRecord, - Repr as MldRepr}; +pub use self::mld::{AddressRecord as MldAddressRecord, Repr as MldRepr}; -pub use self::udp::{Packet as UdpPacket, - Repr as UdpRepr, - HEADER_LEN as UDP_HEADER_LEN}; +pub use self::udp::{Packet as UdpPacket, Repr as UdpRepr, HEADER_LEN as UDP_HEADER_LEN}; -pub use self::tcp::{SeqNumber as TcpSeqNumber, - Packet as TcpPacket, - TcpOption, - Repr as TcpRepr, - Control as TcpControl, - HEADER_LEN as TCP_HEADER_LEN}; +pub use self::tcp::{ + Control as TcpControl, Packet as TcpPacket, Repr as TcpRepr, SeqNumber as TcpSeqNumber, + TcpOption, HEADER_LEN as TCP_HEADER_LEN, +}; #[cfg(feature = "proto-dhcpv4")] -pub use self::dhcpv4::{Packet as DhcpPacket, - Repr as DhcpRepr, - MessageType as DhcpMessageType, - CLIENT_PORT as DHCP_CLIENT_PORT, - SERVER_PORT as DHCP_SERVER_PORT, - MAX_DNS_SERVER_COUNT as DHCP_MAX_DNS_SERVER_COUNT}; +pub use self::dhcpv4::{ + MessageType as DhcpMessageType, Packet as DhcpPacket, Repr as DhcpRepr, + CLIENT_PORT as DHCP_CLIENT_PORT, MAX_DNS_SERVER_COUNT as DHCP_MAX_DNS_SERVER_COUNT, + SERVER_PORT as DHCP_SERVER_PORT, +}; diff --git a/src/wire/ndisc.rs b/src/wire/ndisc.rs index b31cb1c..89c8c71 100644 --- a/src/wire/ndisc.rs +++ b/src/wire/ndisc.rs @@ -1,13 +1,13 @@ -use byteorder::{ByteOrder, NetworkEndian}; use bitflags::bitflags; +use byteorder::{ByteOrder, NetworkEndian}; -use crate::{Error, Result}; +use crate::time::Duration; use crate::wire::icmpv6::{field, Message, Packet}; -use crate::wire::{EthernetAddress, Ipv6Repr, Ipv6Packet}; +use crate::wire::Ipv6Address; +use crate::wire::{EthernetAddress, Ipv6Packet, Ipv6Repr}; use crate::wire::{NdiscOption, NdiscOptionRepr, NdiscOptionType}; use crate::wire::{NdiscPrefixInformation, NdiscRedirectedHeader}; -use crate::time::Duration; -use crate::wire::Ipv6Address; +use crate::{Error, Result}; bitflags! { #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -82,7 +82,6 @@ impl> Packet { } } - /// Getters for the Neighbor Solicitation message header. /// See [RFC 4861 § 4.3]. /// @@ -194,7 +193,7 @@ impl + AsMut<[u8]>> Packet { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Repr<'a> { RouterSolicit { - lladdr: Option + lladdr: Option, }, RouterAdvert { hop_limit: u8, @@ -204,44 +203,47 @@ pub enum Repr<'a> { retrans_time: Duration, lladdr: Option, mtu: Option, - prefix_info: Option + prefix_info: Option, }, NeighborSolicit { target_addr: Ipv6Address, - lladdr: Option + lladdr: Option, }, NeighborAdvert { flags: NeighborFlags, target_addr: Ipv6Address, - lladdr: Option + lladdr: Option, }, Redirect { target_addr: Ipv6Address, dest_addr: Ipv6Address, lladdr: Option, - redirected_hdr: Option> - } + redirected_hdr: Option>, + }, } impl<'a> Repr<'a> { /// Parse an NDISC packet and return a high-level representation of the /// packet. - pub fn parse(packet: &Packet<&'a T>) - -> Result> - where T: AsRef<[u8]> + ?Sized { + pub fn parse(packet: &Packet<&'a T>) -> Result> + where + T: AsRef<[u8]> + ?Sized, + { match packet.msg_type() { Message::RouterSolicit => { let lladdr = if !packet.payload().is_empty() { let opt = NdiscOption::new_checked(packet.payload())?; match opt.option_type() { NdiscOptionType::SourceLinkLayerAddr => Some(opt.link_layer_addr()), - _ => { return Err(Error::Unrecognized); } + _ => { + return Err(Error::Unrecognized); + } } } else { None }; Ok(Repr::RouterSolicit { lladdr }) - }, + } Message::RouterAdvert => { let mut offset = 0; let (mut lladdr, mut mtu, mut prefix_info) = (None, None, None); @@ -252,7 +254,9 @@ impl<'a> Repr<'a> { NdiscOptionRepr::SourceLinkLayerAddr(addr) => lladdr = Some(addr), NdiscOptionRepr::Mtu(val) => mtu = Some(val), NdiscOptionRepr::PrefixInformation(info) => prefix_info = Some(info), - _ => { return Err(Error::Unrecognized); } + _ => { + return Err(Error::Unrecognized); + } } offset += opt.buffer_len(); } @@ -262,29 +266,36 @@ impl<'a> Repr<'a> { router_lifetime: packet.router_lifetime(), reachable_time: packet.reachable_time(), retrans_time: packet.retrans_time(), - lladdr, mtu, prefix_info + lladdr, + mtu, + prefix_info, }) - }, + } Message::NeighborSolicit => { let lladdr = if !packet.payload().is_empty() { let opt = NdiscOption::new_checked(packet.payload())?; match opt.option_type() { NdiscOptionType::SourceLinkLayerAddr => Some(opt.link_layer_addr()), - _ => { return Err(Error::Unrecognized); } + _ => { + return Err(Error::Unrecognized); + } } } else { None }; Ok(Repr::NeighborSolicit { - target_addr: packet.target_addr(), lladdr + target_addr: packet.target_addr(), + lladdr, }) - }, + } Message::NeighborAdvert => { let lladdr = if !packet.payload().is_empty() { let opt = NdiscOption::new_checked(packet.payload())?; match opt.option_type() { NdiscOptionType::TargetLinkLayerAddr => Some(opt.link_layer_addr()), - _ => { return Err(Error::Unrecognized); } + _ => { + return Err(Error::Unrecognized); + } } } else { None @@ -292,9 +303,9 @@ impl<'a> Repr<'a> { Ok(Repr::NeighborAdvert { flags: packet.neighbor_flags(), target_addr: packet.target_addr(), - lladdr + lladdr, }) - }, + } Message::Redirect => { let mut offset = 0; let (mut lladdr, mut redirected_hdr) = (None, None); @@ -304,43 +315,50 @@ impl<'a> Repr<'a> { NdiscOptionType::SourceLinkLayerAddr => { lladdr = Some(opt.link_layer_addr()); offset += 8; - }, + } NdiscOptionType::RedirectedHeader => { if opt.data_len() < 6 { - return Err(Error::Truncated) + return Err(Error::Truncated); } else { let ip_packet = Ipv6Packet::new_unchecked(&opt.data()[offset + 8..]); let ip_repr = Ipv6Repr::parse(&ip_packet)?; let data = &opt.data()[offset + 8 + ip_repr.buffer_len()..]; redirected_hdr = Some(NdiscRedirectedHeader { - header: ip_repr, data + header: ip_repr, + data, }); offset += 8 + ip_repr.buffer_len() + data.len(); } } - _ => { return Err(Error::Unrecognized); } + _ => { + return Err(Error::Unrecognized); + } } } Ok(Repr::Redirect { target_addr: packet.target_addr(), dest_addr: packet.dest_addr(), - lladdr, redirected_hdr + lladdr, + redirected_hdr, }) - }, - _ => Err(Error::Unrecognized) + } + _ => Err(Error::Unrecognized), } } pub fn buffer_len(&self) -> usize { match self { - &Repr::RouterSolicit { lladdr } => { - match lladdr { - Some(_) => field::UNUSED.end + 8, - None => field::UNUSED.end, - } + &Repr::RouterSolicit { lladdr } => match lladdr { + Some(_) => field::UNUSED.end + 8, + None => field::UNUSED.end, }, - &Repr::RouterAdvert { lladdr, mtu, prefix_info, .. } => { + &Repr::RouterAdvert { + lladdr, + mtu, + prefix_info, + .. + } => { let mut offset = 0; if lladdr.is_some() { offset += 8; @@ -352,14 +370,18 @@ impl<'a> Repr<'a> { offset += 32; } field::RETRANS_TM.end + offset - }, + } &Repr::NeighborSolicit { lladdr, .. } | &Repr::NeighborAdvert { lladdr, .. } => { match lladdr { Some(_) => field::TARGET_ADDR.end + 8, None => field::TARGET_ADDR.end, } - }, - &Repr::Redirect { lladdr, redirected_hdr, .. } => { + } + &Repr::Redirect { + lladdr, + redirected_hdr, + .. + } => { let mut offset = 0; if lladdr.is_some() { offset += 8; @@ -373,7 +395,9 @@ impl<'a> Repr<'a> { } pub fn emit(&self, packet: &mut Packet<&mut T>) - where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized { + where + T: AsRef<[u8]> + AsMut<[u8]> + ?Sized, + { match *self { Repr::RouterSolicit { lladdr } => { packet.set_msg_type(Message::RouterSolicit); @@ -383,10 +407,18 @@ impl<'a> Repr<'a> { let mut opt_pkt = NdiscOption::new_unchecked(packet.payload_mut()); NdiscOptionRepr::SourceLinkLayerAddr(lladdr).emit(&mut opt_pkt); } - }, + } - Repr::RouterAdvert { hop_limit, flags, router_lifetime, reachable_time, - retrans_time, lladdr, mtu, prefix_info } => { + Repr::RouterAdvert { + hop_limit, + flags, + router_lifetime, + reachable_time, + retrans_time, + lladdr, + mtu, + prefix_info, + } => { packet.set_msg_type(Message::RouterAdvert); packet.set_msg_code(0); packet.set_current_hop_limit(hop_limit); @@ -396,8 +428,7 @@ impl<'a> Repr<'a> { packet.set_retrans_time(retrans_time); let mut offset = 0; if let Some(lladdr) = lladdr { - let mut opt_pkt = - NdiscOption::new_unchecked(packet.payload_mut()); + let mut opt_pkt = NdiscOption::new_unchecked(packet.payload_mut()); NdiscOptionRepr::SourceLinkLayerAddr(lladdr).emit(&mut opt_pkt); offset += 8; } @@ -412,34 +443,44 @@ impl<'a> Repr<'a> { NdiscOption::new_unchecked(&mut packet.payload_mut()[offset..]); NdiscOptionRepr::PrefixInformation(prefix_info).emit(&mut opt_pkt) } - }, + } - Repr::NeighborSolicit { target_addr, lladdr } => { + Repr::NeighborSolicit { + target_addr, + lladdr, + } => { packet.set_msg_type(Message::NeighborSolicit); packet.set_msg_code(0); packet.clear_reserved(); packet.set_target_addr(target_addr); if let Some(lladdr) = lladdr { - let mut opt_pkt = - NdiscOption::new_unchecked(packet.payload_mut()); + let mut opt_pkt = NdiscOption::new_unchecked(packet.payload_mut()); NdiscOptionRepr::SourceLinkLayerAddr(lladdr).emit(&mut opt_pkt); } - }, + } - Repr::NeighborAdvert { flags, target_addr, lladdr } => { + Repr::NeighborAdvert { + flags, + target_addr, + lladdr, + } => { packet.set_msg_type(Message::NeighborAdvert); packet.set_msg_code(0); packet.clear_reserved(); packet.set_neighbor_flags(flags); packet.set_target_addr(target_addr); if let Some(lladdr) = lladdr { - let mut opt_pkt = - NdiscOption::new_unchecked(packet.payload_mut()); + let mut opt_pkt = NdiscOption::new_unchecked(packet.payload_mut()); NdiscOptionRepr::TargetLinkLayerAddr(lladdr).emit(&mut opt_pkt); } - }, + } - Repr::Redirect { target_addr, dest_addr, lladdr, redirected_hdr } => { + Repr::Redirect { + target_addr, + dest_addr, + lladdr, + redirected_hdr, + } => { packet.set_msg_type(Message::Redirect); packet.set_msg_code(0); packet.clear_reserved(); @@ -447,11 +488,10 @@ impl<'a> Repr<'a> { packet.set_dest_addr(dest_addr); let offset = match lladdr { Some(lladdr) => { - let mut opt_pkt = - NdiscOption::new_unchecked(packet.payload_mut()); + let mut opt_pkt = NdiscOption::new_unchecked(packet.payload_mut()); NdiscOptionRepr::TargetLinkLayerAddr(lladdr).emit(&mut opt_pkt); 8 - }, + } None => 0, }; if let Some(redirected_hdr) = redirected_hdr { @@ -459,28 +499,23 @@ impl<'a> Repr<'a> { NdiscOption::new_unchecked(&mut packet.payload_mut()[offset..]); NdiscOptionRepr::RedirectedHeader(redirected_hdr).emit(&mut opt_pkt); } - }, + } } } } #[cfg(test)] mod test { - use crate::phy::ChecksumCapabilities; use super::*; - use crate::wire::Icmpv6Repr; + use crate::phy::ChecksumCapabilities; use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2}; + use crate::wire::Icmpv6Repr; - static ROUTER_ADVERT_BYTES: [u8; 24] = - [0x86, 0x00, 0xa9, 0xde, - 0x40, 0x80, 0x03, 0x84, - 0x00, 0x00, 0x03, 0x84, - 0x00, 0x00, 0x03, 0x84, - 0x01, 0x01, 0x52, 0x54, - 0x00, 0x12, 0x34, 0x56]; - static SOURCE_LINK_LAYER_OPT: [u8; 8] = - [0x01, 0x01, 0x52, 0x54, - 0x00, 0x12, 0x34, 0x56]; + static ROUTER_ADVERT_BYTES: [u8; 24] = [ + 0x86, 0x00, 0xa9, 0xde, 0x40, 0x80, 0x03, 0x84, 0x00, 0x00, 0x03, 0x84, 0x00, 0x00, 0x03, + 0x84, 0x01, 0x01, 0x52, 0x54, 0x00, 0x12, 0x34, 0x56, + ]; + static SOURCE_LINK_LAYER_OPT: [u8; 8] = [0x01, 0x01, 0x52, 0x54, 0x00, 0x12, 0x34, 0x56]; fn create_repr<'a>() -> Icmpv6Repr<'a> { Icmpv6Repr::Ndisc(Repr::RouterAdvert { @@ -491,7 +526,7 @@ mod test { retrans_time: Duration::from_millis(900), lladdr: Some(EthernetAddress([0x52, 0x54, 0x00, 0x12, 0x34, 0x56])), mtu: None, - prefix_info: None + prefix_info: None, }) } @@ -519,7 +554,9 @@ mod test { packet.set_router_lifetime(Duration::from_secs(900)); packet.set_reachable_time(Duration::from_millis(900)); packet.set_retrans_time(Duration::from_millis(900)); - packet.payload_mut().copy_from_slice(&SOURCE_LINK_LAYER_OPT[..]); + packet + .payload_mut() + .copy_from_slice(&SOURCE_LINK_LAYER_OPT[..]); packet.fill_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2); assert_eq!(&packet.into_inner()[..], &ROUTER_ADVERT_BYTES[..]); } @@ -527,17 +564,28 @@ mod test { #[test] fn test_router_advert_repr_parse() { let packet = Packet::new_unchecked(&ROUTER_ADVERT_BYTES[..]); - assert_eq!(Icmpv6Repr::parse(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2, - &packet, &ChecksumCapabilities::default()).unwrap(), - create_repr()); + assert_eq!( + Icmpv6Repr::parse( + &MOCK_IP_ADDR_1, + &MOCK_IP_ADDR_2, + &packet, + &ChecksumCapabilities::default() + ) + .unwrap(), + create_repr() + ); } #[test] fn test_router_advert_repr_emit() { let mut bytes = vec![0x2a; 24]; let mut packet = Packet::new_unchecked(&mut bytes[..]); - create_repr().emit(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2, - &mut packet, &ChecksumCapabilities::default()); + create_repr().emit( + &MOCK_IP_ADDR_1, + &MOCK_IP_ADDR_2, + &mut packet, + &ChecksumCapabilities::default(), + ); assert_eq!(&packet.into_inner()[..], &ROUTER_ADVERT_BYTES[..]); } } diff --git a/src/wire/ndiscoption.rs b/src/wire/ndiscoption.rs index b0426bd..6c79b5f 100644 --- a/src/wire/ndiscoption.rs +++ b/src/wire/ndiscoption.rs @@ -1,10 +1,10 @@ -use core::fmt; -use byteorder::{NetworkEndian, ByteOrder}; use bitflags::bitflags; +use byteorder::{ByteOrder, NetworkEndian}; +use core::fmt; -use crate::{Error, Result}; use crate::time::Duration; use crate::wire::{EthernetAddress, Ipv6Address, Ipv6Packet, Ipv6Repr}; +use crate::{Error, Result}; enum_with_unknown! { /// NDISC Option Type @@ -27,10 +27,10 @@ impl fmt::Display for Type { match self { Type::SourceLinkLayerAddr => write!(f, "source link-layer address"), Type::TargetLinkLayerAddr => write!(f, "target link-layer address"), - Type::PrefixInformation => write!(f, "prefix information"), - Type::RedirectedHeader => write!(f, "redirected header"), - Type::Mtu => write!(f, "mtu"), - Type::Unknown(id) => write!(f, "{}", id) + Type::PrefixInformation => write!(f, "prefix information"), + Type::RedirectedHeader => write!(f, "redirected header"), + Type::Mtu => write!(f, "mtu"), + Type::Unknown(id) => write!(f, "{}", id), } } } @@ -49,7 +49,7 @@ bitflags! { #[derive(Debug, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct NdiscOption> { - buffer: T + buffer: T, } // Format of an NDISC Option @@ -67,11 +67,11 @@ mod field { use crate::wire::field::*; // 8-bit identifier of the type of option. - pub const TYPE: usize = 0; + pub const TYPE: usize = 0; // 8-bit unsigned integer. Length of the option, in units of 8 octests. - pub const LENGTH: usize = 1; + pub const LENGTH: usize = 1; // Minimum length of an option. - pub const MIN_OPT_LEN: usize = 8; + pub const MIN_OPT_LEN: usize = 8; // Variable-length field. Option-Type-specific data. pub fn DATA(length: u8) -> Field { 2..length as usize * 8 @@ -83,7 +83,7 @@ mod field { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // Link-Layer Address - pub const LL_ADDR: Field = 2..8; + pub const LL_ADDR: Field = 2..8; // Prefix Information Option fields. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -105,17 +105,17 @@ mod field { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // Prefix length. - pub const PREFIX_LEN: usize = 2; + pub const PREFIX_LEN: usize = 2; // Flags field of prefix header. - pub const FLAGS: usize = 3; + pub const FLAGS: usize = 3; // Valid lifetime. - pub const VALID_LT: Field = 4..8; + pub const VALID_LT: Field = 4..8; // Preferred lifetime. - pub const PREF_LT: Field = 8..12; + pub const PREF_LT: Field = 8..12; // Reserved bits pub const PREF_RESERVED: Field = 12..16; // Prefix - pub const PREFIX: Field = 16..32; + pub const PREFIX: Field = 16..32; // Redirected Header Option fields. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -129,10 +129,10 @@ mod field { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // Reserved bits. - pub const IP_RESERVED: Field = 4..8; + pub const IP_RESERVED: Field = 4..8; // Redirected header IP header + data. - pub const IP_DATA: usize = 8; - pub const REDIR_MIN_SZ: usize = 48; + pub const IP_DATA: usize = 8; + pub const REDIR_MIN_SZ: usize = 48; // MTU Option fields // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -142,7 +142,7 @@ mod field { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // MTU - pub const MTU: Field = 4..8; + pub const MTU: Field = 4..8; } /// Core getter methods relevant to any type of NDISC option. @@ -180,16 +180,11 @@ impl> NdiscOption { Err(Error::Truncated) } else { match self.option_type() { - Type::SourceLinkLayerAddr | Type::TargetLinkLayerAddr | Type::Mtu => - Ok(()), - Type::PrefixInformation if data_range.end >= field::PREFIX.end => - Ok(()), - Type::RedirectedHeader if data_range.end >= field::REDIR_MIN_SZ => - Ok(()), - Type::Unknown(_) => - Ok(()), - _ => - Err(Error::Truncated), + Type::SourceLinkLayerAddr | Type::TargetLinkLayerAddr | Type::Mtu => Ok(()), + Type::PrefixInformation if data_range.end >= field::PREFIX.end => Ok(()), + Type::RedirectedHeader if data_range.end >= field::REDIR_MIN_SZ => Ok(()), + Type::Unknown(_) => Ok(()), + _ => Err(Error::Truncated), } } } @@ -371,7 +366,6 @@ impl + AsMut<[u8]>> NdiscOption { } } - impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> NdiscOption<&'a mut T> { /// Return a mutable pointer to the option data. #[inline] @@ -401,14 +395,14 @@ pub struct PrefixInformation { pub flags: PrefixInfoFlags, pub valid_lifetime: Duration, pub preferred_lifetime: Duration, - pub prefix: Ipv6Address + pub prefix: Ipv6Address, } #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct RedirectedHeader<'a> { pub header: Ipv6Repr, - pub data: &'a [u8] + pub data: &'a [u8], } /// A high-level representation of an NDISC Option. @@ -421,16 +415,18 @@ pub enum Repr<'a> { RedirectedHeader(RedirectedHeader<'a>), Mtu(u32), Unknown { - type_: u8, + type_: u8, length: u8, - data: &'a [u8] + data: &'a [u8], }, } impl<'a> Repr<'a> { /// Parse an NDISC Option and return a high-level representation. pub fn parse(opt: &'a NdiscOption<&'a T>) -> Result> - where T: AsRef<[u8]> + ?Sized { + where + T: AsRef<[u8]> + ?Sized, + { match opt.option_type() { Type::SourceLinkLayerAddr => { if opt.data_len() == 1 { @@ -438,14 +434,14 @@ impl<'a> Repr<'a> { } else { Err(Error::Malformed) } - }, + } Type::TargetLinkLayerAddr => { if opt.data_len() == 1 { Ok(Repr::TargetLinkLayerAddr(opt.link_layer_addr())) } else { Err(Error::Malformed) } - }, + } Type::PrefixInformation => { if opt.data_len() == 4 { Ok(Repr::PrefixInformation(PrefixInformation { @@ -453,12 +449,12 @@ impl<'a> Repr<'a> { flags: opt.prefix_flags(), valid_lifetime: opt.valid_lifetime(), preferred_lifetime: opt.preferred_lifetime(), - prefix: opt.prefix() + prefix: opt.prefix(), })) } else { Err(Error::Malformed) } - }, + } Type::RedirectedHeader => { // If the options data length is less than 6, the option // does not have enough data to fill out the IP header @@ -470,60 +466,60 @@ impl<'a> Repr<'a> { let ip_repr = Ipv6Repr::parse(&ip_packet)?; Ok(Repr::RedirectedHeader(RedirectedHeader { header: ip_repr, - data: &opt.data()[field::IP_DATA + ip_repr.buffer_len()..] + data: &opt.data()[field::IP_DATA + ip_repr.buffer_len()..], })) } - }, + } Type::Mtu => { if opt.data_len() == 1 { Ok(Repr::Mtu(opt.mtu())) } else { Err(Error::Malformed) } - }, - Type::Unknown(id) => { - Ok(Repr::Unknown { - type_: id, - length: opt.data_len(), - data: opt.data() - }) } + Type::Unknown(id) => Ok(Repr::Unknown { + type_: id, + length: opt.data_len(), + data: opt.data(), + }), } } /// Return the length of a header that will be emitted from this high-level representation. pub fn buffer_len(&self) -> usize { match self { - &Repr::SourceLinkLayerAddr(_) | &Repr::TargetLinkLayerAddr(_) => - field::LL_ADDR.end, - &Repr::PrefixInformation(_) => - field::PREFIX.end, - &Repr::RedirectedHeader(RedirectedHeader { header, data }) => - field::IP_DATA + header.buffer_len() + data.len(), - &Repr::Mtu(_) => - field::MTU.end, - &Repr::Unknown { length, .. } => - field::DATA(length).end + &Repr::SourceLinkLayerAddr(_) | &Repr::TargetLinkLayerAddr(_) => field::LL_ADDR.end, + &Repr::PrefixInformation(_) => field::PREFIX.end, + &Repr::RedirectedHeader(RedirectedHeader { header, data }) => { + field::IP_DATA + header.buffer_len() + data.len() + } + &Repr::Mtu(_) => field::MTU.end, + &Repr::Unknown { length, .. } => field::DATA(length).end, } } /// Emit a high-level representation into an NDISC Option. pub fn emit(&self, opt: &mut NdiscOption<&'a mut T>) - where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized { + where + T: AsRef<[u8]> + AsMut<[u8]> + ?Sized, + { match *self { Repr::SourceLinkLayerAddr(addr) => { opt.set_option_type(Type::SourceLinkLayerAddr); opt.set_data_len(1); opt.set_link_layer_addr(addr); - }, + } Repr::TargetLinkLayerAddr(addr) => { opt.set_option_type(Type::TargetLinkLayerAddr); opt.set_data_len(1); opt.set_link_layer_addr(addr); - }, + } Repr::PrefixInformation(PrefixInformation { - prefix_len, flags, valid_lifetime, - preferred_lifetime, prefix + prefix_len, + flags, + valid_lifetime, + preferred_lifetime, + prefix, }) => { opt.clear_prefix_reserved(); opt.set_option_type(Type::PrefixInformation); @@ -533,10 +529,8 @@ impl<'a> Repr<'a> { opt.set_valid_lifetime(valid_lifetime); opt.set_preferred_lifetime(preferred_lifetime); opt.set_prefix(prefix); - }, - Repr::RedirectedHeader(RedirectedHeader { - header, data - }) => { + } + Repr::RedirectedHeader(RedirectedHeader { header, data }) => { let data_len = data.len() / 8; opt.clear_redirected_reserved(); opt.set_option_type(Type::RedirectedHeader); @@ -552,7 +546,11 @@ impl<'a> Repr<'a> { opt.set_data_len(1); opt.set_mtu(mtu); } - Repr::Unknown { type_: id, length, data } => { + Repr::Unknown { + type_: id, + length, + data, + } => { opt.set_option_type(Type::Unknown(id)); opt.set_data_len(length); opt.data_mut().copy_from_slice(data); @@ -567,67 +565,61 @@ impl<'a> fmt::Display for Repr<'a> { match *self { Repr::SourceLinkLayerAddr(addr) => { write!(f, "SourceLinkLayer addr={}", addr) - }, + } Repr::TargetLinkLayerAddr(addr) => { write!(f, "TargetLinkLayer addr={}", addr) - }, + } Repr::PrefixInformation(PrefixInformation { - prefix, prefix_len, - .. + prefix, prefix_len, .. }) => { write!(f, "PrefixInformation prefix={}/{}", prefix, prefix_len) - }, - Repr::RedirectedHeader(RedirectedHeader { - header, - .. - }) => { + } + Repr::RedirectedHeader(RedirectedHeader { header, .. }) => { write!(f, "RedirectedHeader header={}", header) - }, + } Repr::Mtu(mtu) => { write!(f, "MTU mtu={}", mtu) - }, - Repr::Unknown { type_: id, length, .. } => { + } + Repr::Unknown { + type_: id, length, .. + } => { write!(f, "Unknown({}) length={}", id, length) } } } } -use crate::wire::pretty_print::{PrettyPrint, PrettyIndent}; +use crate::wire::pretty_print::{PrettyIndent, PrettyPrint}; impl> PrettyPrint for NdiscOption { - fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter, - indent: &mut PrettyIndent) -> fmt::Result { + fn pretty_print( + buffer: &dyn AsRef<[u8]>, + f: &mut fmt::Formatter, + indent: &mut PrettyIndent, + ) -> fmt::Result { match NdiscOption::new_checked(buffer) { Err(err) => return write!(f, "{}({})", indent, err), - Ok(ndisc) => { - match Repr::parse(&ndisc) { - Err(_) => Ok(()), - Ok(repr) => { - write!(f, "{}{}", indent, repr) - } + Ok(ndisc) => match Repr::parse(&ndisc) { + Err(_) => Ok(()), + Ok(repr) => { + write!(f, "{}{}", indent, repr) } - } + }, } } } #[cfg(test)] mod test { - use crate::Error; + use super::{NdiscOption, PrefixInfoFlags, PrefixInformation, Repr, Type}; use crate::time::Duration; use crate::wire::{EthernetAddress, Ipv6Address}; - use super::{NdiscOption, Type, PrefixInfoFlags, PrefixInformation, Repr}; + use crate::Error; static PREFIX_OPT_BYTES: [u8; 32] = [ - 0x03, 0x04, 0x40, 0xc0, - 0x00, 0x00, 0x03, 0x84, - 0x00, 0x00, 0x03, 0xe8, - 0x00, 0x00, 0x00, 0x00, - 0xfe, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01 + 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x03, 0x84, 0x00, 0x00, 0x03, 0xe8, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, ]; #[test] @@ -636,7 +628,10 @@ mod test { assert_eq!(opt.option_type(), Type::PrefixInformation); assert_eq!(opt.data_len(), 4); assert_eq!(opt.prefix_len(), 64); - assert_eq!(opt.prefix_flags(), PrefixInfoFlags::ON_LINK | PrefixInfoFlags::ADDRCONF); + assert_eq!( + opt.prefix_flags(), + PrefixInfoFlags::ON_LINK | PrefixInfoFlags::ADDRCONF + ); assert_eq!(opt.valid_lifetime(), Duration::from_secs(900)); assert_eq!(opt.preferred_lifetime(), Duration::from_secs(1000)); assert_eq!(opt.prefix(), Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)); @@ -658,11 +653,11 @@ mod test { #[test] fn test_short_packet() { - assert_eq!(NdiscOption::new_checked(&[0x00, 0x00]), Err(Error::Truncated)); - let bytes = [ - 0x03, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 - ]; + assert_eq!( + NdiscOption::new_checked(&[0x00, 0x00]), + Err(Error::Truncated) + ); + let bytes = [0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(NdiscOption::new_checked(&bytes), Err(Error::Truncated)); } @@ -671,13 +666,17 @@ mod test { let mut bytes = [0x01, 0x01, 0x54, 0x52, 0x00, 0x12, 0x23, 0x34]; let addr = EthernetAddress([0x54, 0x52, 0x00, 0x12, 0x23, 0x34]); { - assert_eq!(Repr::parse(&NdiscOption::new_unchecked(&bytes)), - Ok(Repr::SourceLinkLayerAddr(addr))); + assert_eq!( + Repr::parse(&NdiscOption::new_unchecked(&bytes)), + Ok(Repr::SourceLinkLayerAddr(addr)) + ); } bytes[0] = 0x02; { - assert_eq!(Repr::parse(&NdiscOption::new_unchecked(&bytes)), - Ok(Repr::TargetLinkLayerAddr(addr))); + assert_eq!( + Repr::parse(&NdiscOption::new_unchecked(&bytes)), + Ok(Repr::TargetLinkLayerAddr(addr)) + ); } } @@ -688,9 +687,12 @@ mod test { flags: PrefixInfoFlags::ON_LINK | PrefixInfoFlags::ADDRCONF, valid_lifetime: Duration::from_secs(900), preferred_lifetime: Duration::from_secs(1000), - prefix: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1) + prefix: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), }); - assert_eq!(Repr::parse(&NdiscOption::new_unchecked(&PREFIX_OPT_BYTES)), Ok(repr)); + assert_eq!( + Repr::parse(&NdiscOption::new_unchecked(&PREFIX_OPT_BYTES)), + Ok(repr) + ); } #[test] @@ -701,7 +703,7 @@ mod test { flags: PrefixInfoFlags::ON_LINK | PrefixInfoFlags::ADDRCONF, valid_lifetime: Duration::from_secs(900), preferred_lifetime: Duration::from_secs(1000), - prefix: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1) + prefix: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), }); let mut opt = NdiscOption::new_unchecked(&mut bytes); repr.emit(&mut opt); @@ -711,6 +713,9 @@ mod test { #[test] fn test_repr_parse_mtu() { let bytes = [0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0xdc]; - assert_eq!(Repr::parse(&NdiscOption::new_unchecked(&bytes)), Ok(Repr::Mtu(1500))); + assert_eq!( + Repr::parse(&NdiscOption::new_unchecked(&bytes)), + Ok(Repr::Mtu(1500)) + ); } } diff --git a/src/wire/pretty_print.rs b/src/wire/pretty_print.rs index 6d900de..a972cb6 100644 --- a/src/wire/pretty_print.rs +++ b/src/wire/pretty_print.rs @@ -37,7 +37,7 @@ use core::marker::PhantomData; #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PrettyIndent { prefix: &'static str, - level: usize + level: usize, } impl PrettyIndent { @@ -72,24 +72,27 @@ pub trait PrettyPrint { /// /// `pretty_print` accepts a buffer and not a packet wrapper because the packet might /// be truncated, and so it might not be possible to create the packet wrapper. - fn pretty_print(buffer: &dyn AsRef<[u8]>, fmt: &mut fmt::Formatter, - indent: &mut PrettyIndent) -> fmt::Result; + fn pretty_print( + buffer: &dyn AsRef<[u8]>, + fmt: &mut fmt::Formatter, + indent: &mut PrettyIndent, + ) -> fmt::Result; } /// Wrapper for using a `PrettyPrint` where a `Display` is expected. pub struct PrettyPrinter<'a, T: PrettyPrint> { - prefix: &'static str, - buffer: &'a dyn AsRef<[u8]>, - phantom: PhantomData + prefix: &'static str, + buffer: &'a dyn AsRef<[u8]>, + phantom: PhantomData, } impl<'a, T: PrettyPrint> PrettyPrinter<'a, T> { /// Format the listing with the recorded parameters when Display::fmt is called. pub fn new(prefix: &'static str, buffer: &'a dyn AsRef<[u8]>) -> PrettyPrinter<'a, T> { PrettyPrinter { - prefix: prefix, - buffer: buffer, - phantom: PhantomData + prefix: prefix, + buffer: buffer, + phantom: PhantomData, } } } diff --git a/src/wire/tcp.rs b/src/wire/tcp.rs index d5622d9..c3aa089 100644 --- a/src/wire/tcp.rs +++ b/src/wire/tcp.rs @@ -1,10 +1,10 @@ -use core::{i32, ops, cmp, fmt}; use byteorder::{ByteOrder, NetworkEndian}; +use core::{cmp, fmt, i32, ops}; -use crate::{Error, Result}; use crate::phy::ChecksumCapabilities; -use crate::wire::{IpProtocol, IpAddress}; use crate::wire::ip::checksum; +use crate::wire::{IpAddress, IpProtocol}; +use crate::{Error, Result}; /// A TCP sequence number. /// @@ -70,7 +70,7 @@ impl cmp::PartialOrd for SeqNumber { #[derive(Debug, PartialEq, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { - buffer: T + buffer: T, } mod field { @@ -80,12 +80,12 @@ mod field { pub const SRC_PORT: Field = 0..2; pub const DST_PORT: Field = 2..4; - pub const SEQ_NUM: Field = 4..8; - pub const ACK_NUM: Field = 8..12; - pub const FLAGS: Field = 12..14; + pub const SEQ_NUM: Field = 4..8; + pub const ACK_NUM: Field = 8..12; + pub const FLAGS: Field = 12..14; pub const WIN_SIZE: Field = 14..16; pub const CHECKSUM: Field = 16..18; - pub const URGENT: Field = 18..20; + pub const URGENT: Field = 18..20; pub fn OPTIONS(length: u8) -> Field { URGENT.end..(length as usize) @@ -99,14 +99,14 @@ mod field { pub const FLG_URG: u16 = 0x020; pub const FLG_ECE: u16 = 0x040; pub const FLG_CWR: u16 = 0x080; - pub const FLG_NS: u16 = 0x100; + pub const FLG_NS: u16 = 0x100; pub const OPT_END: u8 = 0x00; pub const OPT_NOP: u8 = 0x01; pub const OPT_MSS: u8 = 0x02; - pub const OPT_WS: u8 = 0x03; + pub const OPT_WS: u8 = 0x03; pub const OPT_SACKPERM: u8 = 0x04; - pub const OPT_SACKRNG: u8 = 0x05; + pub const OPT_SACKRNG: u8 = 0x05; } pub const HEADER_LEN: usize = field::URGENT.end; @@ -289,8 +289,12 @@ impl> Packet { pub fn segment_len(&self) -> usize { let data = self.buffer.as_ref(); let mut length = data.len() - self.header_len() as usize; - if self.syn() { length += 1 } - if self.fin() { length += 1 } + if self.syn() { + length += 1 + } + if self.fin() { + length += 1 + } length } @@ -333,13 +337,14 @@ impl> Packet { /// # Fuzzing /// This function always returns `true` when fuzzing. pub fn verify_checksum(&self, src_addr: &IpAddress, dst_addr: &IpAddress) -> bool { - if cfg!(fuzzing) { return true } + if cfg!(fuzzing) { + return true; + } let data = self.buffer.as_ref(); checksum::combine(&[ - checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp, - data.len() as u32), - checksum::data(data) + checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp, data.len() as u32), + checksum::data(data), ]) == !0 } } @@ -405,7 +410,11 @@ impl + AsMut<[u8]>> Packet { pub fn set_fin(&mut self, value: bool) { let data = self.buffer.as_mut(); let raw = NetworkEndian::read_u16(&data[field::FLAGS]); - let raw = if value { raw | field::FLG_FIN } else { raw & !field::FLG_FIN }; + let raw = if value { + raw | field::FLG_FIN + } else { + raw & !field::FLG_FIN + }; NetworkEndian::write_u16(&mut data[field::FLAGS], raw) } @@ -414,7 +423,11 @@ impl + AsMut<[u8]>> Packet { pub fn set_syn(&mut self, value: bool) { let data = self.buffer.as_mut(); let raw = NetworkEndian::read_u16(&data[field::FLAGS]); - let raw = if value { raw | field::FLG_SYN } else { raw & !field::FLG_SYN }; + let raw = if value { + raw | field::FLG_SYN + } else { + raw & !field::FLG_SYN + }; NetworkEndian::write_u16(&mut data[field::FLAGS], raw) } @@ -423,7 +436,11 @@ impl + AsMut<[u8]>> Packet { pub fn set_rst(&mut self, value: bool) { let data = self.buffer.as_mut(); let raw = NetworkEndian::read_u16(&data[field::FLAGS]); - let raw = if value { raw | field::FLG_RST } else { raw & !field::FLG_RST }; + let raw = if value { + raw | field::FLG_RST + } else { + raw & !field::FLG_RST + }; NetworkEndian::write_u16(&mut data[field::FLAGS], raw) } @@ -432,7 +449,11 @@ impl + AsMut<[u8]>> Packet { pub fn set_psh(&mut self, value: bool) { let data = self.buffer.as_mut(); let raw = NetworkEndian::read_u16(&data[field::FLAGS]); - let raw = if value { raw | field::FLG_PSH } else { raw & !field::FLG_PSH }; + let raw = if value { + raw | field::FLG_PSH + } else { + raw & !field::FLG_PSH + }; NetworkEndian::write_u16(&mut data[field::FLAGS], raw) } @@ -441,7 +462,11 @@ impl + AsMut<[u8]>> Packet { pub fn set_ack(&mut self, value: bool) { let data = self.buffer.as_mut(); let raw = NetworkEndian::read_u16(&data[field::FLAGS]); - let raw = if value { raw | field::FLG_ACK } else { raw & !field::FLG_ACK }; + let raw = if value { + raw | field::FLG_ACK + } else { + raw & !field::FLG_ACK + }; NetworkEndian::write_u16(&mut data[field::FLAGS], raw) } @@ -450,7 +475,11 @@ impl + AsMut<[u8]>> Packet { pub fn set_urg(&mut self, value: bool) { let data = self.buffer.as_mut(); let raw = NetworkEndian::read_u16(&data[field::FLAGS]); - let raw = if value { raw | field::FLG_URG } else { raw & !field::FLG_URG }; + let raw = if value { + raw | field::FLG_URG + } else { + raw & !field::FLG_URG + }; NetworkEndian::write_u16(&mut data[field::FLAGS], raw) } @@ -459,7 +488,11 @@ impl + AsMut<[u8]>> Packet { pub fn set_ece(&mut self, value: bool) { let data = self.buffer.as_mut(); let raw = NetworkEndian::read_u16(&data[field::FLAGS]); - let raw = if value { raw | field::FLG_ECE } else { raw & !field::FLG_ECE }; + let raw = if value { + raw | field::FLG_ECE + } else { + raw & !field::FLG_ECE + }; NetworkEndian::write_u16(&mut data[field::FLAGS], raw) } @@ -468,7 +501,11 @@ impl + AsMut<[u8]>> Packet { pub fn set_cwr(&mut self, value: bool) { let data = self.buffer.as_mut(); let raw = NetworkEndian::read_u16(&data[field::FLAGS]); - let raw = if value { raw | field::FLG_CWR } else { raw & !field::FLG_CWR }; + let raw = if value { + raw | field::FLG_CWR + } else { + raw & !field::FLG_CWR + }; NetworkEndian::write_u16(&mut data[field::FLAGS], raw) } @@ -477,7 +514,11 @@ impl + AsMut<[u8]>> Packet { pub fn set_ns(&mut self, value: bool) { let data = self.buffer.as_mut(); let raw = NetworkEndian::read_u16(&data[field::FLAGS]); - let raw = if value { raw | field::FLG_NS } else { raw & !field::FLG_NS }; + let raw = if value { + raw | field::FLG_NS + } else { + raw & !field::FLG_NS + }; NetworkEndian::write_u16(&mut data[field::FLAGS], raw) } @@ -521,9 +562,8 @@ impl + AsMut<[u8]>> Packet { let checksum = { let data = self.buffer.as_ref(); !checksum::combine(&[ - checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp, - data.len() as u32), - checksum::data(data) + checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp, data.len() as u32), + checksum::data(data), ]) }; self.set_checksum(checksum) @@ -562,7 +602,7 @@ pub enum TcpOption<'a> { WindowScale(u8), SackPermitted, SackRange([Option<(u32, u32)>; 3]), - Unknown { kind: u8, data: &'a [u8] } + Unknown { kind: u8, data: &'a [u8] }, } impl<'a> TcpOption<'a> { @@ -581,24 +621,18 @@ impl<'a> TcpOption<'a> { length = *buffer.get(1).ok_or(Error::Truncated)? as usize; let data = buffer.get(2..length).ok_or(Error::Truncated)?; match (kind, length) { - (field::OPT_END, _) | - (field::OPT_NOP, _) => - unreachable!(), - (field::OPT_MSS, 4) => - option = TcpOption::MaxSegmentSize(NetworkEndian::read_u16(data)), - (field::OPT_MSS, _) => - return Err(Error::Malformed), - (field::OPT_WS, 3) => - option = TcpOption::WindowScale(data[0]), - (field::OPT_WS, _) => - return Err(Error::Malformed), - (field::OPT_SACKPERM, 2) => - option = TcpOption::SackPermitted, - (field::OPT_SACKPERM, _) => - return Err(Error::Malformed), + (field::OPT_END, _) | (field::OPT_NOP, _) => unreachable!(), + (field::OPT_MSS, 4) => { + option = TcpOption::MaxSegmentSize(NetworkEndian::read_u16(data)) + } + (field::OPT_MSS, _) => return Err(Error::Malformed), + (field::OPT_WS, 3) => option = TcpOption::WindowScale(data[0]), + (field::OPT_WS, _) => return Err(Error::Malformed), + (field::OPT_SACKPERM, 2) => option = TcpOption::SackPermitted, + (field::OPT_SACKPERM, _) => return Err(Error::Malformed), (field::OPT_SACKRNG, n) => { - if n < 10 || (n-2) % 8 != 0 { - return Err(Error::Malformed) + if n < 10 || (n - 2) % 8 != 0 { + return Err(Error::Malformed); } if n > 26 { // It's possible for a remote to send 4 SACK blocks, but extremely rare. @@ -622,19 +656,16 @@ impl<'a> TcpOption<'a> { *nmut = if left < data.len() { let mid = left + 4; let right = mid + 4; - let range_left = NetworkEndian::read_u32( - &data[left..mid]); - let range_right = NetworkEndian::read_u32( - &data[mid..right]); + let range_left = NetworkEndian::read_u32(&data[left..mid]); + let range_right = NetworkEndian::read_u32(&data[mid..right]); Some((range_left, range_right)) } else { None }; }); option = TcpOption::SackRange(sack_ranges); - }, - (_, _) => - option = TcpOption::Unknown { kind, data } + } + (_, _) => option = TcpOption::Unknown { kind, data }, } } } @@ -649,7 +680,7 @@ impl<'a> TcpOption<'a> { TcpOption::WindowScale(_) => 3, TcpOption::SackPermitted => 2, TcpOption::SackRange(s) => s.iter().filter(|s| s.is_some()).count() * 8 + 2, - TcpOption::Unknown { data, .. } => 2 + data.len() + TcpOption::Unknown { data, .. } => 2 + data.len(), } } @@ -657,23 +688,21 @@ impl<'a> TcpOption<'a> { let length; match *self { TcpOption::EndOfList => { - length = 1; + length = 1; // There may be padding space which also should be initialized. for p in buffer.iter_mut() { *p = field::OPT_END; } } TcpOption::NoOperation => { - length = 1; + length = 1; buffer[0] = field::OPT_NOP; } _ => { - length = self.buffer_len(); + length = self.buffer_len(); buffer[1] = length as u8; match self { - &TcpOption::EndOfList | - &TcpOption::NoOperation => - unreachable!(), + &TcpOption::EndOfList | &TcpOption::NoOperation => unreachable!(), &TcpOption::MaxSegmentSize(value) => { buffer[0] = field::OPT_MSS; NetworkEndian::write_u16(&mut buffer[2..], value) @@ -687,14 +716,21 @@ impl<'a> TcpOption<'a> { } &TcpOption::SackRange(slice) => { buffer[0] = field::OPT_SACKRNG; - slice.iter().filter(|s| s.is_some()).enumerate().for_each(|(i, s)| { - let (first, second) = *s.as_ref().unwrap(); - let pos = i * 8 + 2; - NetworkEndian::write_u32(&mut buffer[pos..], first); - NetworkEndian::write_u32(&mut buffer[pos+4..], second); - }); + slice + .iter() + .filter(|s| s.is_some()) + .enumerate() + .for_each(|(i, s)| { + let (first, second) = *s.as_ref().unwrap(); + let pos = i * 8 + 2; + NetworkEndian::write_u32(&mut buffer[pos..], first); + NetworkEndian::write_u32(&mut buffer[pos + 4..], second); + }); } - &TcpOption::Unknown { kind, data: provided } => { + &TcpOption::Unknown { + kind, + data: provided, + } => { buffer[0] = kind; buffer[2..].copy_from_slice(provided) } @@ -713,7 +749,7 @@ pub enum Control { Psh, Syn, Fin, - Rst + Rst, } #[allow(clippy::len_without_is_empty)] @@ -721,8 +757,8 @@ impl Control { /// Return the length of a control flag, in terms of sequence space. pub fn len(self) -> usize { match self { - Control::Syn | Control::Fin => 1, - _ => 0 + Control::Syn | Control::Fin => 1, + _ => 0, } } @@ -730,7 +766,7 @@ impl Control { pub fn quash_psh(self) -> Control { match self { Control::Psh => Control::None, - _ => self + _ => self, } } } @@ -739,46 +775,54 @@ impl Control { #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Repr<'a> { - pub src_port: u16, - pub dst_port: u16, - pub control: Control, - pub seq_number: SeqNumber, - pub ack_number: Option, - pub window_len: u16, + pub src_port: u16, + pub dst_port: u16, + pub control: Control, + pub seq_number: SeqNumber, + pub ack_number: Option, + pub window_len: u16, pub window_scale: Option, pub max_seg_size: Option, pub sack_permitted: bool, - pub sack_ranges: [Option<(u32, u32)>; 3], - pub payload: &'a [u8] + pub sack_ranges: [Option<(u32, u32)>; 3], + pub payload: &'a [u8], } impl<'a> Repr<'a> { /// Parse a Transmission Control Protocol packet and return a high-level representation. - pub fn parse(packet: &Packet<&'a T>, src_addr: &IpAddress, dst_addr: &IpAddress, - checksum_caps: &ChecksumCapabilities) -> Result> - where T: AsRef<[u8]> + ?Sized { + pub fn parse( + packet: &Packet<&'a T>, + src_addr: &IpAddress, + dst_addr: &IpAddress, + checksum_caps: &ChecksumCapabilities, + ) -> Result> + where + T: AsRef<[u8]> + ?Sized, + { // Source and destination ports must be present. - if packet.src_port() == 0 { return Err(Error::Malformed) } - if packet.dst_port() == 0 { return Err(Error::Malformed) } + if packet.src_port() == 0 { + return Err(Error::Malformed); + } + if packet.dst_port() == 0 { + return Err(Error::Malformed); + } // Valid checksum is expected. if checksum_caps.tcp.rx() && !packet.verify_checksum(src_addr, dst_addr) { - return Err(Error::Checksum) + return Err(Error::Checksum); } - let control = - match (packet.syn(), packet.fin(), packet.rst(), packet.psh()) { - (false, false, false, false) => Control::None, - (false, false, false, true) => Control::Psh, - (true, false, false, _) => Control::Syn, - (false, true, false, _) => Control::Fin, - (false, false, true , _) => Control::Rst, - _ => return Err(Error::Malformed) - }; - let ack_number = - match packet.ack() { - true => Some(packet.ack_number()), - false => None - }; + let control = match (packet.syn(), packet.fin(), packet.rst(), packet.psh()) { + (false, false, false, false) => Control::None, + (false, false, false, true) => Control::Psh, + (true, false, false, _) => Control::Syn, + (false, true, false, _) => Control::Fin, + (false, false, true, _) => Control::Rst, + _ => return Err(Error::Malformed), + }; + let ack_number = match packet.ack() { + true => Some(packet.ack_number()), + false => None, + }; // The PSH flag is ignored. // The URG flag and the urgent field is ignored. This behavior is standards-compliant, // however, most deployed systems (e.g. Linux) are *not* standards-compliant, and would @@ -794,41 +838,44 @@ impl<'a> Repr<'a> { match option { TcpOption::EndOfList => break, TcpOption::NoOperation => (), - TcpOption::MaxSegmentSize(value) => - max_seg_size = Some(value), + TcpOption::MaxSegmentSize(value) => max_seg_size = Some(value), TcpOption::WindowScale(value) => { // RFC 1323: Thus, the shift count must be limited to 14 (which allows windows // of 2**30 = 1 Gbyte). If a Window Scale option is received with a shift.cnt // value exceeding 14, the TCP should log the error but use 14 instead of the // specified value. window_scale = if value > 14 { - net_debug!("{}:{}:{}:{}: parsed window scaling factor >14, setting to 14", src_addr, packet.src_port(), dst_addr, packet.dst_port()); + net_debug!( + "{}:{}:{}:{}: parsed window scaling factor >14, setting to 14", + src_addr, + packet.src_port(), + dst_addr, + packet.dst_port() + ); Some(14) } else { Some(value) }; - }, - TcpOption::SackPermitted => - sack_permitted = true, - TcpOption::SackRange(slice) => - sack_ranges = slice, + } + TcpOption::SackPermitted => sack_permitted = true, + TcpOption::SackRange(slice) => sack_ranges = slice, _ => (), } options = next_options; } Ok(Repr { - src_port: packet.src_port(), - dst_port: packet.dst_port(), - control: control, - seq_number: packet.seq_number(), - ack_number: ack_number, - window_len: packet.window_len(), + src_port: packet.src_port(), + dst_port: packet.dst_port(), + control: control, + seq_number: packet.seq_number(), + ack_number: ack_number, + window_len: packet.window_len(), window_scale: window_scale, max_seg_size: max_seg_size, sack_permitted: sack_permitted, - sack_ranges: sack_ranges, - payload: packet.payload() + sack_ranges: sack_ranges, + payload: packet.payload(), }) } @@ -847,9 +894,11 @@ impl<'a> Repr<'a> { if self.sack_permitted { length += 2; } - let sack_range_len: usize = self.sack_ranges.iter().map( - |o| o.map(|_| 8).unwrap_or(0) - ).sum(); + let sack_range_len: usize = self + .sack_ranges + .iter() + .map(|o| o.map(|_| 8).unwrap_or(0)) + .sum(); if sack_range_len > 0 { length += sack_range_len + 2; } @@ -865,9 +914,15 @@ impl<'a> Repr<'a> { } /// Emit a high-level representation into a Transmission Control Protocol packet. - pub fn emit(&self, packet: &mut Packet<&mut T>, src_addr: &IpAddress, dst_addr: &IpAddress, - checksum_caps: &ChecksumCapabilities) - where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized { + pub fn emit( + &self, + packet: &mut Packet<&mut T>, + src_addr: &IpAddress, + dst_addr: &IpAddress, + checksum_caps: &ChecksumCapabilities, + ) where + T: AsRef<[u8]> + AsMut<[u8]> + ?Sized, + { packet.set_src_port(self.src_port); packet.set_dst_port(self.dst_port); packet.set_seq_number(self.seq_number); @@ -877,24 +932,28 @@ impl<'a> Repr<'a> { packet.clear_flags(); match self.control { Control::None => (), - Control::Psh => packet.set_psh(true), - Control::Syn => packet.set_syn(true), - Control::Fin => packet.set_fin(true), - Control::Rst => packet.set_rst(true) + Control::Psh => packet.set_psh(true), + Control::Syn => packet.set_syn(true), + Control::Fin => packet.set_fin(true), + Control::Rst => packet.set_rst(true), } packet.set_ack(self.ack_number.is_some()); { let mut options = packet.options_mut(); if let Some(value) = self.max_seg_size { - let tmp = options; options = TcpOption::MaxSegmentSize(value).emit(tmp); + let tmp = options; + options = TcpOption::MaxSegmentSize(value).emit(tmp); } if let Some(value) = self.window_scale { - let tmp = options; options = TcpOption::WindowScale(value).emit(tmp); + let tmp = options; + options = TcpOption::WindowScale(value).emit(tmp); } if self.sack_permitted { - let tmp = options; options = TcpOption::SackPermitted.emit(tmp); + let tmp = options; + options = TcpOption::SackPermitted.emit(tmp); } else if self.ack_number.is_some() && self.sack_ranges.iter().any(|s| s.is_some()) { - let tmp = options; options = TcpOption::SackRange(self.sack_ranges).emit(tmp); + let tmp = options; + options = TcpOption::SackRange(self.sack_ranges).emit(tmp); } if !options.is_empty() { @@ -922,8 +981,8 @@ impl<'a> Repr<'a> { pub fn is_empty(&self) -> bool { match self.control { _ if !self.payload.is_empty() => false, - Control::Syn | Control::Fin | Control::Rst => false, - Control::None | Control::Psh => true + Control::Syn | Control::Fin | Control::Rst => false, + Control::None | Control::Psh => true, } } } @@ -931,15 +990,28 @@ impl<'a> Repr<'a> { impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Cannot use Repr::parse because we don't have the IP addresses. - write!(f, "TCP src={} dst={}", - self.src_port(), self.dst_port())?; - if self.syn() { write!(f, " syn")? } - if self.fin() { write!(f, " fin")? } - if self.rst() { write!(f, " rst")? } - if self.psh() { write!(f, " psh")? } - if self.ece() { write!(f, " ece")? } - if self.cwr() { write!(f, " cwr")? } - if self.ns() { write!(f, " ns" )? } + write!(f, "TCP src={} dst={}", self.src_port(), self.dst_port())?; + if self.syn() { + write!(f, " syn")? + } + if self.fin() { + write!(f, " fin")? + } + if self.rst() { + write!(f, " rst")? + } + if self.psh() { + write!(f, " psh")? + } + if self.ece() { + write!(f, " ece")? + } + if self.cwr() { + write!(f, " cwr")? + } + if self.ns() { + write!(f, " ns")? + } write!(f, " seq={}", self.seq_number())?; if self.ack() { write!(f, " ack={}", self.ack_number())?; @@ -952,24 +1024,18 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> { let mut options = self.options(); while !options.is_empty() { - let (next_options, option) = - match TcpOption::parse(options) { - Ok(res) => res, - Err(err) => return write!(f, " ({})", err) - }; + let (next_options, option) = match TcpOption::parse(options) { + Ok(res) => res, + Err(err) => return write!(f, " ({})", err), + }; match option { TcpOption::EndOfList => break, TcpOption::NoOperation => (), - TcpOption::MaxSegmentSize(value) => - write!(f, " mss={}", value)?, - TcpOption::WindowScale(value) => - write!(f, " ws={}", value)?, - TcpOption::SackPermitted => - write!(f, " sACK")?, - TcpOption::SackRange(slice) => - write!(f, " sACKr{:?}", slice)?, // debug print conveniently includes the []s - TcpOption::Unknown { kind, .. } => - write!(f, " opt({})", kind)?, + TcpOption::MaxSegmentSize(value) => write!(f, " mss={}", value)?, + TcpOption::WindowScale(value) => write!(f, " ws={}", value)?, + TcpOption::SackPermitted => write!(f, " sACK")?, + TcpOption::SackRange(slice) => write!(f, " sACKr{:?}", slice)?, // debug print conveniently includes the []s + TcpOption::Unknown { kind, .. } => write!(f, " opt({})", kind)?, } options = next_options; } @@ -979,14 +1045,13 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> { impl<'a> fmt::Display for Repr<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "TCP src={} dst={}", - self.src_port, self.dst_port)?; + write!(f, "TCP src={} dst={}", self.src_port, self.dst_port)?; match self.control { Control::Syn => write!(f, " syn")?, Control::Fin => write!(f, " fin")?, Control::Rst => write!(f, " rst")?, Control::Psh => write!(f, " psh")?, - Control::None => () + Control::None => (), } write!(f, " seq={}", self.seq_number)?; if let Some(ack_number) = self.ack_number { @@ -1001,23 +1066,26 @@ impl<'a> fmt::Display for Repr<'a> { } } -use crate::wire::pretty_print::{PrettyPrint, PrettyIndent}; +use crate::wire::pretty_print::{PrettyIndent, PrettyPrint}; impl> PrettyPrint for Packet { - fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter, - indent: &mut PrettyIndent) -> fmt::Result { + fn pretty_print( + buffer: &dyn AsRef<[u8]>, + f: &mut fmt::Formatter, + indent: &mut PrettyIndent, + ) -> fmt::Result { match Packet::new_checked(buffer) { - Err(err) => write!(f, "{}({})", indent, err), - Ok(packet) => write!(f, "{}{}", indent, packet) + Err(err) => write!(f, "{}({})", indent, err), + Ok(packet) => write!(f, "{}{}", indent, packet), } } } #[cfg(test)] mod test { + use super::*; #[cfg(feature = "proto-ipv4")] use crate::wire::Ipv4Address; - use super::*; #[cfg(feature = "proto-ipv4")] const SRC_ADDR: Ipv4Address = Ipv4Address([192, 168, 1, 1]); @@ -1025,22 +1093,16 @@ mod test { const DST_ADDR: Ipv4Address = Ipv4Address([192, 168, 1, 2]); #[cfg(feature = "proto-ipv4")] - static PACKET_BYTES: [u8; 28] = - [0xbf, 0x00, 0x00, 0x50, - 0x01, 0x23, 0x45, 0x67, - 0x89, 0xab, 0xcd, 0xef, - 0x60, 0x35, 0x01, 0x23, - 0x01, 0xb6, 0x02, 0x01, - 0x03, 0x03, 0x0c, 0x01, - 0xaa, 0x00, 0x00, 0xff]; + static PACKET_BYTES: [u8; 28] = [ + 0xbf, 0x00, 0x00, 0x50, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x60, 0x35, 0x01, + 0x23, 0x01, 0xb6, 0x02, 0x01, 0x03, 0x03, 0x0c, 0x01, 0xaa, 0x00, 0x00, 0xff, + ]; #[cfg(feature = "proto-ipv4")] - static OPTION_BYTES: [u8; 4] = - [0x03, 0x03, 0x0c, 0x01]; + static OPTION_BYTES: [u8; 4] = [0x03, 0x03, 0x0c, 0x01]; #[cfg(feature = "proto-ipv4")] - static PAYLOAD_BYTES: [u8; 4] = - [0xaa, 0x00, 0x00, 0xff]; + static PAYLOAD_BYTES: [u8; 4] = [0xaa, 0x00, 0x00, 0xff]; #[test] #[cfg(feature = "proto-ipv4")] @@ -1062,7 +1124,10 @@ mod test { assert_eq!(packet.checksum(), 0x01b6); assert_eq!(packet.options(), &OPTION_BYTES[..]); assert_eq!(packet.payload(), &PAYLOAD_BYTES[..]); - assert_eq!(packet.verify_checksum(&SRC_ADDR.into(), &DST_ADDR.into()), true); + assert_eq!( + packet.verify_checksum(&SRC_ADDR.into(), &DST_ADDR.into()), + true + ); } #[test] @@ -1107,28 +1172,25 @@ mod test { } #[cfg(feature = "proto-ipv4")] - static SYN_PACKET_BYTES: [u8; 24] = - [0xbf, 0x00, 0x00, 0x50, - 0x01, 0x23, 0x45, 0x67, - 0x00, 0x00, 0x00, 0x00, - 0x50, 0x02, 0x01, 0x23, - 0x7a, 0x8d, 0x00, 0x00, - 0xaa, 0x00, 0x00, 0xff]; + static SYN_PACKET_BYTES: [u8; 24] = [ + 0xbf, 0x00, 0x00, 0x50, 0x01, 0x23, 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02, 0x01, + 0x23, 0x7a, 0x8d, 0x00, 0x00, 0xaa, 0x00, 0x00, 0xff, + ]; #[cfg(feature = "proto-ipv4")] fn packet_repr() -> Repr<'static> { Repr { - src_port: 48896, - dst_port: 80, - seq_number: SeqNumber(0x01234567), - ack_number: None, - window_len: 0x0123, + src_port: 48896, + dst_port: 80, + seq_number: SeqNumber(0x01234567), + ack_number: None, + window_len: 0x0123, window_scale: None, - control: Control::Syn, + control: Control::Syn, max_seg_size: None, sack_permitted: false, - sack_ranges: [None, None, None], - payload: &PAYLOAD_BYTES + sack_ranges: [None, None, None], + payload: &PAYLOAD_BYTES, } } @@ -1136,7 +1198,13 @@ mod test { #[cfg(feature = "proto-ipv4")] fn test_parse() { let packet = Packet::new_unchecked(&SYN_PACKET_BYTES[..]); - let repr = Repr::parse(&packet, &SRC_ADDR.into(), &DST_ADDR.into(), &ChecksumCapabilities::default()).unwrap(); + let repr = Repr::parse( + &packet, + &SRC_ADDR.into(), + &DST_ADDR.into(), + &ChecksumCapabilities::default(), + ) + .unwrap(); assert_eq!(repr, packet_repr()); } @@ -1146,7 +1214,12 @@ mod test { let repr = packet_repr(); let mut bytes = vec![0xa5; repr.buffer_len()]; let mut packet = Packet::new_unchecked(&mut bytes); - repr.emit(&mut packet, &SRC_ADDR.into(), &DST_ADDR.into(), &ChecksumCapabilities::default()); + repr.emit( + &mut packet, + &SRC_ADDR.into(), + &DST_ADDR.into(), + &ChecksumCapabilities::default(), + ); assert_eq!(&packet.into_inner()[..], &SYN_PACKET_BYTES[..]); } @@ -1159,57 +1232,62 @@ mod test { } macro_rules! assert_option_parses { - ($opt:expr, $data:expr) => ({ + ($opt:expr, $data:expr) => {{ assert_eq!(TcpOption::parse($data), Ok((&[][..], $opt))); let buffer = &mut [0; 40][..$opt.buffer_len()]; assert_eq!($opt.emit(buffer), &mut []); assert_eq!(&*buffer, $data); - }) + }}; } #[test] fn test_tcp_options() { - assert_option_parses!(TcpOption::EndOfList, - &[0x00]); - assert_option_parses!(TcpOption::NoOperation, - &[0x01]); - assert_option_parses!(TcpOption::MaxSegmentSize(1500), - &[0x02, 0x04, 0x05, 0xdc]); - assert_option_parses!(TcpOption::WindowScale(12), - &[0x03, 0x03, 0x0c]); - assert_option_parses!(TcpOption::SackPermitted, - &[0x4, 0x02]); - assert_option_parses!(TcpOption::SackRange([Some((500, 1500)), None, None]), - &[0x05, 0x0a, - 0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x05, 0xdc]); - assert_option_parses!(TcpOption::SackRange([Some((875, 1225)), Some((1500, 2500)), None]), - &[0x05, 0x12, - 0x00, 0x00, 0x03, 0x6b, 0x00, 0x00, 0x04, 0xc9, - 0x00, 0x00, 0x05, 0xdc, 0x00, 0x00, 0x09, 0xc4]); - assert_option_parses!(TcpOption::SackRange([Some((875000, 1225000)), - Some((1500000, 2500000)), - Some((876543210, 876654320))]), - &[0x05, 0x1a, - 0x00, 0x0d, 0x59, 0xf8, 0x00, 0x12, 0xb1, 0x28, - 0x00, 0x16, 0xe3, 0x60, 0x00, 0x26, 0x25, 0xa0, - 0x34, 0x3e, 0xfc, 0xea, 0x34, 0x40, 0xae, 0xf0]); - assert_option_parses!(TcpOption::Unknown { kind: 12, data: &[1, 2, 3][..] }, - &[0x0c, 0x05, 0x01, 0x02, 0x03]) + assert_option_parses!(TcpOption::EndOfList, &[0x00]); + assert_option_parses!(TcpOption::NoOperation, &[0x01]); + assert_option_parses!(TcpOption::MaxSegmentSize(1500), &[0x02, 0x04, 0x05, 0xdc]); + assert_option_parses!(TcpOption::WindowScale(12), &[0x03, 0x03, 0x0c]); + assert_option_parses!(TcpOption::SackPermitted, &[0x4, 0x02]); + assert_option_parses!( + TcpOption::SackRange([Some((500, 1500)), None, None]), + &[0x05, 0x0a, 0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x05, 0xdc] + ); + assert_option_parses!( + TcpOption::SackRange([Some((875, 1225)), Some((1500, 2500)), None]), + &[ + 0x05, 0x12, 0x00, 0x00, 0x03, 0x6b, 0x00, 0x00, 0x04, 0xc9, 0x00, 0x00, 0x05, 0xdc, + 0x00, 0x00, 0x09, 0xc4 + ] + ); + assert_option_parses!( + TcpOption::SackRange([ + Some((875000, 1225000)), + Some((1500000, 2500000)), + Some((876543210, 876654320)) + ]), + &[ + 0x05, 0x1a, 0x00, 0x0d, 0x59, 0xf8, 0x00, 0x12, 0xb1, 0x28, 0x00, 0x16, 0xe3, 0x60, + 0x00, 0x26, 0x25, 0xa0, 0x34, 0x3e, 0xfc, 0xea, 0x34, 0x40, 0xae, 0xf0 + ] + ); + assert_option_parses!( + TcpOption::Unknown { + kind: 12, + data: &[1, 2, 3][..] + }, + &[0x0c, 0x05, 0x01, 0x02, 0x03] + ) } #[test] fn test_malformed_tcp_options() { - assert_eq!(TcpOption::parse(&[]), - Err(Error::Truncated)); - assert_eq!(TcpOption::parse(&[0xc]), - Err(Error::Truncated)); - assert_eq!(TcpOption::parse(&[0xc, 0x05, 0x01, 0x02]), - Err(Error::Truncated)); - assert_eq!(TcpOption::parse(&[0xc, 0x01]), - Err(Error::Truncated)); - assert_eq!(TcpOption::parse(&[0x2, 0x02]), - Err(Error::Malformed)); - assert_eq!(TcpOption::parse(&[0x3, 0x02]), - Err(Error::Malformed)); + assert_eq!(TcpOption::parse(&[]), Err(Error::Truncated)); + assert_eq!(TcpOption::parse(&[0xc]), Err(Error::Truncated)); + assert_eq!( + TcpOption::parse(&[0xc, 0x05, 0x01, 0x02]), + Err(Error::Truncated) + ); + assert_eq!(TcpOption::parse(&[0xc, 0x01]), Err(Error::Truncated)); + assert_eq!(TcpOption::parse(&[0x2, 0x02]), Err(Error::Malformed)); + assert_eq!(TcpOption::parse(&[0x3, 0x02]), Err(Error::Malformed)); } } diff --git a/src/wire/udp.rs b/src/wire/udp.rs index 4943349..02983ec 100644 --- a/src/wire/udp.rs +++ b/src/wire/udp.rs @@ -1,16 +1,16 @@ -use core::fmt; use byteorder::{ByteOrder, NetworkEndian}; +use core::fmt; -use crate::{Error, Result}; use crate::phy::ChecksumCapabilities; -use crate::wire::{IpProtocol, IpAddress}; use crate::wire::ip::checksum; +use crate::wire::{IpAddress, IpProtocol}; +use crate::{Error, Result}; /// A read/write wrapper around an User Datagram Protocol packet buffer. #[derive(Debug, PartialEq, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { - buffer: T + buffer: T, } mod field { @@ -20,7 +20,7 @@ mod field { pub const SRC_PORT: Field = 0..2; pub const DST_PORT: Field = 2..4; - pub const LENGTH: Field = 4..6; + pub const LENGTH: Field = 4..6; pub const CHECKSUM: Field = 6..8; pub fn PAYLOAD(length: u16) -> Field { @@ -113,13 +113,14 @@ impl> Packet { /// # Fuzzing /// This function always returns `true` when fuzzing. pub fn verify_checksum(&self, src_addr: &IpAddress, dst_addr: &IpAddress) -> bool { - if cfg!(fuzzing) { return true } + if cfg!(fuzzing) { + return true; + } let data = self.buffer.as_ref(); checksum::combine(&[ - checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Udp, - self.len() as u32), - checksum::data(&data[..self.len() as usize]) + checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Udp, self.len() as u32), + checksum::data(&data[..self.len() as usize]), ]) == !0 } } @@ -173,9 +174,8 @@ impl + AsMut<[u8]>> Packet { let checksum = { let data = self.buffer.as_ref(); !checksum::combine(&[ - checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Udp, - self.len() as u32), - checksum::data(&data[..self.len() as usize]) + checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Udp, self.len() as u32), + checksum::data(&data[..self.len() as usize]), ]) }; // UDP checksum value of 0 means no checksum; if the checksum really is zero, @@ -210,21 +210,26 @@ pub struct Repr { impl Repr { /// Parse an User Datagram Protocol packet and return a high-level representation. - pub fn parse(packet: &Packet<&T>, src_addr: &IpAddress, dst_addr: &IpAddress, - checksum_caps: &ChecksumCapabilities) -> Result - where T: AsRef<[u8]> + ?Sized { + pub fn parse( + packet: &Packet<&T>, + src_addr: &IpAddress, + dst_addr: &IpAddress, + checksum_caps: &ChecksumCapabilities, + ) -> Result + where + T: AsRef<[u8]> + ?Sized, + { // Destination port cannot be omitted (but source port can be). - if packet.dst_port() == 0 { return Err(Error::Malformed) } + if packet.dst_port() == 0 { + return Err(Error::Malformed); + } // Valid checksum is expected... if checksum_caps.udp.rx() && !packet.verify_checksum(src_addr, dst_addr) { match (src_addr, dst_addr) { // ... except on UDP-over-IPv4, where it can be omitted. #[cfg(feature = "proto-ipv4")] - (&IpAddress::Ipv4(_), &IpAddress::Ipv4(_)) - if packet.checksum() == 0 => (), - _ => { - return Err(Error::Checksum) - } + (&IpAddress::Ipv4(_), &IpAddress::Ipv4(_)) if packet.checksum() == 0 => (), + _ => return Err(Error::Checksum), } } @@ -240,13 +245,17 @@ impl Repr { } /// Emit a high-level representation into an User Datagram Protocol packet. - pub fn emit(&self, packet: &mut Packet<&mut T>, - src_addr: &IpAddress, - dst_addr: &IpAddress, - payload_len: usize, - emit_payload: impl FnOnce(&mut [u8]), - checksum_caps: &ChecksumCapabilities) - where T: AsRef<[u8]> + AsMut<[u8]> { + pub fn emit( + &self, + packet: &mut Packet<&mut T>, + src_addr: &IpAddress, + dst_addr: &IpAddress, + payload_len: usize, + emit_payload: impl FnOnce(&mut [u8]), + checksum_caps: &ChecksumCapabilities, + ) where + T: AsRef<[u8]> + AsMut<[u8]>, + { packet.set_src_port(self.src_port); packet.set_dst_port(self.dst_port); packet.set_len((HEADER_LEN + payload_len) as u16); @@ -265,8 +274,13 @@ impl Repr { impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Cannot use Repr::parse because we don't have the IP addresses. - write!(f, "UDP src={} dst={} len={}", - self.src_port(), self.dst_port(), self.payload().len()) + write!( + f, + "UDP src={} dst={} len={}", + self.src_port(), + self.dst_port(), + self.payload().len() + ) } } @@ -276,23 +290,26 @@ impl fmt::Display for Repr { } } -use crate::wire::pretty_print::{PrettyPrint, PrettyIndent}; +use crate::wire::pretty_print::{PrettyIndent, PrettyPrint}; impl> PrettyPrint for Packet { - fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter, - indent: &mut PrettyIndent) -> fmt::Result { + fn pretty_print( + buffer: &dyn AsRef<[u8]>, + f: &mut fmt::Formatter, + indent: &mut PrettyIndent, + ) -> fmt::Result { match Packet::new_checked(buffer) { - Err(err) => write!(f, "{}({})", indent, err), - Ok(packet) => write!(f, "{}{}", indent, packet) + Err(err) => write!(f, "{}({})", indent, err), + Ok(packet) => write!(f, "{}{}", indent, packet), } } } #[cfg(test)] mod test { + use super::*; #[cfg(feature = "proto-ipv4")] use crate::wire::Ipv4Address; - use super::*; #[cfg(feature = "proto-ipv4")] const SRC_ADDR: Ipv4Address = Ipv4Address([192, 168, 1, 1]); @@ -300,20 +317,17 @@ mod test { const DST_ADDR: Ipv4Address = Ipv4Address([192, 168, 1, 2]); #[cfg(feature = "proto-ipv4")] - static PACKET_BYTES: [u8; 12] = - [0xbf, 0x00, 0x00, 0x35, - 0x00, 0x0c, 0x12, 0x4d, - 0xaa, 0x00, 0x00, 0xff]; + static PACKET_BYTES: [u8; 12] = [ + 0xbf, 0x00, 0x00, 0x35, 0x00, 0x0c, 0x12, 0x4d, 0xaa, 0x00, 0x00, 0xff, + ]; #[cfg(feature = "proto-ipv4")] - static NO_CHECKSUM_PACKET: [u8; 12] = - [0xbf, 0x00, 0x00, 0x35, - 0x00, 0x0c, 0x00, 0x00, - 0xaa, 0x00, 0x00, 0xff]; + static NO_CHECKSUM_PACKET: [u8; 12] = [ + 0xbf, 0x00, 0x00, 0x35, 0x00, 0x0c, 0x00, 0x00, 0xaa, 0x00, 0x00, 0xff, + ]; #[cfg(feature = "proto-ipv4")] - static PAYLOAD_BYTES: [u8; 4] = - [0xaa, 0x00, 0x00, 0xff]; + static PAYLOAD_BYTES: [u8; 4] = [0xaa, 0x00, 0x00, 0xff]; #[test] #[cfg(feature = "proto-ipv4")] @@ -324,7 +338,10 @@ mod test { assert_eq!(packet.len(), 12); assert_eq!(packet.checksum(), 0x124d); assert_eq!(packet.payload(), &PAYLOAD_BYTES[..]); - assert_eq!(packet.verify_checksum(&SRC_ADDR.into(), &DST_ADDR.into()), true); + assert_eq!( + packet.verify_checksum(&SRC_ADDR.into(), &DST_ADDR.into()), + true + ); } #[test] @@ -373,8 +390,13 @@ mod test { #[cfg(feature = "proto-ipv4")] fn test_parse() { let packet = Packet::new_unchecked(&PACKET_BYTES[..]); - let repr = Repr::parse(&packet, &SRC_ADDR.into(), &DST_ADDR.into(), - &ChecksumCapabilities::default()).unwrap(); + let repr = Repr::parse( + &packet, + &SRC_ADDR.into(), + &DST_ADDR.into(), + &ChecksumCapabilities::default(), + ) + .unwrap(); assert_eq!(repr, packet_repr()); } @@ -384,10 +406,14 @@ mod test { let repr = packet_repr(); let mut bytes = vec![0xa5; repr.header_len() + PAYLOAD_BYTES.len()]; let mut packet = Packet::new_unchecked(&mut bytes); - repr.emit(&mut packet, &SRC_ADDR.into(), &DST_ADDR.into(), - PAYLOAD_BYTES.len(), - |payload| payload.copy_from_slice(&PAYLOAD_BYTES), - &ChecksumCapabilities::default()); + repr.emit( + &mut packet, + &SRC_ADDR.into(), + &DST_ADDR.into(), + PAYLOAD_BYTES.len(), + |payload| payload.copy_from_slice(&PAYLOAD_BYTES), + &ChecksumCapabilities::default(), + ); assert_eq!(&packet.into_inner()[..], &PACKET_BYTES[..]); } @@ -395,8 +421,13 @@ mod test { #[cfg(feature = "proto-ipv4")] fn test_checksum_omitted() { let packet = Packet::new_unchecked(&NO_CHECKSUM_PACKET[..]); - let repr = Repr::parse(&packet, &SRC_ADDR.into(), &DST_ADDR.into(), - &ChecksumCapabilities::default()).unwrap(); + let repr = Repr::parse( + &packet, + &SRC_ADDR.into(), + &DST_ADDR.into(), + &ChecksumCapabilities::default(), + ) + .unwrap(); assert_eq!(repr, packet_repr()); } } diff --git a/utils/packet2pcap.rs b/utils/packet2pcap.rs index 89b9906..5c062f2 100644 --- a/utils/packet2pcap.rs +++ b/utils/packet2pcap.rs @@ -1,15 +1,18 @@ -use std::cell::RefCell; -use std::io::{self, Read, Write}; -use std::path::Path; -use std::fs::File; -use std::env; -use std::process::exit; +use getopts::Options; use smoltcp::phy::{PcapLinkType, PcapSink}; use smoltcp::time::Instant; -use getopts::Options; +use std::cell::RefCell; +use std::env; +use std::fs::File; +use std::io::{self, Read, Write}; +use std::path::Path; +use std::process::exit; -fn convert(packet_filename: &Path, pcap_filename: &Path, link_type: PcapLinkType) - -> io::Result<()> { +fn convert( + packet_filename: &Path, + pcap_filename: &Path, + link_type: PcapLinkType, +) -> io::Result<()> { let mut packet_file = File::open(packet_filename)?; let mut packet = Vec::new(); packet_file.read_to_end(&mut packet)?; @@ -35,31 +38,37 @@ fn main() { let mut opts = Options::new(); opts.optflag("h", "help", "print this help menu"); - opts.optopt("t", "link-type", "set link type (one of: ethernet ip)", "TYPE"); + opts.optopt( + "t", + "link-type", + "set link type (one of: ethernet ip)", + "TYPE", + ); let matches = match opts.parse(&args[1..]) { Ok(m) => m, Err(e) => { eprintln!("{}", e); - return + return; } }; - let link_type = - match matches.opt_str("t").as_ref().map(|s| &s[..]) { - Some("ethernet") => Some(PcapLinkType::Ethernet), - Some("ip") => Some(PcapLinkType::Ip), - _ => None - }; + let link_type = match matches.opt_str("t").as_ref().map(|s| &s[..]) { + Some("ethernet") => Some(PcapLinkType::Ethernet), + Some("ip") => Some(PcapLinkType::Ip), + _ => None, + }; if matches.opt_present("h") || matches.free.len() != 2 || link_type.is_none() { print_usage(&program, opts); - return + return; } - match convert(Path::new(&matches.free[0]), - Path::new(&matches.free[1]), - link_type.unwrap()) { + match convert( + Path::new(&matches.free[0]), + Path::new(&matches.free[1]), + link_type.unwrap(), + ) { Ok(()) => (), Err(e) => { eprintln!("Cannot convert packet to pcap: {}", e);