Source code for rpcclient.ios.wifi

import ctypes
import logging
from typing import List, Mapping

from rpcclient.allocated import Allocated
from rpcclient.darwin.symbol import DarwinSymbol
from rpcclient.exceptions import BadReturnValueError, RpcClientException
from rpcclient.structs.consts import RTLD_NOW

logger = logging.getLogger(__name__)


[docs] class WifiSavedNetwork: def __init__(self, client, wifi_manager: DarwinSymbol, network: DarwinSymbol): self._client = client self._wifi_manager = wifi_manager self._network = network @property def ssid(self) -> bytes: return self.get_property('SSID') @property def bssid(self) -> str: return self.get_property('BSSID')
[docs] def get_property(self, name: str): return self._client.symbols.WiFiNetworkGetProperty(self._network, self._client.cf(name)).py()
[docs] def forget(self): """ forget Wi-Fi network """ self._client.symbols.WiFiManagerClientRemoveNetwork(self._wifi_manager, self._network)
def __repr__(self): result = f'<{self.__class__.__name__} ' result += f'SSID:{self.ssid} ' result += f'BSSID:{self.bssid}' result += '>' return result
[docs] class WifiScannedNetwork: def __init__(self, client, interface: DarwinSymbol, network: Mapping): self._client = client self._interface = interface self.network = network @property def ssid(self) -> bytes: return self.network.get('SSID') @property def bssid(self) -> str: return self.network.get('BSSID') @property def rssi(self) -> int: return ctypes.c_int64(self.network['RSSI']).value @property def channel(self) -> int: return self.network['CHANNEL']
[docs] def connect(self, password: str = None): """ connect to Wi-Fi network """ result = self._client.symbols.Apple80211Associate(self._interface, self._client.cf(self.network), self._client.cf(password) if password else 0) if result: raise BadReturnValueError(f'Apple80211Associate() failed with: {result}')
[docs] def disconnect(self): if self._client.symbols.Apple80211Disassociate(self._interface): raise BadReturnValueError('Apple80211Disassociate() failed')
def __repr__(self): result = f'<{self.__class__.__name__} ' result += f'SSID:{self.ssid} ' result += f'BSSID:{self.bssid} ' result += f'CHANNEL:{self.channel} ' result += f'RSSI:{self.rssi}' result += '>' return result
[docs] class WifiInterface(Allocated): def __init__(self, client, interface, device): super().__init__() self._client = client self._interface = interface self._device = device
[docs] def scan(self, options: Mapping = None) -> List[WifiScannedNetwork]: """ perform Wi-Fi scan """ if options is None: options = {} result = [] with self._client.safe_malloc(8) as p_found_networks: while True: scan_result = self._client.symbols.Apple80211Scan(self._interface, p_found_networks, self._client.cf(options)) if scan_result == 0: break elif scan_result == -1: raise BadReturnValueError('Apple80211Scan failed') # else, try again for network in p_found_networks[0].py(): result.append(WifiScannedNetwork(self._client, self._interface, network)) return result
[docs] def disconnect(self): """ disconnect from current Wi-Fi network """ self._client.symbols.Apple80211Disassociate(self._interface)
def _deallocate(self): self._client.symbols.Apple80211Close(self._interface)
[docs] class IosWifi: """ network utils """ def __init__(self, client): self._client = client self._load_wifi_library() self._wifi_manager = self._client.symbols.WiFiManagerClientCreate(0, 0) if not self._wifi_manager: self._client.raise_errno_exception('WiFiManagerClientCreate failed') @property def saved_networks(self) -> List[WifiSavedNetwork]: result = [] network_list = self._client.symbols.WiFiManagerClientCopyNetworks(self._wifi_manager).py() if not network_list: return result for network in network_list: result.append(WifiSavedNetwork(self._client, self._wifi_manager, network)) return result @property def interfaces(self) -> List[str]: """ get a list of all available wifi interfaces """ with self._client.safe_malloc(8) as p_interface: if self._client.symbols.Apple80211Open(p_interface): self._client.raise_errno_exception('Apple80211Open() failed') with self._client.safe_malloc(8) as p_interface_names: if self._client.symbols.Apple80211GetIfListCopy(p_interface[0], p_interface_names): self._client.raise_errno_exception('Apple80211GetIfListCopy() failed') return p_interface_names[0].py()
[docs] def turn_on(self): self._set(True)
[docs] def turn_off(self): self._set(False)
[docs] def is_on(self) -> bool: return bool(self._client.symbols.WiFiManagerClientCopyProperty(self._wifi_manager, self._client.cf('AllowEnable')).py())
[docs] def get_interface(self, interface_name: str = None) -> WifiInterface: """ get a specific wifi interface object for remote controlling """ with self._client.safe_malloc(8) as p_handle: if self._client.symbols.Apple80211Open(p_handle): self._client.raise_errno_exception('Apple80211Open() failed') handle = p_handle[0] if interface_name is None: wifi_interfaces = self.interfaces if not wifi_interfaces: raise RpcClientException('no available wifi interfaces were found') interface_name = wifi_interfaces[0] if self._client.symbols.Apple80211BindToInterface(handle, self._client.cf(interface_name)): self._client.raise_errno_exception('Apple80211BindToInterface failed') device = self._client.symbols.WiFiManagerClientGetDevice(self._wifi_manager, self._client.cf(interface_name)) if not device: self._client.raise_errno_exception('WiFiManagerClientGetDevice failed') return WifiInterface(self._client, handle, device)
def _load_wifi_library(self): options = [ # macOS '/System/Library/Frameworks/CoreWLAN.framework/Versions/A/CoreWLAN', '/System/Library/Frameworks/CoreWLAN.framework/CoreWLAN', # iOS '/System/Library/PrivateFrameworks/WiFiKit.framework/WiFiKit' ] for option in options: if self._client.dlopen(option, RTLD_NOW): return logger.warning('WiFi library isn\'t available') def _set(self, is_on: bool): if not self._client.symbols.WiFiManagerClientSetProperty(self._wifi_manager, self._client.cf('AllowEnable'), self._client.cf(is_on)): raise BadReturnValueError('WiFiManagerClientSetProperty() failed')