Merge pull request #23 from link2xt/cargo-fmt

Run `cargo fmt` and add GitHub Actions check
main
shellrow 2 years ago committed by GitHub
commit 07a3fce1ea
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. 10
      src/interface/linux.rs
  11. 2
      src/interface/macos.rs
  12. 53
      src/interface/mod.rs
  13. 24
      src/interface/types.rs
  14. 94
      src/interface/unix.rs
  15. 48
      src/interface/windows.rs
  16. 8
      src/ip.rs
  17. 30
      src/lib.rs
  18. 13
      src/socket/mod.rs
  19. 26
      src/socket/packet.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

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

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

@ -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;
@ -50,7 +57,13 @@ pub struct ifreq {
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 {

@ -7,4 +7,3 @@ pub use self::binding::*;
mod unix;
#[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)]
@ -41,14 +47,14 @@ 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"))

@ -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,13 +30,11 @@ pub fn get_default_gateway(interface_name: String) -> Result<Gateway, String> {
}
loop {
match rx.next() {
Ok(frame) => {
match socket::packet::parse_frame(frame){
Ok(frame) => match socket::packet::parse_frame(frame) {
Ok(gateway) => {
return Ok(gateway);
},
Err(_) => {},
}
Err(_) => {}
},
Err(_) => {}
}

@ -1,6 +1,6 @@
use crate::interface::InterfaceType;
use std::convert::TryFrom;
use std::fs::read_to_string;
use crate::interface::InterfaceType;
pub fn get_interface_type(if_name: String) -> InterfaceType {
let if_type_path: String = format!("/sys/class/net/{}/type", if_name);
@ -11,12 +11,12 @@ pub fn get_interface_type(if_name: String) -> InterfaceType {
match if_type_string.parse::<u32>() {
Ok(if_type) => {
return InterfaceType::try_from(if_type).unwrap_or(InterfaceType::Unknown);
},
}
Err(_) => {
return InterfaceType::Unknown;
}
}
},
}
Err(_) => {
return InterfaceType::Unknown;
}
@ -33,12 +33,12 @@ pub fn get_interface_speed(if_name: String) -> Option<u64> {
Ok(if_speed) => {
// Convert Mbps to bps
return Some(if_speed * 1000000);
},
}
Err(_) => {
return None;
}
}
},
}
Err(_) => {
return None;
}

@ -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() {

@ -4,9 +4,25 @@ pub use self::shared::*;
mod types;
pub use self::types::*;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "ios", target_os = "android"))]
#[cfg(any(
target_os = "linux",
target_os = "macos",
target_os = "openbsd",
target_os = "freebsd",
target_os = "netbsd",
target_os = "ios",
target_os = "android"
))]
mod unix;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "ios", target_os = "android"))]
#[cfg(any(
target_os = "linux",
target_os = "macos",
target_os = "openbsd",
target_os = "freebsd",
target_os = "netbsd",
target_os = "ios",
target_os = "android"
))]
use self::unix::*;
#[cfg(target_os = "windows")]
@ -20,9 +36,9 @@ mod linux;
#[cfg(any(target_os = "macos", target_os = "ios"))]
mod macos;
use std::net::IpAddr;
use crate::gateway::Gateway;
use crate::ip::{Ipv4Net, Ipv6Net};
use crate::gateway::{Gateway};
use std::net::IpAddr;
/// Structure of MAC address
#[derive(Clone, Debug)]
@ -31,7 +47,9 @@ pub struct MacAddr(u8, u8, u8, u8, u8, u8);
impl MacAddr {
/// Construct a new MacAddr instance from the given octets
pub fn new(octets: [u8; 6]) -> MacAddr {
MacAddr(octets[0], octets[1], octets[2], octets[3], octets[4], octets[5])
MacAddr(
octets[0], octets[1], octets[2], octets[3], octets[4], octets[5],
)
}
/// Returns an array of MAC address octets
pub fn octets(&self) -> [u8; 6] {
@ -39,7 +57,10 @@ impl MacAddr {
}
/// Return a formatted string of MAC address
pub fn address(&self) -> String {
format!("{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", self.0,self.1,self.2,self.3,self.4,self.5)
format!(
"{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
self.0, self.1, self.2, self.3, self.4, self.5
)
}
/// Construct an all-zero MacAddr instance
pub fn zero() -> MacAddr {
@ -48,7 +69,7 @@ impl MacAddr {
/// Construct a new MacAddr instance from a colon-separated string of hex format
pub fn from_hex_format(hex_mac_addr: &str) -> MacAddr {
if hex_mac_addr.len() != 17 {
return MacAddr(0,0,0,0,0,0)
return MacAddr(0, 0, 0, 0, 0, 0);
}
let fields: Vec<&str> = hex_mac_addr.split(":").collect();
let o1: u8 = u8::from_str_radix(&fields[0], 0x10).unwrap_or(0);
@ -63,7 +84,11 @@ impl MacAddr {
impl std::fmt::Display for MacAddr {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let _ = write!(f,"{:<02x}:{:<02x}:{:<02x}:{:<02x}:{:<02x}:{:<02x}",self.0,self.1,self.2,self.3,self.4,self.5);
let _ = write!(
f,
"{:<02x}:{:<02x}:{:<02x}:{:<02x}:{:<02x}:{:<02x}",
self.0, self.1, self.2, self.3, self.4, self.5
);
Ok(())
}
}
@ -110,12 +135,12 @@ pub fn get_default_interface() -> Result<Interface, String> {
if iface.ipv4.iter().any(|x| x.addr == local_ipv4) {
return Ok(iface);
}
},
}
IpAddr::V6(local_ipv6) => {
if iface.ipv6.iter().any(|x| x.addr == local_ipv6) {
return Ok(iface);
}
},
}
}
}
Err(String::from("Default Interface not found"))
@ -134,12 +159,12 @@ pub fn get_default_interface_index() -> Option<u32> {
if iface.ipv4.iter().any(|x| x.addr == local_ipv4) {
return Some(iface.index);
}
},
}
IpAddr::V6(local_ipv6) => {
if iface.ipv6.iter().any(|x| x.addr == local_ipv6) {
return Some(iface.index);
}
},
}
}
}
None
@ -158,12 +183,12 @@ pub fn get_default_interface_name() -> Option<String> {
if iface.ipv4.iter().any(|x| x.addr == local_ipv4) {
return Some(iface.name);
}
},
}
IpAddr::V6(local_ipv6) => {
if iface.ipv6.iter().any(|x| x.addr == local_ipv6) {
return Some(iface.name);
}
},
}
}
}
None

