@ -1,63 +1,46 @@
use std ::net ::UdpSocket ;
use std ::time ::{ Duration , Instant } ;
use std ::net ::{ IpAddr , Ipv4Addr } ;
use pnet ::packet ::Packet ;
use pnet ::packet ::MutablePacket ;
use crate ::interface ;
use std ::net ::{ IpAddr } ;
use pnet_packet ::Packet ;
use crate ::interface ::{ self , MacAddr } ;
const TIMEOUT : u64 = 3000 ;
const RETRY : u32 = 3 ;
/// Struct of default Gateway information
#[ derive(Clone, Debug) ]
pub struct Gateway {
pub ip : Option < String > ,
pub mac : Option < String > ,
pub mac_addr : MacAddr ,
pub ip_addr : IpAddr ,
}
/// Get default Gateway
pub fn get_default_gateway ( ) -> Gateway {
let mut gateway : Gateway = Gateway {
ip : None ,
mac : None ,
pub fn get_default_gateway ( ) -> Result < Gateway , String > {
let default_idx = match interface ::get_default_interface_index ( ) {
Some ( idx ) = > idx ,
None = > return Err ( String ::from ( "Failed to get default interface" ) ) ,
} ;
let ip : Option < String > = match get_default_gateway_ip ( ) {
Ok ( ip ) = > Some ( ip ) ,
Err ( _ ) = > None ,
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 config = pnet_datalink ::Config {
write_buffer_size : 4096 ,
read_buffer_size : 4096 ,
read_timeout : None ,
write_timeout : None ,
channel_type : pnet_datalink ::ChannelType ::Layer2 ,
bpf_fd_attempts : 1000 ,
linux_fanout : None ,
promiscuous : false ,
} ;
gateway . ip = ip . clone ( ) ;
if let Some ( gateway_ip ) = ip {
let mac : Option < String > = match get_default_gateway_mac ( gateway_ip ) {
Ok ( mac ) = > Some ( mac ) ,
Err ( _ ) = > None ,
let ( mut _tx , mut rx ) = match pnet_datalink ::channel ( & interface , config ) {
Ok ( pnet_datalink ::Channel ::Ethernet ( tx , rx ) ) = > ( tx , rx ) ,
Ok ( _ ) = > panic! ( "Unknown channel type" ) ,
Err ( e ) = > panic! ( "Error happened {}" , e ) ,
} ;
gateway . mac = mac ;
}
return gateway ;
}
/// Get default Gateway IP address
pub fn get_default_gateway_ip ( ) -> Result < String , String > {
match send_udp_packet ( ) {
Ok ( _ ) = > ( ) ,
Err ( e ) = > return Err ( format! ( "Failed to send UDP packet {}" , e ) ) ,
}
let timeout = Duration ::from_millis ( TIMEOUT ) ;
let r = receive_icmp_packets ( pnet ::packet ::icmp ::IcmpTypes ::TimeExceeded , & timeout ) ;
return r ;
}
/// Get default Gateway MAC address
pub fn get_default_gateway_mac ( gateway_ip : String ) -> Result < String , String > {
match gateway_ip . parse ::< Ipv4Addr > ( ) {
Ok ( ipv4_addr ) = > {
if let Some ( gateway_mac ) = get_mac_through_arp ( ipv4_addr ) {
return Ok ( gateway_mac ) ;
} else {
return Err ( String ::from ( "Failed to get gateway mac address" ) ) ;
}
} ,
Err ( _ ) = > return Err ( String ::from ( "Invalid IPv4 address" ) ) ,
}
receive_packets ( & mut rx )
}
fn send_udp_packet ( ) -> Result < ( ) , String > {
@ -78,49 +61,33 @@ fn send_udp_packet() -> Result<(), String> {
Ok ( ( ) )
}
fn receive_icmp_packets ( icmp_type : pnet ::packet ::icmp ::IcmpType , timeout : & Duration ) -> Result < String , String > {
let default_idx = match interface ::get_default_interface_index ( ) {
Some ( idx ) = > idx ,
None = > return Err ( String ::from ( "Failed to get default interface" ) ) ,
} ;
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 config = pnet ::datalink ::Config {
write_buffer_size : 4096 ,
read_buffer_size : 4096 ,
read_timeout : None ,
write_timeout : None ,
channel_type : pnet ::datalink ::ChannelType ::Layer2 ,
bpf_fd_attempts : 1000 ,
linux_fanout : None ,
promiscuous : false ,
} ;
let ( mut _tx , mut rx ) = match pnet ::datalink ::channel ( & interface , config ) {
Ok ( pnet ::datalink ::Channel ::Ethernet ( tx , rx ) ) = > ( tx , rx ) ,
Ok ( _ ) = > panic! ( "Unknown channel type" ) ,
Err ( e ) = > panic! ( "Error happened {}" , e ) ,
} ;
receive_packets ( & mut rx , icmp_type , timeout )
}
fn receive_packets ( rx : & mut Box < dyn pnet ::datalink ::DataLinkReceiver > , icmp_type : pnet ::packet ::icmp ::IcmpType , timeout : & Duration ) -> Result < String , String > {
fn receive_packets ( rx : & mut Box < dyn pnet_datalink ::DataLinkReceiver > ) -> Result < Gateway , String > {
let timeout = Duration ::from_millis ( TIMEOUT ) ;
let start_time = Instant ::now ( ) ;
loop {
match rx . next ( ) {
Ok ( frame ) = > {
let frame = match pnet :: packet ::ethernet ::EthernetPacket ::new ( frame ) {
let frame = match pnet_packet ::ethernet ::EthernetPacket ::new ( frame ) {
Some ( f ) = > f ,
None = > return Err ( String ::from ( "Failed to read packet" ) ) ,
} ;
match frame . get_ethertype ( ) {
pnet ::packet ::ethernet ::EtherTypes ::Ipv4 = > {
if let Some ( ip_addr ) = ipv4_handler ( & frame , icmp_type ) {
return Ok ( ip_addr ) ;
pnet_packet ::ethernet ::EtherTypes ::Ipv4 = > {
if let Some ( ip_addr ) = ipv4_handler ( & frame ) {
let gateway = Gateway {
mac_addr : MacAddr ::new ( frame . get_source ( ) . octets ( ) ) ,
ip_addr : ip_addr ,
} ;
return Ok ( gateway ) ;
}
} ,
pnet ::packet ::ethernet ::EtherTypes ::Ipv6 = > {
if let Some ( ip_addr ) = ipv6_handler ( & frame , icmp_type ) {
return Ok ( ip_addr ) ;
pnet_packet ::ethernet ::EtherTypes ::Ipv6 = > {
if let Some ( ip_addr ) = ipv6_handler ( & frame ) {
let gateway = Gateway {
mac_addr : MacAddr ::new ( frame . get_source ( ) . octets ( ) ) ,
ip_addr : ip_addr ,
} ;
return Ok ( gateway ) ;
}
} ,
_ = > { }
@ -130,8 +97,8 @@ fn receive_packets(rx: &mut Box<dyn pnet::datalink::DataLinkReceiver>, icmp_type
return Err ( format! ( "An error occurred while reading: {}" , e ) ) ;
}
}
if Instant ::now ( ) . duration_since ( start_time ) > * timeout {
return Err ( String ::from ( "timeout" ) ) ;
if Instant ::now ( ) . duration_since ( start_time ) > timeout {
return Err ( String ::from ( "Recieve timeout" ) ) ;
} else {
match send_udp_packet ( ) {
Ok ( _ ) = > ( ) ,
@ -141,11 +108,11 @@ fn receive_packets(rx: &mut Box<dyn pnet::datalink::DataLinkReceiver>, icmp_type
}
}
fn ipv4_handler ( ethernet : & pnet :: packet ::ethernet ::EthernetPacket , icmp_type : pnet ::packet ::icmp ::IcmpType ) -> Option < String > {
if let Some ( packet ) = pnet :: packet ::ipv4 ::Ipv4Packet ::new ( ethernet . payload ( ) ) {
fn ipv4_handler ( ethernet : & pnet_ packet ::ethernet ::EthernetPacket ) -> Option < IpAddr > {
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 , icmp_type ) ;
pnet_ packet ::ip ::IpNextHeaderProtocols ::Icmp = > {
return icmp_handler ( & packet ) ;
} ,
_ = > {
None
@ -156,11 +123,11 @@ fn ipv4_handler(ethernet: &pnet::packet::ethernet::EthernetPacket, icmp_type: pn
}
}
fn ipv6_handler ( ethernet : & pnet :: packet ::ethernet ::EthernetPacket , icmp_type : pnet ::packet ::icmp ::IcmpType ) -> Option < String > {
if let Some ( packet ) = pnet :: packet ::ipv6 ::Ipv6Packet ::new ( ethernet . payload ( ) ) {
fn ipv6_handler ( ethernet : & pnet_ packet ::ethernet ::EthernetPacket ) -> Option < IpAddr > {
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 , icmp_type ) ;
pnet_ packet ::ip ::IpNextHeaderProtocols ::Icmpv6 = > {
return icmpv6_handler ( & packet ) ;
} ,
_ = > {
None
@ -171,11 +138,11 @@ fn ipv6_handler(ethernet: &pnet::packet::ethernet::EthernetPacket, icmp_type: pn
}
}
fn icmp_handler ( ip_packet : & pnet :: packet ::ipv4 ::Ipv4Packet , icmp_type : pnet ::packet ::icmp ::IcmpType ) -> Option < String > {
if let Some ( packet ) = pnet :: packet ::icmp ::IcmpPacket ::new ( ip_packet . payload ( ) ) {
if packet . get_icmp_type ( ) = = icmp_type {
fn icmp_handler ( ip_packet : & pnet_ packet ::ipv4 ::Ipv4Packet ) -> Option < IpAddr > {
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 ( ) )
return Some ( IpAddr ::V4 ( ipv4_addr ) )
} else {
None
}
@ -184,11 +151,11 @@ fn icmp_handler(ip_packet: &pnet::packet::ipv4::Ipv4Packet, icmp_type: pnet::pac
}
}
fn icmpv6_handler ( ip_packet : & pnet :: packet ::ipv6 ::Ipv6Packet , icmp_type : pnet ::packet ::icmp ::IcmpType ) -> Option < String > {
if let Some ( packet ) = pnet ::packet ::icmp ::Icmp Packet ::new ( ip_packet . payload ( ) ) {
if packet . get_icmp_type ( ) = = icmp_type {
fn icmpv6_handler ( ip_packet : & pnet_ packet ::ipv6 ::Ipv6Packet ) -> Option < IpAddr > {
if let Some ( packet ) = pnet_packet ::icmpv6 ::Icmpv6 Packet ::new ( ip_packet . payload ( ) ) {
if packet . get_icmpv6 _type ( ) = = pnet_packet ::icmpv6 ::Icmpv6Types ::TimeExceeded {
let ipv6_addr = ip_packet . get_source ( ) ;
return Some ( ipv6_addr . to_string ( ) )
return Some ( IpAddr ::V6 ( ipv6_addr ) )
} else {
None
}
@ -196,82 +163,3 @@ fn icmpv6_handler(ip_packet: &pnet::packet::ipv6::Ipv6Packet, icmp_type: pnet::p
None
}
}
fn get_mac_through_arp ( dst_ip : Ipv4Addr ) -> Option < String > {
let default_idx = match interface ::get_default_interface_index ( ) {
Some ( idx ) = > idx ,
None = > return None ,
} ;
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 src_ip = interface . ips . iter ( ) . find ( | ip | ip . is_ipv4 ( ) )
. map ( | ip | match ip . ip ( ) {
IpAddr ::V4 ( ip ) = > ip ,
_ = > unreachable! ( ) ,
} )
. unwrap ( ) ;
let ( mut sender , mut receiver ) = match pnet ::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 ) ,
} ;
let iface_mac : pnet ::datalink ::MacAddr = match interface . mac {
Some ( mac ) = > mac ,
None = > return None ,
} ;
let mut ethernet_buffer = [ 0 u8 ; 42 ] ;
let mut ethernet_packet = match pnet ::packet ::ethernet ::MutableEthernetPacket ::new ( & mut ethernet_buffer ) {
Some ( ethernet_packet ) = > ethernet_packet ,
None = > return None ,
} ;
ethernet_packet . set_destination ( pnet ::datalink ::MacAddr ::broadcast ( ) ) ;
ethernet_packet . set_source ( iface_mac ) ;
ethernet_packet . set_ethertype ( pnet ::packet ::ethernet ::EtherTypes ::Arp ) ;
let mut arp_buffer = [ 0 u8 ; 28 ] ;
let mut arp_packet = match pnet ::packet ::arp ::MutableArpPacket ::new ( & mut arp_buffer ) {
Some ( arp_packet ) = > arp_packet ,
None = > return None ,
} ;
arp_packet . set_hardware_type ( pnet ::packet ::arp ::ArpHardwareTypes ::Ethernet ) ;
arp_packet . set_protocol_type ( pnet ::packet ::ethernet ::EtherTypes ::Ipv4 ) ;
arp_packet . set_hw_addr_len ( 6 ) ;
arp_packet . set_proto_addr_len ( 4 ) ;
arp_packet . set_operation ( pnet ::packet ::arp ::ArpOperations ::Request ) ;
arp_packet . set_sender_hw_addr ( iface_mac ) ;
arp_packet . set_sender_proto_addr ( src_ip ) ;
arp_packet . set_target_hw_addr ( pnet ::datalink ::MacAddr ::zero ( ) ) ;
arp_packet . set_target_proto_addr ( dst_ip ) ;
ethernet_packet . set_payload ( arp_packet . packet_mut ( ) ) ;
match sender . send_to ( ethernet_packet . packet ( ) , None ) {
Some ( s ) = > {
match s {
Ok ( _ ) = > ( ) ,
Err ( _ ) = > return None ,
}
} ,
None = > return None ,
}
let mut target_mac_addr : pnet ::datalink ::MacAddr = pnet ::datalink ::MacAddr ::zero ( ) ;
for _x in 0 .. ( RETRY - 1 ) {
let buf = receiver . next ( ) . unwrap ( ) ;
let arp = match pnet ::packet ::arp ::ArpPacket ::new ( & buf [ pnet ::packet ::ethernet ::MutableEthernetPacket ::minimum_packet_size ( ) .. ] ) {
Some ( arp ) = > arp ,
None = > return None ,
} ;
if arp . get_sender_hw_addr ( ) ! = iface_mac {
target_mac_addr = arp . get_sender_hw_addr ( ) ;
break ;
}
}
if target_mac_addr = = pnet ::datalink ::MacAddr ::zero ( ) {
return None ;
} else {
return Some ( target_mac_addr . to_string ( ) ) ;
}
}