1 # GAS tests
2 # Copyright (c) 2013, Qualcomm Atheros, Inc.
3 # Copyright (c) 2013-2015, Jouni Malinen <j@w1.fi>
4 #
5 # This software may be distributed under the terms of the BSD license.
6 # See README for more details.
7 
8 from remotehost import remote_compatible
9 import time
10 import binascii
11 import logging
12 logger = logging.getLogger()
13 import os
14 import re
15 import struct
16 
17 import hostapd
18 from wpasupplicant import WpaSupplicant
19 from tshark import run_tshark
20 from utils import *
21 from hwsim import HWSimRadio
22 
23 def hs20_ap_params():
24     params = hostapd.wpa2_params(ssid="test-gas")
25     params['wpa_key_mgmt'] = "WPA-EAP"
26     params['ieee80211w'] = "1"
27     params['ieee8021x'] = "1"
28     params['auth_server_addr'] = "127.0.0.1"
29     params['auth_server_port'] = "1812"
30     params['auth_server_shared_secret'] = "radius"
31     params['interworking'] = "1"
32     params['access_network_type'] = "14"
33     params['internet'] = "1"
34     params['asra'] = "0"
35     params['esr'] = "0"
36     params['uesa'] = "0"
37     params['venue_group'] = "7"
38     params['venue_type'] = "1"
39     params['venue_name'] = ["eng:Example venue", "fin:Esimerkkipaikka"]
40     params['roaming_consortium'] = ["112233", "1020304050", "010203040506",
41                                     "fedcba"]
42     params['domain_name'] = "example.com,another.example.com"
43     params['nai_realm'] = ["0,example.com,13[5:6],21[2:4][5:7]",
44                            "0,another.example.com"]
45     params['anqp_3gpp_cell_net'] = "244,91"
46     params['network_auth_type'] = "02http://www.example.com/redirect/me/here/"
47     params['ipaddr_type_availability'] = "14"
48     params['hs20'] = "1"
49     params['hs20_oper_friendly_name'] = ["eng:Example operator", "fin:Esimerkkioperaattori"]
50     params['hs20_wan_metrics'] = "01:8000:1000:80:240:3000"
51     params['hs20_conn_capab'] = ["1:0:2", "6:22:1", "17:5060:0"]
52     params['hs20_operating_class'] = "5173"
53     return params
54 
55 def start_ap(ap):
56     params = hs20_ap_params()
57     params['hessid'] = ap['bssid']
58     return hostapd.add_ap(ap, params)
59 
60 def get_gas_response(dev, bssid, info, allow_fetch_failure=False,
61                      extra_test=False):
62     exp = r'<.>(GAS-RESPONSE-INFO) addr=([0-9a-f:]*) dialog_token=([0-9]*) status_code=([0-9]*) resp_len=([\-0-9]*)'
63     res = re.split(exp, info)
64     if len(res) < 6:
65         raise Exception("Could not parse GAS-RESPONSE-INFO")
66     if res[2] != bssid:
67         raise Exception("Unexpected BSSID in response")
68     token = res[3]
69     status = res[4]
70     if status != "0":
71         raise Exception("GAS query failed")
72     resp_len = res[5]
73     if resp_len == "-1":
74         raise Exception("GAS query reported invalid response length")
75     if int(resp_len) > 2000:
76         raise Exception("Unexpected long GAS response")
77 
78     if extra_test:
79         if "FAIL" not in dev.request("GAS_RESPONSE_GET " + bssid + " 123456"):
80             raise Exception("Invalid dialog token accepted")
81         if "FAIL-Invalid range" not in dev.request("GAS_RESPONSE_GET " + bssid + " " + token + " 10000,10001"):
82             raise Exception("Invalid range accepted")
83         if "FAIL-Invalid range" not in dev.request("GAS_RESPONSE_GET " + bssid + " " + token + " 0,10000"):
84             raise Exception("Invalid range accepted")
85         if "FAIL" not in dev.request("GAS_RESPONSE_GET " + bssid + " " + token + " 0"):
86             raise Exception("Invalid GAS_RESPONSE_GET accepted")
87 
88         res1_2 = dev.request("GAS_RESPONSE_GET " + bssid + " " + token + " 1,2")
89         res5_3 = dev.request("GAS_RESPONSE_GET " + bssid + " " + token + " 5,3")
90 
91     resp = dev.request("GAS_RESPONSE_GET " + bssid + " " + token)
92     if "FAIL" in resp:
93         if allow_fetch_failure:
94             logger.debug("GAS response was not available anymore")
95             return
96         raise Exception("Could not fetch GAS response")
97     if len(resp) != int(resp_len) * 2:
98         raise Exception("Unexpected GAS response length")
99     logger.debug("GAS response: " + resp)
100     if extra_test:
101         if resp[2:6] != res1_2:
102             raise Exception("Unexpected response substring res1_2: " + res1_2)
103         if resp[10:16] != res5_3:
104             raise Exception("Unexpected response substring res5_3: " + res5_3)
105 
106 def test_gas_generic(dev, apdev):
107     """Generic GAS query"""
108     bssid = apdev[0]['bssid']
109     params = hs20_ap_params()
110     params['hessid'] = bssid
111     hostapd.add_ap(apdev[0], params)
112 
113     cmds = ["foo",
114             "00:11:22:33:44:55",
115             "00:11:22:33:44:55 ",
116             "00:11:22:33:44:55  ",
117             "00:11:22:33:44:55 1",
118             "00:11:22:33:44:55 1 1234",
119             "00:11:22:33:44:55 qq",
120             "00:11:22:33:44:55 qq 1234",
121             "00:11:22:33:44:55 00      1",
122             "00:11:22:33:44:55 00 123",
123             "00:11:22:33:44:55 00 ",
124             "00:11:22:33:44:55 00 qq"]
125     for cmd in cmds:
126         if "FAIL" not in dev[0].request("GAS_REQUEST " + cmd):
127             raise Exception("Invalid GAS_REQUEST accepted: " + cmd)
128 
129     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
130     req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000101")
131     if "FAIL" in req:
132         raise Exception("GAS query request rejected")
133     ev = dev[0].wait_event(["GAS-RESPONSE-INFO"], timeout=10)
134     if ev is None:
135         raise Exception("GAS query timed out")
136     get_gas_response(dev[0], bssid, ev, extra_test=True)
137 
138     if "FAIL" not in dev[0].request("GAS_RESPONSE_GET ff"):
139         raise Exception("Invalid GAS_RESPONSE_GET accepted")
140 
141 def test_gas_rand_ta(dev, apdev, params):
142     """Generic GAS query with random TA"""
143     flags = int(dev[0].get_driver_status_field('capa.flags'), 16)
144     if flags & 0x0000400000000000 == 0:
145         raise HwsimSkip("Driver does not support random GAS TA")
146 
147     try:
148         _test_gas_rand_ta(dev, apdev, params['logdir'])
149     finally:
150         dev[0].request("SET gas_rand_mac_addr 0")
151 
152 def _test_gas_rand_ta(dev, apdev, logdir):
153     bssid = apdev[0]['bssid']
154     params = hs20_ap_params()
155     params['hessid'] = bssid
156     hostapd.add_ap(apdev[0], params)
157 
158     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
159     req = dev[0].request("SET gas_rand_mac_addr 1")
160     if "FAIL" in req:
161         raise Exception("Failed to set gas_rand_mac_addr")
162 
163     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
164     req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000101")
165     if "FAIL" in req:
166         raise Exception("GAS query request rejected")
167     ev = dev[0].wait_event(["GAS-RESPONSE-INFO"], timeout=10)
168     if ev is None:
169         raise Exception("GAS query timed out")
170     get_gas_response(dev[0], bssid, ev, extra_test=True)
171 
172     time.sleep(1)
173     out = run_tshark(os.path.join(logdir, "hwsim0.pcapng"),
174                      "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)",
175                      display=["wlan.ta", "wlan.ra"])
176     logger.info("tshark output:\n" + out)
177     res = out.splitlines()
178     if len(res) != 2:
179         logger.info("res: " + str(res))
180         raise Exception("Unexpected number of GAS frames")
181     req_ta = res[0].split('\t')[0]
182     resp_ra = res[1].split('\t')[1]
183     logger.info("Request TA: %s, Response RA: %s" % (req_ta, resp_ra))
184     if req_ta != resp_ra:
185         raise Exception("Request TA does not match response RA")
186     if req_ta == dev[0].own_addr():
187         raise Exception("Request TA was own permanent MAC address, not random")
188 
189 def test_gas_concurrent_scan(dev, apdev):
190     """Generic GAS queries with concurrent scan operation"""
191     bssid = apdev[0]['bssid']
192     params = hs20_ap_params()
193     params['hessid'] = bssid
194     hapd = hostapd.add_ap(apdev[0], params)
195 
196     # get BSS entry available to allow GAS query
197     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
198 
199     logger.info("Request concurrent operations")
200     req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000101")
201     if "FAIL" in req:
202         raise Exception("GAS query request rejected")
203     req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000801")
204     if "FAIL" in req:
205         raise Exception("GAS query request rejected")
206     dev[0].scan(no_wait=True)
207     req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000201")
208     if "FAIL" in req:
209         raise Exception("GAS query request rejected")
210     req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000501")
211     if "FAIL" in req:
212         raise Exception("GAS query request rejected")
213 
214     responses = 0
215     for i in range(0, 5):
216         ev = dev[0].wait_event(["GAS-RESPONSE-INFO", "CTRL-EVENT-SCAN-RESULTS"],
217                                timeout=10)
218         if ev is None:
219             raise Exception("Operation timed out")
220         if "GAS-RESPONSE-INFO" in ev:
221             responses = responses + 1
222             get_gas_response(dev[0], bssid, ev, allow_fetch_failure=True)
223 
224     if responses != 4:
225         raise Exception("Unexpected number of GAS responses")
226 
227     # Try to get all GAS frames into the sniffer capture of this test case.
228     hapd.disable()
229     time.sleep(0.1)
230 
231 def test_gas_concurrent_connect(dev, apdev):
232     """Generic GAS queries with concurrent connection operation"""
233     skip_with_fips(dev[0])
234     bssid = apdev[0]['bssid']
235     params = hs20_ap_params()
236     params['hessid'] = bssid
237     hapd = hostapd.add_ap(apdev[0], params)
238 
239     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
240 
241     logger.debug("Start concurrent connect and GAS request")
242     dev[0].connect("test-gas", key_mgmt="WPA-EAP", eap="TTLS",
243                    identity="DOMAIN\\mschapv2 user", anonymous_identity="ttls",
244                    password="password", phase2="auth=MSCHAPV2",
245                    ca_cert="auth_serv/ca.pem", wait_connect=False,
246                    scan_freq="2412")
247     req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000101")
248     if "FAIL" in req:
249         raise Exception("GAS query request rejected")
250 
251     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", "GAS-RESPONSE-INFO"],
252                            timeout=20)
253     if ev is None:
254         raise Exception("Operation timed out")
255     if "CTRL-EVENT-CONNECTED" not in ev:
256         raise Exception("Unexpected operation order")
257 
258     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", "GAS-RESPONSE-INFO"],
259                            timeout=20)
260     if ev is None:
261         raise Exception("Operation timed out")
262     if "GAS-RESPONSE-INFO" not in ev:
263         raise Exception("Unexpected operation order")
264     get_gas_response(dev[0], bssid, ev)
265 
266     hapd.wait_sta()
267     dev[0].request("DISCONNECT")
268     dev[0].wait_disconnected(timeout=5)
269     hapd.wait_sta_disconnect()
270 
271     logger.debug("Wait six seconds for expiration of connect-without-scan")
272     time.sleep(6)
273     dev[0].dump_monitor()
274 
275     logger.debug("Start concurrent GAS request and connect")
276     req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000101")
277     if "FAIL" in req:
278         raise Exception("GAS query request rejected")
279     dev[0].request("RECONNECT")
280 
281     ev = dev[0].wait_event(["GAS-RESPONSE-INFO"], timeout=10)
282     if ev is None:
283         raise Exception("Operation timed out")
284     get_gas_response(dev[0], bssid, ev)
285 
286     ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=20)
287     if ev is None:
288         raise Exception("No new scan results reported")
289 
290     ev = dev[0].wait_connected(timeout=20, error="Operation timed out")
291     if "CTRL-EVENT-CONNECTED" not in ev:
292         raise Exception("Unexpected operation order")
293 
294 def gas_fragment_and_comeback(dev, apdev, frag_limit=0, comeback_delay=0):
295     hapd = start_ap(apdev)
296     if frag_limit:
297         hapd.set("gas_frag_limit", str(frag_limit))
298     if comeback_delay:
299         hapd.set("gas_comeback_delay", str(comeback_delay))
300 
301     dev.scan_for_bss(apdev['bssid'], freq="2412", force_scan=True)
302     dev.request("FETCH_ANQP")
303     ev = dev.wait_event(["GAS-QUERY-DONE"], timeout=5)
304     if ev is None:
305         raise Exception("No GAS-QUERY-DONE event")
306     if "result=SUCCESS" not in ev:
307         raise Exception("Unexpected GAS result: " + ev)
308     for i in range(0, 13):
309         ev = dev.wait_event(["RX-ANQP", "RX-HS20-ANQP"], timeout=5)
310         if ev is None:
311             raise Exception("Operation timed out")
312     ev = dev.wait_event(["ANQP-QUERY-DONE"], timeout=1)
313     if ev is None:
314         raise Exception("No ANQP-QUERY-DONE event")
315     if "result=SUCCESS" not in ev:
316         raise Exception("Unexpected ANQP result: " + ev)
317 
318 def test_gas_fragment(dev, apdev):
319     """GAS fragmentation"""
320     gas_fragment_and_comeback(dev[0], apdev[0], frag_limit=50)
321 
322 def test_gas_fragment_mcc(dev, apdev):
323     """GAS fragmentation with mac80211_hwsim MCC enabled"""
324     with HWSimRadio(n_channels=2) as (radio, iface):
325         wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
326         wpas.interface_add(iface)
327         gas_fragment_and_comeback(wpas, apdev[0], frag_limit=50)
328 
329 def test_gas_fragment_with_comeback_delay(dev, apdev):
330     """GAS fragmentation and comeback delay"""
331     gas_fragment_and_comeback(dev[0], apdev[0], frag_limit=50,
332                               comeback_delay=500)
333 
334 def test_gas_fragment_with_comeback_delay_mcc(dev, apdev):
335     """GAS fragmentation and comeback delay with mac80211_hwsim MCC enabled"""
336     with HWSimRadio(n_channels=2) as (radio, iface):
337         wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
338         wpas.interface_add(iface)
339         gas_fragment_and_comeback(wpas, apdev[0], frag_limit=50,
340                                   comeback_delay=500)
341 
342 def test_gas_comeback_delay(dev, apdev):
343     """GAS comeback delay"""
344     run_gas_comeback_delay(dev, apdev, 500)
345 
346 def test_gas_comeback_delay_long(dev, apdev):
347     """GAS long comeback delay"""
348     run_gas_comeback_delay(dev, apdev, 2500)
349 
350 def test_gas_comeback_delay_long2(dev, apdev):
351     """GAS long comeback delay over default STA timeout"""
352     run_gas_comeback_delay(dev, apdev, 6000)
353 
354 def run_gas_comeback_delay(dev, apdev, delay):
355     hapd = start_ap(apdev[0])
356     hapd.set("gas_comeback_delay", str(delay))
357 
358     dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
359     dev[0].request("FETCH_ANQP")
360     if "FAIL-BUSY" not in dev[0].request("SCAN"):
361         raise Exception("SCAN accepted during FETCH_ANQP")
362     for i in range(0, 6):
363         ev = dev[0].wait_event(["RX-ANQP"], timeout=10)
364         if ev is None:
365             raise Exception("Operation timed out")
366 
367 @remote_compatible
368 def test_gas_stop_fetch_anqp(dev, apdev):
369     """Stop FETCH_ANQP operation"""
370     hapd = start_ap(apdev[0])
371 
372     dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
373     hapd.set("ext_mgmt_frame_handling", "1")
374     dev[0].request("FETCH_ANQP")
375     dev[0].request("STOP_FETCH_ANQP")
376     hapd.set("ext_mgmt_frame_handling", "0")
377     ev = dev[0].wait_event(["RX-ANQP", "GAS-QUERY-DONE"], timeout=10)
378     if ev is None:
379         raise Exception("GAS-QUERY-DONE timed out")
380     if "RX-ANQP" in ev:
381         raise Exception("Unexpected ANQP response received")
382 
383 def test_gas_anqp_get(dev, apdev):
384     """GAS/ANQP query for both IEEE 802.11 and Hotspot 2.0 elements"""
385     hapd = start_ap(apdev[0])
386     bssid = apdev[0]['bssid']
387 
388     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
389     if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258,268,hs20:3,hs20:4"):
390         raise Exception("ANQP_GET command failed")
391 
392     ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
393     if ev is None:
394         raise Exception("GAS query start timed out")
395 
396     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
397     if ev is None:
398         raise Exception("GAS query timed out")
399 
400     ev = dev[0].wait_event(["RX-ANQP"], timeout=1)
401     if ev is None or "Venue Name" not in ev:
402         raise Exception("Did not receive Venue Name")
403 
404     ev = dev[0].wait_event(["RX-ANQP"], timeout=1)
405     if ev is None or "Domain Name list" not in ev:
406         raise Exception("Did not receive Domain Name list")
407 
408     ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=1)
409     if ev is None or "Operator Friendly Name" not in ev:
410         raise Exception("Did not receive Operator Friendly Name")
411 
412     ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=1)
413     if ev is None or "WAN Metrics" not in ev:
414         raise Exception("Did not receive WAN Metrics")
415 
416     ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
417     if ev is None:
418         raise Exception("ANQP-QUERY-DONE event not seen")
419     if "result=SUCCESS" not in ev:
420         raise Exception("Unexpected result: " + ev)
421 
422     if "OK" not in dev[0].request("ANQP_GET " + bssid + " hs20:3"):
423         raise Exception("ANQP_GET command failed")
424 
425     ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
426     if ev is None:
427         raise Exception("GAS query start timed out")
428 
429     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
430     if ev is None:
431         raise Exception("GAS query timed out")
432 
433     ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=1)
434     if ev is None or "Operator Friendly Name" not in ev:
435         raise Exception("Did not receive Operator Friendly Name")
436 
437     ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
438     if ev is None:
439         raise Exception("ANQP-QUERY-DONE event not seen")
440     if "result=SUCCESS" not in ev:
441         raise Exception("Unexpected result: " + ev)
442 
443     if "OK" not in dev[0].request("HS20_ANQP_GET " + bssid + " 3,4"):
444         raise Exception("ANQP_GET command failed")
445 
446     ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=1)
447     if ev is None or "Operator Friendly Name" not in ev:
448         raise Exception("Did not receive Operator Friendly Name")
449 
450     ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=1)
451     if ev is None or "WAN Metrics" not in ev:
452         raise Exception("Did not receive WAN Metrics")
453 
454     logger.info("Attempt an MBO request with an AP that does not support MBO")
455     if "OK" not in dev[0].request("ANQP_GET " + bssid + " 272,mbo:2"):
456         raise Exception("ANQP_GET command failed (2)")
457 
458     ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
459     if ev is None:
460         raise Exception("GAS query start timed out (2)")
461 
462     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
463     if ev is None:
464         raise Exception("GAS query timed out (2)")
465 
466     cmds = ["",
467             "foo",
468             "00:11:22:33:44:55 258,hs20:-1",
469             "00:11:22:33:44:55 258,hs20:0",
470             "00:11:22:33:44:55 258,hs20:32",
471             "00:11:22:33:44:55 hs20:-1",
472             "00:11:22:33:44:55 hs20:0",
473             "00:11:22:33:44:55 hs20:32",
474             "00:11:22:33:44:55 mbo:-1",
475             "00:11:22:33:44:55 mbo:0",
476             "00:11:22:33:44:55 mbo:999",
477             "00:11:22:33:44:55 mbo:1,258,mbo:2,mbo:3,259",
478             "00:11:22:33:44:55",
479             "00:11:22:33:44:55 ",
480             "00:11:22:33:44:55 0",
481             "00:11:22:33:44:55 1"]
482     for cmd in cmds:
483         if "FAIL" not in dev[0].request("ANQP_GET " + cmd):
484             raise Exception("Invalid ANQP_GET accepted")
485 
486     cmds = ["",
487             "foo",
488             "00:11:22:33:44:55 -1",
489             "00:11:22:33:44:55 0",
490             "00:11:22:33:44:55 32",
491             "00:11:22:33:44:55",
492             "00:11:22:33:44:55 ",
493             "00:11:22:33:44:55 0",
494             "00:11:22:33:44:55 1"]
495     for cmd in cmds:
496         if "FAIL" not in dev[0].request("HS20_ANQP_GET " + cmd):
497             raise Exception("Invalid HS20_ANQP_GET accepted")
498 
499 def test_gas_anqp_get_no_scan(dev, apdev):
500     """GAS/ANQP query without scan"""
501     hapd = start_ap(apdev[0])
502     bssid = apdev[0]['bssid']
503     if "OK" not in dev[0].request("ANQP_GET " + bssid + " freq=2412 258"):
504         raise Exception("ANQP_GET command failed")
505     ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
506     if ev is None:
507         raise Exception("ANQP query timed out")
508     dev[0].dump_monitor()
509 
510     if "OK" not in dev[0].request("ANQP_GET 02:11:22:33:44:55 freq=2417 258"):
511         raise Exception("ANQP_GET command failed")
512     ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
513     if ev is None:
514         raise Exception("ANQP query timed out [2]")
515     if "result=FAILURE" not in ev:
516         raise Exception("Unexpected result: " + ev)
517 
518 def test_gas_anqp_get_oom(dev, apdev):
519     """GAS/ANQP query OOM"""
520     hapd = start_ap(apdev[0])
521     bssid = apdev[0]['bssid']
522 
523     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
524     with alloc_fail(dev[0], 1, "wpabuf_alloc;anqp_send_req"):
525         if "FAIL" not in dev[0].request("ANQP_GET " + bssid + " 258,268,hs20:3,hs20:4"):
526             raise Exception("ANQP_GET command accepted during OOM")
527     with alloc_fail(dev[0], 1, "hs20_build_anqp_req;hs20_anqp_send_req"):
528         if "FAIL" not in dev[0].request("HS20_ANQP_GET " + bssid + " 1"):
529             raise Exception("HS20_ANQP_GET command accepted during OOM")
530     with alloc_fail(dev[0], 1, "gas_query_req;hs20_anqp_send_req"):
531         if "FAIL" not in dev[0].request("HS20_ANQP_GET " + bssid + " 1"):
532             raise Exception("HS20_ANQP_GET command accepted during OOM")
533 
534 def test_gas_anqp_hs20_proto(dev, apdev):
535     """GAS/ANQP and Hotspot 2.0 element protocol testing"""
536     hapd = start_ap(apdev[0])
537     bssid = apdev[0]['bssid']
538 
539     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
540     hapd.set("ext_mgmt_frame_handling", "1")
541 
542     tests = ['00', '0100', '0201', '0300', '0400', '0500', '0600', '0700',
543              '0800', '0900', '0a00', '0b0000000000']
544     for test in tests:
545         dev[0].request("HS20_ANQP_GET " + bssid + " 3,4")
546         query = gas_rx(hapd)
547         gas = parse_gas(query['payload'])
548         resp = action_response(query)
549         data = binascii.unhexlify(test)
550         data = binascii.unhexlify('506f9a11') + data
551         data = struct.pack('<HHH', len(data) + 4, 0xdddd, len(data)) + data
552         resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + data
553         send_gas_resp(hapd, resp)
554         expect_gas_result(dev[0], "SUCCESS")
555 
556 def expect_gas_result(dev, result, status=None):
557     ev = dev.wait_event(["GAS-QUERY-DONE"], timeout=10)
558     if ev is None:
559         raise Exception("GAS query timed out")
560     if "result=" + result not in ev:
561         raise Exception("Unexpected GAS query result")
562     if status and "status_code=" + str(status) + ' ' not in ev:
563         raise Exception("Unexpected GAS status code")
564 
565 def anqp_get(dev, bssid, id):
566     if "OK" not in dev.request("ANQP_GET " + bssid + " " + str(id)):
567         raise Exception("ANQP_GET command failed")
568     ev = dev.wait_event(["GAS-QUERY-START"], timeout=5)
569     if ev is None:
570         raise Exception("GAS query start timed out")
571 
572 def test_gas_timeout(dev, apdev):
573     """GAS timeout"""
574     hapd = start_ap(apdev[0])
575     bssid = apdev[0]['bssid']
576 
577     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
578     hapd.set("ext_mgmt_frame_handling", "1")
579 
580     anqp_get(dev[0], bssid, 263)
581 
582     ev = hapd.wait_event(["MGMT-RX"], timeout=5)
583     if ev is None:
584         raise Exception("MGMT RX wait timed out")
585 
586     expect_gas_result(dev[0], "TIMEOUT")
587 
588 MGMT_SUBTYPE_ACTION = 13
589 ACTION_CATEG_PUBLIC = 4
590 
591 GAS_INITIAL_REQUEST = 10
592 GAS_INITIAL_RESPONSE = 11
593 GAS_COMEBACK_REQUEST = 12
594 GAS_COMEBACK_RESPONSE = 13
595 GAS_ACTIONS = [GAS_INITIAL_REQUEST, GAS_INITIAL_RESPONSE,
596                GAS_COMEBACK_REQUEST, GAS_COMEBACK_RESPONSE]
597 
598 def anqp_adv_proto():
599     return struct.pack('BBBB', 108, 2, 127, 0)
600 
601 def anqp_initial_resp(dialog_token, status_code, comeback_delay=0):
602     return struct.pack('<BBBHH', ACTION_CATEG_PUBLIC, GAS_INITIAL_RESPONSE,
603                        dialog_token, status_code, comeback_delay) + anqp_adv_proto()
604 
605 def anqp_comeback_resp(dialog_token, status_code=0, id=0, more=False, comeback_delay=0, bogus_adv_proto=False):
606     if more:
607         id |= 0x80
608     if bogus_adv_proto:
609         adv = struct.pack('BBBB', 108, 2, 127, 1)
610     else:
611         adv = anqp_adv_proto()
612     return struct.pack('<BBBHBH', ACTION_CATEG_PUBLIC, GAS_COMEBACK_RESPONSE,
613                        dialog_token, status_code, id, comeback_delay) + adv
614 
615 def gas_rx(hapd):
616     count = 0
617     while count < 30:
618         count = count + 1
619         query = hapd.mgmt_rx()
620         if query is None:
621             raise Exception("Action frame not received")
622         if query['subtype'] != MGMT_SUBTYPE_ACTION:
623             continue
624         payload = query['payload']
625         if len(payload) < 2:
626             continue
627         (category, action) = struct.unpack('BB', payload[0:2])
628         if category != ACTION_CATEG_PUBLIC or action not in GAS_ACTIONS:
629             continue
630         return query
631     raise Exception("No Action frame received")
632 
633 def parse_gas(payload):
634     pos = payload
635     (category, action, dialog_token) = struct.unpack('BBB', pos[0:3])
636     if category != ACTION_CATEG_PUBLIC:
637         return None
638     if action not in GAS_ACTIONS:
639         return None
640     gas = {}
641     gas['action'] = action
642     pos = pos[3:]
643 
644     if len(pos) < 1 and action != GAS_COMEBACK_REQUEST:
645         return None
646 
647     gas['dialog_token'] = dialog_token
648 
649     if action == GAS_INITIAL_RESPONSE:
650         if len(pos) < 4:
651             return None
652         (status_code, comeback_delay) = struct.unpack('<HH', pos[0:4])
653         gas['status_code'] = status_code
654         gas['comeback_delay'] = comeback_delay
655 
656     if action == GAS_COMEBACK_RESPONSE:
657         if len(pos) < 5:
658             return None
659         (status_code, frag, comeback_delay) = struct.unpack('<HBH', pos[0:5])
660         gas['status_code'] = status_code
661         gas['frag'] = frag
662         gas['comeback_delay'] = comeback_delay
663 
664     return gas
665 
666 def action_response(req):
667     resp = {}
668     resp['fc'] = req['fc']
669     resp['da'] = req['sa']
670     resp['sa'] = req['da']
671     resp['bssid'] = req['bssid']
672     return resp
673 
674 def send_gas_resp(hapd, resp):
675     hapd.mgmt_tx(resp)
676     ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
677     if ev is None:
678         raise Exception("Missing TX status for GAS response")
679     if "ok=1" not in ev:
680         raise Exception("GAS response not acknowledged")
681 
682 def test_gas_invalid_response_type(dev, apdev):
683     """GAS invalid response type"""
684     hapd = start_ap(apdev[0])
685     bssid = apdev[0]['bssid']
686 
687     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
688     hapd.set("ext_mgmt_frame_handling", "1")
689 
690     anqp_get(dev[0], bssid, 263)
691 
692     query = gas_rx(hapd)
693     gas = parse_gas(query['payload'])
694 
695     resp = action_response(query)
696     # GAS Comeback Response instead of GAS Initial Response
697     resp['payload'] = anqp_comeback_resp(gas['dialog_token']) + struct.pack('<H', 0)
698     send_gas_resp(hapd, resp)
699 
700     # station drops the invalid frame, so this needs to result in GAS timeout
701     expect_gas_result(dev[0], "TIMEOUT")
702 
703 def test_gas_failure_status_code(dev, apdev):
704     """GAS failure status code"""
705     hapd = start_ap(apdev[0])
706     bssid = apdev[0]['bssid']
707 
708     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
709     hapd.set("ext_mgmt_frame_handling", "1")
710 
711     anqp_get(dev[0], bssid, 263)
712 
713     query = gas_rx(hapd)
714     gas = parse_gas(query['payload'])
715 
716     resp = action_response(query)
717     resp['payload'] = anqp_initial_resp(gas['dialog_token'], 61) + struct.pack('<H', 0)
718     send_gas_resp(hapd, resp)
719 
720     expect_gas_result(dev[0], "FAILURE")
721 
722 def test_gas_malformed(dev, apdev):
723     """GAS malformed response frames"""
724     hapd = start_ap(apdev[0])
725     bssid = apdev[0]['bssid']
726 
727     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
728     hapd.set("ext_mgmt_frame_handling", "1")
729 
730     anqp_get(dev[0], bssid, 263)
731 
732     query = gas_rx(hapd)
733     gas = parse_gas(query['payload'])
734 
735     resp = action_response(query)
736 
737     resp['payload'] = struct.pack('<BBBH', ACTION_CATEG_PUBLIC,
738                                   GAS_COMEBACK_RESPONSE,
739                                   gas['dialog_token'], 0)
740     hapd.mgmt_tx(resp)
741 
742     resp['payload'] = struct.pack('<BBBHB', ACTION_CATEG_PUBLIC,
743                                   GAS_COMEBACK_RESPONSE,
744                                   gas['dialog_token'], 0, 0)
745     hapd.mgmt_tx(resp)
746 
747     hdr = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC, GAS_INITIAL_RESPONSE,
748                       gas['dialog_token'], 0, 0)
749     resp['payload'] = hdr + struct.pack('B', 108)
750     hapd.mgmt_tx(resp)
751     resp['payload'] = hdr + struct.pack('BB', 108, 0)
752     hapd.mgmt_tx(resp)
753     resp['payload'] = hdr + struct.pack('BB', 108, 1)
754     hapd.mgmt_tx(resp)
755     resp['payload'] = hdr + struct.pack('BB', 108, 255)
756     hapd.mgmt_tx(resp)
757     resp['payload'] = hdr + struct.pack('BBB', 108, 1, 127)
758     hapd.mgmt_tx(resp)
759     resp['payload'] = hdr + struct.pack('BBB', 108, 2, 127)
760     hapd.mgmt_tx(resp)
761     resp['payload'] = hdr + struct.pack('BBBB', 0, 2, 127, 0)
762     hapd.mgmt_tx(resp)
763 
764     resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + struct.pack('<H', 1)
765     hapd.mgmt_tx(resp)
766 
767     resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + struct.pack('<HB', 2, 0)
768     hapd.mgmt_tx(resp)
769 
770     resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + struct.pack('<H', 65535)
771     hapd.mgmt_tx(resp)
772 
773     resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + struct.pack('<HBB', 1, 0, 0)
774     hapd.mgmt_tx(resp)
775 
776     # Station drops invalid frames, but the last of the responses is valid from
777     # GAS view point even though it has an extra octet in the end and the ANQP
778     # part of the response is not valid. This is reported as successfully
779     # completed GAS exchange.
780     expect_gas_result(dev[0], "SUCCESS")
781 
782     ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
783     if ev is None:
784         raise Exception("ANQP-QUERY-DONE not reported")
785     if "result=INVALID_FRAME" not in ev:
786         raise Exception("Unexpected result: " + ev)
787 
788 def init_gas(hapd, bssid, dev):
789     anqp_get(dev, bssid, 263)
790     query = gas_rx(hapd)
791     gas = parse_gas(query['payload'])
792     dialog_token = gas['dialog_token']
793 
794     resp = action_response(query)
795     resp['payload'] = anqp_initial_resp(dialog_token, 0, comeback_delay=1) + struct.pack('<H', 0)
796     send_gas_resp(hapd, resp)
797 
798     query = gas_rx(hapd)
799     gas = parse_gas(query['payload'])
800     if gas['action'] != GAS_COMEBACK_REQUEST:
801         raise Exception("Unexpected request action")
802     if gas['dialog_token'] != dialog_token:
803         raise Exception("Unexpected dialog token change")
804     return query, dialog_token
805 
806 def allow_gas_initial_req(hapd, dialog_token):
807     msg = hapd.mgmt_rx(timeout=1)
808     if msg is not None:
809         gas = parse_gas(msg['payload'])
810         if gas['action'] != GAS_INITIAL_REQUEST or dialog_token == gas['dialog_token']:
811             raise Exception("Unexpected management frame")
812 
813 def test_gas_malformed_comeback_resp(dev, apdev):
814     """GAS malformed comeback response frames"""
815     hapd = start_ap(apdev[0])
816     bssid = apdev[0]['bssid']
817 
818     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
819     hapd.set("ext_mgmt_frame_handling", "1")
820 
821     logger.debug("Non-zero status code in comeback response")
822     query, dialog_token = init_gas(hapd, bssid, dev[0])
823     resp = action_response(query)
824     resp['payload'] = anqp_comeback_resp(dialog_token, status_code=2) + struct.pack('<H', 0)
825     send_gas_resp(hapd, resp)
826     expect_gas_result(dev[0], "FAILURE", status=2)
827 
828     logger.debug("Different advertisement protocol in comeback response")
829     query, dialog_token = init_gas(hapd, bssid, dev[0])
830     resp = action_response(query)
831     resp['payload'] = anqp_comeback_resp(dialog_token, bogus_adv_proto=True) + struct.pack('<H', 0)
832     send_gas_resp(hapd, resp)
833     expect_gas_result(dev[0], "PEER_ERROR")
834 
835     logger.debug("Non-zero frag id and comeback delay in comeback response")
836     query, dialog_token = init_gas(hapd, bssid, dev[0])
837     resp = action_response(query)
838     resp['payload'] = anqp_comeback_resp(dialog_token, id=1, comeback_delay=1) + struct.pack('<H', 0)
839     send_gas_resp(hapd, resp)
840     expect_gas_result(dev[0], "PEER_ERROR")
841 
842     logger.debug("Unexpected frag id in comeback response")
843     query, dialog_token = init_gas(hapd, bssid, dev[0])
844     resp = action_response(query)
845     resp['payload'] = anqp_comeback_resp(dialog_token, id=1) + struct.pack('<H', 0)
846     send_gas_resp(hapd, resp)
847     expect_gas_result(dev[0], "PEER_ERROR")
848 
849     logger.debug("Empty fragment and replay in comeback response")
850     query, dialog_token = init_gas(hapd, bssid, dev[0])
851     resp = action_response(query)
852     resp['payload'] = anqp_comeback_resp(dialog_token, more=True) + struct.pack('<H', 0)
853     send_gas_resp(hapd, resp)
854     query = gas_rx(hapd)
855     gas = parse_gas(query['payload'])
856     if gas['action'] != GAS_COMEBACK_REQUEST:
857         raise Exception("Unexpected request action")
858     if gas['dialog_token'] != dialog_token:
859         raise Exception("Unexpected dialog token change")
860     resp = action_response(query)
861     resp['payload'] = anqp_comeback_resp(dialog_token) + struct.pack('<H', 0)
862     send_gas_resp(hapd, resp)
863     resp['payload'] = anqp_comeback_resp(dialog_token, id=1) + struct.pack('<H', 0)
864     send_gas_resp(hapd, resp)
865     expect_gas_result(dev[0], "SUCCESS")
866 
867     logger.debug("Unexpected initial response when waiting for comeback response")
868     query, dialog_token = init_gas(hapd, bssid, dev[0])
869     resp = action_response(query)
870     resp['payload'] = anqp_initial_resp(dialog_token, 0) + struct.pack('<H', 0)
871     send_gas_resp(hapd, resp)
872     allow_gas_initial_req(hapd, dialog_token)
873     expect_gas_result(dev[0], "TIMEOUT")
874 
875     logger.debug("Too short comeback response")
876     query, dialog_token = init_gas(hapd, bssid, dev[0])
877     resp = action_response(query)
878     resp['payload'] = struct.pack('<BBBH', ACTION_CATEG_PUBLIC,
879                                   GAS_COMEBACK_RESPONSE, dialog_token, 0)
880     send_gas_resp(hapd, resp)
881     allow_gas_initial_req(hapd, dialog_token)
882     expect_gas_result(dev[0], "TIMEOUT")
883 
884     logger.debug("Too short comeback response(2)")
885     query, dialog_token = init_gas(hapd, bssid, dev[0])
886     resp = action_response(query)
887     resp['payload'] = struct.pack('<BBBHBB', ACTION_CATEG_PUBLIC,
888                                   GAS_COMEBACK_RESPONSE, dialog_token, 0, 0x80,
889                                   0)
890     send_gas_resp(hapd, resp)
891     allow_gas_initial_req(hapd, dialog_token)
892     expect_gas_result(dev[0], "TIMEOUT")
893 
894     logger.debug("Maximum comeback response fragment claiming more fragments")
895     query, dialog_token = init_gas(hapd, bssid, dev[0])
896     resp = action_response(query)
897     resp['payload'] = anqp_comeback_resp(dialog_token, more=True) + struct.pack('<H', 0)
898     send_gas_resp(hapd, resp)
899     for i in range(1, 129):
900         query = gas_rx(hapd)
901         gas = parse_gas(query['payload'])
902         if gas['action'] != GAS_COMEBACK_REQUEST:
903             raise Exception("Unexpected request action")
904         if gas['dialog_token'] != dialog_token:
905             raise Exception("Unexpected dialog token change")
906         resp = action_response(query)
907         resp['payload'] = anqp_comeback_resp(dialog_token, id=i, more=True) + struct.pack('<H', 0)
908         send_gas_resp(hapd, resp)
909     expect_gas_result(dev[0], "PEER_ERROR")
910 
911 def test_gas_comeback_resp_additional_delay(dev, apdev):
912     """GAS comeback response requesting additional delay"""
913     hapd = start_ap(apdev[0])
914     bssid = apdev[0]['bssid']
915 
916     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
917     hapd.set("ext_mgmt_frame_handling", "1")
918 
919     query, dialog_token = init_gas(hapd, bssid, dev[0])
920     for i in range(0, 2):
921         resp = action_response(query)
922         resp['payload'] = anqp_comeback_resp(dialog_token, status_code=95, comeback_delay=50) + struct.pack('<H', 0)
923         send_gas_resp(hapd, resp)
924         query = gas_rx(hapd)
925         gas = parse_gas(query['payload'])
926         if gas['action'] != GAS_COMEBACK_REQUEST:
927             raise Exception("Unexpected request action")
928         if gas['dialog_token'] != dialog_token:
929             raise Exception("Unexpected dialog token change")
930     resp = action_response(query)
931     resp['payload'] = anqp_comeback_resp(dialog_token, status_code=0) + struct.pack('<H', 0)
932     send_gas_resp(hapd, resp)
933     expect_gas_result(dev[0], "SUCCESS")
934 
935 def test_gas_unknown_adv_proto(dev, apdev):
936     """Unknown advertisement protocol id"""
937     bssid = apdev[0]['bssid']
938     params = hs20_ap_params()
939     params['hessid'] = bssid
940     hostapd.add_ap(apdev[0], params)
941 
942     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
943     req = dev[0].request("GAS_REQUEST " + bssid + " 42 000102000101")
944     if "FAIL" in req:
945         raise Exception("GAS query request rejected")
946     expect_gas_result(dev[0], "FAILURE", "59")
947     ev = dev[0].wait_event(["GAS-RESPONSE-INFO"], timeout=10)
948     if ev is None:
949         raise Exception("GAS query timed out")
950     exp = r'<.>(GAS-RESPONSE-INFO) addr=([0-9a-f:]*) dialog_token=([0-9]*) status_code=([0-9]*) resp_len=([\-0-9]*)'
951     res = re.split(exp, ev)
952     if len(res) < 6:
953         raise Exception("Could not parse GAS-RESPONSE-INFO")
954     if res[2] != bssid:
955         raise Exception("Unexpected BSSID in response")
956     status = res[4]
957     if status != "59":
958         raise Exception("Unexpected GAS-RESPONSE-INFO status")
959 
960 def test_gas_request_oom(dev, apdev):
961     """GAS_REQUEST OOM"""
962     bssid = apdev[0]['bssid']
963     params = hs20_ap_params()
964     params['hessid'] = bssid
965     hostapd.add_ap(apdev[0], params)
966 
967     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
968 
969     with alloc_fail(dev[0], 1, "gas_build_req;gas_send_request"):
970         if "FAIL" not in dev[0].request("GAS_REQUEST " + bssid + " 42"):
971             raise Exception("GAS query request rejected")
972 
973     with alloc_fail(dev[0], 1, "gas_query_req;gas_send_request"):
974         if "FAIL" not in dev[0].request("GAS_REQUEST " + bssid + " 42"):
975             raise Exception("GAS query request rejected")
976 
977     with alloc_fail(dev[0], 1, "wpabuf_dup;gas_resp_cb"):
978         if "OK" not in dev[0].request("GAS_REQUEST " + bssid + " 00 000102000101"):
979             raise Exception("GAS query request rejected")
980         ev = dev[0].wait_event(["GAS-RESPONSE-INFO"], timeout=10)
981         if ev is None:
982             raise Exception("No GAS response")
983         if "status_code=0" not in ev:
984             raise Exception("GAS response indicated a failure")
985 
986 def test_gas_max_pending(dev, apdev):
987     """GAS and maximum pending query limit"""
988     hapd = start_ap(apdev[0])
989     hapd.set("gas_frag_limit", "50")
990     bssid = apdev[0]['bssid']
991 
992     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
993     wpas.interface_add("wlan5")
994     if "OK" not in wpas.request("P2P_SET listen_channel 1"):
995         raise Exception("Failed to set listen channel")
996     if "OK" not in wpas.p2p_listen():
997         raise Exception("Failed to start listen state")
998     if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"):
999         raise Exception("Failed to enable external management frame handling")
1000 
1001     anqp_query = struct.pack('<HHHHHHHHHH', 256, 16, 257, 258, 260, 261, 262, 263, 264, 268)
1002     gas = struct.pack('<H', len(anqp_query)) + anqp_query
1003 
1004     for dialog_token in range(1, 10):
1005         msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST,
1006                           dialog_token) + anqp_adv_proto() + gas
1007         req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode())
1008         if "OK" not in wpas.request(req):
1009             raise Exception("Could not send management frame")
1010         resp = wpas.mgmt_rx()
1011         if resp is None:
1012             raise Exception("MGMT-RX timeout")
1013         if 'payload' not in resp:
1014             raise Exception("Missing payload")
1015         gresp = parse_gas(resp['payload'])
1016         if gresp['dialog_token'] != dialog_token:
1017             raise Exception("Dialog token mismatch")
1018         status_code = gresp['status_code']
1019         if dialog_token < 9 and status_code != 0:
1020             raise Exception("Unexpected failure status code {} for dialog token {}".format(status_code, dialog_token))
1021         if dialog_token > 8 and status_code == 0:
1022             raise Exception("Unexpected success status code {} for dialog token {}".format(status_code, dialog_token))
1023 
1024 def test_gas_no_pending(dev, apdev):
1025     """GAS and no pending query for comeback request"""
1026     hapd = start_ap(apdev[0])
1027     bssid = apdev[0]['bssid']
1028 
1029     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1030     wpas.interface_add("wlan5")
1031     if "OK" not in wpas.request("P2P_SET listen_channel 1"):
1032         raise Exception("Failed to set listen channel")
1033     if "OK" not in wpas.p2p_listen():
1034         raise Exception("Failed to start listen state")
1035     if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"):
1036         raise Exception("Failed to enable external management frame handling")
1037 
1038     msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_COMEBACK_REQUEST, 1)
1039     req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode())
1040     if "OK" not in wpas.request(req):
1041         raise Exception("Could not send management frame")
1042     resp = wpas.mgmt_rx()
1043     if resp is None:
1044         raise Exception("MGMT-RX timeout")
1045     if 'payload' not in resp:
1046         raise Exception("Missing payload")
1047     gresp = parse_gas(resp['payload'])
1048     status_code = gresp['status_code']
1049     if status_code != 60:
1050         raise Exception("Unexpected status code {} (expected 60)".format(status_code))
1051 
1052 def test_gas_delete_at_deinit(dev, apdev):
1053     """GAS query deleted at deinit"""
1054     hapd = start_ap(apdev[0])
1055     hapd.set("gas_comeback_delay", "1000")
1056     bssid = apdev[0]['bssid']
1057 
1058     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1059     wpas.interface_add("wlan5")
1060     wpas.scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
1061     wpas.request("ANQP_GET " + bssid + " 258")
1062 
1063     wpas.global_request("INTERFACE_REMOVE " + wpas.ifname)
1064     ev = wpas.wait_event(["GAS-QUERY-DONE"], timeout=2)
1065     del wpas
1066     if ev is None:
1067         raise Exception("GAS-QUERY-DONE not seen")
1068     if "result=DELETED_AT_DEINIT" not in ev:
1069         raise Exception("Unexpected result code: " + ev)
1070 
1071 def test_gas_missing_payload(dev, apdev):
1072     """No action code in the query frame"""
1073     bssid = apdev[0]['bssid']
1074     params = hs20_ap_params()
1075     params['hessid'] = bssid
1076     hostapd.add_ap(apdev[0], params)
1077 
1078     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1079 
1080     cmd = "MGMT_TX {} {} freq=2412 action=040A".format(bssid, bssid)
1081     if "FAIL" in dev[0].request(cmd):
1082         raise Exception("Could not send test Action frame")
1083     ev = dev[0].wait_event(["MGMT-TX-STATUS"], timeout=10)
1084     if ev is None:
1085         raise Exception("Timeout on MGMT-TX-STATUS")
1086     if "result=SUCCESS" not in ev:
1087         raise Exception("AP did not ack Action frame")
1088 
1089     cmd = "MGMT_TX {} {} freq=2412 action=04".format(bssid, bssid)
1090     if "FAIL" in dev[0].request(cmd):
1091         raise Exception("Could not send test Action frame")
1092     ev = dev[0].wait_event(["MGMT-TX-STATUS"], timeout=10)
1093     if ev is None:
1094         raise Exception("Timeout on MGMT-TX-STATUS")
1095     if "result=SUCCESS" not in ev:
1096         raise Exception("AP did not ack Action frame")
1097 
1098 def test_gas_query_deinit(dev, apdev):
1099     """Pending GAS/ANQP query during deinit"""
1100     hapd = start_ap(apdev[0])
1101     bssid = apdev[0]['bssid']
1102 
1103     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1104     wpas.interface_add("wlan5")
1105 
1106     wpas.scan_for_bss(bssid, freq="2412", force_scan=True)
1107     id = wpas.request("RADIO_WORK add block-work")
1108     if "OK" not in wpas.request("ANQP_GET " + bssid + " 258"):
1109         raise Exception("ANQP_GET command failed")
1110 
1111     ev = wpas.wait_event(["GAS-QUERY-START", "EXT-RADIO-WORK-START"], timeout=5)
1112     if ev is None:
1113         raise Exception("Timeout while waiting radio work to start")
1114     ev = wpas.wait_event(["GAS-QUERY-START", "EXT-RADIO-WORK-START"], timeout=5)
1115     if ev is None:
1116         raise Exception("Timeout while waiting radio work to start (2)")
1117 
1118     # Remove the interface while the gas-query radio work is still pending and
1119     # GAS query has not yet been started.
1120     wpas.interface_remove("wlan5")
1121 
1122 @remote_compatible
1123 def test_gas_anqp_oom_wpas(dev, apdev):
1124     """GAS/ANQP query and OOM in wpa_supplicant"""
1125     hapd = start_ap(apdev[0])
1126     bssid = apdev[0]['bssid']
1127 
1128     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1129 
1130     with alloc_fail(dev[0], 1, "wpa_bss_anqp_alloc"):
1131         if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
1132             raise Exception("ANQP_GET command failed")
1133         ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
1134         if ev is None:
1135             raise Exception("ANQP query did not complete")
1136 
1137     with alloc_fail(dev[0], 1, "gas_build_req"):
1138         if "FAIL" not in dev[0].request("ANQP_GET " + bssid + " 258"):
1139             raise Exception("Unexpected ANQP_GET command success (OOM)")
1140 
1141 def test_gas_anqp_oom_hapd(dev, apdev):
1142     """GAS/ANQP query and OOM in hostapd"""
1143     hapd = start_ap(apdev[0])
1144     bssid = apdev[0]['bssid']
1145 
1146     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1147 
1148     with alloc_fail(hapd, 1, "gas_build_resp"):
1149         # This query will time out due to the AP not sending a response (OOM).
1150         if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
1151             raise Exception("ANQP_GET command failed")
1152 
1153         ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
1154         if ev is None:
1155             raise Exception("GAS query start timed out")
1156 
1157         ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
1158         if ev is None:
1159             raise Exception("GAS query timed out")
1160         if "result=TIMEOUT" not in ev:
1161             raise Exception("Unexpected result: " + ev)
1162 
1163         ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
1164         if ev is None:
1165             raise Exception("ANQP-QUERY-DONE event not seen")
1166         if "result=FAILURE" not in ev:
1167             raise Exception("Unexpected result: " + ev)
1168 
1169     with alloc_fail(hapd, 1, "gas_anqp_build_comeback_resp"):
1170         hapd.set("gas_frag_limit", "50")
1171 
1172         # The first attempt of this query will time out due to the AP not
1173         # sending a response (OOM), but the retry succeeds.
1174         dev[0].request("FETCH_ANQP")
1175         ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
1176         if ev is None:
1177             raise Exception("GAS query start timed out")
1178 
1179         ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
1180         if ev is None:
1181             raise Exception("GAS query timed out")
1182         if "result=SUCCESS" not in ev:
1183             raise Exception("Unexpected result: " + ev)
1184 
1185         ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
1186         if ev is None:
1187             raise Exception("ANQP-QUERY-DONE event not seen")
1188         if "result=SUCCESS" not in ev:
1189             raise Exception("Unexpected result: " + ev)
1190 
1191 def test_gas_anqp_extra_elements(dev, apdev):
1192     """GAS/ANQP and extra ANQP elements"""
1193     geo_loc = "001052834d12efd2b08b9b4bf1cc2c00004104050000000000060100"
1194     civic_loc = "0000f9555302f50102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5"
1195     held_uri = "https://held.example.com/location"
1196     held = struct.pack('BBB', 0, 1 + len(held_uri), 1) + held_uri.encode()
1197     supl_fqdn = "supl.example.com"
1198     supl = struct.pack('BBB', 0, 1 + len(supl_fqdn), 1) + supl_fqdn.encode()
1199     public_id = binascii.hexlify(held + supl).decode()
1200     params = {"ssid": "gas/anqp",
1201               "interworking": "1",
1202               "anqp_elem": ["265:" + geo_loc,
1203                             "266:" + civic_loc,
1204                             "262:1122334455",
1205                             "267:" + public_id,
1206                             "279:01020304",
1207                             "60000:01",
1208                             "299:0102"]}
1209     hapd = hostapd.add_ap(apdev[0], params)
1210     bssid = apdev[0]['bssid']
1211 
1212     dev[0].flush_scan_cache()
1213     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1214     if "OK" not in dev[0].request("ANQP_GET " + bssid + " 265,266"):
1215         raise Exception("ANQP_GET command failed")
1216 
1217     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
1218     if ev is None:
1219         raise Exception("GAS query timed out")
1220 
1221     bss = dev[0].get_bss(bssid)
1222 
1223     if 'anqp[265]' not in bss:
1224         raise Exception("AP Geospatial Location ANQP-element not seen")
1225     if bss['anqp[265]'] != geo_loc:
1226         raise Exception("Unexpected AP Geospatial Location ANQP-element value: " + bss['anqp[265]'])
1227 
1228     if 'anqp[266]' not in bss:
1229         raise Exception("AP Civic Location ANQP-element not seen")
1230     if bss['anqp[266]'] != civic_loc:
1231         raise Exception("Unexpected AP Civic Location ANQP-element value: " + bss['anqp[266]'])
1232 
1233     dev[1].scan_for_bss(bssid, freq="2412", force_scan=True)
1234     if "OK" not in dev[1].request("ANQP_GET " + bssid + " 257,258,259,260,261,262,263,264,265,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299"):
1235         raise Exception("ANQP_GET command failed")
1236 
1237     ev = dev[1].wait_event(["GAS-QUERY-DONE"], timeout=10)
1238     if ev is None:
1239         raise Exception("GAS query timed out")
1240 
1241     bss = dev[1].get_bss(bssid)
1242 
1243     if 'anqp[265]' not in bss:
1244         raise Exception("AP Geospatial Location ANQP-element not seen")
1245     if bss['anqp[265]'] != geo_loc:
1246         raise Exception("Unexpected AP Geospatial Location ANQP-element value: " + bss['anqp[265]'])
1247 
1248     if 'anqp[266]' in bss:
1249         raise Exception("AP Civic Location ANQP-element unexpectedly seen")
1250 
1251     if 'anqp[267]' not in bss:
1252         raise Exception("AP Location Public Identifier ANQP-element not seen")
1253     if bss['anqp[267]'] != public_id:
1254         raise Exception("Unexpected AP Location Public Identifier ANQP-element value: " + bss['anqp[267]'])
1255 
1256     if 'anqp[279]' not in bss:
1257         raise Exception("ANQP-element Info ID 279 not seen")
1258     if bss['anqp[279]'] != "01020304":
1259         raise Exception("Unexpected AP ANQP-element Info ID 279 value: " + bss['anqp[279]'])
1260 
1261     if 'anqp[299]' not in bss:
1262         raise Exception("ANQP-element Info ID 299 not seen")
1263     if bss['anqp[299]'] != "0102":
1264         raise Exception("Unexpected AP ANQP-element Info ID 299 value: " + bss['anqp[299]'])
1265 
1266     if 'anqp_ip_addr_type_availability' not in bss:
1267         raise Exception("ANQP-element Info ID 292 not seen")
1268     if bss['anqp_ip_addr_type_availability'] != "1122334455":
1269         raise Exception("Unexpected AP ANQP-element Info ID 262 value: " + bss['anqp_ip_addr_type_availability'])
1270 
1271 def test_gas_anqp_address3_not_assoc(dev, apdev, params):
1272     """GAS/ANQP query using IEEE 802.11 compliant Address 3 value when not associated"""
1273     try:
1274         _test_gas_anqp_address3_not_assoc(dev, apdev, params)
1275     finally:
1276         dev[0].request("SET gas_address3 0")
1277 
1278 def _test_gas_anqp_address3_not_assoc(dev, apdev, params):
1279     hapd = start_ap(apdev[0])
1280     bssid = apdev[0]['bssid']
1281 
1282     if "OK" not in dev[0].request("SET gas_address3 1"):
1283         raise Exception("Failed to set gas_address3")
1284 
1285     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1286     if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
1287         raise Exception("ANQP_GET command failed")
1288 
1289     ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
1290     if ev is None:
1291         raise Exception("GAS query start timed out")
1292 
1293     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
1294     if ev is None:
1295         raise Exception("GAS query timed out")
1296 
1297     ev = dev[0].wait_event(["RX-ANQP"], timeout=1)
1298     if ev is None or "Venue Name" not in ev:
1299         raise Exception("Did not receive Venue Name")
1300 
1301     ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
1302     if ev is None:
1303         raise Exception("ANQP-QUERY-DONE event not seen")
1304     if "result=SUCCESS" not in ev:
1305         raise Exception("Unexpected result: " + ev)
1306 
1307     time.sleep(1)
1308     out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
1309                      "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)",
1310                      display=["wlan.bssid"])
1311     logger.info("tshark output:\n" + out)
1312     res = out.splitlines()
1313     if len(res) != 2:
1314         logger.info("res: " + str(res))
1315         raise Exception("Unexpected number of GAS frames")
1316     if res[0] != 'ff:ff:ff:ff:ff:ff':
1317         raise Exception("GAS request used unexpected Address3 field value: " + res[0])
1318     if res[1] != 'ff:ff:ff:ff:ff:ff':
1319         raise Exception("GAS response used unexpected Address3 field value: " + res[1])
1320 
1321 def test_gas_anqp_address3_assoc(dev, apdev, params):
1322     """GAS/ANQP query using IEEE 802.11 compliant Address 3 value when associated"""
1323     try:
1324         _test_gas_anqp_address3_assoc(dev, apdev, params)
1325     finally:
1326         dev[0].request("SET gas_address3 0")
1327 
1328 def _test_gas_anqp_address3_assoc(dev, apdev, params):
1329     hapd = start_ap(apdev[0])
1330     bssid = apdev[0]['bssid']
1331 
1332     if "OK" not in dev[0].request("SET gas_address3 1"):
1333         raise Exception("Failed to set gas_address3")
1334 
1335     dev[0].scan_for_bss(bssid, freq="2412")
1336     dev[0].connect("test-gas", key_mgmt="WPA-EAP", eap="TTLS",
1337                    identity="DOMAIN\\mschapv2 user", anonymous_identity="ttls",
1338                    password="password", phase2="auth=MSCHAPV2",
1339                    ca_cert="auth_serv/ca.pem", scan_freq="2412")
1340     hapd.wait_sta()
1341 
1342     if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
1343         raise Exception("ANQP_GET command failed")
1344 
1345     ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
1346     if ev is None:
1347         raise Exception("GAS query start timed out")
1348 
1349     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
1350     if ev is None:
1351         raise Exception("GAS query timed out")
1352 
1353     ev = dev[0].wait_event(["RX-ANQP"], timeout=1)
1354     if ev is None or "Venue Name" not in ev:
1355         raise Exception("Did not receive Venue Name")
1356 
1357     ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
1358     if ev is None:
1359         raise Exception("ANQP-QUERY-DONE event not seen")
1360     if "result=SUCCESS" not in ev:
1361         raise Exception("Unexpected result: " + ev)
1362 
1363     time.sleep(1)
1364     out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
1365                      "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)",
1366                      display=["wlan.bssid"])
1367     logger.info("tshark output:\n" + out)
1368     res = out.splitlines()
1369     if len(res) != 2:
1370         logger.info("res: " + str(res))
1371         raise Exception("Unexpected number of GAS frames")
1372     if res[0] != bssid:
1373         raise Exception("GAS request used unexpected Address3 field value: " + res[0])
1374     if res[1] != bssid:
1375         raise Exception("GAS response used unexpected Address3 field value: " + res[1])
1376 
1377 def test_gas_anqp_address3_ap_forced(dev, apdev, params):
1378     """GAS/ANQP query using IEEE 802.11 compliant Address 3 value on AP"""
1379     hapd = start_ap(apdev[0])
1380     bssid = apdev[0]['bssid']
1381     hapd.set("gas_address3", "1")
1382 
1383     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1384     if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
1385         raise Exception("ANQP_GET command failed")
1386 
1387     ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
1388     if ev is None:
1389         raise Exception("GAS query start timed out")
1390 
1391     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
1392     if ev is None:
1393         raise Exception("GAS query timed out")
1394 
1395     ev = dev[0].wait_event(["RX-ANQP"], timeout=1)
1396     if ev is None or "Venue Name" not in ev:
1397         raise Exception("Did not receive Venue Name")
1398 
1399     ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
1400     if ev is None:
1401         raise Exception("ANQP-QUERY-DONE event not seen")
1402     if "result=SUCCESS" not in ev:
1403         raise Exception("Unexpected result: " + ev)
1404 
1405     time.sleep(1)
1406     out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
1407                      "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)",
1408                      display=["wlan.bssid"])
1409     logger.info("tshark output:\n" + out)
1410     res = out.splitlines()
1411     if len(res) != 2:
1412         logger.info("res: " + str(res))
1413         raise Exception("Unexpected number of GAS frames")
1414     if res[0] != bssid:
1415         raise Exception("GAS request used unexpected Address3 field value: " + res[0])
1416     if res[1] != 'ff:ff:ff:ff:ff:ff':
1417         raise Exception("GAS response used unexpected Address3 field value: " + res[1])
1418 
1419 def test_gas_anqp_address3_ap_non_compliant(dev, apdev, params):
1420     """GAS/ANQP query using IEEE 802.11 non-compliant Address 3 (AP)"""
1421     try:
1422         _test_gas_anqp_address3_ap_non_compliant(dev, apdev, params)
1423     finally:
1424         dev[0].request("SET gas_address3 0")
1425 
1426 def _test_gas_anqp_address3_ap_non_compliant(dev, apdev, params):
1427     hapd = start_ap(apdev[0])
1428     bssid = apdev[0]['bssid']
1429     hapd.set("gas_address3", "2")
1430 
1431     if "OK" not in dev[0].request("SET gas_address3 1"):
1432         raise Exception("Failed to set gas_address3")
1433 
1434     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1435     if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
1436         raise Exception("ANQP_GET command failed")
1437 
1438     ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
1439     if ev is None:
1440         raise Exception("GAS query start timed out")
1441 
1442     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
1443     if ev is None:
1444         raise Exception("GAS query timed out")
1445 
1446     ev = dev[0].wait_event(["RX-ANQP"], timeout=1)
1447     if ev is None or "Venue Name" not in ev:
1448         raise Exception("Did not receive Venue Name")
1449 
1450     ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
1451     if ev is None:
1452         raise Exception("ANQP-QUERY-DONE event not seen")
1453     if "result=SUCCESS" not in ev:
1454         raise Exception("Unexpected result: " + ev)
1455 
1456     time.sleep(1)
1457     out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
1458                      "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)",
1459                      display=["wlan.bssid"])
1460     logger.info("tshark output:\n" + out)
1461     res = out.splitlines()
1462     if len(res) != 2:
1463         logger.info("res: " + str(res))
1464         raise Exception("Unexpected number of GAS frames")
1465     if res[0] != 'ff:ff:ff:ff:ff:ff':
1466         raise Exception("GAS request used unexpected Address3 field value: " + res[0])
1467     if res[1] != bssid:
1468         raise Exception("GAS response used unexpected Address3 field value: " + res[1])
1469 
1470 def test_gas_anqp_address3_pmf(dev, apdev):
1471     """GAS/ANQP query using IEEE 802.11 compliant Address 3 value with PMF"""
1472     try:
1473         _test_gas_anqp_address3_pmf(dev, apdev)
1474     finally:
1475         dev[0].request("SET gas_address3 0")
1476 
1477 def _test_gas_anqp_address3_pmf(dev, apdev):
1478     hapd = start_ap(apdev[0])
1479     bssid = apdev[0]['bssid']
1480     hapd.set("gas_comeback_delay", "2")
1481     hapd.set("gas_address3", "1")
1482 
1483     if "OK" not in dev[0].request("SET gas_address3 1"):
1484         raise Exception("Failed to set gas_address3")
1485 
1486     dev[0].scan_for_bss(bssid, freq="2412")
1487     dev[0].connect("test-gas", key_mgmt="WPA-EAP", eap="TTLS",
1488                    identity="DOMAIN\\mschapv2 user", anonymous_identity="ttls",
1489                    password="password", phase2="auth=MSCHAPV2",
1490                    ca_cert="auth_serv/ca.pem", scan_freq="2412",
1491                    ieee80211w="2")
1492     hapd.wait_sta()
1493 
1494     if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
1495         raise Exception("ANQP_GET command failed")
1496 
1497     ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
1498     if ev is None:
1499         raise Exception("GAS query start timed out")
1500 
1501     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
1502     if ev is None:
1503         raise Exception("GAS query timed out")
1504 
1505     ev = dev[0].wait_event(["RX-ANQP"], timeout=1)
1506     if ev is None or "Venue Name" not in ev:
1507         raise Exception("Did not receive Venue Name")
1508 
1509     ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
1510     if ev is None:
1511         raise Exception("ANQP-QUERY-DONE event not seen")
1512     if "result=SUCCESS" not in ev:
1513         raise Exception("Unexpected result: " + ev)
1514 
1515     req = dev[0].request("GAS_REQUEST " + bssid + " 42 000102000101")
1516     if "FAIL" in req:
1517         raise Exception("GAS query request rejected")
1518     expect_gas_result(dev[0], "FAILURE", "59")
1519 
1520 def test_gas_prot_vs_not_prot(dev, apdev, params):
1521     """GAS/ANQP query protected vs. not protected"""
1522     hapd = start_ap(apdev[0])
1523     bssid = apdev[0]['bssid']
1524 
1525     dev[0].scan_for_bss(bssid, freq="2412")
1526     dev[0].connect("test-gas", key_mgmt="WPA-EAP", eap="TTLS",
1527                    identity="DOMAIN\\mschapv2 user", anonymous_identity="ttls",
1528                    password="password", phase2="auth=MSCHAPV2",
1529                    ca_cert="auth_serv/ca.pem", scan_freq="2412",
1530                    ieee80211w="2")
1531     hapd.wait_sta()
1532 
1533     if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
1534         raise Exception("ANQP_GET command failed")
1535 
1536     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5)
1537     if ev is None:
1538         raise Exception("No GAS-QUERY-DONE event")
1539     if "result=SUCCESS" not in ev:
1540         raise Exception("Unexpected GAS result: " + ev)
1541 
1542     # GAS: Drop unexpected unprotected GAS frame when PMF is enabled
1543     dev[0].request("SET ext_mgmt_frame_handling 1")
1544     res = dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=d0003a010200000000000200000003000200000003001000040b00000005006c027f000000")
1545     dev[0].request("SET ext_mgmt_frame_handling 0")
1546     if "OK" not in res:
1547         raise Exception("MGMT_RX_PROCESS failed")
1548 
1549     dev[0].request("DISCONNECT")
1550     dev[0].wait_disconnected()
1551 
1552     # GAS: No pending query found for 02:00:00:00:03:00 dialog token 0
1553     dev[0].request("SET ext_mgmt_frame_handling 1")
1554     res = dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=d0003a010200000000000200000003000200000003001000040b00000005006c027f000000")
1555     dev[0].request("SET ext_mgmt_frame_handling 0")
1556     if "OK" not in res:
1557         raise Exception("MGMT_RX_PROCESS failed")
1558 
1559     # GAS: Drop unexpected protected GAS frame when PMF is disabled
1560     dev[0].request("SET ext_mgmt_frame_handling 1")
1561     res = dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=d0003a010200000000000200000003000200000003001000090b00000005006c027f000000")
1562     dev[0].request("SET ext_mgmt_frame_handling 0")
1563     if "OK" not in res:
1564         raise Exception("MGMT_RX_PROCESS failed")
1565 
1566 def test_gas_failures(dev, apdev):
1567     """GAS failure cases"""
1568     hapd = start_ap(apdev[0])
1569     hapd.set("gas_comeback_delay", "5")
1570     bssid = apdev[0]['bssid']
1571 
1572     hapd2 = start_ap(apdev[1])
1573     bssid2 = apdev[1]['bssid']
1574 
1575     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1576     dev[0].scan_for_bss(bssid2, freq="2412")
1577 
1578     tests = [(bssid, "gas_build_req;gas_query_tx_comeback_req"),
1579              (bssid, "gas_query_tx;gas_query_tx_comeback_req"),
1580              (bssid, "gas_query_append;gas_query_rx_comeback"),
1581              (bssid2, "gas_query_append;gas_query_rx_initial"),
1582              (bssid2, "wpabuf_alloc_copy;gas_query_rx_initial"),
1583              (bssid, "gas_query_tx;gas_query_tx_initial_req")]
1584     for addr, func in tests:
1585         with alloc_fail(dev[0], 1, func):
1586             dev[0].request("ANQP_GET " + addr + " 258")
1587             ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5)
1588             if ev is None:
1589                 raise Exception("No GAS-QUERY-DONE seen")
1590             if "result=INTERNAL_ERROR" not in ev:
1591                 raise Exception("Unexpected result code: " + ev)
1592         dev[0].dump_monitor()
1593 
1594     tests = ["=gas_query_req", "radio_add_work;gas_query_req"]
1595     for func in tests:
1596         with alloc_fail(dev[0], 1, func):
1597             if "FAIL" not in dev[0].request("ANQP_GET " + bssid + " 258"):
1598                 raise Exception("ANQP_GET succeeded unexpectedly during OOM")
1599         dev[0].dump_monitor()
1600 
1601     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1602     wpas.interface_add("wlan5")
1603     wpas.scan_for_bss(bssid2, freq="2412")
1604     wpas.request("SET preassoc_mac_addr 1")
1605     with fail_test(wpas, 1, "random_mac_addr"):
1606         wpas.request("ANQP_GET " + bssid2 + " 258")
1607         ev = wpas.wait_event(["Failed to assign random MAC address for GAS"],
1608                              timeout=5)
1609     wpas.request("SET preassoc_mac_addr 0")
1610     if ev is None:
1611         raise Exception("No random MAC address error seen")
1612 
1613 def test_gas_anqp_venue_url(dev, apdev):
1614     """GAS/ANQP and Venue URL"""
1615     venue_group = 1
1616     venue_type = 13
1617     venue_info = struct.pack('BB', venue_group, venue_type)
1618     lang1 = "eng"
1619     name1 = "Example venue"
1620     lang2 = "fin"
1621     name2 = "Esimerkkipaikka"
1622     venue1 = struct.pack('B', len(lang1 + name1)) + lang1.encode() + name1.encode()
1623     venue2 = struct.pack('B', len(lang2 + name2)) + lang2.encode() + name2.encode()
1624     venue_name = binascii.hexlify(venue_info + venue1 + venue2).decode()
1625 
1626     url1 = b"http://example.com/venue"
1627     url2 = b"https://example.org/venue-info/"
1628     duple1 = struct.pack('BB', 1 + len(url1), 1) + url1
1629     duple2 = struct.pack('BB', 1 + len(url2), 2) + url2
1630     venue_url = binascii.hexlify(duple1 + duple2).decode()
1631 
1632     params = {"ssid": "gas/anqp",
1633               "interworking": "1",
1634               "venue_group": str(venue_group),
1635               "venue_type": str(venue_type),
1636               "venue_name": [lang1 + ":" + name1, lang2 + ":" + name2],
1637               "anqp_elem": ["277:" + venue_url]}
1638     hapd = hostapd.add_ap(apdev[0], params)
1639     bssid = apdev[0]['bssid']
1640 
1641     dev[0].flush_scan_cache()
1642     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1643     if "OK" not in dev[0].request("ANQP_GET " + bssid + " 257,258,277"):
1644         raise Exception("ANQP_GET command failed")
1645 
1646     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
1647     if ev is None:
1648         raise Exception("GAS query timed out")
1649 
1650     ev = dev[0].wait_event(["RX-VENUE-URL"], timeout=0.1)
1651     if ev is not None:
1652         raise Exception("Unexpected Venue URL indication without PMF")
1653 
1654     bss = dev[0].get_bss(bssid)
1655 
1656     if 'anqp_venue_name' not in bss:
1657         raise Exception("Venue Name ANQP-element not seen")
1658     if bss['anqp_venue_name'] != venue_name:
1659         raise Exception("Unexpected Venue Name ANQP-element value: " + bss['anqp_venue_name'])
1660     if 'anqp[277]' not in bss:
1661         raise Exception("Venue URL ANQP-element not seen")
1662     if bss['anqp[277]'] != venue_url:
1663         raise Exception("Unexpected Venue URL ANQP-element value: " + bss['anqp[277]'])
1664 
1665     if 'anqp_capability_list' not in bss:
1666         raise Exception("Capability List ANQP-element not seen")
1667     ids = struct.pack('<HHH', 257, 258, 277)
1668     if not bss['anqp_capability_list'].startswith(binascii.hexlify(ids).decode()):
1669         raise Exception("Unexpected Capability List ANQP-element value: " + bss['anqp_capability_list'])
1670 
1671     if "anqp[277]" not in bss:
1672         raise Exception("Venue-URL ANQP info not available")
1673     if "protected-anqp-info[277]" in bss:
1674         raise Exception("Unexpected Venue-URL protection info")
1675 
1676 def test_gas_anqp_venue_url2(dev, apdev):
1677     """GAS/ANQP and Venue URL (hostapd venue_url)"""
1678     venue_group = 1
1679     venue_type = 13
1680     venue_info = struct.pack('BB', venue_group, venue_type)
1681     lang1 = "eng"
1682     name1 = "Example venue"
1683     lang2 = "fin"
1684     name2 = "Esimerkkipaikka"
1685     venue1 = struct.pack('B', len(lang1 + name1)) + lang1.encode() + name1.encode()
1686     venue2 = struct.pack('B', len(lang2 + name2)) + lang2.encode() + name2.encode()
1687     venue_name = binascii.hexlify(venue_info + venue1 + venue2).decode()
1688 
1689     url1 = "http://example.com/venue"
1690     url2 = "https://example.org/venue-info/"
1691     duple1 = struct.pack('BB', 1 + len(url1.encode()), 1) + url1.encode()
1692     duple2 = struct.pack('BB', 1 + len(url2.encode()), 2) + url2.encode()
1693     venue_url = binascii.hexlify(duple1 + duple2).decode()
1694 
1695     params = {"ssid": "gas/anqp",
1696               "interworking": "1",
1697               "venue_group": str(venue_group),
1698               "venue_type": str(venue_type),
1699               "venue_name": [lang1 + ":" + name1, lang2 + ":" + name2],
1700               "venue_url": ["1:" + url1, "2:" + url2]}
1701     hapd = hostapd.add_ap(apdev[0], params)
1702     bssid = apdev[0]['bssid']
1703 
1704     dev[0].flush_scan_cache()
1705     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1706     if "OK" not in dev[0].request("ANQP_GET " + bssid + " 257,258,277"):
1707         raise Exception("ANQP_GET command failed")
1708 
1709     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
1710     if ev is None:
1711         raise Exception("GAS query timed out")
1712 
1713     bss = dev[0].get_bss(bssid)
1714 
1715     if 'anqp_venue_name' not in bss:
1716         raise Exception("Venue Name ANQP-element not seen")
1717     if bss['anqp_venue_name'] != venue_name:
1718         raise Exception("Unexpected Venue Name ANQP-element value: " + bss['anqp_venue_name'])
1719     if 'anqp[277]' not in bss:
1720         raise Exception("Venue URL ANQP-element not seen")
1721     if bss['anqp[277]'] != venue_url:
1722         print(venue_url)
1723         raise Exception("Unexpected Venue URL ANQP-element value: " + bss['anqp[277]'])
1724 
1725     if 'anqp_capability_list' not in bss:
1726         raise Exception("Capability List ANQP-element not seen")
1727     ids = struct.pack('<HHH', 257, 258, 277)
1728     if not bss['anqp_capability_list'].startswith(binascii.hexlify(ids).decode()):
1729         raise Exception("Unexpected Capability List ANQP-element value: " + bss['anqp_capability_list'])
1730 
1731 def test_gas_anqp_venue_url_pmf(dev, apdev):
1732     """GAS/ANQP and Venue URL with PMF"""
1733     venue_group = 1
1734     venue_type = 13
1735     venue_info = struct.pack('BB', venue_group, venue_type)
1736     lang1 = "eng"
1737     name1 = "Example venue"
1738     lang2 = "fin"
1739     name2 = "Esimerkkipaikka"
1740     venue1 = struct.pack('B', len(lang1 + name1)) + lang1.encode() + name1.encode()
1741     venue2 = struct.pack('B', len(lang2 + name2)) + lang2.encode() + name2.encode()
1742     venue_name = binascii.hexlify(venue_info + venue1 + venue2)
1743 
1744     url1 = "http://example.com/venue"
1745     url2 = "https://example.org/venue-info/"
1746 
1747     params = {"ssid": "gas/anqp/pmf",
1748               "wpa": "2",
1749               "wpa_key_mgmt": "WPA-PSK",
1750               "rsn_pairwise": "CCMP",
1751               "wpa_passphrase": "12345678",
1752               "ieee80211w": "2",
1753               "interworking": "1",
1754               "venue_group": str(venue_group),
1755               "venue_type": str(venue_type),
1756               "venue_name": [lang1 + ":" + name1, lang2 + ":" + name2],
1757               "venue_url": ["1:" + url1, "2:" + url2]}
1758     hapd = hostapd.add_ap(apdev[0], params)
1759     bssid = apdev[0]['bssid']
1760 
1761     dev[0].flush_scan_cache()
1762     dev[0].connect("gas/anqp/pmf", psk="12345678", ieee80211w="2",
1763                    scan_freq="2412")
1764     hapd.wait_sta()
1765     if "OK" not in dev[0].request("ANQP_GET " + bssid + " 277"):
1766         raise Exception("ANQP_GET command failed")
1767 
1768     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
1769     if ev is None:
1770         raise Exception("GAS query timed out")
1771 
1772     ev = dev[0].wait_event(["RX-VENUE-URL"], timeout=5)
1773     if ev is None:
1774         raise Exception("No Venue URL indication seen")
1775     if "1 " + url1 not in ev:
1776         raise Exception("Unexpected Venue URL information: " + ev)
1777 
1778     ev = dev[0].wait_event(["RX-VENUE-URL"], timeout=5)
1779     if ev is None:
1780         raise Exception("No Venue URL indication seen (2)")
1781     if "2 " + url2 not in ev:
1782         raise Exception("Unexpected Venue URL information (2): " + ev)
1783 
1784     bss = dev[0].get_bss(bssid)
1785     if "anqp[277]" not in bss:
1786         raise Exception("Venue-URL ANQP info not available")
1787     if "protected-anqp-info[277]" not in bss:
1788         raise Exception("Venue-URL protection info not available")
1789     if bss["protected-anqp-info[277]"] != "1":
1790         raise Exception("Venue-URL was not indicated to be protected")
1791 
1792 def test_gas_anqp_capab_list(dev, apdev):
1793     """GAS/ANQP and Capability List ANQP-element"""
1794     params = {"ssid": "gas/anqp",
1795               "interworking": "1"}
1796     params["anqp_elem"] = []
1797     for i in range(0, 400):
1798         if i not in [257]:
1799             params["anqp_elem"] += ["%d:010203" % i]
1800     hapd = hostapd.add_ap(apdev[0], params)
1801     bssid = apdev[0]['bssid']
1802 
1803     dev[0].flush_scan_cache()
1804     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1805     if "OK" not in dev[0].request("ANQP_GET " + bssid + " 257"):
1806         raise Exception("ANQP_GET command failed")
1807 
1808     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
1809     if ev is None:
1810         raise Exception("GAS query timed out")
1811 
1812     bss = dev[0].get_bss(bssid)
1813 
1814     if 'anqp_capability_list' not in bss:
1815         raise Exception("Capability List ANQP-element not seen")
1816     val = bss['anqp_capability_list']
1817     logger.info("anqp_capability_list: " + val)
1818     ids = []
1819     while len(val) >= 4:
1820         id_bin = binascii.unhexlify(val[0:4])
1821         id = struct.unpack('<H', id_bin)[0]
1822         if id == 0xdddd:
1823             break
1824         ids.append(id)
1825         val = val[4:]
1826     logger.info("InfoIDs: " + str(ids))
1827     for i in range(257, 300):
1828         if i in [273, 274]:
1829             continue
1830         if i not in ids:
1831             raise Exception("Unexpected Capability List ANQP-element value (missing %d): %s" % (i, bss['anqp_capability_list']))
1832 
1833 def test_gas_server_oom(dev, apdev):
1834     """GAS server OOM"""
1835     bssid = apdev[0]['bssid']
1836     params = hs20_ap_params()
1837     params['hessid'] = bssid
1838     params['gas_comeback_delay'] = "5"
1839     hapd = hostapd.add_ap(apdev[0], params)
1840 
1841     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1842 
1843     tests = ["ap_sta_add;gas_dialog_create",
1844              "=gas_dialog_create",
1845              "wpabuf_alloc_copy;gas_serv_rx_gas_comeback_req"]
1846     for t in tests:
1847         with alloc_fail(hapd, 1, t):
1848             if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
1849                 raise Exception("ANQP_GET command failed")
1850             ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5)
1851             if ev is None:
1852                 raise Exception("No GAS-QUERY-DONE seen")
1853             dev[0].dump_monitor()
1854 
1855     hapd.set("gas_comeback_delay", "0")
1856 
1857     tests = ["gas_serv_build_gas_resp_payload"]
1858     for t in tests:
1859         with alloc_fail(hapd, 1, t):
1860             if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
1861                 raise Exception("ANQP_GET command failed")
1862             ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5)
1863             if ev is None:
1864                 raise Exception("No GAS-QUERY-DONE seen")
1865             dev[0].dump_monitor()
1866 
1867     with alloc_fail(hapd, 1,
1868                     "gas_build_initial_resp;gas_serv_rx_gas_initial_req"):
1869         req = dev[0].request("GAS_REQUEST " + bssid + " 42 000102000101")
1870         if "FAIL" in req:
1871             raise Exception("GAS query request rejected")
1872         ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5)
1873         if ev is None:
1874             raise Exception("No GAS-QUERY-DONE seen")
1875         dev[0].dump_monitor()
1876 
1877     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1878     wpas.interface_add("wlan5")
1879     if "OK" not in wpas.request("P2P_SET listen_channel 1"):
1880         raise Exception("Failed to set listen channel")
1881     if "OK" not in wpas.p2p_listen():
1882         raise Exception("Failed to start listen state")
1883     if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"):
1884         raise Exception("Failed to enable external management frame handling")
1885 
1886     msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_COMEBACK_REQUEST, 1)
1887     req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode())
1888     with alloc_fail(hapd, 1,
1889                     "gas_anqp_build_comeback_resp_buf;gas_serv_rx_gas_comeback_req"):
1890         if "OK" not in wpas.request(req):
1891             raise Exception("Could not send management frame")
1892         wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
1893 
1894 def test_gas_anqp_overrides(dev, apdev):
1895     """GAS and ANQP overrides"""
1896     params = {"ssid": "gas/anqp",
1897               "interworking": "1",
1898               "anqp_elem": ["257:111111",
1899                             "258:222222",
1900                             "260:333333",
1901                             "261:444444",
1902                             "262:555555",
1903                             "263:666666",
1904                             "264:777777",
1905                             "268:888888",
1906                             "275:999999"]}
1907     hapd = hostapd.add_ap(apdev[0], params)
1908     bssid = apdev[0]['bssid']
1909 
1910     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1911     if "OK" not in dev[0].request("ANQP_GET " + bssid + " 257,258,260,261,262,263,264,268,275"):
1912         raise Exception("ANQP_GET command failed")
1913 
1914     ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
1915     if ev is None:
1916         raise Exception("GAS query timed out")
1917     elems = 9
1918     capa = dev[0].get_capability("fils")
1919     if capa is None or "FILS" not in capa:
1920         # FILS Realm Info not supported in the build
1921         elems -= 1
1922     for i in range(elems):
1923         ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1924         if ev is None:
1925             raise Exception("ANQP response not seen")
1926 
1927 def test_gas_no_dialog_token_match(dev, apdev):
1928     """GAS and no dialog token match for comeback request"""
1929     hapd = start_ap(apdev[0])
1930     hapd.set("gas_frag_limit", "50")
1931     bssid = apdev[0]['bssid']
1932 
1933     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1934     wpas.interface_add("wlan5")
1935     if "OK" not in wpas.request("P2P_SET listen_channel 1"):
1936         raise Exception("Failed to set listen channel")
1937     if "OK" not in wpas.p2p_listen():
1938         raise Exception("Failed to start listen state")
1939     if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"):
1940         raise Exception("Failed to enable external management frame handling")
1941 
1942     anqp_query = struct.pack('<HHHHHHHHHH', 256, 16, 257, 258, 260, 261, 262, 263, 264, 268)
1943     gas = struct.pack('<H', len(anqp_query)) + anqp_query
1944 
1945     dialog_token = 100
1946     msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST,
1947                       dialog_token) + anqp_adv_proto() + gas
1948     req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode())
1949     if "OK" not in wpas.request(req):
1950         raise Exception("Could not send management frame")
1951     resp = wpas.mgmt_rx()
1952     if resp is None:
1953         raise Exception("MGMT-RX timeout")
1954     if 'payload' not in resp:
1955         raise Exception("Missing payload")
1956     gresp = parse_gas(resp['payload'])
1957     if gresp['dialog_token'] != dialog_token:
1958         raise Exception("Dialog token mismatch")
1959     status_code = gresp['status_code']
1960     if status_code != 0:
1961         raise Exception("Unexpected status code {}".format(status_code))
1962 
1963     msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_COMEBACK_REQUEST,
1964                       dialog_token + 1)
1965     req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode())
1966     if "OK" not in wpas.request(req):
1967         raise Exception("Could not send management frame")
1968     resp = wpas.mgmt_rx()
1969     if resp is None:
1970         raise Exception("MGMT-RX timeout")
1971     if 'payload' not in resp:
1972         raise Exception("Missing payload")
1973     gresp = parse_gas(resp['payload'])
1974     status_code = gresp['status_code']
1975     if status_code != 60:
1976         raise Exception("Unexpected failure status code {}".format(status_code))
1977 
1978 def test_gas_vendor_spec_errors(dev, apdev):
1979     """GAS and vendor specific request error cases"""
1980     bssid = apdev[0]['bssid']
1981     params = hs20_ap_params()
1982     params['hessid'] = bssid
1983     del params['nai_realm']
1984     hapd = hostapd.add_ap(apdev[0], params)
1985 
1986     dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1987     tests = ["00 12340000",
1988              "00 dddd0300506fff",
1989              "00 dddd0400506fffff",
1990              "00 dddd0400506f9aff",
1991              "00 dddd0400506f9a11",
1992              "00 dddd0600506f9a11ff00",
1993              "00 dddd0600506f9a110600",
1994              "00 dddd0600506f9a110600",
1995              "00 dddd0700506f9a11060000",
1996              "00 dddd0700506f9a110600ff",
1997              "00 dddd0800506f9a110600ff00",
1998              "00 dddd0900506f9a110600ff0000",
1999              "00 dddd0900506f9a110600ff0001",
2000              "00 dddd0900506f9a110600ffff00",
2001              "00 dddd0a00506f9a110600ff00013b",
2002              "00 dddd0700506f9a110100ff",
2003              "00 dddd0700506f9a11010008",
2004              "00 dddd14",
2005              "00 dddd1400506f9a11"]
2006     for t in tests:
2007         req = dev[0].request("GAS_REQUEST " + bssid + " " + t)
2008         if "FAIL" in req:
2009             raise Exception("GAS query request rejected")
2010         ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
2011         if ev is None:
2012             raise Exception("GAS query did not start")
2013         ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5)
2014         if ev is None:
2015             raise Exception("GAS query did not complete")
2016         if t == "00 dddd0600506f9a110600":
2017             hapd.set("nai_realm", "0,another.example.com")
2018 
2019     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
2020     wpas.interface_add("wlan5")
2021     if "OK" not in wpas.request("P2P_SET listen_channel 1"):
2022         raise Exception("Failed to set listen channel")
2023     if "OK" not in wpas.p2p_listen():
2024         raise Exception("Failed to start listen state")
2025     if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"):
2026         raise Exception("Failed to enable external management frame handling")
2027 
2028     anqp_query = struct.pack('<HHHHHHHHHH', 256, 16, 257, 258, 260, 261, 262, 263, 264, 268)
2029     gas = struct.pack('<H', len(anqp_query)) + anqp_query
2030 
2031     dialog_token = 100
2032     adv = struct.pack('BBBB', 109, 2, 0, 0)
2033     adv2 = struct.pack('BBB', 108, 1, 0)
2034     adv3 = struct.pack('BBBB', 108, 3, 0, 0)
2035     msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST,
2036                       dialog_token) + adv + gas
2037     msg2 = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST,
2038                        dialog_token) + adv2 + gas
2039     msg3 = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST,
2040                        dialog_token) + adv3
2041     msg4 = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST,
2042                        dialog_token) + anqp_adv_proto()
2043     msg5 = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST,
2044                        dialog_token) + anqp_adv_proto() + struct.pack('<H', 1)
2045     msg6 = struct.pack('<BB', ACTION_CATEG_PUBLIC, GAS_COMEBACK_REQUEST)
2046     tests = [msg, msg2, msg3, msg4, msg5, msg6]
2047     for t in tests:
2048         req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(t).decode())
2049         if "OK" not in wpas.request(req):
2050             raise Exception("Could not send management frame")
2051         ev = wpas.wait_event(["MGMT-TX-STATUS"], timeout=5)
2052         if ev is None:
2053             raise Exception("No ACK frame seen")
2054