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
49 STRUCT: IP_ADDRESS_STRING
53 TYPEDEF: IP_ADDRESS_STRING* PIP_ADDRESS_STRING
54 TYPEDEF: IP_ADDRESS_STRING IP_MASK_STRING
55 TYPEDEF: IP_MASK_STRING* PIP_MASK_STRING
58 STRUCT: IP_ADDR_STRING
59 { Next IP_ADDR_STRING* }
60 { IpAddress IP_ADDRESS_STRING }
61 { IpMask IP_MASK_STRING }
64 TYPEDEF: IP_ADDR_STRING* PIP_ADDR_STRING
67 { HostName char[MAX_HOSTNAME_LEN+4] }
68 { DomainName char[MAX_DOMAIN_NAME_LEN+4] }
69 { CurrentDnsServer PIP_ADDR_STRING }
70 { DnsServerList IP_ADDR_STRING }
72 { ScopeId char[MAX_SCOPE_ID_LEN+4] }
73 { EnableRouting UINT }
76 { ExtraSpace char[4096] } ;
78 DEFER: IP_ADAPTER_INFO
82 TYPEDEF: uint NET_IF_COMPARTMENT_ID
83 TYPEDEF: GUID NET_IF_NETWORK_GUID
92 ENUM: IP_PREFIX_ORIGIN
95 IpPrefixOriginWellKnown,
97 IpPrefixOriginRouterAdvertisement,
98 { IpPrefixOriginUnchanged 16 } ;
100 ENUM: IP_SUFFIX_ORIGIN
102 IpSuffixOriginManual,
103 IpSuffixOriginWellKnown,
105 IpSuffixOriginLinkLayerAddress,
106 IpSuffixOriginRandom,
107 { IpSuffixOriginUnchanged 16 } ;
115 IfOperStatusNotPresent,
116 IfOperStatusLowerLayerDown ;
118 ENUM: NET_IF_CONNECTION_TYPE
119 { NET_IF_CONNECTION_DEDICATED 1 }
120 NET_IF_CONNECTION_PASSIVE,
121 NET_IF_CONNECTION_DEMAND,
122 NET_IF_CONNECTION_MAXIMUM ;
132 TUNNEL_TYPE_IPHTTPS ;
136 STRUCT: SOCKET_ADDRESS
137 { lpSockaddr LPSOCKADDR }
138 { iSockaddrLength INT } ;
140 ERROR: unknown-sockaddr-length sockaddr length ;
142 : SOCKET_ADDRESS>sockaddr ( obj -- sockaddr )
143 dup iSockaddrLength>> {
144 { 16 [ lpSockaddr>> sockaddr-in memory>struct ] }
145 { 28 [ lpSockaddr>> sockaddr-in6 memory>struct ] }
146 [ unknown-sockaddr-length ]
149 TYPEDEF: SOCKET_ADDRESS* PSOCKET_ADDRESS
151 STRUCT: IP_ADAPTER_INFO
152 { Next IP_ADAPTER_INFO* }
154 { AdapterName char[MAX_ADAPTER_NAME_LENGTH+4] }
155 { Description char[MAX_ADAPTER_DESCRIPTION_LENGTH+4] }
156 { AddressLength UINT }
157 { Address BYTE[MAX_ADAPTER_ADDRESS_LENGTH] }
161 { CurrentIpAddress PIP_ADDR_STRING }
162 { IpAddressList IP_ADDR_STRING }
163 { GatewayList IP_ADDR_STRING }
164 { DhcpServer IP_ADDR_STRING }
166 { PrimaryWinsServer IP_ADDR_STRING }
167 { SecondaryWinsServer IP_ADDR_STRING }
168 { LeaseObtained time_t }
169 { LeaseExpires time_t } ;
171 TYPEDEF: IP_ADAPTER_INFO* PIP_ADAPTER_INFO
177 TYPEDEF: LengthIndex LengthFlags
179 UNION-STRUCT: AlignmentLenIndex
180 { Alignment ULONGLONG }
181 { LenIndex LengthIndex } ;
183 UNION-STRUCT: AlignmentLenFlags
184 { Alignment ULONGLONG }
185 { LenFlags LengthFlags } ;
188 { Reserved ULONG64 bits: 24 }
189 { NetLuidIndex ULONG64 bits: 24 }
190 { IfType ULONG64 bits: 16 } ;
192 UNION-STRUCT: NET_LUID
196 TYPEDEF: NET_LUID* PNET_LUID
197 TYPEDEF: NET_LUID IF_LUID
199 DEFER: IP_ADAPTER_ADDRESSES
200 DEFER: IP_ADAPTER_UNICAST_ADDRESS
201 STRUCT: IP_ADAPTER_UNICAST_ADDRESS
202 { Header LengthFlags }
203 { Next IP_ADAPTER_UNICAST_ADDRESS* }
204 { Address SOCKET_ADDRESS }
205 { PrefixOrigin IP_PREFIX_ORIGIN }
206 { SuffixOrigin IP_SUFFIX_ORIGIN }
207 { DadState IP_DAD_STATE }
208 { ValidLifetime ULONG }
209 { PreferredLifetime ULONG }
210 { LeaseLifeTime ULONG }
211 { OnLinkPrefixLength UINT8 } ;
213 TYPEDEF: IP_ADAPTER_UNICAST_ADDRESS* PIP_ADAPTER_UNICAST_ADDRESS
215 DEFER: IP_ADAPTER_ANYCAST_ADDRESS
216 STRUCT: IP_ADAPTER_ANYCAST_ADDRESS
217 { Header AlignmentLenFlags }
218 { Next IP_ADAPTER_ANYCAST_ADDRESS* }
219 { Address SOCKET_ADDRESS } ;
221 TYPEDEF: IP_ADAPTER_ANYCAST_ADDRESS* PIP_ADAPTER_ANYCAST_ADDRESS
224 DEFER: IP_ADAPTER_MULTICAST_ADDRESS
225 STRUCT: IP_ADAPTER_MULTICAST_ADDRESS
226 { Header AlignmentLenFlags }
227 { Next IP_ADAPTER_MULTICAST_ADDRESS* }
228 { Address SOCKET_ADDRESS } ;
230 TYPEDEF: IP_ADAPTER_MULTICAST_ADDRESS* PIP_ADAPTER_MULTICAST_ADDRESS
233 DEFER: IP_ADAPTER_DNS_SERVER_ADDRESS
234 STRUCT: IP_ADAPTER_DNS_SERVER_ADDRESS
235 { Header AlignmentLenFlags }
236 { Next IP_ADAPTER_DNS_SERVER_ADDRESS* }
237 { Address SOCKET_ADDRESS } ;
239 TYPEDEF: IP_ADAPTER_DNS_SERVER_ADDRESS* PIP_ADAPTER_DNS_SERVER_ADDRESS
242 DEFER: IP_ADAPTER_WINS_SERVER_ADDRESS
243 STRUCT: IP_ADAPTER_WINS_SERVER_ADDRESS
244 { Header AlignmentLenFlags }
245 { Next IP_ADAPTER_WINS_SERVER_ADDRESS* }
246 { Address SOCKET_ADDRESS } ;
248 TYPEDEF: IP_ADAPTER_WINS_SERVER_ADDRESS* PIP_ADAPTER_WINS_SERVER_ADDRESS
250 TYPEDEF: IP_ADAPTER_WINS_SERVER_ADDRESS* PIP_ADAPTER_WINS_SERVER_ADDRESS_LH
254 DEFER: IP_ADAPTER_GATEWAY_ADDRESS
255 STRUCT: IP_ADAPTER_GATEWAY_ADDRESS
256 { Header AlignmentLenFlags }
257 { Next IP_ADAPTER_GATEWAY_ADDRESS* }
258 { Address SOCKET_ADDRESS } ;
260 TYPEDEF: IP_ADAPTER_GATEWAY_ADDRESS* PIP_ADAPTER_GATEWAY_ADDRESS
262 TYPEDEF: IP_ADAPTER_GATEWAY_ADDRESS* PIP_ADAPTER_GATEWAY_ADDRESS_LH
264 DEFER: IP_ADAPTER_PREFIX
265 STRUCT: IP_ADAPTER_PREFIX
266 { Header AlignmentLenFlags }
267 { Next IP_ADAPTER_PREFIX* }
268 { Address SOCKET_ADDRESS }
269 { PrefixLength ULONG } ;
271 TYPEDEF: IP_ADAPTER_PREFIX* PIP_ADAPTER_PREFIX
274 DEFER: IP_ADAPTER_DNS_SUFFIX
275 STRUCT: IP_ADAPTER_DNS_SUFFIX
276 { Next IP_ADAPTER_DNS_SUFFIX* }
277 { String WCHAR[MAX_DNS_SUFFIX_STRING_LENGTH] } ;
279 TYPEDEF: IP_ADAPTER_DNS_SUFFIX* PIP_ADAPTER_DNS_SUFFIX
282 CONSTANT: GAA_FLAG_SKIP_UNICAST 0x0001
283 CONSTANT: GAA_FLAG_SKIP_ANYCAST 0x0002
284 CONSTANT: GAA_FLAG_SKIP_MULTICAST 0x0004
285 CONSTANT: GAA_FLAG_SKIP_DNS_SERVER 0x0008
286 CONSTANT: GAA_FLAG_INCLUDE_PREFIX 0x0010
287 CONSTANT: GAA_FLAG_SKIP_FRIENDLY_NAME 0x0020
288 CONSTANT: GAA_FLAG_INCLUDE_WINS_INFO 0x0040
289 CONSTANT: GAA_FLAG_INCLUDE_GATEWAYS 0x0080
290 CONSTANT: GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100
291 CONSTANT: GAA_FLAG_INCLUDE_ALL_COMPARTMENTS 0x0200
292 CONSTANT: GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER 0x0400
294 STRUCT: IP_ADAPTER_ADDRESSES
295 { Header AlignmentLenIndex }
296 { Next IP_ADAPTER_ADDRESSES* }
297 { AdapterName PCHAR }
298 { FirstUnicastAddress PIP_ADAPTER_UNICAST_ADDRESS }
299 { FirstAnycastAddress PIP_ADAPTER_ANYCAST_ADDRESS }
300 { FirstMulticastAddress PIP_ADAPTER_MULTICAST_ADDRESS }
301 { FirstDnsServerAddress PIP_ADAPTER_DNS_SERVER_ADDRESS }
303 { Description PWCHAR }
304 { FriendlyName PWCHAR }
305 { PhysicalAddress BYTE[MAX_ADAPTER_ADDRESS_LENGTH] }
306 { PhysicalAddressLength DWORD }
310 { OperStatus IF_OPER_STATUS }
311 { Ipv6IfIndex DWORD }
312 { ZoneIndices DWORD[16] }
313 { FirstPrefix PIP_ADAPTER_PREFIX }
314 { TransmitLinkSpeed ULONG64 }
315 { ReceiveLinkSpeed ULONG64 }
316 { FirstWinsServerAddress PIP_ADAPTER_WINS_SERVER_ADDRESS_LH }
317 { FirstGatewayAddress PIP_ADAPTER_GATEWAY_ADDRESS_LH }
321 { Dhcpv4Server SOCKET_ADDRESS }
322 { CompartmentId NET_IF_COMPARTMENT_ID }
323 { NetworkGuid NET_IF_NETWORK_GUID }
324 { ConnectionType NET_IF_CONNECTION_TYPE }
325 { TunnelType TUNNEL_TYPE }
326 { Dhcpv6Server SOCKET_ADDRESS }
327 { Dhcpv6ClientDuid BYTE[MAX_DHCPV6_DUID_LENGTH] }
328 { Dhcpv6ClientDuidLength ULONG }
330 { FirstDnsSuffix PIP_ADAPTER_DNS_SUFFIX } ;
332 TYPEDEF: IP_ADAPTER_ADDRESSES* PIP_ADAPTER_ADDRESSES
334 TYPEDEF: FIXED_INFO* PFIXED_INFO
356 STRUCT: IP_ADAPTER_INDEX_MAP
358 { Name WCHAR[MAX_ADAPTER_NAME] } ;
359 TYPEDEF: IP_ADAPTER_INDEX_MAP* PIP_ADAPTER_INDEX_MAP
361 FUNCTION: DWORD IpReleaseAddress ( PIP_ADAPTER_INDEX_MAP AdapterInfo )
362 FUNCTION: DWORD IpRenewAddress ( PIP_ADAPTER_INDEX_MAP AdapterInfo )
365 FUNCTION: DWORD GetBestInterface (
367 PDWORD pdwBestIfIndex
370 FUNCTION: DWORD GetBestInterfaceEx (
372 PDWORD pdwBestIfIndex
375 FUNCTION: ULONG GetAdaptersAddresses (
379 PIP_ADAPTER_ADDRESSES AdapterAddresses,
384 FUNCTION: DWORD GetAdaptersInfo (
385 PIP_ADAPTER_INFO pAdapterInfo,
388 FUNCTION: DWORD GetNetworkParams ( PFIXED_INFO pFixedInfo, PULONG pOutBufLen )
390 : get-fixed-info ( -- FIXED_INFO )
391 FIXED_INFO new dup byte-length ulong <ref>
392 [ GetNetworkParams n>win32-error-check ] keepd ;
394 : dns-server-ips ( -- sequence )
395 get-fixed-info DnsServerList>> [
397 [ IpAddress>> String>> [ 0 = ] trim-tail utf8 decode , ]
403 ! second struct starts at 720h
408 : loop-list ( obj -- seq )
411 ! Don't use this, use each/map-adapters
412 : iterate-interfaces ( -- seq )
413 AF_UNSPEC GAA_FLAG_INCLUDE_PREFIX 0 uint <ref>
414 65,536 [ malloc &free ] [ ULONG <ref> ] bi
415 [ GetAdaptersAddresses win32-error=0/f ] 2keep
417 IP_ADAPTER_ADDRESSES memory>struct loop-list ;
421 : interfaces-each ( quot -- seq )
422 [ [ iterate-interfaces ] dip each ] with-destructors ; inline
424 : interfaces-map ( quot -- seq )
425 [ [ iterate-interfaces ] dip { } map-as ] with-destructors ; inline
427 : interface-mac-addrs ( -- seq )
431 [ [ PhysicalAddress>> ] [ PhysicalAddressLength>> ] bi head ]
435 : interface-ips ( -- seq )
439 [ FirstUnicastAddress>> loop-list [ Address>> SOCKET_ADDRESS>sockaddr sockaddr>ip ] map ]
443 : get-best-interface ( inet -- interface )
444 make-sockaddr 0 DWORD <ref>
445 [ GetBestInterfaceEx win32-error=0/f ] keep DWORD deref ;