@ -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),

@ -1,16 +1,16 @@
use super::Interface;
use super::MacAddr;
use crate::sys;
use crate::gateway;
use crate::ip::{Ipv4Net, Ipv6Net};
use crate::sys;
use crate::interface::InterfaceType;
use libc;
use std::ffi::{CStr, CString};
use std::mem::{self, MaybeUninit};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::os::raw::c_char;
use std::str::from_utf8_unchecked;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use crate::interface::InterfaceType;
#[cfg(any(target_os = "openbsd", target_os = "freebsd", target_os = "netbsd"))]
pub fn interfaces() -> Vec<Interface> {
@ -26,21 +26,21 @@ pub fn interfaces() -> Vec<Interface> {
match gateway::unix::get_default_gateway(iface.name.clone()) {
Ok(gateway) => {
iface.gateway = Some(gateway);
},
Err(_) => {},
}
Err(_) => {}
}
}
}
},
IpAddr::V6(local_ipv6) => {
if iface.ipv6.iter().any(|x| x.addr == local_ipv6) {
match gateway::unix::get_default_gateway(iface.name.clone()) {
Ok(gateway) => {
iface.gateway = Some(gateway);
},
Err(_) => {},
}
Err(_) => {}
}
}
}
},
}
}
interfaces
@ -64,21 +64,21 @@ pub fn interfaces() -> Vec<Interface> {
match gateway::unix::get_default_gateway(iface.name.clone()) {
Ok(gateway) => {
iface.gateway = Some(gateway);
},
Err(_) => {},
}
Err(_) => {}
}
}
}
},
IpAddr::V6(local_ipv6) => {
if iface.ipv6.iter().any(|x| x.addr == local_ipv6) {
match gateway::unix::get_default_gateway(iface.name.clone()) {
Ok(gateway) => {
iface.gateway = Some(gateway);
},
Err(_) => {},
}
Err(_) => {}
}
}
}
},
}
}
interfaces
@ -104,21 +104,21 @@ pub fn interfaces() -> Vec<Interface> {
match gateway::linux::get_default_gateway(iface.name.clone()) {
Ok(gateway) => {
iface.gateway = Some(gateway);
},
Err(_) => {},
}
Err(_) => {}
}
}
}
},
IpAddr::V6(local_ipv6) => {
if iface.ipv6.iter().any(|x| x.addr == local_ipv6) {
match gateway::linux::get_default_gateway(iface.name.clone()) {
Ok(gateway) => {
iface.gateway = Some(gateway);
},
Err(_) => {},
}
Err(_) => {}
}
}
}
},
}
}
interfaces
@ -144,10 +144,8 @@ fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Opti
(Some(mac), None)
} else {
let addr = sys::sockaddr_to_addr(
mem::transmute(sa),
mem::size_of::<libc::sockaddr_storage>(),
);
let addr =
sys::sockaddr_to_addr(mem::transmute(sa), mem::size_of::<libc::sockaddr_storage>());
match addr {
Ok(SocketAddr::V4(sa)) => (None, Some(IpAddr::V4(*sa.ip()))),
@ -158,7 +156,13 @@ fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Opti
}
}
#[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"
))]
fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Option<IpAddr>) {
use crate::bpf;
use std::net::SocketAddr;
@ -180,10 +184,8 @@ fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Opti
(Some(mac), None)
} else {
let addr = sys::sockaddr_to_addr(
mem::transmute(sa),
mem::size_of::<libc::sockaddr_storage>(),
);
let addr =
sys::sockaddr_to_addr(mem::transmute(sa), mem::size_of::<libc::sockaddr_storage>());
match addr {
Ok(SocketAddr::V4(sa)) => (None, Some(IpAddr::V4(*sa.ip()))),
@ -215,30 +217,26 @@ pub fn unix_interfaces() -> Vec<Interface> {
match ip {
IpAddr::V4(ipv4) => {
let netmask: Ipv4Addr = match netmask {
Some(netmask) => {
match netmask {
Some(netmask) => match netmask {
IpAddr::V4(netmask) => netmask,
IpAddr::V6(_) => Ipv4Addr::UNSPECIFIED,
}
},
None => Ipv4Addr::UNSPECIFIED,
};
let ipv4_net: Ipv4Net = Ipv4Net::new_with_netmask(ipv4, netmask);
ini_ipv4.push(ipv4_net);
},
}
IpAddr::V6(ipv6) => {
let netmask: Ipv6Addr = match netmask {
Some(netmask) => {
match netmask {
Some(netmask) => match netmask {
IpAddr::V4(_) => Ipv6Addr::UNSPECIFIED,
IpAddr::V6(netmask) => netmask,
}
},
None => Ipv6Addr::UNSPECIFIED,
};
let ipv6_net: Ipv6Net = Ipv6Net::new_with_netmask(ipv6, netmask);
ini_ipv6.push(ipv6_net);
},
}
}
}
let interface: Interface = Interface {
@ -265,30 +263,26 @@ pub fn unix_interfaces() -> Vec<Interface> {
match ip {
IpAddr::V4(ipv4) => {
let netmask: Ipv4Addr = match netmask {
Some(netmask) => {
match netmask {
Some(netmask) => match netmask {
IpAddr::V4(netmask) => netmask,
IpAddr::V6(_) => Ipv4Addr::UNSPECIFIED,
}
},
None => Ipv4Addr::UNSPECIFIED,
};
let ipv4_net: Ipv4Net = Ipv4Net::new_with_netmask(ipv4, netmask);
iface.ipv4.push(ipv4_net);
},
}
IpAddr::V6(ipv6) => {
let netmask: Ipv6Addr = match netmask {
Some(netmask) => {
match netmask {
Some(netmask) => match netmask {
IpAddr::V4(_) => Ipv6Addr::UNSPECIFIED,
IpAddr::V6(netmask) => netmask,
}
},
None => Ipv6Addr::UNSPECIFIED,
};
let ipv6_net: Ipv6Net = Ipv6Net::new_with_netmask(ipv6, netmask);
iface.ipv6.push(ipv6_net);
},
}
}
}
found = true;
@ -299,10 +293,14 @@ pub fn unix_interfaces() -> Vec<Interface> {
}
addr = addr_ref.ifa_next;
}
unsafe{ libc::freeifaddrs(addrs); }
unsafe {
libc::freeifaddrs(addrs);
}
for iface in &mut ifaces {
let name = CString::new(iface.name.as_bytes()).unwrap();
unsafe { iface.index = libc::if_nametoindex(name.as_ptr()); }
unsafe {
iface.index = libc::if_nametoindex(name.as_ptr());
}
}
ifaces
}

@ -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 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 {
@ -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 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 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 {
@ -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;
}
@ -63,11 +81,11 @@ pub fn interfaces() -> Vec<Interface> {
while !cur.is_null() {
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 };
@ -92,7 +110,9 @@ pub fn interfaces() -> Vec<Interface> {
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 };
@ -156,7 +176,7 @@ pub fn interfaces() -> Vec<Interface> {
} else {
None
}
},
}
None => None,
};
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 {
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;

@ -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(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(())
}

@ -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