From 8ae526a3ee1272ad3e8ed3088561390f1f597d22 Mon Sep 17 00:00:00 2001 From: shellrow Date: Wed, 9 Jul 2025 22:43:46 +0900 Subject: [PATCH 1/4] Add docs --- nex-packet/src/lib.rs | 2 ++ nex-sys/src/lib.rs | 2 ++ nex/src/lib.rs | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/nex-packet/src/lib.rs b/nex-packet/src/lib.rs index a9ae9b9..e89e6c8 100644 --- a/nex-packet/src/lib.rs +++ b/nex-packet/src/lib.rs @@ -1,3 +1,5 @@ +//! Packet parsing and construction utilities for common network protocols. + pub mod packet; pub mod ethernet; pub mod arp; diff --git a/nex-sys/src/lib.rs b/nex-sys/src/lib.rs index 4784d0d..99efc64 100644 --- a/nex-sys/src/lib.rs +++ b/nex-sys/src/lib.rs @@ -1,3 +1,5 @@ +//! Cross-platform system helpers and low-level wrappers used internally by the nex crates. + #[cfg(not(target_os = "windows"))] mod unix; #[cfg(not(target_os = "windows"))] diff --git a/nex/src/lib.rs b/nex/src/lib.rs index f6f5ce5..032a187 100644 --- a/nex/src/lib.rs +++ b/nex/src/lib.rs @@ -1,4 +1,4 @@ -//! Entry point for the nex-next collection of crates. +//! Entry point for the nex crate collection. //! //! This crate re-exports the core modules so applications can simply depend on //! `nex` and gain access to packet parsing, datalink channels and socket helpers. From 42914dc3f2dd97bd430bcfe8864f7f9cdf121461 Mon Sep 17 00:00:00 2001 From: shellrow Date: Wed, 9 Jul 2025 22:46:33 +0900 Subject: [PATCH 2/4] Refactor AsyncUdpSocket to avoid cloning --- nex-socket/src/udp/async_impl.rs | 52 ++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/nex-socket/src/udp/async_impl.rs b/nex-socket/src/udp/async_impl.rs index f685845..29543a8 100644 --- a/nex-socket/src/udp/async_impl.rs +++ b/nex-socket/src/udp/async_impl.rs @@ -7,7 +7,7 @@ use tokio::net::UdpSocket; /// Asynchronous UDP socket built on top of Tokio. #[derive(Debug)] pub struct AsyncUdpSocket { - socket: Socket, + inner: UdpSocket, } impl AsyncUdpSocket { @@ -45,14 +45,41 @@ impl AsyncUdpSocket { socket.set_nonblocking(true)?; - Ok(Self { socket }) + #[cfg(windows)] + let std_socket = unsafe { + use std::os::windows::io::{FromRawSocket, IntoRawSocket}; + StdUdpSocket::from_raw_socket(socket.into_raw_socket()) + }; + #[cfg(unix)] + let std_socket = unsafe { + use std::os::fd::{FromRawFd, IntoRawFd}; + StdUdpSocket::from_raw_fd(socket.into_raw_fd()) + }; + + let inner = UdpSocket::from_std(std_socket)?; + + Ok(Self { inner }) } /// Create a socket of arbitrary type (DGRAM or RAW). pub fn new(domain: Domain, sock_type: SockType) -> io::Result { let socket = Socket::new(domain, sock_type, Some(Protocol::UDP))?; socket.set_nonblocking(true)?; - Ok(Self { socket }) + + #[cfg(windows)] + let std_socket = unsafe { + use std::os::windows::io::{FromRawSocket, IntoRawSocket}; + StdUdpSocket::from_raw_socket(socket.into_raw_socket()) + }; + #[cfg(unix)] + let std_socket = unsafe { + use std::os::fd::{FromRawFd, IntoRawFd}; + StdUdpSocket::from_raw_fd(socket.into_raw_fd()) + }; + + let inner = UdpSocket::from_std(std_socket)?; + + Ok(Self { inner }) } /// Convenience constructor for IPv4 DGRAM. @@ -77,39 +104,32 @@ impl AsyncUdpSocket { /// Send data asynchronously. pub async fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result { - let std_udp: StdUdpSocket = self.socket.try_clone()?.into(); - let udp_socket = UdpSocket::from_std(std_udp)?; - udp_socket.send_to(buf, target).await + self.inner.send_to(buf, target).await } /// Receive data asynchronously. pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - let std_udp: StdUdpSocket = self.socket.try_clone()?.into(); - let udp_socket = UdpSocket::from_std(std_udp)?; - udp_socket.recv_from(buf).await + self.inner.recv_from(buf).await } /// Retrieve the local socket address. pub fn local_addr(&self) -> io::Result { - self.socket.local_addr()?.as_socket().ok_or_else(|| { - io::Error::new(io::ErrorKind::Other, "Failed to get socket address") - }) + self.inner.local_addr() } pub fn into_tokio_socket(self) -> io::Result { - let std_socket: StdUdpSocket = self.socket.into(); - UdpSocket::from_std(std_socket) + Ok(self.inner) } #[cfg(unix)] pub fn as_raw_fd(&self) -> std::os::unix::io::RawFd { use std::os::fd::AsRawFd; - self.socket.as_raw_fd() + self.inner.as_raw_fd() } #[cfg(windows)] pub fn as_raw_socket(&self) -> std::os::windows::io::RawSocket { use std::os::windows::io::AsRawSocket; - self.socket.as_raw_socket() + self.inner.as_raw_socket() } } From 213d79c362cf745755df593604512309e91dea3a Mon Sep 17 00:00:00 2001 From: shellrow Date: Wed, 9 Jul 2025 22:55:14 +0900 Subject: [PATCH 3/4] Add async UDP socket example --- examples/async_udp_socket.rs | 33 +++++++++++++++++++++++++++++++++ nex/Cargo.toml | 4 ++++ 2 files changed, 37 insertions(+) create mode 100644 examples/async_udp_socket.rs diff --git a/examples/async_udp_socket.rs b/examples/async_udp_socket.rs new file mode 100644 index 0000000..a759dc7 --- /dev/null +++ b/examples/async_udp_socket.rs @@ -0,0 +1,33 @@ +//! UDP echo using AsyncUdpSocket +//! +//! This example starts a small UDP echo server and client using nex-socket and Tokio. +//! +//! It will send a single UDP datagram to the server and print the echoed reply. + +use nex_socket::udp::{AsyncUdpSocket, UdpConfig}; +use tokio::task; + +#[tokio::main] +async fn main() -> std::io::Result<()> { + let server_cfg = UdpConfig { bind_addr: Some("127.0.0.1:0".parse().unwrap()), ..Default::default() }; + let server = AsyncUdpSocket::from_config(&server_cfg)?; + let server_addr = server.local_addr()?; + + let handle = task::spawn(async move { + let mut buf = [0u8; 512]; + let (n, peer) = server.recv_from(&mut buf).await?; + println!("Server received: {}", String::from_utf8_lossy(&buf[..n])); + server.send_to(&buf[..n], peer).await?; + Ok::<(), std::io::Error>(()) + }); + + let client = AsyncUdpSocket::v4_dgram()?; + let msg = b"hello via async udp"; + client.send_to(msg, server_addr).await?; + let mut buf = [0u8; 512]; + let (n, _) = client.recv_from(&mut buf).await?; + println!("Client received: {}", String::from_utf8_lossy(&buf[..n])); + + handle.await??; + Ok(()) +} diff --git a/nex/Cargo.toml b/nex/Cargo.toml index 9b91e60..4b063bd 100644 --- a/nex/Cargo.toml +++ b/nex/Cargo.toml @@ -79,3 +79,7 @@ path = "../examples/async_icmp_socket.rs" [[example]] name = "async_tcp_socket" path = "../examples/async_tcp_socket.rs" + +[[example]] +name = "async_udp_socket" +path = "../examples/async_udp_socket.rs" From d647281690ff3546e8d75210e97af54139c02ad2 Mon Sep 17 00:00:00 2001 From: shellrow Date: Wed, 9 Jul 2025 23:00:59 +0900 Subject: [PATCH 4/4] Format code using cargo fmt --- examples/arp.rs | 15 +- examples/async_icmp_socket.rs | 11 +- examples/async_tcp_socket.rs | 6 +- examples/async_udp_socket.rs | 5 +- examples/dns_dump.rs | 45 ++++- examples/dump.rs | 48 +++-- examples/icmp_ping.rs | 12 +- examples/icmp_socket.rs | 27 ++- examples/ndp.rs | 6 +- examples/parse_frame.rs | 5 +- examples/tcp_ping.rs | 13 +- examples/tcp_socket.rs | 12 +- examples/udp_ping.rs | 18 +- examples/udp_socket.rs | 5 +- nex-core/src/bitfield.rs | 227 +++++++++++----------- nex-core/src/ip.rs | 2 +- nex-core/src/lib.rs | 2 +- nex-datalink/src/bindings/bpf.rs | 2 +- nex-datalink/src/linux.rs | 3 +- nex-packet/src/arp.rs | 69 ++++--- nex-packet/src/builder/arp.rs | 4 +- nex-packet/src/builder/dhcp.rs | 5 +- nex-packet/src/builder/ethernet.rs | 7 +- nex-packet/src/builder/icmp.rs | 7 +- nex-packet/src/builder/icmpv6.rs | 4 +- nex-packet/src/builder/ipv4.rs | 37 ++-- nex-packet/src/builder/ipv6.rs | 9 +- nex-packet/src/builder/mod.rs | 6 +- nex-packet/src/builder/ndp.rs | 12 +- nex-packet/src/builder/tcp.rs | 13 +- nex-packet/src/builder/udp.rs | 7 +- nex-packet/src/dhcp.rs | 5 +- nex-packet/src/dns.rs | 295 ++++++++++++++--------------- nex-packet/src/ethernet.rs | 26 ++- nex-packet/src/flowcontrol.rs | 20 +- nex-packet/src/frame.rs | 18 +- nex-packet/src/gre.rs | 2 +- nex-packet/src/icmp.rs | 31 +-- nex-packet/src/icmpv6.rs | 270 +++++++++++++++++--------- nex-packet/src/ip.rs | 1 - nex-packet/src/ipv4.rs | 61 +++--- nex-packet/src/ipv6.rs | 115 +++++++---- nex-packet/src/lib.rs | 22 +-- nex-packet/src/packet.rs | 1 - nex-packet/src/tcp.rs | 27 ++- nex-packet/src/vlan.rs | 18 +- nex-packet/src/vxlan.rs | 2 +- nex-socket/src/icmp/async_impl.rs | 2 +- nex-socket/src/icmp/config.rs | 5 +- nex-socket/src/icmp/mod.rs | 4 +- nex-socket/src/tcp/async_impl.rs | 36 ++-- nex-socket/src/tcp/mod.rs | 4 +- nex-socket/src/tcp/sync_impl.rs | 41 ++-- nex-socket/src/udp/mod.rs | 4 +- nex-socket/src/udp/sync_impl.rs | 14 +- nex-sys/src/lib.rs | 2 +- nex-sys/src/unix.rs | 4 +- 57 files changed, 988 insertions(+), 686 deletions(-) diff --git a/examples/arp.rs b/examples/arp.rs index c03ee77..64df91a 100644 --- a/examples/arp.rs +++ b/examples/arp.rs @@ -10,9 +10,9 @@ use nex::datalink; use nex::datalink::Channel::Ethernet; use nex::net::interface::{get_interfaces, Interface}; use nex::net::mac::MacAddr; +use nex::packet::builder::ethernet::EthernetPacketBuilder; use nex::packet::ethernet::EtherType; use nex::packet::frame::{Frame, ParseOption}; -use nex::packet::builder::ethernet::EthernetPacketBuilder; use nex_packet::arp::ArpOperation; use nex_packet::builder::arp::ArpPacketBuilder; use nex_packet::packet::Packet; @@ -47,7 +47,10 @@ fn main() { None => Interface::default().expect("Failed to get default interface"), }; - let src_mac = interface.mac_addr.clone().expect("No MAC address on interface"); + let src_mac = interface + .mac_addr + .clone() + .expect("No MAC address on interface"); let src_ip = interface.ipv4.get(0).expect("No IPv4 address").addr(); let (mut tx, mut rx) = match datalink::channel(&interface, Default::default()) { @@ -63,9 +66,7 @@ fn main() { let arp_builder = ArpPacketBuilder::new(src_mac, src_ip, target_ip); - let packet = eth_builder - .payload(arp_builder.build().to_bytes()) - .build(); + let packet = eth_builder.payload(arp_builder.build().to_bytes()).build(); match tx.send(&packet.to_bytes()) { Some(_) => println!("ARP Request sent to {}", target_ip), @@ -83,7 +84,9 @@ fn main() { match &frame.datalink { Some(dlink) => { if let Some(arp) = &dlink.arp { - if arp.operation == ArpOperation::Reply && arp.sender_proto_addr == target_ip { + if arp.operation == ArpOperation::Reply + && arp.sender_proto_addr == target_ip + { println!("Received ARP Reply from {}", arp.sender_proto_addr); println!("MAC address: {}", arp.sender_hw_addr); println!( diff --git a/examples/async_icmp_socket.rs b/examples/async_icmp_socket.rs index 9dd4503..27cd226 100644 --- a/examples/async_icmp_socket.rs +++ b/examples/async_icmp_socket.rs @@ -4,16 +4,16 @@ //! Example: async_icmp_socket 192.168.1 use bytes::Bytes; -use nex_socket::icmp::{AsyncIcmpSocket, IcmpConfig, IcmpKind}; +use nex::net::interface::{get_interfaces, Interface}; use nex_packet::builder::icmp::IcmpPacketBuilder; use nex_packet::icmp::{self, IcmpType}; +use nex_socket::icmp::{AsyncIcmpSocket, IcmpConfig, IcmpKind}; +use rand::{thread_rng, Rng}; use std::collections::HashMap; use std::env; -use nex::net::interface::{Interface, get_interfaces}; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::sync::Arc; use std::time::Duration; -use rand::{Rng, thread_rng}; use tokio::sync::Mutex; use tokio::time; @@ -24,7 +24,10 @@ async fn main() -> std::io::Result<()> { assert!(parts.len() == 3, "prefix must be a.b.c"); let interface = match env::args().nth(2) { - Some(name) => get_interfaces().into_iter().find(|i| i.name == name).expect("interface not found"), + Some(name) => get_interfaces() + .into_iter() + .find(|i| i.name == name) + .expect("interface not found"), None => Interface::default().expect("default interface"), }; diff --git a/examples/async_tcp_socket.rs b/examples/async_tcp_socket.rs index 5ffb183..415225d 100644 --- a/examples/async_tcp_socket.rs +++ b/examples/async_tcp_socket.rs @@ -17,7 +17,11 @@ async fn main() -> std::io::Result<()> { for port in ports { let addr = SocketAddr::new(ip, port); handles.push(tokio::spawn(async move { - let cfg = if ip.is_ipv4() { TcpConfig::v4_stream() } else { TcpConfig::v6_stream() }; + let cfg = if ip.is_ipv4() { + TcpConfig::v4_stream() + } else { + TcpConfig::v6_stream() + }; let sock = AsyncTcpSocket::from_config(&cfg).unwrap(); match sock.connect_timeout(addr, Duration::from_millis(500)).await { Ok(_) => println!("Port {} is open", port), diff --git a/examples/async_udp_socket.rs b/examples/async_udp_socket.rs index a759dc7..cd861d4 100644 --- a/examples/async_udp_socket.rs +++ b/examples/async_udp_socket.rs @@ -9,7 +9,10 @@ use tokio::task; #[tokio::main] async fn main() -> std::io::Result<()> { - let server_cfg = UdpConfig { bind_addr: Some("127.0.0.1:0".parse().unwrap()), ..Default::default() }; + let server_cfg = UdpConfig { + bind_addr: Some("127.0.0.1:0".parse().unwrap()), + ..Default::default() + }; let server = AsyncUdpSocket::from_config(&server_cfg)?; let server_addr = server.local_addr()?; diff --git a/examples/dns_dump.rs b/examples/dns_dump.rs index 896441f..fccbd61 100644 --- a/examples/dns_dump.rs +++ b/examples/dns_dump.rs @@ -17,7 +17,7 @@ use nex_core::mac::MacAddr; use nex_packet::ethernet::EthernetHeader; use nex_packet::packet::Packet; use std::env; -use std::net::{IpAddr}; +use std::net::IpAddr; fn main() { let interface: Interface = match env::args().nth(1) { @@ -50,7 +50,8 @@ fn main() { ); let eth_packet = if interface.is_tun() - || (cfg!(any(target_os = "macos", target_os = "ios")) && interface.is_loopback()) + || (cfg!(any(target_os = "macos", target_os = "ios")) + && interface.is_loopback()) { let offset = if interface.is_loopback() { 14 } else { 0 }; let payload = Bytes::copy_from_slice(&packet[offset..]); @@ -59,7 +60,11 @@ fn main() { header: EthernetHeader { destination: MacAddr::zero(), source: MacAddr::zero(), - ethertype: if version == 4 { EtherType::Ipv4 } else { EtherType::Ipv6 }, + ethertype: if version == 4 { + EtherType::Ipv4 + } else { + EtherType::Ipv6 + }, }, payload, } @@ -69,11 +74,19 @@ fn main() { if let EtherType::Ipv4 = eth_packet.header.ethertype { if let Some(ipv4) = Ipv4Packet::from_bytes(eth_packet.payload.clone()) { - handle_udp(ipv4.payload, IpAddr::V4(ipv4.header.source), IpAddr::V4(ipv4.header.destination)); + handle_udp( + ipv4.payload, + IpAddr::V4(ipv4.header.source), + IpAddr::V4(ipv4.header.destination), + ); } } else if let EtherType::Ipv6 = eth_packet.header.ethertype { if let Some(ipv6) = Ipv6Packet::from_bytes(eth_packet.payload.clone()) { - handle_udp(ipv6.payload, IpAddr::V6(ipv6.header.source), IpAddr::V6(ipv6.header.destination)); + handle_udp( + ipv6.payload, + IpAddr::V6(ipv6.header.source), + IpAddr::V6(ipv6.header.destination), + ); } } } @@ -86,24 +99,38 @@ fn handle_udp(packet: Bytes, src: IpAddr, dst: IpAddr) { if let Some(udp) = UdpPacket::from_bytes(packet.clone()) { if udp.payload.len() > 0 { if let Some(dns) = DnsPacket::from_bytes(udp.payload.clone()) { - println!("DNS Packet: {}:{} > {}:{}", src, udp.header.source, dst, udp.header.destination); + println!( + "DNS Packet: {}:{} > {}:{}", + src, udp.header.source, dst, udp.header.destination + ); for query in &dns.queries { - println!(" Query: {:?} (type: {:?}, class: {:?})", query.get_qname_parsed(), query.qtype, query.qclass); + println!( + " Query: {:?} (type: {:?}, class: {:?})", + query.get_qname_parsed(), + query.qtype, + query.qclass + ); } for response in &dns.responses { match response.rtype { DnsType::A | DnsType::AAAA => { if let Some(ip) = response.get_ip() { - println!(" Response: {} (type: {:?}, ttl: {})", ip, response.rtype, response.ttl); + println!( + " Response: {} (type: {:?}, ttl: {})", + ip, response.rtype, response.ttl + ); } else { println!(" Invalid IP data for type: {:?}", response.rtype); } } DnsType::CNAME | DnsType::NS | DnsType::PTR => { if let Some(name) = response.get_name() { - println!(" Response: {} (type: {:?}, ttl: {})", name, response.rtype, response.ttl); + println!( + " Response: {} (type: {:?}, ttl: {})", + name, response.rtype, response.ttl + ); } else { println!(" Invalid name data for type: {:?}", response.rtype); } diff --git a/examples/dump.rs b/examples/dump.rs index c3bef37..8075bc1 100644 --- a/examples/dump.rs +++ b/examples/dump.rs @@ -12,9 +12,9 @@ use nex::packet::icmpv6::Icmpv6Packet; use nex::packet::ip::IpNextProtocol; use nex::packet::ipv4::Ipv4Packet; use nex::packet::ipv6::Ipv6Packet; +use nex::packet::packet::Packet; use nex::packet::tcp::TcpPacket; use nex::packet::udp::UdpPacket; -use nex::packet::packet::Packet; use nex_packet::ethernet::EthernetHeader; use nex_packet::{icmp, icmpv6}; use std::env; @@ -61,7 +61,7 @@ fn main() { capture_no, packet.len() ); - + if interface.is_tun() || (cfg!(any(target_os = "macos", target_os = "ios")) && interface.is_loopback()) @@ -74,14 +74,16 @@ fn main() { } let payload = Bytes::copy_from_slice(&packet[payload_offset..]); if packet.len() > payload_offset { - let version = Ipv4Packet::from_buf(packet) - .unwrap() - .header.version; + let version = Ipv4Packet::from_buf(packet).unwrap().header.version; let fake_eth = EthernetPacket { header: EthernetHeader { destination: MacAddr::zero(), source: MacAddr::zero(), - ethertype: if version == 4 { EtherType::Ipv4 } else { EtherType::Ipv6 }, + ethertype: if version == 4 { + EtherType::Ipv4 + } else { + EtherType::Ipv6 + }, }, payload, }; @@ -220,7 +222,8 @@ fn handle_icmp_packet(source: IpAddr, destination: IpAddr, packet: Bytes) { let total_len = icmp_packet.total_len(); match icmp_packet.header.icmp_type { IcmpType::EchoRequest => { - let echo_request_packet = icmp::echo_request::EchoRequestPacket::try_from(icmp_packet).unwrap(); + let echo_request_packet = + icmp::echo_request::EchoRequestPacket::try_from(icmp_packet).unwrap(); println!( "ICMP echo request {} -> {} (seq={:?}, id={:?}), length: {}", source, @@ -231,7 +234,8 @@ fn handle_icmp_packet(source: IpAddr, destination: IpAddr, packet: Bytes) { ); } IcmpType::EchoReply => { - let echo_reply_packet = icmp::echo_reply::EchoReplyPacket::try_from(icmp_packet).unwrap(); + let echo_reply_packet = + icmp::echo_reply::EchoReplyPacket::try_from(icmp_packet).unwrap(); println!( "ICMP echo reply {} -> {} (seq={:?}, id={:?}), length: {}", source, @@ -242,7 +246,11 @@ fn handle_icmp_packet(source: IpAddr, destination: IpAddr, packet: Bytes) { ); } IcmpType::DestinationUnreachable => { - let unreachable_packet = icmp::destination_unreachable::DestinationUnreachablePacket::try_from(icmp_packet).unwrap(); + let unreachable_packet = + icmp::destination_unreachable::DestinationUnreachablePacket::try_from( + icmp_packet, + ) + .unwrap(); println!( "ICMP destination unreachable {} -> {} (code={:?}), next_hop_mtu={}, length: {}", source, @@ -253,22 +261,17 @@ fn handle_icmp_packet(source: IpAddr, destination: IpAddr, packet: Bytes) { ); } IcmpType::TimeExceeded => { - let time_exceeded_packet = icmp::time_exceeded::TimeExceededPacket::try_from(icmp_packet).unwrap(); + let time_exceeded_packet = + icmp::time_exceeded::TimeExceededPacket::try_from(icmp_packet).unwrap(); println!( "ICMP time exceeded {} -> {} (code={:?}), length: {}", - source, - destination, - time_exceeded_packet.header.icmp_code, - total_len + source, destination, time_exceeded_packet.header.icmp_code, total_len ); } _ => { println!( "ICMP packet {} -> {} (type={:?}), length: {}", - source, - destination, - icmp_packet.header.icmp_type, - total_len + source, destination, icmp_packet.header.icmp_type, total_len ) } } @@ -282,7 +285,8 @@ fn handle_icmpv6_packet(source: IpAddr, destination: IpAddr, packet: Bytes) { if let Some(icmpv6_packet) = icmpv6_packet { match icmpv6_packet.header.icmpv6_type { nex::packet::icmpv6::Icmpv6Type::EchoRequest => { - let echo_request_packet = icmpv6::echo_request::EchoRequestPacket::try_from(icmpv6_packet).unwrap(); + let echo_request_packet = + icmpv6::echo_request::EchoRequestPacket::try_from(icmpv6_packet).unwrap(); println!( "ICMPv6 echo request {} -> {} (type={:?}), length: {}", source, @@ -292,7 +296,8 @@ fn handle_icmpv6_packet(source: IpAddr, destination: IpAddr, packet: Bytes) { ); } nex::packet::icmpv6::Icmpv6Type::EchoReply => { - let echo_reply_packet = icmpv6::echo_reply::EchoReplyPacket::try_from(icmpv6_packet).unwrap(); + let echo_reply_packet = + icmpv6::echo_reply::EchoReplyPacket::try_from(icmpv6_packet).unwrap(); println!( "ICMPv6 echo reply {} -> {} (type={:?}), length: {}", source, @@ -302,7 +307,8 @@ fn handle_icmpv6_packet(source: IpAddr, destination: IpAddr, packet: Bytes) { ); } nex::packet::icmpv6::Icmpv6Type::NeighborSolicitation => { - let ns_packet = icmpv6::ndp::NeighborSolicitPacket::try_from(icmpv6_packet).unwrap(); + let ns_packet = + icmpv6::ndp::NeighborSolicitPacket::try_from(icmpv6_packet).unwrap(); println!( "ICMPv6 neighbor solicitation {} -> {} (type={:?}), length: {}", source, diff --git a/examples/icmp_ping.rs b/examples/icmp_ping.rs index 3ff0f7c..076fe5e 100644 --- a/examples/icmp_ping.rs +++ b/examples/icmp_ping.rs @@ -12,19 +12,19 @@ use nex::datalink; use nex::datalink::Channel::Ethernet; use nex::net::interface::Interface; use nex::net::mac::MacAddr; -use nex::packet::ethernet::EtherType; -use nex::packet::frame::{Frame, ParseOption}; +use nex::packet::builder::ethernet::EthernetPacketBuilder; use nex::packet::builder::icmp::IcmpPacketBuilder; use nex::packet::builder::icmpv6::Icmpv6PacketBuilder; -use nex::packet::icmp::IcmpType; -use nex::packet::icmpv6::Icmpv6Type; -use nex::packet::builder::ethernet::EthernetPacketBuilder; use nex::packet::builder::ipv4::Ipv4PacketBuilder; use nex::packet::builder::ipv6::Ipv6PacketBuilder; -use nex_packet::{icmp, icmpv6}; +use nex::packet::ethernet::EtherType; +use nex::packet::frame::{Frame, ParseOption}; +use nex::packet::icmp::IcmpType; +use nex::packet::icmpv6::Icmpv6Type; use nex_packet::ip::IpNextProtocol; use nex_packet::ipv4::Ipv4Flags; use nex_packet::packet::Packet; +use nex_packet::{icmp, icmpv6}; use std::env; use std::net::IpAddr; diff --git a/examples/icmp_socket.rs b/examples/icmp_socket.rs index 2dab536..d1521d3 100644 --- a/examples/icmp_socket.rs +++ b/examples/icmp_socket.rs @@ -3,23 +3,34 @@ //! Usage: icmp_socket use bytes::Bytes; -use nex_socket::icmp::{IcmpConfig, IcmpKind, IcmpSocket}; +use nex::net::interface::{get_interfaces, Interface}; use nex_packet::builder::icmp::IcmpPacketBuilder; use nex_packet::builder::icmpv6::Icmpv6PacketBuilder; use nex_packet::{icmp, icmpv6}; -use nex::net::interface::{Interface, get_interfaces}; +use nex_socket::icmp::{IcmpConfig, IcmpKind, IcmpSocket}; use std::env; use std::net::{IpAddr, SocketAddr}; fn main() -> std::io::Result<()> { - let target_ip: IpAddr = env::args().nth(1).expect("Missing target IP").parse().expect("parse ip"); + let target_ip: IpAddr = env::args() + .nth(1) + .expect("Missing target IP") + .parse() + .expect("parse ip"); let interface = match env::args().nth(2) { - Some(name) => get_interfaces().into_iter().find(|i| i.name == name).expect("interface not found"), + Some(name) => get_interfaces() + .into_iter() + .find(|i| i.name == name) + .expect("interface not found"), None => Interface::default().expect("default interface"), }; let src_ip = match target_ip { - IpAddr::V4(_) => interface.ipv4.get(0).map(|v| IpAddr::V4(v.addr())).expect("No IPv4 address"), + IpAddr::V4(_) => interface + .ipv4 + .get(0) + .map(|v| IpAddr::V4(v.addr())) + .expect("No IPv4 address"), IpAddr::V6(_) => interface .ipv6 .iter() @@ -28,7 +39,11 @@ fn main() -> std::io::Result<()> { .expect("No global IPv6 address"), }; - let kind = if target_ip.is_ipv4() { IcmpKind::V4 } else { IcmpKind::V6 }; + let kind = if target_ip.is_ipv4() { + IcmpKind::V4 + } else { + IcmpKind::V6 + }; let socket = IcmpSocket::new(&IcmpConfig::new(kind))?; let packet = match (src_ip, target_ip) { diff --git a/examples/ndp.rs b/examples/ndp.rs index 30583a6..bc376d2 100644 --- a/examples/ndp.rs +++ b/examples/ndp.rs @@ -10,14 +10,14 @@ use nex::datalink; use nex::datalink::Channel::Ethernet; use nex::net::interface::{get_interfaces, Interface}; use nex::net::mac::MacAddr; +use nex::packet::builder::ethernet::EthernetPacketBuilder; +use nex::packet::builder::ipv6::Ipv6PacketBuilder; use nex::packet::ethernet::EtherType; use nex::packet::frame::{Frame, ParseOption}; use nex::packet::icmpv6::Icmpv6Type; use nex::packet::ip::IpNextProtocol; -use nex::packet::builder::ethernet::EthernetPacketBuilder; -use nex::packet::builder::ipv6::Ipv6PacketBuilder; -use nex_packet::packet::Packet; use nex_packet::builder::ndp::NdpPacketBuilder; +use nex_packet::packet::Packet; use std::env; use std::net::{IpAddr, Ipv6Addr}; use std::process; diff --git a/examples/parse_frame.rs b/examples/parse_frame.rs index 80f7194..eb32b79 100644 --- a/examples/parse_frame.rs +++ b/examples/parse_frame.rs @@ -83,7 +83,10 @@ pub fn display_frame(frame: &Frame) { if let Some(dl) = &frame.datalink { if let Some(eth) = &dl.ethernet { - println!(" Ethernet: {} > {} ({:?})", eth.source, eth.destination, eth.ethertype); + println!( + " Ethernet: {} > {} ({:?})", + eth.source, eth.destination, eth.ethertype + ); } if let Some(arp) = &dl.arp { println!( diff --git a/examples/tcp_ping.rs b/examples/tcp_ping.rs index 7db328b..7e05b43 100644 --- a/examples/tcp_ping.rs +++ b/examples/tcp_ping.rs @@ -2,7 +2,7 @@ //! //! Usage: //! tcp_ping -//! +//! //! Example: //! //! IPv4: tcp_ping 1.1.1.1:80 eth0 @@ -14,14 +14,14 @@ use nex::datalink; use nex::datalink::Channel::Ethernet; use nex::net::interface::Interface; use nex::net::mac::MacAddr; -use nex::packet::ethernet::EtherType; -use nex::packet::frame::{Frame, ParseOption}; -use nex::packet::ip::IpNextProtocol; -use nex::packet::tcp::{TcpFlags, TcpOptionPacket}; use nex::packet::builder::ethernet::EthernetPacketBuilder; use nex::packet::builder::ipv4::Ipv4PacketBuilder; use nex::packet::builder::ipv6::Ipv6PacketBuilder; use nex::packet::builder::tcp::TcpPacketBuilder; +use nex::packet::ethernet::EtherType; +use nex::packet::frame::{Frame, ParseOption}; +use nex::packet::ip::IpNextProtocol; +use nex::packet::tcp::{TcpFlags, TcpOptionPacket}; use nex_packet::ipv4::Ipv4Flags; use nex_packet::packet::Packet; use std::env; @@ -141,8 +141,7 @@ fn main() { process::exit(1); } } - - }, + } IpAddr::V6(dst_ipv6) => { match src_ip { IpAddr::V4(_) => { diff --git a/examples/tcp_socket.rs b/examples/tcp_socket.rs index d729610..3bacaf2 100644 --- a/examples/tcp_socket.rs +++ b/examples/tcp_socket.rs @@ -9,7 +9,11 @@ use std::net::{IpAddr, SocketAddr}; fn main() -> std::io::Result<()> { let ip: IpAddr = env::args().nth(1).expect("IP").parse().expect("ip"); - let port: u16 = env::args().nth(2).unwrap_or_else(|| "80".into()).parse().expect("port"); + let port: u16 = env::args() + .nth(2) + .unwrap_or_else(|| "80".into()) + .parse() + .expect("port"); let addr = SocketAddr::new(ip, port); let socket = match addr { @@ -24,6 +28,10 @@ fn main() -> std::io::Result<()> { let mut buf = [0u8; 512]; let n = stream.read(&mut buf)?; - println!("Received {} bytes:\n{}", n, String::from_utf8_lossy(&buf[..n])); + println!( + "Received {} bytes:\n{}", + n, + String::from_utf8_lossy(&buf[..n]) + ); Ok(()) } diff --git a/examples/udp_ping.rs b/examples/udp_ping.rs index 1ec5912..929acf2 100644 --- a/examples/udp_ping.rs +++ b/examples/udp_ping.rs @@ -12,14 +12,14 @@ use nex::datalink; use nex::datalink::Channel::Ethernet; use nex::net::interface::Interface; use nex::net::mac::MacAddr; -use nex::packet::ethernet::EtherType; -use nex::packet::frame::{Frame, ParseOption}; -use nex::packet::icmp::IcmpType; -use nex::packet::icmpv6::Icmpv6Type; use nex::packet::builder::ethernet::EthernetPacketBuilder; use nex::packet::builder::ipv4::Ipv4PacketBuilder; use nex::packet::builder::ipv6::Ipv6PacketBuilder; use nex::packet::builder::udp::UdpPacketBuilder; +use nex::packet::ethernet::EtherType; +use nex::packet::frame::{Frame, ParseOption}; +use nex::packet::icmp::IcmpType; +use nex::packet::icmpv6::Icmpv6Type; use nex_packet::ip::IpNextProtocol; use nex_packet::ipv4::Ipv4Flags; use nex_packet::packet::Packet; @@ -132,7 +132,10 @@ fn main() { if let Some(ip_layer) = &frame.ip { if let Some(icmp) = &ip_layer.icmp { if icmp.icmp_type == IcmpType::DestinationUnreachable { - println!("Received ICMP Port Unreachable (v4) from {}", ip_layer.ipv4.as_ref().unwrap().source); + println!( + "Received ICMP Port Unreachable (v4) from {}", + ip_layer.ipv4.as_ref().unwrap().source + ); println!( "---- Interface: {}, Total Length: {} bytes ----", interface.name, @@ -144,7 +147,10 @@ fn main() { } if let Some(icmpv6) = &ip_layer.icmpv6 { if icmpv6.icmpv6_type == Icmpv6Type::DestinationUnreachable { - println!("Received ICMP Port Unreachable (v6) from {}", ip_layer.ipv6.as_ref().unwrap().source); + println!( + "Received ICMP Port Unreachable (v6) from {}", + ip_layer.ipv6.as_ref().unwrap().source + ); println!( "---- Interface: {}, Total Length: {} bytes ----", interface.name, diff --git a/examples/udp_socket.rs b/examples/udp_socket.rs index b2424fb..07d9b80 100644 --- a/examples/udp_socket.rs +++ b/examples/udp_socket.rs @@ -6,7 +6,10 @@ use nex_socket::udp::{UdpConfig, UdpSocket}; use std::thread; fn main() -> std::io::Result<()> { - let server_cfg = UdpConfig { bind_addr: Some("127.0.0.1:0".parse().unwrap()), ..Default::default() }; + let server_cfg = UdpConfig { + bind_addr: Some("127.0.0.1:0".parse().unwrap()), + ..Default::default() + }; let server = UdpSocket::from_config(&server_cfg)?; let server_addr = server.local_addr()?; diff --git a/nex-core/src/bitfield.rs b/nex-core/src/bitfield.rs index 723aa5f..d7d2532 100644 --- a/nex-core/src/bitfield.rs +++ b/nex-core/src/bitfield.rs @@ -3,7 +3,7 @@ //! These types are aliased to the next largest of \[`u8`, `u16`, `u32`, `u64`\] //! //! All aliases for types larger than `u8` contain a `be` or `le` suffix. These specify whether the -//! value is big or little endian, respectively. +//! value is big or little endian, respectively. #![allow(non_camel_case_types)] /// Represents an unsigned, 1-bit integer. @@ -20,231 +20,231 @@ pub type u5 = u8; pub type u6 = u8; /// Represents an unsigned, 7-bit integer. pub type u7 = u8; -/// Represents an unsigned 9-bit integer. +/// Represents an unsigned 9-bit integer. pub type u9be = u16; -/// Represents an unsigned 10-bit integer. +/// Represents an unsigned 10-bit integer. pub type u10be = u16; -/// Represents an unsigned 11-bit integer. +/// Represents an unsigned 11-bit integer. pub type u11be = u16; -/// Represents an unsigned 12-bit integer. +/// Represents an unsigned 12-bit integer. pub type u12be = u16; -/// Represents an unsigned 13-bit integer. +/// Represents an unsigned 13-bit integer. pub type u13be = u16; -/// Represents an unsigned 14-bit integer. +/// Represents an unsigned 14-bit integer. pub type u14be = u16; -/// Represents an unsigned 15-bit integer. +/// Represents an unsigned 15-bit integer. pub type u15be = u16; -/// Represents an unsigned 16-bit integer. +/// Represents an unsigned 16-bit integer. pub type u16be = u16; -/// Represents an unsigned 17-bit integer. +/// Represents an unsigned 17-bit integer. pub type u17be = u32; -/// Represents an unsigned 18-bit integer. +/// Represents an unsigned 18-bit integer. pub type u18be = u32; -/// Represents an unsigned 19-bit integer. +/// Represents an unsigned 19-bit integer. pub type u19be = u32; -/// Represents an unsigned 20-bit integer. +/// Represents an unsigned 20-bit integer. pub type u20be = u32; -/// Represents an unsigned 21-bit integer. +/// Represents an unsigned 21-bit integer. pub type u21be = u32; -/// Represents an unsigned 22-bit integer. +/// Represents an unsigned 22-bit integer. pub type u22be = u32; -/// Represents an unsigned 23-bit integer. +/// Represents an unsigned 23-bit integer. pub type u23be = u32; -/// Represents an unsigned 24-bit integer. +/// Represents an unsigned 24-bit integer. pub type u24be = u32; -/// Represents an unsigned 25-bit integer. +/// Represents an unsigned 25-bit integer. pub type u25be = u32; -/// Represents an unsigned 26-bit integer. +/// Represents an unsigned 26-bit integer. pub type u26be = u32; -/// Represents an unsigned 27-bit integer. +/// Represents an unsigned 27-bit integer. pub type u27be = u32; -/// Represents an unsigned 28-bit integer. +/// Represents an unsigned 28-bit integer. pub type u28be = u32; -/// Represents an unsigned 29-bit integer. +/// Represents an unsigned 29-bit integer. pub type u29be = u32; -/// Represents an unsigned 30-bit integer. +/// Represents an unsigned 30-bit integer. pub type u30be = u32; -/// Represents an unsigned 31-bit integer. +/// Represents an unsigned 31-bit integer. pub type u31be = u32; -/// Represents an unsigned 32-bit integer. +/// Represents an unsigned 32-bit integer. pub type u32be = u32; -/// Represents an unsigned 33-bit integer. +/// Represents an unsigned 33-bit integer. pub type u33be = u64; -/// Represents an unsigned 34-bit integer. +/// Represents an unsigned 34-bit integer. pub type u34be = u64; -/// Represents an unsigned 35-bit integer. +/// Represents an unsigned 35-bit integer. pub type u35be = u64; -/// Represents an unsigned 36-bit integer. +/// Represents an unsigned 36-bit integer. pub type u36be = u64; -/// Represents an unsigned 37-bit integer. +/// Represents an unsigned 37-bit integer. pub type u37be = u64; -/// Represents an unsigned 38-bit integer. +/// Represents an unsigned 38-bit integer. pub type u38be = u64; -/// Represents an unsigned 39-bit integer. +/// Represents an unsigned 39-bit integer. pub type u39be = u64; -/// Represents an unsigned 40-bit integer. +/// Represents an unsigned 40-bit integer. pub type u40be = u64; -/// Represents an unsigned 41-bit integer. +/// Represents an unsigned 41-bit integer. pub type u41be = u64; -/// Represents an unsigned 42-bit integer. +/// Represents an unsigned 42-bit integer. pub type u42be = u64; -/// Represents an unsigned 43-bit integer. +/// Represents an unsigned 43-bit integer. pub type u43be = u64; -/// Represents an unsigned 44-bit integer. +/// Represents an unsigned 44-bit integer. pub type u44be = u64; -/// Represents an unsigned 45-bit integer. +/// Represents an unsigned 45-bit integer. pub type u45be = u64; -/// Represents an unsigned 46-bit integer. +/// Represents an unsigned 46-bit integer. pub type u46be = u64; -/// Represents an unsigned 47-bit integer. +/// Represents an unsigned 47-bit integer. pub type u47be = u64; -/// Represents an unsigned 48-bit integer. +/// Represents an unsigned 48-bit integer. pub type u48be = u64; -/// Represents an unsigned 49-bit integer. +/// Represents an unsigned 49-bit integer. pub type u49be = u64; -/// Represents an unsigned 50-bit integer. +/// Represents an unsigned 50-bit integer. pub type u50be = u64; -/// Represents an unsigned 51-bit integer. +/// Represents an unsigned 51-bit integer. pub type u51be = u64; -/// Represents an unsigned 52-bit integer. +/// Represents an unsigned 52-bit integer. pub type u52be = u64; -/// Represents an unsigned 53-bit integer. +/// Represents an unsigned 53-bit integer. pub type u53be = u64; -/// Represents an unsigned 54-bit integer. +/// Represents an unsigned 54-bit integer. pub type u54be = u64; -/// Represents an unsigned 55-bit integer. +/// Represents an unsigned 55-bit integer. pub type u55be = u64; -/// Represents an unsigned 56-bit integer. +/// Represents an unsigned 56-bit integer. pub type u56be = u64; -/// Represents an unsigned 57-bit integer. +/// Represents an unsigned 57-bit integer. pub type u57be = u64; -/// Represents an unsigned 58-bit integer. +/// Represents an unsigned 58-bit integer. pub type u58be = u64; -/// Represents an unsigned 59-bit integer. +/// Represents an unsigned 59-bit integer. pub type u59be = u64; -/// Represents an unsigned 60-bit integer. +/// Represents an unsigned 60-bit integer. pub type u60be = u64; -/// Represents an unsigned 61-bit integer. +/// Represents an unsigned 61-bit integer. pub type u61be = u64; -/// Represents an unsigned 62-bit integer. +/// Represents an unsigned 62-bit integer. pub type u62be = u64; -/// Represents an unsigned 63-bit integer. +/// Represents an unsigned 63-bit integer. pub type u63be = u64; -/// Represents an unsigned 64-bit integer. +/// Represents an unsigned 64-bit integer. pub type u64be = u64; -/// Represents an unsigned 9-bit integer. +/// Represents an unsigned 9-bit integer. pub type u9le = u16; -/// Represents an unsigned 10-bit integer. +/// Represents an unsigned 10-bit integer. pub type u10le = u16; -/// Represents an unsigned 11-bit integer. +/// Represents an unsigned 11-bit integer. pub type u11le = u16; -/// Represents an unsigned 12-bit integer. +/// Represents an unsigned 12-bit integer. pub type u12le = u16; -/// Represents an unsigned 13-bit integer. +/// Represents an unsigned 13-bit integer. pub type u13le = u16; -/// Represents an unsigned 14-bit integer. +/// Represents an unsigned 14-bit integer. pub type u14le = u16; -/// Represents an unsigned 15-bit integer. +/// Represents an unsigned 15-bit integer. pub type u15le = u16; -/// Represents an unsigned 16-bit integer. +/// Represents an unsigned 16-bit integer. pub type u16le = u16; -/// Represents an unsigned 17-bit integer. +/// Represents an unsigned 17-bit integer. pub type u17le = u32; -/// Represents an unsigned 18-bit integer. +/// Represents an unsigned 18-bit integer. pub type u18le = u32; -/// Represents an unsigned 19-bit integer. +/// Represents an unsigned 19-bit integer. pub type u19le = u32; -/// Represents an unsigned 20-bit integer. +/// Represents an unsigned 20-bit integer. pub type u20le = u32; -/// Represents an unsigned 21-bit integer. +/// Represents an unsigned 21-bit integer. pub type u21le = u32; -/// Represents an unsigned 22-bit integer. +/// Represents an unsigned 22-bit integer. pub type u22le = u32; -/// Represents an unsigned 23-bit integer. +/// Represents an unsigned 23-bit integer. pub type u23le = u32; -/// Represents an unsigned 24-bit integer. +/// Represents an unsigned 24-bit integer. pub type u24le = u32; -/// Represents an unsigned 25-bit integer. +/// Represents an unsigned 25-bit integer. pub type u25le = u32; -/// Represents an unsigned 26-bit integer. +/// Represents an unsigned 26-bit integer. pub type u26le = u32; -/// Represents an unsigned 27-bit integer. +/// Represents an unsigned 27-bit integer. pub type u27le = u32; -/// Represents an unsigned 28-bit integer. +/// Represents an unsigned 28-bit integer. pub type u28le = u32; -/// Represents an unsigned 29-bit integer. +/// Represents an unsigned 29-bit integer. pub type u29le = u32; -/// Represents an unsigned 30-bit integer. +/// Represents an unsigned 30-bit integer. pub type u30le = u32; -/// Represents an unsigned 31-bit integer. +/// Represents an unsigned 31-bit integer. pub type u31le = u32; -/// Represents an unsigned 32-bit integer. +/// Represents an unsigned 32-bit integer. pub type u32le = u32; -/// Represents an unsigned 33-bit integer. +/// Represents an unsigned 33-bit integer. pub type u33le = u64; -/// Represents an unsigned 34-bit integer. +/// Represents an unsigned 34-bit integer. pub type u34le = u64; -/// Represents an unsigned 35-bit integer. +/// Represents an unsigned 35-bit integer. pub type u35le = u64; -/// Represents an unsigned 36-bit integer. +/// Represents an unsigned 36-bit integer. pub type u36le = u64; -/// Represents an unsigned 37-bit integer. +/// Represents an unsigned 37-bit integer. pub type u37le = u64; -/// Represents an unsigned 38-bit integer. +/// Represents an unsigned 38-bit integer. pub type u38le = u64; -/// Represents an unsigned 39-bit integer. +/// Represents an unsigned 39-bit integer. pub type u39le = u64; -/// Represents an unsigned 40-bit integer. +/// Represents an unsigned 40-bit integer. pub type u40le = u64; -/// Represents an unsigned 41-bit integer. +/// Represents an unsigned 41-bit integer. pub type u41le = u64; -/// Represents an unsigned 42-bit integer. +/// Represents an unsigned 42-bit integer. pub type u42le = u64; -/// Represents an unsigned 43-bit integer. +/// Represents an unsigned 43-bit integer. pub type u43le = u64; -/// Represents an unsigned 44-bit integer. +/// Represents an unsigned 44-bit integer. pub type u44le = u64; -/// Represents an unsigned 45-bit integer. +/// Represents an unsigned 45-bit integer. pub type u45le = u64; -/// Represents an unsigned 46-bit integer. +/// Represents an unsigned 46-bit integer. pub type u46le = u64; -/// Represents an unsigned 47-bit integer. +/// Represents an unsigned 47-bit integer. pub type u47le = u64; -/// Represents an unsigned 48-bit integer. +/// Represents an unsigned 48-bit integer. pub type u48le = u64; -/// Represents an unsigned 49-bit integer. +/// Represents an unsigned 49-bit integer. pub type u49le = u64; -/// Represents an unsigned 50-bit integer. +/// Represents an unsigned 50-bit integer. pub type u50le = u64; -/// Represents an unsigned 51-bit integer. +/// Represents an unsigned 51-bit integer. pub type u51le = u64; -/// Represents an unsigned 52-bit integer. +/// Represents an unsigned 52-bit integer. pub type u52le = u64; -/// Represents an unsigned 53-bit integer. +/// Represents an unsigned 53-bit integer. pub type u53le = u64; -/// Represents an unsigned 54-bit integer. +/// Represents an unsigned 54-bit integer. pub type u54le = u64; -/// Represents an unsigned 55-bit integer. +/// Represents an unsigned 55-bit integer. pub type u55le = u64; -/// Represents an unsigned 56-bit integer. +/// Represents an unsigned 56-bit integer. pub type u56le = u64; -/// Represents an unsigned 57-bit integer. +/// Represents an unsigned 57-bit integer. pub type u57le = u64; -/// Represents an unsigned 58-bit integer. +/// Represents an unsigned 58-bit integer. pub type u58le = u64; -/// Represents an unsigned 59-bit integer. +/// Represents an unsigned 59-bit integer. pub type u59le = u64; -/// Represents an unsigned 60-bit integer. +/// Represents an unsigned 60-bit integer. pub type u60le = u64; -/// Represents an unsigned 61-bit integer. +/// Represents an unsigned 61-bit integer. pub type u61le = u64; -/// Represents an unsigned 62-bit integer. +/// Represents an unsigned 62-bit integer. pub type u62le = u64; -/// Represents an unsigned 63-bit integer. +/// Represents an unsigned 63-bit integer. pub type u63le = u64; -/// Represents an unsigned 64-bit integer. +/// Represents an unsigned 64-bit integer. pub type u64le = u64; /// Represents an unsigned 9-bit integer in host endianness. pub type u9he = u16; @@ -384,4 +384,3 @@ mod tests { assert_eq!(std::mem::size_of::(), 8); } } - diff --git a/nex-core/src/ip.rs b/nex-core/src/ip.rs index 575ceac..b78c6b7 100644 --- a/nex-core/src/ip.rs +++ b/nex-core/src/ip.rs @@ -137,4 +137,4 @@ mod tests { assert!(!is_global_ip(&ip_private)); assert!(!is_global_ip(&ip_ula)); } -} \ No newline at end of file +} diff --git a/nex-core/src/lib.rs b/nex-core/src/lib.rs index c107dfb..77e11f2 100644 --- a/nex-core/src/lib.rs +++ b/nex-core/src/lib.rs @@ -3,9 +3,9 @@ pub use netdev; +pub mod bitfield; pub mod device; pub mod gateway; pub mod interface; pub mod ip; pub mod mac; -pub mod bitfield; diff --git a/nex-datalink/src/bindings/bpf.rs b/nex-datalink/src/bindings/bpf.rs index ee594e2..6f1fd73 100644 --- a/nex-datalink/src/bindings/bpf.rs +++ b/nex-datalink/src/bindings/bpf.rs @@ -144,4 +144,4 @@ pub struct bpf_hdr { #[cfg(not(windows))] extern "C" { pub fn ioctl(d: libc::c_int, request: libc::c_ulong, ...) -> libc::c_int; -} \ No newline at end of file +} diff --git a/nex-datalink/src/linux.rs b/nex-datalink/src/linux.rs index 7fd2e3c..c2f4595 100644 --- a/nex-datalink/src/linux.rs +++ b/nex-datalink/src/linux.rs @@ -62,8 +62,7 @@ fn poll_timeout_ms(timeout: Option) -> libc::c_int { timeout .map(|to| { let ms = (to.tv_sec as i64 * 1000) + (to.tv_nsec as i64 / 1_000_000); - ms.clamp(i64::from(libc::c_int::MIN), i64::from(libc::c_int::MAX)) - as libc::c_int + ms.clamp(i64::from(libc::c_int::MIN), i64::from(libc::c_int::MAX)) as libc::c_int }) .unwrap_or(-1) } diff --git a/nex-packet/src/arp.rs b/nex-packet/src/arp.rs index 53e0c76..67f2bff 100644 --- a/nex-packet/src/arp.rs +++ b/nex-packet/src/arp.rs @@ -1,10 +1,13 @@ //! ARP packet abstraction. -use crate::{ethernet::{EtherType, ETHERNET_HEADER_LEN}, packet::Packet}; +use crate::{ + ethernet::{EtherType, ETHERNET_HEADER_LEN}, + packet::Packet, +}; use bytes::{Bytes, BytesMut}; -use nex_core::mac::MacAddr; use core::fmt; +use nex_core::mac::MacAddr; use std::net::Ipv4Addr; #[cfg(feature = "serde")] @@ -230,9 +233,13 @@ impl ArpHardwareType { ArpHardwareType::AsynchronousTransmissionMode => "Asynchronous Transmission Mode (ATM)", ArpHardwareType::HDLC => "HDLC", ArpHardwareType::FibreChannel => "Fibre Channel", - ArpHardwareType::AsynchronousTransmissionMode2 => "Asynchronous Transmission Mode (ATM) 2", + ArpHardwareType::AsynchronousTransmissionMode2 => { + "Asynchronous Transmission Mode (ATM) 2" + } ArpHardwareType::SerialLine => "Serial Line", - ArpHardwareType::AsynchronousTransmissionMode3 => "Asynchronous Transmission Mode (ATM) 3", + ArpHardwareType::AsynchronousTransmissionMode3 => { + "Asynchronous Transmission Mode (ATM) 3" + } ArpHardwareType::MILSTD188220 => "MIL-STD-188-220", ArpHardwareType::Metricom => "Metricom", ArpHardwareType::IEEE13941995 => "IEEE 1394.1995", @@ -244,7 +251,9 @@ impl ArpHardwareType { ArpHardwareType::ARPSec => "ARPSec", ArpHardwareType::IPsecTunnel => "IPsec Tunnel", ArpHardwareType::InfiniBand => "InfiniBand (TM)", - ArpHardwareType::TIA102Project25CommonAirInterface => "TIA-102 Project 25 Common Air Interface", + ArpHardwareType::TIA102Project25CommonAirInterface => { + "TIA-102 Project 25 Common Air Interface" + } ArpHardwareType::WiegandInterface => "Wiegand Interface", ArpHardwareType::PureIP => "Pure IP", ArpHardwareType::HWEXP1 => "HW_EXP1", @@ -372,7 +381,7 @@ impl Packet for ArpPacket { buf.extend_from_slice(&self.header.target_hw_addr.octets()); buf.extend_from_slice(&self.header.target_proto_addr.octets()); buf.extend_from_slice(&self.payload); - + Bytes::from(buf) } @@ -384,7 +393,7 @@ impl Packet for ArpPacket { self.payload.clone() } - fn header_len (&self) -> usize { + fn header_len(&self) -> usize { ARP_HEADER_LEN } fn payload_len(&self) -> usize { @@ -447,13 +456,13 @@ mod tests { let raw = [ 0x00, 0x01, // Hardware Type: Ethernet 0x08, 0x00, // Protocol Type: IPv4 - 0x06, // HW Addr Len - 0x04, // Proto Addr Len + 0x06, // HW Addr Len + 0x04, // Proto Addr Len 0x00, 0x01, // Operation: Request 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, // Sender MAC - 192, 168, 1, 1, // Sender IP + 192, 168, 1, 1, // Sender IP 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Target MAC - 192, 168, 1, 2 // Target IP + 192, 168, 1, 2, // Target IP ]; let padded = [&raw[..], &[0xde, 0xad, 0xbe, 0xef]].concat(); @@ -464,11 +473,26 @@ mod tests { assert_eq!(packet.header.hw_addr_len, 6); assert_eq!(packet.header.proto_addr_len, 4); assert_eq!(packet.header.operation, ArpOperation::Request); - assert_eq!(packet.header.sender_hw_addr, MacAddr::from_octets([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff])); - assert_eq!(packet.header.sender_proto_addr, Ipv4Addr::new(192, 168, 1, 1)); - assert_eq!(packet.header.target_hw_addr, MacAddr::from_octets([0, 0, 0, 0, 0, 0])); - assert_eq!(packet.header.target_proto_addr, Ipv4Addr::new(192, 168, 1, 2)); - assert_eq!(packet.payload, Bytes::from_static(&[0xde, 0xad, 0xbe, 0xef])); + assert_eq!( + packet.header.sender_hw_addr, + MacAddr::from_octets([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]) + ); + assert_eq!( + packet.header.sender_proto_addr, + Ipv4Addr::new(192, 168, 1, 1) + ); + assert_eq!( + packet.header.target_hw_addr, + MacAddr::from_octets([0, 0, 0, 0, 0, 0]) + ); + assert_eq!( + packet.header.target_proto_addr, + Ipv4Addr::new(192, 168, 1, 2) + ); + assert_eq!( + packet.payload, + Bytes::from_static(&[0xde, 0xad, 0xbe, 0xef]) + ); } #[test] @@ -504,14 +528,9 @@ mod tests { let raw = [ 0x99, 0x99, // Hardware Type: unknown 0x08, 0x00, // Protocol Type: IPv4 - 0x06, - 0x04, - 0x99, 0x99, // Operation: unknown - 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, - 192, 168, 1, 1, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 192, 168, 1, 2, - 0x00, 0x01, 0x02, 0x03 + 0x06, 0x04, 0x99, 0x99, // Operation: unknown + 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 192, 168, 1, 1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 192, 168, 1, 2, 0x00, 0x01, 0x02, 0x03, ]; let packet = ArpPacket::from_bytes(Bytes::copy_from_slice(&raw)).unwrap(); @@ -525,5 +544,3 @@ mod tests { } } } - - diff --git a/nex-packet/src/builder/arp.rs b/nex-packet/src/builder/arp.rs index 311e64f..cdf2ae8 100644 --- a/nex-packet/src/builder/arp.rs +++ b/nex-packet/src/builder/arp.rs @@ -1,9 +1,9 @@ -use bytes::Bytes; use crate::{ + arp::{ArpHardwareType, ArpHeader, ArpOperation, ArpPacket}, ethernet::EtherType, packet::Packet, - arp::{ArpHeader, ArpPacket, ArpHardwareType, ArpOperation}, }; +use bytes::Bytes; use nex_core::mac::MacAddr; use std::net::Ipv4Addr; diff --git a/nex-packet/src/builder/dhcp.rs b/nex-packet/src/builder/dhcp.rs index 5152c8b..9fbcc51 100644 --- a/nex-packet/src/builder/dhcp.rs +++ b/nex-packet/src/builder/dhcp.rs @@ -3,7 +3,10 @@ use std::net::Ipv4Addr; use bytes::Bytes; use nex_core::mac::MacAddr; -use crate::{dhcp::{DhcpHardwareType, DhcpHeader, DhcpOperation, DhcpPacket}, packet::Packet}; +use crate::{ + dhcp::{DhcpHardwareType, DhcpHeader, DhcpOperation, DhcpPacket}, + packet::Packet, +}; /// Builder for constructing DHCP packets #[derive(Debug, Clone)] diff --git a/nex-packet/src/builder/ethernet.rs b/nex-packet/src/builder/ethernet.rs index c68771f..a61bca5 100644 --- a/nex-packet/src/builder/ethernet.rs +++ b/nex-packet/src/builder/ethernet.rs @@ -1,6 +1,9 @@ -use crate::{ethernet::{EtherType, EthernetHeader, EthernetPacket}, packet::Packet}; -use nex_core::mac::MacAddr; +use crate::{ + ethernet::{EtherType, EthernetHeader, EthernetPacket}, + packet::Packet, +}; use bytes::Bytes; +use nex_core::mac::MacAddr; /// Builder for constructing Ethernet packets. #[derive(Debug, Clone)] diff --git a/nex-packet/src/builder/icmp.rs b/nex-packet/src/builder/icmp.rs index 02af80b..1d2caff 100644 --- a/nex-packet/src/builder/icmp.rs +++ b/nex-packet/src/builder/icmp.rs @@ -1,7 +1,10 @@ use std::net::Ipv4Addr; -use bytes::{Bytes, BytesMut, BufMut}; -use crate::{icmp::{self, checksum, IcmpCode, IcmpHeader, IcmpPacket, IcmpType}, packet::Packet}; +use crate::{ + icmp::{self, checksum, IcmpCode, IcmpHeader, IcmpPacket, IcmpType}, + packet::Packet, +}; +use bytes::{BufMut, Bytes, BytesMut}; /// Builder for constructing ICMP packets #[derive(Debug, Clone)] diff --git a/nex-packet/src/builder/icmpv6.rs b/nex-packet/src/builder/icmpv6.rs index cf2c5f8..7d613d7 100644 --- a/nex-packet/src/builder/icmpv6.rs +++ b/nex-packet/src/builder/icmpv6.rs @@ -1,15 +1,15 @@ use std::net::Ipv6Addr; -use bytes::{Bytes, BytesMut, BufMut}; use crate::{ icmpv6::{self, checksum, Icmpv6Code, Icmpv6Header, Icmpv6Packet, Icmpv6Type}, packet::Packet, }; +use bytes::{BufMut, Bytes, BytesMut}; /// Builder for constructing ICMPv6 packets #[derive(Debug, Clone)] pub struct Icmpv6PacketBuilder { - source: Ipv6Addr, + source: Ipv6Addr, destination: Ipv6Addr, packet: Icmpv6Packet, } diff --git a/nex-packet/src/builder/ipv4.rs b/nex-packet/src/builder/ipv4.rs index 6bbaaf6..4395d4f 100644 --- a/nex-packet/src/builder/ipv4.rs +++ b/nex-packet/src/builder/ipv4.rs @@ -1,4 +1,8 @@ -use crate::{ipv4::{Ipv4Header, Ipv4Packet, Ipv4OptionPacket, Ipv4OptionType}, ip::IpNextProtocol, packet::Packet}; +use crate::{ + ip::IpNextProtocol, + ipv4::{Ipv4Header, Ipv4OptionPacket, Ipv4OptionType, Ipv4Packet}, + packet::Packet, +}; use bytes::Bytes; use nex_core::bitfield::*; use std::net::Ipv4Addr; @@ -72,12 +76,19 @@ impl Ipv4PacketBuilder { pub fn options(mut self, options: Vec) -> Self { self.packet.header.options = options; - self.packet.header.header_length = ((20 + self.packet.header.options.iter().map(|opt| { - match opt.header.number { - Ipv4OptionType::EOL | Ipv4OptionType::NOP => 1, - _ => 2 + opt.data.len(), - } - }).sum::() + 3) / 4) as u4; // includes padding + self.packet.header.header_length = ((20 + + self + .packet + .header + .options + .iter() + .map(|opt| match opt.header.number { + Ipv4OptionType::EOL | Ipv4OptionType::NOP => 1, + _ => 2 + opt.data.len(), + }) + .sum::() + + 3) + / 4) as u4; // includes padding self } @@ -108,15 +119,17 @@ mod tests { #[test] fn ipv4_builder_total_length() { - let payload = Bytes::from_static(&[1,2]); + let payload = Bytes::from_static(&[1, 2]); let pkt = Ipv4PacketBuilder::new() - .source(Ipv4Addr::new(1,1,1,1)) - .destination(Ipv4Addr::new(2,2,2,2)) + .source(Ipv4Addr::new(1, 1, 1, 1)) + .destination(Ipv4Addr::new(2, 2, 2, 2)) .protocol(IpNextProtocol::Udp) .payload(payload.clone()) .build(); - assert_eq!(pkt.header.total_length, (pkt.header_len() + payload.len()) as u16); + assert_eq!( + pkt.header.total_length, + (pkt.header_len() + payload.len()) as u16 + ); assert_eq!(pkt.payload, payload); } } - diff --git a/nex-packet/src/builder/ipv6.rs b/nex-packet/src/builder/ipv6.rs index 78c099b..9bf7545 100644 --- a/nex-packet/src/builder/ipv6.rs +++ b/nex-packet/src/builder/ipv6.rs @@ -1,10 +1,10 @@ -use std::net::Ipv6Addr; -use bytes::Bytes; use crate::{ ip::IpNextProtocol, - ipv6::{Ipv6Header, Ipv6Packet, Ipv6ExtensionHeader}, + ipv6::{Ipv6ExtensionHeader, Ipv6Header, Ipv6Packet}, packet::Packet, }; +use bytes::Bytes; +use std::net::Ipv6Addr; /// Builder for constructing IPv6 packets #[derive(Debug, Clone)] @@ -105,7 +105,7 @@ mod tests { #[test] fn ipv6_builder_payload_len() { - let payload = Bytes::from_static(&[1,2,3,4]); + let payload = Bytes::from_static(&[1, 2, 3, 4]); let pkt = Ipv6PacketBuilder::new() .source(Ipv6Addr::LOCALHOST) .destination(Ipv6Addr::LOCALHOST) @@ -116,4 +116,3 @@ mod tests { assert_eq!(pkt.payload, payload); } } - diff --git a/nex-packet/src/builder/mod.rs b/nex-packet/src/builder/mod.rs index 8f70f68..3cabb43 100644 --- a/nex-packet/src/builder/mod.rs +++ b/nex-packet/src/builder/mod.rs @@ -1,10 +1,10 @@ pub mod arp; pub mod dhcp; pub mod ethernet; -pub mod ipv4; -pub mod ipv6; pub mod icmp; pub mod icmpv6; +pub mod ipv4; +pub mod ipv6; +pub mod ndp; pub mod tcp; pub mod udp; -pub mod ndp; diff --git a/nex-packet/src/builder/ndp.rs b/nex-packet/src/builder/ndp.rs index cecb80a..24fce2f 100644 --- a/nex-packet/src/builder/ndp.rs +++ b/nex-packet/src/builder/ndp.rs @@ -1,13 +1,9 @@ +use crate::icmpv6::ndp::{NdpOptionPacket, NdpOptionTypes, NeighborSolicitPacket}; +use crate::icmpv6::{self, checksum, Icmpv6Header, Icmpv6Packet, Icmpv6Type}; +use crate::packet::Packet; use bytes::Bytes; -use std::net::Ipv6Addr; use nex_core::mac::MacAddr; -use crate::icmpv6::{ - self, checksum, Icmpv6Header, Icmpv6Packet, Icmpv6Type -}; -use crate::icmpv6::ndp::{ - NdpOptionPacket, NdpOptionTypes, NeighborSolicitPacket -}; -use crate::packet::Packet; +use std::net::Ipv6Addr; /// Length rounded up to an 8-byte multiple (for option length) fn octets_len(len: usize) -> u8 { diff --git a/nex-packet/src/builder/tcp.rs b/nex-packet/src/builder/tcp.rs index 3392100..c18627e 100644 --- a/nex-packet/src/builder/tcp.rs +++ b/nex-packet/src/builder/tcp.rs @@ -1,8 +1,8 @@ use std::net::IpAddr; -use crate::tcp::{TcpPacket, TcpHeader, TcpOptionPacket}; -use bytes::Bytes; use crate::packet::Packet; +use crate::tcp::{TcpHeader, TcpOptionPacket, TcpPacket}; +use bytes::Bytes; /// Builder for constructing TCP packets #[derive(Debug, Clone)] @@ -72,7 +72,13 @@ impl TcpPacketBuilder { self.packet.header.options = options; // Recalculate data offset (header length is in 4-byte units) let base_len = 20; // base header - let opt_len: usize = self.packet.header.options.iter().map(|opt| opt.length() as usize).sum(); + let opt_len: usize = self + .packet + .header + .options + .iter() + .map(|opt| opt.length() as usize) + .sum(); let total = base_len + opt_len; self.packet.header.data_offset = ((total + 3) / 4) as u8; // round up self @@ -123,4 +129,3 @@ mod tests { assert_eq!(pkt.payload, Bytes::from_static(b"abc")); } } - diff --git a/nex-packet/src/builder/udp.rs b/nex-packet/src/builder/udp.rs index 1db3e81..f55d11d 100644 --- a/nex-packet/src/builder/udp.rs +++ b/nex-packet/src/builder/udp.rs @@ -1,7 +1,7 @@ use std::net::IpAddr; -use crate::udp::{UdpPacket, UdpHeader, UDP_HEADER_LEN}; use crate::packet::Packet; +use crate::udp::{UdpHeader, UdpPacket, UDP_HEADER_LEN}; use bytes::Bytes; /// Builder for constructing UDP packets @@ -87,10 +87,9 @@ mod tests { let pkt = UdpPacketBuilder::new() .source(1) .destination(2) - .payload(Bytes::from_static(&[1,2,3])) + .payload(Bytes::from_static(&[1, 2, 3])) .build(); assert_eq!(pkt.header.length, (UDP_HEADER_LEN + 3) as u16); - assert_eq!(pkt.payload, Bytes::from_static(&[1,2,3])); + assert_eq!(pkt.payload, Bytes::from_static(&[1, 2, 3])); } } - diff --git a/nex-packet/src/dhcp.rs b/nex-packet/src/dhcp.rs index d9f38e2..35b93cd 100644 --- a/nex-packet/src/dhcp.rs +++ b/nex-packet/src/dhcp.rs @@ -439,7 +439,10 @@ mod tests { assert_eq!(packet.header.htype, DhcpHardwareType::Ethernet); assert_eq!(packet.header.hlen, 6); assert_eq!(packet.header.xid, 0x12345678); - assert_eq!(packet.header.chaddr, MacAddr::new(0x00, 0x11, 0x22, 0x33, 0x44, 0x55)); + assert_eq!( + packet.header.chaddr, + MacAddr::new(0x00, 0x11, 0x22, 0x33, 0x44, 0x55) + ); let rebuilt = packet.to_bytes(); assert_eq!(rebuilt, raw); diff --git a/nex-packet/src/dns.rs b/nex-packet/src/dns.rs index c827010..d52e604 100644 --- a/nex-packet/src/dns.rs +++ b/nex-packet/src/dns.rs @@ -1,8 +1,11 @@ -use core::str; -use std::{net::{IpAddr, Ipv4Addr, Ipv6Addr}, str::Utf8Error}; +use crate::packet::Packet; use bytes::{BufMut, Bytes, BytesMut}; +use core::str; use nex_core::bitfield::{u1, u16be, u32be}; -use crate::packet::Packet; +use std::{ + net::{IpAddr, Ipv4Addr, Ipv6Addr}, + str::Utf8Error, +}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -14,10 +17,10 @@ use serde::{Deserialize, Serialize}; #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum DnsClass { - IN = 1, // Internet - CS = 2, // CSNET (Obsolete) - CH = 3, // Chaos - HS = 4, // Hesiod + IN = 1, // Internet + CS = 2, // CSNET (Obsolete) + CH = 3, // Chaos + HS = 4, // Hesiod Unknown(u16), } @@ -343,97 +346,97 @@ impl DnsType { pub fn name(&self) -> &'static str { match self { - DnsType::A => "A", // 1 - DnsType::NS => "NS", // 2 - DnsType::MD => "MD", // 3 - DnsType::MF => "MF", // 4 - DnsType::CNAME => "CNAME", // 5 - DnsType::SOA => "SOA", // 6 - DnsType::MB => "MB", // 7 - DnsType::MG => "MG", // 8 - DnsType::MR => "MR", // 9 - DnsType::NULL => "NULL", // 10 - DnsType::WKS => "WKS", // 11 - DnsType::PTR => "PTR", // 12 - DnsType::HINFO => "HINFO", // 13 - DnsType::MINFO => "MINFO", // 14 - DnsType::MX => "MX", // 15 - DnsType::TXT => "TXT", // 16 - DnsType::RP => "RP", // 17 - DnsType::AFSDB => "AFSDB", // 18 - DnsType::X25 => "X25", // 19 - DnsType::ISDN => "ISDN", // 20 - DnsType::RT => "RT", // 21 - DnsType::NSAP => "NSAP", // 22 - DnsType::NSAP_PTR => "NSAP_PTR", // 23 - DnsType::SIG => "SIG", // 24 - DnsType::KEY => "KEY", // 25 - DnsType::PX => "PX", // 26 - DnsType::GPOS => "GPOS", // 27 - DnsType::AAAA => "AAAA", // 28 - DnsType::LOC => "LOC", // 29 - DnsType::NXT => "NXT", // 30 - DnsType::EID => "EID", // 31 - DnsType::NIMLOC => "NIMLOC", // 32 - DnsType::SRV => "SRV", // 33 - DnsType::ATMA => "ATMA", // 34 - DnsType::NAPTR => "NAPTR", // 35 - DnsType::KX => "KX", // 36 - DnsType::CERT => "CERT", // 37 - DnsType::A6 => "A6", // 38 - DnsType::DNAME => "DNAME", // 39 - DnsType::SINK => "SINK", // 40 - DnsType::OPT => "OPT", // 41 - DnsType::APL => "APL", // 42 - DnsType::DS => "DS", // 43 - DnsType::SSHFP => "SSHFP", // 44 - DnsType::IPSECKEY => "IPSECKEY", // 45 - DnsType::RRSIG => "RRSIG", // 46 - DnsType::NSEC => "NSEC", // 47 - DnsType::DNSKEY => "DNSKEY", // 48 - DnsType::DHCID => "DHCID", // 49 - DnsType::NSEC3 => "NSEC3", // 50 - DnsType::NSEC3PARAM => "NSEC3PARAM", // 51 - DnsType::TLSA => "TLSA", // 52 - DnsType::SMIMEA => "SMIMEA", // 53 - DnsType::HIP => "HIP", // 55 - DnsType::NINFO => "NINFO", // 56 - DnsType::RKEY => "RKEY", // 57 - DnsType::TALINK => "TALINK", // 58 - DnsType::CDS => "CDS", // 59 - DnsType::CDNSKEY => "CDNSKEY", // 60 - DnsType::OPENPGPKEY => "OPENPGPKEY", // 61 - DnsType::CSYNC => "CSYNC", // 62 - DnsType::ZONEMD => "ZONEMD", // 63 - DnsType::SVCB => "SVCB", // 64 - DnsType::HTTPS => "HTTPS", // 65 - DnsType::SPF => "SPF", // 99 - DnsType::UINFO => "UINFO", // 100 - DnsType::UID => "UID", // 101 - DnsType::GID => "GID", // 102 - DnsType::UNSPEC => "UNSPEC", // 103 - DnsType::NID => "NID", // 104 - DnsType::L32 => "L32", // 105 - DnsType::L64 => "L64", // 106 - DnsType::LP => "LP", // 107 - DnsType::EUI48 => "EUI48", // 108 - DnsType::EUI64 => "EUI64", // 109 - DnsType::TKEY => "TKEY", // 249 - DnsType::TSIG => "TSIG", // 250 - DnsType::IXFR => "IXFR", // 251 - DnsType::AXFR => "AXFR", // 252 - DnsType::MAILB => "MAILB", // 253 - DnsType::MAILA => "MAILA", // 254 - DnsType::ANY => "ANY", // 255 - DnsType::URI => "URI", // 256 - DnsType::CAA => "CAA", // 257 - DnsType::AVC => "AVC", // 258 - DnsType::DOA => "DOA", // 259 - DnsType::AMTRELAY => "AMTRELAY", // 260 - DnsType::TA => "TA", // 32768 - DnsType::DLV => "DLV", // 32769 - _ => "unknown", - } + DnsType::A => "A", // 1 + DnsType::NS => "NS", // 2 + DnsType::MD => "MD", // 3 + DnsType::MF => "MF", // 4 + DnsType::CNAME => "CNAME", // 5 + DnsType::SOA => "SOA", // 6 + DnsType::MB => "MB", // 7 + DnsType::MG => "MG", // 8 + DnsType::MR => "MR", // 9 + DnsType::NULL => "NULL", // 10 + DnsType::WKS => "WKS", // 11 + DnsType::PTR => "PTR", // 12 + DnsType::HINFO => "HINFO", // 13 + DnsType::MINFO => "MINFO", // 14 + DnsType::MX => "MX", // 15 + DnsType::TXT => "TXT", // 16 + DnsType::RP => "RP", // 17 + DnsType::AFSDB => "AFSDB", // 18 + DnsType::X25 => "X25", // 19 + DnsType::ISDN => "ISDN", // 20 + DnsType::RT => "RT", // 21 + DnsType::NSAP => "NSAP", // 22 + DnsType::NSAP_PTR => "NSAP_PTR", // 23 + DnsType::SIG => "SIG", // 24 + DnsType::KEY => "KEY", // 25 + DnsType::PX => "PX", // 26 + DnsType::GPOS => "GPOS", // 27 + DnsType::AAAA => "AAAA", // 28 + DnsType::LOC => "LOC", // 29 + DnsType::NXT => "NXT", // 30 + DnsType::EID => "EID", // 31 + DnsType::NIMLOC => "NIMLOC", // 32 + DnsType::SRV => "SRV", // 33 + DnsType::ATMA => "ATMA", // 34 + DnsType::NAPTR => "NAPTR", // 35 + DnsType::KX => "KX", // 36 + DnsType::CERT => "CERT", // 37 + DnsType::A6 => "A6", // 38 + DnsType::DNAME => "DNAME", // 39 + DnsType::SINK => "SINK", // 40 + DnsType::OPT => "OPT", // 41 + DnsType::APL => "APL", // 42 + DnsType::DS => "DS", // 43 + DnsType::SSHFP => "SSHFP", // 44 + DnsType::IPSECKEY => "IPSECKEY", // 45 + DnsType::RRSIG => "RRSIG", // 46 + DnsType::NSEC => "NSEC", // 47 + DnsType::DNSKEY => "DNSKEY", // 48 + DnsType::DHCID => "DHCID", // 49 + DnsType::NSEC3 => "NSEC3", // 50 + DnsType::NSEC3PARAM => "NSEC3PARAM", // 51 + DnsType::TLSA => "TLSA", // 52 + DnsType::SMIMEA => "SMIMEA", // 53 + DnsType::HIP => "HIP", // 55 + DnsType::NINFO => "NINFO", // 56 + DnsType::RKEY => "RKEY", // 57 + DnsType::TALINK => "TALINK", // 58 + DnsType::CDS => "CDS", // 59 + DnsType::CDNSKEY => "CDNSKEY", // 60 + DnsType::OPENPGPKEY => "OPENPGPKEY", // 61 + DnsType::CSYNC => "CSYNC", // 62 + DnsType::ZONEMD => "ZONEMD", // 63 + DnsType::SVCB => "SVCB", // 64 + DnsType::HTTPS => "HTTPS", // 65 + DnsType::SPF => "SPF", // 99 + DnsType::UINFO => "UINFO", // 100 + DnsType::UID => "UID", // 101 + DnsType::GID => "GID", // 102 + DnsType::UNSPEC => "UNSPEC", // 103 + DnsType::NID => "NID", // 104 + DnsType::L32 => "L32", // 105 + DnsType::L64 => "L64", // 106 + DnsType::LP => "LP", // 107 + DnsType::EUI48 => "EUI48", // 108 + DnsType::EUI64 => "EUI64", // 109 + DnsType::TKEY => "TKEY", // 249 + DnsType::TSIG => "TSIG", // 250 + DnsType::IXFR => "IXFR", // 251 + DnsType::AXFR => "AXFR", // 252 + DnsType::MAILB => "MAILB", // 253 + DnsType::MAILA => "MAILA", // 254 + DnsType::ANY => "ANY", // 255 + DnsType::URI => "URI", // 256 + DnsType::CAA => "CAA", // 257 + DnsType::AVC => "AVC", // 258 + DnsType::DOA => "DOA", // 259 + DnsType::AMTRELAY => "AMTRELAY", // 260 + DnsType::TA => "TA", // 32768 + DnsType::DLV => "DLV", // 32769 + _ => "unknown", + } } } @@ -568,32 +571,32 @@ impl RetCode { Self::BadAlg => 17, Self::BadTrunc => 18, Self::BadCookie => 19, - Self::Unassigned(v) => *v + Self::Unassigned(v) => *v, } } pub fn name(&self) -> &'static str { match self { - RetCode::NoError => "No Error", - RetCode::FormErr => "Format Error", - RetCode::ServFail => "Server Failure", - RetCode::NXDomain => "Non-Existent Domain", - RetCode::NotImp => "Not Implemented", - RetCode::Refused => "Query Refused", - RetCode::YXDomain => "Name Exists When It Shouldn't", - RetCode::YXRRSet => "RR Set Exists When It Shouldn't", - RetCode::NXRRSet => "RR Set Doesn't Exist When It Should", - RetCode::NotAuth => "Not Authorized", - RetCode::NotZone => "Name Not Zone", - RetCode::Dsotypeni => "DSO Type NI", - RetCode::BadVers => "Bad Version", - RetCode::BadKey => "Bad Key", - RetCode::BadTime => "Bad Time", - RetCode::BadMode => "Bad Mode", - RetCode::BadName => "Bad Name", - RetCode::BadAlg => "Bad Algorithm", - RetCode::BadTrunc => "Bad Truncation", - RetCode::BadCookie => "Bad Cookie", + RetCode::NoError => "No Error", + RetCode::FormErr => "Format Error", + RetCode::ServFail => "Server Failure", + RetCode::NXDomain => "Non-Existent Domain", + RetCode::NotImp => "Not Implemented", + RetCode::Refused => "Query Refused", + RetCode::YXDomain => "Name Exists When It Shouldn't", + RetCode::YXRRSet => "RR Set Exists When It Shouldn't", + RetCode::NXRRSet => "RR Set Doesn't Exist When It Should", + RetCode::NotAuth => "Not Authorized", + RetCode::NotZone => "Name Not Zone", + RetCode::Dsotypeni => "DSO Type NI", + RetCode::BadVers => "Bad Version", + RetCode::BadKey => "Bad Key", + RetCode::BadTime => "Bad Time", + RetCode::BadMode => "Bad Mode", + RetCode::BadName => "Bad Name", + RetCode::BadAlg => "Bad Algorithm", + RetCode::BadTrunc => "Bad Truncation", + RetCode::BadCookie => "Bad Cookie", RetCode::Unassigned(_) => "Unassigned", } } @@ -911,7 +914,12 @@ impl DnsResponsePacket { /// Returns the IPv4 address if the record type is A and data length is 4 bytes. pub fn get_ipv4(&self) -> Option { if self.rtype == DnsType::A && self.data.len() == 4 { - Some(Ipv4Addr::new(self.data[0], self.data[1], self.data[2], self.data[3])) + Some(Ipv4Addr::new( + self.data[0], + self.data[1], + self.data[2], + self.data[3], + )) } else { None } @@ -937,9 +945,7 @@ impl DnsResponsePacket { /// Returns the DNS name if the record type is CNAME, NS, or PTR. pub fn get_name(&self) -> Option { match self.rtype { - DnsType::CNAME | DnsType::NS | DnsType::PTR => { - DnsName::from_bytes(&self.data).ok() - } + DnsType::CNAME | DnsType::NS | DnsType::PTR => DnsName::from_bytes(&self.data).ok(), _ => None, } } @@ -1042,7 +1048,9 @@ impl Packet for DnsPacket { // Parse each section, passing mutable slices fn parse_queries(count: usize, buf: &mut &[u8]) -> Option> { - (0..count).map(|_| DnsQueryPacket::from_buf_mut(buf)).collect() + (0..count) + .map(|_| DnsQueryPacket::from_buf_mut(buf)) + .collect() } fn parse_responses(count: usize, buf: &mut &[u8]) -> Option> { @@ -1192,7 +1200,6 @@ impl DnsName { pub fn labels(&self) -> Vec<&str> { self.0.split('.').collect() } - } impl std::fmt::Display for DnsName { @@ -1208,19 +1215,15 @@ mod tests { #[test] fn test_dns_query() { let bytes = Bytes::from_static(&[ - 0x07, b'b', b'e', b'a', b'c', b'o', b'n', b's', - 0x04, b'g', b'v', b't', b'2', - 0x03, b'c', b'o', b'm', - 0x00, 0x00, 0x41, 0x00, 0x01, // type: HTTPS, class: IN + 0x07, b'b', b'e', b'a', b'c', b'o', b'n', b's', 0x04, b'g', b'v', b't', b'2', 0x03, + b'c', b'o', b'm', 0x00, 0x00, 0x41, 0x00, 0x01, // type: HTTPS, class: IN ]); let packet = DnsQueryPacket::from_bytes(bytes).unwrap(); assert_eq!( packet.qname, vec![ - 0x07, b'b', b'e', b'a', b'c', b'o', b'n', b's', - 0x04, b'g', b'v', b't', b'2', - 0x03, b'c', b'o', b'm', - 0x00 + 0x07, b'b', b'e', b'a', b'c', b'o', b'n', b's', 0x04, b'g', b'v', b't', b'2', 0x03, + b'c', b'o', b'm', 0x00 ] ); assert_eq!(packet.qtype, DnsType::HTTPS); @@ -1248,14 +1251,10 @@ mod tests { #[test] fn test_dns_query_packet() { let bytes = Bytes::from_static(&[ - 0x9b, 0xa0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, b'_', b'l', b'd', b'a', b'p', - 0x04, b'_', b't', b'c', b'p', - 0x02, b'd', b'c', - 0x06, b'_', b'm', b's', b'd', b'c', b's', - 0x05, b'S', b'4', b'D', b'O', b'M', - 0x07, b'P', b'R', b'I', b'V', b'A', b'T', b'E', - 0x00, 0x00, 0x21, 0x00, 0x01, + 0x9b, 0xa0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, b'_', + b'l', b'd', b'a', b'p', 0x04, b'_', b't', b'c', b'p', 0x02, b'd', b'c', 0x06, b'_', + b'm', b's', b'd', b'c', b's', 0x05, b'S', b'4', b'D', b'O', b'M', 0x07, b'P', b'R', + b'I', b'V', b'A', b'T', b'E', 0x00, 0x00, 0x21, 0x00, 0x01, ]); let packet = DnsPacket::from_bytes(bytes).unwrap(); assert_eq!(packet.header.id, 0x9ba0); @@ -1272,14 +1271,10 @@ mod tests { #[test] fn test_dns_response_packet() { let bytes = Bytes::from_static(&[ - 0xbc, 0x12, 0x85, 0x80, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x05, b's', b'4', b'd', b'c', b'1', - 0x05, b's', b'a', b'm', b'b', b'a', - 0x08, b'w', b'i', b'n', b'd', b'o', b'w', b's', b'8', - 0x07, b'p', b'r', b'i', b'v', b'a', b't', b'e', - 0x00, 0x00, 0x01, 0x00, 0x01, - 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x00, 0x03, 0x84, + 0xbc, 0x12, 0x85, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, b's', + b'4', b'd', b'c', b'1', 0x05, b's', b'a', b'm', b'b', b'a', 0x08, b'w', b'i', b'n', + b'd', b'o', b'w', b's', b'8', 0x07, b'p', b'r', b'i', b'v', b'a', b't', b'e', 0x00, + 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x03, 0x84, 0x00, 0x04, 0xc0, 0xa8, 0x7a, 0xbd, ]); let packet = DnsPacket::from_bytes(bytes).unwrap(); @@ -1299,4 +1294,4 @@ mod tests { assert_eq!(packet.responses[0].data_len, 4); assert_eq!(packet.responses[0].data, vec![192, 168, 122, 189]); } -} \ No newline at end of file +} diff --git a/nex-packet/src/ethernet.rs b/nex-packet/src/ethernet.rs index a4fde73..58f15e3 100644 --- a/nex-packet/src/ethernet.rs +++ b/nex-packet/src/ethernet.rs @@ -1,7 +1,7 @@ //! An ethernet packet abstraction. -use core::fmt; use bytes::Bytes; +use core::fmt; use nex_core::mac::MacAddr; #[cfg(feature = "serde")] @@ -198,7 +198,8 @@ impl Packet for EthernetPacket { return None; } let destination = MacAddr::from_octets(bytes[0..MAC_ADDR_LEN].try_into().unwrap()); - let source = MacAddr::from_octets(bytes[MAC_ADDR_LEN..2 * MAC_ADDR_LEN].try_into().unwrap()); + let source = + MacAddr::from_octets(bytes[MAC_ADDR_LEN..2 * MAC_ADDR_LEN].try_into().unwrap()); let ethertype = EtherType::new(u16::from_be_bytes([bytes[12], bytes[13]])); let payload = Bytes::copy_from_slice(&bytes[ETHERNET_HEADER_LEN..]); @@ -294,12 +295,18 @@ mod tests { let raw = [ 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, // dst 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, // src - 0x08, 0x00, // EtherType: IPv4 - 0xde, 0xad, 0xbe, 0xef // Payload (dummy) + 0x08, 0x00, // EtherType: IPv4 + 0xde, 0xad, 0xbe, 0xef, // Payload (dummy) ]; let packet = EthernetPacket::from_bytes(Bytes::copy_from_slice(&raw)).unwrap(); - assert_eq!(packet.get_destination(), MacAddr::from_octets([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff])); - assert_eq!(packet.get_source(), MacAddr::from_octets([0x11, 0x22, 0x33, 0x44, 0x55, 0x66])); + assert_eq!( + packet.get_destination(), + MacAddr::from_octets([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]) + ); + assert_eq!( + packet.get_source(), + MacAddr::from_octets([0x11, 0x22, 0x33, 0x44, 0x55, 0x66]) + ); assert_eq!(packet.get_ethertype(), EtherType::Ipv4); assert_eq!(packet.payload.len(), 4); } @@ -344,10 +351,9 @@ mod tests { #[test] fn test_ethernet_unknown_ethertype() { let raw = [ - 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, - 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, - 0xde, 0xad, // Unknown EtherType - 0x00, 0x11, 0x22, 0x33 + 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xde, + 0xad, // Unknown EtherType + 0x00, 0x11, 0x22, 0x33, ]; let packet = EthernetPacket::from_bytes(Bytes::copy_from_slice(&raw)).unwrap(); match packet.get_ethertype() { diff --git a/nex-packet/src/flowcontrol.rs b/nex-packet/src/flowcontrol.rs index f8afecc..cb99868 100644 --- a/nex-packet/src/flowcontrol.rs +++ b/nex-packet/src/flowcontrol.rs @@ -7,7 +7,7 @@ use nex_core::bitfield::u16be; use crate::packet::Packet; /// Represents the opcode field in an Ethernet Flow Control packet. -/// +/// /// Flow control opcodes are defined in IEEE 802.3x #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(u16)] @@ -34,15 +34,19 @@ impl FlowControlOpcode { impl fmt::Display for FlowControlOpcode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", match self { - FlowControlOpcode::Pause => "pause", - FlowControlOpcode::Unknown(_) => "unknown", - }) + write!( + f, + "{}", + match self { + FlowControlOpcode::Pause => "pause", + FlowControlOpcode::Unknown(_) => "unknown", + } + ) } } /// Represents an Ethernet Flow Control packet defined by IEEE 802.3x. -/// +/// /// [EtherTypes::FlowControl](crate::ethernet::EtherTypes::FlowControl) ethertype (0x8808). pub struct FlowControlPacket { pub command: FlowControlOpcode, @@ -120,8 +124,8 @@ mod tests { #[test] fn flowcontrol_pause_test() { let packet = Bytes::from_static(&[ - 0x00, 0x01, // Opcode: Pause - 0x12, 0x34, // Quanta: 0x1234 + 0x00, 0x01, // Opcode: Pause + 0x12, 0x34, // Quanta: 0x1234 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, // Padding ... ]); diff --git a/nex-packet/src/frame.rs b/nex-packet/src/frame.rs index 334635e..412d357 100644 --- a/nex-packet/src/frame.rs +++ b/nex-packet/src/frame.rs @@ -1,7 +1,18 @@ use bytes::Bytes; use nex_core::mac::MacAddr; -use crate::{arp::{ArpHeader, ArpPacket}, ethernet::{EtherType, EthernetHeader, EthernetPacket}, icmp::{IcmpHeader, IcmpPacket}, icmpv6::{Icmpv6Header, Icmpv6Packet}, ip::IpNextProtocol, ipv4::{Ipv4Header, Ipv4Packet}, ipv6::{Ipv6Header, Ipv6Packet}, packet::Packet, tcp::{TcpHeader, TcpPacket}, udp::{UdpHeader, UdpPacket}}; +use crate::{ + arp::{ArpHeader, ArpPacket}, + ethernet::{EtherType, EthernetHeader, EthernetPacket}, + icmp::{IcmpHeader, IcmpPacket}, + icmpv6::{Icmpv6Header, Icmpv6Packet}, + ip::IpNextProtocol, + ipv4::{Ipv4Header, Ipv4Packet}, + ipv6::{Ipv6Header, Ipv6Packet}, + packet::Packet, + tcp::{TcpHeader, TcpPacket}, + udp::{UdpHeader, UdpPacket}, +}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -38,7 +49,10 @@ pub struct ParseOption { impl Default for ParseOption { fn default() -> Self { - Self { from_ip_packet: false, offset: 0 } + Self { + from_ip_packet: false, + offset: 0, + } } } diff --git a/nex-packet/src/gre.rs b/nex-packet/src/gre.rs index 136cfae..356a39e 100644 --- a/nex-packet/src/gre.rs +++ b/nex-packet/src/gre.rs @@ -1,8 +1,8 @@ //! GRE Packet abstraction. +use crate::packet::Packet; use bytes::{Buf, Bytes}; use nex_core::bitfield::{u1, u16be, u3, u32be, u5}; -use crate::packet::Packet; /// GRE (Generic Routing Encapsulation) Packet. /// diff --git a/nex-packet/src/icmp.rs b/nex-packet/src/icmp.rs index 84ab883..8f178da 100644 --- a/nex-packet/src/icmp.rs +++ b/nex-packet/src/icmp.rs @@ -1,6 +1,6 @@ //! An ICMP packet abstraction. -use crate::{ethernet::ETHERNET_HEADER_LEN, packet::Packet}; use crate::ipv4::IPV4_HEADER_LEN; +use crate::{ethernet::ETHERNET_HEADER_LEN, packet::Packet}; use bytes::{BufMut, Bytes, BytesMut}; use nex_core::bitfield::u16be; @@ -234,7 +234,6 @@ impl Packet for IcmpPacket { fn into_parts(self) -> (Self::Header, Bytes) { (self.header, self.payload) } - } impl IcmpPacket { @@ -322,7 +321,6 @@ pub mod echo_request { }) } } - } pub mod echo_reply { @@ -396,7 +394,6 @@ pub mod echo_reply { }) } } - } pub mod destination_unreachable { @@ -471,7 +468,6 @@ pub mod destination_unreachable { }) } } - } pub mod time_exceeded { @@ -531,8 +527,8 @@ mod tests { fn test_echo_request_from_bytes() { let raw_bytes = Bytes::from_static(&[ 8, 0, 0x3a, 0xbc, // Type = 8 (Echo Request), Code = 0, Checksum = 0x3abc - 0x04, 0xd2, // Identifier = 0x04d2 (1234) - 0x00, 0x2a, // Sequence = 0x002a (42) + 0x04, 0xd2, // Identifier = 0x04d2 (1234) + 0x00, 0x2a, // Sequence = 0x002a (42) b'p', b'i', b'n', b'g', ]); @@ -564,7 +560,11 @@ mod tests { buf.put_u16(sequence); buf.extend_from_slice(&payload); - let pkt = IcmpPacket { header, payload: buf.freeze() }.with_computed_checksum(); + let pkt = IcmpPacket { + header, + payload: buf.freeze(), + } + .with_computed_checksum(); let bytes = pkt.to_bytes(); let parsed = IcmpPacket::from_bytes(bytes.clone()).expect("Failed to parse ICMP"); @@ -592,9 +592,14 @@ mod tests { buf.put_u16(mtu); buf.extend_from_slice(&payload); - let pkt = IcmpPacket { header, payload: buf.freeze() }.with_computed_checksum(); + let pkt = IcmpPacket { + header, + payload: buf.freeze(), + } + .with_computed_checksum(); let parsed = IcmpPacket::from_bytes(pkt.to_bytes()).unwrap(); - let unreachable = destination_unreachable::DestinationUnreachablePacket::try_from(parsed).unwrap(); + let unreachable = + destination_unreachable::DestinationUnreachablePacket::try_from(parsed).unwrap(); assert_eq!(unreachable.next_hop_mtu, mtu); assert_eq!(unreachable.payload, payload); @@ -615,7 +620,11 @@ mod tests { buf.put_u32(unused); buf.extend_from_slice(&payload); - let pkt = IcmpPacket { header, payload: buf.freeze() }.with_computed_checksum(); + let pkt = IcmpPacket { + header, + payload: buf.freeze(), + } + .with_computed_checksum(); let parsed = IcmpPacket::from_bytes(pkt.to_bytes()).unwrap(); let exceeded = time_exceeded::TimeExceededPacket::try_from(parsed).unwrap(); diff --git a/nex-packet/src/icmpv6.rs b/nex-packet/src/icmpv6.rs index 1fad281..6f3c0e9 100644 --- a/nex-packet/src/icmpv6.rs +++ b/nex-packet/src/icmpv6.rs @@ -1,7 +1,7 @@ //! An ICMPv6 packet abstraction. -use crate::{ethernet::ETHERNET_HEADER_LEN, packet::Packet}; use crate::ipv6::IPV6_HEADER_LEN; +use crate::{ethernet::ETHERNET_HEADER_LEN, packet::Packet}; use std::net::Ipv6Addr; use bytes::Bytes; @@ -127,15 +127,23 @@ impl Icmpv6Type { Icmpv6Type::RouterRenumbering => "Router Renumbering", Icmpv6Type::NodeInformationQuery => "Node Information Query", Icmpv6Type::NodeInformationResponse => "Node Information Response", - Icmpv6Type::InverseNeighborDiscoverySolicitation => "Inverse Neighbor Discovery Solicitation", - Icmpv6Type::InverseNeighborDiscoveryAdvertisement => "Inverse Neighbor Discovery Advertisement", + Icmpv6Type::InverseNeighborDiscoverySolicitation => { + "Inverse Neighbor Discovery Solicitation" + } + Icmpv6Type::InverseNeighborDiscoveryAdvertisement => { + "Inverse Neighbor Discovery Advertisement" + } Icmpv6Type::Version2MulticastListenerReport => "Version 2 Multicast Listener Report", Icmpv6Type::HomeAgentAddressDiscoveryRequest => "Home Agent Address Discovery Request", Icmpv6Type::HomeAgentAddressDiscoveryReply => "Home Agent Address Discovery Reply", Icmpv6Type::MobilePrefixSolicitation => "Mobile Prefix Solicitation", Icmpv6Type::MobilePrefixAdvertisement => "Mobile Prefix Advertisement", - Icmpv6Type::CertificationPathSolicitationMessage => "Certification Path Solicitation Message", - Icmpv6Type::CertificationPathAdvertisementMessage => "Certification Path Advertisement Message", + Icmpv6Type::CertificationPathSolicitationMessage => { + "Certification Path Solicitation Message" + } + Icmpv6Type::CertificationPathAdvertisementMessage => { + "Certification Path Advertisement Message" + } Icmpv6Type::ExperimentalMobilityProtocols => "Experimental Mobility Protocols", Icmpv6Type::MulticastRouterAdvertisement => "Multicast Router Advertisement", Icmpv6Type::MulticastRouterSolicitation => "Multicast Router Solicitation", @@ -551,7 +559,6 @@ pub mod ndp { } /// Calculate a length of a `NdpOption`'s payload. - /// Router Solicitation Message [RFC 4861 ยง 4.1] /// @@ -583,13 +590,27 @@ pub mod ndp { if value.payload.len() < 8 { return Err("Payload too short for Router Solicitation"); } - let reserved = u32::from_be_bytes([value.payload[0], value.payload[1], value.payload[2], value.payload[3]]); - let options = value.payload.slice(4..).chunks(8).map(|chunk| { - let option_type = NdpOptionType::new(chunk[0]); - let length = chunk[1]; - let payload = Bytes::from(chunk[2..].to_vec()); - NdpOptionPacket { option_type, length, payload } - }).collect(); + let reserved = u32::from_be_bytes([ + value.payload[0], + value.payload[1], + value.payload[2], + value.payload[3], + ]); + let options = value + .payload + .slice(4..) + .chunks(8) + .map(|chunk| { + let option_type = NdpOptionType::new(chunk[0]); + let length = chunk[1]; + let payload = Bytes::from(chunk[2..].to_vec()); + NdpOptionPacket { + option_type, + length, + payload, + } + }) + .collect(); Ok(RouterSolicitPacket { header: value.header, reserved, @@ -752,14 +773,33 @@ pub mod ndp { let hop_limit = value.payload[0]; let flags = value.payload[1]; let lifetime = u16::from_be_bytes([value.payload[2], value.payload[3]]); - let reachable_time = u32::from_be_bytes([value.payload[4], value.payload[5], value.payload[6], value.payload[7]]); - let retrans_time = u32::from_be_bytes([value.payload[8], value.payload[9], value.payload[10], value.payload[11]]); - let options = value.payload.slice(12..).chunks(8).map(|chunk| { - let option_type = NdpOptionType::new(chunk[0]); - let length = chunk[1]; - let payload = Bytes::from(chunk[2..].to_vec()); - NdpOptionPacket { option_type, length, payload } - }).collect(); + let reachable_time = u32::from_be_bytes([ + value.payload[4], + value.payload[5], + value.payload[6], + value.payload[7], + ]); + let retrans_time = u32::from_be_bytes([ + value.payload[8], + value.payload[9], + value.payload[10], + value.payload[11], + ]); + let options = value + .payload + .slice(12..) + .chunks(8) + .map(|chunk| { + let option_type = NdpOptionType::new(chunk[0]); + let length = chunk[1]; + let payload = Bytes::from(chunk[2..].to_vec()); + NdpOptionPacket { + option_type, + length, + payload, + } + }) + .collect(); Ok(RouterAdvertPacket { header: value.header, hop_limit, @@ -923,7 +963,12 @@ pub mod ndp { if value.payload.len() < 24 { return Err("Payload too short for Neighbor Solicitation"); } - let reserved = u32::from_be_bytes([value.payload[0], value.payload[1], value.payload[2], value.payload[3]]); + let reserved = u32::from_be_bytes([ + value.payload[0], + value.payload[1], + value.payload[2], + value.payload[3], + ]); let target_addr = Ipv6Addr::new( u16::from_be_bytes([value.payload[4], value.payload[5]]), u16::from_be_bytes([value.payload[6], value.payload[7]]), @@ -934,12 +979,21 @@ pub mod ndp { u16::from_be_bytes([value.payload[16], value.payload[17]]), u16::from_be_bytes([value.payload[18], value.payload[19]]), ); - let options = value.payload.slice(20..).chunks(8).map(|chunk| { - let option_type = NdpOptionType::new(chunk[0]); - let length = chunk[1]; - let payload: Bytes = Bytes::from(chunk[2..].to_vec()); - NdpOptionPacket { option_type, length, payload } - }).collect(); + let options = value + .payload + .slice(20..) + .chunks(8) + .map(|chunk| { + let option_type = NdpOptionType::new(chunk[0]); + let length = chunk[1]; + let payload: Bytes = Bytes::from(chunk[2..].to_vec()); + NdpOptionPacket { + option_type, + length, + payload, + } + }) + .collect(); Ok(NeighborSolicitPacket { header: value.header, reserved, @@ -1122,7 +1176,11 @@ pub mod ndp { return Err("Payload too short for Neighbor Advert"); } let flags = value.payload[0]; - let reserved = bitfield::utils::u24be_from_bytes([value.payload[1], value.payload[2], value.payload[3]]); + let reserved = bitfield::utils::u24be_from_bytes([ + value.payload[1], + value.payload[2], + value.payload[3], + ]); let target_addr = Ipv6Addr::new( u16::from_be_bytes([value.payload[4], value.payload[5]]), u16::from_be_bytes([value.payload[6], value.payload[7]]), @@ -1133,12 +1191,21 @@ pub mod ndp { u16::from_be_bytes([value.payload[16], value.payload[17]]), u16::from_be_bytes([value.payload[18], value.payload[19]]), ); - let options = value.payload.slice(20..).chunks(8).map(|chunk| { - let option_type = NdpOptionType::new(chunk[0]); - let length = chunk[1]; - let payload = Bytes::from(chunk[2..].to_vec()); - NdpOptionPacket { option_type, length, payload } - }).collect(); + let options = value + .payload + .slice(20..) + .chunks(8) + .map(|chunk| { + let option_type = NdpOptionType::new(chunk[0]); + let length = chunk[1]; + let payload = Bytes::from(chunk[2..].to_vec()); + NdpOptionPacket { + option_type, + length, + payload, + } + }) + .collect(); Ok(NeighborAdvertPacket { header: value.header, flags, @@ -1149,7 +1216,7 @@ pub mod ndp { }) } } - + impl Packet for NeighborAdvertPacket { type Header = (); fn from_buf(bytes: &[u8]) -> Option { @@ -1321,7 +1388,12 @@ pub mod ndp { if value.payload.len() < 40 { return Err("Payload too short for Redirect"); } - let reserved = u32be::from_be_bytes([value.payload[0], value.payload[1], value.payload[2], value.payload[3]]); + let reserved = u32be::from_be_bytes([ + value.payload[0], + value.payload[1], + value.payload[2], + value.payload[3], + ]); let target_addr = Ipv6Addr::new( u16::from_be_bytes([value.payload[4], value.payload[5]]), u16::from_be_bytes([value.payload[6], value.payload[7]]), @@ -1342,12 +1414,21 @@ pub mod ndp { u16::from_be_bytes([value.payload[32], value.payload[33]]), u16::from_be_bytes([value.payload[34], value.payload[35]]), ); - let options = value.payload.slice(36..).chunks(8).map(|chunk| { - let option_type = NdpOptionType::new(chunk[0]); - let length = chunk[1]; - let payload = Bytes::from(chunk[2..].to_vec()); - NdpOptionPacket { option_type, length, payload } - }).collect(); + let options = value + .payload + .slice(36..) + .chunks(8) + .map(|chunk| { + let option_type = NdpOptionType::new(chunk[0]); + let length = chunk[1]; + let payload = Bytes::from(chunk[2..].to_vec()); + NdpOptionPacket { + option_type, + length, + payload, + } + }) + .collect(); Ok(RedirectPacket { header: value.header, reserved, @@ -1528,13 +1609,19 @@ pub mod ndp { let option = &pkg.options[0]; assert_eq!(option.option_type, NdpOptionTypes::TargetLLAddr); assert_eq!(option.length, 0x01); - assert_eq!(option.payload.as_ref(), &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + assert_eq!( + option.payload.as_ref(), + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + ); assert_eq!(option.payload.len(), 6); let option = &pkg.options[1]; assert_eq!(option.option_type, NdpOptionTypes::SourceLLAddr); assert_eq!(option.length, 1); - assert_eq!(option.payload.as_ref(), &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + assert_eq!( + option.payload.as_ref(), + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + ); } #[test] @@ -1563,7 +1650,7 @@ pub mod ndp { let expected = Bytes::from_static(&[ 0x85, 0x00, 0x00, 0x00, // Type, Code, Checksum 0x00, 0x00, 0x00, 0x00, // Reserved - 0x01, 0x01, // Option Type, Length + 0x01, 0x01, // Option Type, Length 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Option Data ]); @@ -1598,17 +1685,23 @@ pub mod ndp { let option = &pkg.options[0]; assert_eq!(option.option_type, NdpOptionTypes::SourceLLAddr); assert_eq!(option.length, 1); - assert_eq!(option.payload.as_ref(), &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + assert_eq!( + option.payload.as_ref(), + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + ); let option = &pkg.options[1]; assert_eq!(option.option_type, NdpOptionTypes::MTU); assert_eq!(option.length, 1); - assert_eq!(option.payload.as_ref(), &[0x00, 0x00, 0x57, 0x68, 0x61, 0x74]); + assert_eq!( + option.payload.as_ref(), + &[0x00, 0x00, 0x57, 0x68, 0x61, 0x74] + ); } #[test] fn basic_ra_create() { - use crate::icmpv6::ndp::{NdpOptionPacket, RouterAdvertPacket, RouterAdvertFlags}; + use crate::icmpv6::ndp::{NdpOptionPacket, RouterAdvertFlags, RouterAdvertPacket}; let options = vec![NdpOptionPacket { option_type: NdpOptionTypes::MTU, @@ -1637,7 +1730,7 @@ pub mod ndp { 0xff, 0x80, 0x00, 0x00, // hop limit, flags, lifetime 0x00, 0x00, 0x00, 0x00, // reachable 0x00, 0x00, 0x00, 0x00, // retrans - 0x05, 0x01, // option type + len + 0x05, 0x01, // option type + len 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // option data ]); @@ -1655,10 +1748,7 @@ pub mod ndp { assert_eq!(pkg.header.icmpv6_code, Icmpv6Code(0)); assert_eq!(pkg.header.checksum, 0x00); assert_eq!(pkg.reserved, 0x00); - assert_eq!( - pkg.target_addr, - Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1) - ); + assert_eq!(pkg.target_addr, Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1)); } #[test] @@ -1682,10 +1772,8 @@ pub mod ndp { let expected = Bytes::from_static(&[ 0x87, 0x00, 0x00, 0x00, // header 0x00, 0x00, 0x00, 0x00, // reserved - 0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, // target + 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, // target ]); assert_eq!(bytes, expected); @@ -1703,15 +1791,12 @@ pub mod ndp { assert_eq!(pkg.header.checksum, 0x00); assert_eq!(pkg.reserved, 0x00); assert_eq!(pkg.flags, 0x80); - assert_eq!( - pkg.target_addr, - Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1) - ); + assert_eq!(pkg.target_addr, Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1)); } #[test] fn basic_na_create() { - use crate::icmpv6::ndp::{NeighborAdvertPacket, NeighborAdvertFlags}; + use crate::icmpv6::ndp::{NeighborAdvertFlags, NeighborAdvertPacket}; let packet = NeighborAdvertPacket { header: Icmpv6Header { @@ -1731,10 +1816,8 @@ pub mod ndp { let expected = Bytes::from_static(&[ 0x88, 0x00, 0x00, 0x00, // header 0x80, 0x00, 0x00, 0x00, // flags + reserved - 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, 0x01, ]); assert_eq!(bytes, expected); @@ -1752,10 +1835,7 @@ pub mod ndp { assert_eq!(pkg.header.icmpv6_code, Icmpv6Code(0)); assert_eq!(pkg.header.checksum, 0x00); assert_eq!(pkg.reserved, 0x00); - assert_eq!( - pkg.target_addr, - Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1) - ); + assert_eq!(pkg.target_addr, Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1)); assert_eq!(pkg.dest_addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); } @@ -1781,14 +1861,10 @@ pub mod ndp { let expected = Bytes::from_static(&[ 0x89, 0x00, 0x00, 0x00, // header 0x00, 0x00, 0x00, 0x00, // reserved - 0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, // target - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // dest + 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, // target + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, // dest ]); assert_eq!(bytes, expected); @@ -1811,7 +1887,10 @@ pub mod echo_request { use bytes::Bytes; - use crate::{icmpv6::{Icmpv6Code, Icmpv6Header, Icmpv6Packet, Icmpv6Type}, packet::Packet}; + use crate::{ + icmpv6::{Icmpv6Code, Icmpv6Header, Icmpv6Packet, Icmpv6Type}, + packet::Packet, + }; /// Represents the identifier field. #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -1944,7 +2023,6 @@ pub mod echo_request { ((), self.payload) } } - } pub mod echo_reply { @@ -1959,10 +2037,13 @@ pub mod echo_reply { //! | Data ... //! +-+-+-+-+- //! ``` - + use bytes::Bytes; - use crate::{icmpv6::{Icmpv6Code, Icmpv6Header, Icmpv6Packet, Icmpv6Type}, packet::Packet}; + use crate::{ + icmpv6::{Icmpv6Code, Icmpv6Header, Icmpv6Packet, Icmpv6Type}, + packet::Packet, + }; /// Represents the identifier field. #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Identifier(pub u16); @@ -2079,7 +2160,7 @@ pub mod echo_reply { fn header_len(&self) -> usize { 8 // Header length for echo reply } - + fn payload_len(&self) -> usize { self.payload.len() } @@ -2092,24 +2173,26 @@ pub mod echo_reply { ((), self.payload) } } - } #[cfg(test)] mod echo_tests { use super::*; - use crate::icmpv6::{echo_reply::EchoReplyPacket, echo_request::EchoRequestPacket, Icmpv6Code, Icmpv6Type}; - + use crate::icmpv6::{ + echo_reply::EchoReplyPacket, echo_request::EchoRequestPacket, Icmpv6Code, Icmpv6Type, + }; + #[test] fn test_echo_request_parse() { let raw = Bytes::from_static(&[ 0x80, 0x00, 0xbe, 0xef, // header: type, code, checksum - 0x12, 0x34, // identifier - 0x56, 0x78, // sequence number + 0x12, 0x34, // identifier + 0x56, 0x78, // sequence number b'p', b'i', b'n', b'g', b'!', ]); - let parsed = EchoRequestPacket::from_bytes(raw.clone()).expect("Failed to parse Echo Request packet"); + let parsed = EchoRequestPacket::from_bytes(raw.clone()) + .expect("Failed to parse Echo Request packet"); assert_eq!(parsed.header.icmpv6_type, Icmpv6Type::EchoRequest); assert_eq!(parsed.header.icmpv6_code, Icmpv6Code(0)); @@ -2144,12 +2227,13 @@ mod echo_tests { fn test_echo_reply_parse() { let raw = Bytes::from_static(&[ 0x81, 0x00, 0x12, 0x34, // header: type, code, checksum - 0xab, 0xcd, // identifier - 0x56, 0x78, // sequence number + 0xab, 0xcd, // identifier + 0x56, 0x78, // sequence number b'h', b'e', b'l', b'l', b'o', ]); - let parsed = EchoReplyPacket::from_bytes(raw.clone()).expect("Failed to parse Echo Reply packet"); + let parsed = + EchoReplyPacket::from_bytes(raw.clone()).expect("Failed to parse Echo Reply packet"); assert_eq!(parsed.header.icmpv6_type, Icmpv6Type::EchoReply); assert_eq!(parsed.header.icmpv6_code, Icmpv6Code(0)); diff --git a/nex-packet/src/ip.rs b/nex-packet/src/ip.rs index 6e0389d..b4d37ec 100644 --- a/nex-packet/src/ip.rs +++ b/nex-packet/src/ip.rs @@ -608,4 +608,3 @@ impl IpNextProtocol { *self as u8 } } - diff --git a/nex-packet/src/ipv4.rs b/nex-packet/src/ipv4.rs index 9205174..e1f21b6 100644 --- a/nex-packet/src/ipv4.rs +++ b/nex-packet/src/ipv4.rs @@ -204,7 +204,7 @@ pub struct Ipv4Packet { impl Packet for Ipv4Packet { type Header = Ipv4Header; - + fn from_buf(bytes: &[u8]) -> Option { if bytes.len() < IPV4_HEADER_LEN { return None; @@ -304,7 +304,7 @@ impl Packet for Ipv4Packet { payload, }) } - + fn from_bytes(bytes: Bytes) -> Option { Self::from_buf(&bytes) } @@ -314,15 +314,17 @@ impl Packet for Ipv4Packet { let mut tmp_buf = BytesMut::with_capacity(60); // max header size for option in &self.header.options { let number = option.header.number.value(); - let type_byte = (option.header.copied << 7) - | (option.header.class << 5) - | (number & 0b0001_1111); + let type_byte = + (option.header.copied << 7) | (option.header.class << 5) | (number & 0b0001_1111); tmp_buf.put_u8(type_byte); match option.header.number { Ipv4OptionType::EOL | Ipv4OptionType::NOP => {} _ => { - let len = option.header.length.unwrap_or((option.data.len() + 2) as u8); + let len = option + .header + .length + .unwrap_or((option.data.len() + 2) as u8); tmp_buf.put_u8(len); tmp_buf.extend_from_slice(&option.data); } @@ -428,8 +430,7 @@ mod tests { 0xc0, 0xa8, 0x00, 0x01, // Source: 192.168.0.1 0xc0, 0xa8, 0x00, 0xc7, // Destination: 192.168.0.199 // Payload (8 bytes) - 0xde, 0xad, 0xbe, 0xef, - 0xca, 0xfe, 0xba, 0xbe, + 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe, ]); let packet = Ipv4Packet::from_bytes(raw.clone()).expect("Failed to parse Ipv4Packet"); @@ -438,7 +439,10 @@ mod tests { assert_eq!(packet.header.total_length, 28u16); assert_eq!(packet.header.source, Ipv4Addr::new(192, 168, 0, 1)); assert_eq!(packet.header.destination, Ipv4Addr::new(192, 168, 0, 199)); - assert_eq!(packet.payload, Bytes::from_static(&[0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe])); + assert_eq!( + packet.payload, + Bytes::from_static(&[0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe]) + ); let serialized = packet.to_bytes(); assert_eq!(&serialized[..], &raw[..]); @@ -448,24 +452,23 @@ mod tests { fn test_ipv4_packet_with_options_round_trip() { let raw = Bytes::from_static(&[ // IPv4 header (20bytes + 8bytes option + 4bytes payload = 32bytes -> IHL=7) - 0x47, 0x00, 0x00, 0x20, // [0-3] Version(4), IHL(7=28bytes), DSCP/ECN, Total Length=32 bytes + 0x47, 0x00, 0x00, + 0x20, // [0-3] Version(4), IHL(7=28bytes), DSCP/ECN, Total Length=32 bytes 0x12, 0x34, 0x40, 0x00, // [4-7] Identification, Flags=DF(0x40), Fragment Offset - 0x40, 0x11, 0x00, 0x00, // [8-11] TTL=64, Protocol=17(UDP), Header Checksum (0 for now) + 0x40, 0x11, 0x00, + 0x00, // [8-11] TTL=64, Protocol=17(UDP), Header Checksum (0 for now) 0xc0, 0xa8, 0x00, 0x01, // [12-15] Source IP = 192.168.0.1 0xc0, 0xa8, 0x00, 0x02, // [16-19] Destination IP = 192.168.0.2 - // IPv4 options (8bytes) // Option 1: 1byte NOP - 0x01, // [20] NOP (No Operation) - - // Option 2: 4bytes - 0x87, 0x04, 0x12, 0x34, // [21-24] Option Type=RR(7), Copied=1, Class=0, Length=4, Data=[0x12, 0x34] - + 0x01, // [20] NOP (No Operation) + // Option 2: 4bytes + 0x87, 0x04, 0x12, + 0x34, // [21-24] Option Type=RR(7), Copied=1, Class=0, Length=4, Data=[0x12, 0x34] // Option 3: EOL (End of Options List) with padding - 0x00, // [25] EOL (End of Options List) - 0x00, // [26] Padding - 0x00, // [27] Padding - + 0x00, // [25] EOL (End of Options List) + 0x00, // [26] Padding + 0x00, // [27] Padding // Payload 4bytes 0xde, 0xad, 0xbe, 0xef, // [28-31] Payload: deadbeef ]); @@ -510,7 +513,9 @@ mod tests { }; let mut buf = BytesMut::new(); - let ty = (option.header.copied << 7) | (option.header.class << 5) | (option.header.number.value() & 0x1F); + let ty = (option.header.copied << 7) + | (option.header.class << 5) + | (option.header.number.value() & 0x1F); buf.put_u8(ty); buf.put_u8(3); buf.put_slice(&[0x10]); @@ -542,17 +547,15 @@ mod tests { }; // This should panic because the payload length exceeds the total_length specified in the header - let _ = packet.to_bytes(); + let _ = packet.to_bytes(); } #[test] fn test_ipv4_checksum() { let raw = Bytes::from_static(&[ - 0x45, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x40, 0x00, - 0x40, 0x06, 0x00, 0x00, // checksum: 0 - 0x0a, 0x00, 0x00, 0x01, - 0x0a, 0x00, 0x00, 0x02, + 0x45, 0x00, 0x00, 0x14, 0x00, 0x00, 0x40, 0x00, 0x40, 0x06, 0x00, + 0x00, // checksum: 0 + 0x0a, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x02, ]); let mut packet = Ipv4Packet::from_bytes(raw.clone()).expect("Failed to parse"); @@ -572,5 +575,3 @@ mod tests { assert_eq!(&packet.to_bytes()[..], &raw_copy[..]); } } - - diff --git a/nex-packet/src/ipv6.rs b/nex-packet/src/ipv6.rs index 43fb3bd..ae23372 100644 --- a/nex-packet/src/ipv6.rs +++ b/nex-packet/src/ipv6.rs @@ -1,7 +1,7 @@ -use std::net::Ipv6Addr; -use bytes::{Bytes, BytesMut, BufMut}; -use crate::packet::Packet; use crate::ip::IpNextProtocol; +use crate::packet::Packet; +use bytes::{BufMut, Bytes, BytesMut}; +use std::net::Ipv6Addr; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -11,9 +11,9 @@ pub const IPV6_HEADER_LEN: usize = 40; #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Ipv6Header { - pub version: u8, // 4 bits - pub traffic_class: u8, // 8 bits - pub flow_label: u32, // 20 bits + pub version: u8, // 4 bits + pub traffic_class: u8, // 8 bits + pub flow_label: u32, // 20 bits pub payload_length: u16, pub next_header: IpNextProtocol, pub hop_limit: u8, @@ -30,7 +30,7 @@ pub struct Ipv6Packet { impl Packet for Ipv6Packet { type Header = Ipv6Header; - + fn from_buf(bytes: &[u8]) -> Option { if bytes.len() < IPV6_HEADER_LEN { return None; @@ -39,7 +39,8 @@ impl Packet for Ipv6Packet { // --- Parse the header section --- let version_traffic_flow = &bytes[..4]; let version = version_traffic_flow[0] >> 4; - let traffic_class = ((version_traffic_flow[0] & 0x0F) << 4) | (version_traffic_flow[1] >> 4); + let traffic_class = + ((version_traffic_flow[0] & 0x0F) << 4) | (version_traffic_flow[1] >> 4); let flow_label = u32::from(version_traffic_flow[1] & 0x0F) << 16 | u32::from(version_traffic_flow[2]) << 8 | u32::from(version_traffic_flow[3]); @@ -68,7 +69,9 @@ impl Packet for Ipv6Packet { loop { match next_header { - IpNextProtocol::Hopopt | IpNextProtocol::Ipv6Route | IpNextProtocol::Ipv6Frag + IpNextProtocol::Hopopt + | IpNextProtocol::Ipv6Route + | IpNextProtocol::Ipv6Frag | IpNextProtocol::Ipv6Opts => { if offset + 2 > bytes.len() { return None; @@ -84,13 +87,18 @@ impl Packet for Ipv6Packet { return None; } - let data = Bytes::copy_from_slice(&bytes[offset + 2 .. offset + total_len]); + let data = + Bytes::copy_from_slice(&bytes[offset + 2..offset + total_len]); let ext = match next_header { - IpNextProtocol::Hopopt => Ipv6ExtensionHeader::HopByHop { next: nh, data }, - IpNextProtocol::Ipv6Opts => Ipv6ExtensionHeader::Destination { next: nh, data }, - _ => Ipv6ExtensionHeader::Raw { - next: nh, - raw: Bytes::copy_from_slice(&bytes[offset .. offset + total_len]), + IpNextProtocol::Hopopt => { + Ipv6ExtensionHeader::HopByHop { next: nh, data } + } + IpNextProtocol::Ipv6Opts => { + Ipv6ExtensionHeader::Destination { next: nh, data } + } + _ => Ipv6ExtensionHeader::Raw { + next: nh, + raw: Bytes::copy_from_slice(&bytes[offset..offset + total_len]), }, }; @@ -111,7 +119,8 @@ impl Packet for Ipv6Packet { return None; } - let data = Bytes::copy_from_slice(&bytes[offset + 4 .. offset + total_len]); + let data = + Bytes::copy_from_slice(&bytes[offset + 4..offset + total_len]); extensions.push(Ipv6ExtensionHeader::Routing { next: nh, routing_type, @@ -129,12 +138,15 @@ impl Packet for Ipv6Packet { } //let reserved = bytes[offset + 1]; - let frag_off_flags = u16::from_be_bytes([bytes[offset + 2], bytes[offset + 3]]); + let frag_off_flags = + u16::from_be_bytes([bytes[offset + 2], bytes[offset + 3]]); let offset_val = frag_off_flags >> 3; let more = (frag_off_flags & 0x1) != 0; let id = u32::from_be_bytes([ - bytes[offset + 4], bytes[offset + 5], - bytes[offset + 6], bytes[offset + 7], + bytes[offset + 4], + bytes[offset + 5], + bytes[offset + 6], + bytes[offset + 7], ]); extensions.push(Ipv6ExtensionHeader::Fragment { @@ -172,7 +184,8 @@ impl Packet for Ipv6Packet { // --- 1. Basic header (first 40 bytes) --- let vtf_1 = (self.header.version << 4) | (self.header.traffic_class >> 4); - let vtf_2 = ((self.header.traffic_class & 0x0F) << 4) | ((self.header.flow_label >> 16) as u8); + let vtf_2 = + ((self.header.traffic_class & 0x0F) << 4) | ((self.header.flow_label >> 16) as u8); let vtf_3 = (self.header.flow_label >> 8) as u8; let vtf_4 = self.header.flow_label as u8; @@ -182,7 +195,9 @@ impl Packet for Ipv6Packet { buf.put_u8(vtf_4); buf.put_u16(self.header.payload_length); // First next_header (first extension header if present) - let first_next_header = self.extensions.first() + let first_next_header = self + .extensions + .first() .map(|ext| ext.next_protocol()) .unwrap_or(self.header.next_header); buf.put_u8(first_next_header.value()); @@ -222,7 +237,12 @@ impl Packet for Ipv6Packet { } } - Ipv6ExtensionHeader::Fragment { next, offset, more, id } => { + Ipv6ExtensionHeader::Fragment { + next, + offset, + more, + id, + } => { buf.put_u8(next.value()); buf.put_u8(0); // reserved let offset_flags = (offset << 3) | if *more { 1 } else { 0 }; @@ -290,11 +310,30 @@ pub enum ExtensionHeaderType { #[derive(Debug, Clone, PartialEq, Eq)] pub enum Ipv6ExtensionHeader { - HopByHop { next: IpNextProtocol, data: Bytes }, - Destination { next: IpNextProtocol, data: Bytes }, - Routing { next: IpNextProtocol, routing_type: u8, segments_left: u8, data: Bytes }, - Fragment { next: IpNextProtocol, offset: u16, more: bool, id: u32 }, - Raw { next: IpNextProtocol, raw: Bytes }, + HopByHop { + next: IpNextProtocol, + data: Bytes, + }, + Destination { + next: IpNextProtocol, + data: Bytes, + }, + Routing { + next: IpNextProtocol, + routing_type: u8, + segments_left: u8, + data: Bytes, + }, + Fragment { + next: IpNextProtocol, + offset: u16, + more: bool, + id: u32, + }, + Raw { + next: IpNextProtocol, + raw: Bytes, + }, } impl Ipv6ExtensionHeader { @@ -389,20 +428,14 @@ mod tests { let raw_bytes = Bytes::from_static(&[ // Version(6), Traffic Class(0xa), Flow Label(0x12345) - 0x60, 0xA1, 0x23, 0x45, - // Payload Length: 8 bytes - 0x00, 0x08, - // Next Header: TCP (6) - 0x06, - // Hop Limit - 0x40, - // Source IP - 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x1a, 0x2b, 0xff, 0xfe, 0x1a, 0x2b, 0x3c, - // Destination IP - 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - // Payload (dummy 8 bytes) + 0x60, 0xA1, 0x23, 0x45, // Payload Length: 8 bytes + 0x00, 0x08, // Next Header: TCP (6) + 0x06, // Hop Limit + 0x40, // Source IP + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1a, 0x2b, 0xff, 0xfe, 0x1a, + 0x2b, 0x3c, // Destination IP + 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, // Payload (dummy 8 bytes) b'H', b'e', b'l', b'l', b'o', b'!', b'!', b'\n', ]); diff --git a/nex-packet/src/lib.rs b/nex-packet/src/lib.rs index e89e6c8..85c087c 100644 --- a/nex-packet/src/lib.rs +++ b/nex-packet/src/lib.rs @@ -1,21 +1,21 @@ //! Packet parsing and construction utilities for common network protocols. -pub mod packet; -pub mod ethernet; pub mod arp; +pub mod builder; +pub mod dhcp; +pub mod dns; +pub mod ethernet; +pub mod flowcontrol; +pub mod frame; +pub mod gre; +pub mod icmp; +pub mod icmpv6; pub mod ip; pub mod ipv4; pub mod ipv6; -pub mod util; -pub mod icmp; -pub mod icmpv6; +pub mod packet; pub mod tcp; pub mod udp; +pub mod util; pub mod vlan; -pub mod dhcp; -pub mod dns; -pub mod gre; pub mod vxlan; -pub mod flowcontrol; -pub mod frame; -pub mod builder; diff --git a/nex-packet/src/packet.rs b/nex-packet/src/packet.rs index 93e1059..889313f 100644 --- a/nex-packet/src/packet.rs +++ b/nex-packet/src/packet.rs @@ -46,5 +46,4 @@ pub trait Packet: Sized { } fn into_parts(self) -> (Self::Header, Bytes); - } diff --git a/nex-packet/src/tcp.rs b/nex-packet/src/tcp.rs index 2d692b9..700ef10 100644 --- a/nex-packet/src/tcp.rs +++ b/nex-packet/src/tcp.rs @@ -4,8 +4,8 @@ use crate::ip::IpNextProtocol; use crate::packet::Packet; use crate::util::{self, Octets}; -use std::net::{IpAddr, Ipv4Addr}; use std::net::Ipv6Addr; +use std::net::{IpAddr, Ipv4Addr}; use bytes::{Buf, BufMut, Bytes, BytesMut}; use nex_core::bitfield::{u16be, u32be, u4}; @@ -497,11 +497,19 @@ impl Packet for TcpPacket { let kind = TcpOptionKind::new(options_bytes.get_u8()); match kind { TcpOptionKind::EOL => { - options.push(TcpOptionPacket { kind, length: None, data: Bytes::new() }); + options.push(TcpOptionPacket { + kind, + length: None, + data: Bytes::new(), + }); break; } TcpOptionKind::NOP => { - options.push(TcpOptionPacket { kind, length: None, data: Bytes::new() }); + options.push(TcpOptionPacket { + kind, + length: None, + data: Bytes::new(), + }); } _ => { if options_bytes.remaining() < 1 { @@ -541,9 +549,9 @@ impl Packet for TcpPacket { }) } fn from_bytes(mut bytes: Bytes) -> Option { - Self::from_buf(&mut bytes) + Self::from_buf(&mut bytes) } - + fn to_bytes(&self) -> Bytes { let mut bytes = BytesMut::with_capacity(self.header_len() + self.payload.len()); @@ -552,7 +560,8 @@ impl Packet for TcpPacket { bytes.put_u32(self.header.sequence); bytes.put_u32(self.header.acknowledgement); - let offset_reserved = (self.header.data_offset.to_be() << 4) | (self.header.reserved.to_be() & 0x0F); + let offset_reserved = + (self.header.data_offset.to_be() << 4) | (self.header.reserved.to_be() & 0x0F); bytes.put_u8(offset_reserved); bytes.put_u8(self.header.flags); @@ -775,7 +784,9 @@ mod tests { assert_eq!(parsed, packet); assert_eq!(parsed.to_bytes(), bytes); assert_eq!(parsed.header.options.len(), 3); - assert_eq!(parsed.header.options[2].get_timestamp(), (0x2c57cda5, 0x02a04192)); + assert_eq!( + parsed.header.options[2].get_timestamp(), + (0x2c57cda5, 0x02a04192) + ); } - } diff --git a/nex-packet/src/vlan.rs b/nex-packet/src/vlan.rs index ed16a4b..840ef8d 100644 --- a/nex-packet/src/vlan.rs +++ b/nex-packet/src/vlan.rs @@ -1,5 +1,5 @@ //! A VLAN (802.1Q) packet abstraction. -//! +//! use crate::{ethernet::EtherType, packet::Packet}; use bytes::{Buf, BufMut, Bytes, BytesMut}; use nex_core::bitfield::{u1, u12be}; @@ -15,21 +15,21 @@ pub const VLAN_HEADER_LEN: usize = 4; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum ClassOfService { // Background - BK = 1, + BK = 1, // Best Effort - BE = 0, + BE = 0, // Excellent Effort - EE = 2, + EE = 2, // Critical Applications - CA = 3, + CA = 3, // Video - VI = 4, + VI = 4, // Voice - VO = 5, + VO = 5, // Internetwork Control - IC = 6, + IC = 6, // Network Control - NC = 7, + NC = 7, /// Unknown Class of Service Unknown(u8), } diff --git a/nex-packet/src/vxlan.rs b/nex-packet/src/vxlan.rs index 84cd300..a6a5fb9 100644 --- a/nex-packet/src/vxlan.rs +++ b/nex-packet/src/vxlan.rs @@ -114,7 +114,7 @@ fn vxlan_packet_test() { 0x08, // I flag 0x00, 0x00, 0x00, // Reserved 0x12, 0x34, 0x56, // VNI - 0x00 // Reserved + 0x00, // Reserved ]); let vxlan_packet = Vxlan::from_bytes(packet.clone()).unwrap(); assert_eq!(vxlan_packet.to_bytes(), packet); diff --git a/nex-socket/src/icmp/async_impl.rs b/nex-socket/src/icmp/async_impl.rs index 7d361b1..2c99567 100644 --- a/nex-socket/src/icmp/async_impl.rs +++ b/nex-socket/src/icmp/async_impl.rs @@ -69,7 +69,7 @@ impl AsyncIcmpSocket { #[cfg(unix)] let std_socket = unsafe { use std::os::fd::{FromRawFd, IntoRawFd}; - + StdUdpSocket::from_raw_fd(socket.into_raw_fd()) }; diff --git a/nex-socket/src/icmp/config.rs b/nex-socket/src/icmp/config.rs index 7b083a6..9e7d873 100644 --- a/nex-socket/src/icmp/config.rs +++ b/nex-socket/src/icmp/config.rs @@ -1,5 +1,5 @@ -use std::net::SocketAddr; use socket2::Type as SockType; +use std::net::SocketAddr; /// ICMP protocol version. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -27,7 +27,7 @@ impl IcmpConfig { ttl: None, interface: None, sock_type_hint: SockType::DGRAM, // DGRAM preferred on Linux, RAW fallback on macOS/Windows - fib: None, // FreeBSD only + fib: None, // FreeBSD only } } @@ -76,4 +76,3 @@ mod tests { assert_eq!(cfg.sock_type_hint, Type::RAW); } } - diff --git a/nex-socket/src/icmp/mod.rs b/nex-socket/src/icmp/mod.rs index 043548c..4cc664c 100644 --- a/nex-socket/src/icmp/mod.rs +++ b/nex-socket/src/icmp/mod.rs @@ -1,7 +1,7 @@ -mod config; mod async_impl; +mod config; mod sync_impl; +pub use async_impl::*; pub use config::*; pub use sync_impl::*; -pub use async_impl::*; diff --git a/nex-socket/src/tcp/async_impl.rs b/nex-socket/src/tcp/async_impl.rs index 164d91c..42a073a 100644 --- a/nex-socket/src/tcp/async_impl.rs +++ b/nex-socket/src/tcp/async_impl.rs @@ -1,7 +1,7 @@ use crate::tcp::TcpConfig; use socket2::{Domain, Protocol, Socket, Type as SockType}; use std::io; -use std::net::{SocketAddr, TcpStream as StdTcpStream, TcpListener as StdTcpListener}; +use std::net::{SocketAddr, TcpListener as StdTcpListener, TcpStream as StdTcpStream}; use std::time::Duration; use tokio::net::{TcpListener, TcpStream}; @@ -76,7 +76,10 @@ impl AsyncTcpSocket { let std_stream: StdTcpStream = self.socket.into(); return TcpStream::from_std(std_stream); } - Err(e) if e.kind() == io::ErrorKind::WouldBlock || e.raw_os_error() == Some(libc::EINPROGRESS) => { + Err(e) + if e.kind() == io::ErrorKind::WouldBlock + || e.raw_os_error() == Some(libc::EINPROGRESS) => + { // wait until writable let std_stream: StdTcpStream = self.socket.into(); let stream = TcpStream::from_std(std_stream)?; @@ -97,10 +100,17 @@ impl AsyncTcpSocket { } /// Connect with a timeout to the target address. - pub async fn connect_timeout(self, target: SocketAddr, timeout: Duration) -> io::Result { + pub async fn connect_timeout( + self, + target: SocketAddr, + timeout: Duration, + ) -> io::Result { match tokio::time::timeout(timeout, self.connect(target)).await { Ok(result) => result, - Err(_) => Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out")), + Err(_) => Err(io::Error::new( + io::ErrorKind::TimedOut, + "connection timed out", + )), } } @@ -128,9 +138,9 @@ impl AsyncTcpSocket { }; let (n, addr) = self.socket.recv_from(buf_maybe)?; - let addr = addr.as_socket().ok_or_else(|| { - io::Error::new(io::ErrorKind::InvalidData, "invalid address format") - })?; + let addr = addr + .as_socket() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "invalid address format"))?; Ok((n, addr)) } @@ -160,15 +170,19 @@ impl AsyncTcpSocket { #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "fuchsia")))] { let _ = iface; - Err(io::Error::new(io::ErrorKind::Unsupported, "bind_device not supported on this OS")) + Err(io::Error::new( + io::ErrorKind::Unsupported, + "bind_device not supported on this OS", + )) } } /// Retrieve the local address of the socket. pub fn local_addr(&self) -> io::Result { - self.socket.local_addr()?.as_socket().ok_or_else(|| { - io::Error::new(io::ErrorKind::Other, "Failed to get socket address") - }) + self.socket + .local_addr()? + .as_socket() + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Failed to get socket address")) } /// Convert the internal socket into a Tokio `TcpStream`. diff --git a/nex-socket/src/tcp/mod.rs b/nex-socket/src/tcp/mod.rs index 043548c..4cc664c 100644 --- a/nex-socket/src/tcp/mod.rs +++ b/nex-socket/src/tcp/mod.rs @@ -1,7 +1,7 @@ -mod config; mod async_impl; +mod config; mod sync_impl; +pub use async_impl::*; pub use config::*; pub use sync_impl::*; -pub use async_impl::*; diff --git a/nex-socket/src/tcp/sync_impl.rs b/nex-socket/src/tcp/sync_impl.rs index 308bb82..725c8b1 100644 --- a/nex-socket/src/tcp/sync_impl.rs +++ b/nex-socket/src/tcp/sync_impl.rs @@ -1,6 +1,6 @@ use socket2::{Domain, Protocol, Socket, Type as SockType}; use std::io; -use std::net::{SocketAddr, TcpStream, TcpListener}; +use std::net::{SocketAddr, TcpListener, TcpStream}; use std::time::Duration; use crate::tcp::TcpConfig; @@ -97,7 +97,10 @@ impl TcpSocket { // Try to connect first match self.socket.connect(&target.into()) { Ok(_) => { /* succeeded immediately */ } - Err(err) if err.kind() == io::ErrorKind::WouldBlock || err.raw_os_error() == Some(libc::EINPROGRESS) => { + Err(err) + if err.kind() == io::ErrorKind::WouldBlock + || err.raw_os_error() == Some(libc::EINPROGRESS) => + { // Continue waiting } Err(e) => return Err(e), @@ -107,7 +110,10 @@ impl TcpSocket { let timeout_ms = timeout.as_millis() as i32; use std::os::unix::io::BorrowedFd; // Safety: raw_fd is valid for the lifetime of this scope - let mut fds = [PollFd::new(unsafe { BorrowedFd::borrow_raw(raw_fd) }, PollFlags::POLLOUT)]; + let mut fds = [PollFd::new( + unsafe { BorrowedFd::borrow_raw(raw_fd) }, + PollFlags::POLLOUT, + )]; let n = poll(&mut fds, Some(timeout_ms as u16))?; if n == 0 { @@ -115,7 +121,11 @@ impl TcpSocket { } // Check the result with `SO_ERROR` - let err: i32 = self.socket.take_error()?.map(|e| e.raw_os_error().unwrap_or(0)).unwrap_or(0); + let err: i32 = self + .socket + .take_error()? + .map(|e| e.raw_os_error().unwrap_or(0)) + .unwrap_or(0); if err != 0 { return Err(io::Error::from_raw_os_error(err)); } @@ -134,12 +144,11 @@ impl TcpSocket { #[cfg(windows)] pub fn connect_timeout(&self, target: SocketAddr, timeout: Duration) -> io::Result { + use std::mem::size_of; use std::os::windows::io::AsRawSocket; use windows_sys::Win32::Networking::WinSock::{ - WSAPOLLFD, WSAPoll, POLLWRNORM, SOCKET_ERROR, SO_ERROR, SOL_SOCKET, - getsockopt, SOCKET, + getsockopt, WSAPoll, POLLWRNORM, SOCKET, SOCKET_ERROR, SOL_SOCKET, SO_ERROR, WSAPOLLFD, }; - use std::mem::size_of; let sock = self.socket.as_raw_socket() as SOCKET; self.socket.set_nonblocking(true)?; @@ -222,9 +231,9 @@ impl TcpSocket { }; let (n, addr) = self.socket.recv_from(buf_maybe)?; - let addr = addr.as_socket().ok_or_else(|| { - io::Error::new(io::ErrorKind::InvalidData, "invalid address format") - })?; + let addr = addr + .as_socket() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "invalid address format"))?; Ok((n, addr)) } @@ -254,16 +263,20 @@ impl TcpSocket { #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "fuchsia")))] { let _ = iface; - Err(io::Error::new(io::ErrorKind::Unsupported, "bind_device not supported on this OS")) + Err(io::Error::new( + io::ErrorKind::Unsupported, + "bind_device not supported on this OS", + )) } } // --- information helpers --- pub fn local_addr(&self) -> io::Result { - self.socket.local_addr()?.as_socket().ok_or_else(|| { - io::Error::new(io::ErrorKind::Other, "Failed to retrieve local address") - }) + self.socket + .local_addr()? + .as_socket() + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Failed to retrieve local address")) } #[cfg(unix)] diff --git a/nex-socket/src/udp/mod.rs b/nex-socket/src/udp/mod.rs index 043548c..4cc664c 100644 --- a/nex-socket/src/udp/mod.rs +++ b/nex-socket/src/udp/mod.rs @@ -1,7 +1,7 @@ -mod config; mod async_impl; +mod config; mod sync_impl; +pub use async_impl::*; pub use config::*; pub use sync_impl::*; -pub use async_impl::*; diff --git a/nex-socket/src/udp/sync_impl.rs b/nex-socket/src/udp/sync_impl.rs index 7ddd8ff..aa6ea0a 100644 --- a/nex-socket/src/udp/sync_impl.rs +++ b/nex-socket/src/udp/sync_impl.rs @@ -89,18 +89,19 @@ impl UdpSocket { }; let (n, addr) = self.socket.recv_from(buf_maybe)?; - let addr = addr.as_socket().ok_or_else(|| { - io::Error::new(io::ErrorKind::InvalidData, "invalid address format") - })?; + let addr = addr + .as_socket() + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "invalid address format"))?; Ok((n, addr)) } /// Retrieve the local socket address. pub fn local_addr(&self) -> io::Result { - self.socket.local_addr()?.as_socket().ok_or_else(|| { - io::Error::new(io::ErrorKind::Other, "Failed to get socket address") - }) + self.socket + .local_addr()? + .as_socket() + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Failed to get socket address")) } /// Convert into a raw `std::net::UdpSocket`. @@ -132,4 +133,3 @@ mod tests { assert!(addr.is_ipv4()); } } - diff --git a/nex-sys/src/lib.rs b/nex-sys/src/lib.rs index 99efc64..9870937 100644 --- a/nex-sys/src/lib.rs +++ b/nex-sys/src/lib.rs @@ -69,4 +69,4 @@ pub fn recv_from( } else { Ok(len as usize) } -} \ No newline at end of file +} diff --git a/nex-sys/src/unix.rs b/nex-sys/src/unix.rs index ba2240d..a6c7e97 100644 --- a/nex-sys/src/unix.rs +++ b/nex-sys/src/unix.rs @@ -168,7 +168,9 @@ mod tests { #[test] fn test_ipv4_addr_int() { - let addr = InAddr { s_addr: u32::from_be(0x7f000001) }; + let addr = InAddr { + s_addr: u32::from_be(0x7f000001), + }; assert_eq!(ipv4_addr_int(addr), 0x7f000001); } }