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
, IfIndex
, Interface
};
21 pub fn list_interfaces() -> Result
<HashMap
<IfIndex
, Interface
>, 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(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
();
111 println
!("{:?}", ifaces
);