Merge branch 'main' into feat-android

main
shellrow 2 years 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. 4
      examples/default_gateway.rs
  3. 4
      examples/default_interface.rs
  4. 39
      src/bpf/binding.rs
  5. 1
      src/bpf/mod.rs
  6. 11
      src/bpf/unix.rs
  7. 8
      src/gateway/linux.rs
  8. 14
      src/gateway/mod.rs
  9. 12
      src/gateway/unix.rs
  10. 2
      src/interface/macos.rs
  11. 24
      src/interface/types.rs
  12. 4
      src/interface/unix.rs
  13. 48
      src/interface/windows.rs
  14. 8
      src/ip.rs
  15. 30
      src/lib.rs
  16. 13
      src/socket/mod.rs
  17. 26
      src/socket/packet.rs
  18. 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

@ -6,9 +6,9 @@ fn main(){
println!("Default Gateway"); println!("Default Gateway");
println!("\tMAC: {}", gateway.mac_addr); println!("\tMAC: {}", gateway.mac_addr);
println!("\tIP: {}", gateway.ip_addr); println!("\tIP: {}", gateway.ip_addr);
}, }
Err(e) => { Err(e) => {
println!("{}", e); println!("{}", e);
}, }
} }
} }

@ -26,9 +26,9 @@ fn main(){
} else { } else {
println!("Default Gateway: (Not found)"); println!("Default Gateway: (Not found)");
} }
}, }
Err(e) => { Err(e) => {
println!("{}", e); println!("{}", e);
}, }
} }
} }

@ -20,17 +20,24 @@ const SIZEOF_C_UINT: libc::c_ulong = 4;
#[cfg(any(target_os = "freebsd", target_os = "netbsd"))] #[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
const SIZEOF_C_LONG: libc::c_int = 8; 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 BIOCSETIF: libc::c_ulong =
pub const BIOCIMMEDIATE: libc::c_ulong = IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 112; IOC_IN | ((SIZEOF_IFREQ & IOCPARM_MASK) << 16usize) | (('B' as libc::c_ulong) << 8usize) | 108;
pub const BIOCGDLT: libc::c_ulong = IOC_OUT | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 106; pub const BIOCIMMEDIATE: libc::c_ulong =
pub const BIOCSBLEN: libc::c_ulong = IOC_INOUT | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 102; IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 112;
pub const BIOCSHDRCMPLT: libc::c_ulong = IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 117; 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")] #[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")] #[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; pub const DLT_NULL: libc::c_uint = 0;
@ -50,7 +57,13 @@ pub struct ifreq {
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 struct sockaddr_dl {
pub sdl_len: libc::c_uchar, pub sdl_len: libc::c_uchar,
pub sdl_family: libc::c_uchar, pub sdl_family: libc::c_uchar,
@ -65,7 +78,10 @@ pub struct sockaddr_dl {
#[cfg(any( #[cfg(any(
target_os = "freebsd", target_os = "freebsd",
target_os = "netbsd", 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 windows
))] ))]
#[repr(C)] #[repr(C)]
@ -83,7 +99,10 @@ pub struct timeval32 {
#[cfg(any( #[cfg(any(
target_os = "openbsd", 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)] #[repr(C)]
pub struct bpf_hdr { pub struct bpf_hdr {

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

@ -1,6 +1,6 @@
use super::binding; use super::binding;
use crate::socket::{DataLinkReceiver, DataLinkSender};
use crate::interface::Interface; use crate::interface::Interface;
use crate::socket::{DataLinkReceiver, DataLinkSender};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::ffi::CString; 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() }, fd_set: unsafe { mem::zeroed() },
write_buffer: vec![0; config.write_buffer_size], write_buffer: vec![0; config.write_buffer_size],
loopback: loopback, loopback: loopback,
timeout: config timeout: config.write_timeout.map(|to| duration_to_timespec(to)),
.write_timeout
.map(|to| duration_to_timespec(to)),
}); });
unsafe { unsafe {
libc::FD_ZERO(&mut sender.fd_set as *mut libc::fd_set); 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() }, fd_set: unsafe { mem::zeroed() },
read_buffer: vec![0; allocated_read_buffer_size], read_buffer: vec![0; allocated_read_buffer_size],
loopback: loopback, loopback: loopback,
timeout: config timeout: config.read_timeout.map(|to| duration_to_timespec(to)),
.read_timeout
.map(|to| duration_to_timespec(to)),
packets: VecDeque::with_capacity(allocated_read_buffer_size / 64), packets: VecDeque::with_capacity(allocated_read_buffer_size / 64),
}); });
unsafe { unsafe {
@ -245,7 +241,6 @@ impl DataLinkSender for DataLinkSenderImpl {
if len >= self.write_buffer.len() { if len >= self.write_buffer.len() {
None None
} else { } else {
let offset = if self.loopback { let offset = if self.loopback {
ETHERNET_HEADER_SIZE ETHERNET_HEADER_SIZE
} else { } 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 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_ROUTE: &str = "/proc/net/route";
const PATH_PROC_NET_ARP: &str = "/proc/net/arp"; 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> { pub fn get_default_gateway(interface_name: String) -> Result<Gateway, String> {
match super::send_udp_packet() { match super::send_udp_packet() {
Ok(_) => {}, Ok(_) => {}
Err(e) => return Err(format!("Failed to send UDP packet {}", e)), Err(e) => return Err(format!("Failed to send UDP packet {}", e)),
} }
let route_data = read_to_string(PATH_PROC_NET_ROUTE); 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; pub(crate) mod unix;
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
pub(crate) mod linux; pub(crate) mod linux;
use crate::interface::{self, Interface, MacAddr};
use std::net::{IpAddr, Ipv4Addr}; use std::net::{IpAddr, Ipv4Addr};
use crate::interface::{self, MacAddr, Interface};
/// Structure of default Gateway information /// Structure of default Gateway information
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -41,14 +47,14 @@ pub fn get_default_gateway() -> Result<Gateway, String> {
return Ok(gateway); return Ok(gateway);
} }
} }
}, }
IpAddr::V6(local_ipv6) => { IpAddr::V6(local_ipv6) => {
if iface.ipv6.iter().any(|x| x.addr == local_ipv6) { if iface.ipv6.iter().any(|x| x.addr == local_ipv6) {
if let Some(gateway) = iface.gateway { if let Some(gateway) = iface.gateway {
return Ok(gateway); return Ok(gateway);
} }
} }
}, }
} }
} }
Err(String::from("Default Gateway not found")) Err(String::from("Default Gateway not found"))

