Refactoring for unix-like OS

main
shellrow 3 years ago
parent b3172f19e1
commit 7ad6493c88
  1. 2
      Cargo.toml
  2. 34
      src/bpf/binding.rs
  3. 1
      src/bpf/unix.rs
  4. 24
      src/gateway/linux.rs
  5. 13
      src/gateway/mod.rs
  6. 67
      src/gateway/unix.rs
  7. 0
      src/gateway/windows.rs
  8. 61
      src/interface/mod.rs
  9. 18
      src/interface/shared.rs
  10. 67
      src/interface/unix.rs
  11. 215
      src/interface/windows.rs
  12. 1
      src/lib.rs
  13. 40
      src/socket/mod.rs
  14. 1
      src/socket/packet.rs
  15. 16
      src/socket/unix.rs

@ -11,8 +11,6 @@ categories = ["network-programming"]
license = "MIT" license = "MIT"
[target.'cfg(not(windows))'.dependencies] [target.'cfg(not(windows))'.dependencies]
pnet_packet = "0.28"
pnet_datalink = "0.28"
libc = "0.2" libc = "0.2"
[target.'cfg(windows)'.dependencies.windows] [target.'cfg(windows)'.dependencies.windows]

@ -1,11 +1,9 @@
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
#![allow(non_snake_case)] #![allow(non_snake_case)]
#![allow(dead_code)]
extern crate libc; use libc;
pub type SockAddr = libc::sockaddr; pub type SockAddr = libc::sockaddr;
pub const AF_LINK: libc::c_int = 18; pub const AF_LINK: libc::c_int = 18;
const IF_NAMESIZE: usize = 16; const IF_NAMESIZE: usize = 16;
@ -16,39 +14,29 @@ const IOC_INOUT: libc::c_ulong = IOC_IN | IOC_OUT;
const IOCPARM_SHIFT: libc::c_ulong = 13; const IOCPARM_SHIFT: libc::c_ulong = 13;
const IOCPARM_MASK: libc::c_ulong = (1 << (IOCPARM_SHIFT as usize)) - 1; const IOCPARM_MASK: libc::c_ulong = (1 << (IOCPARM_SHIFT as usize)) - 1;
const SIZEOF_TIMEVAL: libc::c_ulong = 16;
const SIZEOF_IFREQ: libc::c_ulong = 32; const SIZEOF_IFREQ: libc::c_ulong = 32;
const SIZEOF_C_UINT: libc::c_ulong = 4; 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 = pub const BIOCSETIF: libc::c_ulong = IOC_IN | ((SIZEOF_IFREQ & IOCPARM_MASK) << 16usize) | (('B' as libc::c_ulong) << 8usize) | 108;
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 BIOCIMMEDIATE: libc::c_ulong = pub const BIOCGDLT: libc::c_ulong = IOC_OUT | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 106;
IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 112; pub const BIOCSBLEN: libc::c_ulong = IOC_INOUT | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 102;
pub const BIOCGBLEN: libc::c_ulong = pub const BIOCSHDRCMPLT: libc::c_ulong = IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 117;
IOC_OUT | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 102;
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 BIOCSRTIMEOUT: libc::c_ulong =
IOC_IN | ((SIZEOF_TIMEVAL & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 109;
#[cfg(target_os = "freebsd")] #[cfg(target_os = "freebsd")]
pub const BIOCFEEDBACK: libc::c_ulong = pub const BIOCFEEDBACK: libc::c_ulong = IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 124;
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 = pub const BIOCFEEDBACK: libc::c_ulong = IOC_IN | ((SIZEOF_C_UINT & IOCPARM_MASK) << 16) | (('B' as libc::c_ulong) << 8) | 125;
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;
#[cfg(any(target_os = "freebsd", target_os = "netbsd"))] #[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
const BPF_ALIGNMENT: libc::c_int = SIZEOF_C_LONG; const BPF_ALIGNMENT: libc::c_int = SIZEOF_C_LONG;
#[cfg(any(target_os = "openbsd", target_os = "macos", target_os = "ios", windows))] #[cfg(any(target_os = "openbsd", target_os = "macos", target_os = "ios", windows))]
const BPF_ALIGNMENT: libc::c_int = 4; const BPF_ALIGNMENT: libc::c_int = 4;

@ -84,6 +84,7 @@ pub fn channel(interface_name: String, config: Config) -> io::Result<crate::sock
} }
} }
#[allow(temporary_cstring_as_ptr)]
#[cfg(any(target_os = "openbsd", target_os = "macos", target_os = "ios"))] #[cfg(any(target_os = "openbsd", target_os = "macos", target_os = "ios"))]
fn get_fd(attempts: usize) -> libc::c_int { fn get_fd(attempts: usize) -> libc::c_int {
for i in 0..attempts { for i in 0..attempts {

@ -0,0 +1,24 @@
use std::net::UdpSocket;
use super::Gateway;
fn send_udp_packet() -> Result<(), String> {
let buf = [0u8; 0];
let socket = match UdpSocket::bind("0.0.0.0:0") {
Ok(s) => s,
Err(e) => return Err(format!("Failed to create UDP socket {}", e)),
};
let dst: &str = "1.1.1.1:80";
match socket.set_ttl(1) {
Ok(_) => (),
Err(e) => return Err(format!("Failed to set TTL {}", e)),
}
match socket.send_to(&buf, dst) {
Ok(_) => (),
Err(e) => return Err(format!("Failed to send data {}", e)),
}
Ok(())
}
pub fn get_default_gateway(interface_name: String) -> Result<Gateway, String> {
Err(String::new())
}

@ -1,6 +1,11 @@
#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "ios"))]
pub mod unix;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod linux;
use std::net::{IpAddr, Ipv4Addr}; use std::net::{IpAddr, Ipv4Addr};
use crate::interface::{MacAddr, Interface}; use crate::interface::{self, MacAddr, Interface};
use crate::os;
/// Structure of default Gateway information /// Structure of default Gateway information
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -20,11 +25,11 @@ impl Gateway {
/// Get default Gateway /// Get default Gateway
pub fn get_default_gateway() -> Result<Gateway, String> { pub fn get_default_gateway() -> Result<Gateway, String> {
let local_ip: IpAddr = match os::get_local_ipaddr(){ let local_ip: IpAddr = match interface::get_local_ipaddr(){
Some(local_ip) => local_ip, Some(local_ip) => local_ip,
None => return Err(String::from("Local IP address not found")), None => return Err(String::from("Local IP address not found")),
}; };
let interfaces: Vec<Interface> = os::interfaces(); let interfaces: Vec<Interface> = interface::get_interfaces();
for iface in interfaces { for iface in interfaces {
match local_ip { match local_ip {
IpAddr::V4(local_ipv4) => { IpAddr::V4(local_ipv4) => {

@ -0,0 +1,67 @@
use std::net::UdpSocket;
use std::time::{Duration, Instant};
use crate::socket;
use super::Gateway;
const TIMEOUT: u64 = 3000;
fn send_udp_packet() -> Result<(), String> {
let buf = [0u8; 0];
let socket = match UdpSocket::bind("0.0.0.0:0") {
Ok(s) => s,
Err(e) => return Err(format!("Failed to create UDP socket {}", e)),
};
let dst: &str = "1.1.1.1:80";
match socket.set_ttl(1) {
Ok(_) => (),
Err(e) => return Err(format!("Failed to set TTL {}", e)),
}
match socket.send_to(&buf, dst) {
Ok(_) => (),
Err(e) => return Err(format!("Failed to send data {}", e)),
}
Ok(())
}
pub fn get_default_gateway(interface_name: String) -> Result<Gateway, String> {
let timeout = Duration::from_millis(TIMEOUT);
let start_time = Instant::now();
let config = socket::Config {
write_buffer_size: 4096,
read_buffer_size: 4096,
read_timeout: None,
write_timeout: None,
channel_type: socket::ChannelType::Layer2,
bpf_fd_attempts: 1000,
promiscuous: false,
};
let (mut _tx, mut rx) = match socket::channel(interface_name, config) {
Ok(socket::Channel::Ethernet(tx, rx)) => (tx, rx),
Err(e) => panic!("Failed to create channel {}", e),
};
match send_udp_packet() {
Ok(_) => (),
Err(e) => return Err(format!("Failed to send UDP packet {}", e)),
}
loop {
match rx.next() {
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{
match send_udp_packet() {
Ok(_) => (),
Err(e) => return Err(format!("Failed to send UDP packet {}", e)),
}
}
}
}

@ -1,9 +1,18 @@
#[cfg(not(target_os="windows"))] mod shared;
pub use self::shared::*;
#[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; 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"))]
use self::unix::*;
#[cfg(target_os = "windows")]
mod windows;
#[cfg(target_os = "windows")]
use self::windows::*;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use crate::gateway::{Gateway}; use crate::gateway::{Gateway};
use crate::os;
/// Structure of MAC address /// Structure of MAC address
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -48,11 +57,11 @@ pub struct Interface {
/// Get default Network Interface /// Get default Network Interface
pub fn get_default_interface() -> Result<Interface, String> { pub fn get_default_interface() -> Result<Interface, String> {
let local_ip: IpAddr = match os::get_local_ipaddr(){ let local_ip: IpAddr = match get_local_ipaddr(){
Some(local_ip) => local_ip, Some(local_ip) => local_ip,
None => return Err(String::from("Local IP address not found")), None => return Err(String::from("Local IP address not found")),
}; };
let interfaces: Vec<Interface> = os::interfaces(); let interfaces: Vec<Interface> = interfaces();
for iface in interfaces { for iface in interfaces {
match local_ip { match local_ip {
IpAddr::V4(local_ipv4) => { IpAddr::V4(local_ipv4) => {
@ -72,17 +81,55 @@ pub fn get_default_interface() -> Result<Interface, String> {
/// Get default Network Interface index /// Get default Network Interface index
pub fn get_default_interface_index() -> Option<u32> { pub fn get_default_interface_index() -> Option<u32> {
os::default_interface_index() let local_ip: IpAddr = match get_local_ipaddr(){
Some(local_ip) => local_ip,
None => return None,
};
let interfaces = interfaces();
for iface in interfaces {
match local_ip {
IpAddr::V4(local_ipv4) => {
if iface.ipv4.contains(&local_ipv4) {
return Some(iface.index);
}
},
IpAddr::V6(local_ipv6) => {
if iface.ipv6.contains(&local_ipv6) {
return Some(iface.index);
}
},
}
}
None
} }
/// Get default Network Interface name /// Get default Network Interface name
pub fn get_default_interface_name() -> Option<String> { pub fn get_default_interface_name() -> Option<String> {
os::default_interface_name() let local_ip: IpAddr = match get_local_ipaddr(){
Some(local_ip) => local_ip,
None => return None,
};
let interfaces = interfaces();
for iface in interfaces {
match local_ip {
IpAddr::V4(local_ipv4) => {
if iface.ipv4.contains(&local_ipv4) {
return Some(iface.name);
}
},
IpAddr::V6(local_ipv6) => {
if iface.ipv6.contains(&local_ipv6) {
return Some(iface.name);
}
},
}
}
None
} }
/// Get a list of available Network Interfaces /// Get a list of available Network Interfaces
pub fn get_interfaces() -> Vec<Interface> { pub fn get_interfaces() -> Vec<Interface> {
os::interfaces() interfaces()
} }
#[cfg(test)] #[cfg(test)]

@ -0,0 +1,18 @@
use std::net::{IpAddr, UdpSocket};
pub fn get_local_ipaddr() -> Option<IpAddr> {
let socket = match UdpSocket::bind("0.0.0.0:0") {
Ok(s) => s,
Err(_) => return None,
};
match socket.connect("1.1.1.1:80") {
Ok(()) => (),
Err(_) => return None,
};
match socket.local_addr() {
Ok(addr) => return Some(addr.ip()),
Err(_) => return None,
};
}

@ -1,6 +1,7 @@
use super::Interface; use super::Interface;
use super::MacAddr; use super::MacAddr;
use crate::sys; use crate::sys;
use crate::gateway;
use libc; use libc;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
@ -9,8 +10,72 @@ use std::os::raw::c_char;
use std::str::from_utf8_unchecked; use std::str::from_utf8_unchecked;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "ios"))]
pub fn interfaces() -> Vec<Interface> { pub fn interfaces() -> Vec<Interface> {
unix_interfaces() let mut interfaces: Vec<Interface> = unix_interfaces();
let local_ip: IpAddr = match super::get_local_ipaddr(){
Some(local_ip) => local_ip,
None => return interfaces,
};
for iface in &mut interfaces {
match local_ip {
IpAddr::V4(local_ipv4) => {
if iface.ipv4.contains(&local_ipv4) {
match gateway::unix::get_default_gateway(iface.name.clone()) {
Ok(gateway) => {
iface.gateway = Some(gateway);
},
Err(_) => {},
}
}
},
IpAddr::V6(local_ipv6) => {
if iface.ipv6.contains(&local_ipv6) {
match gateway::unix::get_default_gateway(iface.name.clone()) {
Ok(gateway) => {
iface.gateway = Some(gateway);
},
Err(_) => {},
}
}
},
}
}
interfaces
}
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn interfaces() -> Vec<Interface> {
let mut interfaces: Vec<Interface> = unix_interfaces();
let local_ip: IpAddr = match super::get_local_ipaddr(){
Some(local_ip) => local_ip,
None => return interfaces,
};
for iface in &mut interfaces {
match local_ip {
IpAddr::V4(local_ipv4) => {
if iface.ipv4.contains(&local_ipv4) {
match gateway::unix::get_default_gateway(iface.name.clone()) {
Ok(gateway) => {
iface.gateway = Some(gateway);
},
Err(_) => {},
}
}
},
IpAddr::V6(local_ipv6) => {
if iface.ipv6.contains(&local_ipv6) {
match gateway::unix::get_default_gateway(iface.name.clone()) {
Ok(gateway) => {
iface.gateway = Some(gateway);
},
Err(_) => {},
}
}
},
}
}
interfaces
} }
pub fn unix_interfaces() -> Vec<Interface> { pub fn unix_interfaces() -> Vec<Interface> {

@ -0,0 +1,215 @@
use windows::Win32::Foundation::{ERROR_BUFFER_OVERFLOW, NO_ERROR};
use windows::Win32::NetworkManagement::IpHelper::{GetAdaptersInfo, IP_ADAPTER_INFO, IP_ADDR_STRING, SendARP};
use std::convert::TryInto;
use std::mem;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::ffi::CStr;
use core::ffi::c_void;
use crate::interface::{Interface, MacAddr};
use crate::gateway::Gateway;
const EXCEPTION_INTERFACE_INDEX: u32 = 0;
const EXCEPTION_INTERFACE_COMBOINDEX: u32 = 4928;
// Convert C string to Rust string without trailing null bytes
fn bytes_to_string(bytes: &[u8]) -> String {
let result: String = match CStr::from_bytes_with_nul(bytes) {
Ok(cstr) => {
match cstr.to_str() {
Ok(rstr) => rstr.to_string(),
Err(_) => cstr.to_string_lossy().replace("\u{0}", "").to_string(),
}
},
Err(_) => {
String::from_utf8_lossy(bytes).replace("\u{0}", "").to_string()
}
};
result
}
#[cfg(target_endian = "little")]
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;
(o0 as u32) << 24 | (o1 as u32) << 16 | (o2 as u32) << 8 | (o3 as u32)
}
#[cfg(target_endian = "big")]
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) };
if res == NO_ERROR {
MacAddr::new(target_mac_addr)
}else{
MacAddr::zero()
}
}
// Get network interfaces using the IP Helper API
// TODO: Make more rusty ...
// Reference: https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersinfo
pub fn interfaces() -> Vec<Interface> {
let mut interfaces: Vec<Interface> = vec![];
let mut out_buf_len : u32 = mem::size_of::<IP_ADAPTER_INFO>().try_into().unwrap();
let mut raw_adaptor_mem: Vec<u8> = Vec::with_capacity(out_buf_len as usize);
let mut p_adaptor: *mut IP_ADAPTER_INFO;
let mut res = unsafe { GetAdaptersInfo(raw_adaptor_mem.as_mut_ptr() as *mut IP_ADAPTER_INFO, &mut out_buf_len ) };
// Make an initial call to GetAdaptersInfo to get the necessary size into the out_buf_len variable
if res == ERROR_BUFFER_OVERFLOW {
raw_adaptor_mem = Vec::with_capacity(out_buf_len as usize);
unsafe {
res = GetAdaptersInfo(raw_adaptor_mem.as_mut_ptr() as *mut IP_ADAPTER_INFO, &mut out_buf_len);
}
}
if res != NO_ERROR {
return interfaces;
}
//Enumerate all adapters
p_adaptor = unsafe { mem::transmute(&raw_adaptor_mem) };
while p_adaptor as u64 != 0 {
let adapter: IP_ADAPTER_INFO = unsafe { *p_adaptor };
if adapter.Index == EXCEPTION_INTERFACE_INDEX || adapter.ComboIndex == EXCEPTION_INTERFACE_COMBOINDEX{
unsafe { p_adaptor = (*p_adaptor).Next; }
continue;
}
let adapter_name: String = bytes_to_string(&adapter.AdapterName);
let adapter_desc: String = bytes_to_string(&adapter.Description);
let mac_addr:[u8; 6] = adapter.Address[..6].try_into().unwrap_or([0, 0, 0, 0, 0, 0]);
//Enumerate all IPs
let mut ipv4_vec: Vec<Ipv4Addr> = vec![];
let mut ipv6_vec: Vec<Ipv6Addr> = vec![];
let mut p_ip_addr: *mut IP_ADDR_STRING;
p_ip_addr = unsafe { mem::transmute(&(*p_adaptor).IpAddressList) };
while p_ip_addr as u64 != 0 {
let ip_addr_string: IP_ADDR_STRING = unsafe{ *p_ip_addr };
let ip_addr: String = bytes_to_string(&ip_addr_string.IpAddress.String);
match ip_addr.parse::<IpAddr>() {
Ok(ip_addr) => {
match ip_addr {
IpAddr::V4(ipv4_addr) => {
ipv4_vec.push(ipv4_addr);
},
IpAddr::V6(ipv6_addr) => {
ipv6_vec.push(ipv6_addr);
}
}
},
Err(_) => {},
}
unsafe { p_ip_addr = (*p_ip_addr).Next; }
}
//Enumerate all gateways
let mut gateway_ips: Vec<IpAddr> = vec![];
let mut p_gateway_addr: *mut IP_ADDR_STRING;
p_gateway_addr = unsafe { mem::transmute(&(*p_adaptor).GatewayList) };
while p_gateway_addr as u64 != 0 {
let gateway_addr_string: IP_ADDR_STRING = unsafe { *p_gateway_addr };
let gateway_addr: String = bytes_to_string(&gateway_addr_string.IpAddress.String);
match gateway_addr.parse::<IpAddr>() {
Ok(ip_addr) => {
gateway_ips.push(ip_addr);
},
Err(_) => {},
}
unsafe { p_gateway_addr = (*p_gateway_addr).Next; }
}
let default_gateway: Option<Gateway> = match gateway_ips.get(0) {
Some(gateway_ip) => {
let gateway_ip: IpAddr = *gateway_ip;
let default_gateway: Option<Gateway> = if gateway_ip != IpAddr::V4(Ipv4Addr::UNSPECIFIED) {
match gateway_ip {
IpAddr::V4(dst_ip) => {
if let Some(src_ip) = ipv4_vec.get(0) {
let mac_addr = get_mac_through_arp(*src_ip, dst_ip);
let gateway = Gateway {
mac_addr: mac_addr,
ip_addr: IpAddr::V4(dst_ip),
};
Some(gateway)
}else{
None
}
},
IpAddr::V6(_dst_ip) => {
None
},
}
}else{
None
};
default_gateway
},
None => None,
};
let interface: Interface = Interface{
index: adapter.Index,
name: adapter_name,
description: Some(adapter_desc),
mac_addr: Some(MacAddr::new(mac_addr)),
ipv4: ipv4_vec,
ipv6: ipv6_vec,
gateway: default_gateway,
};
interfaces.push(interface);
unsafe { p_adaptor = (*p_adaptor).Next; }
}
return interfaces;
}
// Get default Interface index
pub fn default_interface_index() -> Option<u32> {
let local_ip: IpAddr = match super::get_local_ipaddr(){
Some(local_ip) => local_ip,
None => return None,
};
let interfaces = interfaces();
for iface in interfaces {
match local_ip {
IpAddr::V4(local_ipv4) => {
if iface.ipv4.contains(&local_ipv4) {
return Some(iface.index);
}
},
IpAddr::V6(local_ipv6) => {
if iface.ipv6.contains(&local_ipv6) {
return Some(iface.index);
}
},
}
}
None
}
// Get default Interface name
pub fn default_interface_name() -> Option<String> {
let local_ip: IpAddr = match super::get_local_ipaddr(){
Some(local_ip) => local_ip,
None => return None,
};
let interfaces = interfaces();
for iface in interfaces {
match local_ip {
IpAddr::V4(local_ipv4) => {
if iface.ipv4.contains(&local_ipv4) {
return Some(iface.name);
}
},
IpAddr::V6(local_ipv6) => {
if iface.ipv6.contains(&local_ipv6) {
return Some(iface.name);
}
},
}
}
None
}

@ -1,4 +1,3 @@
mod os;
mod sys; mod sys;
mod bpf; mod bpf;
mod socket; mod socket;

@ -9,25 +9,7 @@ pub use self::unix::*;
mod tests { mod tests {
use super::*; use super::*;
use std::net::UdpSocket; use std::net::UdpSocket;
#[test] fn send_udp_packet() {
fn test_packet_capture() {
let interface_name: String = String::from("en0");
let config = Config {
write_buffer_size: 4096,
read_buffer_size: 4096,
read_timeout: None,
write_timeout: None,
channel_type: ChannelType::Layer2,
bpf_fd_attempts: 1000,
linux_fanout: None,
promiscuous: false,
};
let (mut _tx, mut rx) = match channel(interface_name, config) {
Ok(Channel::Ethernet(tx, rx)) => (tx, rx),
//Ok(_) => panic!("Unknown channel type"),
Err(e) => panic!("Error happened {}", e),
};
let buf = [0u8; 0]; let buf = [0u8; 0];
let socket = match UdpSocket::bind("0.0.0.0:0") { let socket = match UdpSocket::bind("0.0.0.0:0") {
Ok(s) => s, Ok(s) => s,
@ -51,6 +33,25 @@ mod tests {
return; return;
}, },
} }
}
#[test]
fn test_packet_capture() {
let interface_name: String = String::from("en7");
let config = Config {
write_buffer_size: 4096,
read_buffer_size: 4096,
read_timeout: None,
write_timeout: None,
channel_type: ChannelType::Layer2,
bpf_fd_attempts: 1000,
promiscuous: false,
};
let (mut _tx, mut rx) = match channel(interface_name, config) {
Ok(Channel::Ethernet(tx, rx)) => (tx, rx),
Err(e) => panic!("Error happened {}", e),
};
send_udp_packet();
loop { loop {
match rx.next() { match rx.next() {
@ -71,6 +72,7 @@ mod tests {
println!("{}", e); println!("{}", e);
} }
} }
send_udp_packet();
} }
} }
} }

@ -11,6 +11,7 @@ pub const NEXT_HEADER_ICMPV6: u8 = 58;
pub const ICMP_TYPE_TIME_EXCEEDED: u8 = 11; pub const ICMP_TYPE_TIME_EXCEEDED: u8 = 11;
pub const ICMPV6_TYPE_TIME_EXCEEDED: u8 = 3; pub const ICMPV6_TYPE_TIME_EXCEEDED: u8 = 3;
#[allow(dead_code)]
pub enum Frame { pub enum Frame {
SrcMacAddr, SrcMacAddr,
DstMacAddr, DstMacAddr,

@ -6,6 +6,7 @@ use crate::interface::Interface;
pub type EtherType = u16; pub type EtherType = u16;
#[allow(dead_code)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum ChannelType { pub enum ChannelType {
Layer2, Layer2,
@ -17,22 +18,9 @@ pub enum Channel {
Ethernet(Box<dyn DataLinkSender>, Box<dyn DataLinkReceiver>), Ethernet(Box<dyn DataLinkSender>, Box<dyn DataLinkReceiver>),
} }
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum FanoutType {
HASH,
LB,
CPU,
ROLLOVER,
RND,
QM,
CBPF,
EBPF,
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct FanoutOption { pub struct FanoutOption {
pub group_id: u16, pub group_id: u16,
pub fanout_type: FanoutType,
pub defrag: bool, pub defrag: bool,
pub rollover: bool, pub rollover: bool,
} }
@ -45,7 +33,6 @@ pub struct Config {
pub write_timeout: Option<Duration>, pub write_timeout: Option<Duration>,
pub channel_type: ChannelType, pub channel_type: ChannelType,
pub bpf_fd_attempts: usize, pub bpf_fd_attempts: usize,
pub linux_fanout: Option<FanoutOption>,
pub promiscuous: bool, pub promiscuous: bool,
} }
@ -58,7 +45,6 @@ impl Default for Config {
write_timeout: None, write_timeout: None,
channel_type: ChannelType::Layer2, channel_type: ChannelType::Layer2,
bpf_fd_attempts: 1000, bpf_fd_attempts: 1000,
linux_fanout: None,
promiscuous: true, promiscuous: true,
} }
} }

Loading…
Cancel
Save