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
::NetworkManagement
::Ndis
::IfOperStatusDown
;
16 use windows
::Win32
::Networking
::WinSock
::{
17 AF_INET
, AF_INET6
, AF_UNSPEC
, SOCKADDR
, SOCKADDR_IN
, SOCKADDR_IN6
,
20 use crate::{Error
, Interface
, List
};
22 pub(crate) fn list_interfaces() -> Result
<List
, Error
> {
23 let mut ifs
= HashMap
::new();
24 // Microsoft recommends a 15 KB initial buffer
25 let start_size
= 15 * 1024;
26 let mut buf
: Vec
<u8> = vec
![0; start_size
];
27 let mut sizepointer
: u32 = start_size
as u32;
31 let bufptr
= &mut buf
[0] as *mut _
as *mut IP_ADAPTER_ADDRESSES_LH
;
32 let res
= GetAdaptersAddresses(
34 GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_MULTICAST
,
39 match WIN32_ERROR(res
) {
40 ERROR_SUCCESS
=> break,
41 ERROR_ADDRESS_NOT_ASSOCIATED
=> return Err(Error
::Internal
),
42 ERROR_BUFFER_OVERFLOW
=> {
43 buf
.resize(sizepointer
as usize, 0);
46 ERROR_INVALID_PARAMETER
=> return Err(Error
::Internal
),
47 ERROR_NOT_ENOUGH_MEMORY
=> return Err(Error
::Internal
),
48 ERROR_NO_DATA
=> return Ok(List(HashMap
::new())), // there aren't any
49 _
=> return Err(Error
::Internal
), // TODO: Use FormatMessage to get a string
53 // We have at least one
54 let mut adapter_ptr
= &buf
[0] as *const _
as *const IP_ADAPTER_ADDRESSES_LH
;
55 while !adapter_ptr
.is
_n
ull
() {
56 let adapter
= &*adapter_ptr
as &IP_ADAPTER_ADDRESSES_LH
;
57 if adapter
.OperStatus
== IfOperStatusDown
{
58 adapter_ptr
= adapter
.Next
;
61 let mut hw_addr
= String
::with_capacity(adapter
.PhysicalAddressLength
as usize * 3);
62 for i
in 0..adapter
.PhysicalAddressLength
as usize {
64 write
!(hw_addr
, ":").map_err(|_
| Error
::Internal
)?
;
66 write
!(hw_addr
, "{:02X}", adapter
.PhysicalAddress
[i
])
67 .map_err(|_
| Error
::Internal
)?
;
70 let mut unicast_ptr
= adapter
.FirstUnicastAddress
;
71 while !unicast_ptr
.is
_n
ull
() {
72 let unicast
= &*unicast_ptr
as &IP_ADAPTER_UNICAST_ADDRESS_LH
;
73 let sockaddr
= &*unicast
.Address
.lpSockaddr
as &SOCKADDR
;
74 let ip
= match sockaddr
.sa_family
{
77 &*(unicast
.Address
.lpSockaddr
as *const SOCKADDR_IN
) as &SOCKADDR_IN
;
78 IpAddr
::V4(sockaddr_in
.sin_addr
.into
())
82 &*(unicast
.Address
.lpSockaddr
as *const SOCKADDR_IN6
) as &SOCKADDR_IN6
;
83 IpAddr
::V6(sockaddr_in6
.sin6_addr
.into
())
88 unicast_ptr
= unicast
.Next
;
90 let ifindex
= adapter
.Ipv6IfIndex
;
94 .unwrap
_or
_else
(|_
| "".to_owned());
95 let iface
= Interface
{
101 ifs
.insert
(ifindex
, iface
);
102 adapter_ptr
= adapter
.Next
;