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