#!/usr/bin/env python3
# vim: set fileencoding=utf-8
"""Implementations of wifi functions of Linux."""
import re
import platform
import time
import logging
from ctypes import *
from ctypes.wintypes import *
from comtypes import GUID
from .const import *
from .profile import Profile
if platform.release().lower() == 'xp':
if platform.win32_ver()[2].lower() in ['sp2', 'sp3']:
CLIENT_VERSION = 1
else:
CLIENT_VERSION = 2
"""
Some types does not exist in python2 ctypes.wintypes so we fake them
using how its defined in python3 ctypes.wintypes.
"""
if not "PDWORD" in dir():
PDWORD = POINTER(DWORD)
if not "PWCHAR" in dir():
PWCHAR= POINTER(WCHAR)
ERROR_SUCCESS = 0
WLAN_MAX_PHY_TYPE_NUMBER = 8
DOT11_MAC_ADDRESS = c_ubyte * 6
native_wifi = windll.wlanapi
status_dict = [
IFACE_INACTIVE,
IFACE_CONNECTED,
IFACE_CONNECTED,
IFACE_DISCONNECTED,
IFACE_DISCONNECTED,
IFACE_CONNECTING,
IFACE_CONNECTING,
IFACE_CONNECTING
]
auth_value_to_str_dict = {
AUTH_ALG_OPEN: 'OPEN',
AUTH_ALG_SHARED: 'SHARED'
}
auth_str_to_value_dict = {
'OPEN': AUTH_ALG_OPEN,
'SHARED': AUTH_ALG_SHARED
}
akm_str_to_value_dict = {
'NONE': AKM_TYPE_NONE,
'WPA': AKM_TYPE_WPA,
'WPAPSK': AKM_TYPE_WPAPSK,
'WPA2': AKM_TYPE_WPA2,
'WPA2PSK': AKM_TYPE_WPA2PSK,
'OTHER': AKM_TYPE_UNKNOWN
}
akm_value_to_str_dict = {
AKM_TYPE_NONE: 'NONE',
AKM_TYPE_WPA: 'WPA',
AKM_TYPE_WPAPSK: 'WPAPSK',
AKM_TYPE_WPA2: 'WPA2',
AKM_TYPE_WPA2PSK: 'WPA2PSK',
AKM_TYPE_UNKNOWN: 'OTHER'
}
cipher_str_to_value_dict = {
'NONE': CIPHER_TYPE_NONE,
'WEP': CIPHER_TYPE_WEP,
'TKIP': CIPHER_TYPE_TKIP,
'AES': CIPHER_TYPE_CCMP,
'OTHER': CIPHER_TYPE_UNKNOWN
}
cipher_value_to_str_dict = {
CIPHER_TYPE_NONE: 'NONE',
CIPHER_TYPE_WEP: 'WEP',
CIPHER_TYPE_TKIP: 'TKIP',
CIPHER_TYPE_CCMP: 'AES',
CIPHER_TYPE_UNKNOWN: 'UNKNOWN'
}
class WLAN_INTERFACE_INFO(Structure):
_fields_ = [
("InterfaceGuid", GUID),
("strInterfaceDescription", c_wchar * 256),
("isState", c_uint)
]
class WLAN_INTERFACE_INFO_LIST(Structure):
_fields_ = [
("dwNumberOfItems", DWORD),
("dwIndex", DWORD),
("InterfaceInfo", WLAN_INTERFACE_INFO * 1)
]
class DOT11_SSID(Structure):
_fields_ = [("uSSIDLength", c_ulong),
("ucSSID", c_char * 32)]
class WLAN_RATE_SET(Structure):
_fields_ = [
("uRateSetLength", c_ulong),
("usRateSet", c_ushort * 126)
]
class WLAN_RAW_DATA(Structure):
_fields_ = [
("dwDataSize", DWORD),
("DataBlob", c_byte * 1)
]
class WLAN_AVAILABLE_NETWORK(Structure):
_fields_ = [
("strProfileName", c_wchar * 256),
("dot11Ssid", DOT11_SSID),
("dot11BssType", c_uint),
("uNumberOfBssids", c_ulong),
("bNetworkConnectable", c_bool),
("wlanNotConnectableReason", c_uint),
("uNumberOfPhyTypes", c_ulong * WLAN_MAX_PHY_TYPE_NUMBER),
("dot11PhyTypes", c_uint),
("bMorePhyTypes", c_bool),
("wlanSignalQuality", c_ulong),
("bSecurityEnabled", c_bool),
("dot11DefaultAuthAlgorithm", c_uint),
("dot11DefaultCipherAlgorithm", c_uint),
("dwFlags", DWORD),
("dwReserved", DWORD)
]
class WLAN_AVAILABLE_NETWORK_LIST(Structure):
_fields_ = [
("dwNumberOfItems", DWORD),
("dwIndex", DWORD),
("Network", WLAN_AVAILABLE_NETWORK * 1)
]
class WLAN_BSS_ENTRY(Structure):
_fields_ = [
("dot11Ssid", DOT11_SSID),
("uPhyId", c_ulong),
("dot11Bssid", DOT11_MAC_ADDRESS),
("dot11BssType", c_uint),
("dot11BssPhyType", c_uint),
("lRssi", c_long),
("uLinkQuality", c_ulong),
("bInRegDomain", c_bool),
("usBeaconPeriod", c_ushort),
("ullTimestamp", c_ulonglong),
("ullHostTimestamp", c_ulonglong),
("usCapabilityInformation", c_ushort),
("ulChCenterFrequency", c_ulong),
("wlanRateSet", WLAN_RATE_SET),
("ulIeOffset", c_ulong),
("ulIeSize", c_ulong)
]
class WLAN_BSS_LIST(Structure):
_fields_ = [
("dwTotalSize", DWORD),
("dwNumberOfItems", DWORD),
("wlanBssEntries", WLAN_BSS_ENTRY * 1)
]
class NDIS_OBJECT_HEADER(Structure):
_fields_ = [
("Type", c_ubyte),
("Revision", c_ubyte),
("Size", c_ushort)
]
class DOT11_BSSID_LIST(Structure):
_fields_ = [
("Header", NDIS_OBJECT_HEADER),
("uNumOfEntries", c_ulong),
("uTotalNumOfEntries", c_ulong),
("BSSIDs", DOT11_MAC_ADDRESS * 1)
]
class WLAN_CONNECTION_PARAMETERS(Structure):
_fields_ = [
("wlanConnectionMode", c_uint),
("strProfile", c_wchar_p),
("pDot11Ssid", POINTER(DOT11_SSID)),
("pDesiredBssidList", POINTER(DOT11_BSSID_LIST)),
("dot11BssType", c_uint),
("dwFlags", DWORD)
]
class WLAN_PROFILE_INFO(Structure):
_fields_ = [
("strProfileName", c_wchar * 256),
("dwFlags", DWORD)
]
class WLAN_PROFILE_INFO_LIST(Structure):
_fields_ = [
("dwNumberOfItems", DWORD),
("dwIndex", DWORD),
("ProfileInfo", WLAN_PROFILE_INFO * 1)
]
class WifiUtil():
"""WifiUtil implements the wifi functions in Windows."""
_nego_version = DWORD()
_handle = HANDLE()
_ifaces = pointer(WLAN_INTERFACE_INFO_LIST())
_logger = logging.getLogger('pywifi')
def scan(self, obj):
"""Trigger the wifi interface to scan."""
self._wlan_scan(self._handle, byref(obj['guid']))
def scan_results(self, obj):
"""Get the AP list after scanning."""
avail_network_list = pointer(WLAN_AVAILABLE_NETWORK_LIST())
self._wlan_get_available_network_list(self._handle,
byref(obj['guid']), byref(avail_network_list))
networks = cast(avail_network_list.contents.Network,
POINTER(WLAN_AVAILABLE_NETWORK))
self._logger.debug("Scan found %d networks.",
avail_network_list.contents.dwNumberOfItems)
network_list = []
for i in range(avail_network_list.contents.dwNumberOfItems):
if networks[i].dot11BssType == 1 and networks[i].bNetworkConnectable :
ssid = ''
for j in range(networks[i].dot11Ssid.uSSIDLength):
if networks[i].dot11Ssid.ucSSID != b'':
ssid += "%c" % networks[i].dot11Ssid.ucSSID[j]
bss_list = pointer(WLAN_BSS_LIST())
self._wlan_get_network_bss_list(self._handle,
byref(obj['guid']), byref(bss_list), networks[i].dot11Ssid, networks[i].bSecurityEnabled)
bsses = cast(bss_list.contents.wlanBssEntries,
POINTER(WLAN_BSS_ENTRY))
if networks[i].bSecurityEnabled:
akm = self._get_akm(networks[i].dot11DefaultCipherAlgorithm)
auth_alg = self._get_auth_alg(networks[i].dot11DefaultAuthAlgorithm)
else:
akm = [AKM_TYPE_NONE]
auth_alg = [AUTH_ALG_OPEN]
for j in range(bss_list.contents.dwNumberOfItems):
network = Profile()
network.ssid = ssid
network.bssid = ''
for k in range(6):
network.bssid += "%02x:" % bsses[j].dot11Bssid[k]
network.signal = bsses[j].lRssi
network.freq = bsses[j].ulChCenterFrequency
network.auth = auth_alg
network.akm = akm
network_list.append(network)
return network_list
def connect(self, obj, params):
"""Connect to the specified AP."""
connect_params = WLAN_CONNECTION_PARAMETERS()
connect_params.wlanConnect
评论0