Skip to content

Commit

Permalink
Merge pull request #25 from messense/windows-sys
Browse files Browse the repository at this point in the history
Rewrite `windows.rs`
  • Loading branch information
messense committed Feb 28, 2023
2 parents 0e3b493 + 26a35b6 commit 5db50e8
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 106 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ features = [
"Win32_Foundation",
"Win32_Networking_WinSock",
"Win32_NetworkManagement_IpHelper",
"Win32_NetworkManagement_Ndis",
]

[features]
Expand Down
16 changes: 8 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,30 +233,30 @@ mod getifaddrs_windows {

for ifaddr in ifaddrs.iter() {
for addr in ifaddr.unicast_addresses() {
if addr.dadstate != IpDadStatePreferred {
if addr.DadState != IpDadStatePreferred {
continue;
}
let addr = match sockaddr::to_ipaddr(addr.address.lp_socket_address) {
let addr = match sockaddr::to_ipaddr(addr.Address.lpSockaddr) {
None => continue,
Some(IpAddr::V4(ipv4_addr)) => {
let mut item_netmask = Ipv4Addr::new(0, 0, 0, 0);
let mut item_broadcast = None;

// Search prefixes for a prefix matching addr
'prefixloopv4: for prefix in ifaddr.prefixes() {
let ipprefix = sockaddr::to_ipaddr(prefix.address.lp_socket_address);
let ipprefix = sockaddr::to_ipaddr(prefix.Address.lpSockaddr);
match ipprefix {
Some(IpAddr::V4(ref a)) => {
let mut netmask: [u8; 4] = [0; 4];
for (n, netmask_elt) in netmask
.iter_mut()
.enumerate()
.take((prefix.prefix_length as usize + 7) / 8)
.take((prefix.PrefixLength as usize + 7) / 8)
{
let x_byte = ipv4_addr.octets()[n];
let y_byte = a.octets()[n];
for m in 0..8 {
if (n * 8) + m > prefix.prefix_length as usize {
if (n * 8) + m > prefix.PrefixLength as usize {
break;
}
let bit = 1 << (7 - m);
Expand Down Expand Up @@ -295,7 +295,7 @@ mod getifaddrs_windows {
let mut item_netmask = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
// Search prefixes for a prefix matching addr
'prefixloopv6: for prefix in ifaddr.prefixes() {
let ipprefix = sockaddr::to_ipaddr(prefix.address.lp_socket_address);
let ipprefix = sockaddr::to_ipaddr(prefix.Address.lpSockaddr);
match ipprefix {
Some(IpAddr::V6(ref a)) => {
// Iterate the bits in the prefix, if they all match this prefix
Expand All @@ -304,12 +304,12 @@ mod getifaddrs_windows {
for (n, netmask_elt) in netmask
.iter_mut()
.enumerate()
.take((prefix.prefix_length as usize + 15) / 16)
.take((prefix.PrefixLength as usize + 15) / 16)
{
let x_word = ipv6_addr.segments()[n];
let y_word = a.segments()[n];
for m in 0..16 {
if (n * 16) + m > prefix.prefix_length as usize {
if (n * 16) + m > prefix.PrefixLength as usize {
break;
}
let bit = 1 << (15 - m);
Expand Down
136 changes: 38 additions & 98 deletions src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,120 +7,55 @@
// specific language governing permissions and limitations relating to use of the SAFE Network
// Software.

use libc::{self, c_char, c_int, c_ulong, c_void, size_t};
use libc::{self, c_ulong, c_void, size_t};
use std::ffi::CStr;
use std::{io, ptr};
use windows_sys::Win32::Foundation::{ERROR_BUFFER_OVERFLOW, ERROR_SUCCESS};
use windows_sys::Win32::NetworkManagement::IpHelper::{
GAA_FLAG_INCLUDE_PREFIX, GAA_FLAG_SKIP_ANYCAST, GAA_FLAG_SKIP_DNS_SERVER,
GAA_FLAG_SKIP_FRIENDLY_NAME, GAA_FLAG_SKIP_MULTICAST,
GetAdaptersAddresses, GAA_FLAG_INCLUDE_PREFIX, GAA_FLAG_SKIP_ANYCAST, GAA_FLAG_SKIP_DNS_SERVER,
GAA_FLAG_SKIP_FRIENDLY_NAME, GAA_FLAG_SKIP_MULTICAST, IP_ADAPTER_ADDRESSES_LH,
IP_ADAPTER_PREFIX_XP, IP_ADAPTER_UNICAST_ADDRESS_LH,
};
use windows_sys::Win32::Networking::WinSock::{NL_DAD_STATE, NL_PREFIX_ORIGIN, NL_SUFFIX_ORIGIN};
use windows_sys::{Win32::Foundation::ERROR_SUCCESS, Win32::Networking::WinSock::SOCKADDR};

type DWORD = c_ulong;

#[repr(C)]
pub struct SocketAddress {
pub lp_socket_address: *const SOCKADDR,
pub i_socket_address_length: c_int,
}

#[repr(C)]
pub struct IpAdapterUnicastAddress {
pub length: c_ulong,
pub flags: DWORD,
pub next: *const IpAdapterUnicastAddress,
pub address: SocketAddress,
pub prefixorigin: NL_PREFIX_ORIGIN,
pub suffixorigin: NL_SUFFIX_ORIGIN,
pub dadstate: NL_DAD_STATE,
// Loads more follows, but I'm not bothering to map these for now
// ULONG ValidLifetime;
// ULONG PreferredLifetime;
// ULONG LeaseLifetime;
// UINT8 OnLinkPrefixLength;
}
#[repr(C)]
pub struct IpAdapterPrefix {
pub length: c_ulong,
pub flags: DWORD,
pub next: *const IpAdapterPrefix,
pub address: SocketAddress,
pub prefix_length: c_ulong,
}
#[repr(C)]
pub struct IpAdapterAddresses {
pub length: c_ulong,
pub if_index: DWORD,
next: *const IpAdapterAddresses,
adapter_name: *const c_char,
first_unicast_address: *const IpAdapterUnicastAddress,
first_anycast_address: *const c_void,
first_multicast_address: *const c_void,
first_dns_server_address: *const c_void,
dns_suffix: *const c_void,
description: *const c_void,
friendly_name: *const c_void,
physical_address: [c_char; 8],
physical_address_length: DWORD,
flags: DWORD,
mtu: DWORD,
if_type: DWORD,
oper_status: c_int,
ipv6_if_index: DWORD,
zone_indices: [DWORD; 16],
// Loads more follows, but I'm not bothering to map these for now
first_prefix: *const IpAdapterPrefix,
}
#[repr(transparent)]
pub struct IpAdapterAddresses(*const IP_ADAPTER_ADDRESSES_LH);

impl IpAdapterAddresses {
#[allow(unsafe_code)]
pub fn name(&self) -> String {
unsafe { CStr::from_ptr(self.adapter_name) }
unsafe { CStr::from_ptr((*self.0).AdapterName as _) }
.to_string_lossy()
.into_owned()
}

pub fn prefixes(&self) -> PrefixesIterator {
PrefixesIterator {
_head: self,
next: self.first_prefix,
_head: unsafe { &*self.0 },
next: unsafe { (*self.0).FirstPrefix },
}
}

pub fn unicast_addresses(&self) -> UnicastAddressesIterator {
UnicastAddressesIterator {
_head: self,
next: self.first_unicast_address,
_head: unsafe { &*self.0 },
next: unsafe { (*self.0).FirstUnicastAddress },
}
}
}

#[link(name = "iphlpapi")]
extern "system" {
/// Get adapter's addresses.
fn GetAdaptersAddresses(
family: c_ulong,
flags: c_ulong,
reserved: *const c_void,
addresses: *const IpAdapterAddresses,
size: *mut c_ulong,
) -> c_ulong;
}

pub struct IfAddrs {
inner: *const IpAdapterAddresses,
inner: IpAdapterAddresses,
}

impl IfAddrs {
#[allow(unsafe_code)]
pub fn new() -> io::Result<Self> {
let mut buffersize: c_ulong = 15000;
let mut ifaddrs: *const IpAdapterAddresses;
let mut ifaddrs: *mut IP_ADAPTER_ADDRESSES_LH;

loop {
unsafe {
ifaddrs = libc::malloc(buffersize as size_t) as *mut IpAdapterAddresses;
ifaddrs = libc::malloc(buffersize as size_t) as *mut IP_ADAPTER_ADDRESSES_LH;
if ifaddrs.is_null() {
panic!("Failed to allocate buffer in get_if_addrs()");
}
Expand All @@ -132,30 +67,35 @@ impl IfAddrs {
| GAA_FLAG_SKIP_DNS_SERVER
| GAA_FLAG_INCLUDE_PREFIX
| GAA_FLAG_SKIP_FRIENDLY_NAME,
ptr::null(),
ptr::null_mut(),
ifaddrs,
&mut buffersize,
);

match retcode {
ERROR_SUCCESS => break,
111 => {
ERROR_BUFFER_OVERFLOW => {
libc::free(ifaddrs as *mut c_void);
buffersize *= 2;
continue;
}
_ => return Err(io::Error::last_os_error()),
_ => {
libc::free(ifaddrs as *mut c_void);
return Err(io::Error::last_os_error());
}
}
}
}

Ok(Self { inner: ifaddrs })
Ok(Self {
inner: IpAdapterAddresses(ifaddrs),
})
}

pub fn iter(&self) -> IfAddrsIterator {
IfAddrsIterator {
_head: self,
next: self.inner,
next: self.inner.0,
}
}
}
Expand All @@ -164,18 +104,18 @@ impl Drop for IfAddrs {
#[allow(unsafe_code)]
fn drop(&mut self) {
unsafe {
libc::free(self.inner as *mut c_void);
libc::free(self.inner.0 as *mut c_void);
}
}
}

pub struct IfAddrsIterator<'a> {
_head: &'a IfAddrs,
next: *const IpAdapterAddresses,
next: *const IP_ADAPTER_ADDRESSES_LH,
}

impl<'a> Iterator for IfAddrsIterator<'a> {
type Item = &'a IpAdapterAddresses;
type Item = IpAdapterAddresses;

#[allow(unsafe_code)]
fn next(&mut self) -> Option<Self::Item> {
Expand All @@ -185,20 +125,20 @@ impl<'a> Iterator for IfAddrsIterator<'a> {

Some(unsafe {
let result = &*self.next;
self.next = (*self.next).next;
self.next = (*self.next).Next;

result
IpAdapterAddresses(result)
})
}
}

pub struct PrefixesIterator<'a> {
_head: &'a IpAdapterAddresses,
next: *const IpAdapterPrefix,
_head: &'a IP_ADAPTER_ADDRESSES_LH,
next: *const IP_ADAPTER_PREFIX_XP,
}

impl<'a> Iterator for PrefixesIterator<'a> {
type Item = &'a IpAdapterPrefix;
type Item = &'a IP_ADAPTER_PREFIX_XP;

#[allow(unsafe_code)]
fn next(&mut self) -> Option<Self::Item> {
Expand All @@ -208,20 +148,20 @@ impl<'a> Iterator for PrefixesIterator<'a> {

Some(unsafe {
let result = &*self.next;
self.next = (*self.next).next;
self.next = (*self.next).Next;

result
})
}
}

pub struct UnicastAddressesIterator<'a> {
_head: &'a IpAdapterAddresses,
next: *const IpAdapterUnicastAddress,
_head: &'a IP_ADAPTER_ADDRESSES_LH,
next: *const IP_ADAPTER_UNICAST_ADDRESS_LH,
}

impl<'a> Iterator for UnicastAddressesIterator<'a> {
type Item = &'a IpAdapterUnicastAddress;
type Item = &'a IP_ADAPTER_UNICAST_ADDRESS_LH;

#[allow(unsafe_code)]
fn next(&mut self) -> Option<Self::Item> {
Expand All @@ -231,7 +171,7 @@ impl<'a> Iterator for UnicastAddressesIterator<'a> {

Some(unsafe {
let result = &*self.next;
self.next = (*self.next).next;
self.next = (*self.next).Next;

result
})
Expand Down

0 comments on commit 5db50e8

Please sign in to comment.