1# P2P device discovery test cases
2# Copyright (c) 2013, Jouni Malinen <j@w1.fi>
3#
4# This software may be distributed under the terms of the BSD license.
5# See README for more details.
6
7from remotehost import remote_compatible
8import logging
9logger = logging.getLogger()
10import binascii
11import os
12import struct
13import time
14
15import hostapd
16import hwsim_utils
17from wpasupplicant import WpaSupplicant
18from p2p_utils import *
19from hwsim import HWSimRadio
20from tshark import run_tshark
21from test_gas import start_ap
22from test_cfg80211 import nl80211_remain_on_channel
23from test_p2p_channel import set_country
24
25@remote_compatible
26def test_discovery(dev):
27    """P2P device discovery and provision discovery"""
28    addr0 = dev[0].p2p_dev_addr()
29    addr1 = dev[1].p2p_dev_addr()
30    logger.info("Start device discovery")
31    dev[0].p2p_find(social=True, delay=1)
32    if not dev[1].discover_peer(addr0):
33        raise Exception("Device discovery timed out")
34    if not dev[0].discover_peer(addr1):
35        raise Exception("Device discovery timed out")
36
37    logger.info("Test provision discovery for display")
38    dev[0].global_request("P2P_PROV_DISC " + addr1 + " display")
39    ev1 = dev[1].wait_global_event(["P2P-PROV-DISC-SHOW-PIN"], timeout=15)
40    if ev1 is None:
41        raise Exception("Provision discovery timed out (display/dev1)")
42    if addr0 not in ev1:
43        raise Exception("Dev0 not in provision discovery event")
44    ev0 = dev[0].wait_global_event(["P2P-PROV-DISC-ENTER-PIN",
45                                    "P2P-PROV-DISC-FAILURE"], timeout=15)
46    if ev0 is None:
47        raise Exception("Provision discovery timed out (display/dev0)")
48    if "P2P-PROV-DISC-FAILURE" in ev0:
49        raise Exception("Provision discovery failed (display/dev0)")
50    if addr1 not in ev0:
51        raise Exception("Dev1 not in provision discovery event")
52
53    logger.info("Test provision discovery for keypad")
54    dev[0].global_request("P2P_PROV_DISC " + addr1 + " keypad")
55    ev1 = dev[1].wait_global_event(["P2P-PROV-DISC-ENTER-PIN"], timeout=15)
56    if ev1 is None:
57        raise Exception("Provision discovery timed out (keypad/dev1)")
58    if addr0 not in ev1:
59        raise Exception("Dev0 not in provision discovery event")
60    ev0 = dev[0].wait_global_event(["P2P-PROV-DISC-SHOW-PIN",
61                                    "P2P-PROV-DISC-FAILURE"],
62                                   timeout=15)
63    if ev0 is None:
64        raise Exception("Provision discovery timed out (keypad/dev0)")
65    if "P2P-PROV-DISC-FAILURE" in ev0:
66        raise Exception("Provision discovery failed (keypad/dev0)")
67    if addr1 not in ev0:
68        raise Exception("Dev1 not in provision discovery event")
69
70    logger.info("Test provision discovery for push button")
71    dev[0].global_request("P2P_PROV_DISC " + addr1 + " pbc")
72    ev1 = dev[1].wait_global_event(["P2P-PROV-DISC-PBC-REQ"], timeout=15)
73    if ev1 is None:
74        raise Exception("Provision discovery timed out (pbc/dev1)")
75    if addr0 not in ev1:
76        raise Exception("Dev0 not in provision discovery event")
77    ev0 = dev[0].wait_global_event(["P2P-PROV-DISC-PBC-RESP",
78                                    "P2P-PROV-DISC-FAILURE"],
79                                   timeout=15)
80    if ev0 is None:
81        raise Exception("Provision discovery timed out (pbc/dev0)")
82    if "P2P-PROV-DISC-FAILURE" in ev0:
83        raise Exception("Provision discovery failed (pbc/dev0)")
84    if addr1 not in ev0:
85        raise Exception("Dev1 not in provision discovery event")
86
87    dev[0].p2p_stop_find()
88    dev[1].p2p_stop_find()
89
90    if "FAIL" not in dev[0].p2p_find(dev_id="foo"):
91        raise Exception("P2P_FIND with invalid dev_id accepted")
92    if "FAIL" not in dev[0].p2p_find(dev_type="foo"):
93        raise Exception("P2P_FIND with invalid dev_type accepted")
94    if "FAIL" not in dev[0].p2p_find(dev_type="1-foo-2"):
95        raise Exception("P2P_FIND with invalid dev_type accepted")
96    if "FAIL" not in dev[0].p2p_find(dev_type="1-11223344"):
97        raise Exception("P2P_FIND with invalid dev_type accepted")
98
99    if "FAIL" not in dev[0].global_request("P2P_PROV_DISC foo pbc"):
100        raise Exception("Invalid P2P_PROV_DISC accepted")
101    if "FAIL" not in dev[0].global_request("P2P_PROV_DISC 00:11:22:33:44:55"):
102        raise Exception("Invalid P2P_PROV_DISC accepted")
103    if "FAIL" not in dev[0].global_request("P2P_PROV_DISC 00:11:22:33:44:55 pbc join"):
104        raise Exception("Invalid P2P_PROV_DISC accepted")
105    if "FAIL" not in dev[0].global_request("P2P_PROV_DISC 00:11:22:33:44:55 foo"):
106        raise Exception("Invalid P2P_PROV_DISC accepted")
107
108@remote_compatible
109def test_discovery_pd_retries(dev):
110    """P2P device discovery and provision discovery retries"""
111    addr0 = dev[0].p2p_dev_addr()
112    addr1 = dev[1].p2p_dev_addr()
113    dev[1].p2p_listen()
114    if not dev[0].discover_peer(addr1):
115        raise Exception("Device discovery timed out")
116    dev[1].p2p_stop_find()
117    dev[0].p2p_stop_find()
118    dev[0].global_request("P2P_PROV_DISC " + addr1 + " display")
119    ev = dev[0].wait_global_event(["P2P-PROV-DISC-FAILURE"], timeout=60)
120    if ev is None:
121        raise Exception("No PD failure reported")
122
123def test_discovery_group_client(dev):
124    """P2P device discovery for a client in a group"""
125    logger.info("Start autonomous GO " + dev[0].ifname)
126    res = dev[0].p2p_start_go(freq="2422")
127    logger.debug("res: " + str(res))
128    logger.info("Connect a client to the GO")
129    pin = dev[1].wps_read_pin()
130    dev[0].p2p_go_authorize_client(pin)
131    dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), pin, freq=int(res['freq']),
132                             timeout=60)
133    logger.info("Client connected")
134    hwsim_utils.test_connectivity_p2p(dev[0], dev[1])
135    logger.info("Try to discover a P2P client in a group")
136    if not dev[2].discover_peer(dev[1].p2p_dev_addr(), social=False, timeout=10):
137        stop_p2p_find_and_wait(dev[2])
138        if not dev[2].discover_peer(dev[1].p2p_dev_addr(), social=False, timeout=10):
139            stop_p2p_find_and_wait(dev[2])
140            if not dev[2].discover_peer(dev[1].p2p_dev_addr(), social=False, timeout=10):
141                raise Exception("Could not discover group client")
142
143    # This is not really perfect, but something to get a bit more testing
144    # coverage.. For proper discoverability mechanism validation, the P2P
145    # client would need to go to sleep to avoid acknowledging the GO Negotiation
146    # Request frame. Offchannel Listen mode operation on the P2P Client with
147    # mac80211_hwsim is apparently not enough to avoid the acknowledgement on
148    # the operating channel, so need to disconnect from the group which removes
149    # the GO-to-P2P Client part of the discoverability exchange in practice.
150
151    pin = dev[2].wps_read_pin()
152    # make group client non-responsive on operating channel
153    dev[1].dump_monitor()
154    dev[1].group_request("DISCONNECT")
155    ev = dev[1].wait_group_event(["CTRL-EVENT-DISCONNECTED"], timeout=10)
156    if ev is None:
157        raise Exception("Timeout on waiting disconnection")
158    dev[2].request("P2P_CONNECT {} {} display".format(dev[1].p2p_dev_addr(),
159                                                      pin))
160    ev = dev[1].wait_global_event(["P2P-GO-NEG-REQUEST"], timeout=2)
161    if ev:
162        raise Exception("Unexpected frame RX on P2P client")
163    # make group client available on operating channe
164    dev[1].group_request("REASSOCIATE")
165    ev = dev[1].wait_global_event(["CTRL-EVENT-CONNECTED",
166                                   "P2P-GO-NEG-REQUEST"], timeout=15)
167    if ev is None:
168        raise Exception("Timeout on reconnection to group")
169    if "P2P-GO-NEG-REQUEST" not in ev:
170        ev = dev[1].wait_global_event(["P2P-GO-NEG-REQUEST"], timeout=10)
171        if ev is None:
172            raise Exception("Timeout on waiting for GO Negotiation Request")
173
174def stop_p2p_find_and_wait(dev):
175    dev.request("P2P_STOP_FIND")
176    for i in range(10):
177        res = dev.get_driver_status_field("scan_state")
178        if "SCAN_STARTED" not in res and "SCAN_REQUESTED" not in res:
179            break
180        logger.debug("Waiting for final P2P_FIND scan to complete")
181        time.sleep(0.02)
182
183def test_discovery_ctrl_char_in_devname(dev):
184    """P2P device discovery and control character in Device Name"""
185    try:
186        _test_discovery_ctrl_char_in_devname(dev)
187    finally:
188        dev[1].global_request("SET device_name Device B")
189
190def _test_discovery_ctrl_char_in_devname(dev):
191    dev[1].global_request("SET device_name Device\tB")
192    addr0 = dev[0].p2p_dev_addr()
193    addr1 = dev[1].p2p_dev_addr()
194    res = dev[0].p2p_start_go(freq=2422)
195    bssid = dev[0].p2p_interface_addr()
196    pin = dev[1].wps_read_pin()
197    dev[0].p2p_go_authorize_client(pin)
198    dev[1].scan_for_bss(bssid, freq=2422)
199    dev[1].p2p_connect_group(addr0, pin, timeout=60, freq=2422)
200    if not dev[2].discover_peer(addr1, social=False, freq=2422, timeout=5):
201        stop_p2p_find_and_wait(dev[2])
202        if not dev[2].discover_peer(addr1, social=False, freq=2422, timeout=5):
203            stop_p2p_find_and_wait(dev[2])
204            if not dev[2].discover_peer(addr1, social=False, freq=2422,
205                                        timeout=5):
206                raise Exception("Could not discover group client")
207    devname = dev[2].get_peer(addr1)['device_name']
208    dev[2].p2p_stop_find()
209    if devname != "Device_B":
210        raise Exception("Unexpected device_name from group client: " + devname)
211
212    terminate_group(dev[0], dev[1])
213    dev[2].request("P2P_FLUSH")
214
215    dev[1].p2p_listen()
216    if not dev[2].discover_peer(addr1, social=True, timeout=10):
217        raise Exception("Could not discover peer")
218    devname = dev[2].get_peer(addr1)['device_name']
219    dev[2].p2p_stop_find()
220    if devname != "Device_B":
221        raise Exception("Unexpected device_name from peer: " + devname)
222
223@remote_compatible
224def test_discovery_dev_type(dev):
225    """P2P device discovery with Device Type filter"""
226    dev[1].request("SET sec_device_type 1-0050F204-2")
227    dev[1].p2p_listen()
228    dev[0].p2p_find(social=True, dev_type="5-0050F204-1")
229    ev = dev[0].wait_global_event(['P2P-DEVICE-FOUND'], timeout=1)
230    if ev:
231        raise Exception("Unexpected P2P device found")
232    dev[0].p2p_find(social=True, dev_type="1-0050F204-2")
233    ev = dev[0].wait_global_event(['P2P-DEVICE-FOUND'], timeout=2)
234    if ev is None:
235        raise Exception("P2P device not found")
236    peer = dev[0].get_peer(dev[1].p2p_dev_addr())
237    if "1-0050F204-2" not in peer['sec_dev_type']:
238        raise Exception("sec_device_type not reported properly")
239
240def test_discovery_dev_type_go(dev):
241    """P2P device discovery with Device Type filter on GO"""
242    addr1 = dev[1].p2p_dev_addr()
243    dev[1].request("SET sec_device_type 1-0050F204-2")
244    res = dev[0].p2p_start_go(freq="2412")
245    pin = dev[1].wps_read_pin()
246    dev[0].p2p_go_authorize_client(pin)
247    dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), pin, timeout=60)
248
249    dev[2].p2p_find(social=True, dev_type="5-0050F204-1")
250    ev = dev[2].wait_global_event(['P2P-DEVICE-FOUND'], timeout=1)
251    if ev:
252        raise Exception("Unexpected P2P device found")
253    dev[2].p2p_find(social=True, dev_type="1-0050F204-2")
254    ev = dev[2].wait_global_event(['P2P-DEVICE-FOUND ' + addr1], timeout=2)
255    if ev is None:
256        raise Exception("P2P device not found")
257
258def test_discovery_dev_id(dev):
259    """P2P device discovery with Device ID filter"""
260    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
261    wpas.interface_add("wlan5")
262    wpas.request("P2P_LISTEN 1")
263    status = wpas.global_request("STATUS")
264    if "p2p_state=LISTEN_ONLY" not in status:
265        raise Exception("Unexpected status: " + status)
266    addr1 = dev[1].p2p_dev_addr()
267    dev[1].p2p_listen()
268    dev[0].p2p_find(social=True, dev_id="02:03:04:05:06:07")
269    ev = dev[0].wait_global_event(['P2P-DEVICE-FOUND'], timeout=1)
270    if ev:
271        raise Exception("Unexpected P2P device found")
272    dev[0].p2p_find(social=True, dev_id=addr1)
273    ev = dev[0].wait_global_event(['P2P-DEVICE-FOUND'], timeout=5)
274    if ev is None:
275        raise Exception("P2P device not found")
276    if addr1 not in ev:
277        raise Exception("Unexpected P2P peer found")
278    status = wpas.global_request("STATUS")
279    for i in range(0, 2):
280        if "p2p_state=IDLE" in status:
281            break
282        time.sleep(0.5)
283        status = wpas.global_request("STATUS")
284    if "p2p_state=IDLE" not in status:
285        raise Exception("Unexpected status: " + status)
286
287def test_discovery_dev_id_go(dev):
288    """P2P device discovery with Device ID filter on GO"""
289    addr1 = dev[1].p2p_dev_addr()
290    res = dev[0].p2p_start_go(freq="2412")
291    pin = dev[1].wps_read_pin()
292    dev[0].p2p_go_authorize_client(pin)
293    dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), pin, timeout=60)
294
295    dev[2].p2p_find(social=True, dev_id="02:03:04:05:06:07")
296    ev = dev[2].wait_global_event(['P2P-DEVICE-FOUND'], timeout=1)
297    if ev:
298        raise Exception("Unexpected P2P device found")
299    dev[2].p2p_find(social=True, dev_id=addr1)
300    ev = dev[2].wait_global_event(['P2P-DEVICE-FOUND ' + addr1], timeout=2)
301    if ev is None:
302        raise Exception("P2P device not found")
303
304def test_discovery_social_plus_one(dev):
305    """P2P device discovery with social-plus-one"""
306    logger.info("Start autonomous GO " + dev[0].ifname)
307    dev[1].p2p_find(social=True)
308    dev[0].p2p_find(progressive=True)
309    logger.info("Wait for initial progressive find phases")
310    dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"])
311    dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"])
312    go = dev[2].p2p_dev_addr()
313    dev[2].p2p_start_go(freq="2422")
314    logger.info("Verify whether the GO on non-social channel can be found")
315    ev = dev[0].wait_global_event(["P2P-DEVICE-FOUND"], timeout=15)
316    if ev is None:
317        raise Exception("Peer not found")
318    if go not in ev:
319        ev = dev[0].wait_global_event(["P2P-DEVICE-FOUND"], timeout=15)
320        if ev is None:
321            raise Exception("Peer not found")
322    ev = dev[1].wait_global_event(["P2P-DEVICE-FOUND"], timeout=15)
323    if ev is None:
324        raise Exception("Peer not found")
325    dev[0].p2p_stop_find()
326    dev[1].p2p_stop_find()
327    if not dev[0].peer_known(go):
328        raise Exception("GO not found in progressive scan")
329    if dev[1].peer_known(go):
330        raise Exception("GO found in social-only scan")
331
332def _test_discovery_and_interface_disabled(dev, delay=1):
333    try:
334        if "OK" not in dev[0].p2p_find():
335            raise Exception("Failed to start P2P find")
336        ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"])
337        if ev is None:
338            raise Exception("Scan did not start")
339        dev[0].request("DRIVER_EVENT INTERFACE_DISABLED")
340        time.sleep(delay)
341
342        # verify that P2P_FIND is rejected
343        if "FAIL" not in dev[0].p2p_find():
344            raise Exception("New P2P_FIND request was accepted unexpectedly")
345
346        dev[0].request("DRIVER_EVENT INTERFACE_ENABLED")
347        time.sleep(3)
348        dev[0].scan(freq="2412")
349        if "OK" not in dev[0].p2p_find():
350            raise Exception("Failed to start P2P find")
351        dev[0].dump_monitor()
352        dev[1].p2p_listen()
353        ev = dev[0].wait_global_event(["P2P-DEVICE-FOUND"], timeout=15)
354        if ev is None:
355            raise Exception("Peer not found")
356    finally:
357        dev[0].request("DRIVER_EVENT INTERFACE_ENABLED")
358
359def test_discovery_and_interface_disabled(dev):
360    """P2P device discovery with interface getting disabled"""
361    _test_discovery_and_interface_disabled(dev, delay=1)
362    _test_discovery_and_interface_disabled(dev, delay=5)
363
364def test_discovery_auto(dev):
365    """P2P device discovery and provision discovery with auto GO/dev selection"""
366    dev[0].flush_scan_cache()
367    addr0 = dev[0].p2p_dev_addr()
368    addr1 = dev[1].p2p_dev_addr()
369    addr2 = dev[2].p2p_dev_addr()
370    dev[2].p2p_start_go(freq="2412")
371    logger.info("Start device discovery")
372    dev[0].p2p_listen()
373    if not dev[1].discover_peer(addr0):
374        raise Exception("Device discovery timed out")
375    dev[1].p2p_listen()
376    if not dev[0].discover_peer(addr1):
377        raise Exception("Device discovery timed out")
378    if not dev[0].discover_peer(addr2):
379        raise Exception("Device discovery timed out")
380
381    logger.info("Test provision discovery for display (device)")
382    dev[0].global_request("P2P_PROV_DISC " + addr1 + " display auto")
383    ev1 = dev[1].wait_global_event(["P2P-PROV-DISC-SHOW-PIN"], timeout=15)
384    if ev1 is None:
385        raise Exception("Provision discovery timed out (display/dev1)")
386    if addr0 not in ev1:
387        raise Exception("Dev0 not in provision discovery event")
388    if " group=" in ev1:
389        raise Exception("Unexpected group parameter from non-GO")
390    ev0 = dev[0].wait_global_event(["P2P-PROV-DISC-ENTER-PIN",
391                                    "P2P-PROV-DISC-FAILURE"], timeout=15)
392    if ev0 is None:
393        raise Exception("Provision discovery timed out (display/dev0)")
394    if "P2P-PROV-DISC-FAILURE" in ev0:
395        raise Exception("Provision discovery failed (display/dev0)")
396    if addr1 not in ev0:
397        raise Exception("Dev1 not in provision discovery event")
398    if "peer_go=0" not in ev0:
399        raise Exception("peer_go incorrect in PD response from non-GO")
400
401    logger.info("Test provision discovery for display (GO)")
402    dev[0].global_request("P2P_PROV_DISC " + addr2 + " display auto")
403    ev2 = dev[2].wait_global_event(["P2P-PROV-DISC-SHOW-PIN"], timeout=15)
404    if ev2 is None:
405        raise Exception("Provision discovery timed out (display/dev2)")
406    if addr0 not in ev2:
407        raise Exception("Dev0 not in provision discovery event")
408    if " group=" not in ev2:
409        raise Exception("Group parameter missing from GO")
410    ev0 = dev[0].wait_global_event(["P2P-PROV-DISC-ENTER-PIN",
411                                    "P2P-PROV-DISC-FAILURE"], timeout=15)
412    if ev0 is None:
413        raise Exception("Provision discovery timed out (display/dev0)")
414    if "P2P-PROV-DISC-FAILURE" in ev0:
415        raise Exception("Provision discovery failed (display/dev0)")
416    if addr2 not in ev0:
417        raise Exception("Dev1 not in provision discovery event")
418    if "peer_go=1" not in ev0:
419        raise Exception("peer_go incorrect in PD response from GO")
420
421def test_discovery_stop(dev):
422    """P2P device discovery and p2p_stop_find"""
423    addr0 = dev[0].p2p_dev_addr()
424    addr1 = dev[1].p2p_dev_addr()
425    dev[1].p2p_listen()
426    dev[2].p2p_listen()
427
428    dev[0].p2p_find(social=False)
429    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.5)
430    if ev is None:
431        logger.info("No CTRL-EVENT-SCAN-STARTED event")
432    dev[0].p2p_stop_find()
433    ev = dev[0].wait_global_event(["P2P-FIND-STOPPED"], timeout=1)
434    if ev is None:
435        raise Exception("P2P_STOP not reported")
436    ev = dev[0].wait_global_event(["P2P-DEVICE-FOUND"], timeout=5)
437    if ev is not None:
438        raise Exception("Peer found unexpectedly: " + ev)
439
440    dev[0].p2p_find(social=False)
441    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.5)
442    if ev is None:
443        logger.info("No CTRL-EVENT-SCAN-STARTED event")
444    dev[0].global_request("P2P_FLUSH")
445    ev = dev[0].wait_global_event(["P2P-FIND-STOPPED"], timeout=1)
446    if ev is None:
447        raise Exception("P2P_STOP not reported")
448    ev = dev[0].wait_global_event(["P2P-DEVICE-FOUND"], timeout=5)
449    if ev is not None:
450        raise Exception("Peer found unexpectedly: " + ev)
451
452def test_discovery_restart(dev):
453    """P2P device discovery and p2p_find restart"""
454    autogo(dev[1], freq=2457)
455    dev[0].p2p_find(social=True)
456    dev[0].p2p_stop_find()
457    dev[0].p2p_find(social=False)
458    ev = dev[0].wait_global_event(["P2P-DEVICE-FOUND"], timeout=7)
459    if ev is None:
460        dev[0].p2p_find(social=False)
461        ev = dev[0].wait_global_event(["P2P-DEVICE-FOUND"], timeout=7)
462        if ev is None:
463            raise Exception("Peer not found")
464
465def test_discovery_restart_progressive(dev):
466    """P2P device discovery and p2p_find type=progressive restart"""
467    try:
468        set_country("US", dev[1])
469        autogo(dev[1], freq=5805)
470        dev[0].p2p_find(social=True)
471        dev[0].p2p_stop_find()
472        dev[0].p2p_find(progressive=True)
473        ev = dev[0].wait_global_event(["P2P-DEVICE-FOUND"], timeout=20)
474        dev[1].remove_group()
475        if ev is None:
476            raise Exception("Peer not found")
477    finally:
478        set_country("00")
479        dev[1].flush_scan_cache()
480
481def test_p2p_peer_command(dev):
482    """P2P_PEER command"""
483    addr0 = dev[0].p2p_dev_addr()
484    addr1 = dev[1].p2p_dev_addr()
485    addr2 = dev[2].p2p_dev_addr()
486    dev[1].p2p_listen()
487    dev[2].p2p_listen()
488    if not dev[0].discover_peer(addr1):
489        raise Exception("Device discovery timed out")
490    if not dev[0].discover_peer(addr2):
491        raise Exception("Device discovery timed out")
492    dev[0].p2p_stop_find()
493    dev[1].p2p_stop_find()
494    dev[2].p2p_stop_find()
495
496    res0 = dev[0].request("P2P_PEER FIRST")
497    peer = res0.splitlines()[0]
498    if peer not in [addr1, addr2]:
499        raise Exception("Unexpected P2P_PEER FIRST address")
500    res1 = dev[0].request("P2P_PEER NEXT-" + peer)
501    peer2 = res1.splitlines()[0]
502    if peer2 not in [addr1, addr2] or peer == peer2:
503        raise Exception("Unexpected P2P_PEER NEXT address")
504
505    if "FAIL" not in dev[0].request("P2P_PEER NEXT-foo"):
506        raise Exception("Invalid P2P_PEER command accepted")
507    if "FAIL" not in dev[0].request("P2P_PEER foo"):
508        raise Exception("Invalid P2P_PEER command accepted")
509    if "FAIL" not in dev[0].request("P2P_PEER 00:11:22:33:44:55"):
510        raise Exception("P2P_PEER command for unknown peer accepted")
511
512def test_p2p_listen_and_offchannel_tx(dev):
513    """P2P_LISTEN behavior with offchannel TX"""
514    addr0 = dev[0].p2p_dev_addr()
515    addr1 = dev[1].p2p_dev_addr()
516    addr2 = dev[2].p2p_dev_addr()
517
518    dev[1].p2p_listen()
519    if not dev[0].discover_peer(addr1):
520        raise Exception("Device discovery timed out")
521
522    dev[0].p2p_listen()
523    dev[0].global_request("P2P_PROV_DISC " + addr1 + " display")
524    ev = dev[0].wait_global_event(["P2P-PROV-DISC-ENTER-PIN"], timeout=15)
525    if ev is None:
526        raise Exception("No PD result reported")
527    dev[1].p2p_stop_find()
528
529    if not dev[2].discover_peer(addr0):
530        raise Exception("Device discovery timed out after PD exchange")
531    dev[2].p2p_stop_find()
532    dev[0].p2p_stop_find()
533
534@remote_compatible
535def test_p2p_listen_and_scan(dev):
536    """P2P_LISTEN and scan"""
537    dev[0].p2p_listen()
538    if "OK" not in dev[0].request("SCAN freq=2412"):
539        raise Exception("Failed to request a scan")
540    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 3)
541    if ev is not None:
542        raise Exception("Unexpected scan results")
543    dev[0].p2p_stop_find()
544    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
545    if ev is None:
546        raise Exception("Scan timed out")
547
548def test_p2p_config_methods(dev):
549    """P2P and WPS config method update"""
550    addr0 = dev[0].p2p_dev_addr()
551    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
552    wpas.interface_add("wlan5")
553    addr1 = wpas.p2p_dev_addr()
554
555    if "OK" not in wpas.request("SET config_methods keypad virtual_push_button"):
556        raise Exception("Failed to set config_methods")
557
558    wpas.p2p_listen()
559    if not dev[0].discover_peer(addr1):
560        raise Exception("Device discovery timed out")
561    dev[0].p2p_stop_find()
562    peer = dev[0].get_peer(addr1)
563    if peer['config_methods'] != '0x180':
564        raise Exception("Unexpected peer config methods(1): " + peer['config_methods'])
565    dev[0].global_request("P2P_FLUSH")
566
567    if "OK" not in wpas.request("SET config_methods virtual_display"):
568        raise Exception("Failed to set config_methods")
569
570    if not dev[0].discover_peer(addr1):
571        raise Exception("Device discovery timed out")
572    dev[0].p2p_stop_find()
573    peer = dev[0].get_peer(addr1)
574    if peer['config_methods'] != '0x8':
575        raise Exception("Unexpected peer config methods(2): " + peer['config_methods'])
576
577    wpas.p2p_stop_find()
578
579@remote_compatible
580def test_discovery_after_gas(dev, apdev):
581    """P2P device discovery after GAS/ANQP exchange"""
582    hapd = start_ap(apdev[0])
583    hapd.set("gas_frag_limit", "50")
584    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
585    dev[0].request("FETCH_ANQP")
586    ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
587    if ev is None:
588        raise Exception("No ANQP-QUERY-DONE event")
589    dev[0].dump_monitor()
590
591    start = os.times()[4]
592    dev[0].p2p_listen()
593    dev[1].p2p_find(social=True)
594    ev = dev[1].wait_global_event(["P2P-DEVICE-FOUND"], timeout=5)
595    if ev is None:
596        raise Exception("Peer not discovered")
597    end = os.times()[4]
598    dev[0].dump_monitor()
599    dev[0].p2p_stop_find()
600    dev[1].p2p_stop_find()
601    logger.info("Device discovery after fragmented GAS took %f seconds" % (end - start))
602    if end - start > 1.3:
603        raise Exception("Device discovery took unexpectedly long time")
604
605@remote_compatible
606def test_discovery_listen_find(dev):
607    """P2P_LISTEN immediately followed by P2P_FIND"""
608    # Request an external remain-on-channel operation to delay start of the ROC
609    # for the following p2p_listen() enough to get p2p_find() processed before
610    # the ROC started event shows up. This is done to test a code path where the
611    # p2p_find() needs to clear the wait for the pending listen operation
612    # (p2p->pending_listen_freq).
613    ifindex = int(dev[0].get_driver_status_field("ifindex"))
614    nl80211_remain_on_channel(dev[0], ifindex, 2417, 200)
615
616    addr0 = dev[0].p2p_dev_addr()
617    dev[0].p2p_listen()
618    dev[0].p2p_find(social=True)
619    time.sleep(0.4)
620    dev[1].p2p_listen()
621    ev = dev[0].wait_global_event(["P2P-DEVICE-FOUND"], timeout=1.2)
622    if not dev[1].discover_peer(addr0):
623        raise Exception("Device discovery timed out")
624    if ev is None:
625        raise Exception("Did not find peer quickly enough after stopped P2P_LISTEN")
626
627def test_discovery_long_listen(dev):
628    """Long P2P_LISTEN and offchannel TX"""
629    addr0 = dev[0].p2p_dev_addr()
630    dev[0].p2p_listen()
631
632    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
633    wpas.interface_add("wlan5")
634    addr = wpas.p2p_dev_addr()
635    if not wpas.discover_peer(addr0):
636        raise Exception("Device discovery timed out")
637    peer = wpas.get_peer(addr0)
638    chan = '1' if peer['listen_freq'] == '2462' else '11'
639
640    wpas.request("P2P_SET listen_channel " + chan)
641    wpas.request("P2P_LISTEN 10")
642    if not dev[0].discover_peer(addr):
643        raise Exception("Device discovery timed out (2)")
644
645    time.sleep(0.1)
646    wpas.global_request("P2P_PROV_DISC " + addr0 + " display")
647    ev = dev[0].wait_global_event(["P2P-PROV-DISC-SHOW-PIN"], timeout=15)
648    if ev is None:
649        raise Exception("Provision discovery timed out")
650    dev[0].p2p_stop_find()
651
652    # Verify that the long listen period is still continuing after off-channel
653    # TX of Provision Discovery frames.
654    if not dev[1].discover_peer(addr):
655        raise Exception("Device discovery timed out (3)")
656
657    dev[1].p2p_stop_find()
658    wpas.p2p_stop_find()
659
660def test_discovery_long_listen2(dev):
661    """Long P2P_LISTEN longer than remain-on-channel time"""
662    with HWSimRadio(use_p2p_device=True) as (radio, iface):
663        wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
664        wpas.interface_add(iface)
665        addr = wpas.p2p_dev_addr()
666        wpas.request("P2P_LISTEN 15")
667
668        # Wait for remain maximum remain-on-channel time to pass
669        time.sleep(7)
670
671        if not dev[0].discover_peer(addr):
672            raise Exception("Device discovery timed out")
673        dev[0].p2p_stop_find()
674        wpas.p2p_stop_find()
675
676def pd_test(dev, addr):
677    if not dev.discover_peer(addr, freq=2412):
678        raise Exception("Device discovery timed out")
679    dev.global_request("P2P_PROV_DISC " + addr + " display")
680    ev0 = dev.wait_global_event(["P2P-PROV-DISC-ENTER-PIN"], timeout=15)
681    if ev0 is None:
682        raise Exception("Provision discovery timed out (display)")
683    dev.p2p_stop_find()
684
685def run_discovery_while_go(wpas, dev, params):
686    wpas.request("P2P_SET listen_channel 1")
687    wpas.p2p_start_go(freq="2412")
688    addr = wpas.p2p_dev_addr()
689    pin = dev[0].wps_read_pin()
690    wpas.p2p_go_authorize_client(pin)
691    dev[1].p2p_connect_group(addr, pin, freq=2412, timeout=30)
692
693    pd_test(dev[0], addr)
694    wpas.p2p_listen()
695    pd_test(dev[2], addr)
696
697    wpas.p2p_stop_find()
698    terminate_group(wpas, dev[1])
699
700    out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
701                     "wifi_p2p.public_action.subtype == 8", ["wlan.da"])
702    da = out.splitlines()
703    logger.info("PD Response DAs: " + str(da))
704    if len(da) != 3:
705        raise Exception("Unexpected DA count for PD Response")
706
707def test_discovery_while_go(dev, apdev, params):
708    """P2P provision discovery from GO"""
709    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
710    wpas.interface_add("wlan5")
711    run_discovery_while_go(wpas, dev, params)
712
713def test_discovery_while_go_p2p_dev(dev, apdev, params):
714    """P2P provision discovery from GO (using P2P Device interface)"""
715    with HWSimRadio(use_p2p_device=True) as (radio, iface):
716        wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
717        wpas.interface_add(iface)
718        run_discovery_while_go(wpas, dev, params)
719
720def run_discovery_while_cli(wpas, dev, params):
721    wpas.request("P2P_SET listen_channel 1")
722    dev[1].p2p_start_go(freq="2412")
723    addr = wpas.p2p_dev_addr()
724    pin = wpas.wps_read_pin()
725    dev[1].p2p_go_authorize_client(pin)
726    wpas.p2p_connect_group(dev[1].p2p_dev_addr(), pin, freq=2412, timeout=30)
727
728    pd_test(dev[0], addr)
729    wpas.p2p_listen()
730    pd_test(dev[2], addr)
731
732    wpas.p2p_stop_find()
733    terminate_group(dev[1], wpas)
734
735    out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
736                     "wifi_p2p.public_action.subtype == 8", ["wlan.da"])
737    da = out.splitlines()
738    logger.info("PD Response DAs: " + str(da))
739    if len(da) != 3:
740        raise Exception("Unexpected DA count for PD Response")
741
742def test_discovery_while_cli(dev, apdev, params):
743    """P2P provision discovery from CLI"""
744    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
745    wpas.interface_add("wlan5")
746    run_discovery_while_cli(wpas, dev, params)
747
748def test_discovery_while_cli_p2p_dev(dev, apdev, params):
749    """P2P provision discovery from CLI (using P2P Device interface)"""
750    with HWSimRadio(use_p2p_device=True) as (radio, iface):
751        wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
752        wpas.interface_add(iface)
753        run_discovery_while_cli(wpas, dev, params)
754
755def test_discovery_device_name_change(dev):
756    """P2P device discovery and peer changing device name"""
757    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
758    wpas.interface_add("wlan5")
759    wpas.set("device_name", "test-a")
760    wpas.p2p_listen()
761    dev[0].p2p_find(social=True)
762    ev = dev[0].wait_global_event(["P2P-DEVICE-FOUND"], timeout=15)
763    if ev is None:
764        raise Exception("Peer not found")
765    if "new=1" not in ev:
766        raise Exception("Incorrect new event: " + ev)
767    if "name='test-a'" not in ev:
768        raise Exception("Unexpected device name(1): " + ev)
769
770    # Verify that new P2P-DEVICE-FOUND event is indicated when the peer changes
771    # its device name.
772    wpas.set("device_name", "test-b")
773    ev = dev[0].wait_global_event(["P2P-DEVICE-FOUND"], timeout=15)
774    if ev is None:
775        raise Exception("Peer update not seen")
776    if "new=0" not in ev:
777        raise Exception("Incorrect update event: " + ev)
778    if "name='test-b'" not in ev:
779        raise Exception("Unexpected device name(2): " + ev)
780    wpas.p2p_stop_find()
781    dev[0].p2p_stop_find()
782
783def test_p2p_group_cli_invalid(dev, apdev):
784    """P2P device discovery with invalid group client info"""
785    attr = struct.pack('<BHBB', 2, 2, 0x25, 0x09)
786
787    attr += struct.pack('<BH', 3, 6) + "\x02\x02\x02\x02\x02\x00".encode()
788
789    cli = bytes()
790    cli += "\x02\x02\x02\x02\x02\x03".encode()
791    cli += "\x02\x02\x02\x02\x02\x04".encode()
792    cli += struct.pack('>BH', 0, 0x3148)
793    dev_type = "\x00\x00\x00\x00\x00\x00\x00\x01".encode()
794    cli += dev_type
795    num_sec = 25
796    cli += struct.pack('B', num_sec)
797    cli += num_sec * dev_type
798    name = "TEST".encode()
799    cli += struct.pack('>HH', 0x1011, len(name)) + name
800    desc = struct.pack('B', len(cli)) + cli
801    attr += struct.pack('<BH', 14, len(desc)) + desc
802
803    p2p_ie = struct.pack('>BBL', 0xdd, 4 + len(attr), 0x506f9a09) + attr
804    ie = binascii.hexlify(p2p_ie).decode()
805
806    params = {"ssid": "DIRECT-test",
807              "eap_server": "1",
808              "wps_state": "2",
809              "wpa_passphrase": "12345678",
810              "wpa": "2",
811              "wpa_key_mgmt": "WPA-PSK",
812              "rsn_pairwise": "CCMP",
813              "vendor_elements": ie}
814    hapd = hostapd.add_ap(apdev[0], params)
815
816    for i in range(2):
817        dev[i].p2p_find(social=True)
818        ev = dev[i].wait_global_event(["P2P-DEVICE-FOUND"], timeout=5)
819        if not ev:
820            raise Exception("P2P device not found")
821
822def test_discovery_max_peers(dev):
823    """P2P device discovery and maximum peer limit exceeded"""
824    dev[0].p2p_listen()
825    dev[0].request("SET ext_mgmt_frame_handling 1")
826    probereq1 = "40000000ffffffffffff"
827    probereq2 = "ffffffffffff000000074449524543542d01080c1218243048606c0301012d1afe131bffff000000000000000000000100000000000000000000ff16230178c812400000bfce0000000000000000fafffaffdd730050f204104a000110103a00010110080002314810470010572cf82fc95756539b16b5cfb298abf1105400080000000000000000103c0001031002000200001009000200001012000200001021000120102300012010240001201011000844657669636520421049000900372a000120030101dd11506f9a0902020025000605005858045106"
828
829    # Fill the P2P peer table with max+1 entries based on Probe Request frames
830    # to verify correct behavior on# removing the oldest entry when running out
831    # of room.
832    for i in range(101):
833        addr = "0202020202%02x" % i
834        probereq = probereq1 + addr + probereq2
835        if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=60 ssi_signal=-30 frame=" + probereq):
836            raise Exception("MGMT_RX_PROCESS failed")
837
838    res = dev[0].global_request("P2P_PEER FIRST")
839    addr = res.splitlines()[0]
840    peers = [addr]
841    limit = 200
842    while limit > 0:
843        res = dev[0].global_request("P2P_PEER NEXT-" + addr)
844        addr = res.splitlines()[0]
845        if addr == "FAIL":
846            break
847        peers.append(addr)
848        limit -= 1
849    logger.info("Peers: " + str(peers))
850
851    if len(peers) != 100:
852        raise Exception("Unexpected number of peer entries")
853    oldest = "02:02:02:02:02:00"
854    if oldest in peers:
855        raise Exception("Oldest entry is still present")
856    for i in range(101):
857        addr = "02:02:02:02:02:%02x" % i
858        if addr == oldest:
859            continue
860        if addr not in peers:
861            raise Exception("Peer missing from table: " + addr)
862
863    # Provision Discovery Request from the oldest peer (SA) using internally
864    # different P2P Device Address as a regression test for incorrect processing
865    # for this corner case.
866    dst = dev[0].own_addr().replace(':', '')
867    src = peers[99].replace(':', '')
868    devaddr = "0202020202ff"
869    pdreq = "d0004000" + dst + src + dst + "d0000409506f9a090701dd29506f9a0902020025000d1d00" + devaddr + "1108000000000000000000101100084465766963652041dd0a0050f204100800020008"
870    if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=60 ssi_signal=-30 frame=" + pdreq):
871        raise Exception("MGMT_RX_PROCESS failed")
872