]>
Commit | Line | Data |
---|---|---|
37fa2eb5 JM |
1 | #!/usr/bin/python |
2 | # | |
3 | # Test cases for AP VLAN | |
44785ff2 | 4 | # Copyright (c) 2013-2016, Jouni Malinen <j@w1.fi> |
37fa2eb5 JM |
5 | # |
6 | # This software may be distributed under the terms of the BSD license. | |
7 | # See README for more details. | |
8 | ||
9fd6804d | 9 | from remotehost import remote_compatible |
37fa2eb5 JM |
10 | import time |
11 | import subprocess | |
12 | import logging | |
13 | logger = logging.getLogger(__name__) | |
14 | ||
54cf411f MB |
15 | try: |
16 | import netifaces | |
17 | netifaces_imported = True | |
18 | except ImportError: | |
19 | netifaces_imported = False | |
20 | ||
37fa2eb5 JM |
21 | import hwsim_utils |
22 | import hostapd | |
44785ff2 | 23 | from utils import iface_is_in_bridge, HwsimSkip, alloc_fail |
ee2b0d19 MB |
24 | import os |
25 | from tshark import run_tshark | |
37fa2eb5 JM |
26 | |
27 | def test_ap_vlan_open(dev, apdev): | |
28 | """AP VLAN with open network""" | |
29 | params = { "ssid": "test-vlan-open", | |
30 | "dynamic_vlan": "1", | |
31 | "accept_mac_file": "hostapd.accept" } | |
8b8a1864 | 32 | hapd = hostapd.add_ap(apdev[0], params) |
37fa2eb5 JM |
33 | |
34 | dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") | |
35 | dev[1].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") | |
36 | dev[2].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") | |
1131a1c8 JM |
37 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") |
38 | hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2") | |
a8375c94 | 39 | hwsim_utils.test_connectivity(dev[2], hapd) |
37fa2eb5 | 40 | |
fd6b727e JM |
41 | def test_ap_vlan_file_open(dev, apdev): |
42 | """AP VLAN with open network and vlan_file mapping""" | |
43 | params = { "ssid": "test-vlan-open", | |
44 | "dynamic_vlan": "1", | |
45 | "vlan_file": "hostapd.vlan", | |
46 | "accept_mac_file": "hostapd.accept" } | |
8b8a1864 | 47 | hapd = hostapd.add_ap(apdev[0], params) |
fd6b727e JM |
48 | |
49 | dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") | |
50 | dev[1].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") | |
51 | dev[2].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") | |
1131a1c8 JM |
52 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") |
53 | hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2") | |
a8375c94 | 54 | hwsim_utils.test_connectivity(dev[2], hapd) |
fd6b727e | 55 | |
afd38c9f JM |
56 | def test_ap_vlan_file_open2(dev, apdev): |
57 | """AP VLAN with open network and vlan_file mapping (2)""" | |
58 | params = { "ssid": "test-vlan-open", | |
59 | "dynamic_vlan": "1", | |
60 | "vlan_file": "hostapd.vlan2", | |
61 | "accept_mac_file": "hostapd.accept2" } | |
62 | hapd = hostapd.add_ap(apdev[0], params) | |
63 | ||
64 | dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") | |
65 | dev[1].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") | |
66 | dev[2].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") | |
67 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") | |
68 | hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2") | |
69 | hwsim_utils.test_connectivity_iface(dev[2], hapd, "hwsimbr3") | |
70 | ||
44785ff2 JM |
71 | def test_ap_vlan_file_parsing(dev, apdev, params): |
72 | """hostapd vlan_file/mac_file parsing""" | |
73 | tmp = os.path.join(params['logdir'], 'ap_vlan_file_parsing.tmp') | |
74 | params = { "ssid": "test-vlan-open", "dynamic_vlan": "1" } | |
75 | hapd = hostapd.add_ap(apdev[0], params) | |
76 | ||
77 | tests = [ "#\n\n0\t11\n", | |
78 | "* ", | |
79 | "1 netdev12345678901234567890" ] | |
80 | for t in tests: | |
81 | with open(tmp, "w") as f: | |
82 | f.write(t) | |
83 | if "FAIL" not in hapd.request("SET vlan_file " + tmp): | |
84 | raise Exception("Invalid vlan_file accepted") | |
85 | ||
86 | with open(tmp, "w") as f: | |
87 | f.write("1\tvlan\n") | |
88 | with alloc_fail(hapd, 1, "=hostapd_config_read_vlan_file"): | |
89 | if "FAIL" not in hapd.request("SET vlan_file " + tmp): | |
90 | raise Exception("vlan_file accepted during OOM") | |
91 | ||
92 | tests = [ "#\n\n0\tvlan\n", | |
93 | "4095\tvlan\n", | |
94 | "vlan\n", | |
95 | "1\t1234567890abcdef1234567890\n", | |
96 | "1\n" ] | |
97 | for t in tests: | |
98 | with open(tmp, "w") as f: | |
99 | f.write(t) | |
100 | if "FAIL" not in hapd.request("SET accept_mac_file " + tmp): | |
101 | raise Exception("Invalid accept_mac_file accepted") | |
102 | ||
103 | with open(tmp, "w") as f: | |
104 | f.write("00:11:22:33:44:55\n") | |
105 | with alloc_fail(hapd, 1, "hostapd_config_read_maclist"): | |
106 | if "FAIL" not in hapd.request("SET accept_mac_file " + tmp): | |
107 | raise Exception("accept_mac_file accepted during OOM") | |
108 | ||
37fa2eb5 JM |
109 | def test_ap_vlan_wpa2(dev, apdev): |
110 | """AP VLAN with WPA2-PSK""" | |
111 | params = hostapd.wpa2_params(ssid="test-vlan", | |
112 | passphrase="12345678") | |
bc6e3288 JM |
113 | params['dynamic_vlan'] = "1" |
114 | params['accept_mac_file'] = "hostapd.accept" | |
8b8a1864 | 115 | hapd = hostapd.add_ap(apdev[0], params) |
37fa2eb5 JM |
116 | |
117 | dev[0].connect("test-vlan", psk="12345678", scan_freq="2412") | |
118 | dev[1].connect("test-vlan", psk="12345678", scan_freq="2412") | |
119 | dev[2].connect("test-vlan", psk="12345678", scan_freq="2412") | |
1131a1c8 JM |
120 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") |
121 | hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2") | |
a8375c94 | 122 | hwsim_utils.test_connectivity(dev[2], hapd) |
fac17227 JM |
123 | |
124 | def test_ap_vlan_wpa2_radius(dev, apdev): | |
125 | """AP VLAN with WPA2-Enterprise and RADIUS attributes""" | |
126 | params = hostapd.wpa2_eap_params(ssid="test-vlan") | |
bc6e3288 | 127 | params['dynamic_vlan'] = "1" |
8b8a1864 | 128 | hapd = hostapd.add_ap(apdev[0], params) |
fac17227 JM |
129 | |
130 | dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX", | |
131 | identity="vlan1", | |
132 | password_hex="0123456789abcdef0123456789abcdef", | |
133 | scan_freq="2412") | |
134 | dev[1].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX", | |
135 | identity="vlan2", | |
136 | password_hex="0123456789abcdef0123456789abcdef", | |
137 | scan_freq="2412") | |
138 | dev[2].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX", | |
139 | identity="pax.user@example.com", | |
140 | password_hex="0123456789abcdef0123456789abcdef", | |
141 | scan_freq="2412") | |
1131a1c8 JM |
142 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") |
143 | hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2") | |
a8375c94 | 144 | hwsim_utils.test_connectivity(dev[2], hapd) |
fac17227 | 145 | |
57af507e MB |
146 | def test_ap_vlan_wpa2_radius_2(dev, apdev): |
147 | """AP VLAN with WPA2-Enterprise and RADIUS EGRESS_VLANID attributes""" | |
148 | params = hostapd.wpa2_eap_params(ssid="test-vlan") | |
bc6e3288 | 149 | params['dynamic_vlan'] = "1" |
8b8a1864 | 150 | hapd = hostapd.add_ap(apdev[0], params) |
57af507e MB |
151 | |
152 | dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX", | |
153 | identity="vlan1b", | |
154 | password_hex="0123456789abcdef0123456789abcdef", | |
155 | scan_freq="2412") | |
156 | ||
157 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") | |
158 | ||
fef133e9 JM |
159 | def test_ap_vlan_wpa2_radius_local(dev, apdev): |
160 | """AP VLAN with WPA2-Enterprise and local file setting VLAN IDs""" | |
161 | params = hostapd.wpa2_eap_params(ssid="test-vlan") | |
162 | params['dynamic_vlan'] = "0" | |
163 | params['vlan_file'] = "hostapd.vlan" | |
164 | params['vlan_bridge'] = "test_br_vlan" | |
165 | params['accept_mac_file'] = "hostapd.accept" | |
166 | hapd = hostapd.add_ap(apdev[0], params) | |
167 | ||
168 | dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX", | |
169 | identity="pax.user@example.com", | |
170 | password_hex="0123456789abcdef0123456789abcdef", | |
171 | scan_freq="2412") | |
172 | dev[1].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX", | |
173 | identity="pax.user@example.com", | |
174 | password_hex="0123456789abcdef0123456789abcdef", | |
175 | scan_freq="2412") | |
176 | dev[2].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX", | |
177 | identity="pax.user@example.com", | |
178 | password_hex="0123456789abcdef0123456789abcdef", | |
179 | scan_freq="2412") | |
180 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "test_br_vlan1") | |
181 | hwsim_utils.test_connectivity_iface(dev[1], hapd, "test_br_vlan2") | |
182 | hwsim_utils.test_connectivity(dev[2], hapd) | |
183 | ||
3a4bace4 JM |
184 | def test_ap_vlan_wpa2_radius_id_change(dev, apdev): |
185 | """AP VLAN with WPA2-Enterprise and RADIUS attributes changing VLANID""" | |
3fdb5005 MB |
186 | generic_ap_vlan_wpa2_radius_id_change(dev, apdev, False) |
187 | ||
188 | def test_ap_vlan_tagged_wpa2_radius_id_change(dev, apdev): | |
189 | """AP tagged VLAN with WPA2-Enterprise and RADIUS attributes changing VLANID""" | |
190 | ifname1 = 'wlan0.1' | |
191 | ifname2 = 'wlan0.2' | |
192 | try: | |
193 | # Create tagged interface for wpa_supplicant | |
194 | subprocess.call(['ip', 'link', 'add', 'link', dev[0].ifname, | |
195 | 'name', ifname1, 'type', 'vlan', 'id', '1']) | |
196 | subprocess.call(['ifconfig', ifname1, 'up']) | |
197 | ||
198 | subprocess.call(['ip', 'link', 'add', 'link', dev[0].ifname, | |
199 | 'name', ifname2, 'type', 'vlan', 'id', '2']) | |
200 | subprocess.call(['ifconfig', ifname2, 'up']) | |
201 | ||
202 | generic_ap_vlan_wpa2_radius_id_change(dev, apdev, True) | |
203 | finally: | |
204 | subprocess.call(['ifconfig', ifname1, 'down']) | |
205 | subprocess.call(['ifconfig', ifname2, 'down']) | |
206 | subprocess.call(['ip', 'link', 'del', ifname1]) | |
207 | subprocess.call(['ip', 'link', 'del', ifname2]) | |
208 | ||
209 | def generic_ap_vlan_wpa2_radius_id_change(dev, apdev, tagged): | |
3a4bace4 JM |
210 | as_params = { "ssid": "as", |
211 | "beacon_int": "2000", | |
212 | "radius_server_clients": "auth_serv/radius_clients.conf", | |
213 | "radius_server_auth_port": '18128', | |
214 | "eap_server": "1", | |
215 | "eap_user_file": "auth_serv/eap_user.conf", | |
216 | "ca_cert": "auth_serv/ca.pem", | |
217 | "server_cert": "auth_serv/server.pem", | |
218 | "private_key": "auth_serv/server.key" } | |
8b8a1864 | 219 | authserv = hostapd.add_ap(apdev[1], as_params) |
3a4bace4 JM |
220 | |
221 | params = hostapd.wpa2_eap_params(ssid="test-vlan") | |
bc6e3288 | 222 | params['dynamic_vlan'] = "1" |
3a4bace4 | 223 | params['auth_server_port'] = "18128" |
8b8a1864 | 224 | hapd = hostapd.add_ap(apdev[0], params) |
3a4bace4 | 225 | |
3fdb5005 MB |
226 | identity = "vlan1tagged" if tagged else "vlan1" |
227 | ||
3a4bace4 | 228 | dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX", |
3fdb5005 | 229 | identity=identity, |
3a4bace4 JM |
230 | password_hex="0123456789abcdef0123456789abcdef", |
231 | scan_freq="2412") | |
3fdb5005 MB |
232 | if tagged: |
233 | hwsim_utils.run_connectivity_test(dev[0], hapd, 0, ifname1="wlan0.1", | |
234 | ifname2="brvlan1") | |
235 | else: | |
236 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") | |
3a4bace4 | 237 | |
bbe9eddc MB |
238 | logger.info("VLAN-ID -> 2") |
239 | ||
3a4bace4 JM |
240 | authserv.disable() |
241 | authserv.set('eap_user_file', "auth_serv/eap_user_vlan.conf") | |
242 | authserv.enable() | |
243 | ||
244 | dev[0].dump_monitor() | |
245 | dev[0].request("REAUTHENTICATE") | |
246 | ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15) | |
247 | if ev is None: | |
248 | raise Exception("EAP reauthentication timed out") | |
8aba435b JM |
249 | ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=5) |
250 | if ev is None: | |
251 | raise Exception("4-way handshake after reauthentication timed out") | |
3a4bace4 JM |
252 | state = dev[0].get_status_field('wpa_state') |
253 | if state != "COMPLETED": | |
9416e47f | 254 | raise Exception("Unexpected state after reauth: " + state) |
f80fd58d JM |
255 | sta = hapd.get_sta(dev[0].own_addr()) |
256 | if 'vlan_id' not in sta: | |
257 | raise Exception("No VLAN ID in STA info") | |
3fdb5005 | 258 | if (not tagged) and (sta['vlan_id'] != '2'): |
f80fd58d | 259 | raise Exception("Unexpected VLAN ID: " + sta['vlan_id']) |
3fdb5005 MB |
260 | if tagged: |
261 | hwsim_utils.run_connectivity_test(dev[0], hapd, 0, ifname1="wlan0.2", | |
262 | ifname2="brvlan2") | |
263 | else: | |
264 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan2") | |
3a4bace4 | 265 | |
bbe9eddc MB |
266 | logger.info("VLAN-ID -> 1") |
267 | time.sleep(1) | |
268 | ||
269 | authserv.disable() | |
270 | authserv.set('eap_user_file', "auth_serv/eap_user.conf") | |
271 | authserv.enable() | |
272 | ||
273 | dev[0].dump_monitor() | |
274 | dev[0].request("REAUTHENTICATE") | |
275 | ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15) | |
276 | if ev is None: | |
277 | raise Exception("EAP reauthentication timed out") | |
278 | ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=5) | |
279 | if ev is None: | |
280 | raise Exception("4-way handshake after reauthentication timed out") | |
281 | state = dev[0].get_status_field('wpa_state') | |
282 | if state != "COMPLETED": | |
283 | raise Exception("Unexpected state after reauth: " + state) | |
284 | sta = hapd.get_sta(dev[0].own_addr()) | |
285 | if 'vlan_id' not in sta: | |
286 | raise Exception("No VLAN ID in STA info") | |
3fdb5005 | 287 | if (not tagged) and (sta['vlan_id'] != '1'): |
bbe9eddc MB |
288 | raise Exception("Unexpected VLAN ID: " + sta['vlan_id']) |
289 | time.sleep(0.2) | |
290 | try: | |
3fdb5005 MB |
291 | if tagged: |
292 | hwsim_utils.run_connectivity_test(dev[0], hapd, 0, | |
293 | ifname1="wlan0.1", | |
294 | ifname2="brvlan1") | |
295 | else: | |
296 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") | |
bab493b9 | 297 | except Exception as e: |
bbe9eddc MB |
298 | # It is possible for new bridge setup to not be ready immediately, so |
299 | # try again to avoid reporting issues related to that. | |
300 | logger.info("First VLAN-ID 1 data test failed - try again") | |
3fdb5005 MB |
301 | if tagged: |
302 | hwsim_utils.run_connectivity_test(dev[0], hapd, 0, | |
303 | ifname1="wlan0.1", | |
304 | ifname2="brvlan1") | |
305 | else: | |
306 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") | |
bbe9eddc | 307 | |
fac17227 JM |
308 | def test_ap_vlan_wpa2_radius_required(dev, apdev): |
309 | """AP VLAN with WPA2-Enterprise and RADIUS attributes required""" | |
310 | params = hostapd.wpa2_eap_params(ssid="test-vlan") | |
bc6e3288 | 311 | params['dynamic_vlan'] = "2" |
8b8a1864 | 312 | hostapd.add_ap(apdev[0], params) |
fac17227 JM |
313 | |
314 | dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX", | |
315 | identity="vlan1", | |
316 | password_hex="0123456789abcdef0123456789abcdef", | |
317 | scan_freq="2412") | |
318 | dev[2].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX", | |
319 | identity="pax.user@example.com", | |
320 | password_hex="0123456789abcdef0123456789abcdef", | |
321 | scan_freq="2412", wait_connect=False) | |
322 | ev = dev[2].wait_event(["CTRL-EVENT-CONNECTED", | |
323 | "CTRL-EVENT-DISCONNECTED"], timeout=20) | |
324 | if ev is None: | |
325 | raise Exception("Timeout on connection attempt") | |
326 | if "CTRL-EVENT-CONNECTED" in ev: | |
327 | raise Exception("Unexpected success without tunnel parameters") | |
018ead42 JM |
328 | |
329 | def test_ap_vlan_tagged(dev, apdev): | |
330 | """AP VLAN with tagged interface""" | |
331 | params = { "ssid": "test-vlan-open", | |
332 | "dynamic_vlan": "1", | |
333 | "vlan_tagged_interface": "lo", | |
334 | "accept_mac_file": "hostapd.accept" } | |
8b8a1864 | 335 | hapd = hostapd.add_ap(apdev[0], params) |
018ead42 JM |
336 | |
337 | dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") | |
338 | dev[1].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") | |
339 | dev[2].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") | |
1131a1c8 JM |
340 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brlo.1") |
341 | hwsim_utils.test_connectivity_iface(dev[1], hapd, "brlo.2") | |
a8375c94 | 342 | hwsim_utils.test_connectivity(dev[2], hapd) |
54cf411f MB |
343 | |
344 | def ap_vlan_iface_cleanup_multibss_cleanup(): | |
345 | subprocess.call(['ifconfig', 'dummy0', 'down'], | |
346 | stderr=open('/dev/null', 'w')) | |
347 | ifnames = [ 'wlan3.1', 'wlan3.2', 'wlan3-2.1', 'wlan3-2.2', 'dummy0.2', | |
348 | 'dummy0.1', 'dummy0', 'brvlan1', 'brvlan2' ] | |
349 | for ifname in ifnames: | |
350 | subprocess.call(['ip', 'link', 'del', ifname], | |
351 | stderr=open('/dev/null', 'w')) | |
352 | ||
353 | def ap_vlan_iface_test_and_prepare_environ(): | |
354 | ifaces = netifaces.interfaces() | |
355 | if "dummy0" in ifaces: | |
356 | raise Exception("dummy0 already exists before") | |
357 | ifaces = netifaces.interfaces() | |
358 | if "dummy0.1" in ifaces: | |
359 | raise Exception("dummy0.1 already exists before") | |
360 | ||
361 | subprocess.call(['ip', 'link', 'add', 'dummy0', 'type', 'dummy']) | |
362 | subprocess.call(['ifconfig', 'dummy0', 'up']) | |
363 | ||
364 | ifaces = netifaces.interfaces() | |
365 | if not("dummy0" in ifaces): | |
366 | raise HwsimSkip("failed to add dummy0 - missing kernel config DUMMY ?") | |
367 | ||
368 | subprocess.call(['ip', 'link', 'add', 'link', 'dummy0', 'name', 'dummy0.1', | |
369 | 'type', 'vlan', 'id', '1']) | |
370 | ||
371 | ifaces = netifaces.interfaces() | |
372 | if not("dummy0.1" in ifaces): | |
373 | raise HwsimSkip("failed to add dummy0.1 - missing kernel config VLAN_8021Q ?") | |
374 | ||
375 | subprocess.call(['ip', 'link', 'del', 'dummy0.1']) | |
376 | ||
377 | ifaces = netifaces.interfaces() | |
378 | if "dummy0.1" in ifaces: | |
379 | raise Exception("dummy0.1 was not removed before testing") | |
380 | ||
381 | def test_ap_vlan_iface_cleanup_multibss(dev, apdev): | |
382 | """AP VLAN operation in multi-BSS multi-VLAN case""" | |
a8c235ee | 383 | ap_vlan_iface_cleanup_multibss(dev, apdev, 'multi-bss-iface.conf') |
54cf411f | 384 | |
a8c235ee | 385 | def ap_vlan_iface_cleanup_multibss(dev, apdev, cfgfile): |
54cf411f MB |
386 | # AP VLAN with WPA2-Enterprise and RADIUS attributes changing VLANID |
387 | # check that multiple bss do not interfere with each other with respect | |
388 | # to deletion of bridge and tagged interface. | |
389 | ||
390 | if not netifaces_imported: | |
391 | raise HwsimSkip("python module netifaces not available") | |
392 | ||
393 | try: | |
394 | ap_vlan_iface_cleanup_multibss_cleanup() | |
395 | ap_vlan_iface_test_and_prepare_environ() | |
396 | ||
397 | as_params = { "ssid": "as", | |
398 | "beacon_int": "2000", | |
399 | "radius_server_clients": "auth_serv/radius_clients.conf", | |
400 | "radius_server_auth_port": '18128', | |
401 | "eap_server": "1", | |
402 | "eap_user_file": "auth_serv/eap_user.conf", | |
403 | "ca_cert": "auth_serv/ca.pem", | |
404 | "server_cert": "auth_serv/server.pem", | |
405 | "private_key": "auth_serv/server.key", | |
406 | "vlan_naming": "1" } | |
8b8a1864 | 407 | authserv = hostapd.add_ap(apdev[1], as_params) |
54cf411f | 408 | |
54cf411f | 409 | # start the actual test |
50e49cd2 | 410 | hapd = hostapd.add_iface(apdev[0], cfgfile) |
54cf411f MB |
411 | hapd1 = hostapd.Hostapd("wlan3-2", 1) |
412 | hapd1.enable() | |
413 | ||
414 | ifaces = netifaces.interfaces() | |
415 | if "brvlan1" in ifaces: | |
416 | raise Exception("bridge brvlan1 already exists before") | |
417 | if "brvlan2" in ifaces: | |
418 | raise Exception("bridge brvlan2 already exists before") | |
419 | ||
420 | dev[0].connect("bss-1", key_mgmt="WPA-EAP", eap="PAX", | |
421 | identity="vlan1", | |
422 | password_hex="0123456789abcdef0123456789abcdef", | |
423 | scan_freq="2412") | |
424 | ||
425 | ifaces = netifaces.interfaces() | |
426 | if not("brvlan1" in ifaces): | |
427 | raise Exception("bridge brvlan1 was not created") | |
428 | ||
429 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") | |
430 | if not iface_is_in_bridge("brvlan1", "dummy0.1"): | |
431 | raise Exception("dummy0.1 not in brvlan1") | |
432 | ||
433 | dev[1].connect("bss-2", key_mgmt="WPA-EAP", eap="PAX", | |
434 | identity="vlan1", | |
435 | password_hex="0123456789abcdef0123456789abcdef", | |
436 | scan_freq="2412") | |
437 | ||
438 | hwsim_utils.test_connectivity_iface(dev[1], hapd1, "brvlan1") | |
439 | if not iface_is_in_bridge("brvlan1", "dummy0.1"): | |
440 | raise Exception("dummy0.1 not in brvlan1") | |
441 | ||
442 | authserv.disable() | |
443 | authserv.set('eap_user_file', "auth_serv/eap_user_vlan.conf") | |
444 | authserv.enable() | |
445 | ||
446 | logger.info("wlan0 -> VLAN 2") | |
447 | ||
448 | dev[0].dump_monitor() | |
449 | dev[0].request("REAUTHENTICATE") | |
450 | ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15) | |
451 | if ev is None: | |
452 | raise Exception("EAP reauthentication timed out") | |
453 | ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=5) | |
454 | if ev is None: | |
455 | raise Exception("4-way handshake after reauthentication timed out") | |
456 | state = dev[0].get_status_field('wpa_state') | |
457 | if state != "COMPLETED": | |
458 | raise Exception("Unexpected state after reauth: " + state) | |
459 | ||
460 | ifaces = netifaces.interfaces() | |
461 | if not ("brvlan1" in ifaces): | |
462 | raise Exception("bridge brvlan1 has been removed too early") | |
463 | ||
464 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan2", | |
465 | max_tries=5) | |
466 | ||
467 | if not iface_is_in_bridge("brvlan2", "dummy0.2"): | |
468 | raise Exception("dummy0.2 not in brvlan2") | |
469 | ||
470 | logger.info("test wlan1 == VLAN 1") | |
471 | hwsim_utils.test_connectivity_iface(dev[1], hapd1, "brvlan1") | |
472 | if not iface_is_in_bridge("brvlan1", "dummy0.1"): | |
473 | raise Exception("dummy0.1 not in brvlan1") | |
474 | ||
475 | logger.info("wlan1 -> VLAN 2") | |
476 | ||
477 | dev[1].dump_monitor() | |
478 | dev[1].request("REAUTHENTICATE") | |
479 | ev = dev[1].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15) | |
480 | if ev is None: | |
481 | raise Exception("EAP reauthentication timed out") | |
482 | ev = dev[1].wait_event(["WPA: Key negotiation completed"], timeout=5) | |
483 | if ev is None: | |
484 | raise Exception("4-way handshake after reauthentication timed out") | |
485 | state = dev[1].get_status_field('wpa_state') | |
486 | if state != "COMPLETED": | |
487 | raise Exception("Unexpected state after reauth: " + state) | |
488 | ||
489 | # it can take some time for data connectivity to be updated | |
490 | hwsim_utils.test_connectivity_iface(dev[1], hapd1, "brvlan2", | |
491 | max_tries=5) | |
492 | logger.info("test wlan0 == VLAN 2") | |
493 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan2") | |
494 | ||
495 | if not iface_is_in_bridge("brvlan2", "dummy0.2"): | |
496 | raise Exception("dummy0.2 not in brvlan2") | |
497 | ||
498 | ifaces = netifaces.interfaces() | |
499 | if "brvlan1" in ifaces: | |
500 | raise Exception("bridge brvlan1 has not been cleaned up") | |
501 | ||
502 | # disconnect dev0 first to test a corner case | |
503 | dev[0].request("DISCONNECT") | |
504 | dev[0].wait_disconnected() | |
505 | dev[1].request("DISCONNECT") | |
506 | dev[1].wait_disconnected() | |
507 | ||
508 | # station removal needs some time | |
97ad4d20 | 509 | for i in range(15): |
54cf411f MB |
510 | time.sleep(1) |
511 | ifaces = netifaces.interfaces() | |
512 | if "brvlan2" not in ifaces: | |
513 | break | |
514 | ||
515 | ifaces = netifaces.interfaces() | |
516 | if "brvlan2" in ifaces: | |
517 | raise Exception("bridge brvlan2 has not been cleaned up") | |
518 | ||
519 | hapd.request("DISABLE") | |
520 | finally: | |
521 | ap_vlan_iface_cleanup_multibss_cleanup() | |
ee2b0d19 | 522 | |
a8c235ee MB |
523 | def test_ap_vlan_iface_cleanup_multibss_per_sta_vif(dev, apdev): |
524 | """AP VLAN operation in multi-BSS multi-VLAN case with per-sta-vif set""" | |
525 | ||
526 | # AP VLAN with WPA2-Enterprise and RADIUS attributes changing VLANID | |
527 | # check that multiple bss do not interfere with each other with respect | |
528 | # to deletion of bridge and tagged interface. per_sta_vif is enabled. | |
529 | ap_vlan_iface_cleanup_multibss(dev, apdev, | |
530 | 'multi-bss-iface-per_sta_vif.conf') | |
531 | ||
ee2b0d19 MB |
532 | def test_ap_vlan_without_station(dev, apdev, p): |
533 | """AP VLAN with WPA2-PSK and no station""" | |
534 | try: | |
535 | subprocess.call(['brctl', 'addbr', 'brvlan1']) | |
536 | subprocess.call(['brctl', 'setfd', 'brvlan1', '0']) | |
537 | subprocess.call(['ifconfig', 'brvlan1', 'up']) | |
538 | # use a passphrase wlantest does not know, so it cannot | |
539 | # inject decrypted frames into pcap | |
540 | params = hostapd.wpa2_params(ssid="test-vlan", | |
541 | passphrase="12345678x") | |
bc6e3288 | 542 | params['dynamic_vlan'] = "1" |
ee2b0d19 | 543 | params['vlan_file'] = 'hostapd.wlan3.vlan' |
bc6e3288 | 544 | params['accept_mac_file'] = "hostapd.accept" |
8b8a1864 | 545 | hapd = hostapd.add_ap(apdev[0], params) |
ee2b0d19 MB |
546 | |
547 | # inject some traffic | |
548 | sa = hapd.own_addr() | |
549 | da = "ff:ff:ff:ff:ff:00" | |
550 | hapd.request('DATA_TEST_CONFIG 1 ifname=brvlan1') | |
551 | hapd.request('DATA_TEST_TX {} {} 0'.format(da, sa)) | |
552 | hapd.request('DATA_TEST_CONFIG 0') | |
553 | time.sleep(.1) | |
554 | ||
555 | dev[0].connect("test-vlan", psk="12345678x", scan_freq="2412") | |
556 | ||
557 | # inject some traffic | |
558 | sa = hapd.own_addr() | |
559 | da = "ff:ff:ff:ff:ff:01" | |
560 | hapd.request('DATA_TEST_CONFIG 1 ifname=brvlan1') | |
561 | hapd.request('DATA_TEST_TX {} {} 0'.format(da, sa)) | |
562 | hapd.request('DATA_TEST_CONFIG 0') | |
563 | ||
564 | # let the AP send couple of Beacon frames | |
565 | time.sleep(1) | |
566 | out = run_tshark(os.path.join(p['logdir'], "hwsim0.pcapng"), | |
567 | "wlan.da == ff:ff:ff:ff:ff:00", | |
568 | ["wlan.fc.protected"]) | |
569 | ||
570 | if out is not None: | |
571 | lines = out.splitlines() | |
572 | if len(lines) < 1: | |
09b306b1 JM |
573 | # Newer kernel versions filter out frames when there are no |
574 | # authorized stations on an AP/AP_VLAN interface, so do not | |
575 | # trigger an error here. | |
576 | logger.info("first frame not observed") | |
ee2b0d19 MB |
577 | state = 1 |
578 | for l in lines: | |
579 | is_protected = int(l, 16) | |
580 | if is_protected != 1: | |
581 | state = 0 | |
582 | if state != 1: | |
583 | raise Exception("Broadcast packets were not encrypted when no station was connected") | |
584 | else: | |
585 | raise Exception("first frame not observed") | |
586 | ||
587 | out = run_tshark(os.path.join(p['logdir'], "hwsim0.pcapng"), | |
588 | "wlan.da == ff:ff:ff:ff:ff:01", | |
589 | ["wlan.fc.protected"]) | |
590 | ||
591 | if out is not None: | |
592 | lines = out.splitlines() | |
593 | if len(lines) < 1: | |
594 | raise Exception("second frame not observed") | |
595 | state = 1 | |
596 | for l in lines: | |
597 | is_protected = int(l, 16) | |
598 | if is_protected != 1: | |
599 | state = 0 | |
600 | if state != 1: | |
601 | raise Exception("Broadcast packets were not encrypted when station was connected") | |
602 | else: | |
603 | raise Exception("second frame not observed") | |
604 | ||
605 | dev[0].request("DISCONNECT") | |
606 | dev[0].wait_disconnected() | |
607 | ||
608 | finally: | |
609 | subprocess.call(['ip', 'link', 'set', 'dev', 'brvlan1', 'down']) | |
610 | subprocess.call(['ip', 'link', 'set', 'dev', 'wlan3.1', 'down'], | |
611 | stderr=open('/dev/null', 'w')) | |
612 | subprocess.call(['brctl', 'delif', 'brvlan1', 'wlan3.1'], | |
613 | stderr=open('/dev/null', 'w')) | |
614 | subprocess.call(['brctl', 'delbr', 'brvlan1']) | |
629d3696 | 615 | |
9fd6804d | 616 | @remote_compatible |
571e6907 MB |
617 | def test_ap_open_per_sta_vif(dev, apdev): |
618 | """AP VLAN with open network""" | |
619 | params = { "ssid": "test-vlan-open", | |
620 | "per_sta_vif": "1" } | |
8b8a1864 | 621 | hapd = hostapd.add_ap(apdev[0], params) |
571e6907 MB |
622 | |
623 | dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") | |
624 | hwsim_utils.test_connectivity_iface(dev[0], hapd, | |
625 | apdev[0]['ifname'] + ".4096") | |
626 | ||
9fd6804d | 627 | @remote_compatible |
571e6907 MB |
628 | def test_ap_vlan_open_per_sta_vif(dev, apdev): |
629 | """AP VLAN (dynamic) with open network""" | |
630 | params = { "ssid": "test-vlan-open", | |
631 | "per_sta_vif": "1", | |
632 | "dynamic_vlan": "1" } | |
8b8a1864 | 633 | hapd = hostapd.add_ap(apdev[0], params) |
571e6907 MB |
634 | |
635 | dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") | |
636 | hwsim_utils.test_connectivity_iface(dev[0], hapd, | |
637 | apdev[0]['ifname'] + ".4096") | |
638 | ||
629d3696 MB |
639 | def test_ap_vlan_wpa2_radius_tagged(dev, apdev): |
640 | """AP VLAN with WPA2-Enterprise and RADIUS EGRESS_VLANID attributes""" | |
641 | ifname = 'wlan0.1' | |
642 | try: | |
643 | params = hostapd.wpa2_eap_params(ssid="test-vlan") | |
644 | params['dynamic_vlan'] = "1" | |
645 | params["vlan_naming"] = "1" | |
8b8a1864 | 646 | hapd = hostapd.add_ap(apdev[0], params) |
629d3696 MB |
647 | |
648 | dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX", | |
649 | identity="vlan1tagged", | |
650 | password_hex="0123456789abcdef0123456789abcdef", | |
651 | scan_freq="2412") | |
652 | ||
653 | # Create tagged interface for wpa_supplicant | |
654 | subprocess.call(['ip', 'link', 'add', 'link', dev[0].ifname, | |
655 | 'name', ifname, 'type', 'vlan', 'id', '1']) | |
656 | subprocess.call(['ifconfig', ifname, 'up']) | |
657 | ||
658 | hwsim_utils.run_connectivity_test(dev[0], hapd, 0, ifname1=ifname, | |
659 | ifname2="brvlan1") | |
660 | finally: | |
661 | subprocess.call(['ifconfig', ifname, 'down']) | |
662 | subprocess.call(['ip', 'link', 'del', ifname]) | |
732bbcc7 MB |
663 | |
664 | def test_ap_vlan_wpa2_radius_mixed(dev, apdev): | |
665 | """AP VLAN with WPA2-Enterprise and tagged+untagged VLANs""" | |
666 | ifname = 'wlan0.1' | |
667 | try: | |
668 | params = hostapd.wpa2_eap_params(ssid="test-vlan") | |
669 | params['dynamic_vlan'] = "1" | |
670 | params["vlan_naming"] = "1" | |
8b8a1864 | 671 | hapd = hostapd.add_ap(apdev[0], params) |
732bbcc7 MB |
672 | |
673 | dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX", | |
674 | identity="vlan12mixed", | |
675 | password_hex="0123456789abcdef0123456789abcdef", | |
676 | scan_freq="2412") | |
677 | ||
678 | # Add tagged VLAN interface to wpa_supplicant interface for testing | |
679 | subprocess.call(['ip', 'link', 'add', 'link', dev[0].ifname, | |
680 | 'name', ifname, 'type', 'vlan', 'id', '1']) | |
681 | subprocess.call(['ifconfig', ifname, 'up']) | |
682 | ||
683 | logger.info("Test connectivity in untagged VLAN 2") | |
684 | hwsim_utils.run_connectivity_test(dev[0], hapd, 0, | |
685 | ifname1=dev[0].ifname, | |
686 | ifname2="brvlan2") | |
687 | logger.info("Test connectivity in tagged VLAN 1") | |
688 | hwsim_utils.run_connectivity_test(dev[0], hapd, 0, ifname1=ifname, | |
689 | ifname2="brvlan1") | |
690 | finally: | |
691 | subprocess.call(['ifconfig', ifname, 'down']) | |
692 | subprocess.call(['ip', 'link', 'del', ifname]) | |
6556ddaf MB |
693 | |
694 | def test_ap_vlan_reconnect(dev, apdev): | |
695 | """AP VLAN with WPA2-PSK connect, disconnect, connect""" | |
696 | params = hostapd.wpa2_params(ssid="test-vlan", | |
697 | passphrase="12345678") | |
bc6e3288 JM |
698 | params['dynamic_vlan'] = "1" |
699 | params['accept_mac_file'] = "hostapd.accept" | |
8b8a1864 | 700 | hapd = hostapd.add_ap(apdev[0], params) |
6556ddaf MB |
701 | |
702 | logger.info("connect sta") | |
703 | dev[0].connect("test-vlan", psk="12345678", scan_freq="2412") | |
704 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") | |
705 | logger.info("disconnect sta") | |
706 | dev[0].request("REMOVE_NETWORK all") | |
707 | dev[0].wait_disconnected(timeout=10) | |
708 | time.sleep(1) | |
709 | logger.info("reconnect sta") | |
710 | dev[0].connect("test-vlan", psk="12345678", scan_freq="2412") | |
711 | hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") |