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
8from remotehost import remote_compatible
9import time
10import binascii
11import logging
12logger = logging.getLogger()
13import os
14import re
15import struct
16
17import hostapd
18from wpasupplicant import WpaSupplicant
19from tshark import run_tshark
20from utils import *
21from hwsim import HWSimRadio
22
23def 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
55def start_ap(ap):
56    params = hs20_ap_params()
57    params['hessid'] = ap['bssid']
58    return hostapd.add_ap(ap, params)
59
60def 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
106def 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
141def 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
152def _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
189def 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
231def 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
294def 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
318def test_gas_fragment(dev, apdev):
319    """GAS fragmentation"""
320    gas_fragment_and_comeback(dev[0], apdev[0], frag_limit=50)
321
322def 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
329def 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
334def 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
342def test_gas_comeback_delay(dev, apdev):
343    """GAS comeback delay"""
344    run_gas_comeback_delay(dev, apdev, 500)
345
346def test_gas_comeback_delay_long(dev, apdev):
347    """GAS long comeback delay"""
348    run_gas_comeback_delay(dev, apdev, 2500)
349
350def 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
354def 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
368def 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
383def 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
499def 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
518def 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
534def 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
556def 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
565def 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
572def 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
588MGMT_SUBTYPE_ACTION = 13
589ACTION_CATEG_PUBLIC = 4
590
591GAS_INITIAL_REQUEST = 10
592GAS_INITIAL_RESPONSE = 11
593GAS_COMEBACK_REQUEST = 12
594GAS_COMEBACK_RESPONSE = 13
595GAS_ACTIONS = [GAS_INITIAL_REQUEST, GAS_INITIAL_RESPONSE,
596               GAS_COMEBACK_REQUEST, GAS_COMEBACK_RESPONSE]
597
598def anqp_adv_proto():
599    return struct.pack('BBBB', 108, 2, 127, 0)
600
601def 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
605def 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
615def 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
633def 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
666def 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
674def 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
682def 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
703def 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
722def 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
788def 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
806def 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
813def 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
911def 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
935def 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
960def 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
986def 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
1024def 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
1052def 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
1071def 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
1098def 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
1123def 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
1141def 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
1191def 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
1271def 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
1278def _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
1321def 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
1328def _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
1377def 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
1419def 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
1426def _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
1470def 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
1477def _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
1520def 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
1566def 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
1613def 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
1676def 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
1731def 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
1792def 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
1833def 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
1894def 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
1927def 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
1978def 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