1 ! Copyright (C) 2010 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien alien.c-types alien.data alien.syntax
4 classes.struct combinators combinators.smart destructors
5 io.encodings.string io.encodings.utf8 io.sockets.private kernel
6 libc make sequences windows.errors windows.kernel32
7 windows.types windows.winsock ;
13 CONSTANT: DEFAULT_MINIMUM_ENTITIES 32
14 CONSTANT: MAX_ADAPTER_ADDRESS_LENGTH 8
15 CONSTANT: MAX_ADAPTER_DESCRIPTION_LENGTH 128
16 CONSTANT: MAX_ADAPTER_NAME_LENGTH 256
17 CONSTANT: MAX_DOMAIN_NAME_LEN 128
18 CONSTANT: MAX_HOSTNAME_LEN 128
19 CONSTANT: MAX_SCOPE_ID_LEN 256
20 CONSTANT: BROADCAST_NODETYPE 1
21 CONSTANT: PEER_TO_PEER_NODETYPE 2
22 CONSTANT: MIXED_NODETYPE 4
23 CONSTANT: HYBRID_NODETYPE 8
24 CONSTANT: IF_OTHER_ADAPTERTYPE 0
25 CONSTANT: IF_ETHERNET_ADAPTERTYPE 1
26 CONSTANT: IF_TOKEN_RING_ADAPTERTYPE 2
27 CONSTANT: IF_FDDI_ADAPTERTYPE 3
28 CONSTANT: IF_PPP_ADAPTERTYPE 4
29 CONSTANT: IF_LOOPBACK_ADAPTERTYPE 5
32 CONSTANT: MAX_DOMAIN_NAME_LEN+4 132
33 CONSTANT: MAX_HOSTNAME_LEN+4 132
34 CONSTANT: MAX_SCOPE_ID_LEN+4 260
35 CONSTANT: MAX_ADAPTER_NAME_LENGTH+4 264
36 CONSTANT: MAX_ADAPTER_DESCRIPTION_LENGTH+4 136
37 CONSTANT: ERROR_BUFFER_OVERFLOW 111
38 CONSTANT: MIB_IF_TYPE_ETHERNET 6
39 CONSTANT: MIB_IF_TYPE_TOKENRING 9
40 CONSTANT: MIB_IF_TYPE_FDDI 15
41 CONSTANT: MIB_IF_TYPE_PPP 23
42 CONSTANT: MIB_IF_TYPE_LOOPBACK 24
43 CONSTANT: MIB_IF_TYPE_SLIP 28
44 CONSTANT: MAX_DNS_SUFFIX_STRING_LENGTH 256 ! 246?
45 CONSTANT: MAX_DHCPV6_DUID_LENGTH 130
46 CONSTANT: MAX_ADAPTER_NAME 128
48 STRUCT: IP_ADDRESS_STRING
51 TYPEDEF: IP_ADDRESS_STRING* PIP_ADDRESS_STRING
52 TYPEDEF: IP_ADDRESS_STRING IP_MASK_STRING
53 TYPEDEF: IP_MASK_STRING* PIP_MASK_STRING
55 STRUCT: IP_ADDR_STRING
56 { Next IP_ADDR_STRING* }
57 { IpAddress IP_ADDRESS_STRING }
58 { IpMask IP_MASK_STRING }
61 TYPEDEF: IP_ADDR_STRING* PIP_ADDR_STRING
64 { HostName char[MAX_HOSTNAME_LEN+4] }
65 { DomainName char[MAX_DOMAIN_NAME_LEN+4] }
66 { CurrentDnsServer PIP_ADDR_STRING }
67 { DnsServerList IP_ADDR_STRING }
69 { ScopeId char[MAX_SCOPE_ID_LEN+4] }
70 { EnableRouting UINT }
73 { ExtraSpace char[4096] } ;
75 DEFER: IP_ADAPTER_INFO
79 TYPEDEF: uint NET_IF_COMPARTMENT_ID
80 TYPEDEF: GUID NET_IF_NETWORK_GUID
89 ENUM: IP_PREFIX_ORIGIN
92 IpPrefixOriginWellKnown,
94 IpPrefixOriginRouterAdvertisement,
95 { IpPrefixOriginUnchanged 16 } ;
97 ENUM: IP_SUFFIX_ORIGIN
100 IpSuffixOriginWellKnown,
102 IpSuffixOriginLinkLayerAddress,
103 IpSuffixOriginRandom,
104 { IpSuffixOriginUnchanged 16 } ;
112 IfOperStatusNotPresent,
113 IfOperStatusLowerLayerDown ;
115 ENUM: NET_IF_CONNECTION_TYPE
116 { NET_IF_CONNECTION_DEDICATED 1 }
117 NET_IF_CONNECTION_PASSIVE,
118 NET_IF_CONNECTION_DEMAND,
119 NET_IF_CONNECTION_MAXIMUM ;
129 TUNNEL_TYPE_IPHTTPS ;
133 STRUCT: SOCKET_ADDRESS
134 { lpSockaddr LPSOCKADDR }
135 { iSockaddrLength INT } ;
137 ERROR: unknown-sockaddr-length sockaddr length ;
139 : SOCKET_ADDRESS>sockaddr ( obj -- sockaddr )
140 dup iSockaddrLength>> {
141 { 16 [ lpSockaddr>> sockaddr-in memory>struct ] }
142 { 28 [ lpSockaddr>> sockaddr-in6 memory>struct ] }
143 [ unknown-sockaddr-length ]
146 TYPEDEF: SOCKET_ADDRESS* PSOCKET_ADDRESS
148 STRUCT: IP_ADAPTER_INFO
149 { Next IP_ADAPTER_INFO* }
151 { AdapterName char[MAX_ADAPTER_NAME_LENGTH+4] }
152 { Description char[MAX_ADAPTER_DESCRIPTION_LENGTH+4] }
153 { AddressLength UINT }
154 { Address BYTE[MAX_ADAPTER_ADDRESS_LENGTH] }
158 { CurrentIpAddress PIP_ADDR_STRING }
159 { IpAddressList IP_ADDR_STRING }
160 { GatewayList IP_ADDR_STRING }
161 { DhcpServer IP_ADDR_STRING }
163 { PrimaryWinsServer IP_ADDR_STRING }
164 { SecondaryWinsServer IP_ADDR_STRING }
165 { LeaseObtained time_t }
166 { LeaseExpires time_t } ;
168 TYPEDEF: IP_ADAPTER_INFO* PIP_ADAPTER_INFO
174 TYPEDEF: LengthIndex LengthFlags
176 UNION-STRUCT: AlignmentLenIndex
177 { Alignment ULONGLONG }
178 { LenIndex LengthIndex } ;
180 UNION-STRUCT: AlignmentLenFlags
181 { Alignment ULONGLONG }
182 { LenFlags LengthFlags } ;
185 { Reserved ULONG64 bits: 24 }
186 { NetLuidIndex ULONG64 bits: 24 }
187 { IfType ULONG64 bits: 16 } ;
189 UNION-STRUCT: NET_LUID
193 TYPEDEF: NET_LUID* PNET_LUID
194 TYPEDEF: NET_LUID IF_LUID
196 DEFER: IP_ADAPTER_ADDRESSES
197 DEFER: IP_ADAPTER_UNICAST_ADDRESS
198 STRUCT: IP_ADAPTER_UNICAST_ADDRESS
199 { Header LengthFlags }
200 { Next IP_ADAPTER_UNICAST_ADDRESS* }
201 { Address SOCKET_ADDRESS }
202 { PrefixOrigin IP_PREFIX_ORIGIN }
203 { SuffixOrigin IP_SUFFIX_ORIGIN }
204 { DadState IP_DAD_STATE }
205 { ValidLifetime ULONG }
206 { PreferredLifetime ULONG }
207 { LeaseLifeTime ULONG }
208 { OnLinkPrefixLength UINT8 } ;
210 TYPEDEF: IP_ADAPTER_UNICAST_ADDRESS* PIP_ADAPTER_UNICAST_ADDRESS
212 DEFER: IP_ADAPTER_ANYCAST_ADDRESS
213 STRUCT: IP_ADAPTER_ANYCAST_ADDRESS
214 { Header AlignmentLenFlags }
215 { Next IP_ADAPTER_ANYCAST_ADDRESS* }
216 { Address SOCKET_ADDRESS } ;
218 TYPEDEF: IP_ADAPTER_ANYCAST_ADDRESS* PIP_ADAPTER_ANYCAST_ADDRESS
221 DEFER: IP_ADAPTER_MULTICAST_ADDRESS
222 STRUCT: IP_ADAPTER_MULTICAST_ADDRESS
223 { Header AlignmentLenFlags }
224 { Next IP_ADAPTER_MULTICAST_ADDRESS* }
225 { Address SOCKET_ADDRESS } ;
227 TYPEDEF: IP_ADAPTER_MULTICAST_ADDRESS* PIP_ADAPTER_MULTICAST_ADDRESS
230 DEFER: IP_ADAPTER_DNS_SERVER_ADDRESS
231 STRUCT: IP_ADAPTER_DNS_SERVER_ADDRESS
232 { Header AlignmentLenFlags }
233 { Next IP_ADAPTER_DNS_SERVER_ADDRESS* }
234 { Address SOCKET_ADDRESS } ;
236 TYPEDEF: IP_ADAPTER_DNS_SERVER_ADDRESS* PIP_ADAPTER_DNS_SERVER_ADDRESS
239 DEFER: IP_ADAPTER_WINS_SERVER_ADDRESS
240 STRUCT: IP_ADAPTER_WINS_SERVER_ADDRESS
241 { Header AlignmentLenFlags }
242 { Next IP_ADAPTER_WINS_SERVER_ADDRESS* }
243 { Address SOCKET_ADDRESS } ;
245 TYPEDEF: IP_ADAPTER_WINS_SERVER_ADDRESS* PIP_ADAPTER_WINS_SERVER_ADDRESS
247 TYPEDEF: IP_ADAPTER_WINS_SERVER_ADDRESS* PIP_ADAPTER_WINS_SERVER_ADDRESS_LH
251 DEFER: IP_ADAPTER_GATEWAY_ADDRESS
252 STRUCT: IP_ADAPTER_GATEWAY_ADDRESS
253 { Header AlignmentLenFlags }
254 { Next IP_ADAPTER_GATEWAY_ADDRESS* }
255 { Address SOCKET_ADDRESS } ;
257 TYPEDEF: IP_ADAPTER_GATEWAY_ADDRESS* PIP_ADAPTER_GATEWAY_ADDRESS
259 TYPEDEF: IP_ADAPTER_GATEWAY_ADDRESS* PIP_ADAPTER_GATEWAY_ADDRESS_LH
261 DEFER: IP_ADAPTER_PREFIX
262 STRUCT: IP_ADAPTER_PREFIX
263 { Header AlignmentLenFlags }
264 { Next IP_ADAPTER_PREFIX* }
265 { Address SOCKET_ADDRESS }
266 { PrefixLength ULONG } ;
268 TYPEDEF: IP_ADAPTER_PREFIX* PIP_ADAPTER_PREFIX
271 DEFER: IP_ADAPTER_DNS_SUFFIX
272 STRUCT: IP_ADAPTER_DNS_SUFFIX
273 { Next IP_ADAPTER_DNS_SUFFIX* }
274 { String WCHAR[MAX_DNS_SUFFIX_STRING_LENGTH] } ;
276 TYPEDEF: IP_ADAPTER_DNS_SUFFIX* PIP_ADAPTER_DNS_SUFFIX
279 CONSTANT: GAA_FLAG_SKIP_UNICAST 0x0001
280 CONSTANT: GAA_FLAG_SKIP_ANYCAST 0x0002
281 CONSTANT: GAA_FLAG_SKIP_MULTICAST 0x0004
282 CONSTANT: GAA_FLAG_SKIP_DNS_SERVER 0x0008
283 CONSTANT: GAA_FLAG_INCLUDE_PREFIX 0x0010
284 CONSTANT: GAA_FLAG_SKIP_FRIENDLY_NAME 0x0020
285 CONSTANT: GAA_FLAG_INCLUDE_WINS_INFO 0x0040
286 CONSTANT: GAA_FLAG_INCLUDE_GATEWAYS 0x0080
287 CONSTANT: GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100
288 CONSTANT: GAA_FLAG_INCLUDE_ALL_COMPARTMENTS 0x0200
289 CONSTANT: GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER 0x0400
291 STRUCT: IP_ADAPTER_ADDRESSES
292 { Header AlignmentLenIndex }
293 { Next IP_ADAPTER_ADDRESSES* }
294 { AdapterName PCHAR }
295 { FirstUnicastAddress PIP_ADAPTER_UNICAST_ADDRESS }
296 { FirstAnycastAddress PIP_ADAPTER_ANYCAST_ADDRESS }
297 { FirstMulticastAddress PIP_ADAPTER_MULTICAST_ADDRESS }
298 { FirstDnsServerAddress PIP_ADAPTER_DNS_SERVER_ADDRESS }
300 { Description PWCHAR }
301 { FriendlyName PWCHAR }
302 { PhysicalAddress BYTE[MAX_ADAPTER_ADDRESS_LENGTH] }
303 { PhysicalAddressLength DWORD }
307 { OperStatus IF_OPER_STATUS }
308 { Ipv6IfIndex DWORD }
309 { ZoneIndices DWORD[16] }
310 { FirstPrefix PIP_ADAPTER_PREFIX }
311 { TransmitLinkSpeed ULONG64 }
312 { ReceiveLinkSpeed ULONG64 }
313 { FirstWinsServerAddress PIP_ADAPTER_WINS_SERVER_ADDRESS_LH }
314 { FirstGatewayAddress PIP_ADAPTER_GATEWAY_ADDRESS_LH }
318 { Dhcpv4Server SOCKET_ADDRESS }
319 { CompartmentId NET_IF_COMPARTMENT_ID }
320 { NetworkGuid NET_IF_NETWORK_GUID }
321 { ConnectionType NET_IF_CONNECTION_TYPE }
322 { TunnelType TUNNEL_TYPE }
323 { Dhcpv6Server SOCKET_ADDRESS }
324 { Dhcpv6ClientDuid BYTE[MAX_DHCPV6_DUID_LENGTH] }
325 { Dhcpv6ClientDuidLength ULONG }
327 { FirstDnsSuffix PIP_ADAPTER_DNS_SUFFIX } ;
329 TYPEDEF: IP_ADAPTER_ADDRESSES* PIP_ADAPTER_ADDRESSES
331 TYPEDEF: FIXED_INFO* PFIXED_INFO
353 STRUCT: IP_ADAPTER_INDEX_MAP
355 { Name WCHAR[MAX_ADAPTER_NAME] } ;
356 TYPEDEF: IP_ADAPTER_INDEX_MAP* PIP_ADAPTER_INDEX_MAP
358 FUNCTION: DWORD IpReleaseAddress ( PIP_ADAPTER_INDEX_MAP AdapterInfo )
359 FUNCTION: DWORD IpRenewAddress ( PIP_ADAPTER_INDEX_MAP AdapterInfo )
362 FUNCTION: DWORD GetBestInterface (
364 PDWORD pdwBestIfIndex
367 FUNCTION: DWORD GetBestInterfaceEx (
369 PDWORD pdwBestIfIndex
372 FUNCTION: ULONG GetAdaptersAddresses (
376 PIP_ADAPTER_ADDRESSES AdapterAddresses,
381 FUNCTION: DWORD GetAdaptersInfo (
382 PIP_ADAPTER_INFO pAdapterInfo,
385 FUNCTION: DWORD GetNetworkParams ( PFIXED_INFO pFixedInfo, PULONG pOutBufLen )
387 : get-fixed-info ( -- FIXED_INFO )
388 FIXED_INFO new dup byte-length ulong <ref>
389 [ GetNetworkParams n>win32-error-check ] keepd ;
391 : dns-server-ips ( -- sequence )
392 get-fixed-info DnsServerList>> [
394 [ IpAddress>> String>> [ 0 = ] trim-tail utf8 decode , ]
400 ! second struct starts at 720h
405 : loop-list ( obj -- seq )
408 ! Don't use this, use each/map-adapters
409 : iterate-interfaces ( -- seq )
410 AF_UNSPEC GAA_FLAG_INCLUDE_PREFIX 0 uint <ref>
411 65,536 [ malloc &free ] [ ULONG <ref> ] bi
412 [ GetAdaptersAddresses win32-error=0/f ] 2keep
414 IP_ADAPTER_ADDRESSES memory>struct loop-list ;
418 : interfaces-each ( quot -- seq )
419 [ [ iterate-interfaces ] dip each ] with-destructors ; inline
421 : interfaces-map ( quot -- seq )
422 [ [ iterate-interfaces ] dip { } map-as ] with-destructors ; inline
424 : interface-mac-addrs ( -- seq )
428 [ [ PhysicalAddress>> ] [ PhysicalAddressLength>> ] bi head ]
432 : interface-ips ( -- seq )
436 [ FirstUnicastAddress>> loop-list [ Address>> SOCKET_ADDRESS>sockaddr sockaddr>ip ] map ]
440 : get-best-interface ( inet -- interface )
441 make-sockaddr 0 DWORD <ref>
442 [ GetBestInterfaceEx win32-error=0/f ] keep DWORD deref ;