diff --git a/Cargo.toml b/Cargo.toml index d8ae0c8..f1e3473 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,4 +10,4 @@ categories = ["network-programming"] license = "MIT" [dependencies] -pnet = "0.27" +pnet = "0.26" diff --git a/examples/default_gateway.rs b/examples/default_gateway.rs index ca6a1a8..530a839 100644 --- a/examples/default_gateway.rs +++ b/examples/default_gateway.rs @@ -1,5 +1,8 @@ use default_net; fn main(){ - default_net::get_default_gateway(); + match default_net::get_default_gateway() { + Ok(default_gateway) => {println!("Default Gateway: {}",default_gateway)}, + Err(e) => {println!("{}",e)}, + } } diff --git a/src/lib.rs b/src/lib.rs index 5b675e5..576f853 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,8 +6,11 @@ use std::time::{Duration, Instant}; use std::net::IpAddr; //use pnet::packet::Packet; use pnet::transport::icmp_packet_iter; +use pnet::packet::Packet; +use pnet::datalink; -pub fn get_default_gateway(){ +pub fn get_default_gateway() -> Result { + /* let buf = [0u8; 0]; let socket = match UdpSocket::bind("0.0.0.0:0") { Ok(s) => s, @@ -16,22 +19,41 @@ pub fn get_default_gateway(){ let dest: &str = "192.168.11.1:80"; socket.set_ttl(1).unwrap(); socket.send_to(&buf, dest).unwrap(); + */ + send_udp_packet(); + /* 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)}, - } + */ + let timeout = Duration::from_millis(3000); + //let r = receive_icmp_packets(&mut rx, pnet::packet::icmp::IcmpTypes::TimeExceeded, &timeout); + let r = receive_icmp_packets(pnet::packet::icmp::IcmpTypes::TimeExceeded, &timeout); + return r; +} + +pub fn send_udp_packet(){ + 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(); } #[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); +pub fn receive_icmp_packets(icmp_type: pnet::packet::icmp::IcmpType, timeout: &Duration) -> Result{ + 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 mut iter = icmp_packet_iter(&mut rx); let start_time = Instant::now(); loop { match iter.next_with_timeout(*timeout) { @@ -53,19 +75,21 @@ pub fn receive_icmp_packets(rx: &mut pnet::transport::TransportReceiver, icmp_ty } if Instant::now().duration_since(start_time) > *timeout { return Err(String::from("timeout")); + }else{ + send_udp_packet(); } } } -/* -#[cfg(target_os = "windows")] -fn send_icmp_packet(){ - -} -*/ #[cfg(target_os = "windows")] -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); +fn receive_icmp_packets(icmp_type: pnet::packet::icmp::IcmpType, timeout: &Duration) -> Result{ + /* + 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 mut iter = icmp_packet_iter(&mut rx); let start_time = Instant::now(); loop { match iter.next() { @@ -83,7 +107,153 @@ fn receive_icmp_packets(rx: &mut pnet::transport::TransportReceiver, icmp_type: } if Instant::now().duration_since(start_time) > *timeout { return Err(String::from("timeout")); + }else{ + send_udp_packet(); + } + } + */ + let default_idx = get_default_interface_index().unwrap(); + let interfaces = pnet::datalink::interfaces(); + let interface = interfaces.into_iter().filter(|interface: &pnet::datalink::NetworkInterface| interface.index == default_idx).next().expect("Failed to get Interface"); + let (mut _sender, mut receiver) = match datalink::channel(&interface, Default::default()) { + Ok(pnet::datalink::Channel::Ethernet(tx, rx)) => (tx, rx), + Ok(_) => panic!("Unknown channel type"), + Err(e) => panic!("Error happened {}", e), + }; + receive_packets(&mut receiver, timeout) +} + +#[cfg(target_os = "windows")] +fn receive_packets(rx: &mut Box, timeout: &Duration) -> Result{ + let start_time = Instant::now(); + loop { + match rx.next() { + Ok(frame) => { + let frame = pnet::packet::ethernet::EthernetPacket::new(frame).unwrap(); + match frame.get_ethertype() { + pnet::packet::ethernet::EtherTypes::Ipv4 => { + if let Some(ip_addr) = ipv4_handler(&frame){ + return Ok(ip_addr); + } + }, + pnet::packet::ethernet::EtherTypes::Ipv6 => { + if let Some(ip_addr) = ipv6_handler(&frame){ + return Ok(ip_addr); + } + }, + _ => { + //println!("Not a ipv4 or ipv6"); + } + } + }, + Err(e) => { + return Err(format!("An error occurred while reading: {}", e)); + } + } + if Instant::now().duration_since(start_time) > *timeout { + return Err(String::from("timeout")); + }else{ + send_udp_packet(); + } + } +} + +fn ipv4_handler(ethernet: &pnet::packet::ethernet::EthernetPacket) -> Option { + if let Some(packet) = pnet::packet::ipv4::Ipv4Packet::new(ethernet.payload()){ + match packet.get_next_level_protocol() { + pnet::packet::ip::IpNextHeaderProtocols::Icmp => { + return icmp_handler(&packet); + }, + _ => { + None + } + } + }else{ + None + } +} + +fn ipv6_handler(ethernet: &pnet::packet::ethernet::EthernetPacket) -> Option { + if let Some(packet) = pnet::packet::ipv6::Ipv6Packet::new(ethernet.payload()){ + match packet.get_next_header() { + pnet::packet::ip::IpNextHeaderProtocols::Icmpv6 => { + return icmpv6_handler(&packet); + }, + _ => { + None + } + } + }else{ + None + } +} + +fn icmp_handler(ip_packet: &pnet::packet::ipv4::Ipv4Packet) -> Option { + if let Some(packet) = pnet::packet::icmp::IcmpPacket::new(ip_packet.payload()){ + if packet.get_icmp_type() == pnet::packet::icmp::IcmpTypes::TimeExceeded { + let ipv4_addr = ip_packet.get_source(); + return Some(ipv4_addr.to_string()) + }else{ + None + } + }else{ + None + } +} + +fn icmpv6_handler(ip_packet: &pnet::packet::ipv6::Ipv6Packet) -> Option { + if let Some(packet) = pnet::packet::icmp::IcmpPacket::new(ip_packet.payload()){ + if packet.get_icmp_type() == pnet::packet::icmp::IcmpTypes::TimeExceeded { + let ipv6_addr = ip_packet.get_source(); + return Some(ipv6_addr.to_string()) + }else{ + None + } + }else{ + None + } +} + +pub fn get_local_ipaddr() -> Option { + let socket = match UdpSocket::bind("0.0.0.0:0") { + Ok(s) => s, + Err(_) => return None, + }; + + match socket.connect("8.8.8.8:80") { + Ok(()) => (), + Err(_) => return None, + }; + + match socket.local_addr() { + Ok(addr) => return Some(addr.ip().to_string()), + Err(_) => return None, + }; +} + +pub fn get_default_interface_index() -> Option { + let local_ip = get_local_ipaddr(); + let all_interfaces = datalink::interfaces(); + if let Some(local_ip) = local_ip { + for iface in all_interfaces{ + for ip in iface.ips{ + match ip.ip() { + IpAddr::V4(ipv4) => { + if local_ip == ipv4.to_string() { + return Some(iface.index) + } + }, + IpAddr::V6(ipv6) => { + if local_ip == ipv6.to_string() { + return Some(iface.index) + } + }, + } + } } + return None; + }else{ + return None; } }