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