factor/basis/windows/iphlpapi/iphlpapi.factor

444 lines
12 KiB
Factor

! Copyright (C) 2010 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien alien.c-types alien.data alien.strings
alien.syntax arrays byte-arrays classes.struct combinators
combinators.smart destructors io.encodings.string
io.encodings.utf8 io.sockets io.sockets.private kernel libc
make refs sequences sequences.extras windows.errors
windows.kernel32 windows.types windows.winsock fry ;
IN: windows.iphlpapi
LIBRARY: iphlpapi
<<
CONSTANT: DEFAULT_MINIMUM_ENTITIES 32
CONSTANT: MAX_ADAPTER_ADDRESS_LENGTH 8
CONSTANT: MAX_ADAPTER_DESCRIPTION_LENGTH 128
CONSTANT: MAX_ADAPTER_NAME_LENGTH 256
CONSTANT: MAX_DOMAIN_NAME_LEN 128
CONSTANT: MAX_HOSTNAME_LEN 128
CONSTANT: MAX_SCOPE_ID_LEN 256
CONSTANT: BROADCAST_NODETYPE 1
CONSTANT: PEER_TO_PEER_NODETYPE 2
CONSTANT: MIXED_NODETYPE 4
CONSTANT: HYBRID_NODETYPE 8
CONSTANT: IF_OTHER_ADAPTERTYPE 0
CONSTANT: IF_ETHERNET_ADAPTERTYPE 1
CONSTANT: IF_TOKEN_RING_ADAPTERTYPE 2
CONSTANT: IF_FDDI_ADAPTERTYPE 3
CONSTANT: IF_PPP_ADAPTERTYPE 4
CONSTANT: IF_LOOPBACK_ADAPTERTYPE 5
>>
CONSTANT: MAX_DOMAIN_NAME_LEN+4 132
CONSTANT: MAX_HOSTNAME_LEN+4 132
CONSTANT: MAX_SCOPE_ID_LEN+4 260
CONSTANT: MAX_ADAPTER_NAME_LENGTH+4 264
CONSTANT: MAX_ADAPTER_DESCRIPTION_LENGTH+4 136
CONSTANT: ERROR_BUFFER_OVERFLOW 111
CONSTANT: MIB_IF_TYPE_ETHERNET 6
CONSTANT: MIB_IF_TYPE_TOKENRING 9
CONSTANT: MIB_IF_TYPE_FDDI 15
CONSTANT: MIB_IF_TYPE_PPP 23
CONSTANT: MIB_IF_TYPE_LOOPBACK 24
CONSTANT: MIB_IF_TYPE_SLIP 28
CONSTANT: MAX_DNS_SUFFIX_STRING_LENGTH 256 ! 246?
CONSTANT: MAX_DHCPV6_DUID_LENGTH 130
CONSTANT: MAX_ADAPTER_NAME 128
STRUCT: IP_ADDRESS_STRING
{ String char[16] } ;
TYPEDEF: IP_ADDRESS_STRING* PIP_ADDRESS_STRING
TYPEDEF: IP_ADDRESS_STRING IP_MASK_STRING
TYPEDEF: IP_MASK_STRING* PIP_MASK_STRING
STRUCT: IP_ADDR_STRING
{ Next IP_ADDR_STRING* }
{ IpAddress IP_ADDRESS_STRING }
{ IpMask IP_MASK_STRING }
{ Context DWORD } ;
TYPEDEF: IP_ADDR_STRING* PIP_ADDR_STRING
STRUCT: FIXED_INFO
{ HostName char[MAX_HOSTNAME_LEN+4] }
{ DomainName char[MAX_DOMAIN_NAME_LEN+4] }
{ CurrentDnsServer PIP_ADDR_STRING }
{ DnsServerList IP_ADDR_STRING }
{ NodeType UINT }
{ ScopeId char[MAX_SCOPE_ID_LEN+4] }
{ EnableRouting UINT }
{ EnableProxy UINT }
{ EnableDns UINT }
{ ExtraSpace char[4096] } ;
DEFER: IP_ADAPTER_INFO
TYPEDEF: ulong time_t
TYPEDEF: uchar UINT8
TYPEDEF: uint NET_IF_COMPARTMENT_ID
TYPEDEF: GUID NET_IF_NETWORK_GUID
ENUM: IP_DAD_STATE
IpDadStateInvalid
IpDadStateTentative,
IpDadStateDuplicate,
IpDadStateDeprecated,
IpDadStatePreferred ;
ENUM: IP_PREFIX_ORIGIN
IpPrefixOriginOther,
IpPrefixOriginManual,
IpPrefixOriginWellKnown,
IpPrefixOriginDhcp,
IpPrefixOriginRouterAdvertisement,
{ IpPrefixOriginUnchanged 16 } ;
ENUM: IP_SUFFIX_ORIGIN
IpSuffixOriginOther
IpSuffixOriginManual,
IpSuffixOriginWellKnown,
IpSuffixOriginDhcp,
IpSuffixOriginLinkLayerAddress,
IpSuffixOriginRandom,
{ IpSuffixOriginUnchanged 16 } ;
ENUM: IF_OPER_STATUS
{ IfOperStatusUp 1 }
IfOperStatusDown,
IfOperStatusTesting,
IfOperStatusUnknown,
IfOperStatusDormant,
IfOperStatusNotPresent,
IfOperStatusLowerLayerDown ;
ENUM: NET_IF_CONNECTION_TYPE
{ NET_IF_CONNECTION_DEDICATED 1 }
NET_IF_CONNECTION_PASSIVE,
NET_IF_CONNECTION_DEMAND,
NET_IF_CONNECTION_MAXIMUM ;
ENUM: TUNNEL_TYPE
TUNNEL_TYPE_NONE,
TUNNEL_TYPE_OTHER,
TUNNEL_TYPE_DIRECT,
TUNNEL_TYPE_6TO4,
TUNNEL_TYPE_ISATAP,
TUNNEL_TYPE_TEREDO,
TUNNEL_TYPE_IPHTTPS ;
STRUCT: SOCKET_ADDRESS
{ lpSockaddr LPSOCKADDR }
{ iSockaddrLength INT } ;
ERROR: unknown-sockaddr-length sockaddr length ;
: SOCKET_ADDRESS>sockaddr ( obj -- sockaddr )
dup iSockaddrLength>> {
{ 16 [ lpSockaddr>> sockaddr-in memory>struct ] }
{ 28 [ lpSockaddr>> sockaddr-in6 memory>struct ] }
[ unknown-sockaddr-length ]
} case ;
TYPEDEF: SOCKET_ADDRESS* PSOCKET_ADDRESS
STRUCT: IP_ADAPTER_INFO
{ Next IP_ADAPTER_INFO* }
{ ComboIndex DWORD }
{ AdapterName char[MAX_ADAPTER_NAME_LENGTH+4] }
{ Description char[MAX_ADAPTER_DESCRIPTION_LENGTH+4] }
{ AddressLength UINT }
{ Address BYTE[MAX_ADAPTER_ADDRESS_LENGTH] }
{ Index DWORD }
{ Type UINT }
{ DhcpEnabled UINT }
{ CurrentIpAddress PIP_ADDR_STRING }
{ IpAddressList IP_ADDR_STRING }
{ GatewayList IP_ADDR_STRING }
{ DhcpServer IP_ADDR_STRING }
{ HaveWins BOOL }
{ PrimaryWinsServer IP_ADDR_STRING }
{ SecondaryWinsServer IP_ADDR_STRING }
{ LeaseObtained time_t }
{ LeaseExpires time_t } ;
TYPEDEF: IP_ADAPTER_INFO* PIP_ADAPTER_INFO
STRUCT: LengthIndex
{ Length ULONG }
{ IfIndex DWORD } ;
TYPEDEF: LengthIndex LengthFlags
UNION-STRUCT: AlignmentLenIndex
{ Alignment ULONGLONG }
{ LenIndex LengthIndex } ;
UNION-STRUCT: AlignmentLenFlags
{ Alignment ULONGLONG }
{ LenFlags LengthFlags } ;
STRUCT: ResNetIf
{ Reserved ULONG64 bits: 24 }
{ NetLuidIndex ULONG64 bits: 24 }
{ IfType ULONG64 bits: 16 } ;
UNION-STRUCT: NET_LUID
{ Value ULONG64 }
{ Info ResNetIf } ;
TYPEDEF: NET_LUID* PNET_LUID
TYPEDEF: NET_LUID IF_LUID
DEFER: IP_ADAPTER_ADDRESSES
DEFER: IP_ADAPTER_UNICAST_ADDRESS
STRUCT: IP_ADAPTER_UNICAST_ADDRESS
{ Header LengthFlags }
{ Next IP_ADAPTER_UNICAST_ADDRESS* }
{ Address SOCKET_ADDRESS }
{ PrefixOrigin IP_PREFIX_ORIGIN }
{ SuffixOrigin IP_SUFFIX_ORIGIN }
{ DadState IP_DAD_STATE }
{ ValidLifetime ULONG }
{ PreferredLifetime ULONG }
{ LeaseLifeTime ULONG }
{ OnLinkPrefixLength UINT8 } ;
TYPEDEF: IP_ADAPTER_UNICAST_ADDRESS* PIP_ADAPTER_UNICAST_ADDRESS
DEFER: IP_ADAPTER_ANYCAST_ADDRESS
STRUCT: IP_ADAPTER_ANYCAST_ADDRESS
{ Header AlignmentLenFlags }
{ Next IP_ADAPTER_ANYCAST_ADDRESS* }
{ Address SOCKET_ADDRESS } ;
TYPEDEF: IP_ADAPTER_ANYCAST_ADDRESS* PIP_ADAPTER_ANYCAST_ADDRESS
DEFER: IP_ADAPTER_MULTICAST_ADDRESS
STRUCT: IP_ADAPTER_MULTICAST_ADDRESS
{ Header AlignmentLenFlags }
{ Next IP_ADAPTER_MULTICAST_ADDRESS* }
{ Address SOCKET_ADDRESS } ;
TYPEDEF: IP_ADAPTER_MULTICAST_ADDRESS* PIP_ADAPTER_MULTICAST_ADDRESS
DEFER: IP_ADAPTER_DNS_SERVER_ADDRESS
STRUCT: IP_ADAPTER_DNS_SERVER_ADDRESS
{ Header AlignmentLenFlags }
{ Next IP_ADAPTER_DNS_SERVER_ADDRESS* }
{ Address SOCKET_ADDRESS } ;
TYPEDEF: IP_ADAPTER_DNS_SERVER_ADDRESS* PIP_ADAPTER_DNS_SERVER_ADDRESS
DEFER: IP_ADAPTER_WINS_SERVER_ADDRESS
STRUCT: IP_ADAPTER_WINS_SERVER_ADDRESS
{ Header AlignmentLenFlags }
{ Next IP_ADAPTER_WINS_SERVER_ADDRESS* }
{ Address SOCKET_ADDRESS } ;
TYPEDEF: IP_ADAPTER_WINS_SERVER_ADDRESS* PIP_ADAPTER_WINS_SERVER_ADDRESS
TYPEDEF: IP_ADAPTER_WINS_SERVER_ADDRESS* PIP_ADAPTER_WINS_SERVER_ADDRESS_LH
DEFER: IP_ADAPTER_GATEWAY_ADDRESS
STRUCT: IP_ADAPTER_GATEWAY_ADDRESS
{ Header AlignmentLenFlags }
{ Next IP_ADAPTER_GATEWAY_ADDRESS* }
{ Address SOCKET_ADDRESS } ;
TYPEDEF: IP_ADAPTER_GATEWAY_ADDRESS* PIP_ADAPTER_GATEWAY_ADDRESS
TYPEDEF: IP_ADAPTER_GATEWAY_ADDRESS* PIP_ADAPTER_GATEWAY_ADDRESS_LH
DEFER: IP_ADAPTER_PREFIX
STRUCT: IP_ADAPTER_PREFIX
{ Header AlignmentLenFlags }
{ Next IP_ADAPTER_PREFIX* }
{ Address SOCKET_ADDRESS }
{ PrefixLength ULONG } ;
TYPEDEF: IP_ADAPTER_PREFIX* PIP_ADAPTER_PREFIX
DEFER: IP_ADAPTER_DNS_SUFFIX
STRUCT: IP_ADAPTER_DNS_SUFFIX
{ Next IP_ADAPTER_DNS_SUFFIX* }
{ String WCHAR[MAX_DNS_SUFFIX_STRING_LENGTH] } ;
TYPEDEF: IP_ADAPTER_DNS_SUFFIX* PIP_ADAPTER_DNS_SUFFIX
CONSTANT: GAA_FLAG_SKIP_UNICAST 0x0001
CONSTANT: GAA_FLAG_SKIP_ANYCAST 0x0002
CONSTANT: GAA_FLAG_SKIP_MULTICAST 0x0004
CONSTANT: GAA_FLAG_SKIP_DNS_SERVER 0x0008
CONSTANT: GAA_FLAG_INCLUDE_PREFIX 0x0010
CONSTANT: GAA_FLAG_SKIP_FRIENDLY_NAME 0x0020
CONSTANT: GAA_FLAG_INCLUDE_WINS_INFO 0x0040
CONSTANT: GAA_FLAG_INCLUDE_GATEWAYS 0x0080
CONSTANT: GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100
CONSTANT: GAA_FLAG_INCLUDE_ALL_COMPARTMENTS 0x0200
CONSTANT: GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER 0x0400
STRUCT: IP_ADAPTER_ADDRESSES
{ Header AlignmentLenIndex }
{ Next IP_ADAPTER_ADDRESSES* }
{ AdapterName PCHAR }
{ FirstUnicastAddress PIP_ADAPTER_UNICAST_ADDRESS }
{ FirstAnycastAddress PIP_ADAPTER_ANYCAST_ADDRESS }
{ FirstMulticastAddress PIP_ADAPTER_MULTICAST_ADDRESS }
{ FirstDnsServerAddress PIP_ADAPTER_DNS_SERVER_ADDRESS }
{ DnsSuffix PWCHAR }
{ Description PWCHAR }
{ FriendlyName PWCHAR }
{ PhysicalAddress BYTE[MAX_ADAPTER_ADDRESS_LENGTH] }
{ PhysicalAddressLength DWORD }
{ Flags DWORD }
{ Mtu DWORD }
{ IfType DWORD }
{ OperStatus IF_OPER_STATUS }
{ Ipv6IfIndex DWORD }
{ ZoneIndices DWORD[16] }
{ FirstPrefix PIP_ADAPTER_PREFIX }
{ TransmitLinkSpeed ULONG64 }
{ ReceiveLinkSpeed ULONG64 }
{ FirstWinsServerAddress PIP_ADAPTER_WINS_SERVER_ADDRESS_LH }
{ FirstGatewayAddress PIP_ADAPTER_GATEWAY_ADDRESS_LH }
{ Ipv4Metric ULONG }
{ Ipv6Metric ULONG }
{ Luid IF_LUID }
{ Dhcpv4Server SOCKET_ADDRESS }
{ CompartmentId NET_IF_COMPARTMENT_ID }
{ NetworkGuid NET_IF_NETWORK_GUID }
{ ConnectionType NET_IF_CONNECTION_TYPE }
{ TunnelType TUNNEL_TYPE }
{ Dhcpv6Server SOCKET_ADDRESS }
{ Dhcpv6ClientDuid BYTE[MAX_DHCPV6_DUID_LENGTH] }
{ Dhcpv6ClientDuidLength ULONG }
{ Dhcpv6Iaid ULONG }
{ FirstDnsSuffix PIP_ADAPTER_DNS_SUFFIX } ;
TYPEDEF: IP_ADAPTER_ADDRESSES* PIP_ADAPTER_ADDRESSES
TYPEDEF: FIXED_INFO* PFIXED_INFO
STRUCT: S_un_b
{ s_b1 uchar }
{ s_b2 uchar }
{ s_b3 uchar }
{ s_b4 uchar } ;
STRUCT: S_un_w
{ s_w1 ushort }
{ s_w2 ushort } ;
UNION-STRUCT: IPAddr
{ S_un_b S_un_b }
{ S_un_w S_un_w }
{ S_addr ulong } ;
UNION-STRUCT: S_un
{ S_un_b S_un_b }
{ S_un_w S_un_w }
{ S_addr ulong } ;
STRUCT: IP_ADAPTER_INDEX_MAP
{ Index ULONG }
{ Name WCHAR[MAX_ADAPTER_NAME] } ;
TYPEDEF: IP_ADAPTER_INDEX_MAP* PIP_ADAPTER_INDEX_MAP
FUNCTION: DWORD IpReleaseAddress ( PIP_ADAPTER_INDEX_MAP AdapterInfo ) ;
FUNCTION: DWORD IpRenewAddress ( PIP_ADAPTER_INDEX_MAP AdapterInfo ) ;
FUNCTION: DWORD GetBestInterface (
IPAddr dwDestAddr,
PDWORD pdwBestIfIndex
) ;
FUNCTION: DWORD GetBestInterfaceEx (
sockaddr* pDestAddr,
PDWORD pdwBestIfIndex
) ;
FUNCTION: ULONG GetAdaptersAddresses (
ULONG Family,
ULONG Flags,
PVOID Reserved,
PIP_ADAPTER_ADDRESSES AdapterAddresses,
PULONG SizePointer
) ;
! Deprecated
FUNCTION: DWORD GetAdaptersInfo (
PIP_ADAPTER_INFO pAdapterInfo,
PULONG pOutBufLen ) ;
FUNCTION: DWORD GetNetworkParams ( PFIXED_INFO pFixedInfo, PULONG pOutBufLen ) ;
: get-fixed-info ( -- FIXED_INFO )
FIXED_INFO <struct> dup byte-length ulong <ref>
[ GetNetworkParams n>win32-error-check ] 2keep drop ;
: dns-server-ips ( -- sequence )
get-fixed-info DnsServerList>> [
[
[ IpAddress>> String>> [ 0 = ] trim-tail utf8 decode , ]
[ Next>> ] bi dup
] loop drop
] { } make ;
! second struct starts at 720h
<PRIVATE
: loop-list ( obj -- seq )
[ [ dup [ Next>> ] when ] keep ] loop>array nip ;
! Don't use this, use each/map-adapters
: iterate-interfaces ( -- seq )
AF_UNSPEC GAA_FLAG_INCLUDE_PREFIX 0 uint <ref>
65,536 [ malloc &free ] [ ULONG <ref> ] bi
[ GetAdaptersAddresses win32-error=0/f ] 2keep
uint deref drop
IP_ADAPTER_ADDRESSES memory>struct loop-list ;
PRIVATE>
: interfaces-each ( quot -- seq )
[ [ iterate-interfaces ] dip each ] with-destructors ; inline
: interfaces-map ( quot -- seq )
[ [ iterate-interfaces ] dip { } map-as ] with-destructors ; inline
: interface-mac-addrs ( -- seq )
[
{
[ Description>> ]
[ [ PhysicalAddress>> ] [ PhysicalAddressLength>> ] bi head ]
} cleave>array
] interfaces-map ;
: interface-ips ( -- seq )
[
{
[ Description>> ]
[ FirstUnicastAddress>> loop-list [ Address>> SOCKET_ADDRESS>sockaddr sockaddr>ip ] map ]
} cleave>array
] interfaces-map ;
: get-best-interface ( inet -- interface )
make-sockaddr 0 DWORD <ref>
[ GetBestInterfaceEx win32-error=0/f ] keep DWORD deref ;