1 use std
::collections
::HashMap
; 
   5 use windows
::Win32
::Foundation
::{ 
   6     ERROR_ADDRESS_NOT_ASSOCIATED
, ERROR_BUFFER_OVERFLOW
, ERROR_INVALID_PARAMETER
, 
   7     ERROR_NOT_ENOUGH_MEMORY
, ERROR_NO_DATA
, ERROR_SUCCESS
, WIN32_ERROR
, 
   9 use windows
::Win32
::NetworkManagement
::IpHelper
::{ 
  10     GetAdaptersAddresses
, IP_ADAPTER_UNICAST_ADDRESS_LH
, 
  12 use windows
::Win32
::NetworkManagement
::IpHelper
::{ 
  13     GAA_FLAG_SKIP_ANYCAST
, GAA_FLAG_SKIP_MULTICAST
, IP_ADAPTER_ADDRESSES_LH
, 
  15 use windows
::Win32
::Networking
::WinSock
::{ 
  16     AF_INET
, AF_INET6
, AF_UNSPEC
, SOCKADDR
, SOCKADDR_IN
, SOCKADDR_IN6
, 
  19 use crate::{Error
, Interface
, List
}; 
  21 pub(crate) fn list_interfaces() -> Result
<List
, Error
> { 
  22     let mut ifs 
= HashMap
::new(); 
  23     // Microsoft recommends a 15 KB initial buffer 
  24     let start_size 
= 15 * 1024; 
  25     let mut buf
: Vec
<u8> = vec
![0; start_size
]; 
  26     let mut sizepointer
: u32 = start_size 
as u32; 
  30             let bufptr 
= &mut buf
[0] as *mut _ 
as *mut IP_ADAPTER_ADDRESSES_LH
; 
  31             let res 
= GetAdaptersAddresses( 
  33                 GAA_FLAG_SKIP_ANYCAST 
| GAA_FLAG_SKIP_MULTICAST
, 
  38             match WIN32_ERROR(res
) { 
  39                 ERROR_SUCCESS 
=> break, 
  40                 ERROR_ADDRESS_NOT_ASSOCIATED 
=> return Err(Error
::Internal
), 
  41                 ERROR_BUFFER_OVERFLOW 
=> { 
  42                     buf
.resize(sizepointer 
as usize, 0); 
  45                 ERROR_INVALID_PARAMETER 
=> return Err(Error
::Internal
), 
  46                 ERROR_NOT_ENOUGH_MEMORY 
=> return Err(Error
::Internal
), 
  47                 ERROR_NO_DATA 
=> return Ok(List(HashMap
::new())), // there aren't any 
  48                 _ 
=> return Err(Error
::Internal
), // TODO: Use FormatMessage to get a string 
  52         // We have at least one 
  53         let mut adapter_ptr 
= &buf
[0] as *const _ 
as *const IP_ADAPTER_ADDRESSES_LH
; 
  54         while !adapter_ptr
.is
_n
ull
() { 
  55             let adapter 
= &*adapter_ptr 
as &IP_ADAPTER_ADDRESSES_LH
; 
  56             let mut hw_addr 
= String
::with_capacity(adapter
.PhysicalAddressLength 
as usize * 3); 
  57             for i 
in 0..adapter
.PhysicalAddressLength 
as usize { 
  59                     write
!(hw_addr
, ":").map_err(|_
| Error
::Internal
)?
; 
  61                 write
!(hw_addr
, "{:02X}", adapter
.PhysicalAddress
[i
]) 
  62                     .map_err(|_
| Error
::Internal
)?
; 
  65             let mut unicast_ptr 
= adapter
.FirstUnicastAddress
; 
  66             while !unicast_ptr
.is
_n
ull
() { 
  67                 let unicast 
= &*unicast_ptr 
as &IP_ADAPTER_UNICAST_ADDRESS_LH
; 
  68                 let sockaddr 
= &*unicast
.Address
.lpSockaddr 
as &SOCKADDR
; 
  69                 let ip 
= match sockaddr
.sa_family 
{ 
  72                             &*(unicast
.Address
.lpSockaddr 
as *const SOCKADDR_IN
) as &SOCKADDR_IN
; 
  73                         IpAddr
::V4(sockaddr_in
.sin_addr
.into
()) 
  77                             &*(unicast
.Address
.lpSockaddr 
as *const SOCKADDR_IN6
) as &SOCKADDR_IN6
; 
  78                         IpAddr
::V6(sockaddr_in6
.sin6_addr
.into
()) 
  83                 unicast_ptr 
= unicast
.Next
; 
  85             let ifindex 
= adapter
.Ipv6IfIndex
; 
  89                 .unwrap
_or
_else
(|_
| "".to_owned()); 
  90             let iface 
= Interface 
{ 
  96             ifs
.insert
(ifindex
, iface
); 
  97             adapter_ptr 
= adapter
.Next
; 
 106     use super::list_interfaces
; 
 110         let ifaces 
= list_interfaces().unwrap
().0; 
 111         println
!("{:?}", ifaces
);