668111f28882cd5534fa6ceac755aa2bde2004ec
[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_fetch_osu(dev, apdev):
2106     """Hotspot 2.0 OSU provider and icon fetch"""
2107     bssid = apdev[0]['bssid']
2108     params = hs20_ap_params()
2109     params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
2110     params['osu_ssid'] = '"HS 2.0 OSU open"'
2111     params['osu_method_list'] = "1"
2112     params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
2113     params['osu_icon'] = "w1fi_logo"
2114     params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
2115     params['osu_server_uri'] = "https://example.com/osu/"
2116     hostapd.add_ap(apdev[0]['ifname'], params)
2117
2118     bssid2 = apdev[1]['bssid']
2119     params = hs20_ap_params(ssid="test-hs20b")
2120     params['hessid'] = bssid2
2121     params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
2122     params['osu_ssid'] = '"HS 2.0 OSU OSEN"'
2123     params['osu_method_list'] = "0"
2124     params['osu_nai'] = "osen@example.com"
2125     params['osu_friendly_name'] = [ "eng:Test2 OSU", "fin:Testi2-OSU" ]
2126     params['osu_icon'] = "w1fi_logo"
2127     params['osu_service_desc'] = [ "eng:Example services2", "fin:Esimerkkipalveluja2" ]
2128     params['osu_server_uri'] = "https://example.org/osu/"
2129     hostapd.add_ap(apdev[1]['ifname'], params)
2130
2131     with open("w1fi_logo.png", "r") as f:
2132         orig_logo = f.read()
2133     dev[0].hs20_enable()
2134     dir = "/tmp/osu-fetch"
2135     if os.path.isdir(dir):
2136        files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
2137        for f in files:
2138            os.remove(dir + "/" + f)
2139     else:
2140         try:
2141             os.makedirs(dir)
2142         except:
2143             pass
2144     try:
2145         dev[1].scan_for_bss(bssid, freq="2412")
2146         dev[0].request("SET osu_dir " + dir)
2147         dev[0].request("FETCH_OSU")
2148         if "FAIL" not in dev[1].request("HS20_ICON_REQUEST foo w1fi_logo"):
2149             raise Exception("Invalid HS20_ICON_REQUEST accepted")
2150         if "OK" not in dev[1].request("HS20_ICON_REQUEST " + bssid + " w1fi_logo"):
2151             raise Exception("HS20_ICON_REQUEST failed")
2152         icons = 0
2153         while True:
2154             ev = dev[0].wait_event(["OSU provider fetch completed",
2155                                     "RX-HS20-ANQP-ICON"], timeout=15)
2156             if ev is None:
2157                 raise Exception("Timeout on OSU fetch")
2158             if "OSU provider fetch completed" in ev:
2159                 break
2160             if "RX-HS20-ANQP-ICON" in ev:
2161                 with open(ev.split(' ')[1], "r") as f:
2162                     logo = f.read()
2163                     if logo == orig_logo:
2164                         icons += 1
2165
2166         with open(dir + "/osu-providers.txt", "r") as f:
2167             prov = f.read()
2168             logger.debug("osu-providers.txt: " + prov)
2169         if "OSU-PROVIDER " + bssid not in prov:
2170             raise Exception("Missing OSU_PROVIDER(1)")
2171         if "OSU-PROVIDER " + bssid2 not in prov:
2172             raise Exception("Missing OSU_PROVIDER(2)")
2173     finally:
2174         files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
2175         for f in files:
2176             os.remove(dir + "/" + f)
2177         os.rmdir(dir)
2178
2179     if icons != 2:
2180         raise Exception("Unexpected number of icons fetched")
2181
2182     ev = dev[1].wait_event(["GAS-QUERY-START"], timeout=5)
2183     if ev is None:
2184         raise Exception("Timeout on GAS-QUERY-DONE")
2185     ev = dev[1].wait_event(["GAS-QUERY-DONE"], timeout=5)
2186     if ev is None:
2187         raise Exception("Timeout on GAS-QUERY-DONE")
2188     if "freq=2412 status_code=0 result=SUCCESS" not in ev:
2189         raise Exception("Unexpected GAS-QUERY-DONE: " + ev)
2190     ev = dev[1].wait_event(["RX-HS20-ANQP"], timeout=15)
2191     if ev is None:
2192         raise Exception("Timeout on icon fetch")
2193     if "Icon Binary File" not in ev:
2194         raise Exception("Unexpected ANQP element")
2195
2196 def test_ap_hs20_fetch_osu_stop(dev, apdev):
2197     """Hotspot 2.0 OSU provider fetch stopped"""
2198     bssid = apdev[0]['bssid']
2199     params = hs20_ap_params()
2200     params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
2201     params['osu_ssid'] = '"HS 2.0 OSU open"'
2202     params['osu_method_list'] = "1"
2203     params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
2204     params['osu_icon'] = "w1fi_logo"
2205     params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
2206     params['osu_server_uri'] = "https://example.com/osu/"
2207     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2208
2209     dev[0].hs20_enable()
2210     dir = "/tmp/osu-fetch"
2211     if os.path.isdir(dir):
2212        files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
2213        for f in files:
2214            os.remove(dir + "/" + f)
2215     else:
2216         try:
2217             os.makedirs(dir)
2218         except:
2219             pass
2220     try:
2221         dev[0].request("SET osu_dir " + dir)
2222         dev[0].request("SCAN freq=2412-2462")
2223         ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=10)
2224         if ev is None:
2225             raise Exception("Scan did not start")
2226         if "FAIL" not in dev[0].request("FETCH_OSU"):
2227             raise Exception("FETCH_OSU accepted while scanning")
2228         ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
2229         if ev is None:
2230             raise Exception("Scan timed out")
2231         hapd.set("ext_mgmt_frame_handling", "1")
2232         dev[0].request("FETCH_ANQP")
2233         if "FAIL" not in dev[0].request("FETCH_OSU"):
2234             raise Exception("FETCH_OSU accepted while in FETCH_ANQP")
2235         dev[0].request("STOP_FETCH_ANQP")
2236         dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5)
2237         dev[0].dump_monitor()
2238         hapd.dump_monitor()
2239         dev[0].request("INTERWORKING_SELECT freq=2412")
2240         for i in range(5):
2241             msg = hapd.mgmt_rx()
2242             if msg['subtype'] == 13:
2243                 break
2244         if "FAIL" not in dev[0].request("FETCH_OSU"):
2245             raise Exception("FETCH_OSU accepted while in INTERWORKING_SELECT")
2246         ev = dev[0].wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
2247                                timeout=15)
2248         if ev is None:
2249             raise Exception("Network selection timed out");
2250
2251         dev[0].dump_monitor()
2252         if "OK" not in dev[0].request("FETCH_OSU"):
2253             raise Exception("FETCH_OSU failed")
2254         dev[0].request("CANCEL_FETCH_OSU")
2255
2256         for i in range(15):
2257             time.sleep(0.5)
2258             if dev[0].get_driver_status_field("scan_state") == "SCAN_COMPLETED":
2259                 break
2260
2261         dev[0].dump_monitor()
2262         if "OK" not in dev[0].request("FETCH_OSU"):
2263             raise Exception("FETCH_OSU failed")
2264         if "FAIL" not in dev[0].request("FETCH_OSU"):
2265             raise Exception("FETCH_OSU accepted while in FETCH_OSU")
2266         ev = dev[0].wait_event(["GAS-QUERY-START"], 10)
2267         if ev is None:
2268             raise Exception("GAS timed out")
2269         if "FAIL" not in dev[0].request("FETCH_OSU"):
2270             raise Exception("FETCH_OSU accepted while in FETCH_OSU")
2271         dev[0].request("CANCEL_FETCH_OSU")
2272         ev = dev[0].wait_event(["GAS-QUERY-DONE"], 10)
2273         if ev is None:
2274             raise Exception("GAS event timed out after CANCEL_FETCH_OSU")
2275     finally:
2276         files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
2277         for f in files:
2278             os.remove(dir + "/" + f)
2279         os.rmdir(dir)
2280
2281 def test_ap_hs20_ft(dev, apdev):
2282     """Hotspot 2.0 connection with FT"""
2283     bssid = apdev[0]['bssid']
2284     params = hs20_ap_params()
2285     params['wpa_key_mgmt'] = "FT-EAP"
2286     params['nas_identifier'] = "nas1.w1.fi"
2287     params['r1_key_holder'] = "000102030405"
2288     params["mobility_domain"] = "a1b2"
2289     params["reassociation_deadline"] = "1000"
2290     hostapd.add_ap(apdev[0]['ifname'], params)
2291
2292     dev[0].hs20_enable()
2293     id = dev[0].add_cred_values({ 'realm': "example.com",
2294                                   'username': "hs20-test",
2295                                   'password': "password",
2296                                   'ca_cert': "auth_serv/ca.pem",
2297                                   'domain': "example.com",
2298                                   'update_identifier': "1234" })
2299     interworking_select(dev[0], bssid, "home", freq="2412")
2300     interworking_connect(dev[0], bssid, "TTLS")
2301
2302 def test_ap_hs20_remediation_sql(dev, apdev, params):
2303     """Hotspot 2.0 connection and remediation required using SQLite for user DB"""
2304     try:
2305         import sqlite3
2306     except ImportError:
2307         raise HwsimSkip("No sqlite3 module available")
2308     dbfile = os.path.join(params['logdir'], "eap-user.db")
2309     try:
2310         os.remove(dbfile)
2311     except:
2312         pass
2313     con = sqlite3.connect(dbfile)
2314     with con:
2315         cur = con.cursor()
2316         cur.execute("CREATE TABLE users(identity TEXT PRIMARY KEY, methods TEXT, password TEXT, remediation TEXT, phase2 INTEGER)")
2317         cur.execute("CREATE TABLE wildcards(identity TEXT PRIMARY KEY, methods TEXT)")
2318         cur.execute("INSERT INTO users(identity,methods,password,phase2,remediation) VALUES ('user-mschapv2','TTLS-MSCHAPV2','password',1,'user')")
2319         cur.execute("INSERT INTO wildcards(identity,methods) VALUES ('','TTLS,TLS')")
2320         cur.execute("CREATE TABLE authlog(timestamp TEXT, session TEXT, nas_ip TEXT, username TEXT, note TEXT)")
2321
2322     try:
2323         params = { "ssid": "as", "beacon_int": "2000",
2324                    "radius_server_clients": "auth_serv/radius_clients.conf",
2325                    "radius_server_auth_port": '18128',
2326                    "eap_server": "1",
2327                    "eap_user_file": "sqlite:" + dbfile,
2328                    "ca_cert": "auth_serv/ca.pem",
2329                    "server_cert": "auth_serv/server.pem",
2330                    "private_key": "auth_serv/server.key",
2331                    "subscr_remediation_url": "https://example.org/",
2332                    "subscr_remediation_method": "1" }
2333         hostapd.add_ap(apdev[1]['ifname'], params)
2334
2335         bssid = apdev[0]['bssid']
2336         params = hs20_ap_params()
2337         params['auth_server_port'] = "18128"
2338         hostapd.add_ap(apdev[0]['ifname'], params)
2339
2340         dev[0].request("SET pmf 1")
2341         dev[0].hs20_enable()
2342         id = dev[0].add_cred_values({ 'realm': "example.com",
2343                                       'username': "user-mschapv2",
2344                                       'password': "password",
2345                                       'ca_cert': "auth_serv/ca.pem" })
2346         interworking_select(dev[0], bssid, freq="2412")
2347         interworking_connect(dev[0], bssid, "TTLS")
2348         ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
2349         if ev is None:
2350             raise Exception("Timeout on subscription remediation notice")
2351         if " 1 https://example.org/" not in ev:
2352             raise Exception("Unexpected subscription remediation event contents")
2353
2354         with con:
2355             cur = con.cursor()
2356             cur.execute("SELECT * from authlog")
2357             rows = cur.fetchall()
2358             if len(rows) < 1:
2359                 raise Exception("No authlog entries")
2360
2361     finally:
2362         os.remove(dbfile)
2363         dev[0].request("SET pmf 0")
2364
2365 def test_ap_hs20_external_selection(dev, apdev):
2366     """Hotspot 2.0 connection using external network selection and creation"""
2367     bssid = apdev[0]['bssid']
2368     params = hs20_ap_params()
2369     params['hessid'] = bssid
2370     params['disable_dgaf'] = '1'
2371     hostapd.add_ap(apdev[0]['ifname'], params)
2372
2373     dev[0].hs20_enable()
2374     dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="TTLS",
2375                    identity="hs20-test", password="password",
2376                    ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
2377                    scan_freq="2412", update_identifier="54321")
2378     if dev[0].get_status_field("hs20") != "2":
2379         raise Exception("Unexpected hs20 indication")
2380
2381 def test_ap_hs20_random_mac_addr(dev, apdev):
2382     """Hotspot 2.0 connection with random MAC address"""
2383     bssid = apdev[0]['bssid']
2384     params = hs20_ap_params()
2385     params['hessid'] = bssid
2386     params['disable_dgaf'] = '1'
2387     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2388
2389     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
2390     wpas.interface_add("wlan5")
2391     addr = wpas.p2p_interface_addr()
2392     wpas.request("SET mac_addr 1")
2393     wpas.request("SET preassoc_mac_addr 1")
2394     wpas.request("SET rand_addr_lifetime 60")
2395     wpas.hs20_enable()
2396     wpas.flush_scan_cache()
2397     id = wpas.add_cred_values({ 'realm': "example.com",
2398                                   'username': "hs20-test",
2399                                   'password': "password",
2400                                   'ca_cert': "auth_serv/ca.pem",
2401                                   'domain': "example.com",
2402                                   'update_identifier': "1234" })
2403     interworking_select(wpas, bssid, "home", freq="2412")
2404     interworking_connect(wpas, bssid, "TTLS")
2405     addr1 = wpas.get_driver_status_field("addr")
2406     if addr == addr1:
2407         raise Exception("Did not use random MAC address")
2408
2409     sta = hapd.get_sta(addr)
2410     if sta['addr'] != "FAIL":
2411         raise Exception("Unexpected STA association with permanent address")
2412     sta = hapd.get_sta(addr1)
2413     if sta['addr'] != addr1:
2414         raise Exception("STA association with random address not found")
2415
2416 def test_ap_hs20_multi_network_and_cred_removal(dev, apdev):
2417     """Multiple networks and cred removal"""
2418     bssid = apdev[0]['bssid']
2419     params = hs20_ap_params()
2420     params['nai_realm'] = [ "0,example.com,25[3:26]"]
2421     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2422
2423     dev[0].add_network()
2424     dev[0].hs20_enable()
2425     id = dev[0].add_cred_values({ 'realm': "example.com",
2426                                   'username': "user",
2427                                   'password': "password" })
2428     interworking_select(dev[0], bssid, freq="2412")
2429     interworking_connect(dev[0], bssid, "PEAP")
2430     dev[0].add_network()
2431
2432     dev[0].request("DISCONNECT")
2433     dev[0].wait_disconnected(timeout=10)
2434
2435     hapd.disable()
2436     hapd.set("ssid", "another ssid")
2437     hapd.enable()
2438
2439     interworking_select(dev[0], bssid, freq="2412")
2440     interworking_connect(dev[0], bssid, "PEAP")
2441     dev[0].add_network()
2442     if len(dev[0].list_networks()) != 5:
2443         raise Exception("Unexpected number of networks prior to remove_crec")
2444
2445     dev[0].dump_monitor()
2446     dev[0].remove_cred(id)
2447     if len(dev[0].list_networks()) != 3:
2448         raise Exception("Unexpected number of networks after to remove_crec")
2449     dev[0].wait_disconnected(timeout=10)
2450
2451 def test_ap_hs20_interworking_add_network(dev, apdev):
2452     """Hotspot 2.0 connection using INTERWORKING_ADD_NETWORK"""
2453     bssid = apdev[0]['bssid']
2454     params = hs20_ap_params()
2455     params['nai_realm'] = [ "0,example.com,21[3:26][6:7][99:99]" ]
2456     hostapd.add_ap(apdev[0]['ifname'], params)
2457
2458     dev[0].hs20_enable()
2459     dev[0].add_cred_values(default_cred(user="user"))
2460     interworking_select(dev[0], bssid, freq=2412)
2461     id = dev[0].interworking_add_network(bssid)
2462     dev[0].select_network(id, freq=2412)
2463     dev[0].wait_connected()
2464
2465 def _test_ap_hs20_proxyarp(dev, apdev):
2466     bssid = apdev[0]['bssid']
2467     params = hs20_ap_params()
2468     params['hessid'] = bssid
2469     params['disable_dgaf'] = '0'
2470     params['proxy_arp'] = '1'
2471     hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
2472     if "OK" in hapd.request("ENABLE"):
2473         raise Exception("Incomplete hostapd configuration was accepted")
2474     hapd.set("ap_isolate", "1")
2475     if "OK" in hapd.request("ENABLE"):
2476         raise Exception("Incomplete hostapd configuration was accepted")
2477     hapd.set('bridge', 'ap-br0')
2478     hapd.dump_monitor()
2479     try:
2480         hapd.enable()
2481     except:
2482         # For now, do not report failures due to missing kernel support
2483         raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
2484     ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
2485     if ev is None:
2486         raise Exception("AP startup timed out")
2487     if "AP-ENABLED" not in ev:
2488         raise Exception("AP startup failed")
2489
2490     dev[0].hs20_enable()
2491     subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
2492     subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
2493
2494     id = dev[0].add_cred_values({ 'realm': "example.com",
2495                                   'username': "hs20-test",
2496                                   'password': "password",
2497                                   'ca_cert': "auth_serv/ca.pem",
2498                                   'domain': "example.com",
2499                                   'update_identifier': "1234" })
2500     interworking_select(dev[0], bssid, "home", freq="2412")
2501     interworking_connect(dev[0], bssid, "TTLS")
2502
2503     dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
2504                    identity="hs20-test", password="password",
2505                    ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
2506                    scan_freq="2412")
2507     time.sleep(0.1)
2508
2509     addr0 = dev[0].p2p_interface_addr()
2510     addr1 = dev[1].p2p_interface_addr()
2511
2512     src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':',''))
2513     src_ll_opt1 = "\x01\x01" + binascii.unhexlify(addr1.replace(':',''))
2514
2515     pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
2516                    ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
2517                    opt=src_ll_opt0)
2518     if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2519         raise Exception("DATA_TEST_FRAME failed")
2520
2521     pkt = build_ns(src_ll=addr1, ip_src="aaaa:bbbb:dddd::2",
2522                    ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:dddd::2",
2523                    opt=src_ll_opt1)
2524     if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2525         raise Exception("DATA_TEST_FRAME failed")
2526
2527     pkt = build_ns(src_ll=addr1, ip_src="aaaa:bbbb:eeee::2",
2528                    ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:eeee::2",
2529                    opt=src_ll_opt1)
2530     if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2531         raise Exception("DATA_TEST_FRAME failed")
2532
2533     matches = get_permanent_neighbors("ap-br0")
2534     logger.info("After connect: " + str(matches))
2535     if len(matches) != 3:
2536         raise Exception("Unexpected number of neighbor entries after connect")
2537     if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
2538         raise Exception("dev0 addr missing")
2539     if 'aaaa:bbbb:dddd::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
2540         raise Exception("dev1 addr(1) missing")
2541     if 'aaaa:bbbb:eeee::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
2542         raise Exception("dev1 addr(2) missing")
2543     dev[0].request("DISCONNECT")
2544     dev[1].request("DISCONNECT")
2545     time.sleep(0.5)
2546     matches = get_permanent_neighbors("ap-br0")
2547     logger.info("After disconnect: " + str(matches))
2548     if len(matches) > 0:
2549         raise Exception("Unexpected neighbor entries after disconnect")
2550
2551 def test_ap_hs20_hidden_ssid_in_scan_res(dev, apdev):
2552     """Hotspot 2.0 connection with hidden SSId in scan results"""
2553     bssid = apdev[0]['bssid']
2554
2555     hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": 'secret',
2556                                                 "ignore_broadcast_ssid": "1" })
2557     dev[0].scan_for_bss(bssid, freq=2412)
2558     hapd.disable()
2559     hapd_global = hostapd.HostapdGlobal()
2560     hapd_global.flush()
2561     hapd_global.remove(apdev[0]['ifname'])
2562
2563     params = hs20_ap_params()
2564     params['hessid'] = bssid
2565     hostapd.add_ap(apdev[0]['ifname'], params)
2566
2567     dev[0].hs20_enable()
2568     id = dev[0].add_cred_values({ 'realm': "example.com",
2569                                   'username': "hs20-test",
2570                                   'password': "password",
2571                                   'ca_cert': "auth_serv/ca.pem",
2572                                   'domain': "example.com" })
2573     interworking_select(dev[0], bssid, "home", freq="2412")
2574     interworking_connect(dev[0], bssid, "TTLS")
2575
2576     # clear BSS table to avoid issues in following test cases
2577     dev[0].request("DISCONNECT")
2578     dev[0].wait_disconnected()
2579     dev[0].flush_scan_cache()
2580
2581 def test_ap_hs20_proxyarp(dev, apdev):
2582     """Hotspot 2.0 and ProxyARP"""
2583     try:
2584         _test_ap_hs20_proxyarp(dev, apdev)
2585     finally:
2586         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
2587                         stderr=open('/dev/null', 'w'))
2588         subprocess.call(['brctl', 'delbr', 'ap-br0'],
2589                         stderr=open('/dev/null', 'w'))
2590
2591 def _test_ap_hs20_proxyarp_dgaf(dev, apdev, disabled):
2592     bssid = apdev[0]['bssid']
2593     params = hs20_ap_params()
2594     params['hessid'] = bssid
2595     params['disable_dgaf'] = '1' if disabled else '0'
2596     params['proxy_arp'] = '1'
2597     params['ap_isolate'] = '1'
2598     params['bridge'] = 'ap-br0'
2599     hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
2600     try:
2601         hapd.enable()
2602     except:
2603         # For now, do not report failures due to missing kernel support
2604         raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
2605     ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
2606     if ev is None:
2607         raise Exception("AP startup timed out")
2608
2609     dev[0].hs20_enable()
2610     subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
2611     subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
2612
2613     id = dev[0].add_cred_values({ 'realm': "example.com",
2614                                   'username': "hs20-test",
2615                                   'password': "password",
2616                                   'ca_cert': "auth_serv/ca.pem",
2617                                   'domain': "example.com",
2618                                   'update_identifier': "1234" })
2619     interworking_select(dev[0], bssid, "home", freq="2412")
2620     interworking_connect(dev[0], bssid, "TTLS")
2621
2622     dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
2623                    identity="hs20-test", password="password",
2624                    ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
2625                    scan_freq="2412")
2626     time.sleep(0.1)
2627
2628     addr0 = dev[0].p2p_interface_addr()
2629
2630     src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':',''))
2631
2632     pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
2633                    ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
2634                    opt=src_ll_opt0)
2635     if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2636         raise Exception("DATA_TEST_FRAME failed")
2637
2638     pkt = build_ra(src_ll=apdev[0]['bssid'], ip_src="aaaa:bbbb:cccc::33",
2639                    ip_dst="ff01::1")
2640     if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2641         raise Exception("DATA_TEST_FRAME failed")
2642
2643     pkt = build_na(src_ll=apdev[0]['bssid'], ip_src="aaaa:bbbb:cccc::44",
2644                    ip_dst="ff01::1", target="aaaa:bbbb:cccc::55")
2645     if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2646         raise Exception("DATA_TEST_FRAME failed")
2647
2648     pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
2649                          ip_src="192.168.1.1", ip_dst="255.255.255.255",
2650                          yiaddr="192.168.1.123", chaddr=addr0)
2651     if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2652         raise Exception("DATA_TEST_FRAME failed")
2653     # another copy for additional code coverage
2654     pkt = build_dhcp_ack(dst_ll=addr0, src_ll=bssid,
2655                          ip_src="192.168.1.1", ip_dst="255.255.255.255",
2656                          yiaddr="192.168.1.123", chaddr=addr0)
2657     if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2658         raise Exception("DATA_TEST_FRAME failed")
2659
2660     matches = get_permanent_neighbors("ap-br0")
2661     logger.info("After connect: " + str(matches))
2662     if len(matches) != 2:
2663         raise Exception("Unexpected number of neighbor entries after connect")
2664     if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
2665         raise Exception("dev0 addr missing")
2666     if '192.168.1.123 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
2667         raise Exception("dev0 IPv4 addr missing")
2668     dev[0].request("DISCONNECT")
2669     dev[1].request("DISCONNECT")
2670     time.sleep(0.5)
2671     matches = get_permanent_neighbors("ap-br0")
2672     logger.info("After disconnect: " + str(matches))
2673     if len(matches) > 0:
2674         raise Exception("Unexpected neighbor entries after disconnect")
2675
2676 def test_ap_hs20_proxyarp_disable_dgaf(dev, apdev):
2677     """Hotspot 2.0 and ProxyARP with DGAF disabled"""
2678     try:
2679         _test_ap_hs20_proxyarp_dgaf(dev, apdev, True)
2680     finally:
2681         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
2682                         stderr=open('/dev/null', 'w'))
2683         subprocess.call(['brctl', 'delbr', 'ap-br0'],
2684                         stderr=open('/dev/null', 'w'))
2685
2686 def test_ap_hs20_proxyarp_enable_dgaf(dev, apdev):
2687     """Hotspot 2.0 and ProxyARP with DGAF enabled"""
2688     try:
2689         _test_ap_hs20_proxyarp_dgaf(dev, apdev, False)
2690     finally:
2691         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
2692                         stderr=open('/dev/null', 'w'))
2693         subprocess.call(['brctl', 'delbr', 'ap-br0'],
2694                         stderr=open('/dev/null', 'w'))
2695
2696 def ip_checksum(buf):
2697     sum = 0
2698     if len(buf) & 0x01:
2699         buf += '\0x00'
2700     for i in range(0, len(buf), 2):
2701         val, = struct.unpack('H', buf[i:i+2])
2702         sum += val
2703     while (sum >> 16):
2704         sum = (sum & 0xffff) + (sum >> 16)
2705     return struct.pack('H', ~sum & 0xffff)
2706
2707 def ipv6_solicited_node_mcaddr(target):
2708     prefix = socket.inet_pton(socket.AF_INET6, "ff02::1:ff00:0")
2709     mask = socket.inet_pton(socket.AF_INET6, "::ff:ffff")
2710     _target = socket.inet_pton(socket.AF_INET6, target)
2711     p = struct.unpack('4I', prefix)
2712     m = struct.unpack('4I', mask)
2713     t = struct.unpack('4I', _target)
2714     res = (p[0] | (t[0] & m[0]),
2715            p[1] | (t[1] & m[1]),
2716            p[2] | (t[2] & m[2]),
2717            p[3] | (t[3] & m[3]))
2718     return socket.inet_ntop(socket.AF_INET6, struct.pack('4I', *res))
2719
2720 def build_icmpv6(ipv6_addrs, type, code, payload):
2721     start = struct.pack("BB", type, code)
2722     end = payload
2723     icmp = start + '\x00\x00' + end
2724     pseudo = ipv6_addrs + struct.pack(">LBBBB", len(icmp), 0, 0, 0, 58)
2725     csum = ip_checksum(pseudo + icmp)
2726     return start + csum + end
2727
2728 def build_ra(src_ll, ip_src, ip_dst, cur_hop_limit=0, router_lifetime=0,
2729              reachable_time=0, retrans_timer=0, opt=None):
2730     link_mc = binascii.unhexlify("3333ff000002")
2731     _src_ll = binascii.unhexlify(src_ll.replace(':',''))
2732     proto = '\x86\xdd'
2733     ehdr = link_mc + _src_ll + proto
2734     _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
2735     _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
2736
2737     adv = struct.pack('>BBHLL', cur_hop_limit, 0, router_lifetime,
2738                       reachable_time, retrans_timer)
2739     if opt:
2740         payload = adv + opt
2741     else:
2742         payload = adv
2743     icmp = build_icmpv6(_ip_src + _ip_dst, 134, 0, payload)
2744
2745     ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
2746     ipv6 += _ip_src + _ip_dst
2747
2748     return ehdr + ipv6 + icmp
2749
2750 def build_ns(src_ll, ip_src, ip_dst, target, 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     if ip_dst is None:
2757         ip_dst = ipv6_solicited_node_mcaddr(target)
2758     _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
2759
2760     reserved = '\x00\x00\x00\x00'
2761     _target = socket.inet_pton(socket.AF_INET6, target)
2762     if opt:
2763         payload = reserved + _target + opt
2764     else:
2765         payload = reserved + _target
2766     icmp = build_icmpv6(_ip_src + _ip_dst, 135, 0, payload)
2767
2768     ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
2769     ipv6 += _ip_src + _ip_dst
2770
2771     return ehdr + ipv6 + icmp
2772
2773 def send_ns(dev, src_ll=None, target=None, ip_src=None, ip_dst=None, opt=None,
2774             hapd_bssid=None):
2775     if hapd_bssid:
2776         if src_ll is None:
2777             src_ll = hapd_bssid
2778         cmd = "DATA_TEST_FRAME ifname=ap-br0 "
2779     else:
2780         if src_ll is None:
2781             src_ll = dev.p2p_interface_addr()
2782         cmd = "DATA_TEST_FRAME "
2783
2784     if opt is None:
2785         opt = "\x01\x01" + binascii.unhexlify(src_ll.replace(':',''))
2786
2787     pkt = build_ns(src_ll=src_ll, ip_src=ip_src, ip_dst=ip_dst, target=target,
2788                    opt=opt)
2789     if "OK" not in dev.request(cmd + binascii.hexlify(pkt)):
2790         raise Exception("DATA_TEST_FRAME failed")
2791
2792 def build_na(src_ll, ip_src, ip_dst, target, opt=None):
2793     link_mc = binascii.unhexlify("3333ff000002")
2794     _src_ll = binascii.unhexlify(src_ll.replace(':',''))
2795     proto = '\x86\xdd'
2796     ehdr = link_mc + _src_ll + proto
2797     _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
2798     _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
2799
2800     reserved = '\x00\x00\x00\x00'
2801     _target = socket.inet_pton(socket.AF_INET6, target)
2802     if opt:
2803         payload = reserved + _target + opt
2804     else:
2805         payload = reserved + _target
2806     icmp = build_icmpv6(_ip_src + _ip_dst, 136, 0, payload)
2807
2808     ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
2809     ipv6 += _ip_src + _ip_dst
2810
2811     return ehdr + ipv6 + icmp
2812
2813 def send_na(dev, src_ll=None, target=None, ip_src=None, ip_dst=None, opt=None,
2814             hapd_bssid=None):
2815     if hapd_bssid:
2816         if src_ll is None:
2817             src_ll = hapd_bssid
2818         cmd = "DATA_TEST_FRAME ifname=ap-br0 "
2819     else:
2820         if src_ll is None:
2821             src_ll = dev.p2p_interface_addr()
2822         cmd = "DATA_TEST_FRAME "
2823
2824     pkt = build_na(src_ll=src_ll, ip_src=ip_src, ip_dst=ip_dst, target=target,
2825                    opt=opt)
2826     if "OK" not in dev.request(cmd + binascii.hexlify(pkt)):
2827         raise Exception("DATA_TEST_FRAME failed")
2828
2829 def build_dhcp_ack(dst_ll, src_ll, ip_src, ip_dst, yiaddr, chaddr,
2830                    subnet_mask="255.255.255.0", truncated_opt=False,
2831                    wrong_magic=False, force_tot_len=None, no_dhcp=False):
2832     _dst_ll = binascii.unhexlify(dst_ll.replace(':',''))
2833     _src_ll = binascii.unhexlify(src_ll.replace(':',''))
2834     proto = '\x08\x00'
2835     ehdr = _dst_ll + _src_ll + proto
2836     _ip_src = socket.inet_pton(socket.AF_INET, ip_src)
2837     _ip_dst = socket.inet_pton(socket.AF_INET, ip_dst)
2838     _subnet_mask = socket.inet_pton(socket.AF_INET, subnet_mask)
2839
2840     _ciaddr = '\x00\x00\x00\x00'
2841     _yiaddr = socket.inet_pton(socket.AF_INET, yiaddr)
2842     _siaddr = '\x00\x00\x00\x00'
2843     _giaddr = '\x00\x00\x00\x00'
2844     _chaddr = binascii.unhexlify(chaddr.replace(':','') + "00000000000000000000")
2845     payload = struct.pack('>BBBBL3BB', 2, 1, 6, 0, 12345, 0, 0, 0, 0)
2846     payload += _ciaddr + _yiaddr + _siaddr + _giaddr + _chaddr + 192*'\x00'
2847     # magic
2848     if wrong_magic:
2849         payload += '\x63\x82\x53\x00'
2850     else:
2851         payload += '\x63\x82\x53\x63'
2852     if truncated_opt:
2853         payload += '\x22\xff\x00'
2854     # Option: DHCP Message Type = ACK
2855     payload += '\x35\x01\x05'
2856     # Pad Option
2857     payload += '\x00'
2858     # Option: Subnet Mask
2859     payload += '\x01\x04' + _subnet_mask
2860     # Option: Time Offset
2861     payload += struct.pack('>BBL', 2, 4, 0)
2862     # End Option
2863     payload += '\xff'
2864     # Pad Option
2865     payload += '\x00\x00\x00\x00'
2866
2867     if no_dhcp:
2868         payload = struct.pack('>BBBBL3BB', 2, 1, 6, 0, 12345, 0, 0, 0, 0)
2869         payload += _ciaddr + _yiaddr + _siaddr + _giaddr + _chaddr + 192*'\x00'
2870
2871     udp = struct.pack('>HHHH', 67, 68, 8 + len(payload), 0) + payload
2872
2873     if force_tot_len:
2874         tot_len = force_tot_len
2875     else:
2876         tot_len = 20 + len(udp)
2877     start = struct.pack('>BBHHBBBB', 0x45, 0, tot_len, 0, 0, 0, 128, 17)
2878     ipv4 = start + '\x00\x00' + _ip_src + _ip_dst
2879     csum = ip_checksum(ipv4)
2880     ipv4 = start + csum + _ip_src + _ip_dst
2881
2882     return ehdr + ipv4 + udp
2883
2884 def build_arp(dst_ll, src_ll, opcode, sender_mac, sender_ip,
2885               target_mac, target_ip):
2886     _dst_ll = binascii.unhexlify(dst_ll.replace(':',''))
2887     _src_ll = binascii.unhexlify(src_ll.replace(':',''))
2888     proto = '\x08\x06'
2889     ehdr = _dst_ll + _src_ll + proto
2890
2891     _sender_mac = binascii.unhexlify(sender_mac.replace(':',''))
2892     _sender_ip = socket.inet_pton(socket.AF_INET, sender_ip)
2893     _target_mac = binascii.unhexlify(target_mac.replace(':',''))
2894     _target_ip = socket.inet_pton(socket.AF_INET, target_ip)
2895
2896     arp = struct.pack('>HHBBH', 1, 0x0800, 6, 4, opcode)
2897     arp += _sender_mac + _sender_ip
2898     arp += _target_mac + _target_ip
2899
2900     return ehdr + arp
2901
2902 def send_arp(dev, dst_ll="ff:ff:ff:ff:ff:ff", src_ll=None, opcode=1,
2903              sender_mac=None, sender_ip="0.0.0.0",
2904              target_mac="00:00:00:00:00:00", target_ip="0.0.0.0",
2905              hapd_bssid=None):
2906     if hapd_bssid:
2907         if src_ll is None:
2908             src_ll = hapd_bssid
2909         if sender_mac is None:
2910             sender_mac = hapd_bssid
2911         cmd = "DATA_TEST_FRAME ifname=ap-br0 "
2912     else:
2913         if src_ll is None:
2914             src_ll = dev.p2p_interface_addr()
2915         if sender_mac is None:
2916             sender_mac = dev.p2p_interface_addr()
2917         cmd = "DATA_TEST_FRAME "
2918
2919     pkt = build_arp(dst_ll=dst_ll, src_ll=src_ll, opcode=opcode,
2920                     sender_mac=sender_mac, sender_ip=sender_ip,
2921                     target_mac=target_mac, target_ip=target_ip)
2922     if "OK" not in dev.request(cmd + binascii.hexlify(pkt)):
2923         raise Exception("DATA_TEST_FRAME failed")
2924
2925 def get_permanent_neighbors(ifname):
2926     cmd = subprocess.Popen(['ip', 'nei'], stdout=subprocess.PIPE)
2927     res = cmd.stdout.read()
2928     cmd.stdout.close()
2929     return [ line for line in res.splitlines() if "PERMANENT" in line and ifname in line ]
2930
2931 def get_bridge_macs(ifname):
2932     cmd = subprocess.Popen(['brctl', 'showmacs', ifname],
2933                            stdout=subprocess.PIPE)
2934     res = cmd.stdout.read()
2935     cmd.stdout.close()
2936     return res
2937
2938 def tshark_get_arp(cap, filter):
2939     res = run_tshark(cap, filter,
2940                      [ "eth.dst", "eth.src",
2941                        "arp.src.hw_mac", "arp.src.proto_ipv4",
2942                        "arp.dst.hw_mac", "arp.dst.proto_ipv4" ],
2943                      wait=False)
2944     frames = []
2945     for l in res.splitlines():
2946         frames.append(l.split('\t'))
2947     return frames
2948
2949 def tshark_get_ns(cap):
2950     res = run_tshark(cap, "icmpv6.type == 135",
2951                      [ "eth.dst", "eth.src",
2952                        "ipv6.src", "ipv6.dst",
2953                        "icmpv6.nd.ns.target_address",
2954                        "icmpv6.opt.linkaddr" ],
2955                      wait=False)
2956     frames = []
2957     for l in res.splitlines():
2958         frames.append(l.split('\t'))
2959     return frames
2960
2961 def tshark_get_na(cap):
2962     res = run_tshark(cap, "icmpv6.type == 136",
2963                      [ "eth.dst", "eth.src",
2964                        "ipv6.src", "ipv6.dst",
2965                        "icmpv6.nd.na.target_address",
2966                        "icmpv6.opt.linkaddr" ],
2967                      wait=False)
2968     frames = []
2969     for l in res.splitlines():
2970         frames.append(l.split('\t'))
2971     return frames
2972
2973 def _test_proxyarp_open(dev, apdev, params, ebtables=False):
2974     prefix = "proxyarp_open"
2975     if ebtables:
2976         prefix += "_ebtables"
2977     cap_br = os.path.join(params['logdir'], prefix + ".ap-br0.pcap")
2978     cap_dev0 = os.path.join(params['logdir'],
2979                             prefix + ".%s.pcap" % dev[0].ifname)
2980     cap_dev1 = os.path.join(params['logdir'],
2981                             prefix + ".%s.pcap" % dev[1].ifname)
2982     cap_dev2 = os.path.join(params['logdir'],
2983                             prefix + ".%s.pcap" % dev[2].ifname)
2984
2985     bssid = apdev[0]['bssid']
2986     params = { 'ssid': 'open' }
2987     params['proxy_arp'] = '1'
2988     hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
2989     hapd.set("ap_isolate", "1")
2990     hapd.set('bridge', 'ap-br0')
2991     hapd.dump_monitor()
2992     try:
2993         hapd.enable()
2994     except:
2995         # For now, do not report failures due to missing kernel support
2996         raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
2997     ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
2998     if ev is None:
2999         raise Exception("AP startup timed out")
3000     if "AP-ENABLED" not in ev:
3001         raise Exception("AP startup failed")
3002
3003     params2 = { 'ssid': 'another' }
3004     hapd2 = hostapd.add_ap(apdev[1]['ifname'], params2, no_enable=True)
3005     hapd2.set('bridge', 'ap-br0')
3006     hapd2.enable()
3007
3008     subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
3009     subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
3010
3011     if ebtables:
3012         for chain in [ 'FORWARD', 'OUTPUT' ]:
3013             subprocess.call(['ebtables', '-A', chain, '-p', 'ARP',
3014                              '-d', 'Broadcast', '-o', apdev[0]['ifname'],
3015                              '-j', 'DROP'])
3016             subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
3017                              '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
3018                              '--ip6-icmp-type', 'neighbor-solicitation',
3019                              '-o', apdev[0]['ifname'], '-j', 'DROP'])
3020             subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
3021                              '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
3022                              '--ip6-icmp-type', 'neighbor-advertisement',
3023                              '-o', apdev[0]['ifname'], '-j', 'DROP'])
3024             subprocess.call(['ebtables', '-A', chain,
3025                              '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
3026                              '--ip6-icmp-type', 'router-solicitation',
3027                              '-o', apdev[0]['ifname'], '-j', 'DROP'])
3028             # Multicast Listener Report Message
3029             subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
3030                              '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
3031                              '--ip6-icmp-type', '143',
3032                              '-o', apdev[0]['ifname'], '-j', 'DROP'])
3033
3034     time.sleep(0.5)
3035     cmd = {}
3036     cmd[0] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', 'ap-br0',
3037                                '-w', cap_br, '-s', '2000'],
3038                               stderr=open('/dev/null', 'w'))
3039     cmd[1] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[0].ifname,
3040                                '-w', cap_dev0, '-s', '2000'],
3041                               stderr=open('/dev/null', 'w'))
3042     cmd[2] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[1].ifname,
3043                                '-w', cap_dev1, '-s', '2000'],
3044                               stderr=open('/dev/null', 'w'))
3045     cmd[3] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[2].ifname,
3046                                '-w', cap_dev2, '-s', '2000'],
3047                               stderr=open('/dev/null', 'w'))
3048
3049     dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
3050     dev[1].connect("open", key_mgmt="NONE", scan_freq="2412")
3051     dev[2].connect("another", key_mgmt="NONE", scan_freq="2412")
3052     time.sleep(0.1)
3053
3054     brcmd = subprocess.Popen(['brctl', 'show'], stdout=subprocess.PIPE)
3055     res = brcmd.stdout.read()
3056     brcmd.stdout.close()
3057     logger.info("Bridge setup: " + res)
3058
3059     brcmd = subprocess.Popen(['brctl', 'showstp', 'ap-br0'],
3060                              stdout=subprocess.PIPE)
3061     res = brcmd.stdout.read()
3062     brcmd.stdout.close()
3063     logger.info("Bridge showstp: " + res)
3064
3065     addr0 = dev[0].p2p_interface_addr()
3066     addr1 = dev[1].p2p_interface_addr()
3067     addr2 = dev[2].p2p_interface_addr()
3068
3069     src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':',''))
3070     src_ll_opt1 = "\x01\x01" + binascii.unhexlify(addr1.replace(':',''))
3071
3072     # DAD NS
3073     send_ns(dev[0], ip_src="::", target="aaaa:bbbb:cccc::2")
3074
3075     send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2")
3076     # test frame without source link-layer address option
3077     send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
3078             opt='')
3079     # test frame with bogus option
3080     send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
3081             opt="\x70\x01\x01\x02\x03\x04\x05\x05")
3082     # test frame with truncated source link-layer address option
3083     send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
3084             opt="\x01\x01\x01\x02\x03\x04")
3085     # test frame with foreign source link-layer address option
3086     send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
3087             opt="\x01\x01\x01\x02\x03\x04\x05\x06")
3088
3089     send_ns(dev[1], ip_src="aaaa:bbbb:dddd::2", target="aaaa:bbbb:dddd::2")
3090
3091     send_ns(dev[1], ip_src="aaaa:bbbb:eeee::2", target="aaaa:bbbb:eeee::2")
3092     # another copy for additional code coverage
3093     send_ns(dev[1], ip_src="aaaa:bbbb:eeee::2", target="aaaa:bbbb:eeee::2")
3094
3095     pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
3096                          ip_src="192.168.1.1", ip_dst="255.255.255.255",
3097                          yiaddr="192.168.1.124", chaddr=addr0)
3098     if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
3099         raise Exception("DATA_TEST_FRAME failed")
3100     # Change address and verify unicast
3101     pkt = build_dhcp_ack(dst_ll=addr0, src_ll=bssid,
3102                          ip_src="192.168.1.1", ip_dst="255.255.255.255",
3103                          yiaddr="192.168.1.123", chaddr=addr0)
3104     if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
3105         raise Exception("DATA_TEST_FRAME failed")
3106
3107     # Not-associated client MAC address
3108     pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
3109                          ip_src="192.168.1.1", ip_dst="255.255.255.255",
3110                          yiaddr="192.168.1.125", chaddr="22:33:44:55:66:77")
3111     if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
3112         raise Exception("DATA_TEST_FRAME failed")
3113
3114     # No IP address
3115     pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
3116                          ip_src="192.168.1.1", ip_dst="255.255.255.255",
3117                          yiaddr="0.0.0.0", chaddr=addr1)
3118     if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
3119         raise Exception("DATA_TEST_FRAME failed")
3120
3121     # Zero subnet mask
3122     pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
3123                          ip_src="192.168.1.1", ip_dst="255.255.255.255",
3124                          yiaddr="192.168.1.126", chaddr=addr1,
3125                          subnet_mask="0.0.0.0")
3126     if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
3127         raise Exception("DATA_TEST_FRAME failed")
3128
3129     # Truncated option
3130     pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
3131                          ip_src="192.168.1.1", ip_dst="255.255.255.255",
3132                          yiaddr="192.168.1.127", chaddr=addr1,
3133                          truncated_opt=True)
3134     if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
3135         raise Exception("DATA_TEST_FRAME failed")
3136
3137     # Wrong magic
3138     pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
3139                          ip_src="192.168.1.1", ip_dst="255.255.255.255",
3140                          yiaddr="192.168.1.128", chaddr=addr1,
3141                          wrong_magic=True)
3142     if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
3143         raise Exception("DATA_TEST_FRAME failed")
3144
3145     # Wrong IPv4 total length
3146     pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
3147                          ip_src="192.168.1.1", ip_dst="255.255.255.255",
3148                          yiaddr="192.168.1.129", chaddr=addr1,
3149                          force_tot_len=1000)
3150     if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
3151         raise Exception("DATA_TEST_FRAME failed")
3152
3153     # BOOTP
3154     pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
3155                          ip_src="192.168.1.1", ip_dst="255.255.255.255",
3156                          yiaddr="192.168.1.129", chaddr=addr1,
3157                          no_dhcp=True)
3158     if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
3159         raise Exception("DATA_TEST_FRAME failed")
3160
3161     macs = get_bridge_macs("ap-br0")
3162     logger.info("After connect (showmacs): " + str(macs))
3163
3164     matches = get_permanent_neighbors("ap-br0")
3165     logger.info("After connect: " + str(matches))
3166     if len(matches) != 4:
3167         raise Exception("Unexpected number of neighbor entries after connect")
3168     if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
3169         raise Exception("dev0 addr missing")
3170     if 'aaaa:bbbb:dddd::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
3171         raise Exception("dev1 addr(1) missing")
3172     if 'aaaa:bbbb:eeee::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
3173         raise Exception("dev1 addr(2) missing")
3174     if '192.168.1.123 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
3175         raise Exception("dev0 IPv4 addr missing")
3176
3177     targets = [ "192.168.1.123", "192.168.1.124", "192.168.1.125",
3178                 "192.168.1.126" ]
3179     for target in targets:
3180         send_arp(dev[1], sender_ip="192.168.1.100", target_ip=target)
3181
3182     for target in targets:
3183         send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.101",
3184                  target_ip=target)
3185
3186     for target in targets:
3187         send_arp(dev[2], sender_ip="192.168.1.103", target_ip=target)
3188
3189     # ARP Probe from wireless STA
3190     send_arp(dev[1], target_ip="192.168.1.127")
3191     # ARP Announcement from wireless STA
3192     send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.127")
3193     send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.127",
3194              opcode=2)
3195
3196     macs = get_bridge_macs("ap-br0")
3197     logger.info("After ARP Probe + Announcement (showmacs): " + str(macs))
3198
3199     matches = get_permanent_neighbors("ap-br0")
3200     logger.info("After ARP Probe + Announcement: " + str(matches))
3201
3202     # ARP Request for the newly introduced IP address from wireless STA
3203     send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.127")
3204
3205     # ARP Request for the newly introduced IP address from bridge
3206     send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.102",
3207              target_ip="192.168.1.127")
3208     send_arp(dev[2], sender_ip="192.168.1.103", target_ip="192.168.1.127")
3209
3210     # ARP Probe from bridge
3211     send_arp(hapd, hapd_bssid=bssid, target_ip="192.168.1.130")
3212     send_arp(dev[2], target_ip="192.168.1.131")
3213     # ARP Announcement from bridge (not to be learned by AP for proxyarp)
3214     send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.130",
3215              target_ip="192.168.1.130")
3216     send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.130",
3217              target_ip="192.168.1.130", opcode=2)
3218     send_arp(dev[2], sender_ip="192.168.1.131", target_ip="192.168.1.131")
3219     send_arp(dev[2], sender_ip="192.168.1.131", target_ip="192.168.1.131",
3220              opcode=2)
3221
3222     macs = get_bridge_macs("ap-br0")
3223     logger.info("After ARP Probe + Announcement (showmacs): " + str(macs))
3224
3225     matches = get_permanent_neighbors("ap-br0")
3226     logger.info("After ARP Probe + Announcement: " + str(matches))
3227
3228     # ARP Request for the newly introduced IP address from wireless STA
3229     send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.130")
3230     # ARP Response from bridge (AP does not proxy for non-wireless devices)
3231     send_arp(hapd, hapd_bssid=bssid, dst_ll=addr0, sender_ip="192.168.1.130",
3232              target_ip="192.168.1.123", opcode=2)
3233
3234     # ARP Request for the newly introduced IP address from wireless STA
3235     send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.131")
3236     # ARP Response from bridge (AP does not proxy for non-wireless devices)
3237     send_arp(dev[2], dst_ll=addr0, sender_ip="192.168.1.131",
3238              target_ip="192.168.1.123", opcode=2)
3239
3240     # ARP Request for the newly introduced IP address from bridge
3241     send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.102",
3242              target_ip="192.168.1.130")
3243     send_arp(dev[2], sender_ip="192.168.1.104", target_ip="192.168.1.131")
3244
3245     # ARP Probe from wireless STA (duplicate address; learned through DHCP)
3246     send_arp(dev[1], target_ip="192.168.1.123")
3247     # ARP Probe from wireless STA (duplicate address; learned through ARP)
3248     send_arp(dev[0], target_ip="192.168.1.127")
3249
3250     # Gratuitous ARP Reply for another STA's IP address
3251     send_arp(dev[0], opcode=2, sender_mac=addr0, sender_ip="192.168.1.127",
3252              target_mac=addr1, target_ip="192.168.1.127")
3253     send_arp(dev[1], opcode=2, sender_mac=addr1, sender_ip="192.168.1.123",
3254              target_mac=addr0, target_ip="192.168.1.123")
3255     # ARP Request to verify previous mapping
3256     send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.123")
3257     send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.127")
3258
3259     time.sleep(0.1)
3260
3261     send_ns(dev[0], target="aaaa:bbbb:dddd::2", ip_src="aaaa:bbbb:cccc::2")
3262     time.sleep(0.1)
3263     send_ns(dev[1], target="aaaa:bbbb:cccc::2", ip_src="aaaa:bbbb:dddd::2")
3264     time.sleep(0.1)
3265     send_ns(hapd, hapd_bssid=bssid, target="aaaa:bbbb:dddd::2",
3266             ip_src="aaaa:bbbb:ffff::2")
3267     time.sleep(0.1)
3268     send_ns(dev[2], target="aaaa:bbbb:cccc::2", ip_src="aaaa:bbbb:ff00::2")
3269     time.sleep(0.1)
3270     send_ns(dev[2], target="aaaa:bbbb:dddd::2", ip_src="aaaa:bbbb:ff00::2")
3271     time.sleep(0.1)
3272     send_ns(dev[2], target="aaaa:bbbb:eeee::2", ip_src="aaaa:bbbb:ff00::2")
3273     time.sleep(0.1)
3274
3275     # Try to probe for an already assigned address
3276     send_ns(dev[1], target="aaaa:bbbb:cccc::2", ip_src="::")
3277     time.sleep(0.1)
3278     send_ns(hapd, hapd_bssid=bssid, target="aaaa:bbbb:cccc::2", ip_src="::")
3279     time.sleep(0.1)
3280     send_ns(dev[2], target="aaaa:bbbb:cccc::2", ip_src="::")
3281     time.sleep(0.1)
3282
3283     # Unsolicited NA
3284     send_na(dev[1], target="aaaa:bbbb:cccc:aeae::3",
3285             ip_src="aaaa:bbbb:cccc:aeae::3", ip_dst="ff02::1")
3286     send_na(hapd, hapd_bssid=bssid, target="aaaa:bbbb:cccc:aeae::4",
3287             ip_src="aaaa:bbbb:cccc:aeae::4", ip_dst="ff02::1")
3288     send_na(dev[2], target="aaaa:bbbb:cccc:aeae::5",
3289             ip_src="aaaa:bbbb:cccc:aeae::5", ip_dst="ff02::1")
3290
3291     try:
3292         hwsim_utils.test_connectivity_iface(dev[0], hapd, "ap-br0")
3293     except Exception, e:
3294         logger.info("test_connectibity_iface failed: " + str(e))
3295         raise HwsimSkip("Assume kernel did not have the required patches for proxyarp")
3296     hwsim_utils.test_connectivity_iface(dev[1], hapd, "ap-br0")
3297     hwsim_utils.test_connectivity(dev[0], dev[1])
3298
3299     dev[0].request("DISCONNECT")
3300     dev[1].request("DISCONNECT")
3301     time.sleep(0.5)
3302     for i in range(len(cmd)):
3303         cmd[i].terminate()
3304     macs = get_bridge_macs("ap-br0")
3305     logger.info("After disconnect (showmacs): " + str(macs))
3306     matches = get_permanent_neighbors("ap-br0")
3307     logger.info("After disconnect: " + str(matches))
3308     if len(matches) > 0:
3309         raise Exception("Unexpected neighbor entries after disconnect")
3310     if ebtables:
3311         cmd = subprocess.Popen(['ebtables', '-L', '--Lc'],
3312                                stdout=subprocess.PIPE)
3313         res = cmd.stdout.read()
3314         cmd.stdout.close()
3315         logger.info("ebtables results:\n" + res)
3316
3317     # Verify that expected ARP messages were seen and no unexpected
3318     # ARP messages were seen.
3319
3320     arp_req = tshark_get_arp(cap_dev0, "arp.opcode == 1")
3321     arp_reply = tshark_get_arp(cap_dev0, "arp.opcode == 2")
3322     logger.info("dev0 seen ARP requests:\n" + str(arp_req))
3323     logger.info("dev0 seen ARP replies:\n" + str(arp_reply))
3324
3325     if [ 'ff:ff:ff:ff:ff:ff', addr1,
3326          addr1, '192.168.1.100',
3327          '00:00:00:00:00:00', '192.168.1.123' ] in arp_req:
3328         raise Exception("dev0 saw ARP request from dev1")
3329     if [ 'ff:ff:ff:ff:ff:ff', addr2,
3330          addr2, '192.168.1.103',
3331          '00:00:00:00:00:00', '192.168.1.123' ] in arp_req:
3332         raise Exception("dev0 saw ARP request from dev2")
3333     # TODO: Uncomment once fixed in kernel
3334     #if [ 'ff:ff:ff:ff:ff:ff', bssid,
3335     #     bssid, '192.168.1.101',
3336     #     '00:00:00:00:00:00', '192.168.1.123' ] in arp_req:
3337     #    raise Exception("dev0 saw ARP request from br")
3338
3339     if ebtables:
3340         for req in arp_req:
3341             if req[1] != addr0:
3342                 raise Exception("Unexpected foreign ARP request on dev0")
3343
3344     arp_req = tshark_get_arp(cap_dev1, "arp.opcode == 1")
3345     arp_reply = tshark_get_arp(cap_dev1, "arp.opcode == 2")
3346     logger.info("dev1 seen ARP requests:\n" + str(arp_req))
3347     logger.info("dev1 seen ARP replies:\n" + str(arp_reply))
3348
3349     if [ 'ff:ff:ff:ff:ff:ff', addr2,
3350          addr2, '192.168.1.103',
3351          '00:00:00:00:00:00', '192.168.1.123' ] in arp_req:
3352         raise Exception("dev1 saw ARP request from dev2")
3353     if [addr1, addr0, addr0, '192.168.1.123', addr1, '192.168.1.100'] not in arp_reply:
3354         raise Exception("dev1 did not get ARP response for 192.168.1.123")
3355
3356     if ebtables:
3357         for req in arp_req:
3358             if req[1] != addr1:
3359                 raise Exception("Unexpected foreign ARP request on dev1")
3360
3361     arp_req = tshark_get_arp(cap_dev2, "arp.opcode == 1")
3362     arp_reply = tshark_get_arp(cap_dev2, "arp.opcode == 2")
3363     logger.info("dev2 seen ARP requests:\n" + str(arp_req))
3364     logger.info("dev2 seen ARP replies:\n" + str(arp_reply))
3365
3366     if [ addr2, addr0,
3367          addr0, '192.168.1.123',
3368          addr2, '192.168.1.103' ] not in arp_reply:
3369         raise Exception("dev2 did not get ARP response for 192.168.1.123")
3370
3371     arp_req = tshark_get_arp(cap_br, "arp.opcode == 1")
3372     arp_reply = tshark_get_arp(cap_br, "arp.opcode == 2")
3373     logger.info("br seen ARP requests:\n" + str(arp_req))
3374     logger.info("br seen ARP replies:\n" + str(arp_reply))
3375
3376     # TODO: Uncomment once fixed in kernel
3377     #if [ bssid, addr0,
3378     #     addr0, '192.168.1.123',
3379     #     bssid, '192.168.1.101' ] not in arp_reply:
3380     #    raise Exception("br did not get ARP response for 192.168.1.123")
3381
3382     ns = tshark_get_ns(cap_dev0)
3383     logger.info("dev0 seen NS: " + str(ns))
3384     na = tshark_get_na(cap_dev0)
3385     logger.info("dev0 seen NA: " + str(na))
3386
3387     # FIX: src mac addr is supposed to be addr1, not bssid
3388     if [ addr0, bssid, 'aaaa:bbbb:dddd::2', 'aaaa:bbbb:cccc::2',
3389          'aaaa:bbbb:dddd::2', addr1 ] not in na:
3390         raise Exception("dev0 did not get NA for aaaa:bbbb:dddd::2")
3391
3392     if ebtables:
3393         for req in ns:
3394             if req[1] != addr0:
3395                 raise Exception("Unexpected foreign NS on dev0: " + str(req))
3396
3397     ns = tshark_get_ns(cap_dev1)
3398     logger.info("dev1 seen NS: " + str(ns))
3399     na = tshark_get_na(cap_dev1)
3400     logger.info("dev1 seen NA: " + str(na))
3401
3402     # FIX: src mac addr is supposed to be addr0, not bssid
3403     if [ addr1, bssid, 'aaaa:bbbb:cccc::2', 'aaaa:bbbb:dddd::2',
3404          'aaaa:bbbb:cccc::2', addr0 ] not in na:
3405         raise Exception("dev1 did not get NA for aaaa:bbbb:cccc::2")
3406
3407     if ebtables:
3408         for req in ns:
3409             if req[1] != addr1:
3410                 raise Exception("Unexpected foreign NS on dev1: " + str(req))
3411
3412     ns = tshark_get_ns(cap_dev2)
3413     logger.info("dev2 seen NS: " + str(ns))
3414     na = tshark_get_na(cap_dev2)
3415     logger.info("dev2 seen NA: " + str(na))
3416
3417     # FIX: enable once kernel implementation for proxyarp IPv6 is fixed
3418     # FIX: src mac addr is supposed to be addr0/addr1, not bssid
3419     #if [ addr2, bssid, 'aaaa:bbbb:cccc::2', 'aaaa:bbbb:ff00::2',
3420     #     'aaaa:bbbb:cccc::2', addr0 ] not in na:
3421     #    raise Exception("dev2 did not get NA for aaaa:bbbb:cccc::2")
3422     #if [ addr2, bssid, 'aaaa:bbbb:dddd::2', 'aaaa:bbbb:ff00::2',
3423     #     'aaaa:bbbb:dddd::2', addr1 ] not in na:
3424     #    raise Exception("dev2 did not get NA for aaaa:bbbb:dddd::2")
3425     #if [ addr2, bssid, 'aaaa:bbbb:eeee::2', 'aaaa:bbbb:ff00::2',
3426     #     'aaaa:bbbb:eeee::2', addr1 ] not in na:
3427     #    raise Exception("dev2 did not get NA for aaaa:bbbb:eeee::2")
3428
3429 def test_proxyarp_open(dev, apdev, params):
3430     """ProxyARP with open network"""
3431     try:
3432         _test_proxyarp_open(dev, apdev, params)
3433     finally:
3434         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
3435                         stderr=open('/dev/null', 'w'))
3436         subprocess.call(['brctl', 'delbr', 'ap-br0'],
3437                         stderr=open('/dev/null', 'w'))
3438
3439 def test_proxyarp_open_ebtables(dev, apdev, params):
3440     """ProxyARP with open network"""
3441     try:
3442         _test_proxyarp_open(dev, apdev, params, ebtables=True)
3443     finally:
3444         try:
3445             subprocess.call(['ebtables', '-F', 'FORWARD'])
3446             subprocess.call(['ebtables', '-F', 'OUTPUT'])
3447         except:
3448             pass
3449         subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
3450                         stderr=open('/dev/null', 'w'))
3451         subprocess.call(['brctl', 'delbr', 'ap-br0'],
3452                         stderr=open('/dev/null', 'w'))