1
# Copyright (c) Twisted Matrix Laboratories.
2
# See LICENSE for details.
5
Windows implementation of local network interface enumeration.
8
from socket import socket, AF_INET6, SOCK_STREAM
10
WinDLL, byref, create_string_buffer, c_int, c_void_p,
11
POINTER, Structure, cast, string_at)
13
WS2_32 = WinDLL('ws2_32')
19
LPWSAPROTOCOL_INFO = c_void_p
22
LPWSAOVERLAPPED = c_void_p
23
LPWSAOVERLAPPED_COMPLETION_ROUTINE = c_void_p
25
# http://msdn.microsoft.com/en-us/library/ms741621(v=VS.85).aspx
28
# __in DWORD dwIoControlCode,
29
# __in LPVOID lpvInBuffer,
30
# __in DWORD cbInBuffer,
31
# __out LPVOID lpvOutBuffer,
32
# __in DWORD cbOutBuffer,
33
# __out LPDWORD lpcbBytesReturned,
34
# __in LPWSAOVERLAPPED lpOverlapped,
35
# __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
37
WSAIoctl = WS2_32.WSAIoctl
39
SOCKET, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD,
40
LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE]
41
WSAIoctl.restype = c_int
43
# http://msdn.microsoft.com/en-us/library/ms741516(VS.85).aspx
44
# INT WSAAPI WSAAddressToString(
45
# __in LPSOCKADDR lpsaAddress,
46
# __in DWORD dwAddressLength,
47
# __in_opt LPWSAPROTOCOL_INFO lpProtocolInfo,
48
# __inout LPTSTR lpszAddressString,
49
# __inout LPDWORD lpdwAddressStringLength
51
WSAAddressToString = WS2_32.WSAAddressToStringA
52
WSAAddressToString.argtypes = [
53
LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFO, LPTSTR, LPDWORD]
54
WSAAddressToString.restype = c_int
57
SIO_ADDRESS_LIST_QUERY = 0x48000016
60
class SOCKET_ADDRESS(Structure):
61
_fields_ = [('lpSockaddr', c_void_p),
62
('iSockaddrLength', c_int)]
67
class SOCKET_ADDRESS_LIST(Structure):
68
_fields_ = [('iAddressCount', c_int),
69
('Address', SOCKET_ADDRESS * ln)]
70
return SOCKET_ADDRESS_LIST
74
def win32GetLinkLocalIPv6Addresses():
76
Return a list of strings in colon-hex format representing all the link local
77
IPv6 addresses available on the system, as reported by
78
I{WSAIoctl}/C{SIO_ADDRESS_LIST_QUERY}.
80
s = socket(AF_INET6, SOCK_STREAM)
84
buf = create_string_buffer(size)
87
SIO_ADDRESS_LIST_QUERY, 0, 0, buf, size, byref(retBytes), 0, 0)
89
# WSAIoctl might fail with WSAEFAULT, which means there was not enough
90
# space in the buffer we gave it. There's no way to check the errno
91
# until Python 2.6, so we don't even try. :/ Maybe if retBytes is still
92
# 0 another error happened, though.
93
if ret and retBytes.value:
98
# If it failed, then we'll just have to give up. Still no way to see why.
100
raise RuntimeError("WSAIoctl failure")
102
addrList = cast(buf, POINTER(make_SAL(0)))
103
addrCount = addrList[0].iAddressCount
104
addrList = cast(buf, POINTER(make_SAL(addrCount)))
106
addressStringBufLength = 1024
107
addressStringBuf = create_string_buffer(addressStringBufLength)
110
for i in range(addrList[0].iAddressCount):
111
retBytes.value = addressStringBufLength
112
address = addrList[0].Address[i]
113
ret = WSAAddressToString(
114
address.lpSockaddr, address.iSockaddrLength, 0, addressStringBuf,
117
raise RuntimeError("WSAAddressToString failure")
118
retList.append(string_at(addressStringBuf))
119
return [addr for addr in retList if '%' in addr]