1# rfkill tests 2# Copyright (c) 2014, Jouni Malinen <j@w1.fi> 3# 4# This software may be distributed under the terms of the BSD license. 5# See README for more details. 6 7import logging 8logger = logging.getLogger() 9import time 10 11import hostapd 12from hostapd import HostapdGlobal 13import hwsim_utils 14from wpasupplicant import WpaSupplicant 15from rfkill import RFKill 16from utils import HwsimSkip 17from hwsim import HWSimRadio 18 19def get_rfkill(dev): 20 phy = dev.get_driver_status_field("phyname") 21 try: 22 for r, s, h in RFKill.list(): 23 if r.name == phy: 24 return r 25 except Exception as e: 26 raise HwsimSkip("No rfkill available: " + str(e)) 27 raise HwsimSkip("No rfkill match found for the interface") 28 29def test_rfkill_open(dev, apdev): 30 """rfkill block/unblock during open mode connection""" 31 rfk = get_rfkill(dev[0]) 32 33 hapd = hostapd.add_ap(apdev[0], {"ssid": "open"}) 34 dev[0].connect("open", key_mgmt="NONE", scan_freq="2412") 35 try: 36 logger.info("rfkill block") 37 rfk.block() 38 dev[0].wait_disconnected(timeout=10, 39 error="Missing disconnection event on rfkill block") 40 41 if "FAIL" not in dev[0].request("REASSOCIATE"): 42 raise Exception("REASSOCIATE accepted while disabled") 43 if "FAIL" not in dev[0].request("REATTACH"): 44 raise Exception("REATTACH accepted while disabled") 45 if "FAIL" not in dev[0].request("RECONNECT"): 46 raise Exception("RECONNECT accepted while disabled") 47 if "FAIL" not in dev[0].request("FETCH_OSU"): 48 raise Exception("FETCH_OSU accepted while disabled") 49 50 logger.info("rfkill unblock") 51 rfk.unblock() 52 dev[0].wait_connected(timeout=10, 53 error="Missing connection event on rfkill unblock") 54 hwsim_utils.test_connectivity(dev[0], hapd) 55 finally: 56 rfk.unblock() 57 58def test_rfkill_wpa2_psk(dev, apdev): 59 """rfkill block/unblock during WPA2-PSK connection""" 60 rfk = get_rfkill(dev[0]) 61 62 ssid = "test-wpa2-psk" 63 passphrase = 'qwertyuiop' 64 params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) 65 hapd = hostapd.add_ap(apdev[0], params) 66 dev[0].connect(ssid, psk=passphrase, scan_freq="2412") 67 hapd.wait_sta() 68 try: 69 logger.info("rfkill block") 70 rfk.block() 71 dev[0].wait_disconnected(timeout=10, 72 error="Missing disconnection event on rfkill block") 73 74 logger.info("rfkill unblock") 75 rfk.unblock() 76 dev[0].wait_connected(timeout=10, 77 error="Missing connection event on rfkill unblock") 78 hapd.wait_sta() 79 hwsim_utils.test_connectivity(dev[0], hapd) 80 finally: 81 rfk.unblock() 82 83def test_rfkill_autogo(dev, apdev): 84 """rfkill block/unblock for autonomous P2P GO""" 85 rfk0 = get_rfkill(dev[0]) 86 rfk1 = get_rfkill(dev[1]) 87 88 dev[0].p2p_start_go() 89 dev[1].request("SET p2p_no_group_iface 0") 90 dev[1].p2p_start_go() 91 92 try: 93 logger.info("rfkill block 0") 94 rfk0.block() 95 ev = dev[0].wait_global_event(["P2P-GROUP-REMOVED"], timeout=10) 96 if ev is None: 97 raise Exception("Group removal not reported") 98 if "reason=UNAVAILABLE" not in ev: 99 raise Exception("Unexpected group removal reason: " + ev) 100 if "FAIL" not in dev[0].request("P2P_LISTEN 1"): 101 raise Exception("P2P_LISTEN accepted unexpectedly") 102 if "FAIL" not in dev[0].request("P2P_LISTEN"): 103 raise Exception("P2P_LISTEN accepted unexpectedly") 104 105 logger.info("rfkill block 1") 106 rfk1.block() 107 ev = dev[1].wait_global_event(["P2P-GROUP-REMOVED"], timeout=10) 108 if ev is None: 109 raise Exception("Group removal not reported") 110 if "reason=UNAVAILABLE" not in ev: 111 raise Exception("Unexpected group removal reason: " + ev) 112 113 logger.info("rfkill unblock 0") 114 rfk0.unblock() 115 logger.info("rfkill unblock 1") 116 rfk1.unblock() 117 time.sleep(1) 118 finally: 119 rfk0.unblock() 120 rfk1.unblock() 121 122def _test_rfkill_p2p_discovery(dev0, dev1): 123 """rfkill block/unblock P2P Discovery""" 124 rfk0 = get_rfkill(dev0) 125 rfk1 = get_rfkill(dev1) 126 127 try: 128 addr0 = dev0.p2p_dev_addr() 129 130 logger.info("rfkill block 0") 131 rfk0.block() 132 logger.info("rfkill block 1") 133 rfk1.block() 134 135 for i in range(10): 136 time.sleep(0.1) 137 if dev0.get_status_field("wpa_state") == "INTERFACE_DISABLED" and dev1.get_status_field("wpa_state") == "INTERFACE_DISABLED": 138 break 139 140 if "OK" in dev0.p2p_listen(): 141 raise Exception("P2P Listen success although in rfkill") 142 143 if "OK" in dev1.p2p_find(): 144 raise Exception("P2P Find success although in rfkill") 145 146 dev0.dump_monitor() 147 dev1.dump_monitor() 148 149 logger.info("rfkill unblock 0") 150 rfk0.unblock() 151 logger.info("rfkill unblock 1") 152 rfk1.unblock() 153 154 for i in range(10): 155 time.sleep(0.1) 156 if dev0.get_status_field("wpa_state") != "INTERFACE_DISABLED" and dev1.get_status_field("wpa_state") != "INTERFACE_DISABLED": 157 break 158 159 if "OK" not in dev0.p2p_listen(): 160 raise Exception("P2P Listen failed after unblocking rfkill") 161 162 if not dev1.discover_peer(addr0, social=True): 163 raise Exception("Failed to discover peer after unblocking rfkill") 164 165 finally: 166 rfk0.unblock() 167 rfk1.unblock() 168 dev0.p2p_stop_find() 169 dev1.p2p_stop_find() 170 dev0.dump_monitor() 171 dev1.dump_monitor() 172 173def test_rfkill_p2p_discovery(dev, apdev): 174 """rfkill block/unblock P2P Discovery""" 175 _test_rfkill_p2p_discovery(dev[0], dev[1]) 176 177def test_rfkill_p2p_discovery_p2p_dev(dev, apdev): 178 """rfkill block/unblock P2P Discovery with P2P Device""" 179 with HWSimRadio(use_p2p_device=True) as (radio, iface): 180 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 181 wpas.interface_add(iface) 182 _test_rfkill_p2p_discovery(dev[0], wpas) 183 _test_rfkill_p2p_discovery(wpas, dev[1]) 184 185def test_rfkill_hostapd(dev, apdev): 186 """rfkill block/unblock during and prior to hostapd operations""" 187 hapd = hostapd.add_ap(apdev[0], {"ssid": "open"}) 188 189 rfk = get_rfkill(hapd) 190 191 try: 192 rfk.block() 193 ev = hapd.wait_event(["INTERFACE-DISABLED"], timeout=5) 194 if ev is None: 195 raise Exception("INTERFACE-DISABLED event not seen") 196 rfk.unblock() 197 ev = hapd.wait_event(["INTERFACE-ENABLED"], timeout=5) 198 if ev is None: 199 raise Exception("INTERFACE-ENABLED event not seen") 200 # hostapd does not current re-enable beaconing automatically 201 hapd.disable() 202 hapd.enable() 203 dev[0].connect("open", key_mgmt="NONE", scan_freq="2412") 204 rfk.block() 205 ev = hapd.wait_event(["INTERFACE-DISABLED"], timeout=5) 206 if ev is None: 207 raise Exception("INTERFACE-DISABLED event not seen") 208 dev[0].wait_disconnected(timeout=10) 209 dev[0].request("DISCONNECT") 210 hapd.disable() 211 212 hglobal = HostapdGlobal(apdev[0]) 213 hglobal.flush() 214 hglobal.remove(apdev[0]['ifname']) 215 216 hapd = hostapd.add_ap(apdev[0], {"ssid": "open2"}, 217 no_enable=True) 218 if "FAIL" not in hapd.request("ENABLE"): 219 raise Exception("ENABLE succeeded unexpectedly (rfkill)") 220 finally: 221 rfk.unblock() 222 223def test_rfkill_wpas(dev, apdev): 224 """rfkill block prior to wpa_supplicant start""" 225 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 226 wpas.interface_add("wlan5") 227 rfk = get_rfkill(wpas) 228 wpas.interface_remove("wlan5") 229 try: 230 rfk.block() 231 wpas.interface_add("wlan5") 232 time.sleep(0.5) 233 state = wpas.get_status_field("wpa_state") 234 if state != "INTERFACE_DISABLED": 235 raise Exception("Unexpected state with rfkill blocked: " + state) 236 rfk.unblock() 237 time.sleep(0.5) 238 state = wpas.get_status_field("wpa_state") 239 if state == "INTERFACE_DISABLED": 240 raise Exception("Unexpected state with rfkill unblocked: " + state) 241 finally: 242 rfk.unblock() 243