Adds cloudbaseinit.utils.windows.network module
Replaces WMI queries to obtain DHCP client configuration with Win32 calls in order to execute plugins that require DHCP options in the Specialize pass after Sysprep.
This commit is contained in:
parent
6ddd3f093a
commit
b96c547857
@ -29,6 +29,7 @@ from win32com import client
|
||||
|
||||
from cloudbaseinit.openstack.common import log as logging
|
||||
from cloudbaseinit.osutils import base
|
||||
from cloudbaseinit.utils.windows import network
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -465,12 +466,10 @@ class WindowsUtils(base.BaseOSUtils):
|
||||
|
||||
def get_dhcp_hosts_in_use(self):
|
||||
dhcp_hosts = []
|
||||
conn = wmi.WMI(moniker='//./root/cimv2')
|
||||
for net_cfg in conn.Win32_NetworkAdapterConfiguration(
|
||||
DHCPEnabled=True):
|
||||
if net_cfg.DHCPServer:
|
||||
dhcp_hosts.append((str(net_cfg.MACAddress),
|
||||
str(net_cfg.DHCPServer)))
|
||||
for net_addr in network.get_adapter_addresses():
|
||||
if net_addr["dhcp_enabled"]:
|
||||
dhcp_hosts.append((net_addr["mac_address"],
|
||||
net_addr["dhcp_server"]))
|
||||
return dhcp_hosts
|
||||
|
||||
def set_ntp_client_config(self, ntp_host):
|
||||
@ -491,15 +490,16 @@ class WindowsUtils(base.BaseOSUtils):
|
||||
raise Exception('Setting the MTU is currently not supported on '
|
||||
'Windows XP and Windows Server 2003')
|
||||
|
||||
conn = wmi.WMI(moniker='//./root/cimv2')
|
||||
net_cfg_list = conn.Win32_NetworkAdapterConfiguration(
|
||||
MACAddress=mac_address)
|
||||
iface_index_list = [
|
||||
net_addr["interface_index"] for net_addr
|
||||
in network.get_adapter_addresses()
|
||||
if net_addr["mac_address"] == mac_address]
|
||||
|
||||
if not net_cfg_list:
|
||||
if not iface_index_list:
|
||||
raise Exception('Network interface with MAC address "%s" '
|
||||
'not found' % mac_address)
|
||||
else:
|
||||
net_cfg = net_cfg_list[0]
|
||||
iface_index = iface_index_list[0]
|
||||
|
||||
LOG.debug('Setting MTU for interface "%(mac_address)s" with '
|
||||
'value "%(mtu)s"' %
|
||||
@ -509,7 +509,7 @@ class WindowsUtils(base.BaseOSUtils):
|
||||
netsh_path = os.path.join(base_dir, 'netsh.exe')
|
||||
|
||||
args = [netsh_path, "interface", "ipv4", "set", "subinterface",
|
||||
str(net_cfg.InterfaceIndex), "mtu=%s" % mtu,
|
||||
str(iface_index), "mtu=%s" % mtu,
|
||||
"store=persistent"]
|
||||
(out, err, ret_val) = self.execute_process(args, False)
|
||||
if ret_val:
|
||||
|
@ -1192,17 +1192,15 @@ class WindowsUtilsTest(unittest.TestCase):
|
||||
def test_execute_powershell_script_system32(self):
|
||||
self._test_execute_powershell_script(ret_val=False)
|
||||
|
||||
@mock.patch('wmi.WMI')
|
||||
def test_get_dhcp_hosts_in_use(self, mock_WMI):
|
||||
mock_net_cfg = mock.MagicMock()
|
||||
mock_net_cfg.MACAddress = 'fake mac address'
|
||||
mock_net_cfg.DHCPServer = 'fake dhcp server'
|
||||
mock_WMI().Win32_NetworkAdapterConfiguration.return_value = [
|
||||
mock_net_cfg]
|
||||
@mock.patch('cloudbaseinit.utils.windows.network.get_adapter_addresses')
|
||||
def test_get_dhcp_hosts_in_use(self, mock_get_adapter_addresses):
|
||||
net_addr = {}
|
||||
net_addr["mac_address"] = 'fake mac address'
|
||||
net_addr["dhcp_server"] = 'fake dhcp server'
|
||||
net_addr["dhcp_enabled"] = True
|
||||
mock_get_adapter_addresses.return_value = [net_addr]
|
||||
response = self._winutils.get_dhcp_hosts_in_use()
|
||||
mock_WMI.assert_called_with(moniker='//./root/cimv2')
|
||||
mock_WMI().Win32_NetworkAdapterConfiguration.assert_called_with(
|
||||
DHCPEnabled=True)
|
||||
mock_get_adapter_addresses.assert_called()
|
||||
self.assertEqual(response, [('fake mac address', 'fake dhcp server')])
|
||||
|
||||
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||
|
182
cloudbaseinit/utils/windows/iphlpapi.py
Normal file
182
cloudbaseinit/utils/windows/iphlpapi.py
Normal file
@ -0,0 +1,182 @@
|
||||
# Copyright 2014 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ctypes
|
||||
|
||||
from ctypes import windll
|
||||
from ctypes import wintypes
|
||||
|
||||
from cloudbaseinit.utils.windows import kernel32
|
||||
from cloudbaseinit.utils.windows import ws2_32
|
||||
|
||||
MAX_ADAPTER_NAME_LENGTH = 256
|
||||
MAX_ADAPTER_DESCRIPTION_LENGTH = 128
|
||||
MAX_ADAPTER_ADDRESS_LENGTH = 8
|
||||
|
||||
GAA_FLAG_SKIP_ANYCAST = 2
|
||||
GAA_FLAG_SKIP_ANYCAST = 4
|
||||
|
||||
IP_ADAPTER_DHCP_ENABLED = 4
|
||||
IP_ADAPTER_IPV4_ENABLED = 0x80
|
||||
IP_ADAPTER_IPV6_ENABLED = 0x0100
|
||||
|
||||
MAX_DHCPV6_DUID_LENGTH = 130
|
||||
|
||||
IF_TYPE_ETHERNET_CSMACD = 6
|
||||
IF_TYPE_SOFTWARE_LOOPBACK = 24
|
||||
IF_TYPE_IEEE80211 = 71
|
||||
IF_TYPE_TUNNEL = 131
|
||||
|
||||
IP_ADAPTER_ADDRESSES_SIZE_2003 = 144
|
||||
|
||||
|
||||
class SOCKET_ADDRESS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('lpSockaddr', ctypes.POINTER(ws2_32.SOCKADDR)),
|
||||
('iSockaddrLength', wintypes.INT),
|
||||
]
|
||||
|
||||
|
||||
class IP_ADAPTER_ADDRESSES_Struct1(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Length', wintypes.ULONG),
|
||||
('IfIndex', wintypes.DWORD),
|
||||
]
|
||||
|
||||
|
||||
class IP_ADAPTER_ADDRESSES_Union1(ctypes.Union):
|
||||
_fields_ = [
|
||||
('Alignment', wintypes.ULARGE_INTEGER),
|
||||
('Struct1', IP_ADAPTER_ADDRESSES_Struct1),
|
||||
]
|
||||
|
||||
|
||||
class IP_ADAPTER_UNICAST_ADDRESS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Union1', IP_ADAPTER_ADDRESSES_Union1),
|
||||
('Next', wintypes.LPVOID),
|
||||
('Address', SOCKET_ADDRESS),
|
||||
('PrefixOrigin', wintypes.DWORD),
|
||||
('SuffixOrigin', wintypes.DWORD),
|
||||
('DadState', wintypes.DWORD),
|
||||
('ValidLifetime', wintypes.ULONG),
|
||||
('PreferredLifetime', wintypes.ULONG),
|
||||
('LeaseLifetime', wintypes.ULONG),
|
||||
]
|
||||
|
||||
|
||||
class IP_ADAPTER_DNS_SERVER_ADDRESS_Struct1(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Length', wintypes.ULONG),
|
||||
('Reserved', wintypes.DWORD),
|
||||
]
|
||||
|
||||
|
||||
class IP_ADAPTER_DNS_SERVER_ADDRESS_Union1(ctypes.Union):
|
||||
_fields_ = [
|
||||
('Alignment', wintypes.ULARGE_INTEGER),
|
||||
('Struct1', IP_ADAPTER_DNS_SERVER_ADDRESS_Struct1),
|
||||
]
|
||||
|
||||
|
||||
class IP_ADAPTER_DNS_SERVER_ADDRESS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Union1', IP_ADAPTER_DNS_SERVER_ADDRESS_Union1),
|
||||
('Next', wintypes.LPVOID),
|
||||
('Address', SOCKET_ADDRESS),
|
||||
]
|
||||
|
||||
|
||||
class IP_ADAPTER_PREFIX_Struct1(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Length', wintypes.ULONG),
|
||||
('Flags', wintypes.DWORD),
|
||||
]
|
||||
|
||||
|
||||
class IP_ADAPTER_PREFIX_Union1(ctypes.Union):
|
||||
_fields_ = [
|
||||
('Alignment', wintypes.ULARGE_INTEGER),
|
||||
('Struct1', IP_ADAPTER_PREFIX_Struct1),
|
||||
]
|
||||
|
||||
|
||||
class IP_ADAPTER_PREFIX(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Union1', IP_ADAPTER_PREFIX_Union1),
|
||||
('Next', wintypes.LPVOID),
|
||||
('Address', SOCKET_ADDRESS),
|
||||
('PrefixLength', wintypes.ULONG),
|
||||
]
|
||||
|
||||
|
||||
class NET_LUID_LH(ctypes.Union):
|
||||
_fields_ = [
|
||||
('Value', wintypes.ULARGE_INTEGER),
|
||||
('Info', wintypes.ULARGE_INTEGER),
|
||||
]
|
||||
|
||||
|
||||
class IP_ADAPTER_ADDRESSES(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Union1', IP_ADAPTER_ADDRESSES_Union1),
|
||||
('Next', wintypes.LPVOID),
|
||||
('AdapterName', ctypes.c_char_p),
|
||||
('FirstUnicastAddress',
|
||||
ctypes.POINTER(IP_ADAPTER_UNICAST_ADDRESS)),
|
||||
('FirstAnycastAddress',
|
||||
ctypes.POINTER(IP_ADAPTER_DNS_SERVER_ADDRESS)),
|
||||
('FirstMulticastAddress',
|
||||
ctypes.POINTER(IP_ADAPTER_DNS_SERVER_ADDRESS)),
|
||||
('FirstDnsServerAddress',
|
||||
ctypes.POINTER(IP_ADAPTER_DNS_SERVER_ADDRESS)),
|
||||
('DnsSuffix', wintypes.LPWSTR),
|
||||
('Description', wintypes.LPWSTR),
|
||||
('FriendlyName', wintypes.LPWSTR),
|
||||
('PhysicalAddress', ctypes.c_ubyte*MAX_ADAPTER_ADDRESS_LENGTH),
|
||||
('PhysicalAddressLength', wintypes.DWORD),
|
||||
('Flags', wintypes.DWORD),
|
||||
('Mtu', wintypes.DWORD),
|
||||
('IfType', wintypes.DWORD),
|
||||
('OperStatus', wintypes.DWORD),
|
||||
('Ipv6IfIndex', wintypes.DWORD),
|
||||
('ZoneIndices', wintypes.DWORD*16),
|
||||
('FirstPrefix', ctypes.POINTER(IP_ADAPTER_PREFIX)),
|
||||
# kernel >= 6.0
|
||||
('TransmitLinkSpeed', wintypes.ULARGE_INTEGER),
|
||||
('ReceiveLinkSpeed', wintypes.ULARGE_INTEGER),
|
||||
('FirstWinsServerAddress',
|
||||
ctypes.POINTER(IP_ADAPTER_DNS_SERVER_ADDRESS)),
|
||||
('FirstGatewayAddress',
|
||||
ctypes.POINTER(IP_ADAPTER_DNS_SERVER_ADDRESS)),
|
||||
('Ipv4Metric', wintypes.ULONG),
|
||||
('Ipv6Metric', wintypes.ULONG),
|
||||
('Luid', NET_LUID_LH),
|
||||
('Dhcpv4Server', SOCKET_ADDRESS),
|
||||
('CompartmentId', wintypes.DWORD),
|
||||
('NetworkGuid', kernel32.GUID),
|
||||
('ConnectionType', wintypes.DWORD),
|
||||
('TunnelType', wintypes.DWORD),
|
||||
('Dhcpv6Server', SOCKET_ADDRESS),
|
||||
('Dhcpv6ClientDuid', ctypes.c_ubyte*MAX_DHCPV6_DUID_LENGTH),
|
||||
('Dhcpv6ClientDuidLength', wintypes.ULONG),
|
||||
('Dhcpv6Iaid', wintypes.ULONG),
|
||||
]
|
||||
|
||||
GetAdaptersAddresses = windll.Iphlpapi.GetAdaptersAddresses
|
||||
GetAdaptersAddresses.argtypes = [
|
||||
wintypes.ULONG, wintypes.ULONG, wintypes.LPVOID,
|
||||
ctypes.POINTER(IP_ADAPTER_ADDRESSES),
|
||||
ctypes.POINTER(wintypes.ULONG)]
|
||||
GetAdaptersAddresses.restype = wintypes.ULONG
|
56
cloudbaseinit/utils/windows/kernel32.py
Normal file
56
cloudbaseinit/utils/windows/kernel32.py
Normal file
@ -0,0 +1,56 @@
|
||||
# Copyright 2014 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ctypes
|
||||
|
||||
from ctypes import windll
|
||||
from ctypes import wintypes
|
||||
|
||||
ERROR_BUFFER_OVERFLOW = 111
|
||||
ERROR_NO_DATA = 232
|
||||
|
||||
|
||||
class GUID(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("data1", wintypes.DWORD),
|
||||
("data2", wintypes.WORD),
|
||||
("data3", wintypes.WORD),
|
||||
("data4", wintypes.BYTE * 8)]
|
||||
|
||||
def __init__(self, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8):
|
||||
self.data1 = l
|
||||
self.data2 = w1
|
||||
self.data3 = w2
|
||||
self.data4[0] = b1
|
||||
self.data4[1] = b2
|
||||
self.data4[2] = b3
|
||||
self.data4[3] = b4
|
||||
self.data4[4] = b5
|
||||
self.data4[5] = b6
|
||||
self.data4[6] = b7
|
||||
self.data4[7] = b8
|
||||
|
||||
|
||||
GetProcessHeap = windll.kernel32.GetProcessHeap
|
||||
GetProcessHeap.argtypes = []
|
||||
GetProcessHeap.restype = wintypes.HANDLE
|
||||
|
||||
HeapAlloc = windll.kernel32.HeapAlloc
|
||||
# Note: wintypes.ULONG must be replaced with a 64 bit variable on x64
|
||||
HeapAlloc.argtypes = [wintypes.HANDLE, wintypes.DWORD, wintypes.ULONG]
|
||||
HeapAlloc.restype = wintypes.LPVOID
|
||||
|
||||
HeapFree = windll.kernel32.HeapFree
|
||||
HeapFree.argtypes = [wintypes.HANDLE, wintypes.DWORD, wintypes.LPVOID]
|
||||
HeapFree.restype = wintypes.BOOL
|
164
cloudbaseinit/utils/windows/network.py
Normal file
164
cloudbaseinit/utils/windows/network.py
Normal file
@ -0,0 +1,164 @@
|
||||
# Copyright 2014 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import _winreg
|
||||
import ctypes
|
||||
|
||||
from ctypes import wintypes
|
||||
|
||||
from cloudbaseinit.utils.windows import iphlpapi
|
||||
from cloudbaseinit.utils.windows import kernel32
|
||||
from cloudbaseinit.utils.windows import ws2_32
|
||||
|
||||
|
||||
def _format_mac_address(phys_address, phys_address_len):
|
||||
mac_address = ""
|
||||
for i in range(0, phys_address_len):
|
||||
b = phys_address[i]
|
||||
if mac_address:
|
||||
mac_address += ":"
|
||||
mac_address += "%02X" % b
|
||||
return mac_address
|
||||
|
||||
|
||||
def _socket_addr_to_str(socket_addr):
|
||||
addr_str_len = wintypes.DWORD(256)
|
||||
addr_str = ctypes.create_unicode_buffer(256)
|
||||
|
||||
ret_val = ws2_32.WSAAddressToStringW(
|
||||
socket_addr.lpSockaddr,
|
||||
socket_addr.iSockaddrLength,
|
||||
None, addr_str, ctypes.byref(addr_str_len))
|
||||
if ret_val:
|
||||
raise Exception("WSAAddressToStringW failed")
|
||||
|
||||
return addr_str.value
|
||||
|
||||
|
||||
def _get_registry_dhcp_server(adapter_name):
|
||||
with _winreg.OpenKey(
|
||||
_winreg.HKEY_LOCAL_MACHINE,
|
||||
"SYSTEM\\CurrentControlSet\\Services\\" +
|
||||
"Tcpip\\Parameters\\Interfaces\\%s" % adapter_name, 0,
|
||||
_winreg.KEY_READ) as key:
|
||||
try:
|
||||
dhcp_server = _winreg.QueryValueEx(key, "DhcpServer")[0]
|
||||
if dhcp_server == "255.255.255.255":
|
||||
dhcp_server = None
|
||||
return dhcp_server
|
||||
except Exception, ex:
|
||||
# Not found
|
||||
if ex.errno != 2:
|
||||
raise
|
||||
|
||||
|
||||
def get_adapter_addresses():
|
||||
net_adapters = []
|
||||
|
||||
size = wintypes.ULONG()
|
||||
ret_val = iphlpapi.GetAdaptersAddresses(
|
||||
ws2_32.AF_UNSPEC,
|
||||
iphlpapi.GAA_FLAG_SKIP_ANYCAST | iphlpapi.GAA_FLAG_SKIP_ANYCAST,
|
||||
None, None, ctypes.byref(size))
|
||||
|
||||
if ret_val == kernel32.ERROR_NO_DATA:
|
||||
return net_adapters
|
||||
|
||||
if ret_val == kernel32.ERROR_BUFFER_OVERFLOW:
|
||||
proc_heap = kernel32.GetProcessHeap()
|
||||
p = kernel32.HeapAlloc(proc_heap, 0, size.value)
|
||||
if not p:
|
||||
raise Exception("Cannot allocate memory")
|
||||
|
||||
ws2_32.init_wsa()
|
||||
|
||||
try:
|
||||
p_addr = ctypes.cast(p, ctypes.POINTER(
|
||||
iphlpapi.IP_ADAPTER_ADDRESSES))
|
||||
|
||||
ret_val = iphlpapi.GetAdaptersAddresses(
|
||||
ws2_32.AF_UNSPEC,
|
||||
iphlpapi.GAA_FLAG_SKIP_ANYCAST |
|
||||
iphlpapi.GAA_FLAG_SKIP_ANYCAST,
|
||||
None, p_addr, ctypes.byref(size))
|
||||
|
||||
if ret_val == kernel32.ERROR_NO_DATA:
|
||||
return net_adapters
|
||||
|
||||
if ret_val:
|
||||
raise Exception("GetAdaptersAddresses failed")
|
||||
|
||||
p_curr_addr = p_addr
|
||||
while p_curr_addr:
|
||||
curr_addr = p_curr_addr.contents
|
||||
|
||||
xp_data_only = (curr_addr.Union1.Struct1.Length <=
|
||||
iphlpapi.IP_ADAPTER_ADDRESSES_SIZE_2003)
|
||||
|
||||
mac_address = _format_mac_address(
|
||||
curr_addr.PhysicalAddress,
|
||||
curr_addr.PhysicalAddressLength)
|
||||
|
||||
dhcp_enabled = (
|
||||
curr_addr.Flags & iphlpapi.IP_ADAPTER_DHCP_ENABLED) != 0
|
||||
dhcp_server = None
|
||||
|
||||
if dhcp_enabled:
|
||||
if not xp_data_only:
|
||||
if curr_addr.Flags & iphlpapi.IP_ADAPTER_IPV4_ENABLED:
|
||||
dhcp_addr = curr_addr.Dhcpv4Server
|
||||
elif (curr_addr.Flags &
|
||||
iphlpapi.IP_ADAPTER_IPV6_ENABLED):
|
||||
dhcp_addr = curr_addr.Dhcpv6Server
|
||||
|
||||
dhcp_server = _socket_addr_to_str(dhcp_addr)
|
||||
else:
|
||||
dhcp_server = _get_registry_dhcp_server(
|
||||
curr_addr.AdapterName)
|
||||
|
||||
unicast_addresses = []
|
||||
|
||||
p_unicast_addr = curr_addr.FirstUnicastAddress
|
||||
while p_unicast_addr:
|
||||
unicast_addr = p_unicast_addr.contents
|
||||
unicast_addresses.append((
|
||||
_socket_addr_to_str(unicast_addr.Address),
|
||||
unicast_addr.Address.lpSockaddr.contents.sa_family))
|
||||
p_unicast_addr = ctypes.cast(
|
||||
unicast_addr.Next,
|
||||
ctypes.POINTER(iphlpapi.IP_ADAPTER_UNICAST_ADDRESS))
|
||||
|
||||
net_adapters.append(
|
||||
{
|
||||
"interface_index": curr_addr.Union1.Struct1.IfIndex,
|
||||
"adapter_name": curr_addr.AdapterName,
|
||||
"friendly_name": curr_addr.FriendlyName,
|
||||
"description": curr_addr.Description,
|
||||
"mtu": curr_addr.Mtu,
|
||||
"mac_address": mac_address,
|
||||
"dhcp_enabled": dhcp_enabled,
|
||||
"dhcp_server": dhcp_server,
|
||||
"interface_type": curr_addr.IfType,
|
||||
"unicast_addresses": unicast_addresses
|
||||
})
|
||||
|
||||
p_curr_addr = ctypes.cast(
|
||||
curr_addr.Next, ctypes.POINTER(
|
||||
iphlpapi.IP_ADAPTER_ADDRESSES))
|
||||
|
||||
finally:
|
||||
kernel32.HeapFree(proc_heap, 0, p)
|
||||
ws2_32.WSACleanup()
|
||||
|
||||
return net_adapters
|
61
cloudbaseinit/utils/windows/ws2_32.py
Normal file
61
cloudbaseinit/utils/windows/ws2_32.py
Normal file
@ -0,0 +1,61 @@
|
||||
# Copyright 2014 Cloudbase Solutions Srl
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ctypes
|
||||
|
||||
from ctypes import windll
|
||||
from ctypes import wintypes
|
||||
|
||||
AF_UNSPEC = 0
|
||||
AF_INET = 2
|
||||
AF_INET6 = 23
|
||||
|
||||
VERSION_2_2 = (2 << 8) + 2
|
||||
|
||||
|
||||
class SOCKADDR(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('sa_family', wintypes.USHORT),
|
||||
('sa_data', ctypes.c_char*14),
|
||||
]
|
||||
|
||||
|
||||
class WSADATA(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('opaque_data', wintypes.BYTE*400),
|
||||
]
|
||||
|
||||
|
||||
WSAGetLastError = windll.Ws2_32.WSAGetLastError
|
||||
WSAGetLastError.argtypes = []
|
||||
WSAGetLastError.restype = wintypes.INT
|
||||
|
||||
WSAStartup = windll.Ws2_32.WSAStartup
|
||||
WSAStartup.argtypes = [wintypes.WORD, ctypes.POINTER(WSADATA)]
|
||||
WSAStartup.restype = wintypes.INT
|
||||
|
||||
WSACleanup = windll.Ws2_32.WSACleanup
|
||||
WSACleanup.argtypes = []
|
||||
WSACleanup.restype = wintypes.INT
|
||||
|
||||
WSAAddressToStringW = windll.Ws2_32.WSAAddressToStringW
|
||||
WSAAddressToStringW.argtypes = [
|
||||
ctypes.POINTER(SOCKADDR), wintypes.DWORD, wintypes.LPVOID,
|
||||
wintypes.LPWSTR, ctypes.POINTER(wintypes.DWORD)]
|
||||
WSAAddressToStringW.restype = wintypes.INT
|
||||
|
||||
|
||||
def init_wsa(version=VERSION_2_2):
|
||||
wsadata = WSADATA()
|
||||
WSAStartup(version, ctypes.byref(wsadata))
|
Loading…
x
Reference in New Issue
Block a user