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