]> git.ipfire.org Git - thirdparty/hostap.git/blob - tests/hwsim/test_ap_hs20.py
tests: Fix proxyarp_open IPv4-from-bridge
[thirdparty/hostap.git] / tests / hwsim / test_ap_hs20.py
1 # Hotspot 2.0 tests
2 # Copyright (c) 2013-2014, 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
7 import binascii
8 import struct
9 import time
10 import subprocess
11 import logging
12 logger = logging.getLogger()
13 import os
14 import os.path
15 import socket
16 import subprocess
17
18 import hostapd
19 import hwsim_utils
20 from wlantest import Wlantest
21 from wpasupplicant import WpaSupplicant
22
23 def hs20_ap_params(ssid="test-hs20"):
24 params = hostapd.wpa2_params(ssid=ssid)
25 params['wpa_key_mgmt'] = "WPA-EAP"
26 params['ieee80211w'] = "1"
27 params['ieee8021x'] = "1"
28 params['auth_server_addr'] = "127.0.0.1"
29 params['auth_server_port'] = "1812"
30 params['auth_server_shared_secret'] = "radius"
31 params['interworking'] = "1"
32 params['access_network_type'] = "14"
33 params['internet'] = "1"
34 params['asra'] = "0"
35 params['esr'] = "0"
36 params['uesa'] = "0"
37 params['venue_group'] = "7"
38 params['venue_type'] = "1"
39 params['venue_name'] = [ "eng:Example venue", "fin:Esimerkkipaikka" ]
40 params['roaming_consortium'] = [ "112233", "1020304050", "010203040506",
41 "fedcba" ]
42 params['domain_name'] = "example.com,another.example.com"
43 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
44 "0,another.example.com" ]
45 params['hs20'] = "1"
46 params['hs20_wan_metrics'] = "01:8000:1000:80:240:3000"
47 params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0" ]
48 params['hs20_operating_class'] = "5173"
49 params['anqp_3gpp_cell_net'] = "244,91"
50 return params
51
52 def check_auto_select(dev, bssid):
53 dev.scan_for_bss(bssid, freq="2412")
54 dev.request("INTERWORKING_SELECT auto freq=2412")
55 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
56 if ev is None:
57 raise Exception("Connection timed out")
58 if bssid not in ev:
59 raise Exception("Connected to incorrect network")
60 dev.request("REMOVE_NETWORK all")
61
62 def interworking_select(dev, bssid, type=None, no_match=False, freq=None):
63 dev.dump_monitor()
64 if bssid and freq and not no_match:
65 dev.scan_for_bss(bssid, freq=freq)
66 freq_extra = " freq=" + freq if freq else ""
67 dev.request("INTERWORKING_SELECT" + freq_extra)
68 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
69 timeout=15)
70 if ev is None:
71 raise Exception("Network selection timed out");
72 if no_match:
73 if "INTERWORKING-NO-MATCH" not in ev:
74 raise Exception("Unexpected network match")
75 return
76 if "INTERWORKING-NO-MATCH" in ev:
77 logger.info("Matching network not found - try again")
78 dev.dump_monitor()
79 dev.request("INTERWORKING_SELECT" + freq_extra)
80 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
81 timeout=15)
82 if ev is None:
83 raise Exception("Network selection timed out");
84 if "INTERWORKING-NO-MATCH" in ev:
85 raise Exception("Matching network not found")
86 if bssid and bssid not in ev:
87 raise Exception("Unexpected BSSID in match")
88 if type and "type=" + type not in ev:
89 raise Exception("Network type not recognized correctly")
90
91 def check_sp_type(dev, sp_type):
92 type = dev.get_status_field("sp_type")
93 if type is None:
94 raise Exception("sp_type not available")
95 if type != sp_type:
96 raise Exception("sp_type did not indicate home network")
97
98 def hlr_auc_gw_available():
99 if not os.path.exists("/tmp/hlr_auc_gw.sock"):
100 logger.info("No hlr_auc_gw available");
101 return False
102 if not os.path.exists("../../hostapd/hlr_auc_gw"):
103 logger.info("No hlr_auc_gw available");
104 return False
105 return True
106
107 def interworking_ext_sim_connect(dev, bssid, method):
108 dev.request("INTERWORKING_CONNECT " + bssid)
109 interworking_ext_sim_auth(dev, method)
110
111 def interworking_ext_sim_auth(dev, method):
112 ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
113 if ev is None:
114 raise Exception("Network connected timed out")
115 if "(" + method + ")" not in ev:
116 raise Exception("Unexpected EAP method selection")
117
118 ev = dev.wait_event(["CTRL-REQ-SIM"], timeout=15)
119 if ev is None:
120 raise Exception("Wait for external SIM processing request timed out")
121 p = ev.split(':', 2)
122 if p[1] != "GSM-AUTH":
123 raise Exception("Unexpected CTRL-REQ-SIM type")
124 id = p[0].split('-')[3]
125 rand = p[2].split(' ')[0]
126
127 res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
128 "-m",
129 "auth_serv/hlr_auc_gw.milenage_db",
130 "GSM-AUTH-REQ 232010000000000 " + rand])
131 if "GSM-AUTH-RESP" not in res:
132 raise Exception("Unexpected hlr_auc_gw response")
133 resp = res.split(' ')[2].rstrip()
134
135 dev.request("CTRL-RSP-SIM-" + id + ":GSM-AUTH:" + resp)
136 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
137 if ev is None:
138 raise Exception("Connection timed out")
139
140 def interworking_connect(dev, bssid, method):
141 dev.request("INTERWORKING_CONNECT " + bssid)
142 interworking_auth(dev, method)
143
144 def interworking_auth(dev, method):
145 ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
146 if ev is None:
147 raise Exception("Network connected timed out")
148 if "(" + method + ")" not in ev:
149 raise Exception("Unexpected EAP method selection")
150
151 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
152 if ev is None:
153 raise Exception("Connection timed out")
154
155 def check_probe_resp(wt, bssid_unexpected, bssid_expected):
156 if bssid_unexpected:
157 count = wt.get_bss_counter("probe_response", bssid_unexpected)
158 if count > 0:
159 raise Exception("Unexpected Probe Response frame from AP")
160
161 if bssid_expected:
162 count = wt.get_bss_counter("probe_response", bssid_expected)
163 if count == 0:
164 raise Exception("No Probe Response frame from AP")
165
166 def test_ap_anqp_sharing(dev, apdev):
167 """ANQP sharing within ESS and explicit unshare"""
168 bssid = apdev[0]['bssid']
169 params = hs20_ap_params()
170 params['hessid'] = bssid
171 hostapd.add_ap(apdev[0]['ifname'], params)
172
173 bssid2 = apdev[1]['bssid']
174 params = hs20_ap_params()
175 params['hessid'] = bssid
176 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ]
177 hostapd.add_ap(apdev[1]['ifname'], params)
178
179 dev[0].hs20_enable()
180 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
181 'password': "secret",
182 'domain': "example.com" })
183 logger.info("Normal network selection with shared ANQP results")
184 dev[0].scan_for_bss(bssid, freq="2412")
185 dev[0].scan_for_bss(bssid2, freq="2412")
186 interworking_select(dev[0], None, "home", freq="2412")
187 dev[0].dump_monitor()
188
189 res1 = dev[0].get_bss(bssid)
190 res2 = dev[0].get_bss(bssid2)
191 if res1['anqp_nai_realm'] != res2['anqp_nai_realm']:
192 raise Exception("ANQP results were not shared between BSSes")
193
194 logger.info("Explicit ANQP request to unshare ANQP results")
195 dev[0].request("ANQP_GET " + bssid + " 263")
196 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
197 if ev is None:
198 raise Exception("ANQP operation timed out")
199
200 dev[0].request("ANQP_GET " + bssid2 + " 263")
201 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
202 if ev is None:
203 raise Exception("ANQP operation timed out")
204
205 res1 = dev[0].get_bss(bssid)
206 res2 = dev[0].get_bss(bssid2)
207 if res1['anqp_nai_realm'] == res2['anqp_nai_realm']:
208 raise Exception("ANQP results were not unshared")
209
210 def test_ap_nai_home_realm_query(dev, apdev):
211 """NAI Home Realm Query"""
212 bssid = apdev[0]['bssid']
213 params = hs20_ap_params()
214 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
215 "0,another.example.org" ]
216 hostapd.add_ap(apdev[0]['ifname'], params)
217
218 dev[0].scan(freq="2412")
219 dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid + " realm=example.com")
220 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
221 if ev is None:
222 raise Exception("ANQP operation timed out")
223 nai1 = dev[0].get_bss(bssid)['anqp_nai_realm']
224 dev[0].dump_monitor()
225
226 dev[0].request("ANQP_GET " + bssid + " 263")
227 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
228 if ev is None:
229 raise Exception("ANQP operation timed out")
230 nai2 = dev[0].get_bss(bssid)['anqp_nai_realm']
231
232 if len(nai1) >= len(nai2):
233 raise Exception("Unexpected NAI Realm list response lengths")
234 if "example.com".encode('hex') not in nai1:
235 raise Exception("Home realm not reported")
236 if "example.org".encode('hex') in nai1:
237 raise Exception("Non-home realm reported")
238 if "example.com".encode('hex') not in nai2:
239 raise Exception("Home realm not reported in wildcard query")
240 if "example.org".encode('hex') not in nai2:
241 raise Exception("Non-home realm not reported in wildcard query ")
242
243 cmds = [ "foo",
244 "00:11:22:33:44:55 123",
245 "00:11:22:33:44:55 qq" ]
246 for cmd in cmds:
247 if "FAIL" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + cmd):
248 raise Exception("Invalid HS20_GET_NAI_HOME_REALM_LIST accepted: " + cmd)
249
250 dev[0].dump_monitor()
251 if "OK" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid):
252 raise Exception("HS20_GET_NAI_HOME_REALM_LIST failed")
253 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
254 if ev is None:
255 raise Exception("ANQP operation timed out")
256 ev = dev[0].wait_event(["RX-ANQP"], timeout=0.1)
257 if ev is not None:
258 raise Exception("Unexpected ANQP response: " + ev)
259
260 dev[0].dump_monitor()
261 if "OK" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid + " 01000b6578616d706c652e636f6d"):
262 raise Exception("HS20_GET_NAI_HOME_REALM_LIST failed")
263 ev = dev[0].wait_event(["RX-ANQP"], timeout=10)
264 if ev is None:
265 raise Exception("No ANQP response")
266 if "NAI Realm list" not in ev:
267 raise Exception("Missing NAI Realm list: " + ev)
268
269 dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
270 'password': "secret",
271 'domain': "example.com" })
272 dev[0].dump_monitor()
273 if "OK" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid):
274 raise Exception("HS20_GET_NAI_HOME_REALM_LIST failed")
275 ev = dev[0].wait_event(["RX-ANQP"], timeout=10)
276 if ev is None:
277 raise Exception("No ANQP response")
278 if "NAI Realm list" not in ev:
279 raise Exception("Missing NAI Realm list: " + ev)
280
281 def test_ap_interworking_scan_filtering(dev, apdev):
282 """Interworking scan filtering with HESSID and access network type"""
283 try:
284 return _test_ap_interworking_scan_filtering(dev, apdev)
285 finally:
286 dev[0].request("SET hessid 00:00:00:00:00:00")
287 dev[0].request("SET access_network_type 15")
288
289 def _test_ap_interworking_scan_filtering(dev, apdev):
290 bssid = apdev[0]['bssid']
291 params = hs20_ap_params()
292 ssid = "test-hs20-ap1"
293 params['ssid'] = ssid
294 params['hessid'] = bssid
295 hostapd.add_ap(apdev[0]['ifname'], params)
296
297 bssid2 = apdev[1]['bssid']
298 params = hs20_ap_params()
299 ssid2 = "test-hs20-ap2"
300 params['ssid'] = ssid2
301 params['hessid'] = bssid2
302 params['access_network_type'] = "1"
303 del params['venue_group']
304 del params['venue_type']
305 hostapd.add_ap(apdev[1]['ifname'], params)
306
307 dev[0].hs20_enable()
308
309 wt = Wlantest()
310 wt.flush()
311
312 logger.info("Check probe request filtering based on HESSID")
313
314 dev[0].request("SET hessid " + bssid2)
315 dev[0].scan(freq="2412")
316 time.sleep(0.03)
317 check_probe_resp(wt, bssid, bssid2)
318
319 logger.info("Check probe request filtering based on access network type")
320
321 wt.clear_bss_counters(bssid)
322 wt.clear_bss_counters(bssid2)
323 dev[0].request("SET hessid 00:00:00:00:00:00")
324 dev[0].request("SET access_network_type 14")
325 dev[0].scan(freq="2412")
326 time.sleep(0.03)
327 check_probe_resp(wt, bssid2, bssid)
328
329 wt.clear_bss_counters(bssid)
330 wt.clear_bss_counters(bssid2)
331 dev[0].request("SET hessid 00:00:00:00:00:00")
332 dev[0].request("SET access_network_type 1")
333 dev[0].scan(freq="2412")
334 time.sleep(0.03)
335 check_probe_resp(wt, bssid, bssid2)
336
337 logger.info("Check probe request filtering based on HESSID and ANT")
338
339 wt.clear_bss_counters(bssid)
340 wt.clear_bss_counters(bssid2)
341 dev[0].request("SET hessid " + bssid)
342 dev[0].request("SET access_network_type 14")
343 dev[0].scan(freq="2412")
344 time.sleep(0.03)
345 check_probe_resp(wt, bssid2, bssid)
346
347 wt.clear_bss_counters(bssid)
348 wt.clear_bss_counters(bssid2)
349 dev[0].request("SET hessid " + bssid2)
350 dev[0].request("SET access_network_type 14")
351 dev[0].scan(freq="2412")
352 time.sleep(0.03)
353 check_probe_resp(wt, bssid, None)
354 check_probe_resp(wt, bssid2, None)
355
356 wt.clear_bss_counters(bssid)
357 wt.clear_bss_counters(bssid2)
358 dev[0].request("SET hessid " + bssid)
359 dev[0].request("SET access_network_type 1")
360 dev[0].scan(freq="2412")
361 time.sleep(0.03)
362 check_probe_resp(wt, bssid, None)
363 check_probe_resp(wt, bssid2, None)
364
365 def test_ap_hs20_select(dev, apdev):
366 """Hotspot 2.0 network selection"""
367 bssid = apdev[0]['bssid']
368 params = hs20_ap_params()
369 params['hessid'] = bssid
370 hostapd.add_ap(apdev[0]['ifname'], params)
371
372 dev[0].hs20_enable()
373 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
374 'password': "secret",
375 'domain': "example.com" })
376 interworking_select(dev[0], bssid, "home")
377
378 dev[0].remove_cred(id)
379 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
380 'password': "secret",
381 'domain': "no.match.example.com" })
382 interworking_select(dev[0], bssid, "roaming", freq="2412")
383
384 dev[0].set_cred_quoted(id, "realm", "no.match.example.com");
385 interworking_select(dev[0], bssid, no_match=True, freq="2412")
386
387 res = dev[0].request("SCAN_RESULTS")
388 if "[HS20]" not in res:
389 raise Exception("HS20 flag missing from scan results: " + res)
390
391 bssid2 = apdev[1]['bssid']
392 params = hs20_ap_params()
393 params['nai_realm'] = [ "0,example.org,21" ]
394 params['hessid'] = bssid2
395 params['domain_name'] = "example.org"
396 hostapd.add_ap(apdev[1]['ifname'], params)
397 dev[0].remove_cred(id)
398 id = dev[0].add_cred_values({ 'realm': "example.org", 'username': "test",
399 'password': "secret",
400 'domain': "example.org" })
401 interworking_select(dev[0], bssid2, "home", freq="2412")
402
403 def hs20_simulated_sim(dev, ap, method):
404 bssid = ap['bssid']
405 params = hs20_ap_params()
406 params['hessid'] = bssid
407 params['anqp_3gpp_cell_net'] = "555,444"
408 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
409 hostapd.add_ap(ap['ifname'], params)
410
411 dev.hs20_enable()
412 dev.add_cred_values({ 'imsi': "555444-333222111", 'eap': method,
413 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
414 interworking_select(dev, "home", freq="2412")
415 interworking_connect(dev, bssid, method)
416 check_sp_type(dev, "home")
417
418 def test_ap_hs20_sim(dev, apdev):
419 """Hotspot 2.0 with simulated SIM and EAP-SIM"""
420 if not hlr_auc_gw_available():
421 return "skip"
422 hs20_simulated_sim(dev[0], apdev[0], "SIM")
423 dev[0].request("INTERWORKING_SELECT auto freq=2412")
424 ev = dev[0].wait_event(["INTERWORKING-ALREADY-CONNECTED"], timeout=15)
425 if ev is None:
426 raise Exception("Timeout on already-connected event")
427
428 def test_ap_hs20_aka(dev, apdev):
429 """Hotspot 2.0 with simulated USIM and EAP-AKA"""
430 if not hlr_auc_gw_available():
431 return "skip"
432 hs20_simulated_sim(dev[0], apdev[0], "AKA")
433
434 def test_ap_hs20_aka_prime(dev, apdev):
435 """Hotspot 2.0 with simulated USIM and EAP-AKA'"""
436 if not hlr_auc_gw_available():
437 return "skip"
438 hs20_simulated_sim(dev[0], apdev[0], "AKA'")
439
440 def test_ap_hs20_ext_sim(dev, apdev):
441 """Hotspot 2.0 with external SIM processing"""
442 if not hlr_auc_gw_available():
443 return "skip"
444 bssid = apdev[0]['bssid']
445 params = hs20_ap_params()
446 params['hessid'] = bssid
447 params['anqp_3gpp_cell_net'] = "232,01"
448 params['domain_name'] = "wlan.mnc001.mcc232.3gppnetwork.org"
449 hostapd.add_ap(apdev[0]['ifname'], params)
450
451 dev[0].hs20_enable()
452 try:
453 dev[0].request("SET external_sim 1")
454 dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
455 interworking_select(dev[0], "home", freq="2412")
456 interworking_ext_sim_connect(dev[0], bssid, "SIM")
457 check_sp_type(dev[0], "home")
458 finally:
459 dev[0].request("SET external_sim 0")
460
461 def test_ap_hs20_ext_sim_roaming(dev, apdev):
462 """Hotspot 2.0 with external SIM processing in roaming network"""
463 if not hlr_auc_gw_available():
464 return "skip"
465 bssid = apdev[0]['bssid']
466 params = hs20_ap_params()
467 params['hessid'] = bssid
468 params['anqp_3gpp_cell_net'] = "244,91;310,026;232,01;234,56"
469 params['domain_name'] = "wlan.mnc091.mcc244.3gppnetwork.org"
470 hostapd.add_ap(apdev[0]['ifname'], params)
471
472 dev[0].hs20_enable()
473 try:
474 dev[0].request("SET external_sim 1")
475 dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
476 interworking_select(dev[0], "roaming", freq="2412")
477 interworking_ext_sim_connect(dev[0], bssid, "SIM")
478 check_sp_type(dev[0], "roaming")
479 finally:
480 dev[0].request("SET external_sim 0")
481
482 def test_ap_hs20_username(dev, apdev):
483 """Hotspot 2.0 connection in username/password credential"""
484 bssid = apdev[0]['bssid']
485 params = hs20_ap_params()
486 params['hessid'] = bssid
487 params['disable_dgaf'] = '1'
488 hostapd.add_ap(apdev[0]['ifname'], params)
489
490 dev[0].hs20_enable()
491 id = dev[0].add_cred_values({ 'realm': "example.com",
492 'username': "hs20-test",
493 'password': "password",
494 'ca_cert': "auth_serv/ca.pem",
495 'domain': "example.com",
496 'update_identifier': "1234" })
497 interworking_select(dev[0], bssid, "home", freq="2412")
498 interworking_connect(dev[0], bssid, "TTLS")
499 check_sp_type(dev[0], "home")
500 status = dev[0].get_status()
501 if status['pairwise_cipher'] != "CCMP":
502 raise Exception("Unexpected pairwise cipher")
503 if status['hs20'] != "2":
504 raise Exception("Unexpected HS 2.0 support indication")
505
506 dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
507 identity="hs20-test", password="password",
508 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
509 scan_freq="2412")
510
511 def test_ap_hs20_connect_api(dev, apdev):
512 """Hotspot 2.0 connection with connect API"""
513 bssid = apdev[0]['bssid']
514 params = hs20_ap_params()
515 params['hessid'] = bssid
516 params['disable_dgaf'] = '1'
517 hostapd.add_ap(apdev[0]['ifname'], params)
518
519 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
520 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
521 wpas.hs20_enable()
522 wpas.flush_scan_cache()
523 id = wpas.add_cred_values({ 'realm': "example.com",
524 'username': "hs20-test",
525 'password': "password",
526 'ca_cert': "auth_serv/ca.pem",
527 'domain': "example.com",
528 'update_identifier': "1234" })
529 interworking_select(wpas, bssid, "home", freq="2412")
530 interworking_connect(wpas, bssid, "TTLS")
531 check_sp_type(wpas, "home")
532 status = wpas.get_status()
533 if status['pairwise_cipher'] != "CCMP":
534 raise Exception("Unexpected pairwise cipher")
535 if status['hs20'] != "2":
536 raise Exception("Unexpected HS 2.0 support indication")
537
538 def test_ap_hs20_auto_interworking(dev, apdev):
539 """Hotspot 2.0 connection with auto_interworking=1"""
540 bssid = apdev[0]['bssid']
541 params = hs20_ap_params()
542 params['hessid'] = bssid
543 params['disable_dgaf'] = '1'
544 hostapd.add_ap(apdev[0]['ifname'], params)
545
546 dev[0].hs20_enable(auto_interworking=True)
547 id = dev[0].add_cred_values({ 'realm': "example.com",
548 'username': "hs20-test",
549 'password': "password",
550 'ca_cert': "auth_serv/ca.pem",
551 'domain': "example.com",
552 'update_identifier': "1234" })
553 dev[0].request("REASSOCIATE")
554 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
555 if ev is None:
556 raise Exception("Connection timed out")
557 check_sp_type(dev[0], "home")
558 status = dev[0].get_status()
559 if status['pairwise_cipher'] != "CCMP":
560 raise Exception("Unexpected pairwise cipher")
561 if status['hs20'] != "2":
562 raise Exception("Unexpected HS 2.0 support indication")
563
564 def test_ap_hs20_auto_interworking_no_cred_match(dev, apdev):
565 """Hotspot 2.0 connection with auto_interworking=1 but no cred match"""
566 bssid = apdev[0]['bssid']
567 params = { "ssid": "test" }
568 hostapd.add_ap(apdev[0]['ifname'], params)
569
570 dev[0].hs20_enable(auto_interworking=True)
571 dev[0].add_cred_values({ 'realm': "example.com",
572 'username': "hs20-test",
573 'password': "password",
574 'ca_cert': "auth_serv/ca.pem",
575 'domain': "example.com" })
576
577 id = dev[0].connect("test", psk="12345678", only_add_network=True)
578 dev[0].request("ENABLE_NETWORK %s" % id)
579 logger.info("Verify that scanning continues when there is partial network block match")
580 for i in range(0, 2):
581 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
582 if ev is None:
583 raise Exception("Scan timed out")
584 logger.info("Scan completed")
585
586 def eap_test(dev, ap, eap_params, method, user):
587 bssid = ap['bssid']
588 params = hs20_ap_params()
589 params['nai_realm'] = [ "0,example.com," + eap_params ]
590 hostapd.add_ap(ap['ifname'], params)
591
592 dev.hs20_enable()
593 dev.add_cred_values({ 'realm': "example.com",
594 'username': user,
595 'password': "password" })
596 interworking_select(dev, bssid, freq="2412")
597 interworking_connect(dev, bssid, method)
598
599 def test_ap_hs20_eap_unknown(dev, apdev):
600 """Hotspot 2.0 connection with unknown EAP method"""
601 bssid = apdev[0]['bssid']
602 params = hs20_ap_params()
603 params['nai_realm'] = "0,example.com,99"
604 hostapd.add_ap(apdev[0]['ifname'], params)
605
606 dev[0].hs20_enable()
607 dev[0].add_cred_values(default_cred())
608 interworking_select(dev[0], None, no_match=True, freq="2412")
609
610 def test_ap_hs20_eap_peap_mschapv2(dev, apdev):
611 """Hotspot 2.0 connection with PEAP/MSCHAPV2"""
612 eap_test(dev[0], apdev[0], "25[3:26]", "PEAP", "user")
613
614 def test_ap_hs20_eap_peap_default(dev, apdev):
615 """Hotspot 2.0 connection with PEAP/MSCHAPV2 (as default)"""
616 eap_test(dev[0], apdev[0], "25", "PEAP", "user")
617
618 def test_ap_hs20_eap_peap_gtc(dev, apdev):
619 """Hotspot 2.0 connection with PEAP/GTC"""
620 eap_test(dev[0], apdev[0], "25[3:6]", "PEAP", "user")
621
622 def test_ap_hs20_eap_peap_unknown(dev, apdev):
623 """Hotspot 2.0 connection with PEAP/unknown"""
624 bssid = apdev[0]['bssid']
625 params = hs20_ap_params()
626 params['nai_realm'] = "0,example.com,25[3:99]"
627 hostapd.add_ap(apdev[0]['ifname'], params)
628
629 dev[0].hs20_enable()
630 dev[0].add_cred_values(default_cred())
631 interworking_select(dev[0], None, no_match=True, freq="2412")
632
633 def test_ap_hs20_eap_ttls_chap(dev, apdev):
634 """Hotspot 2.0 connection with TTLS/CHAP"""
635 eap_test(dev[0], apdev[0], "21[2:2]", "TTLS", "chap user")
636
637 def test_ap_hs20_eap_ttls_mschap(dev, apdev):
638 """Hotspot 2.0 connection with TTLS/MSCHAP"""
639 eap_test(dev[0], apdev[0], "21[2:3]", "TTLS", "mschap user")
640
641 def test_ap_hs20_eap_ttls_eap_mschapv2(dev, apdev):
642 """Hotspot 2.0 connection with TTLS/EAP-MSCHAPv2"""
643 eap_test(dev[0], apdev[0], "21[3:26][6:7][99:99]", "TTLS", "user")
644
645 def test_ap_hs20_eap_ttls_eap_unknown(dev, apdev):
646 """Hotspot 2.0 connection with TTLS/EAP-unknown"""
647 bssid = apdev[0]['bssid']
648 params = hs20_ap_params()
649 params['nai_realm'] = "0,example.com,21[3:99]"
650 hostapd.add_ap(apdev[0]['ifname'], params)
651
652 dev[0].hs20_enable()
653 dev[0].add_cred_values(default_cred())
654 interworking_select(dev[0], None, no_match=True, freq="2412")
655
656 def test_ap_hs20_eap_ttls_eap_unsupported(dev, apdev):
657 """Hotspot 2.0 connection with TTLS/EAP-OTP(unsupported)"""
658 bssid = apdev[0]['bssid']
659 params = hs20_ap_params()
660 params['nai_realm'] = "0,example.com,21[3:5]"
661 hostapd.add_ap(apdev[0]['ifname'], params)
662
663 dev[0].hs20_enable()
664 dev[0].add_cred_values(default_cred())
665 interworking_select(dev[0], None, no_match=True, freq="2412")
666
667 def test_ap_hs20_eap_ttls_unknown(dev, apdev):
668 """Hotspot 2.0 connection with TTLS/unknown"""
669 bssid = apdev[0]['bssid']
670 params = hs20_ap_params()
671 params['nai_realm'] = "0,example.com,21[2:5]"
672 hostapd.add_ap(apdev[0]['ifname'], params)
673
674 dev[0].hs20_enable()
675 dev[0].add_cred_values(default_cred())
676 interworking_select(dev[0], None, no_match=True, freq="2412")
677
678 def test_ap_hs20_eap_fast_mschapv2(dev, apdev):
679 """Hotspot 2.0 connection with FAST/EAP-MSCHAPV2"""
680 eap_test(dev[0], apdev[0], "43[3:26]", "FAST", "user")
681
682 def test_ap_hs20_eap_fast_gtc(dev, apdev):
683 """Hotspot 2.0 connection with FAST/EAP-GTC"""
684 eap_test(dev[0], apdev[0], "43[3:6]", "FAST", "user")
685
686 def test_ap_hs20_eap_tls(dev, apdev):
687 """Hotspot 2.0 connection with EAP-TLS"""
688 bssid = apdev[0]['bssid']
689 params = hs20_ap_params()
690 params['nai_realm'] = [ "0,example.com,13[5:6]" ]
691 hostapd.add_ap(apdev[0]['ifname'], params)
692
693 dev[0].hs20_enable()
694 dev[0].add_cred_values({ 'realm': "example.com",
695 'username': "certificate-user",
696 'ca_cert': "auth_serv/ca.pem",
697 'client_cert': "auth_serv/user.pem",
698 'private_key': "auth_serv/user.key"})
699 interworking_select(dev[0], bssid, freq="2412")
700 interworking_connect(dev[0], bssid, "TLS")
701
702 def test_ap_hs20_eap_cert_unknown(dev, apdev):
703 """Hotspot 2.0 connection with certificate, but unknown EAP method"""
704 bssid = apdev[0]['bssid']
705 params = hs20_ap_params()
706 params['nai_realm'] = [ "0,example.com,99[5:6]" ]
707 hostapd.add_ap(apdev[0]['ifname'], params)
708
709 dev[0].hs20_enable()
710 dev[0].add_cred_values({ 'realm': "example.com",
711 'username': "certificate-user",
712 'ca_cert': "auth_serv/ca.pem",
713 'client_cert': "auth_serv/user.pem",
714 'private_key': "auth_serv/user.key"})
715 interworking_select(dev[0], None, no_match=True, freq="2412")
716
717 def test_ap_hs20_eap_cert_unsupported(dev, apdev):
718 """Hotspot 2.0 connection with certificate, but unsupported TTLS"""
719 bssid = apdev[0]['bssid']
720 params = hs20_ap_params()
721 params['nai_realm'] = [ "0,example.com,21[5:6]" ]
722 hostapd.add_ap(apdev[0]['ifname'], params)
723
724 dev[0].hs20_enable()
725 dev[0].add_cred_values({ 'realm': "example.com",
726 'username': "certificate-user",
727 'ca_cert': "auth_serv/ca.pem",
728 'client_cert': "auth_serv/user.pem",
729 'private_key': "auth_serv/user.key"})
730 interworking_select(dev[0], None, no_match=True, freq="2412")
731
732 def test_ap_hs20_eap_invalid_cred(dev, apdev):
733 """Hotspot 2.0 connection with invalid cred configuration"""
734 bssid = apdev[0]['bssid']
735 params = hs20_ap_params()
736 hostapd.add_ap(apdev[0]['ifname'], params)
737
738 dev[0].hs20_enable()
739 dev[0].add_cred_values({ 'realm': "example.com",
740 'username': "certificate-user",
741 'client_cert': "auth_serv/user.pem" })
742 interworking_select(dev[0], None, no_match=True, freq="2412")
743
744 def test_ap_hs20_nai_realms(dev, apdev):
745 """Hotspot 2.0 connection and multiple NAI realms and TTLS/PAP"""
746 bssid = apdev[0]['bssid']
747 params = hs20_ap_params()
748 params['hessid'] = bssid
749 params['nai_realm'] = [ "0,no.match.here;example.com;no.match.here.either,21[2:1][5:7]" ]
750 hostapd.add_ap(apdev[0]['ifname'], params)
751
752 dev[0].hs20_enable()
753 id = dev[0].add_cred_values({ 'realm': "example.com",
754 'username': "pap user",
755 'password': "password",
756 'domain': "example.com" })
757 interworking_select(dev[0], bssid, "home", freq="2412")
758 interworking_connect(dev[0], bssid, "TTLS")
759 check_sp_type(dev[0], "home")
760
761 def test_ap_hs20_roaming_consortium(dev, apdev):
762 """Hotspot 2.0 connection based on roaming consortium match"""
763 bssid = apdev[0]['bssid']
764 params = hs20_ap_params()
765 params['hessid'] = bssid
766 hostapd.add_ap(apdev[0]['ifname'], params)
767
768 dev[0].hs20_enable()
769 for consortium in [ "112233", "1020304050", "010203040506", "fedcba" ]:
770 id = dev[0].add_cred_values({ 'username': "user",
771 'password': "password",
772 'domain': "example.com",
773 'roaming_consortium': consortium,
774 'eap': "PEAP" })
775 interworking_select(dev[0], bssid, "home", freq="2412")
776 interworking_connect(dev[0], bssid, "PEAP")
777 check_sp_type(dev[0], "home")
778 dev[0].request("INTERWORKING_SELECT auto freq=2412")
779 ev = dev[0].wait_event(["INTERWORKING-ALREADY-CONNECTED"], timeout=15)
780 if ev is None:
781 raise Exception("Timeout on already-connected event")
782 dev[0].remove_cred(id)
783
784 def test_ap_hs20_username_roaming(dev, apdev):
785 """Hotspot 2.0 connection in username/password credential (roaming)"""
786 bssid = apdev[0]['bssid']
787 params = hs20_ap_params()
788 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
789 "0,roaming.example.com,21[2:4][5:7]",
790 "0,another.example.com" ]
791 params['domain_name'] = "another.example.com"
792 params['hessid'] = bssid
793 hostapd.add_ap(apdev[0]['ifname'], params)
794
795 dev[0].hs20_enable()
796 id = dev[0].add_cred_values({ 'realm': "roaming.example.com",
797 'username': "hs20-test",
798 'password': "password",
799 'domain': "example.com" })
800 interworking_select(dev[0], bssid, "roaming", freq="2412")
801 interworking_connect(dev[0], bssid, "TTLS")
802 check_sp_type(dev[0], "roaming")
803
804 def test_ap_hs20_username_unknown(dev, apdev):
805 """Hotspot 2.0 connection in username/password credential (no domain in cred)"""
806 bssid = apdev[0]['bssid']
807 params = hs20_ap_params()
808 params['hessid'] = bssid
809 hostapd.add_ap(apdev[0]['ifname'], params)
810
811 dev[0].hs20_enable()
812 id = dev[0].add_cred_values({ 'realm': "example.com",
813 'username': "hs20-test",
814 'password': "password" })
815 interworking_select(dev[0], bssid, "unknown", freq="2412")
816 interworking_connect(dev[0], bssid, "TTLS")
817 check_sp_type(dev[0], "unknown")
818
819 def test_ap_hs20_username_unknown2(dev, apdev):
820 """Hotspot 2.0 connection in username/password credential (no domain advertized)"""
821 bssid = apdev[0]['bssid']
822 params = hs20_ap_params()
823 params['hessid'] = bssid
824 del params['domain_name']
825 hostapd.add_ap(apdev[0]['ifname'], params)
826
827 dev[0].hs20_enable()
828 id = dev[0].add_cred_values({ 'realm': "example.com",
829 'username': "hs20-test",
830 'password': "password",
831 'domain': "example.com" })
832 interworking_select(dev[0], bssid, "unknown", freq="2412")
833 interworking_connect(dev[0], bssid, "TTLS")
834 check_sp_type(dev[0], "unknown")
835
836 def test_ap_hs20_gas_while_associated(dev, apdev):
837 """Hotspot 2.0 connection with GAS query while associated"""
838 bssid = apdev[0]['bssid']
839 params = hs20_ap_params()
840 params['hessid'] = bssid
841 hostapd.add_ap(apdev[0]['ifname'], params)
842
843 dev[0].hs20_enable()
844 id = dev[0].add_cred_values({ 'realm': "example.com",
845 'username': "hs20-test",
846 'password': "password",
847 'domain': "example.com" })
848 interworking_select(dev[0], bssid, "home", freq="2412")
849 interworking_connect(dev[0], bssid, "TTLS")
850
851 logger.info("Verifying GAS query while associated")
852 dev[0].request("FETCH_ANQP")
853 for i in range(0, 6):
854 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
855 if ev is None:
856 raise Exception("Operation timed out")
857
858 def test_ap_hs20_gas_while_associated_with_pmf(dev, apdev):
859 """Hotspot 2.0 connection with GAS query while associated and using PMF"""
860 try:
861 _test_ap_hs20_gas_while_associated_with_pmf(dev, apdev)
862 finally:
863 dev[0].request("SET pmf 0")
864
865 def _test_ap_hs20_gas_while_associated_with_pmf(dev, apdev):
866 bssid = apdev[0]['bssid']
867 params = hs20_ap_params()
868 params['hessid'] = bssid
869 hostapd.add_ap(apdev[0]['ifname'], params)
870
871 bssid2 = apdev[1]['bssid']
872 params = hs20_ap_params()
873 params['hessid'] = bssid2
874 params['nai_realm'] = [ "0,no-match.example.org,13[5:6],21[2:4][5:7]" ]
875 hostapd.add_ap(apdev[1]['ifname'], params)
876
877 dev[0].hs20_enable()
878 dev[0].request("SET pmf 2")
879 id = dev[0].add_cred_values({ 'realm': "example.com",
880 'username': "hs20-test",
881 'password': "password",
882 'domain': "example.com" })
883 interworking_select(dev[0], bssid, "home", freq="2412")
884 interworking_connect(dev[0], bssid, "TTLS")
885
886 logger.info("Verifying GAS query while associated")
887 dev[0].request("FETCH_ANQP")
888 for i in range(0, 2 * 6):
889 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
890 if ev is None:
891 raise Exception("Operation timed out")
892
893 def test_ap_hs20_gas_frag_while_associated(dev, apdev):
894 """Hotspot 2.0 connection with fragmented GAS query while associated"""
895 bssid = apdev[0]['bssid']
896 params = hs20_ap_params()
897 params['hessid'] = bssid
898 hostapd.add_ap(apdev[0]['ifname'], params)
899 hapd = hostapd.Hostapd(apdev[0]['ifname'])
900 hapd.set("gas_frag_limit", "50")
901
902 dev[0].hs20_enable()
903 id = dev[0].add_cred_values({ 'realm': "example.com",
904 'username': "hs20-test",
905 'password': "password",
906 'domain': "example.com" })
907 interworking_select(dev[0], bssid, "home", freq="2412")
908 interworking_connect(dev[0], bssid, "TTLS")
909
910 logger.info("Verifying GAS query while associated")
911 dev[0].request("FETCH_ANQP")
912 for i in range(0, 6):
913 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
914 if ev is None:
915 raise Exception("Operation timed out")
916
917 def test_ap_hs20_multiple_connects(dev, apdev):
918 """Hotspot 2.0 connection through multiple network selections"""
919 bssid = apdev[0]['bssid']
920 params = hs20_ap_params()
921 params['hessid'] = bssid
922 hostapd.add_ap(apdev[0]['ifname'], params)
923
924 dev[0].hs20_enable()
925 values = { 'realm': "example.com",
926 'username': "hs20-test",
927 'password': "password",
928 'domain': "example.com" }
929 id = dev[0].add_cred_values(values)
930
931 dev[0].scan_for_bss(bssid, freq="2412")
932
933 for i in range(0, 3):
934 logger.info("Starting Interworking network selection")
935 dev[0].request("INTERWORKING_SELECT auto freq=2412")
936 while True:
937 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH",
938 "INTERWORKING-ALREADY-CONNECTED",
939 "CTRL-EVENT-CONNECTED"], timeout=15)
940 if ev is None:
941 raise Exception("Connection timed out")
942 if "INTERWORKING-NO-MATCH" in ev:
943 raise Exception("Matching AP not found")
944 if "CTRL-EVENT-CONNECTED" in ev:
945 break
946 if i == 2 and "INTERWORKING-ALREADY-CONNECTED" in ev:
947 break
948 if i == 0:
949 dev[0].request("DISCONNECT")
950 dev[0].dump_monitor()
951
952 networks = dev[0].list_networks()
953 if len(networks) > 1:
954 raise Exception("Duplicated network block detected")
955
956 def test_ap_hs20_disallow_aps(dev, apdev):
957 """Hotspot 2.0 connection and disallow_aps"""
958 bssid = apdev[0]['bssid']
959 params = hs20_ap_params()
960 params['hessid'] = bssid
961 hostapd.add_ap(apdev[0]['ifname'], params)
962
963 dev[0].hs20_enable()
964 values = { 'realm': "example.com",
965 'username': "hs20-test",
966 'password': "password",
967 'domain': "example.com" }
968 id = dev[0].add_cred_values(values)
969
970 dev[0].scan_for_bss(bssid, freq="2412")
971
972 logger.info("Verify disallow_aps bssid")
973 dev[0].request("SET disallow_aps bssid " + bssid.translate(None, ':'))
974 dev[0].request("INTERWORKING_SELECT auto")
975 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15)
976 if ev is None:
977 raise Exception("Network selection timed out")
978 dev[0].dump_monitor()
979
980 logger.info("Verify disallow_aps ssid")
981 dev[0].request("SET disallow_aps ssid 746573742d68733230")
982 dev[0].request("INTERWORKING_SELECT auto freq=2412")
983 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15)
984 if ev is None:
985 raise Exception("Network selection timed out")
986 dev[0].dump_monitor()
987
988 logger.info("Verify disallow_aps clear")
989 dev[0].request("SET disallow_aps ")
990 interworking_select(dev[0], bssid, "home", freq="2412")
991
992 dev[0].request("SET disallow_aps bssid " + bssid.translate(None, ':'))
993 ret = dev[0].request("INTERWORKING_CONNECT " + bssid)
994 if "FAIL" not in ret:
995 raise Exception("INTERWORKING_CONNECT to disallowed BSS not rejected")
996
997 if "FAIL" not in dev[0].request("INTERWORKING_CONNECT foo"):
998 raise Exception("Invalid INTERWORKING_CONNECT not rejected")
999 if "FAIL" not in dev[0].request("INTERWORKING_CONNECT 00:11:22:33:44:55"):
1000 raise Exception("Invalid INTERWORKING_CONNECT not rejected")
1001
1002 def policy_test(dev, ap, values, only_one=True):
1003 dev.dump_monitor()
1004 if ap:
1005 logger.info("Verify network selection to AP " + ap['ifname'])
1006 bssid = ap['bssid']
1007 dev.scan_for_bss(bssid, freq="2412")
1008 else:
1009 logger.info("Verify network selection")
1010 bssid = None
1011 dev.hs20_enable()
1012 id = dev.add_cred_values(values)
1013 dev.request("INTERWORKING_SELECT auto freq=2412")
1014 events = []
1015 while True:
1016 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH",
1017 "INTERWORKING-BLACKLISTED",
1018 "INTERWORKING-SELECTED"], timeout=15)
1019 if ev is None:
1020 raise Exception("Network selection timed out")
1021 events.append(ev)
1022 if "INTERWORKING-NO-MATCH" in ev:
1023 raise Exception("Matching AP not found")
1024 if bssid and only_one and "INTERWORKING-AP" in ev and bssid not in ev:
1025 raise Exception("Unexpected AP claimed acceptable")
1026 if "INTERWORKING-SELECTED" in ev:
1027 if bssid and bssid not in ev:
1028 raise Exception("Selected incorrect BSS")
1029 break
1030
1031 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
1032 if ev is None:
1033 raise Exception("Connection timed out")
1034 if bssid and bssid not in ev:
1035 raise Exception("Connected to incorrect BSS")
1036
1037 conn_bssid = dev.get_status_field("bssid")
1038 if bssid and conn_bssid != bssid:
1039 raise Exception("bssid information points to incorrect BSS")
1040
1041 dev.remove_cred(id)
1042 dev.dump_monitor()
1043 return events
1044
1045 def default_cred(domain=None):
1046 cred = { 'realm': "example.com",
1047 'username': "hs20-test",
1048 'password': "password" }
1049 if domain:
1050 cred['domain'] = domain
1051 return cred
1052
1053 def test_ap_hs20_prefer_home(dev, apdev):
1054 """Hotspot 2.0 required roaming consortium"""
1055 params = hs20_ap_params()
1056 params['domain_name'] = "example.org"
1057 hostapd.add_ap(apdev[0]['ifname'], params)
1058
1059 params = hs20_ap_params()
1060 params['ssid'] = "test-hs20-other"
1061 params['domain_name'] = "example.com"
1062 hostapd.add_ap(apdev[1]['ifname'], params)
1063
1064 values = default_cred()
1065 values['domain'] = "example.com"
1066 policy_test(dev[0], apdev[1], values, only_one=False)
1067 values['domain'] = "example.org"
1068 policy_test(dev[0], apdev[0], values, only_one=False)
1069
1070 def test_ap_hs20_req_roaming_consortium(dev, apdev):
1071 """Hotspot 2.0 required roaming consortium"""
1072 params = hs20_ap_params()
1073 hostapd.add_ap(apdev[0]['ifname'], params)
1074
1075 params = hs20_ap_params()
1076 params['ssid'] = "test-hs20-other"
1077 params['roaming_consortium'] = [ "223344" ]
1078 hostapd.add_ap(apdev[1]['ifname'], params)
1079
1080 values = default_cred()
1081 values['required_roaming_consortium'] = "223344"
1082 policy_test(dev[0], apdev[1], values)
1083 values['required_roaming_consortium'] = "112233"
1084 policy_test(dev[0], apdev[0], values)
1085
1086 id = dev[0].add_cred()
1087 dev[0].set_cred(id, "required_roaming_consortium", "112233")
1088 dev[0].set_cred(id, "required_roaming_consortium", "112233445566778899aabbccddeeff")
1089
1090 for val in [ "", "1", "11", "1122", "1122334", "112233445566778899aabbccddeeff00" ]:
1091 if "FAIL" not in dev[0].request('SET_CRED {} required_roaming_consortium {}'.format(id, val)):
1092 raise Exception("Invalid roaming consortium value accepted: " + val)
1093
1094 def test_ap_hs20_excluded_ssid(dev, apdev):
1095 """Hotspot 2.0 exclusion based on SSID"""
1096 params = hs20_ap_params()
1097 params['roaming_consortium'] = [ "223344" ]
1098 params['anqp_3gpp_cell_net'] = "555,444"
1099 hostapd.add_ap(apdev[0]['ifname'], params)
1100
1101 params = hs20_ap_params()
1102 params['ssid'] = "test-hs20-other"
1103 params['roaming_consortium'] = [ "223344" ]
1104 params['anqp_3gpp_cell_net'] = "555,444"
1105 hostapd.add_ap(apdev[1]['ifname'], params)
1106
1107 values = default_cred()
1108 values['excluded_ssid'] = "test-hs20"
1109 events = policy_test(dev[0], apdev[1], values)
1110 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
1111 if len(ev) != 1:
1112 raise Exception("Excluded network not reported")
1113 values['excluded_ssid'] = "test-hs20-other"
1114 events = policy_test(dev[0], apdev[0], values)
1115 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[1]['bssid'] in e]
1116 if len(ev) != 1:
1117 raise Exception("Excluded network not reported")
1118
1119 values = default_cred()
1120 values['roaming_consortium'] = "223344"
1121 values['eap'] = "TTLS"
1122 values['phase2'] = "auth=MSCHAPV2"
1123 values['excluded_ssid'] = "test-hs20"
1124 events = policy_test(dev[0], apdev[1], values)
1125 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
1126 if len(ev) != 1:
1127 raise Exception("Excluded network not reported")
1128
1129 values = { 'imsi': "555444-333222111", 'eap': "SIM",
1130 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
1131 'excluded_ssid': "test-hs20" }
1132 events = policy_test(dev[0], apdev[1], values)
1133 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
1134 if len(ev) != 1:
1135 raise Exception("Excluded network not reported")
1136
1137 def test_ap_hs20_roam_to_higher_prio(dev, apdev):
1138 """Hotspot 2.0 and roaming from current to higher priority network"""
1139 bssid = apdev[0]['bssid']
1140 params = hs20_ap_params(ssid="test-hs20-visited")
1141 params['domain_name'] = "visited.example.org"
1142 hostapd.add_ap(apdev[0]['ifname'], params)
1143
1144 dev[0].hs20_enable()
1145 id = dev[0].add_cred_values({ 'realm': "example.com",
1146 'username': "hs20-test",
1147 'password': "password",
1148 'domain': "example.com" })
1149 logger.info("Connect to the only network option")
1150 interworking_select(dev[0], bssid, "roaming", freq="2412")
1151 dev[0].dump_monitor()
1152 interworking_connect(dev[0], bssid, "TTLS")
1153
1154 logger.info("Start another AP (home operator) and reconnect")
1155 bssid2 = apdev[1]['bssid']
1156 params = hs20_ap_params(ssid="test-hs20-home")
1157 params['domain_name'] = "example.com"
1158 hostapd.add_ap(apdev[1]['ifname'], params)
1159
1160 dev[0].scan_for_bss(bssid2, freq="2412", force_scan=True)
1161 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1162 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH",
1163 "INTERWORKING-ALREADY-CONNECTED",
1164 "CTRL-EVENT-CONNECTED"], timeout=15)
1165 if ev is None:
1166 raise Exception("Connection timed out")
1167 if "INTERWORKING-NO-MATCH" in ev:
1168 raise Exception("Matching AP not found")
1169 if "INTERWORKING-ALREADY-CONNECTED" in ev:
1170 raise Exception("Unexpected AP selected")
1171 if bssid2 not in ev:
1172 raise Exception("Unexpected BSSID after reconnection")
1173
1174 def test_ap_hs20_domain_suffix_match(dev, apdev):
1175 """Hotspot 2.0 and domain_suffix_match"""
1176 bssid = apdev[0]['bssid']
1177 params = hs20_ap_params()
1178 hostapd.add_ap(apdev[0]['ifname'], params)
1179
1180 dev[0].hs20_enable()
1181 id = dev[0].add_cred_values({ 'realm': "example.com",
1182 'username': "hs20-test",
1183 'password': "password",
1184 'domain': "example.com",
1185 'domain_suffix_match': "w1.fi" })
1186 interworking_select(dev[0], bssid, "home", freq="2412")
1187 dev[0].dump_monitor()
1188 interworking_connect(dev[0], bssid, "TTLS")
1189 dev[0].request("REMOVE_NETWORK all")
1190 dev[0].dump_monitor()
1191
1192 dev[0].set_cred_quoted(id, "domain_suffix_match", "no-match.example.com")
1193 interworking_select(dev[0], bssid, "home", freq="2412")
1194 dev[0].dump_monitor()
1195 dev[0].request("INTERWORKING_CONNECT " + bssid)
1196 ev = dev[0].wait_event(["CTRL-EVENT-EAP-TLS-CERT-ERROR"])
1197 if ev is None:
1198 raise Exception("TLS certificate error not reported")
1199 if "Domain suffix mismatch" not in ev:
1200 raise Exception("Domain suffix mismatch not reported")
1201
1202 def test_ap_hs20_roaming_partner_preference(dev, apdev):
1203 """Hotspot 2.0 and roaming partner preference"""
1204 params = hs20_ap_params()
1205 params['domain_name'] = "roaming.example.org"
1206 hostapd.add_ap(apdev[0]['ifname'], params)
1207
1208 params = hs20_ap_params()
1209 params['ssid'] = "test-hs20-other"
1210 params['domain_name'] = "roaming.example.net"
1211 hostapd.add_ap(apdev[1]['ifname'], params)
1212
1213 logger.info("Verify default vs. specified preference")
1214 values = default_cred()
1215 values['roaming_partner'] = "roaming.example.net,1,127,*"
1216 policy_test(dev[0], apdev[1], values, only_one=False)
1217 values['roaming_partner'] = "roaming.example.net,1,129,*"
1218 policy_test(dev[0], apdev[0], values, only_one=False)
1219
1220 logger.info("Verify partial FQDN match")
1221 values['roaming_partner'] = "example.net,0,0,*"
1222 policy_test(dev[0], apdev[1], values, only_one=False)
1223 values['roaming_partner'] = "example.net,0,255,*"
1224 policy_test(dev[0], apdev[0], values, only_one=False)
1225
1226 def test_ap_hs20_max_bss_load(dev, apdev):
1227 """Hotspot 2.0 and maximum BSS load"""
1228 params = hs20_ap_params()
1229 params['bss_load_test'] = "12:200:20000"
1230 hostapd.add_ap(apdev[0]['ifname'], params)
1231
1232 params = hs20_ap_params()
1233 params['ssid'] = "test-hs20-other"
1234 params['bss_load_test'] = "5:20:10000"
1235 hostapd.add_ap(apdev[1]['ifname'], params)
1236
1237 logger.info("Verify maximum BSS load constraint")
1238 values = default_cred()
1239 values['domain'] = "example.com"
1240 values['max_bss_load'] = "100"
1241 events = policy_test(dev[0], apdev[1], values, only_one=False)
1242
1243 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1244 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1245 raise Exception("Maximum BSS Load case not noticed")
1246 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1247 if len(ev) != 1 or "over_max_bss_load=1" in ev[0]:
1248 raise Exception("Maximum BSS Load case reported incorrectly")
1249
1250 logger.info("Verify maximum BSS load does not prevent connection")
1251 values['max_bss_load'] = "1"
1252 events = policy_test(dev[0], None, values)
1253
1254 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1255 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1256 raise Exception("Maximum BSS Load case not noticed")
1257 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1258 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1259 raise Exception("Maximum BSS Load case not noticed")
1260
1261 def test_ap_hs20_max_bss_load2(dev, apdev):
1262 """Hotspot 2.0 and maximum BSS load with one AP not advertising"""
1263 params = hs20_ap_params()
1264 params['bss_load_test'] = "12:200:20000"
1265 hostapd.add_ap(apdev[0]['ifname'], params)
1266
1267 params = hs20_ap_params()
1268 params['ssid'] = "test-hs20-other"
1269 hostapd.add_ap(apdev[1]['ifname'], params)
1270
1271 logger.info("Verify maximum BSS load constraint with AP advertisement")
1272 values = default_cred()
1273 values['domain'] = "example.com"
1274 values['max_bss_load'] = "100"
1275 events = policy_test(dev[0], apdev[1], values, only_one=False)
1276
1277 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1278 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1279 raise Exception("Maximum BSS Load case not noticed")
1280 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1281 if len(ev) != 1 or "over_max_bss_load=1" in ev[0]:
1282 raise Exception("Maximum BSS Load case reported incorrectly")
1283
1284 def test_ap_hs20_multi_cred_sp_prio(dev, apdev):
1285 """Hotspot 2.0 multi-cred sp_priority"""
1286 try:
1287 return _test_ap_hs20_multi_cred_sp_prio(dev, apdev)
1288 finally:
1289 dev[0].request("SET external_sim 0")
1290
1291 def _test_ap_hs20_multi_cred_sp_prio(dev, apdev):
1292 if not hlr_auc_gw_available():
1293 return "skip"
1294 bssid = apdev[0]['bssid']
1295 params = hs20_ap_params()
1296 params['hessid'] = bssid
1297 del params['domain_name']
1298 params['anqp_3gpp_cell_net'] = "232,01"
1299 hostapd.add_ap(apdev[0]['ifname'], params)
1300
1301 dev[0].hs20_enable()
1302 dev[0].scan_for_bss(bssid, freq="2412")
1303 dev[0].request("SET external_sim 1")
1304 id1 = dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM",
1305 'provisioning_sp': "example.com",
1306 'sp_priority' :"1" })
1307 id2 = dev[0].add_cred_values({ 'realm': "example.com",
1308 'username': "hs20-test",
1309 'password': "password",
1310 'domain': "example.com",
1311 'provisioning_sp': "example.com",
1312 'sp_priority': "2" })
1313 dev[0].dump_monitor()
1314 dev[0].scan_for_bss(bssid, freq="2412")
1315 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1316 interworking_ext_sim_auth(dev[0], "SIM")
1317 check_sp_type(dev[0], "unknown")
1318 dev[0].request("REMOVE_NETWORK all")
1319
1320 dev[0].set_cred(id1, "sp_priority", "2")
1321 dev[0].set_cred(id2, "sp_priority", "1")
1322 dev[0].dump_monitor()
1323 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1324 interworking_auth(dev[0], "TTLS")
1325 check_sp_type(dev[0], "unknown")
1326
1327 def test_ap_hs20_multi_cred_sp_prio2(dev, apdev):
1328 """Hotspot 2.0 multi-cred sp_priority with two BSSes"""
1329 try:
1330 return _test_ap_hs20_multi_cred_sp_prio2(dev, apdev)
1331 finally:
1332 dev[0].request("SET external_sim 0")
1333
1334 def _test_ap_hs20_multi_cred_sp_prio2(dev, apdev):
1335 if not hlr_auc_gw_available():
1336 return "skip"
1337 bssid = apdev[0]['bssid']
1338 params = hs20_ap_params()
1339 params['hessid'] = bssid
1340 del params['nai_realm']
1341 del params['domain_name']
1342 params['anqp_3gpp_cell_net'] = "232,01"
1343 hostapd.add_ap(apdev[0]['ifname'], params)
1344
1345 bssid2 = apdev[1]['bssid']
1346 params = hs20_ap_params()
1347 params['ssid'] = "test-hs20-other"
1348 params['hessid'] = bssid2
1349 del params['domain_name']
1350 del params['anqp_3gpp_cell_net']
1351 hostapd.add_ap(apdev[1]['ifname'], params)
1352
1353 dev[0].hs20_enable()
1354 dev[0].request("SET external_sim 1")
1355 id1 = dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM",
1356 'provisioning_sp': "example.com",
1357 'sp_priority': "1" })
1358 id2 = dev[0].add_cred_values({ 'realm': "example.com",
1359 'username': "hs20-test",
1360 'password': "password",
1361 'domain': "example.com",
1362 'provisioning_sp': "example.com",
1363 'sp_priority': "2" })
1364 dev[0].dump_monitor()
1365 dev[0].scan_for_bss(bssid, freq="2412")
1366 dev[0].scan_for_bss(bssid2, freq="2412")
1367 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1368 interworking_ext_sim_auth(dev[0], "SIM")
1369 check_sp_type(dev[0], "unknown")
1370 conn_bssid = dev[0].get_status_field("bssid")
1371 if conn_bssid != bssid:
1372 raise Exception("Connected to incorrect BSS")
1373 dev[0].request("REMOVE_NETWORK all")
1374
1375 dev[0].set_cred(id1, "sp_priority", "2")
1376 dev[0].set_cred(id2, "sp_priority", "1")
1377 dev[0].dump_monitor()
1378 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1379 interworking_auth(dev[0], "TTLS")
1380 check_sp_type(dev[0], "unknown")
1381 conn_bssid = dev[0].get_status_field("bssid")
1382 if conn_bssid != bssid2:
1383 raise Exception("Connected to incorrect BSS")
1384
1385 def check_conn_capab_selection(dev, type, missing):
1386 dev.request("INTERWORKING_SELECT freq=2412")
1387 ev = dev.wait_event(["INTERWORKING-AP"])
1388 if ev is None:
1389 raise Exception("Network selection timed out");
1390 if "type=" + type not in ev:
1391 raise Exception("Unexpected network type")
1392 if missing and "conn_capab_missing=1" not in ev:
1393 raise Exception("conn_capab_missing not reported")
1394 if not missing and "conn_capab_missing=1" in ev:
1395 raise Exception("conn_capab_missing reported unexpectedly")
1396
1397 def conn_capab_cred(domain=None, req_conn_capab=None):
1398 cred = default_cred(domain=domain)
1399 if req_conn_capab:
1400 cred['req_conn_capab'] = req_conn_capab
1401 return cred
1402
1403 def test_ap_hs20_req_conn_capab(dev, apdev):
1404 """Hotspot 2.0 network selection with req_conn_capab"""
1405 bssid = apdev[0]['bssid']
1406 params = hs20_ap_params()
1407 hostapd.add_ap(apdev[0]['ifname'], params)
1408
1409 dev[0].hs20_enable()
1410 dev[0].scan_for_bss(bssid, freq="2412")
1411 logger.info("Not used in home network")
1412 values = conn_capab_cred(domain="example.com", req_conn_capab="6:1234")
1413 id = dev[0].add_cred_values(values)
1414 check_conn_capab_selection(dev[0], "home", False)
1415
1416 logger.info("Used in roaming network")
1417 dev[0].remove_cred(id)
1418 values = conn_capab_cred(domain="example.org", req_conn_capab="6:1234")
1419 id = dev[0].add_cred_values(values)
1420 check_conn_capab_selection(dev[0], "roaming", True)
1421
1422 logger.info("Verify that req_conn_capab does not prevent connection if no other network is available")
1423 check_auto_select(dev[0], bssid)
1424
1425 logger.info("Additional req_conn_capab checks")
1426
1427 dev[0].remove_cred(id)
1428 values = conn_capab_cred(domain="example.org", req_conn_capab="1:0")
1429 id = dev[0].add_cred_values(values)
1430 check_conn_capab_selection(dev[0], "roaming", True)
1431
1432 dev[0].remove_cred(id)
1433 values = conn_capab_cred(domain="example.org", req_conn_capab="17:5060")
1434 id = dev[0].add_cred_values(values)
1435 check_conn_capab_selection(dev[0], "roaming", True)
1436
1437 bssid2 = apdev[1]['bssid']
1438 params = hs20_ap_params(ssid="test-hs20b")
1439 params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0", "50:0:1" ]
1440 hostapd.add_ap(apdev[1]['ifname'], params)
1441
1442 dev[0].remove_cred(id)
1443 values = conn_capab_cred(domain="example.org", req_conn_capab="50")
1444 id = dev[0].add_cred_values(values)
1445 dev[0].set_cred(id, "req_conn_capab", "6:22")
1446 dev[0].scan_for_bss(bssid2, freq="2412")
1447 dev[0].request("INTERWORKING_SELECT freq=2412")
1448 for i in range(0, 2):
1449 ev = dev[0].wait_event(["INTERWORKING-AP"])
1450 if ev is None:
1451 raise Exception("Network selection timed out");
1452 if bssid in ev and "conn_capab_missing=1" not in ev:
1453 raise Exception("Missing protocol connection capability not reported")
1454 if bssid2 in ev and "conn_capab_missing=1" in ev:
1455 raise Exception("Protocol connection capability not reported correctly")
1456
1457 def test_ap_hs20_req_conn_capab_and_roaming_partner_preference(dev, apdev):
1458 """Hotspot 2.0 and req_conn_capab with roaming partner preference"""
1459 bssid = apdev[0]['bssid']
1460 params = hs20_ap_params()
1461 params['domain_name'] = "roaming.example.org"
1462 params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0", "50:0:1" ]
1463 hostapd.add_ap(apdev[0]['ifname'], params)
1464
1465 bssid2 = apdev[1]['bssid']
1466 params = hs20_ap_params(ssid="test-hs20-b")
1467 params['domain_name'] = "roaming.example.net"
1468 hostapd.add_ap(apdev[1]['ifname'], params)
1469
1470 values = default_cred()
1471 values['roaming_partner'] = "roaming.example.net,1,127,*"
1472 id = dev[0].add_cred_values(values)
1473 check_auto_select(dev[0], bssid2)
1474
1475 dev[0].set_cred(id, "req_conn_capab", "50")
1476 check_auto_select(dev[0], bssid)
1477
1478 dev[0].remove_cred(id)
1479 id = dev[0].add_cred_values(values)
1480 dev[0].set_cred(id, "req_conn_capab", "51")
1481 check_auto_select(dev[0], bssid2)
1482
1483 def check_bandwidth_selection(dev, type, below):
1484 dev.request("INTERWORKING_SELECT freq=2412")
1485 ev = dev.wait_event(["INTERWORKING-AP"])
1486 if ev is None:
1487 raise Exception("Network selection timed out");
1488 if "type=" + type not in ev:
1489 raise Exception("Unexpected network type")
1490 if below and "below_min_backhaul=1" not in ev:
1491 raise Exception("below_min_backhaul not reported")
1492 if not below and "below_min_backhaul=1" in ev:
1493 raise Exception("below_min_backhaul reported unexpectedly")
1494
1495 def bw_cred(domain=None, dl_home=None, ul_home=None, dl_roaming=None, ul_roaming=None):
1496 cred = default_cred(domain=domain)
1497 if dl_home:
1498 cred['min_dl_bandwidth_home'] = str(dl_home)
1499 if ul_home:
1500 cred['min_ul_bandwidth_home'] = str(ul_home)
1501 if dl_roaming:
1502 cred['min_dl_bandwidth_roaming'] = str(dl_roaming)
1503 if ul_roaming:
1504 cred['min_ul_bandwidth_roaming'] = str(ul_roaming)
1505 return cred
1506
1507 def test_ap_hs20_min_bandwidth_home(dev, apdev):
1508 """Hotspot 2.0 network selection with min bandwidth (home)"""
1509 bssid = apdev[0]['bssid']
1510 params = hs20_ap_params()
1511 hostapd.add_ap(apdev[0]['ifname'], params)
1512
1513 dev[0].hs20_enable()
1514 dev[0].scan_for_bss(bssid, freq="2412")
1515 values = bw_cred(domain="example.com", dl_home=5490, ul_home=58)
1516 id = dev[0].add_cred_values(values)
1517 check_bandwidth_selection(dev[0], "home", False)
1518 dev[0].remove_cred(id)
1519
1520 values = bw_cred(domain="example.com", dl_home=5491, ul_home=58)
1521 id = dev[0].add_cred_values(values)
1522 check_bandwidth_selection(dev[0], "home", True)
1523 dev[0].remove_cred(id)
1524
1525 values = bw_cred(domain="example.com", dl_home=5490, ul_home=59)
1526 id = dev[0].add_cred_values(values)
1527 check_bandwidth_selection(dev[0], "home", True)
1528 dev[0].remove_cred(id)
1529
1530 values = bw_cred(domain="example.com", dl_home=5491, ul_home=59)
1531 id = dev[0].add_cred_values(values)
1532 check_bandwidth_selection(dev[0], "home", True)
1533 check_auto_select(dev[0], bssid)
1534
1535 bssid2 = apdev[1]['bssid']
1536 params = hs20_ap_params(ssid="test-hs20-b")
1537 params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
1538 hostapd.add_ap(apdev[1]['ifname'], params)
1539
1540 check_auto_select(dev[0], bssid2)
1541
1542 def test_ap_hs20_min_bandwidth_roaming(dev, apdev):
1543 """Hotspot 2.0 network selection with min bandwidth (roaming)"""
1544 bssid = apdev[0]['bssid']
1545 params = hs20_ap_params()
1546 hostapd.add_ap(apdev[0]['ifname'], params)
1547
1548 dev[0].hs20_enable()
1549 dev[0].scan_for_bss(bssid, freq="2412")
1550 values = bw_cred(domain="example.org", dl_roaming=5490, ul_roaming=58)
1551 id = dev[0].add_cred_values(values)
1552 check_bandwidth_selection(dev[0], "roaming", False)
1553 dev[0].remove_cred(id)
1554
1555 values = bw_cred(domain="example.org", dl_roaming=5491, ul_roaming=58)
1556 id = dev[0].add_cred_values(values)
1557 check_bandwidth_selection(dev[0], "roaming", True)
1558 dev[0].remove_cred(id)
1559
1560 values = bw_cred(domain="example.org", dl_roaming=5490, ul_roaming=59)
1561 id = dev[0].add_cred_values(values)
1562 check_bandwidth_selection(dev[0], "roaming", True)
1563 dev[0].remove_cred(id)
1564
1565 values = bw_cred(domain="example.org", dl_roaming=5491, ul_roaming=59)
1566 id = dev[0].add_cred_values(values)
1567 check_bandwidth_selection(dev[0], "roaming", True)
1568 check_auto_select(dev[0], bssid)
1569
1570 bssid2 = apdev[1]['bssid']
1571 params = hs20_ap_params(ssid="test-hs20-b")
1572 params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
1573 hostapd.add_ap(apdev[1]['ifname'], params)
1574
1575 check_auto_select(dev[0], bssid2)
1576
1577 def test_ap_hs20_min_bandwidth_and_roaming_partner_preference(dev, apdev):
1578 """Hotspot 2.0 and minimum bandwidth with roaming partner preference"""
1579 bssid = apdev[0]['bssid']
1580 params = hs20_ap_params()
1581 params['domain_name'] = "roaming.example.org"
1582 params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
1583 hostapd.add_ap(apdev[0]['ifname'], params)
1584
1585 bssid2 = apdev[1]['bssid']
1586 params = hs20_ap_params(ssid="test-hs20-b")
1587 params['domain_name'] = "roaming.example.net"
1588 hostapd.add_ap(apdev[1]['ifname'], params)
1589
1590 values = default_cred()
1591 values['roaming_partner'] = "roaming.example.net,1,127,*"
1592 id = dev[0].add_cred_values(values)
1593 check_auto_select(dev[0], bssid2)
1594
1595 dev[0].set_cred(id, "min_dl_bandwidth_roaming", "6000")
1596 check_auto_select(dev[0], bssid)
1597
1598 dev[0].set_cred(id, "min_dl_bandwidth_roaming", "10000")
1599 check_auto_select(dev[0], bssid2)
1600
1601 def test_ap_hs20_min_bandwidth_no_wan_metrics(dev, apdev):
1602 """Hotspot 2.0 network selection with min bandwidth but no WAN Metrics"""
1603 bssid = apdev[0]['bssid']
1604 params = hs20_ap_params()
1605 del params['hs20_wan_metrics']
1606 hostapd.add_ap(apdev[0]['ifname'], params)
1607
1608 dev[0].hs20_enable()
1609 dev[0].scan_for_bss(bssid, freq="2412")
1610 values = bw_cred(domain="example.com", dl_home=10000, ul_home=10000,
1611 dl_roaming=10000, ul_roaming=10000)
1612 dev[0].add_cred_values(values)
1613 check_bandwidth_selection(dev[0], "home", False)
1614
1615 def test_ap_hs20_deauth_req_ess(dev, apdev):
1616 """Hotspot 2.0 connection and deauthentication request for ESS"""
1617 try:
1618 _test_ap_hs20_deauth_req_ess(dev, apdev)
1619 finally:
1620 dev[0].request("SET pmf 0")
1621
1622 def _test_ap_hs20_deauth_req_ess(dev, apdev):
1623 dev[0].request("SET pmf 2")
1624 eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user")
1625 dev[0].dump_monitor()
1626 addr = dev[0].p2p_interface_addr()
1627 hapd = hostapd.Hostapd(apdev[0]['ifname'])
1628 hapd.request("HS20_DEAUTH_REQ " + addr + " 1 120 http://example.com/")
1629 ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"])
1630 if ev is None:
1631 raise Exception("Timeout on deauth imminent notice")
1632 if "1 120 http://example.com/" not in ev:
1633 raise Exception("Unexpected deauth imminent notice: " + ev)
1634 hapd.request("DEAUTHENTICATE " + addr)
1635 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
1636 if ev is None:
1637 raise Exception("Timeout on disconnection")
1638 if "[TEMP-DISABLED]" not in dev[0].list_networks()[0]['flags']:
1639 raise Exception("Network not marked temporarily disabled")
1640 ev = dev[0].wait_event(["SME: Trying to authenticate",
1641 "Trying to associate",
1642 "CTRL-EVENT-CONNECTED"], timeout=5)
1643 if ev is not None:
1644 raise Exception("Unexpected connection attempt")
1645
1646 def test_ap_hs20_deauth_req_bss(dev, apdev):
1647 """Hotspot 2.0 connection and deauthentication request for BSS"""
1648 try:
1649 _test_ap_hs20_deauth_req_bss(dev, apdev)
1650 finally:
1651 dev[0].request("SET pmf 0")
1652
1653 def _test_ap_hs20_deauth_req_bss(dev, apdev):
1654 dev[0].request("SET pmf 2")
1655 eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user")
1656 dev[0].dump_monitor()
1657 addr = dev[0].p2p_interface_addr()
1658 hapd = hostapd.Hostapd(apdev[0]['ifname'])
1659 hapd.request("HS20_DEAUTH_REQ " + addr + " 0 120 http://example.com/")
1660 ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"])
1661 if ev is None:
1662 raise Exception("Timeout on deauth imminent notice")
1663 if "0 120 http://example.com/" not in ev:
1664 raise Exception("Unexpected deauth imminent notice: " + ev)
1665 hapd.request("DEAUTHENTICATE " + addr + " reason=4")
1666 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
1667 if ev is None:
1668 raise Exception("Timeout on disconnection")
1669 if "reason=4" not in ev:
1670 raise Exception("Unexpected disconnection reason")
1671 if "[TEMP-DISABLED]" not in dev[0].list_networks()[0]['flags']:
1672 raise Exception("Network not marked temporarily disabled")
1673 ev = dev[0].wait_event(["SME: Trying to authenticate",
1674 "Trying to associate",
1675 "CTRL-EVENT-CONNECTED"], timeout=5)
1676 if ev is not None:
1677 raise Exception("Unexpected connection attempt")
1678
1679 def test_ap_hs20_deauth_req_from_radius(dev, apdev):
1680 """Hotspot 2.0 connection and deauthentication request from RADIUS"""
1681 try:
1682 _test_ap_hs20_deauth_req_from_radius(dev, apdev)
1683 finally:
1684 dev[0].request("SET pmf 0")
1685
1686 def _test_ap_hs20_deauth_req_from_radius(dev, apdev):
1687 bssid = apdev[0]['bssid']
1688 params = hs20_ap_params()
1689 params['nai_realm'] = [ "0,example.com,21[2:4]" ]
1690 params['hs20_deauth_req_timeout'] = "2"
1691 hostapd.add_ap(apdev[0]['ifname'], params)
1692
1693 dev[0].request("SET pmf 2")
1694 dev[0].hs20_enable()
1695 dev[0].add_cred_values({ 'realm': "example.com",
1696 'username': "hs20-deauth-test",
1697 'password': "password" })
1698 interworking_select(dev[0], bssid, freq="2412")
1699 interworking_connect(dev[0], bssid, "TTLS")
1700 ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"], timeout=5)
1701 if ev is None:
1702 raise Exception("Timeout on deauth imminent notice")
1703 if " 1 100" not in ev:
1704 raise Exception("Unexpected deauth imminent contents")
1705 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=3)
1706 if ev is None:
1707 raise Exception("Timeout on disconnection")
1708
1709 def test_ap_hs20_remediation_required(dev, apdev):
1710 """Hotspot 2.0 connection and remediation required from RADIUS"""
1711 try:
1712 _test_ap_hs20_remediation_required(dev, apdev)
1713 finally:
1714 dev[0].request("SET pmf 0")
1715
1716 def _test_ap_hs20_remediation_required(dev, apdev):
1717 bssid = apdev[0]['bssid']
1718 params = hs20_ap_params()
1719 params['nai_realm'] = [ "0,example.com,21[2:4]" ]
1720 hostapd.add_ap(apdev[0]['ifname'], params)
1721
1722 dev[0].request("SET pmf 1")
1723 dev[0].hs20_enable()
1724 dev[0].add_cred_values({ 'realm': "example.com",
1725 'username': "hs20-subrem-test",
1726 'password': "password" })
1727 interworking_select(dev[0], bssid, freq="2412")
1728 interworking_connect(dev[0], bssid, "TTLS")
1729 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
1730 if ev is None:
1731 raise Exception("Timeout on subscription remediation notice")
1732 if " 1 https://example.com/" not in ev:
1733 raise Exception("Unexpected subscription remediation event contents")
1734
1735 def test_ap_hs20_remediation_required_ctrl(dev, apdev):
1736 """Hotspot 2.0 connection and subrem from ctrl_iface"""
1737 try:
1738 _test_ap_hs20_remediation_required_ctrl(dev, apdev)
1739 finally:
1740 dev[0].request("SET pmf 0")
1741
1742 def _test_ap_hs20_remediation_required_ctrl(dev, apdev):
1743 bssid = apdev[0]['bssid']
1744 addr = dev[0].p2p_dev_addr()
1745 params = hs20_ap_params()
1746 params['nai_realm'] = [ "0,example.com,21[2:4]" ]
1747 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1748
1749 dev[0].request("SET pmf 1")
1750 dev[0].hs20_enable()
1751 dev[0].add_cred_values(default_cred())
1752 interworking_select(dev[0], bssid, freq="2412")
1753 interworking_connect(dev[0], bssid, "TTLS")
1754
1755 hapd.request("HS20_WNM_NOTIF " + addr + " https://example.com/")
1756 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
1757 if ev is None:
1758 raise Exception("Timeout on subscription remediation notice")
1759 if " 1 https://example.com/" not in ev:
1760 raise Exception("Unexpected subscription remediation event contents")
1761
1762 hapd.request("HS20_WNM_NOTIF " + addr)
1763 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
1764 if ev is None:
1765 raise Exception("Timeout on subscription remediation notice")
1766 if not ev.endswith("HS20-SUBSCRIPTION-REMEDIATION "):
1767 raise Exception("Unexpected subscription remediation event contents: " + ev)
1768
1769 if "FAIL" not in hapd.request("HS20_WNM_NOTIF "):
1770 raise Exception("Unexpected HS20_WNM_NOTIF success")
1771 if "FAIL" not in hapd.request("HS20_WNM_NOTIF foo"):
1772 raise Exception("Unexpected HS20_WNM_NOTIF success")
1773 if "FAIL" not in hapd.request("HS20_WNM_NOTIF " + addr + " https://12345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678927.very.long.example.com/"):
1774 raise Exception("Unexpected HS20_WNM_NOTIF success")
1775
1776 def test_ap_hs20_session_info(dev, apdev):
1777 """Hotspot 2.0 connection and session information from RADIUS"""
1778 try:
1779 _test_ap_hs20_session_info(dev, apdev)
1780 finally:
1781 dev[0].request("SET pmf 0")
1782
1783 def _test_ap_hs20_session_info(dev, apdev):
1784 bssid = apdev[0]['bssid']
1785 params = hs20_ap_params()
1786 params['nai_realm'] = [ "0,example.com,21[2:4]" ]
1787 hostapd.add_ap(apdev[0]['ifname'], params)
1788
1789 dev[0].request("SET pmf 1")
1790 dev[0].hs20_enable()
1791 dev[0].add_cred_values({ 'realm': "example.com",
1792 'username': "hs20-session-info-test",
1793 'password': "password" })
1794 interworking_select(dev[0], bssid, freq="2412")
1795 interworking_connect(dev[0], bssid, "TTLS")
1796 ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"], timeout=10)
1797 if ev is None:
1798 raise Exception("Timeout on ESS disassociation imminent notice")
1799 if " 1 59904 https://example.com/" not in ev:
1800 raise Exception("Unexpected ESS disassociation imminent event contents")
1801 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"])
1802 if ev is None:
1803 raise Exception("Scan not started")
1804 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=30)
1805 if ev is None:
1806 raise Exception("Scan not completed")
1807
1808 def test_ap_hs20_osen(dev, apdev):
1809 """Hotspot 2.0 OSEN connection"""
1810 params = { 'ssid': "osen",
1811 'osen': "1",
1812 'auth_server_addr': "127.0.0.1",
1813 'auth_server_port': "1812",
1814 'auth_server_shared_secret': "radius" }
1815 hostapd.add_ap(apdev[0]['ifname'], params)
1816
1817 dev[1].connect("osen", key_mgmt="NONE", scan_freq="2412",
1818 wait_connect=False)
1819 dev[2].connect("osen", key_mgmt="NONE", wep_key0='"hello"',
1820 scan_freq="2412", wait_connect=False)
1821 dev[0].connect("osen", proto="OSEN", key_mgmt="OSEN", pairwise="CCMP",
1822 group="GTK_NOT_USED",
1823 eap="WFA-UNAUTH-TLS", identity="osen@example.com",
1824 ca_cert="auth_serv/ca.pem",
1825 scan_freq="2412")
1826
1827 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1828 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
1829 wpas.connect("osen", proto="OSEN", key_mgmt="OSEN", pairwise="CCMP",
1830 group="GTK_NOT_USED",
1831 eap="WFA-UNAUTH-TLS", identity="osen@example.com",
1832 ca_cert="auth_serv/ca.pem",
1833 scan_freq="2412")
1834 wpas.request("DISCONNECT")
1835
1836 def test_ap_hs20_network_preference(dev, apdev):
1837 """Hotspot 2.0 network selection with preferred home network"""
1838 bssid = apdev[0]['bssid']
1839 params = hs20_ap_params()
1840 hostapd.add_ap(apdev[0]['ifname'], params)
1841
1842 dev[0].hs20_enable()
1843 values = { 'realm': "example.com",
1844 'username': "hs20-test",
1845 'password': "password",
1846 'domain': "example.com" }
1847 dev[0].add_cred_values(values)
1848
1849 id = dev[0].add_network()
1850 dev[0].set_network_quoted(id, "ssid", "home")
1851 dev[0].set_network_quoted(id, "psk", "12345678")
1852 dev[0].set_network(id, "priority", "1")
1853 dev[0].request("ENABLE_NETWORK %s no-connect" % id)
1854
1855 dev[0].scan_for_bss(bssid, freq="2412")
1856 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1857 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
1858 if ev is None:
1859 raise Exception("Connection timed out")
1860 if bssid not in ev:
1861 raise Exception("Unexpected network selected")
1862
1863 bssid2 = apdev[1]['bssid']
1864 params = hostapd.wpa2_params(ssid="home", passphrase="12345678")
1865 hostapd.add_ap(apdev[1]['ifname'], params)
1866
1867 dev[0].scan_for_bss(bssid2, freq="2412")
1868 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1869 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1870 "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
1871 if ev is None:
1872 raise Exception("Connection timed out")
1873 if "INTERWORKING-ALREADY-CONNECTED" in ev:
1874 raise Exception("No roam to higher priority network")
1875 if bssid2 not in ev:
1876 raise Exception("Unexpected network selected")
1877
1878 def test_ap_hs20_network_preference2(dev, apdev):
1879 """Hotspot 2.0 network selection with preferred credential"""
1880 bssid2 = apdev[1]['bssid']
1881 params = hostapd.wpa2_params(ssid="home", passphrase="12345678")
1882 hostapd.add_ap(apdev[1]['ifname'], params)
1883
1884 dev[0].hs20_enable()
1885 values = { 'realm': "example.com",
1886 'username': "hs20-test",
1887 'password': "password",
1888 'domain': "example.com",
1889 'priority': "1" }
1890 dev[0].add_cred_values(values)
1891
1892 id = dev[0].add_network()
1893 dev[0].set_network_quoted(id, "ssid", "home")
1894 dev[0].set_network_quoted(id, "psk", "12345678")
1895 dev[0].request("ENABLE_NETWORK %s no-connect" % id)
1896
1897 dev[0].scan_for_bss(bssid2, freq="2412")
1898 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1899 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
1900 if ev is None:
1901 raise Exception("Connection timed out")
1902 if bssid2 not in ev:
1903 raise Exception("Unexpected network selected")
1904
1905 bssid = apdev[0]['bssid']
1906 params = hs20_ap_params()
1907 hostapd.add_ap(apdev[0]['ifname'], params)
1908
1909 dev[0].scan_for_bss(bssid, freq="2412")
1910 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1911 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1912 "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
1913 if ev is None:
1914 raise Exception("Connection timed out")
1915 if "INTERWORKING-ALREADY-CONNECTED" in ev:
1916 raise Exception("No roam to higher priority network")
1917 if bssid not in ev:
1918 raise Exception("Unexpected network selected")
1919
1920 def test_ap_hs20_network_preference3(dev, apdev):
1921 """Hotspot 2.0 network selection with two credential (one preferred)"""
1922 bssid = apdev[0]['bssid']
1923 params = hs20_ap_params()
1924 hostapd.add_ap(apdev[0]['ifname'], params)
1925
1926 bssid2 = apdev[1]['bssid']
1927 params = hs20_ap_params(ssid="test-hs20b")
1928 params['nai_realm'] = "0,example.org,13[5:6],21[2:4][5:7]"
1929 hostapd.add_ap(apdev[1]['ifname'], params)
1930
1931 dev[0].hs20_enable()
1932 values = { 'realm': "example.com",
1933 'username': "hs20-test",
1934 'password': "password",
1935 'priority': "1" }
1936 dev[0].add_cred_values(values)
1937 values = { 'realm': "example.org",
1938 'username': "hs20-test",
1939 'password': "password" }
1940 id = dev[0].add_cred_values(values)
1941
1942 dev[0].scan_for_bss(bssid, freq="2412")
1943 dev[0].scan_for_bss(bssid2, freq="2412")
1944 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1945 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
1946 if ev is None:
1947 raise Exception("Connection timed out")
1948 if bssid not in ev:
1949 raise Exception("Unexpected network selected")
1950
1951 dev[0].set_cred(id, "priority", "2")
1952 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1953 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1954 "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
1955 if ev is None:
1956 raise Exception("Connection timed out")
1957 if "INTERWORKING-ALREADY-CONNECTED" in ev:
1958 raise Exception("No roam to higher priority network")
1959 if bssid2 not in ev:
1960 raise Exception("Unexpected network selected")
1961
1962 def test_ap_hs20_network_preference4(dev, apdev):
1963 """Hotspot 2.0 network selection with username vs. SIM credential"""
1964 bssid = apdev[0]['bssid']
1965 params = hs20_ap_params()
1966 hostapd.add_ap(apdev[0]['ifname'], params)
1967
1968 bssid2 = apdev[1]['bssid']
1969 params = hs20_ap_params(ssid="test-hs20b")
1970 params['hessid'] = bssid2
1971 params['anqp_3gpp_cell_net'] = "555,444"
1972 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
1973 hostapd.add_ap(apdev[1]['ifname'], params)
1974
1975 dev[0].hs20_enable()
1976 values = { 'realm': "example.com",
1977 'username': "hs20-test",
1978 'password': "password",
1979 'priority': "1" }
1980 dev[0].add_cred_values(values)
1981 values = { 'imsi': "555444-333222111",
1982 'eap': "SIM",
1983 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123" }
1984 id = dev[0].add_cred_values(values)
1985
1986 dev[0].scan_for_bss(bssid, freq="2412")
1987 dev[0].scan_for_bss(bssid2, freq="2412")
1988 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1989 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
1990 if ev is None:
1991 raise Exception("Connection timed out")
1992 if bssid not in ev:
1993 raise Exception("Unexpected network selected")
1994
1995 dev[0].set_cred(id, "priority", "2")
1996 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1997 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1998 "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
1999 if ev is None:
2000 raise Exception("Connection timed out")
2001 if "INTERWORKING-ALREADY-CONNECTED" in ev:
2002 raise Exception("No roam to higher priority network")
2003 if bssid2 not in ev:
2004 raise Exception("Unexpected network selected")
2005
2006 def test_ap_hs20_fetch_osu(dev, apdev):
2007 """Hotspot 2.0 OSU provider and icon fetch"""
2008 bssid = apdev[0]['bssid']
2009 params = hs20_ap_params()
2010 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
2011 params['osu_ssid'] = '"HS 2.0 OSU open"'
2012 params['osu_method_list'] = "1"
2013 params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
2014 params['osu_icon'] = "w1fi_logo"
2015 params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
2016 params['osu_server_uri'] = "https://example.com/osu/"
2017 hostapd.add_ap(apdev[0]['ifname'], params)
2018
2019 bssid2 = apdev[1]['bssid']
2020 params = hs20_ap_params(ssid="test-hs20b")
2021 params['hessid'] = bssid2
2022 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
2023 params['osu_ssid'] = '"HS 2.0 OSU OSEN"'
2024 params['osu_method_list'] = "0"
2025 params['osu_nai'] = "osen@example.com"
2026 params['osu_friendly_name'] = [ "eng:Test2 OSU", "fin:Testi2-OSU" ]
2027 params['osu_icon'] = "w1fi_logo"
2028 params['osu_service_desc'] = [ "eng:Example services2", "fin:Esimerkkipalveluja2" ]
2029 params['osu_server_uri'] = "https://example.org/osu/"
2030 hostapd.add_ap(apdev[1]['ifname'], params)
2031
2032 with open("w1fi_logo.png", "r") as f:
2033 orig_logo = f.read()
2034 dev[0].hs20_enable()
2035 dir = "/tmp/osu-fetch"
2036 if os.path.isdir(dir):
2037 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
2038 for f in files:
2039 os.remove(dir + "/" + f)
2040 else:
2041 try:
2042 os.makedirs(dir)
2043 except:
2044 pass
2045 try:
2046 dev[1].scan_for_bss(bssid, freq="2412")
2047 dev[0].request("SET osu_dir " + dir)
2048 dev[0].request("FETCH_OSU")
2049 if "FAIL" not in dev[1].request("HS20_ICON_REQUEST foo w1fi_logo"):
2050 raise Exception("Invalid HS20_ICON_REQUEST accepted")
2051 if "OK" not in dev[1].request("HS20_ICON_REQUEST " + bssid + " w1fi_logo"):
2052 raise Exception("HS20_ICON_REQUEST failed")
2053 icons = 0
2054 while True:
2055 ev = dev[0].wait_event(["OSU provider fetch completed",
2056 "RX-HS20-ANQP-ICON"], timeout=15)
2057 if ev is None:
2058 raise Exception("Timeout on OSU fetch")
2059 if "OSU provider fetch completed" in ev:
2060 break
2061 if "RX-HS20-ANQP-ICON" in ev:
2062 with open(ev.split(' ')[1], "r") as f:
2063 logo = f.read()
2064 if logo == orig_logo:
2065 icons += 1
2066
2067 with open(dir + "/osu-providers.txt", "r") as f:
2068 prov = f.read()
2069 if "OSU-PROVIDER " + bssid not in prov:
2070 raise Exception("Missing OSU_PROVIDER")
2071 if "OSU-PROVIDER " + bssid2 not in prov:
2072 raise Exception("Missing OSU_PROVIDER")
2073 finally:
2074 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
2075 for f in files:
2076 os.remove(dir + "/" + f)
2077 os.rmdir(dir)
2078
2079 if icons != 2:
2080 raise Exception("Unexpected number of icons fetched")
2081
2082 ev = dev[1].wait_event(["GAS-QUERY-START"], timeout=5)
2083 if ev is None:
2084 raise Exception("Timeout on GAS-QUERY-DONE")
2085 ev = dev[1].wait_event(["GAS-QUERY-DONE"], timeout=5)
2086 if ev is None:
2087 raise Exception("Timeout on GAS-QUERY-DONE")
2088 if "freq=2412 status_code=0 result=SUCCESS" not in ev:
2089 raise Exception("Unexpected GAS-QUERY-DONE: " + ev)
2090 ev = dev[1].wait_event(["RX-HS20-ANQP"], timeout=15)
2091 if ev is None:
2092 raise Exception("Timeout on icon fetch")
2093 if "Icon Binary File" not in ev:
2094 raise Exception("Unexpected ANQP element")
2095
2096 def test_ap_hs20_fetch_osu_stop(dev, apdev):
2097 """Hotspot 2.0 OSU provider fetch stopped"""
2098 bssid = apdev[0]['bssid']
2099 params = hs20_ap_params()
2100 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
2101 params['osu_ssid'] = '"HS 2.0 OSU open"'
2102 params['osu_method_list'] = "1"
2103 params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
2104 params['osu_icon'] = "w1fi_logo"
2105 params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
2106 params['osu_server_uri'] = "https://example.com/osu/"
2107 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2108
2109 dev[0].hs20_enable()
2110 dir = "/tmp/osu-fetch"
2111 if os.path.isdir(dir):
2112 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
2113 for f in files:
2114 os.remove(dir + "/" + f)
2115 else:
2116 try:
2117 os.makedirs(dir)
2118 except:
2119 pass
2120 try:
2121 dev[0].request("SET osu_dir " + dir)
2122 dev[0].request("SCAN freq=2412-2462")
2123 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=10)
2124 if ev is None:
2125 raise Exception("Scan did not start")
2126 if "FAIL" not in dev[0].request("FETCH_OSU"):
2127 raise Exception("FETCH_OSU accepted while scanning")
2128 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
2129 if ev is None:
2130 raise Exception("Scan timed out")
2131 hapd.set("ext_mgmt_frame_handling", "1")
2132 dev[0].request("FETCH_ANQP")
2133 if "FAIL" not in dev[0].request("FETCH_OSU"):
2134 raise Exception("FETCH_OSU accepted while in FETCH_ANQP")
2135 dev[0].request("STOP_FETCH_ANQP")
2136 dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5)
2137 dev[0].dump_monitor()
2138 hapd.dump_monitor()
2139 dev[0].request("INTERWORKING_SELECT freq=2412")
2140 for i in range(5):
2141 msg = hapd.mgmt_rx()
2142 if msg['subtype'] == 13:
2143 break
2144 if "FAIL" not in dev[0].request("FETCH_OSU"):
2145 raise Exception("FETCH_OSU accepted while in INTERWORKING_SELECT")
2146 ev = dev[0].wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
2147 timeout=15)
2148 if ev is None:
2149 raise Exception("Network selection timed out");
2150
2151 dev[0].dump_monitor()
2152 if "OK" not in dev[0].request("FETCH_OSU"):
2153 raise Exception("FETCH_OSU failed")
2154 dev[0].request("CANCEL_FETCH_OSU")
2155
2156 for i in range(15):
2157 time.sleep(0.5)
2158 if dev[0].get_driver_status_field("scan_state") == "SCAN_COMPLETED":
2159 break
2160
2161 dev[0].dump_monitor()
2162 if "OK" not in dev[0].request("FETCH_OSU"):
2163 raise Exception("FETCH_OSU failed")
2164 if "FAIL" not in dev[0].request("FETCH_OSU"):
2165 raise Exception("FETCH_OSU accepted while in FETCH_OSU")
2166 ev = dev[0].wait_event(["GAS-QUERY-START"], 10)
2167 if ev is None:
2168 raise Exception("GAS timed out")
2169 if "FAIL" not in dev[0].request("FETCH_OSU"):
2170 raise Exception("FETCH_OSU accepted while in FETCH_OSU")
2171 dev[0].request("CANCEL_FETCH_OSU")
2172 ev = dev[0].wait_event(["GAS-QUERY-DONE"], 10)
2173 if ev is None:
2174 raise Exception("GAS event timed out after CANCEL_FETCH_OSU")
2175 finally:
2176 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
2177 for f in files:
2178 os.remove(dir + "/" + f)
2179 os.rmdir(dir)
2180
2181 def test_ap_hs20_ft(dev, apdev):
2182 """Hotspot 2.0 connection with FT"""
2183 bssid = apdev[0]['bssid']
2184 params = hs20_ap_params()
2185 params['wpa_key_mgmt'] = "FT-EAP"
2186 params['nas_identifier'] = "nas1.w1.fi"
2187 params['r1_key_holder'] = "000102030405"
2188 params["mobility_domain"] = "a1b2"
2189 params["reassociation_deadline"] = "1000"
2190 hostapd.add_ap(apdev[0]['ifname'], params)
2191
2192 dev[0].hs20_enable()
2193 id = dev[0].add_cred_values({ 'realm': "example.com",
2194 'username': "hs20-test",
2195 'password': "password",
2196 'ca_cert': "auth_serv/ca.pem",
2197 'domain': "example.com",
2198 'update_identifier': "1234" })
2199 interworking_select(dev[0], bssid, "home", freq="2412")
2200 interworking_connect(dev[0], bssid, "TTLS")
2201
2202 def test_ap_hs20_remediation_sql(dev, apdev, params):
2203 """Hotspot 2.0 connection and remediation required using SQLite for user DB"""
2204 try:
2205 import sqlite3
2206 except ImportError:
2207 return "skip"
2208 dbfile = os.path.join(params['logdir'], "eap-user.db")
2209 try:
2210 os.remove(dbfile)
2211 except:
2212 pass
2213 con = sqlite3.connect(dbfile)
2214 with con:
2215 cur = con.cursor()
2216 cur.execute("CREATE TABLE users(identity TEXT PRIMARY KEY, methods TEXT, password TEXT, remediation TEXT, phase2 INTEGER)")
2217 cur.execute("CREATE TABLE wildcards(identity TEXT PRIMARY KEY, methods TEXT)")
2218 cur.execute("INSERT INTO users(identity,methods,password,phase2,remediation) VALUES ('user-mschapv2','TTLS-MSCHAPV2','password',1,'user')")
2219 cur.execute("INSERT INTO wildcards(identity,methods) VALUES ('','TTLS,TLS')")
2220 cur.execute("CREATE TABLE authlog(timestamp TEXT, session TEXT, nas_ip TEXT, username TEXT, note TEXT)")
2221
2222 try:
2223 params = { "ssid": "as", "beacon_int": "2000",
2224 "radius_server_clients": "auth_serv/radius_clients.conf",
2225 "radius_server_auth_port": '18128',
2226 "eap_server": "1",
2227 "eap_user_file": "sqlite:" + dbfile,
2228 "ca_cert": "auth_serv/ca.pem",
2229 "server_cert": "auth_serv/server.pem",
2230 "private_key": "auth_serv/server.key",
2231 "subscr_remediation_url": "https://example.org/",
2232 "subscr_remediation_method": "1" }
2233 hostapd.add_ap(apdev[1]['ifname'], params)
2234
2235 bssid = apdev[0]['bssid']
2236 params = hs20_ap_params()
2237 params['auth_server_port'] = "18128"
2238 hostapd.add_ap(apdev[0]['ifname'], params)
2239
2240 dev[0].request("SET pmf 1")
2241 dev[0].hs20_enable()
2242 id = dev[0].add_cred_values({ 'realm': "example.com",
2243 'username': "user-mschapv2",
2244 'password': "password",
2245 'ca_cert': "auth_serv/ca.pem" })
2246 interworking_select(dev[0], bssid, freq="2412")
2247 interworking_connect(dev[0], bssid, "TTLS")
2248 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
2249 if ev is None:
2250 raise Exception("Timeout on subscription remediation notice")
2251 if " 1 https://example.org/" not in ev:
2252 raise Exception("Unexpected subscription remediation event contents")
2253
2254 with con:
2255 cur = con.cursor()
2256 cur.execute("SELECT * from authlog")
2257 rows = cur.fetchall()
2258 if len(rows) < 1:
2259 raise Exception("No authlog entries")
2260
2261 finally:
2262 os.remove(dbfile)
2263 dev[0].request("SET pmf 0")
2264
2265 def test_ap_hs20_external_selection(dev, apdev):
2266 """Hotspot 2.0 connection using external network selection and creation"""
2267 bssid = apdev[0]['bssid']
2268 params = hs20_ap_params()
2269 params['hessid'] = bssid
2270 params['disable_dgaf'] = '1'
2271 hostapd.add_ap(apdev[0]['ifname'], params)
2272
2273 dev[0].hs20_enable()
2274 dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="TTLS",
2275 identity="hs20-test", password="password",
2276 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
2277 scan_freq="2412", update_identifier="54321")
2278 if dev[0].get_status_field("hs20") != "2":
2279 raise Exception("Unexpected hs20 indication")
2280
2281 def test_ap_hs20_random_mac_addr(dev, apdev):
2282 """Hotspot 2.0 connection with random MAC address"""
2283 bssid = apdev[0]['bssid']
2284 params = hs20_ap_params()
2285 params['hessid'] = bssid
2286 params['disable_dgaf'] = '1'
2287 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2288
2289 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
2290 wpas.interface_add("wlan5")
2291 addr = wpas.p2p_interface_addr()
2292 wpas.request("SET mac_addr 1")
2293 wpas.request("SET preassoc_mac_addr 1")
2294 wpas.request("SET rand_addr_lifetime 60")
2295 wpas.hs20_enable()
2296 wpas.flush_scan_cache()
2297 id = wpas.add_cred_values({ 'realm': "example.com",
2298 'username': "hs20-test",
2299 'password': "password",
2300 'ca_cert': "auth_serv/ca.pem",
2301 'domain': "example.com",
2302 'update_identifier': "1234" })
2303 interworking_select(wpas, bssid, "home", freq="2412")
2304 interworking_connect(wpas, bssid, "TTLS")
2305 addr1 = wpas.get_driver_status_field("addr")
2306 if addr == addr1:
2307 raise Exception("Did not use random MAC address")
2308
2309 sta = hapd.get_sta(addr)
2310 if sta['addr'] != "FAIL":
2311 raise Exception("Unexpected STA association with permanent address")
2312 sta = hapd.get_sta(addr1)
2313 if sta['addr'] != addr1:
2314 raise Exception("STA association with random address not found")
2315
2316 def test_ap_hs20_multi_network_and_cred_removal(dev, apdev):
2317 """Multiple networks and cred removal"""
2318 bssid = apdev[0]['bssid']
2319 params = hs20_ap_params()
2320 params['nai_realm'] = [ "0,example.com,25[3:26]"]
2321 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2322
2323 dev[0].add_network()
2324 dev[0].hs20_enable()
2325 id = dev[0].add_cred_values({ 'realm': "example.com",
2326 'username': "user",
2327 'password': "password" })
2328 interworking_select(dev[0], bssid, freq="2412")
2329 interworking_connect(dev[0], bssid, "PEAP")
2330 dev[0].add_network()
2331
2332 dev[0].request("DISCONNECT")
2333 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
2334 if ev is None:
2335 raise Exception("Timeout on disconnection")
2336
2337 hapd.disable()
2338 hapd.set("ssid", "another ssid")
2339 hapd.enable()
2340
2341 interworking_select(dev[0], bssid, freq="2412")
2342 interworking_connect(dev[0], bssid, "PEAP")
2343 dev[0].add_network()
2344 if len(dev[0].list_networks()) != 5:
2345 raise Exception("Unexpected number of networks prior to remove_crec")
2346
2347 dev[0].dump_monitor()
2348 dev[0].remove_cred(id)
2349 if len(dev[0].list_networks()) != 3:
2350 raise Exception("Unexpected number of networks after to remove_crec")
2351 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
2352 if ev is None:
2353 raise Exception("Timeout on disconnection")
2354
2355 def _test_ap_hs20_proxyarp(dev, apdev):
2356 bssid = apdev[0]['bssid']
2357 params = hs20_ap_params()
2358 params['hessid'] = bssid
2359 params['disable_dgaf'] = '0'
2360 params['proxy_arp'] = '1'
2361 hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
2362 if "OK" in hapd.request("ENABLE"):
2363 raise Exception("Incomplete hostapd configuration was accepted")
2364 hapd.set("ap_isolate", "1")
2365 if "OK" in hapd.request("ENABLE"):
2366 raise Exception("Incomplete hostapd configuration was accepted")
2367 hapd.set('bridge', 'ap-br0')
2368 hapd.dump_monitor()
2369 try:
2370 hapd.enable()
2371 except:
2372 # For now, do not report failures due to missing kernel support
2373 logger.info("Could not start hostapd - assume proxyarp not supported in kernel version")
2374 return "skip"
2375 ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
2376 if ev is None:
2377 raise Exception("AP startup timed out")
2378 if "AP-ENABLED" not in ev:
2379 raise Exception("AP startup failed")
2380
2381 dev[0].hs20_enable()
2382 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
2383 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
2384
2385 id = dev[0].add_cred_values({ 'realm': "example.com",
2386 'username': "hs20-test",
2387 'password': "password",
2388 'ca_cert': "auth_serv/ca.pem",
2389 'domain': "example.com",
2390 'update_identifier': "1234" })
2391 interworking_select(dev[0], bssid, "home", freq="2412")
2392 interworking_connect(dev[0], bssid, "TTLS")
2393
2394 dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
2395 identity="hs20-test", password="password",
2396 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
2397 scan_freq="2412")
2398 time.sleep(0.1)
2399
2400 addr0 = dev[0].p2p_interface_addr()
2401 addr1 = dev[1].p2p_interface_addr()
2402
2403 src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':',''))
2404 src_ll_opt1 = "\x01\x01" + binascii.unhexlify(addr1.replace(':',''))
2405
2406 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
2407 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
2408 opt=src_ll_opt0)
2409 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2410 raise Exception("DATA_TEST_FRAME failed")
2411
2412 pkt = build_ns(src_ll=addr1, ip_src="aaaa:bbbb:dddd::2",
2413 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:dddd::2",
2414 opt=src_ll_opt1)
2415 if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2416 raise Exception("DATA_TEST_FRAME failed")
2417
2418 pkt = build_ns(src_ll=addr1, ip_src="aaaa:bbbb:eeee::2",
2419 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:eeee::2",
2420 opt=src_ll_opt1)
2421 if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2422 raise Exception("DATA_TEST_FRAME failed")
2423
2424 matches = get_permanent_neighbors("ap-br0")
2425 logger.info("After connect: " + str(matches))
2426 if len(matches) != 3:
2427 raise Exception("Unexpected number of neighbor entries after connect")
2428 if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
2429 raise Exception("dev0 addr missing")
2430 if 'aaaa:bbbb:dddd::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
2431 raise Exception("dev1 addr(1) missing")
2432 if 'aaaa:bbbb:eeee::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
2433 raise Exception("dev1 addr(2) missing")
2434 dev[0].request("DISCONNECT")
2435 dev[1].request("DISCONNECT")
2436 time.sleep(0.5)
2437 matches = get_permanent_neighbors("ap-br0")
2438 logger.info("After disconnect: " + str(matches))
2439 if len(matches) > 0:
2440 raise Exception("Unexpected neighbor entries after disconnect")
2441
2442 def test_ap_hs20_proxyarp(dev, apdev):
2443 """Hotspot 2.0 and ProxyARP"""
2444 res = None
2445 try:
2446 res = _test_ap_hs20_proxyarp(dev, apdev)
2447 finally:
2448 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
2449 stderr=open('/dev/null', 'w'))
2450 subprocess.call(['brctl', 'delbr', 'ap-br0'],
2451 stderr=open('/dev/null', 'w'))
2452
2453 return res
2454
2455 def _test_ap_hs20_proxyarp_dgaf(dev, apdev, disabled):
2456 bssid = apdev[0]['bssid']
2457 params = hs20_ap_params()
2458 params['hessid'] = bssid
2459 params['disable_dgaf'] = '1' if disabled else '0'
2460 params['proxy_arp'] = '1'
2461 params['ap_isolate'] = '1'
2462 params['bridge'] = 'ap-br0'
2463 hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
2464 try:
2465 hapd.enable()
2466 except:
2467 # For now, do not report failures due to missing kernel support
2468 logger.info("Could not start hostapd - assume proxyarp not supported in kernel version")
2469 return "skip"
2470 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
2471 if ev is None:
2472 raise Exception("AP startup timed out")
2473
2474 dev[0].hs20_enable()
2475 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
2476 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
2477
2478 id = dev[0].add_cred_values({ 'realm': "example.com",
2479 'username': "hs20-test",
2480 'password': "password",
2481 'ca_cert': "auth_serv/ca.pem",
2482 'domain': "example.com",
2483 'update_identifier': "1234" })
2484 interworking_select(dev[0], bssid, "home", freq="2412")
2485 interworking_connect(dev[0], bssid, "TTLS")
2486
2487 dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
2488 identity="hs20-test", password="password",
2489 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
2490 scan_freq="2412")
2491 time.sleep(0.1)
2492
2493 addr0 = dev[0].p2p_interface_addr()
2494
2495 src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':',''))
2496
2497 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
2498 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
2499 opt=src_ll_opt0)
2500 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2501 raise Exception("DATA_TEST_FRAME failed")
2502
2503 pkt = build_ra(src_ll=apdev[0]['bssid'], ip_src="aaaa:bbbb:cccc::33",
2504 ip_dst="ff01::1")
2505 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2506 raise Exception("DATA_TEST_FRAME failed")
2507
2508 pkt = build_na(src_ll=apdev[0]['bssid'], ip_src="aaaa:bbbb:cccc::44",
2509 ip_dst="ff01::1", target="aaaa:bbbb:cccc::55")
2510 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2511 raise Exception("DATA_TEST_FRAME failed")
2512
2513 pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
2514 ip_src="192.168.1.1", ip_dst="255.255.255.255",
2515 yiaddr="192.168.1.123", chaddr=addr0)
2516 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2517 raise Exception("DATA_TEST_FRAME failed")
2518 # another copy for additional code coverage
2519 pkt = build_dhcp_ack(dst_ll=addr0, src_ll=bssid,
2520 ip_src="192.168.1.1", ip_dst="255.255.255.255",
2521 yiaddr="192.168.1.123", chaddr=addr0)
2522 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2523 raise Exception("DATA_TEST_FRAME failed")
2524
2525 matches = get_permanent_neighbors("ap-br0")
2526 logger.info("After connect: " + str(matches))
2527 if len(matches) != 2:
2528 raise Exception("Unexpected number of neighbor entries after connect")
2529 if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
2530 raise Exception("dev0 addr missing")
2531 if '192.168.1.123 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
2532 raise Exception("dev0 IPv4 addr missing")
2533 dev[0].request("DISCONNECT")
2534 dev[1].request("DISCONNECT")
2535 time.sleep(0.5)
2536 matches = get_permanent_neighbors("ap-br0")
2537 logger.info("After disconnect: " + str(matches))
2538 if len(matches) > 0:
2539 raise Exception("Unexpected neighbor entries after disconnect")
2540
2541 def test_ap_hs20_proxyarp_disable_dgaf(dev, apdev):
2542 """Hotspot 2.0 and ProxyARP with DGAF disabled"""
2543 res = None
2544 try:
2545 res = _test_ap_hs20_proxyarp_dgaf(dev, apdev, True)
2546 finally:
2547 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
2548 stderr=open('/dev/null', 'w'))
2549 subprocess.call(['brctl', 'delbr', 'ap-br0'],
2550 stderr=open('/dev/null', 'w'))
2551
2552 return res
2553
2554 def test_ap_hs20_proxyarp_enable_dgaf(dev, apdev):
2555 """Hotspot 2.0 and ProxyARP with DGAF enabled"""
2556 res = None
2557 try:
2558 res = _test_ap_hs20_proxyarp_dgaf(dev, apdev, False)
2559 finally:
2560 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
2561 stderr=open('/dev/null', 'w'))
2562 subprocess.call(['brctl', 'delbr', 'ap-br0'],
2563 stderr=open('/dev/null', 'w'))
2564
2565 return res
2566
2567 def ip_checksum(buf):
2568 sum = 0
2569 if len(buf) & 0x01:
2570 buf += '\0x00'
2571 for i in range(0, len(buf), 2):
2572 val, = struct.unpack('H', buf[i:i+2])
2573 sum += val
2574 while (sum >> 16):
2575 sum = (sum & 0xffff) + (sum >> 16)
2576 return struct.pack('H', ~sum & 0xffff)
2577
2578 def ipv6_solicited_node_mcaddr(target):
2579 prefix = socket.inet_pton(socket.AF_INET6, "ff02::1:ff00:0")
2580 mask = socket.inet_pton(socket.AF_INET6, "::ff:ffff")
2581 _target = socket.inet_pton(socket.AF_INET6, target)
2582 p = struct.unpack('4I', prefix)
2583 m = struct.unpack('4I', mask)
2584 t = struct.unpack('4I', _target)
2585 res = (p[0] | (t[0] & m[0]),
2586 p[1] | (t[1] & m[1]),
2587 p[2] | (t[2] & m[2]),
2588 p[3] | (t[3] & m[3]))
2589 return socket.inet_ntop(socket.AF_INET6, struct.pack('4I', *res))
2590
2591 def build_icmpv6(ipv6_addrs, type, code, payload):
2592 start = struct.pack("BB", type, code)
2593 end = payload
2594 icmp = start + '\x00\x00' + end
2595 pseudo = ipv6_addrs + struct.pack(">LBBBB", len(icmp), 0, 0, 0, 58)
2596 csum = ip_checksum(pseudo + icmp)
2597 return start + csum + end
2598
2599 def build_ra(src_ll, ip_src, ip_dst, cur_hop_limit=0, router_lifetime=0,
2600 reachable_time=0, retrans_timer=0, opt=None):
2601 link_mc = binascii.unhexlify("3333ff000002")
2602 _src_ll = binascii.unhexlify(src_ll.replace(':',''))
2603 proto = '\x86\xdd'
2604 ehdr = link_mc + _src_ll + proto
2605 _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
2606 _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
2607
2608 adv = struct.pack('>BBHLL', cur_hop_limit, 0, router_lifetime,
2609 reachable_time, retrans_timer)
2610 if opt:
2611 payload = adv + opt
2612 else:
2613 payload = adv
2614 icmp = build_icmpv6(_ip_src + _ip_dst, 134, 0, payload)
2615
2616 ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
2617 ipv6 += _ip_src + _ip_dst
2618
2619 return ehdr + ipv6 + icmp
2620
2621 def build_ns(src_ll, ip_src, ip_dst, target, opt=None):
2622 link_mc = binascii.unhexlify("3333ff000002")
2623 _src_ll = binascii.unhexlify(src_ll.replace(':',''))
2624 proto = '\x86\xdd'
2625 ehdr = link_mc + _src_ll + proto
2626 _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
2627 if ip_dst is None:
2628 ip_dst = ipv6_solicited_node_mcaddr(target)
2629 _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
2630
2631 reserved = '\x00\x00\x00\x00'
2632 _target = socket.inet_pton(socket.AF_INET6, target)
2633 if opt:
2634 payload = reserved + _target + opt
2635 else:
2636 payload = reserved + _target
2637 icmp = build_icmpv6(_ip_src + _ip_dst, 135, 0, payload)
2638
2639 ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
2640 ipv6 += _ip_src + _ip_dst
2641
2642 return ehdr + ipv6 + icmp
2643
2644 def send_ns(dev, src_ll=None, target=None, ip_src=None, ip_dst=None, opt=None,
2645 hapd_bssid=None):
2646 if hapd_bssid:
2647 if src_ll is None:
2648 src_ll = hapd_bssid
2649 cmd = "DATA_TEST_FRAME ifname=ap-br0 "
2650 else:
2651 if src_ll is None:
2652 src_ll = dev.p2p_interface_addr()
2653 cmd = "DATA_TEST_FRAME "
2654
2655 if opt is None:
2656 opt = "\x01\x01" + binascii.unhexlify(src_ll.replace(':',''))
2657
2658 pkt = build_ns(src_ll=src_ll, ip_src=ip_src, ip_dst=ip_dst, target=target,
2659 opt=opt)
2660 if "OK" not in dev.request(cmd + binascii.hexlify(pkt)):
2661 raise Exception("DATA_TEST_FRAME failed")
2662
2663 def build_na(src_ll, ip_src, ip_dst, target, opt=None):
2664 link_mc = binascii.unhexlify("3333ff000002")
2665 _src_ll = binascii.unhexlify(src_ll.replace(':',''))
2666 proto = '\x86\xdd'
2667 ehdr = link_mc + _src_ll + proto
2668 _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
2669 _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
2670
2671 reserved = '\x00\x00\x00\x00'
2672 _target = socket.inet_pton(socket.AF_INET6, target)
2673 if opt:
2674 payload = reserved + _target + opt
2675 else:
2676 payload = reserved + _target
2677 icmp = build_icmpv6(_ip_src + _ip_dst, 136, 0, payload)
2678
2679 ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
2680 ipv6 += _ip_src + _ip_dst
2681
2682 return ehdr + ipv6 + icmp
2683
2684 def send_na(dev, src_ll=None, target=None, ip_src=None, ip_dst=None, opt=None,
2685 hapd_bssid=None):
2686 if hapd_bssid:
2687 if src_ll is None:
2688 src_ll = hapd_bssid
2689 cmd = "DATA_TEST_FRAME ifname=ap-br0 "
2690 else:
2691 if src_ll is None:
2692 src_ll = dev.p2p_interface_addr()
2693 cmd = "DATA_TEST_FRAME "
2694
2695 pkt = build_na(src_ll=src_ll, ip_src=ip_src, ip_dst=ip_dst, target=target,
2696 opt=opt)
2697 if "OK" not in dev.request(cmd + binascii.hexlify(pkt)):
2698 raise Exception("DATA_TEST_FRAME failed")
2699
2700 def build_dhcp_ack(dst_ll, src_ll, ip_src, ip_dst, yiaddr, chaddr,
2701 subnet_mask="255.255.255.0", truncated_opt=False,
2702 wrong_magic=False, force_tot_len=None, no_dhcp=False):
2703 _dst_ll = binascii.unhexlify(dst_ll.replace(':',''))
2704 _src_ll = binascii.unhexlify(src_ll.replace(':',''))
2705 proto = '\x08\x00'
2706 ehdr = _dst_ll + _src_ll + proto
2707 _ip_src = socket.inet_pton(socket.AF_INET, ip_src)
2708 _ip_dst = socket.inet_pton(socket.AF_INET, ip_dst)
2709 _subnet_mask = socket.inet_pton(socket.AF_INET, subnet_mask)
2710
2711 _ciaddr = '\x00\x00\x00\x00'
2712 _yiaddr = socket.inet_pton(socket.AF_INET, yiaddr)
2713 _siaddr = '\x00\x00\x00\x00'
2714 _giaddr = '\x00\x00\x00\x00'
2715 _chaddr = binascii.unhexlify(chaddr.replace(':','') + "00000000000000000000")
2716 payload = struct.pack('>BBBBL3BB', 2, 1, 6, 0, 12345, 0, 0, 0, 0)
2717 payload += _ciaddr + _yiaddr + _siaddr + _giaddr + _chaddr + 192*'\x00'
2718 # magic
2719 if wrong_magic:
2720 payload += '\x63\x82\x53\x00'
2721 else:
2722 payload += '\x63\x82\x53\x63'
2723 if truncated_opt:
2724 payload += '\x22\xff\x00'
2725 # Option: DHCP Message Type = ACK
2726 payload += '\x35\x01\x05'
2727 # Pad Option
2728 payload += '\x00'
2729 # Option: Subnet Mask
2730 payload += '\x01\x04' + _subnet_mask
2731 # Option: Time Offset
2732 payload += struct.pack('>BBL', 2, 4, 0)
2733 # End Option
2734 payload += '\xff'
2735 # Pad Option
2736 payload += '\x00\x00\x00\x00'
2737
2738 if no_dhcp:
2739 payload = struct.pack('>BBBBL3BB', 2, 1, 6, 0, 12345, 0, 0, 0, 0)
2740 payload += _ciaddr + _yiaddr + _siaddr + _giaddr + _chaddr + 192*'\x00'
2741
2742 udp = struct.pack('>HHHH', 67, 68, 8 + len(payload), 0) + payload
2743
2744 if force_tot_len:
2745 tot_len = force_tot_len
2746 else:
2747 tot_len = 20 + len(udp)
2748 start = struct.pack('>BBHHBBBB', 0x45, 0, tot_len, 0, 0, 0, 128, 17)
2749 ipv4 = start + '\x00\x00' + _ip_src + _ip_dst
2750 csum = ip_checksum(ipv4)
2751 ipv4 = start + csum + _ip_src + _ip_dst
2752
2753 return ehdr + ipv4 + udp
2754
2755 def build_arp(dst_ll, src_ll, opcode, sender_mac, sender_ip,
2756 target_mac, target_ip):
2757 _dst_ll = binascii.unhexlify(dst_ll.replace(':',''))
2758 _src_ll = binascii.unhexlify(src_ll.replace(':',''))
2759 proto = '\x08\x06'
2760 ehdr = _dst_ll + _src_ll + proto
2761
2762 _sender_mac = binascii.unhexlify(sender_mac.replace(':',''))
2763 _sender_ip = socket.inet_pton(socket.AF_INET, sender_ip)
2764 _target_mac = binascii.unhexlify(target_mac.replace(':',''))
2765 _target_ip = socket.inet_pton(socket.AF_INET, target_ip)
2766
2767 arp = struct.pack('>HHBBH', 1, 0x0800, 6, 4, opcode)
2768 arp += _sender_mac + _sender_ip
2769 arp += _target_mac + _target_ip
2770
2771 return ehdr + arp
2772
2773 def send_arp(dev, dst_ll="ff:ff:ff:ff:ff:ff", src_ll=None, opcode=1,
2774 sender_mac=None, sender_ip="0.0.0.0",
2775 target_mac="00:00:00:00:00:00", target_ip="0.0.0.0",
2776 hapd_bssid=None):
2777 if hapd_bssid:
2778 if src_ll is None:
2779 src_ll = hapd_bssid
2780 if sender_mac is None:
2781 sender_mac = hapd_bssid
2782 cmd = "DATA_TEST_FRAME ifname=ap-br0 "
2783 else:
2784 if src_ll is None:
2785 src_ll = dev.p2p_interface_addr()
2786 if sender_mac is None:
2787 sender_mac = dev.p2p_interface_addr()
2788 cmd = "DATA_TEST_FRAME "
2789
2790 pkt = build_arp(dst_ll=dst_ll, src_ll=src_ll, opcode=opcode,
2791 sender_mac=sender_mac, sender_ip=sender_ip,
2792 target_mac=target_mac, target_ip=target_ip)
2793 if "OK" not in dev.request(cmd + binascii.hexlify(pkt)):
2794 raise Exception("DATA_TEST_FRAME failed")
2795
2796 def get_permanent_neighbors(ifname):
2797 cmd = subprocess.Popen(['ip', 'nei'], stdout=subprocess.PIPE)
2798 res = cmd.stdout.read()
2799 cmd.stdout.close()
2800 return [ line for line in res.splitlines() if "PERMANENT" in line and ifname in line ]
2801
2802 def _test_proxyarp_open(dev, apdev, params):
2803 cap_br = os.path.join(params['logdir'], "proxyarp_open.ap-br0.pcap")
2804 cap_dev0 = os.path.join(params['logdir'], "proxyarp_open.%s.pcap" % dev[0].ifname)
2805 cap_dev1 = os.path.join(params['logdir'], "proxyarp_open.%s.pcap" % dev[1].ifname)
2806
2807 bssid = apdev[0]['bssid']
2808 params = { 'ssid': 'open' }
2809 params['proxy_arp'] = '1'
2810 hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
2811 hapd.set("ap_isolate", "1")
2812 hapd.set('bridge', 'ap-br0')
2813 hapd.dump_monitor()
2814 try:
2815 hapd.enable()
2816 except:
2817 # For now, do not report failures due to missing kernel support
2818 logger.info("Could not start hostapd - assume proxyarp not supported in kernel version")
2819 return "skip"
2820 ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
2821 if ev is None:
2822 raise Exception("AP startup timed out")
2823 if "AP-ENABLED" not in ev:
2824 raise Exception("AP startup failed")
2825
2826 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
2827 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
2828
2829 for chain in [ 'FORWARD', 'OUTPUT' ]:
2830 subprocess.call(['ebtables', '-A', chain, '-p', 'ARP',
2831 '-d', 'Broadcast', '-o', apdev[0]['ifname'],
2832 '-j', 'DROP'])
2833 subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
2834 '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
2835 '--ip6-icmp-type', 'neighbor-solicitation',
2836 '-o', apdev[0]['ifname'], '-j', 'DROP'])
2837 subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
2838 '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
2839 '--ip6-icmp-type', 'neighbor-advertisement',
2840 '-o', apdev[0]['ifname'], '-j', 'DROP'])
2841 subprocess.call(['ebtables', '-A', chain,
2842 '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
2843 '--ip6-icmp-type', 'router-solicitation',
2844 '-o', apdev[0]['ifname'], '-j', 'DROP'])
2845 # Multicast Listener Report Message
2846 subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
2847 '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
2848 '--ip6-icmp-type', '143',
2849 '-o', apdev[0]['ifname'], '-j', 'DROP'])
2850
2851 cmd = {}
2852 cmd[0] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', 'ap-br0',
2853 '-w', cap_br, '-s', '2000'],
2854 stderr=open('/dev/null', 'w'))
2855 cmd[1] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[0].ifname,
2856 '-w', cap_dev0, '-s', '2000'],
2857 stderr=open('/dev/null', 'w'))
2858 cmd[2] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[1].ifname,
2859 '-w', cap_dev1, '-s', '2000'],
2860 stderr=open('/dev/null', 'w'))
2861
2862 dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
2863 dev[1].connect("open", key_mgmt="NONE", scan_freq="2412")
2864 time.sleep(0.1)
2865
2866 addr0 = dev[0].p2p_interface_addr()
2867 addr1 = dev[1].p2p_interface_addr()
2868
2869 src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':',''))
2870 src_ll_opt1 = "\x01\x01" + binascii.unhexlify(addr1.replace(':',''))
2871
2872 # DAD NS
2873 send_ns(dev[0], ip_src="::", target="aaaa:bbbb:cccc::2")
2874
2875 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2")
2876 # test frame without source link-layer address option
2877 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
2878 opt='')
2879 # test frame with bogus option
2880 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
2881 opt="\x70\x01\x01\x02\x03\x04\x05\x05")
2882 # test frame with truncated source link-layer address option
2883 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
2884 opt="\x01\x01\x01\x02\x03\x04")
2885 # test frame with foreign source link-layer address option
2886 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
2887 opt="\x01\x01\x01\x02\x03\x04\x05\x06")
2888
2889 send_ns(dev[1], ip_src="aaaa:bbbb:dddd::2", target="aaaa:bbbb:dddd::2")
2890
2891 send_ns(dev[1], ip_src="aaaa:bbbb:eeee::2", target="aaaa:bbbb:eeee::2")
2892 # another copy for additional code coverage
2893 send_ns(dev[1], ip_src="aaaa:bbbb:eeee::2", target="aaaa:bbbb:eeee::2")
2894
2895 pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
2896 ip_src="192.168.1.1", ip_dst="255.255.255.255",
2897 yiaddr="192.168.1.124", chaddr=addr0)
2898 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2899 raise Exception("DATA_TEST_FRAME failed")
2900 # Change address and verify unicast
2901 pkt = build_dhcp_ack(dst_ll=addr0, src_ll=bssid,
2902 ip_src="192.168.1.1", ip_dst="255.255.255.255",
2903 yiaddr="192.168.1.123", chaddr=addr0)
2904 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2905 raise Exception("DATA_TEST_FRAME failed")
2906
2907 # Not-associated client MAC address
2908 pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
2909 ip_src="192.168.1.1", ip_dst="255.255.255.255",
2910 yiaddr="192.168.1.125", chaddr="22:33:44:55:66:77")
2911 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2912 raise Exception("DATA_TEST_FRAME failed")
2913
2914 # No IP address
2915 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
2916 ip_src="192.168.1.1", ip_dst="255.255.255.255",
2917 yiaddr="0.0.0.0", chaddr=addr1)
2918 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2919 raise Exception("DATA_TEST_FRAME failed")
2920
2921 # Zero subnet mask
2922 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
2923 ip_src="192.168.1.1", ip_dst="255.255.255.255",
2924 yiaddr="192.168.1.126", chaddr=addr1,
2925 subnet_mask="0.0.0.0")
2926 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2927 raise Exception("DATA_TEST_FRAME failed")
2928
2929 # Truncated option
2930 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
2931 ip_src="192.168.1.1", ip_dst="255.255.255.255",
2932 yiaddr="192.168.1.127", chaddr=addr1,
2933 truncated_opt=True)
2934 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2935 raise Exception("DATA_TEST_FRAME failed")
2936
2937 # Wrong magic
2938 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
2939 ip_src="192.168.1.1", ip_dst="255.255.255.255",
2940 yiaddr="192.168.1.128", chaddr=addr1,
2941 wrong_magic=True)
2942 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2943 raise Exception("DATA_TEST_FRAME failed")
2944
2945 # Wrong IPv4 total length
2946 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
2947 ip_src="192.168.1.1", ip_dst="255.255.255.255",
2948 yiaddr="192.168.1.129", chaddr=addr1,
2949 force_tot_len=1000)
2950 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2951 raise Exception("DATA_TEST_FRAME failed")
2952
2953 # BOOTP
2954 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
2955 ip_src="192.168.1.1", ip_dst="255.255.255.255",
2956 yiaddr="192.168.1.129", chaddr=addr1,
2957 no_dhcp=True)
2958 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2959 raise Exception("DATA_TEST_FRAME failed")
2960
2961 matches = get_permanent_neighbors("ap-br0")
2962 logger.info("After connect: " + str(matches))
2963 if len(matches) != 4:
2964 raise Exception("Unexpected number of neighbor entries after connect")
2965 if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
2966 raise Exception("dev0 addr missing")
2967 if 'aaaa:bbbb:dddd::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
2968 raise Exception("dev1 addr(1) missing")
2969 if 'aaaa:bbbb:eeee::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
2970 raise Exception("dev1 addr(2) missing")
2971 if '192.168.1.123 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
2972 raise Exception("dev0 IPv4 addr missing")
2973
2974 targets = [ "192.168.1.123", "192.168.1.124", "192.168.1.125",
2975 "192.168.1.126" ]
2976 for target in targets:
2977 send_arp(dev[1], sender_ip="192.168.1.100", target_ip=target)
2978
2979 for target in targets:
2980 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.101",
2981 target_ip=target)
2982
2983 # ARP Probe from wireless STA
2984 send_arp(dev[1], target_ip="192.168.1.127")
2985 # ARP Announcement from wireless STA
2986 send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.127")
2987 send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.127",
2988 opcode=2)
2989
2990 matches = get_permanent_neighbors("ap-br0")
2991 logger.info("After ARP Probe + Announcement: " + str(matches))
2992
2993 # ARP Request for the newly introduced IP address from wireless STA
2994 send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.127")
2995
2996 # ARP Request for the newly introduced IP address from bridge
2997 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.102",
2998 target_ip="192.168.1.127")
2999
3000 # ARP Probe from bridge
3001 send_arp(hapd, hapd_bssid=bssid, target_ip="192.168.1.130")
3002 # ARP Announcement from bridge (not to be learned by AP for proxyarp)
3003 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.130",
3004 target_ip="192.168.1.130")
3005 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.130",
3006 target_ip="192.168.1.130", opcode=2)
3007
3008 matches = get_permanent_neighbors("ap-br0")
3009 logger.info("After ARP Probe + Announcement: " + str(matches))
3010
3011 # ARP Request for the newly introduced IP address from wireless STA
3012 send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.130")
3013 # ARP Response from bridge (AP does not proxy for non-wireless devices)
3014 send_arp(hapd, hapd_bssid=bssid, dst_ll=addr0, sender_ip="192.168.1.130",
3015 target_ip="192.168.1.123", opcode=2)
3016
3017 # ARP Request for the newly introduced IP address from bridge
3018 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.102",
3019 target_ip="192.168.1.130")
3020
3021 # ARP Probe from wireless STA (duplicate address; learned through DHCP)
3022 send_arp(dev[1], target_ip="192.168.1.123")
3023 # ARP Probe from wireless STA (duplicate address; learned through ARP)
3024 send_arp(dev[0], target_ip="192.168.1.127")
3025
3026 # Gratuitous ARP Reply for another STA's IP address
3027 send_arp(dev[0], opcode=2, sender_mac=addr0, sender_ip="192.168.1.127",
3028 target_mac=addr1, target_ip="192.168.1.127")
3029 send_arp(dev[1], opcode=2, sender_mac=addr1, sender_ip="192.168.1.123",
3030 target_mac=addr0, target_ip="192.168.1.123")
3031 # ARP Request to verify previous mapping
3032 send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.123")
3033 send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.127")
3034
3035 time.sleep(0.1)
3036
3037 send_ns(dev[0], target="aaaa:bbbb:dddd::2", ip_src="aaaa:bbbb:cccc::2")
3038 time.sleep(0.1)
3039 send_ns(dev[1], target="aaaa:bbbb:cccc::2", ip_src="aaaa:bbbb:dddd::2")
3040 time.sleep(0.1)
3041 send_ns(hapd, hapd_bssid=bssid, target="aaaa:bbbb:dddd::2",
3042 ip_src="aaaa:bbbb:ffff::2")
3043 time.sleep(0.1)
3044
3045 # Try to probe for an already assigned address
3046 send_ns(dev[1], target="aaaa:bbbb:cccc::2", ip_src="::")
3047 time.sleep(0.1)
3048 send_ns(hapd, hapd_bssid=bssid, target="aaaa:bbbb:cccc::2", ip_src="::")
3049 time.sleep(0.1)
3050
3051 # Unsolicited NA
3052 send_na(dev[1], target="aaaa:bbbb:cccc:aeae::3",
3053 ip_src="aaaa:bbbb:cccc:aeae::3", ip_dst="ff02::1")
3054 send_na(hapd, hapd_bssid=bssid, target="aaaa:bbbb:cccc:aeae::4",
3055 ip_src="aaaa:bbbb:cccc:aeae::4", ip_dst="ff02::1")
3056
3057 hwsim_utils.test_connectivity_iface(dev[0], hapd, "ap-br0")
3058 hwsim_utils.test_connectivity_iface(dev[1], hapd, "ap-br0")
3059 hwsim_utils.test_connectivity(dev[0], dev[1])
3060
3061 dev[0].request("DISCONNECT")
3062 dev[1].request("DISCONNECT")
3063 time.sleep(0.5)
3064 for i in range(3):
3065 cmd[i].terminate()
3066 matches = get_permanent_neighbors("ap-br0")
3067 logger.info("After disconnect: " + str(matches))
3068 if len(matches) > 0:
3069 raise Exception("Unexpected neighbor entries after disconnect")
3070 cmd = subprocess.Popen(['ebtables', '-L', '--Lc'], stdout=subprocess.PIPE)
3071 res = cmd.stdout.read()
3072 cmd.stdout.close()
3073 logger.info("ebtables results:\n" + res)
3074
3075 def test_proxyarp_open(dev, apdev, params):
3076 """ProxyARP with open network"""
3077 res = None
3078 try:
3079 res = _test_proxyarp_open(dev, apdev, params)
3080 finally:
3081 subprocess.call(['ebtables', '-F', 'FORWARD'])
3082 subprocess.call(['ebtables', '-F', 'OUTPUT'])
3083 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
3084 stderr=open('/dev/null', 'w'))
3085 subprocess.call(['brctl', 'delbr', 'ap-br0'],
3086 stderr=open('/dev/null', 'w'))
3087
3088 return res