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 addr = addrList[0].Address[i]
113 ret = WSAAddressToString(
114 addr.lpSockaddr, addr.iSockaddrLength, 0, addressStringBuf,
117 raise RuntimeError("WSAAddressToString failure")
118 retList.append(string_at(addressStringBuf))
119 return [addr for addr in retList if '%' in addr]