Merge branch 'main' into feat-android

main
shellrow 1 year ago committed by GitHub
commit 584b96f8f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      .github/workflows/ci.yml
  2. 6
      examples/default_gateway.rs
  3. 10
      examples/default_interface.rs
  4. 6
      examples/list_interfaces.rs
  5. 41
      src/bpf/binding.rs
  6. 9
      src/bpf/mod.rs
  7. 11
      src/bpf/unix.rs
  8. 8
      src/gateway/linux.rs
  9. 18
      src/gateway/mod.rs
  10. 18
      src/gateway/unix.rs
  11. 8
      src/interface/macos.rs
  12. 24
      src/interface/types.rs
  13. 4
      src/interface/unix.rs
  14. 80
      src/interface/windows.rs
  15. 8
      src/ip.rs
  16. 30
      src/lib.rs
  17. 31
      src/socket/mod.rs
  18. 26
      src/socket/packet.rs
  19. 4
      src/sys/mod.rs
  20. 5
      src/sys/unix.rs

@ -0,0 +1,16 @@
name: CI
on:
pull_request:
push:
branches:
- main
jobs:
lint:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run rustfmt
run: cargo fmt --all --check

@ -1,14 +1,14 @@
use default_net;
fn main(){
fn main() {
match default_net::get_default_gateway() {
Ok(gateway) => {
println!("Default Gateway");
println!("\tMAC: {}", gateway.mac_addr);
println!("\tIP: {}", gateway.ip_addr);
},
}
Err(e) => {
println!("{}", e);
},
}
}
}

@ -1,6 +1,6 @@
use default_net;
fn main(){
fn main() {
match default_net::get_default_interface() {
Ok(default_interface) => {
println!("Default Interface");
@ -11,7 +11,7 @@ fn main(){
println!("\tType: {}", default_interface.if_type.name());
if let Some(mac_addr) = default_interface.mac_addr {
println!("\tMAC: {}", mac_addr);
}else{
} else {
println!("\tMAC: (Failed to get mac address)");
}
println!("\tIPv4: {:?}", default_interface.ipv4);
@ -23,12 +23,12 @@ fn main(){
println!("Default Gateway");
println!("\tMAC: {}", gateway.mac_addr);
println!("\tIP: {}", gateway.ip_addr);
}else {
} else {
println!("Default Gateway: (Not found)");
}
},
}
Err(e) => {
println!("{}", e);
},
}
}
}

