1# bgscan tests
2# Copyright (c) 2014-2017, 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 time
8import logging
9logger = logging.getLogger()
10import os
11
12import hostapd
13from utils import alloc_fail, fail_test
14
15def test_bgscan_simple(dev, apdev):
16    """bgscan_simple"""
17    hostapd.add_ap(apdev[0], {"ssid": "bgscan"})
18    hostapd.add_ap(apdev[1], {"ssid": "bgscan"})
19
20    dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
21                   bgscan="simple:1:-20:2")
22    dev[1].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
23                   bgscan="simple:1:-45:2")
24
25    dev[2].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
26                   bgscan="simple:1:-45")
27    dev[2].request("REMOVE_NETWORK all")
28    dev[2].wait_disconnected()
29
30    dev[2].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
31                   bgscan="simple:0:0")
32    dev[2].request("REMOVE_NETWORK all")
33    dev[2].wait_disconnected()
34
35    dev[2].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
36                   bgscan="simple")
37    dev[2].request("REMOVE_NETWORK all")
38    dev[2].wait_disconnected()
39
40    dev[2].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
41                   bgscan="simple:1")
42    dev[2].request("REMOVE_NETWORK all")
43    dev[2].wait_disconnected()
44
45    ev = dev[0].wait_event(["CTRL-EVENT-SIGNAL-CHANGE"], timeout=10)
46    if ev is None:
47        raise Exception("dev0 did not indicate signal change event")
48    if "above=0" not in ev:
49        raise Exception("Unexpected signal change event contents from dev0: " + ev)
50
51    ev = dev[1].wait_event(["CTRL-EVENT-SIGNAL-CHANGE"], timeout=10)
52    if ev is None:
53        raise Exception("dev1 did not indicate signal change event")
54    if "above=1" not in ev:
55        raise Exception("Unexpected signal change event contents from dev1: " + ev)
56
57    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=3)
58    if ev is None:
59        raise Exception("dev0 did not start a scan")
60
61    ev = dev[1].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=3)
62    if ev is None:
63        raise Exception("dev1 did not start a scan")
64
65    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
66    if ev is None:
67        raise Exception("dev0 did not complete a scan")
68    ev = dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
69    if ev is None:
70        raise Exception("dev1 did not complete a scan")
71
72def test_bgscan_simple_beacon_loss(dev, apdev):
73    """bgscan_simple and beacon loss"""
74    params = hostapd.wpa2_params(ssid="bgscan", passphrase="12345678")
75    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
76    params["ieee80211w"] = "2"
77    hapd = hostapd.add_ap(apdev[0], params)
78
79    dev[0].set("disable_sa_query", "1")
80    dev[0].connect("bgscan", ieee80211w="2", key_mgmt="WPA-PSK-SHA256",
81                   psk="12345678", scan_freq="2412",
82                   bgscan="simple:100:-20:200")
83    hapd.set("ext_mgmt_frame_handling", "1")
84    if "OK" not in hapd.request("STOP_AP"):
85        raise Exception("Failed to stop AP")
86    hapd.disable()
87    hapd.set("ssid", "foo")
88    hapd.set("beacon_int", "10000")
89    hapd.enable()
90    ev = dev[0].wait_event(["CTRL-EVENT-BEACON-LOSS"], timeout=10)
91    if ev is None:
92        raise Exception("Beacon loss not reported")
93
94def test_bgscan_simple_scan_failure(dev, apdev):
95    """bgscan_simple and scan failure"""
96    hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"})
97
98    dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
99                   bgscan="simple:1:-20:2")
100    with alloc_fail(dev[0], 1,
101                    "wpa_supplicant_trigger_scan;bgscan_simple_timeout"):
102        ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=10)
103        if ev is None:
104            raise Exception("No scan failure reported")
105    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
106    if ev is None:
107        raise Exception("Scanning not continued after failure")
108
109def test_bgscan_simple_scanning(dev, apdev):
110    """bgscan_simple and scanning behavior"""
111    hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"})
112
113    dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
114                   bgscan="simple:1:-20:2")
115    # Go through seven bgscan_simple_timeout calls for code coverage. This falls
116    # back from short to long scan interval and then reduces short_scan_count
117    # back to zero.
118    for i in range(7):
119        ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
120        if ev is None:
121            raise Exception("Scanning not continued")
122
123def test_bgscan_simple_same_scan_int(dev, apdev):
124    """bgscan_simple and same short/long scan interval"""
125    hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"})
126
127    dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
128                   bgscan="simple:1:-20:1")
129    for i in range(2):
130        ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
131        if ev is None:
132            raise Exception("Scanning not continued")
133
134def test_bgscan_simple_oom(dev, apdev):
135    """bgscan_simple OOM"""
136    hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"})
137
138    with alloc_fail(dev[0], 1, "bgscan_simple_init"):
139        dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
140                       bgscan="simple:1:-20:2")
141
142def test_bgscan_simple_driver_conf_failure(dev, apdev):
143    """bgscan_simple driver configuration failure"""
144    hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"})
145
146    with fail_test(dev[0], 1, "bgscan_simple_init"):
147        dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
148                       bgscan="simple:1:-20:2")
149
150def test_bgscan_learn(dev, apdev):
151    """bgscan_learn"""
152    hostapd.add_ap(apdev[0], {"ssid": "bgscan"})
153    hostapd.add_ap(apdev[1], {"ssid": "bgscan"})
154
155    try:
156        os.remove("/tmp/test_bgscan_learn.bgscan")
157    except:
158        pass
159
160    try:
161        dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
162                       bgscan="learn:1:-20:2")
163        id = dev[1].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
164                            bgscan="learn:1:-45:2:/tmp/test_bgscan_learn.bgscan")
165
166        dev[2].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
167                       bgscan="learn:1:-45")
168        dev[2].request("REMOVE_NETWORK all")
169        dev[2].wait_disconnected()
170
171        dev[2].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
172                       bgscan="learn:0:0")
173        dev[2].request("REMOVE_NETWORK all")
174        dev[2].wait_disconnected()
175
176        dev[2].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
177                       bgscan="learn")
178        dev[2].request("REMOVE_NETWORK all")
179        dev[2].wait_disconnected()
180
181        dev[2].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
182                       bgscan="learn:1")
183        dev[2].request("REMOVE_NETWORK all")
184        dev[2].wait_disconnected()
185
186        ev = dev[0].wait_event(["CTRL-EVENT-SIGNAL-CHANGE"], timeout=10)
187        if ev is None:
188            raise Exception("dev0 did not indicate signal change event")
189        if "above=0" not in ev:
190            raise Exception("Unexpected signal change event contents from dev0: " + ev)
191
192        ev = dev[1].wait_event(["CTRL-EVENT-SIGNAL-CHANGE"], timeout=10)
193        if ev is None:
194            raise Exception("dev1 did not indicate signal change event")
195        if "above=1" not in ev:
196            raise Exception("Unexpected signal change event contents from dev1: " + ev)
197
198        ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=3)
199        if ev is None:
200            raise Exception("dev0 did not start a scan")
201
202        ev = dev[1].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=3)
203        if ev is None:
204            raise Exception("dev1 did not start a scan")
205
206        ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
207        if ev is None:
208            raise Exception("dev0 did not complete a scan")
209        ev = dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
210        if ev is None:
211            raise Exception("dev1 did not complete a scan")
212
213        dev[0].request("DISCONNECT")
214        dev[1].request("DISCONNECT")
215        dev[0].request("REMOVE_NETWORK all")
216
217        with open("/tmp/test_bgscan_learn.bgscan", "r") as f:
218            lines = f.read().splitlines()
219        if lines[0] != "wpa_supplicant-bgscan-learn":
220            raise Exception("Unexpected bgscan header line")
221        if 'BSS 02:00:00:00:03:00 2412' not in lines:
222            raise Exception("Missing BSS1")
223        if 'BSS 02:00:00:00:04:00 2412' not in lines:
224            raise Exception("Missing BSS2")
225        if 'NEIGHBOR 02:00:00:00:03:00 02:00:00:00:04:00' not in lines:
226            raise Exception("Missing BSS1->BSS2 neighbor entry")
227        if 'NEIGHBOR 02:00:00:00:04:00 02:00:00:00:03:00' not in lines:
228            raise Exception("Missing BSS2->BSS1 neighbor entry")
229
230        dev[1].set_network(id, "scan_freq", "")
231        dev[1].connect_network(id)
232
233        ev = dev[1].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=10)
234        if ev is None:
235            raise Exception("dev1 did not start a scan")
236
237        ev = dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
238        if ev is None:
239            raise Exception("dev1 did not complete a scan")
240
241        dev[1].request("REMOVE_NETWORK all")
242    finally:
243        try:
244            os.remove("/tmp/test_bgscan_learn.bgscan")
245        except:
246            pass
247
248def test_bgscan_learn_beacon_loss(dev, apdev):
249    """bgscan_simple and beacon loss"""
250    params = hostapd.wpa2_params(ssid="bgscan", passphrase="12345678")
251    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
252    params["ieee80211w"] = "2"
253    hapd = hostapd.add_ap(apdev[0], params)
254
255    dev[0].set("disable_sa_query", "1")
256    dev[0].connect("bgscan", ieee80211w="2", key_mgmt="WPA-PSK-SHA256",
257                   psk="12345678", scan_freq="2412", bgscan="learn:100:-20:200")
258    hapd.set("ext_mgmt_frame_handling", "1")
259    if "OK" not in hapd.request("STOP_AP"):
260        raise Exception("Failed to stop AP")
261    hapd.disable()
262    hapd.set("ssid", "foo")
263    hapd.set("beacon_int", "10000")
264    hapd.enable()
265    ev = dev[0].wait_event(["CTRL-EVENT-BEACON-LOSS"], timeout=10)
266    if ev is None:
267        raise Exception("Beacon loss not reported")
268
269def test_bgscan_learn_scan_failure(dev, apdev):
270    """bgscan_learn and scan failure"""
271    hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"})
272
273    dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
274                   bgscan="learn:1:-20:2")
275    with alloc_fail(dev[0], 1,
276                    "wpa_supplicant_trigger_scan;bgscan_learn_timeout"):
277        ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=10)
278        if ev is None:
279            raise Exception("No scan failure reported")
280    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
281    if ev is None:
282        raise Exception("Scanning not continued after failure")
283
284def test_bgscan_learn_oom(dev, apdev):
285    """bgscan_learn OOM"""
286    hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"})
287
288    with alloc_fail(dev[0], 1, "bgscan_learn_init"):
289        dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
290                       bgscan="learn:1:-20:2")
291
292def test_bgscan_learn_driver_conf_failure(dev, apdev):
293    """bgscan_learn driver configuration failure"""
294    hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"})
295
296    with fail_test(dev[0], 1, "bgscan_learn_init"):
297        dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
298                       bgscan="learn:1:-20:2")
299
300def test_bgscan_unknown_module(dev, apdev):
301    """bgscan init failing due to unknown module"""
302    hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"})
303    dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
304                   bgscan="unknown:-20:2")
305
306def test_bgscan_reconfig(dev, apdev):
307    """bgscan parameter update"""
308    hostapd.add_ap(apdev[0], {"ssid": "bgscan"})
309    hostapd.add_ap(apdev[1], {"ssid": "bgscan"})
310
311    id = dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
312                        bgscan="simple:1:-20:2")
313    dev[0].set_network_quoted(id, "bgscan", "simple:1:-45:2")
314    dev[0].set_network_quoted(id, "bgscan", "learn:1:-20:2")
315    dev[0].set_network_quoted(id, "bgscan", "")
316