tests: Disable and re-enable hostapd interface
[mech_eap.git] / tests / hwsim / test_ap_open.py
1 # Open mode AP tests
2 # Copyright (c) 2014, Qualcomm Atheros, Inc.
3 #
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
6
7 import logging
8 logger = logging.getLogger()
9 import struct
10 import subprocess
11 import time
12 import os
13
14 import hostapd
15 import hwsim_utils
16 from tshark import run_tshark
17 from utils import alloc_fail
18 from wpasupplicant import WpaSupplicant
19
20 def test_ap_open(dev, apdev):
21     """AP with open mode (no security) configuration"""
22     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
23     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
24                    bg_scan_period="0")
25     ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
26     if ev is None:
27         raise Exception("No connection event received from hostapd")
28     hwsim_utils.test_connectivity(dev[0], hapd)
29
30     dev[0].request("DISCONNECT")
31     ev = hapd.wait_event([ "AP-STA-DISCONNECTED" ], timeout=5)
32     if ev is None:
33         raise Exception("No disconnection event received from hostapd")
34
35 def test_ap_open_packet_loss(dev, apdev):
36     """AP with open mode configuration and large packet loss"""
37     params = { "ssid": "open",
38                "ignore_probe_probability": "0.5",
39                "ignore_auth_probability": "0.5",
40                "ignore_assoc_probability": "0.5",
41                "ignore_reassoc_probability": "0.5" }
42     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
43     for i in range(0, 3):
44         dev[i].connect("open", key_mgmt="NONE", scan_freq="2412",
45                        wait_connect=False)
46     for i in range(0, 3):
47         dev[i].wait_connected(timeout=20)
48
49 def test_ap_open_unknown_action(dev, apdev):
50     """AP with open mode configuration and unknown Action frame"""
51     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
52     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
53     bssid = apdev[0]['bssid']
54     cmd = "MGMT_TX {} {} freq=2412 action=765432".format(bssid, bssid)
55     if "FAIL" in dev[0].request(cmd):
56         raise Exception("Could not send test Action frame")
57     ev = dev[0].wait_event(["MGMT-TX-STATUS"], timeout=10)
58     if ev is None:
59         raise Exception("Timeout on MGMT-TX-STATUS")
60     if "result=SUCCESS" not in ev:
61         raise Exception("AP did not ack Action frame")
62
63 def test_ap_open_reconnect_on_inactivity_disconnect(dev, apdev):
64     """Reconnect to open mode AP after inactivity related disconnection"""
65     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
66     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
67     hapd.request("DEAUTHENTICATE " + dev[0].p2p_interface_addr() + " reason=4")
68     dev[0].wait_disconnected(timeout=5)
69     dev[0].wait_connected(timeout=2, error="Timeout on reconnection")
70
71 def test_ap_open_assoc_timeout(dev, apdev):
72     """AP timing out association"""
73     ssid = "test"
74     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
75     dev[0].scan(freq="2412")
76     hapd.set("ext_mgmt_frame_handling", "1")
77     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
78                    wait_connect=False)
79     for i in range(0, 10):
80         req = hapd.mgmt_rx()
81         if req is None:
82             raise Exception("MGMT RX wait timed out")
83         if req['subtype'] == 11:
84             break
85         req = None
86     if not req:
87         raise Exception("Authentication frame not received")
88
89     resp = {}
90     resp['fc'] = req['fc']
91     resp['da'] = req['sa']
92     resp['sa'] = req['da']
93     resp['bssid'] = req['bssid']
94     resp['payload'] = struct.pack('<HHH', 0, 2, 0)
95     hapd.mgmt_tx(resp)
96
97     assoc = 0
98     for i in range(0, 10):
99         req = hapd.mgmt_rx()
100         if req is None:
101             raise Exception("MGMT RX wait timed out")
102         if req['subtype'] == 0:
103             assoc += 1
104             if assoc == 3:
105                 break
106     if assoc != 3:
107         raise Exception("Association Request frames not received: assoc=%d" % assoc)
108     hapd.set("ext_mgmt_frame_handling", "0")
109     dev[0].wait_connected(timeout=15)
110
111 def test_ap_open_id_str(dev, apdev):
112     """AP with open mode and id_str"""
113     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
114     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412", id_str="foo",
115                    wait_connect=False)
116     ev = dev[0].wait_connected(timeout=10)
117     if "id_str=foo" not in ev:
118         raise Exception("CTRL-EVENT-CONNECT did not have matching id_str: " + ev)
119     if dev[0].get_status_field("id_str") != "foo":
120         raise Exception("id_str mismatch")
121
122 def test_ap_open_select_any(dev, apdev):
123     """AP with open mode and select any network"""
124     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
125     id = dev[0].connect("unknown", key_mgmt="NONE", scan_freq="2412",
126                         only_add_network=True)
127     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
128                    only_add_network=True)
129     dev[0].select_network(id)
130     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
131     if ev is not None:
132         raise Exception("Unexpected connection")
133
134     dev[0].select_network("any")
135     dev[0].wait_connected(timeout=10)
136
137 def test_ap_open_unexpected_assoc_event(dev, apdev):
138     """AP with open mode and unexpected association event"""
139     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
140     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
141     dev[0].request("DISCONNECT")
142     dev[0].wait_disconnected(timeout=15)
143     dev[0].dump_monitor()
144     # This will be accepted due to matching network
145     subprocess.call(['iw', 'dev', dev[0].ifname, 'connect', 'open', "2412",
146                      apdev[0]['bssid']])
147     dev[0].wait_connected(timeout=15)
148     dev[0].dump_monitor()
149
150     dev[0].request("REMOVE_NETWORK all")
151     dev[0].wait_disconnected(timeout=5)
152     dev[0].dump_monitor()
153     # This will result in disconnection due to no matching network
154     subprocess.call(['iw', 'dev', dev[0].ifname, 'connect', 'open', "2412",
155                      apdev[0]['bssid']])
156     dev[0].wait_disconnected(timeout=15)
157
158 def test_ap_bss_load(dev, apdev):
159     """AP with open mode (no security) configuration"""
160     hapd = hostapd.add_ap(apdev[0]['ifname'],
161                           { "ssid": "open",
162                             "bss_load_update_period": "10" })
163     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
164     # this does not really get much useful output with mac80211_hwsim currently,
165     # but run through the channel survey update couple of times
166     for i in range(0, 10):
167         hwsim_utils.test_connectivity(dev[0], hapd)
168         hwsim_utils.test_connectivity(dev[0], hapd)
169         hwsim_utils.test_connectivity(dev[0], hapd)
170         time.sleep(0.15)
171
172 def hapd_out_of_mem(hapd, apdev, count, func):
173     with alloc_fail(hapd, count, func):
174         started = False
175         try:
176             hostapd.add_ap(apdev['ifname'], { "ssid": "open" })
177             started = True
178         except:
179             pass
180         if started:
181             raise Exception("hostapd interface started even with memory allocation failure: " + arg)
182
183 def test_ap_open_out_of_memory(dev, apdev):
184     """hostapd failing to setup interface due to allocation failure"""
185     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
186     hapd_out_of_mem(hapd, apdev[1], 1, "hostapd_alloc_bss_data")
187
188     for i in range(1, 3):
189         hapd_out_of_mem(hapd, apdev[1], i, "hostapd_iface_alloc")
190
191     for i in range(1, 5):
192         hapd_out_of_mem(hapd, apdev[1], i, "hostapd_config_defaults;hostapd_config_alloc")
193
194     hapd_out_of_mem(hapd, apdev[1], 1, "hostapd_config_alloc")
195
196     hapd_out_of_mem(hapd, apdev[1], 1, "hostapd_driver_init")
197
198     for i in range(1, 4):
199         hapd_out_of_mem(hapd, apdev[1], i, "=wpa_driver_nl80211_drv_init")
200
201     # eloop_register_read_sock() call from i802_init()
202     hapd_out_of_mem(hapd, apdev[1], 1, "eloop_sock_table_add_sock;eloop_register_sock;?eloop_register_read_sock;=i802_init")
203
204     # verify that a new interface can still be added when memory allocation does
205     # not fail
206     hostapd.add_ap(apdev[1]['ifname'], { "ssid": "open" })
207
208 def test_bssid_black_white_list(dev, apdev):
209     """BSSID black/white list"""
210     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
211     hapd2 = hostapd.add_ap(apdev[1]['ifname'], { "ssid": "open" })
212
213     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
214                    bssid_whitelist=apdev[1]['bssid'])
215     dev[1].connect("open", key_mgmt="NONE", scan_freq="2412",
216                    bssid_blacklist=apdev[1]['bssid'])
217     dev[2].connect("open", key_mgmt="NONE", scan_freq="2412",
218                    bssid_whitelist="00:00:00:00:00:00/00:00:00:00:00:00",
219                    bssid_blacklist=apdev[1]['bssid'])
220     if dev[0].get_status_field('bssid') != apdev[1]['bssid']:
221         raise Exception("dev[0] connected to unexpected AP")
222     if dev[1].get_status_field('bssid') != apdev[0]['bssid']:
223         raise Exception("dev[1] connected to unexpected AP")
224     if dev[2].get_status_field('bssid') != apdev[0]['bssid']:
225         raise Exception("dev[2] connected to unexpected AP")
226     dev[0].request("REMOVE_NETWORK all")
227     dev[1].request("REMOVE_NETWORK all")
228     dev[2].request("REMOVE_NETWORK all")
229
230     dev[2].connect("open", key_mgmt="NONE", scan_freq="2412",
231                    bssid_whitelist="00:00:00:00:00:00", wait_connect=False)
232     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
233                    bssid_whitelist="11:22:33:44:55:66/ff:00:00:00:00:00 " + apdev[1]['bssid'] + " aa:bb:cc:dd:ee:ff")
234     dev[1].connect("open", key_mgmt="NONE", scan_freq="2412",
235                    bssid_blacklist="11:22:33:44:55:66/ff:00:00:00:00:00 " + apdev[1]['bssid'] + " aa:bb:cc:dd:ee:ff")
236     if dev[0].get_status_field('bssid') != apdev[1]['bssid']:
237         raise Exception("dev[0] connected to unexpected AP")
238     if dev[1].get_status_field('bssid') != apdev[0]['bssid']:
239         raise Exception("dev[1] connected to unexpected AP")
240     dev[0].request("REMOVE_NETWORK all")
241     dev[1].request("REMOVE_NETWORK all")
242     ev = dev[2].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.1)
243     if ev is not None:
244         raise Exception("Unexpected dev[2] connectin")
245     dev[2].request("REMOVE_NETWORK all")
246
247 def test_ap_open_wpas_in_bridge(dev, apdev):
248     """Open mode AP and wpas interface in a bridge"""
249     br_ifname='sta-br0'
250     ifname='wlan5'
251     try:
252         _test_ap_open_wpas_in_bridge(dev, apdev)
253     finally:
254         subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'down'])
255         subprocess.call(['brctl', 'delif', br_ifname, ifname])
256         subprocess.call(['brctl', 'delbr', br_ifname])
257         subprocess.call(['iw', ifname, 'set', '4addr', 'off'])
258
259 def _test_ap_open_wpas_in_bridge(dev, apdev):
260     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
261
262     br_ifname='sta-br0'
263     ifname='wlan5'
264     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
265     # First, try a failure case of adding an interface
266     try:
267         wpas.interface_add(ifname, br_ifname=br_ifname)
268         raise Exception("Interface addition succeeded unexpectedly")
269     except Exception, e:
270         if "Failed to add" in str(e):
271             logger.info("Ignore expected interface_add failure due to missing bridge interface: " + str(e))
272         else:
273             raise
274
275     # Next, add the bridge interface and add the interface again
276     subprocess.call(['brctl', 'addbr', br_ifname])
277     subprocess.call(['brctl', 'setfd', br_ifname, '0'])
278     subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'up'])
279     subprocess.call(['iw', ifname, 'set', '4addr', 'on'])
280     subprocess.check_call(['brctl', 'addif', br_ifname, ifname])
281     wpas.interface_add(ifname, br_ifname=br_ifname)
282
283     wpas.connect("open", key_mgmt="NONE", scan_freq="2412")
284
285 def test_ap_open_start_disabled(dev, apdev):
286     """AP with open mode and beaconing disabled"""
287     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open",
288                                                 "start_disabled": "1" })
289     bssid = apdev[0]['bssid']
290
291     dev[0].flush_scan_cache()
292     dev[0].scan(freq=2412, only_new=True)
293     if dev[0].get_bss(bssid) is not None:
294         raise Exception("AP was seen beaconing")
295     if "OK" not in hapd.request("RELOAD"):
296         raise Exception("RELOAD failed")
297     dev[0].scan_for_bss(bssid, freq=2412)
298     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
299
300 def test_ap_open_start_disabled2(dev, apdev):
301     """AP with open mode and beaconing disabled (2)"""
302     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open",
303                                                 "start_disabled": "1" })
304     bssid = apdev[0]['bssid']
305
306     dev[0].flush_scan_cache()
307     dev[0].scan(freq=2412, only_new=True)
308     if dev[0].get_bss(bssid) is not None:
309         raise Exception("AP was seen beaconing")
310     if "OK" not in hapd.request("UPDATE_BEACON"):
311         raise Exception("UPDATE_BEACON failed")
312     dev[0].scan_for_bss(bssid, freq=2412)
313     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
314     if "OK" not in hapd.request("UPDATE_BEACON"):
315         raise Exception("UPDATE_BEACON failed")
316     dev[0].request("DISCONNECT")
317     dev[0].wait_disconnected()
318     dev[0].request("RECONNECT")
319     dev[0].wait_connected()
320
321 def test_ap_open_ifdown(dev, apdev):
322     """AP with open mode and external ifconfig down"""
323     params = { "ssid": "open",
324                "ap_max_inactivity": "1" }
325     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
326     bssid = apdev[0]['bssid']
327
328     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
329     dev[1].connect("open", key_mgmt="NONE", scan_freq="2412")
330     subprocess.call(['ip', 'link', 'set', 'dev', apdev[0]['ifname'], 'down'])
331     ev = hapd.wait_event(["AP-STA-DISCONNECTED"], timeout=10)
332     if ev is None:
333         raise Exception("Timeout on AP-STA-DISCONNECTED (1)")
334     ev = hapd.wait_event(["AP-STA-DISCONNECTED"], timeout=5)
335     if ev is None:
336         raise Exception("Timeout on AP-STA-DISCONNECTED (2)")
337     ev = hapd.wait_event(["INTERFACE-DISABLED"], timeout=5)
338     if ev is None:
339         raise Exception("No INTERFACE-DISABLED event")
340     # The following wait tests beacon loss detection in mac80211 on dev0.
341     # dev1 is used to test stopping of AP side functionality on client polling.
342     dev[1].request("REMOVE_NETWORK all")
343     subprocess.call(['ip', 'link', 'set', 'dev', apdev[0]['ifname'], 'up'])
344     dev[0].wait_disconnected()
345     dev[1].wait_disconnected()
346     ev = hapd.wait_event(["INTERFACE-ENABLED"], timeout=10)
347     if ev is None:
348         raise Exception("No INTERFACE-ENABLED event")
349     dev[0].wait_connected()
350     hwsim_utils.test_connectivity(dev[0], hapd)
351
352 def test_ap_open_disconnect_in_ps(dev, apdev, params):
353     """Disconnect with the client in PS to regression-test a kernel bug"""
354     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
355     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
356                    bg_scan_period="0")
357     ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
358     if ev is None:
359         raise Exception("No connection event received from hostapd")
360
361     time.sleep(0.2)
362     hwsim_utils.set_powersave(dev[0], hwsim_utils.PS_MANUAL_POLL)
363     try:
364         # inject some traffic
365         sa = hapd.own_addr()
366         da = dev[0].own_addr()
367         hapd.request('DATA_TEST_CONFIG 1')
368         hapd.request('DATA_TEST_TX {} {} 0'.format(da, sa))
369         hapd.request('DATA_TEST_CONFIG 0')
370
371         # let the AP send couple of Beacon frames
372         time.sleep(0.3)
373
374         # disconnect - with traffic pending - shouldn't cause kernel warnings
375         dev[0].request("DISCONNECT")
376     finally:
377         hwsim_utils.set_powersave(dev[0], hwsim_utils.PS_DISABLED)
378
379     time.sleep(0.2)
380     out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
381                      "wlan_mgt.tim.partial_virtual_bitmap",
382                      ["wlan_mgt.tim.partial_virtual_bitmap"])
383     if out is not None:
384         state = 0
385         for l in out.splitlines():
386             pvb = int(l, 16)
387             if pvb > 0 and state == 0:
388                 state = 1
389             elif pvb == 0 and state == 1:
390                 state = 2
391         if state != 2:
392             raise Exception("Didn't observe TIM bit getting set and unset (state=%d)" % state)
393
394 def test_ap_open_select_network(dev, apdev):
395     """Open mode connection and SELECT_NETWORK to change network"""
396     hapd1 = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
397     bssid1 = apdev[0]['bssid']
398     hapd2 = hostapd.add_ap(apdev[1]['ifname'], { "ssid": "open2" })
399     bssid2 = apdev[1]['bssid']
400
401     id1 = dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
402                          only_add_network=True)
403     id2 = dev[0].connect("open2", key_mgmt="NONE", scan_freq="2412")
404     hwsim_utils.test_connectivity(dev[0], hapd2)
405
406     dev[0].select_network(id1)
407     dev[0].wait_connected()
408     res = dev[0].request("BLACKLIST")
409     if bssid1 in res or bssid2 in res:
410         raise Exception("Unexpected blacklist entry")
411     hwsim_utils.test_connectivity(dev[0], hapd1)
412
413     dev[0].select_network(id2)
414     dev[0].wait_connected()
415     hwsim_utils.test_connectivity(dev[0], hapd2)
416     res = dev[0].request("BLACKLIST")
417     if bssid1 in res or bssid2 in res:
418         raise Exception("Unexpected blacklist entry(2)")
419
420 def test_ap_open_disable_enable(dev, apdev):
421     """AP with open mode getting disabled and re-enabled"""
422     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
423     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
424                    bg_scan_period="0")
425
426     for i in range(2):
427         hapd.request("DISABLE")
428         dev[0].wait_disconnected()
429         hapd.request("ENABLE")
430         dev[0].wait_connected()
431         hwsim_utils.test_connectivity(dev[0], hapd)