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