@ -1,6 +1,6 @@
use default_net;
fn main(){
fn main() {
let interfaces = default_net::get_interfaces();
for interface in interfaces {
println!("Interface");
@ -11,7 +11,7 @@ fn main(){
println!("\tType: {}", interface.if_type.name());
if let Some(mac_addr) = interface.mac_addr {
println!("\tMAC: {}", mac_addr);
}else{
} else {
println!("\tMAC: (Failed to get mac address)");
}
println!("\tIPv4: {:?}", interface.ipv4);
@ -23,7 +23,7 @@ fn main(){
println!("Gateway");
println!("\tMAC: {}", gateway.mac_addr);
println!("\tIP: {}", gateway.ip_addr);
}else {
} else {
println!("Gateway: (Not found)");
}
println!();

@ -20,17 +20,24 @@ const SIZEOF_C_UINT: libc::c_ulong = 4;
#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
const SIZEOF_C_LONG: libc::c_int = 8;
pub const BIOCSETIF: libc::c_ulong = IOC_IN | ((SIZEOF_IFREQ & IOCPARM_MASK) << 16usize) | (('B' as libc::c_ulong) << 8usize) | 108;
pub const BIOCIMMEDIATE: libc::c_ulong = IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 112;
pub const BIOCGDLT: libc::c_ulong = IOC_OUT | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 106;
pub const BIOCSBLEN: libc::c_ulong = IOC_INOUT | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 102;
pub const BIOCSHDRCMPLT: libc::c_ulong = IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 117;
pub const BIOCSETIF: libc::c_ulong =
IOC_IN | ((SIZEOF_IFREQ & IOCPARM_MASK) << 16usize) | (('B' as libc::c_ulong) << 8usize) | 108;
pub const BIOCIMMEDIATE: libc::c_ulong =
IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 112;
pub const BIOCGDLT: libc::c_ulong =
IOC_OUT | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 106;
pub const BIOCSBLEN: libc::c_ulong =
IOC_INOUT | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 102;
pub const BIOCSHDRCMPLT: libc::c_ulong =
IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 117;
#[cfg(target_os = "freebsd")]
pub const BIOCFEEDBACK: libc::c_ulong = IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 124;
pub const BIOCFEEDBACK: libc::c_ulong =
IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 124;
#[cfg(target_os = "netbsd")]
pub const BIOCFEEDBACK: libc::c_ulong = IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 125;
pub const BIOCFEEDBACK: libc::c_ulong =
IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 125;
pub const DLT_NULL: libc::c_uint = 0;
@ -47,10 +54,16 @@ pub fn BPF_WORDALIGN(x: isize) -> isize {
pub struct ifreq {
pub ifr_name: [libc::c_char; IFNAMSIZ],
pub ifru_addr: SockAddr,
pub ifru_addr: SockAddr,
}
#[cfg(any(target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "macos", target_os = "ios"))]
#[cfg(any(
target_os = "openbsd",
target_os = "freebsd",
target_os = "netbsd",
target_os = "macos",
target_os = "ios"
))]
pub struct sockaddr_dl {
pub sdl_len: libc::c_uchar,
pub sdl_family: libc::c_uchar,
@ -65,7 +78,10 @@ pub struct sockaddr_dl {
#[cfg(any(
target_os = "freebsd",
target_os = "netbsd",
all(any(target_os = "macos", target_os = "ios"), target_pointer_width = "32"),
all(
any(target_os = "macos", target_os = "ios"),
target_pointer_width = "32"
),
windows
))]
#[repr(C)]
@ -83,7 +99,10 @@ pub struct timeval32 {
#[cfg(any(
target_os = "openbsd",
all(any(target_os = "macos", target_os = "ios"), target_pointer_width = "64")
all(
any(target_os = "macos", target_os = "ios"),
target_pointer_width = "64"
)
))]
#[repr(C)]
pub struct bpf_hdr {

@ -1,10 +1,9 @@
#[cfg(not(target_os="windows"))]
#[cfg(not(target_os = "windows"))]
mod binding;
#[cfg(not(target_os="windows"))]
#[cfg(not(target_os = "windows"))]
pub use self::binding::*;
#[cfg(not(target_os="windows"))]
#[cfg(not(target_os = "windows"))]
mod unix;
#[cfg(not(target_os="windows"))]
#[cfg(not(target_os = "windows"))]
pub use self::unix::*;

@ -1,6 +1,6 @@
use super::binding;
use crate::socket::{DataLinkReceiver, DataLinkSender};
use crate::interface::Interface;
use crate::socket::{DataLinkReceiver, DataLinkSender};
use std::collections::VecDeque;
use std::ffi::CString;
@ -200,9 +200,7 @@ pub fn channel(interface_name: String, config: Config) -> io::Result<crate::sock
fd_set: unsafe { mem::zeroed() },
write_buffer: vec![0; config.write_buffer_size],
loopback: loopback,
timeout: config
.write_timeout
.map(|to| duration_to_timespec(to)),
timeout: config.write_timeout.map(|to| duration_to_timespec(to)),
});
unsafe {
libc::FD_ZERO(&mut sender.fd_set as *mut libc::fd_set);
@ -213,9 +211,7 @@ pub fn channel(interface_name: String, config: Config) -> io::Result<crate::sock
fd_set: unsafe { mem::zeroed() },
read_buffer: vec![0; allocated_read_buffer_size],
loopback: loopback,
timeout: config
.read_timeout
.map(|to| duration_to_timespec(to)),
timeout: config.read_timeout.map(|to| duration_to_timespec(to)),
packets: VecDeque::with_capacity(allocated_read_buffer_size / 64),
});
unsafe {
@ -245,7 +241,6 @@ impl DataLinkSender for DataLinkSenderImpl {
if len >= self.write_buffer.len() {
None
} else {
let offset = if self.loopback {
ETHERNET_HEADER_SIZE
} else {

@ -1,7 +1,7 @@
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::fs::read_to_string;
use crate::interface::MacAddr;
use super::Gateway;
use crate::interface::MacAddr;
use std::fs::read_to_string;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
const PATH_PROC_NET_ROUTE: &str = "/proc/net/route";
const PATH_PROC_NET_ARP: &str = "/proc/net/arp";
@ -35,7 +35,7 @@ fn convert_hex_ipv6(hex_ip: &str) -> Ipv6Addr {
pub fn get_default_gateway(interface_name: String) -> Result<Gateway, String> {
match super::send_udp_packet() {
Ok(_) => {},
Ok(_) => {}
Err(e) => return Err(format!("Failed to send UDP packet {}", e)),
}
let route_data = read_to_string(PATH_PROC_NET_ROUTE);

@ -1,11 +1,17 @@
#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "ios"))]
#[cfg(any(
target_os = "macos",
target_os = "openbsd",
target_os = "freebsd",
target_os = "netbsd",
target_os = "ios"
))]
pub(crate) mod unix;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub(crate) mod linux;
use crate::interface::{self, Interface, MacAddr};
use std::net::{IpAddr, Ipv4Addr};
use crate::interface::{self, MacAddr, Interface};
/// Structure of default Gateway information
#[derive(Clone, Debug)]
@ -28,7 +34,7 @@ impl Gateway {
/// Get default Gateway
pub fn get_default_gateway() -> Result<Gateway, String> {
let local_ip: IpAddr = match interface::get_local_ipaddr(){
let local_ip: IpAddr = match interface::get_local_ipaddr() {
Some(local_ip) => local_ip,
None => return Err(String::from("Local IP address not found")),
};
@ -41,20 +47,20 @@ pub fn get_default_gateway() -> Result<Gateway, String> {
return Ok(gateway);
}
}
},
}
IpAddr::V6(local_ipv6) => {
if iface.ipv6.iter().any(|x| x.addr == local_ipv6) {
if let Some(gateway) = iface.gateway {
return Ok(gateway);
}
}
},
}
}
}
Err(String::from("Default Gateway not found"))
}
#[cfg(not(target_os="windows"))]
#[cfg(not(target_os = "windows"))]
fn send_udp_packet() -> Result<(), String> {
use std::net::UdpSocket;
let buf = [0u8; 0];

@ -1,6 +1,6 @@
use std::time::{Duration, Instant};
use crate::socket;
use super::Gateway;
use crate::socket;
use std::time::{Duration, Instant};
const TIMEOUT: u64 = 3000;
@ -21,7 +21,7 @@ pub fn get_default_gateway(interface_name: String) -> Result<Gateway, String> {
Ok(socket::Channel::Ethernet(etx, erx)) => {
_tx = etx;
rx = erx;
},
}
Err(e) => return Err(format!("Failed to create channel {}", e)),
}
match super::send_udp_packet() {
@ -30,19 +30,17 @@ pub fn get_default_gateway(interface_name: String) -> Result<Gateway, String> {
}
loop {
match rx.next() {
Ok(frame) => {
match socket::packet::parse_frame(frame){
Ok(gateway) => {
return Ok(gateway);
},
Err(_) => {},
Ok(frame) => match socket::packet::parse_frame(frame) {
Ok(gateway) => {
return Ok(gateway);
}
Err(_) => {}
},
Err(_) => {}
}
if Instant::now().duration_since(start_time) > timeout {
return Err(String::from("Recieve timeout"));
}else{
} else {
match super::send_udp_packet() {
Ok(_) => (),
Err(e) => return Err(format!("Failed to send UDP packet {}", e)),

@ -1,6 +1,6 @@
use crate::interface::InterfaceType;
use std::collections::HashMap;
use system_configuration::network_configuration;
use crate::interface::InterfaceType;
fn get_if_type_from_id(type_id: String) -> InterfaceType {
match type_id.as_str() {
@ -11,18 +11,18 @@ fn get_if_type_from_id(type_id: String) -> InterfaceType {
}
}
pub fn get_if_type_map() -> HashMap<String, InterfaceType> {
pub fn get_if_type_map() -> HashMap<String, InterfaceType> {
let mut map: HashMap<String, InterfaceType> = HashMap::new();
let interfaces = network_configuration::get_interfaces();
for interface in &interfaces {
let if_name: String = if let Some(bsd_name) = interface.bsd_name() {
bsd_name.to_string()
}else{
} else {
continue;
};
let type_id: String = if let Some(type_string) = interface.interface_type_string() {
type_string.to_string()
}else{
} else {
continue;
};
map.insert(if_name, get_if_type_from_id(type_id));

@ -114,7 +114,13 @@ impl InterfaceType {
}
}
/// Returns OS-specific value of InterfaceType
#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "ios"))]
#[cfg(any(
target_os = "macos",
target_os = "openbsd",
target_os = "freebsd",
target_os = "netbsd",
target_os = "ios"
))]
pub fn value(&self) -> u32 {
// TODO
match *self {
@ -168,7 +174,9 @@ impl TryFrom<u32> for InterfaceType {
x if x == InterfaceType::PrimaryIsdn.value() => Ok(InterfaceType::PrimaryIsdn),
x if x == InterfaceType::Ppp.value() => Ok(InterfaceType::Ppp),
x if x == InterfaceType::Loopback.value() => Ok(InterfaceType::Loopback),
x if x == InterfaceType::Ethernet3Megabit.value() => Ok(InterfaceType::Ethernet3Megabit),
x if x == InterfaceType::Ethernet3Megabit.value() => {
Ok(InterfaceType::Ethernet3Megabit)
}
x if x == InterfaceType::Slip.value() => Ok(InterfaceType::Slip),
x if x == InterfaceType::Atm.value() => Ok(InterfaceType::Atm),
x if x == InterfaceType::GenericModem.value() => Ok(InterfaceType::GenericModem),
@ -179,12 +187,18 @@ impl TryFrom<u32> for InterfaceType {
x if x == InterfaceType::AsymmetricDsl.value() => Ok(InterfaceType::AsymmetricDsl),
x if x == InterfaceType::RateAdaptDsl.value() => Ok(InterfaceType::RateAdaptDsl),
x if x == InterfaceType::SymmetricDsl.value() => Ok(InterfaceType::SymmetricDsl),
x if x == InterfaceType::VeryHighSpeedDsl.value() => Ok(InterfaceType::VeryHighSpeedDsl),
x if x == InterfaceType::VeryHighSpeedDsl.value() => {
Ok(InterfaceType::VeryHighSpeedDsl)
}
x if x == InterfaceType::IPOverAtm.value() => Ok(InterfaceType::IPOverAtm),
x if x == InterfaceType::GigabitEthernet.value() => Ok(InterfaceType::GigabitEthernet),
x if x == InterfaceType::Tunnel.value() => Ok(InterfaceType::Tunnel),
x if x == InterfaceType::MultiRateSymmetricDsl.value() => Ok(InterfaceType::MultiRateSymmetricDsl),
x if x == InterfaceType::HighPerformanceSerialBus.value() => Ok(InterfaceType::HighPerformanceSerialBus),
x if x == InterfaceType::MultiRateSymmetricDsl.value() => {
Ok(InterfaceType::MultiRateSymmetricDsl)
}
x if x == InterfaceType::HighPerformanceSerialBus.value() => {
Ok(InterfaceType::HighPerformanceSerialBus)
}
x if x == InterfaceType::Wman.value() => Ok(InterfaceType::Wman),
x if x == InterfaceType::Wwanpp.value() => Ok(InterfaceType::Wwanpp),
x if x == InterfaceType::Wwanpp2.value() => Ok(InterfaceType::Wwanpp2),

@ -5,6 +5,7 @@ use crate::interface::InterfaceType;
use crate::ip::{Ipv4Net, Ipv6Net};
use crate::sys;
use crate::interface::InterfaceType;
use libc;
use std::ffi::{CStr, CString};
use std::mem::{self, MaybeUninit};
@ -230,7 +231,6 @@ fn unix_interfaces_inner(
let c_str = addr_ref.ifa_name as *const c_char;
let bytes = unsafe { CStr::from_ptr(c_str).to_bytes() };
let name = unsafe { from_utf8_unchecked(bytes).to_owned() };
let (mac, ip) = sockaddr_to_network_addr(addr_ref.ifa_addr as *const libc::sockaddr);
let (_, netmask) = sockaddr_to_network_addr(addr_ref.ifa_netmask as *const libc::sockaddr);
let mut ini_ipv4: Vec<Ipv4Net> = vec![];
@ -316,7 +316,7 @@ fn unix_interfaces_inner(
addr = addr_ref.ifa_next;
}
unsafe {
freeifaddrs(addrs);
libc::freeifaddrs(addrs);
}
for iface in &mut ifaces {
let name = CString::new(iface.name.as_bytes()).unwrap();

@ -1,40 +1,50 @@
use windows::Win32::Foundation::{ERROR_BUFFER_OVERFLOW, NO_ERROR};
use windows::Win32::Networking::WinSock::{SOCKADDR_IN, SOCKADDR_IN6};
use windows::Win32::NetworkManagement::IpHelper::{GetAdaptersAddresses, AF_UNSPEC, AF_INET, AF_INET6, GAA_FLAG_INCLUDE_GATEWAYS, IP_ADAPTER_ADDRESSES_LH, SendARP};
use std::convert::TryInto;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::convert::TryFrom;
use core::ffi::c_void;
use libc::{c_char, strlen, wchar_t, wcslen};
use memalloc::{allocate, deallocate};
use std::convert::TryFrom;
use std::convert::TryInto;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use windows::Win32::Foundation::{ERROR_BUFFER_OVERFLOW, NO_ERROR};
use windows::Win32::NetworkManagement::IpHelper::{
GetAdaptersAddresses, SendARP, AF_INET, AF_INET6, AF_UNSPEC, GAA_FLAG_INCLUDE_GATEWAYS,
IP_ADAPTER_ADDRESSES_LH,
};
use windows::Win32::Networking::WinSock::{SOCKADDR_IN, SOCKADDR_IN6};
use crate::ip::{Ipv4Net, Ipv6Net};
use crate::interface::{Interface, MacAddr,InterfaceType};
use crate::gateway::Gateway;
use crate::interface::{Interface, InterfaceType, MacAddr};
use crate::ip::{Ipv4Net, Ipv6Net};
#[cfg(target_endian = "little")]
fn htonl(val : u32) -> u32 {
fn htonl(val: u32) -> u32 {
let o3 = (val >> 24) as u8;
let o2 = (val >> 16) as u8;
let o1 = (val >> 8) as u8;
let o0 = val as u8;
let o1 = (val >> 8) as u8;
let o0 = val as u8;
(o0 as u32) << 24 | (o1 as u32) << 16 | (o2 as u32) << 8 | (o3 as u32)
}
#[cfg(target_endian = "big")]
fn htonl(val : u32) -> u32 {
fn htonl(val: u32) -> u32 {
val
}
fn get_mac_through_arp(src_ip: Ipv4Addr, dst_ip: Ipv4Addr) -> MacAddr {
let src_ip_int: u32 = htonl(u32::from(src_ip));
let dst_ip_int: u32 = htonl(u32::from(dst_ip));
let mut out_buf_len : u32 = 6;
let mut target_mac_addr: [u8; 6] = [0; 6];
let res = unsafe { SendARP(dst_ip_int, src_ip_int, target_mac_addr.as_mut_ptr() as *mut c_void, &mut out_buf_len) };
let mut out_buf_len: u32 = 6;
let mut target_mac_addr: [u8; 6] = [0; 6];
let res = unsafe {
SendARP(
dst_ip_int,
src_ip_int,
target_mac_addr.as_mut_ptr() as *mut c_void,
&mut out_buf_len,
)
};
if res == NO_ERROR.0 {
MacAddr::new(target_mac_addr)
}else{
} else {
MacAddr::zero()
}
}
@ -49,7 +59,15 @@ pub fn interfaces() -> Vec<Interface> {
let mut ret_val;
loop {
let old_size = dwsize as usize;
ret_val = unsafe { GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_GATEWAYS, std::ptr::null_mut::<std::ffi::c_void>(), mem, &mut dwsize) };
ret_val = unsafe {
GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_INCLUDE_GATEWAYS,
std::ptr::null_mut::<std::ffi::c_void>(),
mem,
&mut dwsize,
)
};
if ret_val != ERROR_BUFFER_OVERFLOW.0 || retries <= 0 {
break;
}
@ -61,17 +79,17 @@ pub fn interfaces() -> Vec<Interface> {
// Enumerate all adapters
let mut cur = mem;
while !cur.is_null() {
let if_type: u32 = unsafe{ (*cur).IfType };
let if_type: u32 = unsafe { (*cur).IfType };
match InterfaceType::try_from(if_type) {
Ok(_) => {},
Ok(_) => {}
Err(_) => {
cur = unsafe { (*cur).Next };
continue;
},
}
}
// Index
let anon1 = unsafe { (*cur).Anonymous1 };
let anon = unsafe { anon1.Anonymous};
let anon = unsafe { anon1.Anonymous };
let index = anon.IfIndex;
// Flags
let anon2 = unsafe { (*cur).Anonymous2 };
@ -87,26 +105,28 @@ pub fn interfaces() -> Vec<Interface> {
let fname_slice = unsafe { std::slice::from_raw_parts(p_fname, fname_len) };
let friendly_name = String::from_utf16(fname_slice).unwrap();
// Description
let p_desc = unsafe { (*cur).Description.0};
let p_desc = unsafe { (*cur).Description.0 };
let desc_len = unsafe { wcslen(p_desc as *const wchar_t) };
let desc_slice = unsafe { std::slice::from_raw_parts(p_desc, desc_len) };
let description = String::from_utf16(desc_slice).unwrap();
// MAC address
let mac_addr_arr: [u8; 6] = unsafe { (*cur).PhysicalAddress }[..6].try_into().unwrap_or([0, 0, 0, 0, 0, 0]);
let mac_addr_arr: [u8; 6] = unsafe { (*cur).PhysicalAddress }[..6]
.try_into()
.unwrap_or([0, 0, 0, 0, 0, 0]);
let mac_addr: MacAddr = MacAddr::new(mac_addr_arr);
// TransmitLinkSpeed (bits per second)
let transmit_speed = unsafe { (*cur).TransmitLinkSpeed};
let transmit_speed = unsafe { (*cur).TransmitLinkSpeed };
// ReceiveLinkSpeed (bits per second)
let receive_speed = unsafe { (*cur).ReceiveLinkSpeed};
let receive_speed = unsafe { (*cur).ReceiveLinkSpeed };
let mut ipv4_vec: Vec<Ipv4Net> = vec![];
let mut ipv6_vec: Vec<Ipv6Net> = vec![];
// Enumerate all IPs
let mut cur_a = unsafe { (*cur).FirstUnicastAddress };
while !cur_a.is_null() {
let addr = unsafe { (*cur_a).Address };
let prefix_len = unsafe{ (*cur_a).OnLinkPrefixLength };
let prefix_len = unsafe { (*cur_a).OnLinkPrefixLength };
let sockaddr = unsafe { *addr.lpSockaddr };
if sockaddr.sa_family == AF_INET.0 as u16{
if sockaddr.sa_family == AF_INET.0 as u16 {
let sockaddr: *mut SOCKADDR_IN = addr.lpSockaddr as *mut SOCKADDR_IN;
let a = unsafe { (*sockaddr).sin_addr.S_un.S_addr };
let ipv4 = if cfg!(target_endian = "little") {
@ -153,13 +173,13 @@ pub fn interfaces() -> Vec<Interface> {
ip_addr: IpAddr::V4(*gateway_ip),
};
Some(gateway)
}else{
} else {
None
}
},
}
None => None,
};
let interface: Interface = Interface{
let interface: Interface = Interface {
index: index,
name: adapter_name,
friendly_name: Some(friendly_name),

@ -97,11 +97,15 @@ fn ipv6_netmask_to_prefix(netmask: Ipv6Addr) -> u8 {
}
fn prefix_to_ipv4_netmask(prefix_len: u8) -> Ipv4Addr {
let netmask_u32: u32 = u32::max_value().checked_shl(32 - prefix_len as u32).unwrap_or(0);
let netmask_u32: u32 = u32::max_value()
.checked_shl(32 - prefix_len as u32)
.unwrap_or(0);
Ipv4Addr::from(netmask_u32)
}
fn prefix_to_ipv6_netmask(prefix_len: u8) -> Ipv6Addr {
let netmask_u128: u128 = u128::max_value().checked_shl((128 - prefix_len) as u32).unwrap_or(u128::min_value());
let netmask_u128: u128 = u128::max_value()
.checked_shl((128 - prefix_len) as u32)
.unwrap_or(u128::min_value());
Ipv6Addr::from(netmask_u128)
}

@ -1,16 +1,28 @@
#[cfg(not(target_os="windows"))]
mod sys;
#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "ios"))]
#[cfg(any(
target_os = "macos",
target_os = "openbsd",
target_os = "freebsd",
target_os = "netbsd",
target_os = "ios"
))]
mod bpf;
#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "ios"))]
#[cfg(any(
target_os = "macos",
target_os = "openbsd",
target_os = "freebsd",
target_os = "netbsd",
target_os = "ios"
))]
mod socket;
#[cfg(not(target_os = "windows"))]
mod sys;
pub mod ip;
pub mod interface;
pub mod gateway;
pub mod interface;
pub mod ip;
pub use interface::Interface;
pub use gateway::get_default_gateway;
pub use gateway::Gateway;
pub use interface::get_default_interface;
pub use interface::get_interfaces;
pub use gateway::Gateway;
pub use gateway::get_default_gateway;
pub use interface::Interface;

@ -1,8 +1,8 @@
pub mod packet;
#[cfg(not(target_os="windows"))]
#[cfg(not(target_os = "windows"))]
mod unix;
#[cfg(not(target_os="windows"))]
#[cfg(not(target_os = "windows"))]
pub use self::unix::*;
#[cfg(test)]
@ -16,7 +16,7 @@ mod tests {
Err(e) => {
println!("Failed to create UDP socket {}", e);
return;
},
}
};
let dst: &str = "1.1.1.1:80";
match socket.set_ttl(1) {
@ -24,14 +24,14 @@ mod tests {
Err(e) => {
println!("Failed to set TTL {}", e);
return;
},
}
}
match socket.send_to(&buf, dst) {
Ok(_) => (),
Err(e) => {
println!("Failed to send data {}", e);
return;
},
}
}
}
#[test]
@ -55,17 +55,15 @@ mod tests {
loop {
match rx.next() {
Ok(frame) => {
match packet::parse_frame(frame){
Ok(gateway) => {
println!("Default Gateway:");
println!("{}", gateway.mac_addr);
println!("{}", gateway.ip_addr);
return;
},
Err(_) => {
println!("Parse Error");
},
Ok(frame) => match packet::parse_frame(frame) {
Ok(gateway) => {
println!("Default Gateway:");
println!("{}", gateway.mac_addr);
println!("{}", gateway.ip_addr);
return;
}
Err(_) => {
println!("Parse Error");
}
},
Err(e) => {
@ -76,4 +74,3 @@ mod tests {
}
}
}

@ -1,6 +1,6 @@
use std::convert::TryInto;
use crate::gateway::Gateway;
use crate::interface::MacAddr;
use std::convert::TryInto;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::u16;
@ -76,11 +76,18 @@ fn convert_ipv6_bytes(bytes: [u8; 16]) -> Ipv6Addr {
}
pub fn parse_frame(frame: &[u8]) -> Result<Gateway, ()> {
let src_mac: [u8; 6] = frame[Frame::SrcMacAddr.start_index()..Frame::SrcMacAddr.end_index()].try_into().unwrap();
let ether_type: [u8; 2] = frame[Frame::EtherType.start_index()..Frame::EtherType.end_index()].try_into().unwrap();
let src_mac: [u8; 6] = frame[Frame::SrcMacAddr.start_index()..Frame::SrcMacAddr.end_index()]
.try_into()
.unwrap();
let ether_type: [u8; 2] = frame[Frame::EtherType.start_index()..Frame::EtherType.end_index()]
.try_into()
.unwrap();
match ether_type {
ETHER_TYPE_IPV4 => {
let src_ip: [u8; 4] = frame[Frame::SrcIpv4Addr.start_index()..Frame::SrcIpv4Addr.end_index()].try_into().unwrap();
let src_ip: [u8; 4] = frame
[Frame::SrcIpv4Addr.start_index()..Frame::SrcIpv4Addr.end_index()]
.try_into()
.unwrap();
let next_header_protocol: u8 = frame[Frame::NextHeaderProtocolIpv4.start_index()];
if next_header_protocol == NEXT_HEADER_ICMP {
let icmp_type: u8 = frame[Frame::IcmpType.start_index()];
@ -92,9 +99,12 @@ pub fn parse_frame(frame: &[u8]) -> Result<Gateway, ()> {
return Ok(gateway);
}
}
},
}
ETHER_TYPE_IPV6 => {
let src_ip: [u8; 16] = frame[Frame::SrcIpv6Addr.start_index()..Frame::SrcIpv6Addr.end_index()].try_into().unwrap();
let src_ip: [u8; 16] = frame
[Frame::SrcIpv6Addr.start_index()..Frame::SrcIpv6Addr.end_index()]
.try_into()
.unwrap();
let next_header_protocol: u8 = frame[Frame::NextHeaderProtocolIpv6.start_index()];
if next_header_protocol == NEXT_HEADER_ICMPV6 {
let icmp_type: u8 = frame[Frame::Icmpv6Type.start_index()];
@ -109,8 +119,8 @@ pub fn parse_frame(frame: &[u8]) -> Result<Gateway, ()> {
}
}
}
},
_ => {},
}
_ => {}
}
Err(())
}

@ -1,4 +1,4 @@
#[cfg(not(target_os="windows"))]
#[cfg(not(target_os = "windows"))]
mod unix;
#[cfg(not(target_os="windows"))]
#[cfg(not(target_os = "windows"))]
pub use self::unix::*;

@ -27,7 +27,8 @@ pub fn sockaddr_to_addr(storage: &SockAddrStorage, len: usize) -> io::Result<Soc
let o2 = (ip >> 16) as u8;
let o3 = (ip >> 8) as u8;
let o4 = ip as u8;
let sockaddrv4 = SocketAddrV4::new(Ipv4Addr::new(o1, o2, o3, o4), ntohs(storage.sin_port));
let sockaddrv4 =
SocketAddrV4::new(Ipv4Addr::new(o1, o2, o3, o4), ntohs(storage.sin_port));
Ok(SocketAddr::V4(sockaddrv4))
}
AF_INET6 => {
@ -51,7 +52,7 @@ pub fn sockaddr_to_addr(storage: &SockAddrStorage, len: usize) -> io::Result<Soc
storage.sin6_scope_id,
)))
}
_ => Err(io::Error::new(io::ErrorKind::InvalidData, "Not supported",)),
_ => Err(io::Error::new(io::ErrorKind::InvalidData, "Not supported")),
}
}

Loading…
Cancel
Save