@ -1,6 +1,6 @@
use std::time::{Duration, Instant};
use crate::socket;
use super::Gateway; use super::Gateway;
use crate::socket;
use std::time::{Duration, Instant};
const TIMEOUT: u64 = 3000; 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)) => { Ok(socket::Channel::Ethernet(etx, erx)) => {
_tx = etx; _tx = etx;
rx = erx; rx = erx;
}, }
Err(e) => return Err(format!("Failed to create channel {}", e)), Err(e) => return Err(format!("Failed to create channel {}", e)),
} }
match super::send_udp_packet() { match super::send_udp_packet() {
@ -30,13 +30,11 @@ pub fn get_default_gateway(interface_name: String) -> Result<Gateway, String> {
} }
loop { loop {
match rx.next() { match rx.next() {
Ok(frame) => { Ok(frame) => match socket::packet::parse_frame(frame) {
match socket::packet::parse_frame(frame){
Ok(gateway) => { Ok(gateway) => {
return Ok(gateway); return Ok(gateway);
},
Err(_) => {},
} }
Err(_) => {}
}, },
Err(_) => {} Err(_) => {}
} }

@ -1,6 +1,6 @@
use crate::interface::InterfaceType;
use std::collections::HashMap; use std::collections::HashMap;
use system_configuration::network_configuration; use system_configuration::network_configuration;
use crate::interface::InterfaceType;
fn get_if_type_from_id(type_id: String) -> InterfaceType { fn get_if_type_from_id(type_id: String) -> InterfaceType {
match type_id.as_str() { match type_id.as_str() {

@ -114,7 +114,13 @@ impl InterfaceType {
} }
} }
/// Returns OS-specific value of 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 { pub fn value(&self) -> u32 {
// TODO // TODO
match *self { match *self {
@ -168,7 +174,9 @@ impl TryFrom<u32> for InterfaceType {
x if x == InterfaceType::PrimaryIsdn.value() => Ok(InterfaceType::PrimaryIsdn), x if x == InterfaceType::PrimaryIsdn.value() => Ok(InterfaceType::PrimaryIsdn),
x if x == InterfaceType::Ppp.value() => Ok(InterfaceType::Ppp), x if x == InterfaceType::Ppp.value() => Ok(InterfaceType::Ppp),
x if x == InterfaceType::Loopback.value() => Ok(InterfaceType::Loopback), 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::Slip.value() => Ok(InterfaceType::Slip),
x if x == InterfaceType::Atm.value() => Ok(InterfaceType::Atm), x if x == InterfaceType::Atm.value() => Ok(InterfaceType::Atm),
x if x == InterfaceType::GenericModem.value() => Ok(InterfaceType::GenericModem), 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::AsymmetricDsl.value() => Ok(InterfaceType::AsymmetricDsl),
x if x == InterfaceType::RateAdaptDsl.value() => Ok(InterfaceType::RateAdaptDsl), x if x == InterfaceType::RateAdaptDsl.value() => Ok(InterfaceType::RateAdaptDsl),
x if x == InterfaceType::SymmetricDsl.value() => Ok(InterfaceType::SymmetricDsl), 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::IPOverAtm.value() => Ok(InterfaceType::IPOverAtm),
x if x == InterfaceType::GigabitEthernet.value() => Ok(InterfaceType::GigabitEthernet), x if x == InterfaceType::GigabitEthernet.value() => Ok(InterfaceType::GigabitEthernet),
x if x == InterfaceType::Tunnel.value() => Ok(InterfaceType::Tunnel), x if x == InterfaceType::Tunnel.value() => Ok(InterfaceType::Tunnel),
x if x == InterfaceType::MultiRateSymmetricDsl.value() => Ok(InterfaceType::MultiRateSymmetricDsl), x if x == InterfaceType::MultiRateSymmetricDsl.value() => {
x if x == InterfaceType::HighPerformanceSerialBus.value() => Ok(InterfaceType::HighPerformanceSerialBus), 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::Wman.value() => Ok(InterfaceType::Wman),
x if x == InterfaceType::Wwanpp.value() => Ok(InterfaceType::Wwanpp), x if x == InterfaceType::Wwanpp.value() => Ok(InterfaceType::Wwanpp),
x if x == InterfaceType::Wwanpp2.value() => Ok(InterfaceType::Wwanpp2), x if x == InterfaceType::Wwanpp2.value() => Ok(InterfaceType::Wwanpp2),

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

@ -1,16 +1,19 @@
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 core::ffi::c_void;
use libc::{c_char, strlen, wchar_t, wcslen}; use libc::{c_char, strlen, wchar_t, wcslen};
use memalloc::{allocate, deallocate}; 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::gateway::Gateway;
use crate::interface::{Interface, InterfaceType, MacAddr};
use crate::ip::{Ipv4Net, Ipv6Net};
#[cfg(target_endian = "little")] #[cfg(target_endian = "little")]
fn htonl(val: u32) -> u32 { fn htonl(val: u32) -> u32 {
@ -31,7 +34,14 @@ fn get_mac_through_arp(src_ip: Ipv4Addr, dst_ip: Ipv4Addr) -> MacAddr {
let dst_ip_int: u32 = htonl(u32::from(dst_ip)); let dst_ip_int: u32 = htonl(u32::from(dst_ip));
let mut out_buf_len: u32 = 6; let mut out_buf_len: u32 = 6;
let mut target_mac_addr: [u8; 6] = [0; 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 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 { if res == NO_ERROR.0 {
MacAddr::new(target_mac_addr) MacAddr::new(target_mac_addr)
} else { } else {
@ -49,7 +59,15 @@ pub fn interfaces() -> Vec<Interface> {
let mut ret_val; let mut ret_val;
loop { loop {
let old_size = dwsize as usize; 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 { if ret_val != ERROR_BUFFER_OVERFLOW.0 || retries <= 0 {
break; break;
} }
@ -63,11 +81,11 @@ pub fn interfaces() -> Vec<Interface> {
while !cur.is_null() { while !cur.is_null() {
let if_type: u32 = unsafe { (*cur).IfType }; let if_type: u32 = unsafe { (*cur).IfType };
match InterfaceType::try_from(if_type) { match InterfaceType::try_from(if_type) {
Ok(_) => {}, Ok(_) => {}
Err(_) => { Err(_) => {
cur = unsafe { (*cur).Next }; cur = unsafe { (*cur).Next };
continue; continue;
}, }
} }
// Index // Index
let anon1 = unsafe { (*cur).Anonymous1 }; let anon1 = unsafe { (*cur).Anonymous1 };
@ -92,7 +110,9 @@ pub fn interfaces() -> Vec<Interface> {
let desc_slice = unsafe { std::slice::from_raw_parts(p_desc, desc_len) }; let desc_slice = unsafe { std::slice::from_raw_parts(p_desc, desc_len) };
let description = String::from_utf16(desc_slice).unwrap(); let description = String::from_utf16(desc_slice).unwrap();
// MAC address // 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); let mac_addr: MacAddr = MacAddr::new(mac_addr_arr);
// TransmitLinkSpeed (bits per second) // TransmitLinkSpeed (bits per second)
let transmit_speed = unsafe { (*cur).TransmitLinkSpeed }; let transmit_speed = unsafe { (*cur).TransmitLinkSpeed };
@ -156,7 +176,7 @@ pub fn interfaces() -> Vec<Interface> {
} else { } else {
None None
} }
}, }
None => None, None => None,
}; };
let interface: Interface = Interface { let interface: Interface = Interface {

@ -97,11 +97,15 @@ fn ipv6_netmask_to_prefix(netmask: Ipv6Addr) -> u8 {
} }
fn prefix_to_ipv4_netmask(prefix_len: u8) -> Ipv4Addr { 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) Ipv4Addr::from(netmask_u32)
} }
fn prefix_to_ipv6_netmask(prefix_len: u8) -> Ipv6Addr { 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) Ipv6Addr::from(netmask_u128)
} }

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

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

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

@ -27,7 +27,8 @@ pub fn sockaddr_to_addr(storage: &SockAddrStorage, len: usize) -> io::Result<Soc
let o2 = (ip >> 16) as u8; let o2 = (ip >> 16) as u8;
let o3 = (ip >> 8) as u8; let o3 = (ip >> 8) as u8;
let o4 = ip 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)) Ok(SocketAddr::V4(sockaddrv4))
} }
AF_INET6 => { AF_INET6 => {
@ -51,7 +52,7 @@ pub fn sockaddr_to_addr(storage: &SockAddrStorage, len: usize) -> io::Result<Soc
storage.sin6_scope_id, 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