1# hostapd and out-of-memory error paths
2# Copyright (c) 2015, Jouni Malinen
3#
4# This software may be distributed under the terms of the BSD license.
5# See README for more details.
6
7from remotehost import remote_compatible
8import logging
9logger = logging.getLogger()
10import time
11
12import hostapd
13from utils import *
14
15def hostapd_oom_loop(apdev, params, start_func="main"):
16    hapd = hostapd.add_ap(apdev[0], {"ssid": "ctrl"})
17
18    count = 0
19    for i in range(1, 1000):
20        if "OK" not in hapd.request("TEST_ALLOC_FAIL %d:%s" % (i, start_func)):
21            raise HwsimSkip("TEST_ALLOC_FAIL not supported")
22        try:
23            hostapd.add_ap(apdev[1], params, timeout=2.5)
24            logger.info("Iteration %d - success" % i)
25            hostapd.remove_bss(apdev[1])
26
27            state = hapd.request('GET_ALLOC_FAIL')
28            logger.info("GET_ALLOC_FAIL: " + state)
29            hapd.request("TEST_ALLOC_FAIL 0:")
30            if i < 3:
31                raise Exception("AP setup succeeded during out-of-memory")
32            if state.startswith('0:'):
33                count = 0
34            else:
35                count += 1
36                if count == 5:
37                    break
38        except Exception as e:
39            logger.info("Iteration %d - %s" % (i, str(e)))
40
41@remote_compatible
42def test_hostapd_oom_open(dev, apdev):
43    """hostapd failing to setup open mode due to OOM"""
44    params = {"ssid": "open"}
45    hostapd_oom_loop(apdev, params)
46
47def test_hostapd_oom_wpa2_psk(dev, apdev):
48    """hostapd failing to setup WPA2-PSK mode due to OOM"""
49    params = hostapd.wpa2_params(ssid="test", passphrase="12345678")
50    params['wpa_psk_file'] = 'hostapd.wpa_psk'
51    hostapd_oom_loop(apdev, params)
52
53    tests = ["hostapd_config_read_wpa_psk", "hostapd_derive_psk"]
54    for t in tests:
55        hapd = hostapd.add_ap(apdev[0], {"ssid": "ctrl"})
56        hapd.request("TEST_ALLOC_FAIL 1:%s" % t)
57        try:
58            hostapd.add_ap(apdev[1], params, timeout=2.5)
59            raise Exception("Unexpected add_ap() success during OOM")
60        except Exception as e:
61            if "Failed to enable hostapd" in str(e):
62                pass
63            else:
64                raise
65        state = hapd.request('GET_ALLOC_FAIL')
66        if state != "0:%s" % t:
67            raise Exception("OOM not triggered")
68
69@remote_compatible
70def test_hostapd_oom_wpa2_eap(dev, apdev):
71    """hostapd failing to setup WPA2-EAP mode due to OOM"""
72    params = hostapd.wpa2_eap_params(ssid="test")
73    params['acct_server_addr'] = "127.0.0.1"
74    params['acct_server_port'] = "1813"
75    params['acct_server_shared_secret'] = "radius"
76    hostapd_oom_loop(apdev, params)
77
78@remote_compatible
79def test_hostapd_oom_wpa2_eap_radius(dev, apdev):
80    """hostapd failing to setup WPA2-EAP mode due to OOM in RADIUS"""
81    params = hostapd.wpa2_eap_params(ssid="test")
82    params['acct_server_addr'] = "127.0.0.1"
83    params['acct_server_port'] = "1813"
84    params['acct_server_shared_secret'] = "radius"
85    hostapd_oom_loop(apdev, params, start_func="accounting_init")
86
87def test_hostapd_oom_wpa2_psk_connect(dev, apdev):
88    """hostapd failing during WPA2-PSK mode connection due to OOM"""
89    params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678")
90    hapd = hostapd.add_ap(apdev[0], params)
91
92    dev[0].request("SCAN_INTERVAL 1")
93    count = 0
94    for i in range(1, 1000):
95        logger.info("Iteration %d" % i)
96        if "OK" not in hapd.request("TEST_ALLOC_FAIL %d:main" % i):
97            raise HwsimSkip("TEST_ALLOC_FAIL not supported")
98        id = dev[0].connect("test-wpa2-psk", psk="12345678",
99                            scan_freq="2412", wait_connect=False)
100        ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
101                                "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=5)
102        if ev is None:
103            logger.info("Timeout while waiting for connection in iteration %d" % i)
104            dev[0].request("REMOVE_NETWORK all")
105            time.sleep(0.1)
106        else:
107            if "CTRL-EVENT-SSID-TEMP-DISABLED" in ev:
108                logger.info("Re-select to avoid long wait for temp disavle")
109                dev[0].select_network(id)
110                dev[0].wait_connected()
111            dev[0].request("REMOVE_NETWORK all")
112            dev[0].wait_disconnected()
113        for i in range(3):
114            dev[i].dump_monitor()
115        hapd.dump_monitor()
116
117        state = hapd.request('GET_ALLOC_FAIL')
118        logger.info("GET_ALLOC_FAIL: " + state)
119        hapd.request("TEST_ALLOC_FAIL 0:")
120        if state.startswith('0:'):
121            count = 0
122        else:
123            count += 1
124            if count == 5:
125                break
126    dev[0].request("SCAN_INTERVAL 5")
127
128@long_duration_test
129def test_hostapd_oom_wpa2_eap_connect_1(dev, apdev):
130    """hostapd failing during WPA2-EAP mode connection due to OOM (1-50)"""
131    run_hostapd_oom_wpa2_eap_connect(dev, apdev, 1, 50)
132
133@long_duration_test
134def test_hostapd_oom_wpa2_eap_connect_2(dev, apdev):
135    """hostapd failing during WPA2-EAP mode connection due to OOM (51-100)"""
136    run_hostapd_oom_wpa2_eap_connect(dev, apdev, 51, 100)
137
138@long_duration_test
139def test_hostapd_oom_wpa2_eap_connect_3(dev, apdev):
140    """hostapd failing during WPA2-EAP mode connection due to OOM (101-150)"""
141    run_hostapd_oom_wpa2_eap_connect(dev, apdev, 101, 150)
142
143@long_duration_test
144def test_hostapd_oom_wpa2_eap_connect_4(dev, apdev):
145    """hostapd failing during WPA2-EAP mode connection due to OOM (151-200)"""
146    run_hostapd_oom_wpa2_eap_connect(dev, apdev, 151, 200)
147
148@long_duration_test
149def test_hostapd_oom_wpa2_eap_connect_5(dev, apdev):
150    """hostapd failing during WPA2-EAP mode connection due to OOM (201-999)"""
151    run_hostapd_oom_wpa2_eap_connect(dev, apdev, 201, 999)
152
153def run_hostapd_oom_wpa2_eap_connect(dev, apdev, start, end):
154    params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
155    params['acct_server_addr'] = "127.0.0.1"
156    params['acct_server_port'] = "1813"
157    params['acct_server_shared_secret'] = "radius"
158    hapd = hostapd.add_ap(apdev[0], params)
159
160    dev[0].request("SCAN_INTERVAL 1")
161    count = 0
162    for i in range(start, end + 1):
163        logger.info("Iteration %d" % i)
164        if "OK" not in hapd.request("TEST_ALLOC_FAIL %d:main" % i):
165            raise HwsimSkip("TEST_ALLOC_FAIL not supported")
166        id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
167                            eap="GPSK", identity="gpsk user",
168                            password="abcdefghijklmnop0123456789abcdef",
169                            scan_freq="2412", wait_connect=False)
170        ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
171                                "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=5)
172        if ev is None:
173            logger.info("Timeout while waiting for connection in iteration %d" % i)
174            dev[0].request("REMOVE_NETWORK all")
175            time.sleep(0.1)
176        else:
177            if "CTRL-EVENT-SSID-TEMP-DISABLED" in ev:
178                logger.info("Re-select to avoid long wait for temp disavle")
179                dev[0].select_network(id)
180                dev[0].wait_connected()
181            dev[0].request("REMOVE_NETWORK all")
182            dev[0].wait_disconnected()
183        for i in range(3):
184            dev[i].dump_monitor()
185        hapd.dump_monitor()
186
187        state = hapd.request('GET_ALLOC_FAIL')
188        logger.info("GET_ALLOC_FAIL: " + state)
189        hapd.request("TEST_ALLOC_FAIL 0:")
190        if state.startswith('0:'):
191            count = 0
192        else:
193            count += 1
194            if count == 5:
195                break
196    dev[0].request("SCAN_INTERVAL 5")
197