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