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
::{AF_INET
, AF_INET6
, SOCKADDR
, SOCKADDR_IN
, SOCKADDR_IN6
};
17 use crate::{Error
, IfIndex
, Interface
};
19 pub(crate) fn list_interfaces() -> Result
<HashMap
<IfIndex
, Interface
>, Error
> {
20 let mut ifs
= HashMap
::new();
21 // Microsoft recommends a 15 KB initial buffer
22 let start_size
= 15 * 1024;
23 let mut buf
: Vec
<u8> = vec
![0; start_size
];
24 let mut sizepointer
: u32 = start_size
as u32;
28 let bufptr
= &mut buf
[0] as *mut _
as *mut IP_ADAPTER_ADDRESSES_LH
;
29 let res
= GetAdaptersAddresses(
31 GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_MULTICAST
,
36 match WIN32_ERROR(res
) {
37 ERROR_SUCCESS
=> break,
38 ERROR_ADDRESS_NOT_ASSOCIATED
=> return Err(Error
::Internal
),
39 ERROR_BUFFER_OVERFLOW
=> {
40 buf
.resize(sizepointer
as usize, 0);
43 ERROR_INVALID_PARAMETER
=> return Err(Error
::Internal
),
44 ERROR_NOT_ENOUGH_MEMORY
=> return Err(Error
::Internal
),
45 ERROR_NO_DATA
=> return Ok(HashMap
::new()), // there aren't any
46 _
=> return Err(Error
::Internal
), // TODO: Use FormatMessage to get a string
50 // We have at least one
51 let mut adapter_ptr
= &buf
[0] as *const _
as *const IP_ADAPTER_ADDRESSES_LH
;
52 while !adapter_ptr
.is
_n
ull
() {
53 let adapter
= &*adapter_ptr
as &IP_ADAPTER_ADDRESSES_LH
;
54 let mut hw_addr
= String
::with_capacity(adapter
.PhysicalAddressLength
as usize * 3);
55 for i
in 0..adapter
.PhysicalAddressLength
as usize {
57 write
!(hw_addr
, ":").map_err(|_
| Error
::Internal
)?
;
59 write
!(hw_addr
, "{:02X}", adapter
.PhysicalAddress
[i
])
60 .map_err(|_
| Error
::Internal
)?
;
63 let mut unicast_ptr
= adapter
.FirstUnicastAddress
;
64 while !unicast_ptr
.is
_n
ull
() {
65 let unicast
= &*unicast_ptr
as &IP_ADAPTER_UNICAST_ADDRESS_LH
;
66 let sockaddr
= &*unicast
.Address
.lpSockaddr
as &SOCKADDR
;
67 let ip
= match sockaddr
.sa_family
{
70 &*(unicast
.Address
.lpSockaddr
as *const SOCKADDR_IN
) as &SOCKADDR_IN
;
71 IpAddr
::V4(sockaddr_in
.sin_addr
.into
())
75 &*(unicast
.Address
.lpSockaddr
as *const SOCKADDR_IN6
) as &SOCKADDR_IN6
;
76 IpAddr
::V6(sockaddr_in6
.sin6_addr
.into
())
81 unicast_ptr
= unicast
.Next
;
83 let ifindex
= adapter
.Ipv6IfIndex
;
87 .unwrap
_or
_else
(|_
| "".to_owned());
88 let iface
= Interface
{
94 ifs
.insert
(ifindex
, iface
);
95 adapter_ptr
= adapter
.Next
;
104 use super::list_interfaces
;
108 let ifaces
= list_interfaces().unwrap
();
109 println
!("{:?}", ifaces
);