diff --git a/crates/wtfnet-probe/Cargo.toml b/crates/wtfnet-probe/Cargo.toml index cffbfdf..f9bd125 100644 --- a/crates/wtfnet-probe/Cargo.toml +++ b/crates/wtfnet-probe/Cargo.toml @@ -11,3 +11,4 @@ thiserror = "2" tokio = { version = "1", features = ["net", "time"] } surge-ping = "0.8" wtfnet-geoip = { path = "../wtfnet-geoip" } +libc = "0.2" diff --git a/crates/wtfnet-probe/src/lib.rs b/crates/wtfnet-probe/src/lib.rs index d3ddf6e..101fd85 100644 --- a/crates/wtfnet-probe/src/lib.rs +++ b/crates/wtfnet-probe/src/lib.rs @@ -9,9 +9,12 @@ use pnet::transport::{ TransportChannelType, TransportProtocol, icmp_packet_iter, icmpv6_packet_iter, transport_channel, }; +#[cfg(unix)] +use std::os::unix::io::AsRawFd; use serde::{Deserialize, Serialize}; use socket2::{Domain, Protocol, Socket, Type}; use std::net::{IpAddr, SocketAddr}; +use std::mem::size_of_val; use std::time::{Duration, Instant}; use thiserror::Error; use tokio::net::{TcpStream, lookup_host}; @@ -473,9 +476,7 @@ fn udp_trace_hop_v6( let socket = std::net::UdpSocket::bind("[::]:0").map_err(|err| ProbeError::Io(err.to_string()))?; - socket - .set_unicast_hops_v6(u32::from(ttl)) - .map_err(|err| ProbeError::Io(err.to_string()))?; + set_ipv6_unicast_hops(&socket, ttl)?; let _ = socket.send_to(&[0u8; 4], addr); let mut iter = icmpv6_packet_iter(&mut rx); @@ -491,6 +492,28 @@ fn udp_trace_hop_v6( } } +#[cfg(unix)] +fn set_ipv6_unicast_hops(socket: &std::net::UdpSocket, ttl: u8) -> Result<(), ProbeError> { + let fd = socket.as_raw_fd(); + let hops: libc::c_int = ttl.into(); + let result = unsafe { + libc::setsockopt( + fd, + libc::IPPROTO_IPV6, + libc::IPV6_UNICAST_HOPS, + &hops as *const _ as *const libc::c_void, + size_of_val(&hops) as libc::socklen_t, + ) + }; + if result == 0 { + Ok(()) + } else { + Err(ProbeError::Io( + std::io::Error::last_os_error().to_string(), + )) + } +} + #[cfg(unix)] fn interpret_icmp_v4(packet: &IcmpPacket) -> Option { let icmp_type = packet.get_icmp_type(); diff --git a/docs/debian_error_msg.txt b/docs/debian_error_msg.txt index 2602495..72e951a 100644 --- a/docs/debian_error_msg.txt +++ b/docs/debian_error_msg.txt @@ -1,16 +1,17 @@ -error[E0308]: mismatched types - --> crates/wtfnet-probe/src/lib.rs:477:32 +Compiling wtfnet-probe v0.1.0 (/home/dazuo/rust-projects/WTFnet/crates/wtfnet-probe) + Compiling wtfnet-dns v0.1.0 (/home/dazuo/rust-projects/WTFnet/crates/wtfnet-dns) +error[E0599]: no method named `set_unicast_hops_v6` found for struct `std::net::UdpSocket` in the current scope + --> crates/wtfnet-probe/src/lib.rs:477:10 | -477 | .set_multicast_loop_v6(u32::from(ttl)) - | --------------------- ^^^^^^^^^^^^^^ expected `bool`, found `u32` - | | - | arguments to this method are incorrect +476 | / socket +477 | | .set_unicast_hops_v6(u32::from(ttl)) + | |_________-^^^^^^^^^^^^^^^^^^^ | -note: method defined here - --> /home/dazuo/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/sr c/net/udp.rs:527:12 +help: there is a method `set_multicast_loop_v6` with a similar name + | +477 - .set_unicast_hops_v6(u32::from(ttl)) +477 + .set_multicast_loop_v6(u32::from(ttl)) | -527 | pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> { - | ^^^^^^^^^^^^^^^^^^^^^ -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0599`. error: could not compile `wtfnet-probe` (lib) due to 1 previous error \ No newline at end of file