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