diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d8ae0c8 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "default-net" +version = "0.1.0" +authors = ["shellrow <81893184+shellrow@users.noreply.github.com>"] +edition = "2018" +repository = "https://github.com/shellrow/default-net" +readme = "README.md" +keywords = ["network"] +categories = ["network-programming"] +license = "MIT" + +[dependencies] +pnet = "0.27" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..469c514 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,94 @@ +use std::net::UdpSocket; +use pnet::transport::TransportChannelType::Layer4; +use pnet::transport::TransportProtocol::Ipv4; +use std::time; +use std::time::{Duration, Instant}; +use std::net::IpAddr; +//use pnet::packet::Packet; +use pnet::transport::icmp_packet_iter; + +pub fn get_router_ip(){ + let buf = [0u8; 0]; + let socket = match UdpSocket::bind("0.0.0.0:0") { + Ok(s) => s, + Err(_) => panic!("error!"), + }; + let dest: &str = "192.168.11.1:80"; + socket.set_ttl(1).unwrap(); + socket.send_to(&buf, dest).unwrap(); + let protocol = Layer4(Ipv4(pnet::packet::ip::IpNextHeaderProtocols::Icmp)); + let (mut _tx, mut rx) = match pnet::transport::transport_channel(4096, protocol) { + Ok((tx, rx)) => (tx, rx), + Err(e) => panic!("Error happened {}", e), + }; + let timeout = Duration::from_millis(3000); + let router_ip = receive_icmp_packets(&mut rx, pnet::packet::icmp::IcmpTypes::TimeExceeded, &timeout); + match router_ip { + Ok(ip) => {println!("{}", ip)}, + Err(e) => {println!("{}", e)}, + } +} + +#[cfg(any(unix, macos))] +pub fn receive_icmp_packets(rx: &mut pnet::transport::TransportReceiver, icmp_type: pnet::packet::icmp::IcmpType, timeout: &Duration) -> Result{ + let mut iter = icmp_packet_iter(rx); + let start_time = Instant::now(); + loop { + match iter.next_with_timeout(time::Duration::from_millis(100)) { + Ok(r) => { + if let Some((packet, addr)) = r { + if packet.get_icmp_type() == icmp_type { + match addr { + IpAddr::V4(ipv4_addr) =>{return Ok(ipv4_addr.to_string())}, + IpAddr::V6(ipv6_addr) =>{return Ok(ipv6_addr.to_string())}, + } + } + }else{ + return Err(String::from("Failed to read packet")); + } + }, + Err(e) => { + return Err(format!("An error occurred while reading: {}", e)); + } + } + if Instant::now().duration_since(start_time) > *timeout { + return Err(String::from("timeout")); + } + } +} + +#[cfg(target_os = "windows")] +pub fn receive_icmp_packets(rx: &mut pnet::transport::TransportReceiver, icmp_type: pnet::packet::icmp::IcmpType, timeout: &Duration) -> Result{ + let mut iter = icmp_packet_iter(rx); + let start_time = Instant::now(); + loop { + match iter.next() { + Ok((packet, addr)) => { + if let Some((packet, addr)) = r { + if packet.get_icmp_type() == icmp_type { + match addr { + IpAddr::V4(ipv4_addr) =>{return Ok(ipv4_addr.to_string())}, + IpAddr::V6(ipv6_addr) =>{return Ok(ipv6_addr.to_string())}, + } + } + }else{ + return Err(String::from("Failed to read packet")); + } + }, + Err(e) => { + return Err(format!("An error occurred while reading: {}", e)); + } + } + } + if Instant::now().duration_since(start_time) > *timeout { + return Err(String::from("timeout")); + } +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +}