1# FST functionality tests
2# Copyright (c) 2015, Qualcomm Atheros, Inc.
3#
4# This software may be distributed under the terms of the BSD license.
5# See README for more details.
6
7import logging
8logger = logging.getLogger()
9import struct
10import subprocess
11import time
12import os
13import re
14
15import hwsim_utils
16from hwsim import HWSimRadio
17import hostapd
18from wpasupplicant import WpaSupplicant
19import fst_test_common
20import fst_module_aux
21from utils import alloc_fail, HwsimSkip
22
23#enum - bad parameter types
24bad_param_none = 0
25bad_param_session_add_no_params = 1
26bad_param_group_id = 2
27bad_param_session_set_no_params = 3
28bad_param_session_set_unknown_param = 4
29bad_param_session_id = 5
30bad_param_old_iface = 6
31bad_param_new_iface = 7
32bad_param_negative_llt = 8
33bad_param_zero_llt = 9
34bad_param_llt_too_big = 10
35bad_param_llt_nan = 11
36bad_param_peer_addr = 12
37bad_param_session_initiate_no_params = 13
38bad_param_session_initiate_bad_session_id = 14
39bad_param_session_initiate_with_no_new_iface_set = 15
40bad_param_session_initiate_with_bad_peer_addr_set = 16
41bad_param_session_initiate_request_with_bad_stie = 17
42bad_param_session_initiate_response_with_reject = 18
43bad_param_session_initiate_response_with_bad_stie = 19
44bad_param_session_initiate_response_with_zero_llt = 20
45bad_param_session_initiate_stt_no_response = 21
46bad_param_session_initiate_concurrent_setup_request = 22
47bad_param_session_transfer_no_params = 23
48bad_param_session_transfer_bad_session_id = 24
49bad_param_session_transfer_setup_skipped = 25
50bad_param_session_teardown_no_params = 26
51bad_param_session_teardown_bad_session_id = 27
52bad_param_session_teardown_setup_skipped = 28
53bad_param_session_teardown_bad_fsts_id = 29
54
55bad_param_names = ("None",
56                   "No params passed to session add",
57                   "Group ID",
58                   "No params passed to session set",
59                   "Unknown param passed to session set",
60                   "Session ID",
61                   "Old interface name",
62                   "New interface name",
63                   "Negative LLT",
64                   "Zero LLT",
65                   "LLT too big",
66                   "LLT is not a number",
67                   "Peer address",
68                   "No params passed to session initiate",
69                   "Session ID",
70                   "No new_iface was set",
71                   "Peer address",
72                   "Request with bad st ie",
73                   "Response with reject",
74                   "Response with bad st ie",
75                   "Response with zero llt",
76                   "No response, STT",
77                   "Concurrent setup request",
78                   "No params passed to session transfer",
79                   "Session ID",
80                   "Session setup skipped",
81                   "No params passed to session teardown",
82                   "Bad session",
83                   "Session setup skipped",
84                   "Bad fsts_id")
85
86def fst_start_session(apdev, test_params, bad_param_type, start_on_ap,
87                      peer_addr=None):
88    """This function makes the necessary preparations and the adds and sets a
89    session using either correct or incorrect parameters depending on the value
90    of bad_param_type. If the call ends as expected (with session being
91    successfully added and set in case of correct parameters or with the
92    expected exception in case of incorrect parameters), the function silently
93    exits. Otherwise, it throws an exception thus failing the test."""
94
95    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
96    bad_parameter_detected = False
97    exception_already_raised = False
98    try:
99        fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
100        if start_on_ap:
101            initiator = ap1
102            responder = sta1
103            new_iface = ap2.ifname()
104            new_peer_addr = ap2.get_actual_peer_addr()
105        else:
106            initiator = sta1
107            responder = ap1
108            new_iface = sta2.ifname()
109            new_peer_addr = sta2.get_actual_peer_addr()
110        initiator.add_peer(responder, peer_addr, new_peer_addr)
111        group_id = None
112        if bad_param_type == bad_param_group_id:
113            group_id = '-1'
114        elif bad_param_type == bad_param_session_add_no_params:
115            group_id = ''
116        initiator.set_fst_parameters(group_id=group_id)
117        sid = initiator.add_session()
118        if bad_param_type == bad_param_session_set_no_params:
119            res = initiator.set_session_param(None)
120            if not res.startswith("OK"):
121                raise Exception("Session set operation failed")
122        elif bad_param_type == bad_param_session_set_unknown_param:
123            res = initiator.set_session_param("bad_param=1")
124            if not res.startswith("OK"):
125                raise Exception("Session set operation failed")
126        else:
127            if bad_param_type == bad_param_session_initiate_with_no_new_iface_set:
128                new_iface = None
129            elif bad_param_type == bad_param_new_iface:
130                new_iface = 'wlan12'
131            old_iface = None if bad_param_type != bad_param_old_iface else 'wlan12'
132            llt = None
133            if bad_param_type == bad_param_negative_llt:
134                llt = '-1'
135            elif bad_param_type == bad_param_zero_llt:
136                llt = '0'
137            elif bad_param_type == bad_param_llt_too_big:
138                llt = '4294967296'    #0x100000000
139            elif bad_param_type == bad_param_llt_nan:
140                llt = 'nan'
141            elif bad_param_type == bad_param_session_id:
142                sid = '-1'
143            initiator.set_fst_parameters(llt=llt)
144            initiator.configure_session(sid, new_iface, old_iface)
145    except Exception as e:
146        if e.args[0].startswith("Cannot add FST session with groupid"):
147            if bad_param_type == bad_param_group_id or bad_param_type == bad_param_session_add_no_params:
148                bad_parameter_detected = True
149        elif e.args[0].startswith("Cannot set FST session new_ifname:"):
150            if bad_param_type == bad_param_new_iface:
151                bad_parameter_detected = True
152        elif e.args[0].startswith("Session set operation failed"):
153            if (bad_param_type == bad_param_session_set_no_params or
154                bad_param_type == bad_param_session_set_unknown_param):
155                bad_parameter_detected = True
156        elif e.args[0].startswith("Cannot set FST session old_ifname:"):
157            if (bad_param_type == bad_param_old_iface or
158                bad_param_type == bad_param_session_id or
159                bad_param_type == bad_param_session_set_no_params):
160                bad_parameter_detected = True
161        elif e.args[0].startswith("Cannot set FST session llt:"):
162            if (bad_param_type == bad_param_negative_llt or
163                bad_param_type == bad_param_llt_too_big or
164                bad_param_type == bad_param_llt_nan):
165                bad_parameter_detected = True
166        elif e.args[0].startswith("Cannot set FST session peer address:"):
167            if bad_param_type == bad_param_peer_addr:
168                bad_parameter_detected = True
169        if not bad_parameter_detected:
170            # The exception was unexpected
171            logger.info(e)
172            exception_already_raised = True
173            raise
174    finally:
175        fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
176        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
177        if not exception_already_raised:
178            if bad_parameter_detected:
179                logger.info("Success. Bad parameter was detected (%s)" % bad_param_names[bad_param_type])
180            else:
181                if bad_param_type == bad_param_none or bad_param_type == bad_param_zero_llt:
182                    logger.info("Success. Session added and set")
183                else:
184                    exception_text = ""
185                    if bad_param_type == bad_param_peer_addr:
186                        exception_text = "Failure. Bad parameter was not detected (Peer address == %s)" % ap1.get_new_peer_addr()
187                    else:
188                        exception_text = "Failure. Bad parameter was not detected (%s)" % bad_param_names[bad_param_type]
189                    raise Exception(exception_text)
190        else:
191            logger.info("Failure. Unexpected exception")
192
193def fst_initiate_session(apdev, test_params, bad_param_type, init_on_ap):
194    """This function makes the necessary preparations and then adds, sets and
195    initiates a session using either correct or incorrect parameters at each
196    stage depending on the value of bad_param_type. If the call ends as expected
197    (with session being successfully added, set and initiated in case of correct
198    parameters or with the expected exception in case of incorrect parameters),
199    the function silently exits. Otherwise it throws an exception thus failing
200    the test."""
201    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
202    bad_parameter_detected = False
203    exception_already_raised = False
204    try:
205        fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
206        # This call makes sure FstHostapd singleton object is created and, as a
207        # result, the global control interface is registered (this is done from
208        # the constructor).
209        ap1.get_global_instance()
210        if init_on_ap:
211            initiator = ap1
212            responder = sta1
213            new_iface = ap2.ifname() if bad_param_type != bad_param_session_initiate_with_no_new_iface_set else None
214            new_peer_addr = ap2.get_actual_peer_addr()
215            resp_newif = sta2.ifname()
216        else:
217            initiator = sta1
218            responder = ap1
219            new_iface = sta2.ifname() if bad_param_type != bad_param_session_initiate_with_no_new_iface_set else None
220            new_peer_addr = sta2.get_actual_peer_addr()
221            resp_newif = ap2.ifname()
222        peeraddr = None if bad_param_type != bad_param_session_initiate_with_bad_peer_addr_set else '10:DE:AD:DE:AD:11'
223        initiator.add_peer(responder, peeraddr, new_peer_addr)
224        if bad_param_type == bad_param_session_initiate_response_with_zero_llt:
225            initiator.set_fst_parameters(llt='0')
226        sid = initiator.add_session()
227        initiator.configure_session(sid, new_iface)
228        if bad_param_type == bad_param_session_initiate_no_params:
229            sid = ''
230        elif bad_param_type == bad_param_session_initiate_bad_session_id:
231            sid = '-1'
232        if bad_param_type == bad_param_session_initiate_request_with_bad_stie:
233            actual_fsts_id = initiator.get_fsts_id_by_sid(sid)
234            initiator.send_test_session_setup_request(str(actual_fsts_id), "bad_new_band")
235            responder.wait_for_session_event(5)
236        elif bad_param_type == bad_param_session_initiate_response_with_reject:
237            initiator.send_session_setup_request(sid)
238            initiator.wait_for_session_event(5, [], ["EVENT_FST_SESSION_STATE"])
239            setup_event = responder.wait_for_session_event(5, [],
240                                                           ['EVENT_FST_SETUP'])
241            if 'id' not in setup_event:
242                raise Exception("No session id in FST setup event")
243            responder.send_session_setup_response(str(setup_event['id']),
244                                                  "reject")
245            event = initiator.wait_for_session_event(5, [], ["EVENT_FST_SESSION_STATE"])
246            if event['new_state'] != "INITIAL" or event['reason'] != "REASON_REJECT":
247                raise Exception("Response with reject not handled as expected")
248            bad_parameter_detected = True
249        elif bad_param_type == bad_param_session_initiate_response_with_bad_stie:
250            initiator.send_session_setup_request(sid)
251            initiator.wait_for_session_event(5, [], ["EVENT_FST_SESSION_STATE"])
252            responder.wait_for_session_event(5, [], ['EVENT_FST_SETUP'])
253            actual_fsts_id = initiator.get_fsts_id_by_sid(sid)
254            responder.send_test_session_setup_response(str(actual_fsts_id),
255                                                       "accept", "bad_new_band")
256            event = initiator.wait_for_session_event(5, [], ["EVENT_FST_SESSION_STATE"])
257            if event['new_state'] != "INITIAL" or event['reason'] != "REASON_ERROR_PARAMS":
258                raise Exception("Response with bad STIE not handled as expected")
259            bad_parameter_detected = True
260        elif bad_param_type == bad_param_session_initiate_response_with_zero_llt:
261            initiator.initiate_session(sid, "accept")
262            event = initiator.wait_for_session_event(5, [], ["EVENT_FST_SESSION_STATE"])
263            if event['new_state'] != "TRANSITION_DONE":
264                raise Exception("Response reception for a session with llt=0 not handled as expected")
265            bad_parameter_detected = True
266        elif bad_param_type == bad_param_session_initiate_stt_no_response:
267            initiator.send_session_setup_request(sid)
268            initiator.wait_for_session_event(5, [], ["EVENT_FST_SESSION_STATE"])
269            responder.wait_for_session_event(5, [], ['EVENT_FST_SETUP'])
270            event = initiator.wait_for_session_event(5, [], ["EVENT_FST_SESSION_STATE"])
271            if event['new_state'] != "INITIAL" or event['reason'] != "REASON_STT":
272                raise Exception("No response scenario not handled as expected")
273            bad_parameter_detected = True
274        elif bad_param_type == bad_param_session_initiate_concurrent_setup_request:
275            responder.add_peer(initiator)
276            resp_sid = responder.add_session()
277            responder.configure_session(resp_sid, resp_newif)
278            initiator.send_session_setup_request(sid)
279            actual_fsts_id = initiator.get_fsts_id_by_sid(sid)
280            responder.send_test_session_setup_request(str(actual_fsts_id))
281            event = initiator.wait_for_session_event(5, [], ["EVENT_FST_SESSION_STATE"])
282            initiator_addr = initiator.get_own_mac_address()
283            responder_addr = responder.get_own_mac_address()
284            if initiator_addr < responder_addr:
285                event = initiator.wait_for_session_event(5, [], ["EVENT_FST_SESSION_STATE"])
286                if event['new_state'] != "INITIAL" or event['reason'] != "REASON_SETUP":
287                    raise Exception("Concurrent setup scenario not handled as expected")
288                event = initiator.wait_for_session_event(5, [], ["EVENT_FST_SETUP"])
289                # The incoming setup request received by the initiator has
290                # priority over the one sent previously by the initiator itself
291                # because the initiator's MAC address is numerically lower than
292                # the one of the responder. Thus, the initiator should generate
293                # an FST_SETUP event.
294            else:
295                event = initiator.wait_for_session_event(5, [], ["EVENT_FST_SESSION_STATE"])
296                if event['new_state'] != "INITIAL" or event['reason'] != "REASON_STT":
297                    raise Exception("Concurrent setup scenario not handled as expected")
298                # The incoming setup request was dropped at the initiator
299                # because its MAC address is numerically bigger than the one of
300                # the responder. Thus, the initiator continue to wait for a
301                # setup response until the STT event fires.
302            bad_parameter_detected = True
303        else:
304            initiator.initiate_session(sid, "accept")
305    except Exception as e:
306        if e.args[0].startswith("Cannot initiate fst session"):
307            if bad_param_type != bad_param_none:
308                bad_parameter_detected = True
309        elif e.args[0].startswith("No FST-EVENT-SESSION received"):
310            if bad_param_type == bad_param_session_initiate_request_with_bad_stie:
311                bad_parameter_detected = True
312        if not bad_parameter_detected:
313            #The exception was unexpected
314            logger.info(e)
315            exception_already_raised = True
316            raise
317    finally:
318        fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
319        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
320        if not exception_already_raised:
321            if bad_parameter_detected:
322                logger.info("Success. Bad parameter was detected (%s)" % bad_param_names[bad_param_type])
323            else:
324                if bad_param_type == bad_param_none:
325                    logger.info("Success. Session initiated")
326                else:
327                    raise Exception("Failure. Bad parameter was not detected (%s)" % bad_param_names[bad_param_type])
328        else:
329            logger.info("Failure. Unexpected exception")
330
331def fst_transfer_session(apdev, test_params, bad_param_type, init_on_ap,
332                         rsn=False):
333    """This function makes the necessary preparations and then adds, sets,
334    initiates and attempts to transfer a session using either correct or
335    incorrect parameters at each stage depending on the value of bad_param_type.
336    If the call ends as expected the function silently exits. Otherwise, it
337    throws an exception thus failing the test."""
338    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev, rsn=rsn)
339    bad_parameter_detected = False
340    exception_already_raised = False
341    try:
342        fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2, rsn=rsn)
343        # This call makes sure FstHostapd singleton object is created and, as a
344        # result, the global control interface is registered (this is done from
345        # the constructor).
346        ap1.get_global_instance()
347        if init_on_ap:
348            initiator = ap1
349            responder = sta1
350            new_iface = ap2.ifname()
351            new_peer_addr = ap2.get_actual_peer_addr()
352        else:
353            initiator = sta1
354            responder = ap1
355            new_iface = sta2.ifname()
356            new_peer_addr = sta2.get_actual_peer_addr()
357        initiator.add_peer(responder, new_peer_addr=new_peer_addr)
358        sid = initiator.add_session()
359        initiator.configure_session(sid, new_iface)
360        if bad_param_type != bad_param_session_transfer_setup_skipped:
361            initiator.initiate_session(sid, "accept")
362        if bad_param_type == bad_param_session_transfer_no_params:
363            sid = ''
364        elif bad_param_type == bad_param_session_transfer_bad_session_id:
365            sid = '-1'
366        initiator.transfer_session(sid)
367    except Exception as e:
368        if e.args[0].startswith("Cannot transfer fst session"):
369            if bad_param_type != bad_param_none:
370                bad_parameter_detected = True
371        if not bad_parameter_detected:
372            # The exception was unexpected
373            logger.info(e)
374            exception_already_raised = True
375            raise
376    finally:
377        fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
378        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
379        if not exception_already_raised:
380            if bad_parameter_detected:
381                logger.info("Success. Bad parameter was detected (%s)" % bad_param_names[bad_param_type])
382            else:
383                if bad_param_type == bad_param_none:
384                    logger.info("Success. Session transferred")
385                else:
386                    raise Exception("Failure. Bad parameter was not detected (%s)" % bad_param_names[bad_param_type])
387        else:
388            logger.info("Failure. Unexpected exception")
389
390
391def fst_tear_down_session(apdev, test_params, bad_param_type, init_on_ap):
392    """This function makes the necessary preparations and then adds, sets, and
393    initiates a session. It then issues a tear down command using either
394    correct or incorrect parameters at each stage. If the call ends as expected,
395    the function silently exits. Otherwise, it throws an exception thus failing
396    the test."""
397    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
398    bad_parameter_detected = False
399    exception_already_raised = False
400    try:
401        fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
402        # This call makes sure FstHostapd singleton object is created and, as a
403        # result, the global control interface is registered (this is done from
404        # the constructor).
405        ap1.get_global_instance()
406        if init_on_ap:
407            initiator = ap1
408            responder = sta1
409            new_iface = ap2.ifname()
410            new_peer_addr = ap2.get_actual_peer_addr()
411        else:
412            initiator = sta1
413            responder = ap1
414            new_iface = sta2.ifname()
415            new_peer_addr = sta2.get_actual_peer_addr()
416        initiator.add_peer(responder, new_peer_addr=new_peer_addr)
417        sid = initiator.add_session()
418        initiator.configure_session(sid, new_iface)
419        if bad_param_type != bad_param_session_teardown_setup_skipped:
420            initiator.initiate_session(sid, "accept")
421        if bad_param_type == bad_param_session_teardown_bad_fsts_id:
422            initiator.send_test_tear_down('-1')
423            responder.wait_for_session_event(5)
424        else:
425            if bad_param_type == bad_param_session_teardown_no_params:
426                sid = ''
427            elif bad_param_type == bad_param_session_teardown_bad_session_id:
428                sid = '-1'
429            initiator.teardown_session(sid)
430    except Exception as e:
431        if e.args[0].startswith("Cannot tear down fst session"):
432            if (bad_param_type == bad_param_session_teardown_no_params or
433                bad_param_type == bad_param_session_teardown_bad_session_id or
434                bad_param_type == bad_param_session_teardown_setup_skipped):
435                bad_parameter_detected = True
436        elif e.args[0].startswith("No FST-EVENT-SESSION received"):
437            if bad_param_type == bad_param_session_teardown_bad_fsts_id:
438                bad_parameter_detected = True
439        if not bad_parameter_detected:
440            # The exception was unexpected
441            logger.info(e)
442            exception_already_raised = True
443            raise
444    finally:
445        fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
446        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
447        if not exception_already_raised:
448            if bad_parameter_detected:
449                logger.info("Success. Bad parameter was detected (%s)" % bad_param_names[bad_param_type])
450            else:
451                if bad_param_type == bad_param_none:
452                    logger.info("Success. Session torn down")
453                else:
454                    raise Exception("Failure. Bad parameter was not detected (%s)" % bad_param_names[bad_param_type])
455        else:
456            logger.info("Failure. Unexpected exception")
457
458
459#enum - remove session scenarios
460remove_scenario_no_params = 0
461remove_scenario_bad_session_id = 1
462remove_scenario_non_established_session = 2
463remove_scenario_established_session = 3
464
465remove_scenario_names = ("No params",
466                         "Bad session id",
467                         "Remove non-established session",
468                         "Remove established session")
469
470
471def fst_remove_session(apdev, test_params, remove_session_scenario, init_on_ap):
472    """This function attempts to remove a session at various stages of its
473    formation, depending on the value of remove_session_scenario. If the call
474    ends as expected, the function silently exits. Otherwise, it throws an
475    exception thus failing the test."""
476    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
477    bad_parameter_detected = False
478    exception_already_raised = False
479    try:
480        fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
481        # This call makes sure FstHostapd singleton object is created and, as a
482        # result, the global control interface is registered (this is done from
483        # the constructor).
484        ap1.get_global_instance()
485        if init_on_ap:
486            initiator = ap1
487            responder = sta1
488            new_iface = ap2.ifname()
489            new_peer_addr = ap2.get_actual_peer_addr()
490        else:
491            initiator = sta1
492            responder = ap1
493            new_iface = sta2.ifname()
494            new_peer_addr = sta2.get_actual_peer_addr()
495        initiator.add_peer(responder, new_peer_addr=new_peer_addr)
496        sid = initiator.add_session()
497        initiator.configure_session(sid, new_iface)
498        if remove_session_scenario != remove_scenario_no_params:
499            if remove_session_scenario != remove_scenario_non_established_session:
500                initiator.initiate_session(sid, "accept")
501        if remove_session_scenario == remove_scenario_no_params:
502            sid = ''
503        elif remove_session_scenario == remove_scenario_bad_session_id:
504            sid = '-1'
505        initiator.remove_session(sid)
506    except Exception as e:
507        if e.args[0].startswith("Cannot remove fst session"):
508            if (remove_session_scenario == remove_scenario_no_params or
509                remove_session_scenario == remove_scenario_bad_session_id):
510                bad_parameter_detected = True
511        elif e.args[0].startswith("No FST-EVENT-SESSION received"):
512            if remove_session_scenario == remove_scenario_non_established_session:
513                bad_parameter_detected = True
514        if not bad_parameter_detected:
515            #The exception was unexpected
516            logger.info(e)
517            exception_already_raised = True
518            raise
519    finally:
520        fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
521        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
522        if not exception_already_raised:
523            if bad_parameter_detected:
524                logger.info("Success. Remove scenario ended as expected (%s)" % remove_scenario_names[remove_session_scenario])
525            else:
526                if remove_session_scenario == remove_scenario_established_session:
527                    logger.info("Success. Session removed")
528                else:
529                    raise Exception("Failure. Remove scenario ended in an unexpected way (%s)" % remove_scenario_names[remove_session_scenario])
530        else:
531            logger.info("Failure. Unexpected exception")
532
533
534#enum - frame types
535frame_type_session_request = 0
536frame_type_session_response = 1
537frame_type_ack_request = 2
538frame_type_ack_response = 3
539frame_type_tear_down = 4
540
541frame_type_names = ("Session request",
542                    "Session Response",
543                    "Ack request",
544                    "Ack response",
545                    "Tear down")
546
547def fst_send_unexpected_frame(apdev, test_params, frame_type, send_from_ap, additional_param=''):
548    """This function creates two pairs of APs and stations, makes them connect
549    and then causes one side to send an unexpected FST frame of the specified
550    type to the other. The other side should then identify and ignore the
551    frame."""
552    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
553    exception_already_raised = False
554    frame_receive_timeout = False
555    try:
556        fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
557        # This call makes sure FstHostapd singleton object is created and, as a
558        # result, the global control interface is registered (this is done from
559        # the constructor).
560        ap1.get_global_instance()
561        if send_from_ap:
562            sender = ap1
563            receiver = sta1
564            new_iface = ap2.ifname()
565            new_peer_addr = ap2.get_actual_peer_addr()
566        else:
567            sender = sta1
568            receiver = ap1
569            new_iface = sta2.ifname()
570            new_peer_addr = sta2.get_actual_peer_addr()
571        sender.add_peer(receiver, new_peer_addr=new_peer_addr)
572        sid = sender.add_session()
573        sender.configure_session(sid, new_iface)
574        if frame_type == frame_type_session_request:
575            sender.send_session_setup_request(sid)
576            event = receiver.wait_for_session_event(5)
577            if event['type'] != 'EVENT_FST_SETUP':
578                raise Exception("Unexpected indication: " + event['type'])
579        elif frame_type == frame_type_session_response:
580            #fsts_id doesn't matter, no actual session exists
581            sender.send_test_session_setup_response('0', additional_param)
582            receiver.wait_for_session_event(5)
583        elif frame_type == frame_type_ack_request:
584            #fsts_id doesn't matter, no actual session exists
585            sender.send_test_ack_request('0')
586            receiver.wait_for_session_event(5)
587        elif frame_type == frame_type_ack_response:
588            #fsts_id doesn't matter, no actual session exists
589            sender.send_test_ack_response('0')
590            receiver.wait_for_session_event(5)
591        elif frame_type == frame_type_tear_down:
592            #fsts_id doesn't matter, no actual session exists
593            sender.send_test_tear_down('0')
594            receiver.wait_for_session_event(5)
595    except Exception as e:
596        if e.args[0].startswith("No FST-EVENT-SESSION received"):
597            if frame_type != frame_type_session_request:
598                frame_receive_timeout = True
599        else:
600            logger.info(e)
601            exception_already_raised = True
602            raise
603    finally:
604        fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
605        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
606        if not exception_already_raised:
607            if frame_receive_timeout:
608                logger.info("Success. Frame was ignored (%s)" % frame_type_names[frame_type])
609            else:
610                if frame_type == frame_type_session_request:
611                    logger.info("Success. Frame received, session created")
612                else:
613                    raise Exception("Failure. Frame was not ignored (%s)" % frame_type_names[frame_type])
614        else:
615            logger.info("Failure. Unexpected exception")
616
617
618#enum - bad session transfer scenarios
619bad_scenario_none = 0
620bad_scenario_ack_req_session_not_set_up = 1
621bad_scenario_ack_req_session_not_established_init_side = 2
622bad_scenario_ack_req_session_not_established_resp_side = 3
623bad_scenario_ack_req_bad_fsts_id = 4
624bad_scenario_ack_resp_session_not_set_up = 5
625bad_scenario_ack_resp_session_not_established_init_side = 6
626bad_scenario_ack_resp_session_not_established_resp_side = 7
627bad_scenario_ack_resp_no_ack_req = 8
628bad_scenario_ack_resp_bad_fsts_id = 9
629
630bad_scenario_names = ("None",
631                      "Ack request received before the session was set up",
632                      "Ack request received on the initiator side before session was established",
633                      "Ack request received on the responder side before session was established",
634                      "Ack request received with bad fsts_id",
635                      "Ack response received before the session was set up",
636                      "Ack response received on the initiator side before session was established",
637                      "Ack response received on the responder side before session was established",
638                      "Ack response received before ack request was sent",
639                      "Ack response received with bad fsts_id")
640
641def fst_bad_transfer(apdev, test_params, bad_scenario_type, init_on_ap):
642    """This function makes the necessary preparations and then adds and sets a
643    session. It then initiates and it unless instructed otherwise) and attempts
644    to send one of the frames involved in the session transfer protocol,
645    skipping or distorting one of the stages according to the value of
646    bad_scenario_type parameter."""
647    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
648    bad_parameter_detected = False
649    exception_already_raised = False
650    try:
651        fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
652        # This call makes sure FstHostapd singleton object is created and, as a
653        # result, the global control interface is registered (this is done from
654        # the constructor).
655        ap1.get_global_instance()
656        if init_on_ap:
657            initiator = ap1
658            responder = sta1
659            new_iface = ap2.ifname()
660            new_peer_addr = ap2.get_actual_peer_addr()
661        else:
662            initiator = sta1
663            responder = ap1
664            new_iface = sta2.ifname()
665            new_peer_addr = sta2.get_actual_peer_addr()
666        initiator.add_peer(responder, new_peer_addr=new_peer_addr)
667        sid = initiator.add_session()
668        initiator.configure_session(sid, new_iface)
669        if (bad_scenario_type != bad_scenario_ack_req_session_not_set_up and
670            bad_scenario_type != bad_scenario_ack_resp_session_not_set_up):
671            if (bad_scenario_type != bad_scenario_ack_req_session_not_established_init_side and
672                bad_scenario_type != bad_scenario_ack_resp_session_not_established_init_side and
673                bad_scenario_type != bad_scenario_ack_req_session_not_established_resp_side and
674                bad_scenario_type != bad_scenario_ack_resp_session_not_established_resp_side):
675                response = "accept"
676            else:
677                response = ''
678            initiator.initiate_session(sid, response)
679        if bad_scenario_type == bad_scenario_ack_req_session_not_set_up:
680            #fsts_id doesn't matter, no actual session exists
681            responder.send_test_ack_request('0')
682            initiator.wait_for_session_event(5)
683            # We want to send the unexpected frame to the side that already has
684            # a session created
685        elif bad_scenario_type == bad_scenario_ack_resp_session_not_set_up:
686            #fsts_id doesn't matter, no actual session exists
687            responder.send_test_ack_response('0')
688            initiator.wait_for_session_event(5)
689            # We want to send the unexpected frame to the side that already has
690            # a session created
691        elif bad_scenario_type == bad_scenario_ack_req_session_not_established_init_side:
692            #fsts_id doesn't matter, no actual session exists
693            initiator.send_test_ack_request('0')
694            responder.wait_for_session_event(5, ["EVENT_FST_SESSION_STATE"])
695        elif bad_scenario_type == bad_scenario_ack_req_session_not_established_resp_side:
696            #fsts_id doesn't matter, no actual session exists
697            responder.send_test_ack_request('0')
698            initiator.wait_for_session_event(5, ["EVENT_FST_SESSION_STATE"])
699        elif bad_scenario_type == bad_scenario_ack_resp_session_not_established_init_side:
700            #fsts_id doesn't matter, no actual session exists
701            initiator.send_test_ack_response('0')
702            responder.wait_for_session_event(5, ["EVENT_FST_SESSION_STATE"])
703        elif bad_scenario_type == bad_scenario_ack_resp_session_not_established_resp_side:
704            #fsts_id doesn't matter, no actual session exists
705            responder.send_test_ack_response('0')
706            initiator.wait_for_session_event(5, ["EVENT_FST_SESSION_STATE"])
707        elif bad_scenario_type == bad_scenario_ack_req_bad_fsts_id:
708            initiator.send_test_ack_request('-1')
709            responder.wait_for_session_event(5, ["EVENT_FST_SESSION_STATE"])
710        elif bad_scenario_type == bad_scenario_ack_resp_bad_fsts_id:
711            initiator.send_test_ack_response('-1')
712            responder.wait_for_session_event(5, ["EVENT_FST_SESSION_STATE"])
713        elif bad_scenario_type == bad_scenario_ack_resp_no_ack_req:
714            actual_fsts_id = initiator.get_fsts_id_by_sid(sid)
715            initiator.send_test_ack_response(str(actual_fsts_id))
716            responder.wait_for_session_event(5, ["EVENT_FST_SESSION_STATE"])
717        else:
718            raise Exception("Unknown bad scenario identifier")
719    except Exception as e:
720        if e.args[0].startswith("No FST-EVENT-SESSION received"):
721            bad_parameter_detected = True
722        if not bad_parameter_detected:
723            # The exception was unexpected
724            logger.info(e)
725            exception_already_raised = True
726            raise
727    finally:
728        fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
729        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
730        if not exception_already_raised:
731            if bad_parameter_detected:
732                logger.info("Success. Bad scenario was handled correctly (%s)" % bad_scenario_names[bad_scenario_type])
733            else:
734                raise Exception("Failure. Bad scenario was handled incorrectly (%s)" % bad_scenario_names[bad_scenario_type])
735        else:
736            logger.info("Failure. Unexpected exception")
737
738def test_fst_sta_connect_to_non_fst_ap(dev, apdev, test_params):
739    """FST STA connecting to non-FST AP"""
740    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
741    with HWSimRadio() as (radio, iface):
742        non_fst_ap = hostapd.add_ap(iface, {"ssid": "non_fst_11g"})
743        try:
744            orig_sta1_mbies = sta1.get_local_mbies()
745            orig_sta2_mbies = sta2.get_local_mbies()
746            sta2.connect_to_external_ap(non_fst_ap, ssid="non_fst_11g",
747                                        key_mgmt="NONE", scan_freq='2412')
748            time.sleep(2)
749            res_sta1_mbies = sta1.get_local_mbies()
750            res_sta2_mbies = sta2.get_local_mbies()
751            if (orig_sta1_mbies.startswith("FAIL") or
752                orig_sta2_mbies.startswith("FAIL") or
753                res_sta1_mbies.startswith("FAIL") or
754                res_sta2_mbies.startswith("FAIL")):
755                raise Exception("Failure. MB IEs must be present on the stations")
756        except Exception as e:
757            logger.info(e)
758            raise
759        finally:
760            sta2.disconnect_from_external_ap()
761            fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
762            hostapd.HostapdGlobal().remove(iface)
763
764def test_fst_sta_connect_to_fst_ap(dev, apdev, test_params):
765    """FST STA connecting to FST AP"""
766    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
767    try:
768        orig_sta2_mbies = sta2.get_local_mbies()
769        vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
770        sta1.connect(ap1, key_mgmt="NONE",
771                     scan_freq=fst_test_common.fst_test_def_freq_a)
772        time.sleep(2)
773        res_sta2_mbies = sta2.get_local_mbies()
774        if res_sta2_mbies == orig_sta2_mbies:
775            raise Exception("Failure. MB IEs have not been updated")
776    except Exception as e:
777        logger.info(e)
778        raise
779    finally:
780        sta1.disconnect()
781        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
782
783def test_fst_ap_connect_to_fst_sta(dev, apdev, test_params):
784    """FST AP connecting to FST STA"""
785    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
786    try:
787        orig_ap_mbies = ap1.get_local_mbies()
788        vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
789        sta1.connect(ap1, key_mgmt="NONE",
790                     scan_freq=fst_test_common.fst_test_def_freq_a)
791        time.sleep(2)
792        res_ap_mbies = ap1.get_local_mbies()
793        if res_ap_mbies != orig_ap_mbies:
794            raise Exception("Failure. MB IEs have been unexpectedly updated on the AP")
795    except Exception as e:
796        logger.info(e)
797        raise
798    finally:
799        sta1.disconnect()
800        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
801
802def test_fst_ap_connect_to_non_fst_sta(dev, apdev, test_params):
803    """FST AP connecting to non-FST STA"""
804    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
805    try:
806        orig_ap_mbies = ap2.get_local_mbies()
807        vals = dev[0].scan(None, fst_test_common.fst_test_def_freq_g)
808        fst_module_aux.external_sta_connect(dev[0], ap2, key_mgmt="NONE",
809                                            scan_freq=fst_test_common.fst_test_def_freq_g)
810        time.sleep(2)
811        res_ap_mbies = ap2.get_local_mbies()
812        if res_ap_mbies != orig_ap_mbies:
813            raise Exception("Failure. MB IEs have been unexpectedly updated on the AP")
814    except Exception as e:
815        logger.info(e)
816        raise
817    finally:
818        fst_module_aux.disconnect_external_sta(dev[0], ap2)
819        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
820
821def test_fst_second_sta_connect_to_non_fst_ap(dev, apdev, test_params):
822    """FST STA 2nd connecting to non-FST AP"""
823    fst_ap1, fst_ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
824    with HWSimRadio() as (radio, iface):
825        non_fst_ap = hostapd.add_ap(iface, {"ssid": "non_fst_11g"})
826        try:
827            vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
828            sta1.connect(fst_ap1, key_mgmt="NONE", scan_freq=fst_test_common.fst_test_def_freq_a)
829            time.sleep(2)
830            orig_sta1_mbies = sta1.get_local_mbies()
831            orig_sta2_mbies = sta2.get_local_mbies()
832            sta2.connect_to_external_ap(non_fst_ap, ssid="non_fst_11g",
833                                        key_mgmt="NONE", scan_freq='2412')
834            time.sleep(2)
835            res_sta1_mbies = sta1.get_local_mbies()
836            res_sta2_mbies = sta2.get_local_mbies()
837            if (orig_sta1_mbies.startswith("FAIL") or
838                orig_sta2_mbies.startswith("FAIL") or
839                res_sta1_mbies.startswith("FAIL") or
840                res_sta2_mbies.startswith("FAIL")):
841                raise Exception("Failure. MB IEs must be present on the stations")
842        except Exception as e:
843            logger.info(e)
844            raise
845        finally:
846            sta1.disconnect()
847            sta2.disconnect_from_external_ap()
848            fst_module_aux.stop_two_ap_sta_pairs(fst_ap1, fst_ap2, sta1, sta2)
849            hostapd.HostapdGlobal().remove(iface)
850
851def test_fst_second_sta_connect_to_fst_ap(dev, apdev, test_params):
852    """FST STA 2nd connecting to FST AP"""
853    fst_ap1, fst_ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
854    with HWSimRadio() as (radio, iface):
855        non_fst_ap = hostapd.add_ap(iface, {"ssid": "non_fst_11g"})
856        try:
857            sta2.connect_to_external_ap(non_fst_ap, ssid="non_fst_11g",
858                                        key_mgmt="NONE", scan_freq='2412')
859            time.sleep(2)
860            orig_sta1_mbies = sta1.get_local_mbies()
861            orig_sta2_mbies = sta2.get_local_mbies()
862            vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
863            sta1.connect(fst_ap1, key_mgmt="NONE", scan_freq=fst_test_common.fst_test_def_freq_a)
864            time.sleep(2)
865            res_sta1_mbies = sta1.get_local_mbies()
866            res_sta2_mbies = sta2.get_local_mbies()
867            if (orig_sta1_mbies.startswith("FAIL") or
868                orig_sta2_mbies.startswith("FAIL") or
869                res_sta1_mbies.startswith("FAIL") or
870                res_sta2_mbies.startswith("FAIL")):
871                raise Exception("Failure. MB IEs must be present on the stations")
872        except Exception as e:
873            logger.info(e)
874            raise
875        finally:
876            sta1.disconnect()
877            sta2.disconnect_from_external_ap()
878            fst_module_aux.stop_two_ap_sta_pairs(fst_ap1, fst_ap2, sta1, sta2)
879            hostapd.HostapdGlobal().remove(iface)
880
881def test_fst_disconnect_1_of_2_stas_from_non_fst_ap(dev, apdev, test_params):
882    """FST disconnect 1 of 2 STAs from non-FST AP"""
883    fst_ap1, fst_ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
884    with HWSimRadio() as (radio, iface):
885        non_fst_ap = hostapd.add_ap(iface, {"ssid": "non_fst_11g"})
886        try:
887            vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
888            sta1.connect(fst_ap1, key_mgmt="NONE", scan_freq=fst_test_common.fst_test_def_freq_a)
889            sta2.connect_to_external_ap(non_fst_ap, ssid="non_fst_11g",
890                                        key_mgmt="NONE", scan_freq='2412')
891            time.sleep(2)
892            orig_sta1_mbies = sta1.get_local_mbies()
893            orig_sta2_mbies = sta2.get_local_mbies()
894            sta2.disconnect_from_external_ap()
895            time.sleep(2)
896            res_sta1_mbies = sta1.get_local_mbies()
897            res_sta2_mbies = sta2.get_local_mbies()
898            if (orig_sta1_mbies.startswith("FAIL") or
899                orig_sta2_mbies.startswith("FAIL") or
900                res_sta1_mbies.startswith("FAIL") or
901                res_sta2_mbies.startswith("FAIL")):
902                raise Exception("Failure. MB IEs must be present on the stations")
903        except Exception as e:
904            logger.info(e)
905            raise
906        finally:
907            sta1.disconnect()
908            sta2.disconnect_from_external_ap()
909            fst_module_aux.stop_two_ap_sta_pairs(fst_ap1, fst_ap2, sta1, sta2)
910            hostapd.HostapdGlobal().remove(iface)
911
912def test_fst_disconnect_1_of_2_stas_from_fst_ap(dev, apdev, test_params):
913    """FST disconnect 1 of 2 STAs from FST AP"""
914    fst_ap1, fst_ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
915    with HWSimRadio() as (radio, iface):
916        non_fst_ap = hostapd.add_ap(iface, {"ssid": "non_fst_11g"})
917        try:
918            vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
919            sta1.connect(fst_ap1, key_mgmt="NONE", scan_freq=fst_test_common.fst_test_def_freq_a)
920            sta2.connect_to_external_ap(non_fst_ap, ssid="non_fst_11g",
921                                        key_mgmt="NONE", scan_freq='2412')
922            time.sleep(2)
923            orig_sta1_mbies = sta1.get_local_mbies()
924            orig_sta2_mbies = sta2.get_local_mbies()
925            sta1.disconnect()
926            time.sleep(2)
927            res_sta1_mbies = sta1.get_local_mbies()
928            res_sta2_mbies = sta2.get_local_mbies()
929            if (orig_sta1_mbies.startswith("FAIL") or
930                orig_sta2_mbies.startswith("FAIL") or
931                res_sta1_mbies.startswith("FAIL") or
932                res_sta2_mbies.startswith("FAIL")):
933                raise Exception("Failure. MB IEs must be present on the stations")
934        except Exception as e:
935            logger.info(e)
936            raise
937        finally:
938            sta1.disconnect()
939            sta2.disconnect_from_external_ap()
940            fst_module_aux.stop_two_ap_sta_pairs(fst_ap1, fst_ap2, sta1, sta2)
941            hostapd.HostapdGlobal().remove(iface)
942
943def test_fst_disconnect_2_of_2_stas_from_non_fst_ap(dev, apdev, test_params):
944    """FST disconnect 2 of 2 STAs from non-FST AP"""
945    fst_ap1, fst_ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
946    with HWSimRadio() as (radio, iface):
947        non_fst_ap = hostapd.add_ap(iface, {"ssid": "non_fst_11g"})
948        try:
949            vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
950            sta1.connect(fst_ap1, key_mgmt="NONE", scan_freq=fst_test_common.fst_test_def_freq_a)
951            sta2.connect_to_external_ap(non_fst_ap, ssid="non_fst_11g",
952                                        key_mgmt="NONE", scan_freq='2412')
953            time.sleep(2)
954            sta1.disconnect()
955            time.sleep(2)
956            orig_sta1_mbies = sta1.get_local_mbies()
957            orig_sta2_mbies = sta2.get_local_mbies()
958            sta2.disconnect_from_external_ap()
959            time.sleep(2)
960            res_sta1_mbies = sta1.get_local_mbies()
961            res_sta2_mbies = sta2.get_local_mbies()
962            if (orig_sta1_mbies.startswith("FAIL") or
963                orig_sta2_mbies.startswith("FAIL") or
964                res_sta1_mbies.startswith("FAIL") or
965                res_sta2_mbies.startswith("FAIL")):
966                raise Exception("Failure. MB IEs must be present on the stations")
967        except Exception as e:
968            logger.info(e)
969            raise
970        finally:
971            sta1.disconnect()
972            sta2.disconnect_from_external_ap()
973            fst_module_aux.stop_two_ap_sta_pairs(fst_ap1, fst_ap2, sta1, sta2)
974            hostapd.HostapdGlobal().remove(iface)
975
976def test_fst_disconnect_2_of_2_stas_from_fst_ap(dev, apdev, test_params):
977    """FST disconnect 2 of 2 STAs from FST AP"""
978    fst_ap1, fst_ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
979    with HWSimRadio() as (radio, iface):
980        non_fst_ap = hostapd.add_ap(iface, {"ssid": "non_fst_11g"})
981        try:
982            vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
983            sta1.connect(fst_ap1, key_mgmt="NONE", scan_freq=fst_test_common.fst_test_def_freq_a)
984            sta2.connect_to_external_ap(non_fst_ap, ssid="non_fst_11g",
985                                        key_mgmt="NONE", scan_freq='2412')
986            time.sleep(2)
987            sta2.disconnect_from_external_ap()
988            time.sleep(2)
989            orig_sta1_mbies = sta1.get_local_mbies()
990            orig_sta2_mbies = sta2.get_local_mbies()
991            sta1.disconnect()
992            time.sleep(2)
993            res_sta1_mbies = sta1.get_local_mbies()
994            res_sta2_mbies = sta2.get_local_mbies()
995            if (orig_sta1_mbies.startswith("FAIL") or
996                orig_sta2_mbies.startswith("FAIL") or
997                res_sta1_mbies.startswith("FAIL") or
998                res_sta2_mbies.startswith("FAIL")):
999                raise Exception("Failure. MB IEs should have stayed present on both stations")
1000            # Mandatory part of 8.4.2.140 Multi-band element is 24 bytes = 48 hex chars
1001            basic_sta1_mbies = res_sta1_mbies[0:48] + res_sta1_mbies[60:108]
1002            basic_sta2_mbies = res_sta2_mbies[0:48] + res_sta2_mbies[60:108]
1003            if (basic_sta1_mbies != basic_sta2_mbies):
1004                raise Exception("Failure. Basic MB IEs should have become identical on both stations")
1005            addr_sta1_str = sta1.get_own_mac_address().replace(":", "")
1006            addr_sta2_str = sta2.get_own_mac_address().replace(":", "")
1007            # Mandatory part of 8.4.2.140 Multi-band element is followed by STA MAC Address field (6 bytes = 12 hex chars)
1008            addr_sta1_mbie1 = res_sta1_mbies[48:60]
1009            addr_sta1_mbie2 = res_sta1_mbies[108:120]
1010            addr_sta2_mbie1 = res_sta2_mbies[48:60]
1011            addr_sta2_mbie2 = res_sta2_mbies[108:120]
1012            if (addr_sta1_mbie1 != addr_sta1_mbie2 or
1013                addr_sta1_mbie1 != addr_sta2_str or
1014                addr_sta2_mbie1 != addr_sta2_mbie2 or
1015                addr_sta2_mbie1 != addr_sta1_str):
1016                raise Exception("Failure. STA Address in MB IEs should have been same as the other STA's")
1017        except Exception as e:
1018            logger.info(e)
1019            raise
1020        finally:
1021            sta1.disconnect()
1022            sta2.disconnect_from_external_ap()
1023            fst_module_aux.stop_two_ap_sta_pairs(fst_ap1, fst_ap2, sta1, sta2)
1024            hostapd.HostapdGlobal().remove(iface)
1025
1026def test_fst_disconnect_non_fst_sta(dev, apdev, test_params):
1027    """FST disconnect non-FST STA"""
1028    ap1, ap2, fst_sta1, fst_sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
1029    external_sta_connected = False
1030    try:
1031        vals = fst_sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
1032        fst_sta1.connect(ap1, key_mgmt="NONE",
1033                         scan_freq=fst_test_common.fst_test_def_freq_a)
1034        vals = dev[0].scan(None, fst_test_common.fst_test_def_freq_g)
1035        fst_module_aux.external_sta_connect(dev[0], ap2, key_mgmt="NONE",
1036                                            scan_freq=fst_test_common.fst_test_def_freq_g)
1037        external_sta_connected = True
1038        time.sleep(2)
1039        fst_sta1.disconnect()
1040        time.sleep(2)
1041        orig_ap_mbies = ap2.get_local_mbies()
1042        fst_module_aux.disconnect_external_sta(dev[0], ap2)
1043        external_sta_connected = False
1044        time.sleep(2)
1045        res_ap_mbies = ap2.get_local_mbies()
1046        if res_ap_mbies != orig_ap_mbies:
1047            raise Exception("Failure. MB IEs have been unexpectedly updated on the AP")
1048    except Exception as e:
1049        logger.info(e)
1050        raise
1051    finally:
1052        fst_sta1.disconnect()
1053        if external_sta_connected:
1054            fst_module_aux.disconnect_external_sta(dev[0], ap2)
1055        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, fst_sta1, fst_sta2)
1056
1057def test_fst_disconnect_fst_sta(dev, apdev, test_params):
1058    """FST disconnect FST STA"""
1059    ap1, ap2, fst_sta1, fst_sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
1060    external_sta_connected = False
1061    try:
1062        vals = fst_sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
1063        fst_sta1.connect(ap1, key_mgmt="NONE",
1064                         scan_freq=fst_test_common.fst_test_def_freq_a)
1065        vals = dev[0].scan(None, fst_test_common.fst_test_def_freq_g)
1066        fst_module_aux.external_sta_connect(dev[0], ap2, key_mgmt="NONE",
1067                                            scan_freq=fst_test_common.fst_test_def_freq_g)
1068        external_sta_connected = True
1069        time.sleep(2)
1070        fst_module_aux.disconnect_external_sta(dev[0], ap2)
1071        external_sta_connected = False
1072        time.sleep(2)
1073        orig_ap_mbies = ap2.get_local_mbies()
1074        fst_sta1.disconnect()
1075        time.sleep(2)
1076        res_ap_mbies = ap2.get_local_mbies()
1077        if res_ap_mbies != orig_ap_mbies:
1078            raise Exception("Failure. MB IEs have been unexpectedly updated on the AP")
1079    except Exception as e:
1080        logger.info(e)
1081        raise
1082    finally:
1083        fst_sta1.disconnect()
1084        if external_sta_connected:
1085            fst_module_aux.disconnect_external_sta(dev[0], ap2)
1086        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, fst_sta1, fst_sta2)
1087
1088def test_fst_dynamic_iface_attach(dev, apdev, test_params):
1089    """FST dynamic interface attach"""
1090    ap1 = fst_module_aux.FstAP(apdev[0]['ifname'], 'fst_11a', 'a',
1091                               fst_test_common.fst_test_def_chan_a,
1092                               fst_test_common.fst_test_def_group,
1093                               fst_test_common.fst_test_def_prio_low,
1094                               fst_test_common.fst_test_def_llt)
1095    ap1.start()
1096    ap2 = fst_module_aux.FstAP(apdev[1]['ifname'], 'fst_11g', 'b',
1097                               fst_test_common.fst_test_def_chan_g,
1098                               '', '', '')
1099    ap2.start()
1100
1101    sta1 = fst_module_aux.FstSTA('wlan5',
1102                                 fst_test_common.fst_test_def_group,
1103                                 fst_test_common.fst_test_def_prio_low,
1104                                 fst_test_common.fst_test_def_llt)
1105    sta1.start()
1106    sta2 = fst_module_aux.FstSTA('wlan6', '', '', '')
1107    sta2.start()
1108
1109    try:
1110        orig_sta2_mbies = sta2.get_local_mbies()
1111        orig_ap2_mbies = ap2.get_local_mbies()
1112        sta2.send_iface_attach_request(sta2.ifname(),
1113                                       fst_test_common.fst_test_def_group,
1114                                       '52', '27')
1115        event = sta2.wait_for_iface_event(5)
1116        if event['event_type'] != 'attached':
1117            raise Exception("Failure. Iface was not properly attached")
1118        ap2.send_iface_attach_request(ap2.ifname(),
1119                                      fst_test_common.fst_test_def_group,
1120                                      '102', '77')
1121        event = ap2.wait_for_iface_event(5)
1122        if event['event_type'] != 'attached':
1123            raise Exception("Failure. Iface was not properly attached")
1124        time.sleep(2)
1125        res_sta2_mbies = sta2.get_local_mbies()
1126        res_ap2_mbies = ap2.get_local_mbies()
1127        sta2.send_iface_detach_request(sta2.ifname())
1128        event = sta2.wait_for_iface_event(5)
1129        if event['event_type'] != 'detached':
1130            raise Exception("Failure. Iface was not properly detached")
1131        ap2.send_iface_detach_request(ap2.ifname())
1132        event = ap2.wait_for_iface_event(5)
1133        if event['event_type'] != 'detached':
1134            raise Exception("Failure. Iface was not properly detached")
1135        if (not orig_sta2_mbies.startswith("FAIL") or
1136            not orig_ap2_mbies.startswith("FAIL") or
1137            res_sta2_mbies.startswith("FAIL") or
1138            res_ap2_mbies.startswith("FAIL")):
1139            raise Exception("Failure. MB IEs should have appeared on the station and on the AP")
1140    except Exception as e:
1141        logger.info(e)
1142        raise
1143    finally:
1144        ap1.stop()
1145        ap2.stop()
1146        sta1.stop()
1147        sta2.stop()
1148
1149# AP side FST module tests
1150
1151def test_fst_ap_start_session(dev, apdev, test_params):
1152    """FST AP start session"""
1153    fst_start_session(apdev, test_params, bad_param_none, True)
1154
1155def test_fst_ap_start_session_no_add_params(dev, apdev, test_params):
1156    """FST AP start session - no add params"""
1157    fst_start_session(apdev, test_params, bad_param_session_add_no_params, True)
1158
1159def test_fst_ap_start_session_bad_group_id(dev, apdev, test_params):
1160    """FST AP start session - bad group id"""
1161    fst_start_session(apdev, test_params, bad_param_group_id, True)
1162
1163def test_fst_ap_start_session_no_set_params(dev, apdev, test_params):
1164    """FST AP start session - no set params"""
1165    fst_start_session(apdev, test_params, bad_param_session_set_no_params, True)
1166
1167def test_fst_ap_start_session_set_unknown_param(dev, apdev, test_params):
1168    """FST AP start session - set unknown param"""
1169    fst_start_session(apdev, test_params, bad_param_session_set_unknown_param,
1170                      True)
1171
1172def test_fst_ap_start_session_bad_session_id(dev, apdev, test_params):
1173    """FST AP start session - bad session id"""
1174    fst_start_session(apdev, test_params, bad_param_session_id, True)
1175
1176def test_fst_ap_start_session_bad_new_iface(dev, apdev, test_params):
1177    """FST AP start session - bad new iface"""
1178    fst_start_session(apdev, test_params, bad_param_new_iface, True)
1179
1180def test_fst_ap_start_session_bad_old_iface(dev, apdev, test_params):
1181    """FST AP start session - bad old iface"""
1182    fst_start_session(apdev, test_params, bad_param_old_iface, True)
1183
1184def test_fst_ap_start_session_negative_llt(dev, apdev, test_params):
1185    """FST AP start session - negative llt"""
1186    fst_start_session(apdev, test_params, bad_param_negative_llt, True)
1187
1188def test_fst_ap_start_session_zero_llt(dev, apdev, test_params):
1189    """FST AP start session - zero llt"""
1190    fst_start_session(apdev, test_params, bad_param_zero_llt, True)
1191
1192def test_fst_ap_start_session_llt_too_big(dev, apdev, test_params):
1193    """FST AP start session - llt too large"""
1194    fst_start_session(apdev, test_params, bad_param_llt_too_big, True)
1195
1196def test_fst_ap_start_session_invalid_peer_addr(dev, apdev, test_params):
1197    """FST AP start session - invalid peer address"""
1198    fst_start_session(apdev, test_params, bad_param_peer_addr, True,
1199                      'GG:GG:GG:GG:GG:GG')
1200
1201def test_fst_ap_start_session_multicast_peer_addr(dev, apdev, test_params):
1202    """FST AP start session - multicast peer address"""
1203    fst_start_session(apdev, test_params, bad_param_peer_addr, True,
1204                      '01:00:11:22:33:44')
1205
1206def test_fst_ap_start_session_broadcast_peer_addr(dev, apdev, test_params):
1207    """FST AP start session - broadcast peer address"""
1208    fst_start_session(apdev, test_params, bad_param_peer_addr, True,
1209                      'FF:FF:FF:FF:FF:FF')
1210
1211def test_fst_ap_initiate_session(dev, apdev, test_params):
1212    """FST AP initiate session"""
1213    fst_initiate_session(apdev, test_params, bad_param_none, True)
1214
1215def test_fst_ap_initiate_session_no_params(dev, apdev, test_params):
1216    """FST AP initiate session - no params"""
1217    fst_initiate_session(apdev, test_params,
1218                         bad_param_session_initiate_no_params, True)
1219
1220def test_fst_ap_initiate_session_invalid_session_id(dev, apdev, test_params):
1221    """FST AP initiate session - invalid session id"""
1222    fst_initiate_session(apdev, test_params,
1223                         bad_param_session_initiate_bad_session_id, True)
1224
1225def test_fst_ap_initiate_session_no_new_iface(dev, apdev, test_params):
1226    """FST AP initiate session - no new iface"""
1227    fst_initiate_session(apdev, test_params,
1228                         bad_param_session_initiate_with_no_new_iface_set, True)
1229
1230def test_fst_ap_initiate_session_bad_peer_addr(dev, apdev, test_params):
1231    """FST AP initiate session - bad peer address"""
1232    fst_initiate_session(apdev, test_params,
1233                         bad_param_session_initiate_with_bad_peer_addr_set,
1234                         True)
1235
1236def test_fst_ap_initiate_session_request_with_bad_stie(dev, apdev, test_params):
1237    """FST AP initiate session - request with bad stie"""
1238    fst_initiate_session(apdev, test_params,
1239                         bad_param_session_initiate_request_with_bad_stie, True)
1240
1241def test_fst_ap_initiate_session_response_with_reject(dev, apdev, test_params):
1242    """FST AP initiate session - response with reject"""
1243    fst_initiate_session(apdev, test_params,
1244                         bad_param_session_initiate_response_with_reject, True)
1245
1246def test_fst_ap_initiate_session_response_with_bad_stie(dev, apdev,
1247                                                        test_params):
1248    """FST AP initiate session - response with bad stie"""
1249    fst_initiate_session(apdev, test_params,
1250                         bad_param_session_initiate_response_with_bad_stie,
1251                         True)
1252
1253def test_fst_ap_initiate_session_response_with_zero_llt(dev, apdev,
1254                                                        test_params):
1255    """FST AP initiate session - zero llt"""
1256    fst_initiate_session(apdev, test_params,
1257                         bad_param_session_initiate_response_with_zero_llt,
1258                         True)
1259
1260def test_fst_ap_initiate_session_stt_no_response(dev, apdev, test_params):
1261    """FST AP initiate session - stt no response"""
1262    fst_initiate_session(apdev, test_params,
1263                         bad_param_session_initiate_stt_no_response, True)
1264
1265def test_fst_ap_initiate_session_concurrent_setup_request(dev, apdev,
1266                                                          test_params):
1267    """FST AP initiate session - concurrent setup request"""
1268    fst_initiate_session(apdev, test_params,
1269                         bad_param_session_initiate_concurrent_setup_request,
1270                         True)
1271
1272def test_fst_ap_session_request_with_no_session(dev, apdev, test_params):
1273    """FST AP session request with no session"""
1274    fst_send_unexpected_frame(apdev, test_params, frame_type_session_request,
1275                              True)
1276
1277def test_fst_ap_session_response_accept_with_no_session(dev, apdev,
1278                                                        test_params):
1279    """FST AP session response accept with no session"""
1280    fst_send_unexpected_frame(apdev, test_params, frame_type_session_response,
1281                              True, "accept")
1282
1283def test_fst_ap_session_response_reject_with_no_session(dev, apdev,
1284                                                        test_params):
1285    """FST AP session response reject with no session"""
1286    fst_send_unexpected_frame(apdev, test_params, frame_type_session_response,
1287                              True, "reject")
1288
1289def test_fst_ap_ack_request_with_no_session(dev, apdev, test_params):
1290    """FST AP ack request with no session"""
1291    fst_send_unexpected_frame(apdev, test_params, frame_type_ack_request, True)
1292
1293def test_fst_ap_ack_response_with_no_session(dev, apdev, test_params):
1294    """FST AP ack response with no session"""
1295    fst_send_unexpected_frame(apdev, test_params, frame_type_ack_response, True)
1296
1297def test_fst_ap_tear_down_response_with_no_session(dev, apdev, test_params):
1298    """FST AP tear down response with no session"""
1299    fst_send_unexpected_frame(apdev, test_params, frame_type_tear_down, True)
1300
1301def test_fst_ap_transfer_session(dev, apdev, test_params):
1302    """FST AP transfer session"""
1303    fst_transfer_session(apdev, test_params, bad_param_none, True)
1304
1305def test_fst_ap_transfer_session_no_params(dev, apdev, test_params):
1306    """FST AP transfer session - no params"""
1307    fst_transfer_session(apdev, test_params,
1308                         bad_param_session_transfer_no_params, True)
1309
1310def test_fst_ap_transfer_session_bad_session_id(dev, apdev, test_params):
1311    """FST AP transfer session - bad session id"""
1312    fst_transfer_session(apdev, test_params,
1313                         bad_param_session_transfer_bad_session_id, True)
1314
1315def test_fst_ap_transfer_session_setup_skipped(dev, apdev, test_params):
1316    """FST AP transfer session - setup skipped"""
1317    fst_transfer_session(apdev, test_params,
1318                         bad_param_session_transfer_setup_skipped, True)
1319
1320def test_fst_ap_ack_request_with_session_not_set_up(dev, apdev, test_params):
1321    """FST AP ack request with session not set up"""
1322    fst_bad_transfer(apdev, test_params,
1323                     bad_scenario_ack_req_session_not_set_up, True)
1324
1325def test_fst_ap_ack_request_with_session_not_established_init_side(dev, apdev,
1326                                                                   test_params):
1327    """FST AP ack request with session not established init side"""
1328    fst_bad_transfer(apdev, test_params,
1329                     bad_scenario_ack_req_session_not_established_init_side,
1330                     True)
1331
1332def test_fst_ap_ack_request_with_session_not_established_resp_side(dev, apdev,
1333                                                                   test_params):
1334    """FST AP ack request with session not established resp side"""
1335    fst_bad_transfer(apdev, test_params,
1336                     bad_scenario_ack_req_session_not_established_resp_side,
1337                     True)
1338
1339def test_fst_ap_ack_request_with_bad_fsts_id(dev, apdev, test_params):
1340    """FST AP ack request with bad fsts id"""
1341    fst_bad_transfer(apdev, test_params, bad_scenario_ack_req_bad_fsts_id, True)
1342
1343def test_fst_ap_ack_response_with_session_not_set_up(dev, apdev, test_params):
1344    """FST AP ack response with session not set up"""
1345    fst_bad_transfer(apdev, test_params,
1346                     bad_scenario_ack_resp_session_not_set_up, True)
1347
1348def test_fst_ap_ack_response_with_session_not_established_init_side(dev, apdev, test_params):
1349    """FST AP ack response with session not established init side"""
1350    fst_bad_transfer(apdev, test_params,
1351                     bad_scenario_ack_resp_session_not_established_init_side,
1352                     True)
1353
1354def test_fst_ap_ack_response_with_session_not_established_resp_side(dev, apdev, test_params):
1355    """FST AP ack response with session not established resp side"""
1356    fst_bad_transfer(apdev, test_params,
1357                     bad_scenario_ack_resp_session_not_established_resp_side,
1358                     True)
1359
1360def test_fst_ap_ack_response_with_no_ack_request(dev, apdev, test_params):
1361    """FST AP ack response with no ack request"""
1362    fst_bad_transfer(apdev, test_params, bad_scenario_ack_resp_no_ack_req, True)
1363
1364def test_fst_ap_tear_down_session(dev, apdev, test_params):
1365    """FST AP tear down session"""
1366    fst_tear_down_session(apdev, test_params, bad_param_none, True)
1367
1368def test_fst_ap_tear_down_session_no_params(dev, apdev, test_params):
1369    """FST AP tear down session - no params"""
1370    fst_tear_down_session(apdev, test_params,
1371                          bad_param_session_teardown_no_params, True)
1372
1373def test_fst_ap_tear_down_session_bad_session_id(dev, apdev, test_params):
1374    """FST AP tear down session - bad session id"""
1375    fst_tear_down_session(apdev, test_params,
1376                          bad_param_session_teardown_bad_session_id, True)
1377
1378def test_fst_ap_tear_down_session_setup_skipped(dev, apdev, test_params):
1379    """FST AP tear down session - setup skipped"""
1380    fst_tear_down_session(apdev, test_params,
1381                          bad_param_session_teardown_setup_skipped, True)
1382
1383def test_fst_ap_tear_down_session_bad_fsts_id(dev, apdev, test_params):
1384    """FST AP tear down session - bad fsts id"""
1385    fst_tear_down_session(apdev, test_params,
1386                          bad_param_session_teardown_bad_fsts_id, True)
1387
1388def test_fst_ap_remove_session_not_established(dev, apdev, test_params):
1389    """FST AP remove session - not established"""
1390    fst_remove_session(apdev, test_params,
1391                       remove_scenario_non_established_session, True)
1392
1393def test_fst_ap_remove_session_established(dev, apdev, test_params):
1394    """FST AP remove session - established"""
1395    fst_remove_session(apdev, test_params,
1396                       remove_scenario_established_session, True)
1397
1398def test_fst_ap_remove_session_no_params(dev, apdev, test_params):
1399    """FST AP remove session - no params"""
1400    fst_remove_session(apdev, test_params, remove_scenario_no_params, True)
1401
1402def test_fst_ap_remove_session_bad_session_id(dev, apdev, test_params):
1403    """FST AP remove session - bad session id"""
1404    fst_remove_session(apdev, test_params, remove_scenario_bad_session_id, True)
1405
1406def test_fst_ap_ctrl_iface(dev, apdev, test_params):
1407    """FST control interface behavior"""
1408    hglobal = hostapd.HostapdGlobal()
1409    start_num_groups = 0
1410    res = hglobal.request("FST-MANAGER LIST_GROUPS")
1411    del hglobal
1412    if "FAIL" not in res:
1413        start_num_groups = len(res.splitlines())
1414
1415    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
1416    try:
1417        fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
1418        initiator = ap1
1419        responder = sta1
1420        initiator.add_peer(responder, None)
1421        initiator.set_fst_parameters(group_id=None)
1422        sid = initiator.add_session()
1423        res = initiator.get_session_params(sid)
1424        logger.info("Initial session params:\n" + str(res))
1425        if res['state'] != 'INITIAL':
1426            raise Exception("Unexpected state: " + res['state'])
1427        initiator.set_fst_parameters(llt=None)
1428        initiator.configure_session(sid, ap2.ifname(), None)
1429        res = initiator.get_session_params(sid)
1430        logger.info("Session params after configuration:\n" + str(res))
1431        res = initiator.iface_peers(initiator.ifname())
1432        logger.info("Interface peers: " + str(res))
1433        if len(res) != 1:
1434            raise Exception("Unexpected number of peers")
1435        res = initiator.get_peer_mbies(initiator.ifname(),
1436                                       initiator.get_new_peer_addr())
1437        logger.info("Peer MB IEs: " + str(res))
1438        res = initiator.list_ifaces()
1439        logger.info("Interfaces: " + str(res))
1440        if len(res) != 2:
1441            raise Exception("Unexpected number of interfaces")
1442        res = initiator.list_groups()
1443        logger.info("Groups: " + str(res))
1444        if len(res) != 1 + start_num_groups:
1445            raise Exception("Unexpected number of groups")
1446
1447        tests = ["LIST_IFACES unknown",
1448                 "LIST_IFACES     unknown2",
1449                 "SESSION_GET 12345678",
1450                 "SESSION_SET " + sid + " unknown=foo",
1451                 "SESSION_RESPOND 12345678 foo",
1452                 "SESSION_RESPOND " + sid,
1453                 "SESSION_RESPOND " + sid + " foo",
1454                 "TEST_REQUEST foo",
1455                 "TEST_REQUEST SEND_SETUP_REQUEST",
1456                 "TEST_REQUEST SEND_SETUP_REQUEST foo",
1457                 "TEST_REQUEST SEND_SETUP_RESPONSE",
1458                 "TEST_REQUEST SEND_SETUP_RESPONSE foo",
1459                 "TEST_REQUEST SEND_ACK_REQUEST",
1460                 "TEST_REQUEST SEND_ACK_REQUEST foo",
1461                 "TEST_REQUEST SEND_ACK_RESPONSE",
1462                 "TEST_REQUEST SEND_ACK_RESPONSE foo",
1463                 "TEST_REQUEST SEND_TEAR_DOWN",
1464                 "TEST_REQUEST SEND_TEAR_DOWN foo",
1465                 "TEST_REQUEST GET_FSTS_ID",
1466                 "TEST_REQUEST GET_FSTS_ID foo",
1467                 "TEST_REQUEST GET_LOCAL_MBIES",
1468                 "TEST_REQUEST GET_LOCAL_MBIES foo",
1469                 "GET_PEER_MBIES",
1470                 "GET_PEER_MBIES ",
1471                 "GET_PEER_MBIES unknown",
1472                 "GET_PEER_MBIES unknown unknown",
1473                 "GET_PEER_MBIES unknown  " + initiator.get_new_peer_addr(),
1474                 "GET_PEER_MBIES " + initiator.ifname() + " 01:ff:ff:ff:ff:ff",
1475                 "GET_PEER_MBIES " + initiator.ifname() + " 00:ff:ff:ff:ff:ff",
1476                 "GET_PEER_MBIES " + initiator.ifname() + " 00:00:00:00:00:00",
1477                 "IFACE_PEERS",
1478                 "IFACE_PEERS ",
1479                 "IFACE_PEERS unknown",
1480                 "IFACE_PEERS unknown unknown",
1481                 "IFACE_PEERS " + initiator.fst_group,
1482                 "IFACE_PEERS " + initiator.fst_group + " unknown"]
1483        for t in tests:
1484            if "FAIL" not in initiator.grequest("FST-MANAGER " + t):
1485                raise Exception("Unexpected response for invalid FST-MANAGER command " + t)
1486        if "UNKNOWN FST COMMAND" not in initiator.grequest("FST-MANAGER unknown"):
1487            raise Exception("Unexpected response for unknown FST-MANAGER command")
1488
1489        tests = ["FST-DETACH", "FST-DETACH ", "FST-DETACH unknown",
1490                 "FST-ATTACH", "FST-ATTACH ", "FST-ATTACH unknown",
1491                 "FST-ATTACH unknown unknown"]
1492        for t in tests:
1493            if "FAIL" not in initiator.grequest(t):
1494                raise Exception("Unexpected response for invalid command " + t)
1495
1496        try:
1497            # Trying to add same interface again needs to fail.
1498            ap1.send_iface_attach_request(ap1.iface, ap1.fst_group,
1499                                          ap1.fst_llt, ap1.fst_pri)
1500            raise Exception("Duplicate FST-ATTACH succeeded")
1501        except Exception as e:
1502            if not str(e).startswith("Cannot attach"):
1503                raise
1504
1505        try:
1506            ap1.get_fsts_id_by_sid("123")
1507        except Exception as e:
1508            if not str(e).startswith("Cannot get fsts_id for sid"):
1509                raise
1510    finally:
1511        fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
1512        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
1513
1514def test_fst_ap_start_session_oom(dev, apdev, test_params):
1515    """FST AP setup failing due to OOM"""
1516    ap1 = fst_module_aux.FstAP(apdev[0]['ifname'], 'fst_11a', 'a',
1517                               fst_test_common.fst_test_def_chan_a,
1518                               fst_test_common.fst_test_def_group,
1519                               fst_test_common.fst_test_def_prio_low,
1520                               fst_test_common.fst_test_def_llt)
1521    ap1.start()
1522    try:
1523        run_fst_ap_start_session_oom(apdev, ap1)
1524    finally:
1525        ap1.stop()
1526        fst_test_common.fst_clear_regdom()
1527
1528def run_fst_ap_start_session_oom(apdev, ap1):
1529    with alloc_fail(ap1, 1, "fst_iface_create"):
1530        ap2_started = False
1531        try:
1532            ap2 = fst_module_aux.FstAP(apdev[1]['ifname'], 'fst_11g', 'b',
1533                                       fst_test_common.fst_test_def_chan_g,
1534                                       fst_test_common.fst_test_def_group,
1535                                       fst_test_common.fst_test_def_prio_high,
1536                                       fst_test_common.fst_test_def_llt)
1537            try:
1538                # This will fail in fst_iface_create() OOM
1539                ap2.start()
1540            except:
1541                pass
1542        finally:
1543            try:
1544                ap2.stop()
1545            except:
1546                pass
1547
1548# STA side FST module tests
1549
1550def test_fst_sta_start_session(dev, apdev, test_params):
1551    """FST STA start session"""
1552    fst_start_session(apdev, test_params, bad_param_none, False)
1553
1554def test_fst_sta_start_session_no_add_params(dev, apdev, test_params):
1555    """FST STA start session - no add params"""
1556    fst_start_session(apdev, test_params, bad_param_session_add_no_params,
1557                      False)
1558
1559def test_fst_sta_start_session_bad_group_id(dev, apdev, test_params):
1560    """FST STA start session - bad group id"""
1561    fst_start_session(apdev, test_params, bad_param_group_id, False)
1562
1563def test_fst_sta_start_session_no_set_params(dev, apdev, test_params):
1564    """FST STA start session - no set params"""
1565    fst_start_session(apdev, test_params, bad_param_session_set_no_params,
1566                      False)
1567
1568def test_fst_sta_start_session_set_unknown_param(dev, apdev, test_params):
1569    """FST STA start session - set unknown param"""
1570    fst_start_session(apdev, test_params, bad_param_session_set_unknown_param,
1571                      False)
1572
1573def test_fst_sta_start_session_bad_session_id(dev, apdev, test_params):
1574    """FST STA start session - bad session id"""
1575    fst_start_session(apdev, test_params, bad_param_session_id, False)
1576
1577def test_fst_sta_start_session_bad_new_iface(dev, apdev, test_params):
1578    """FST STA start session - bad new iface"""
1579    fst_start_session(apdev, test_params, bad_param_new_iface, False)
1580
1581def test_fst_sta_start_session_bad_old_iface(dev, apdev, test_params):
1582    """FST STA start session - bad old iface"""
1583    fst_start_session(apdev, test_params, bad_param_old_iface, False)
1584
1585def test_fst_sta_start_session_negative_llt(dev, apdev, test_params):
1586    """FST STA start session - negative llt"""
1587    fst_start_session(apdev, test_params, bad_param_negative_llt, False)
1588
1589def test_fst_sta_start_session_zero_llt(dev, apdev, test_params):
1590    """FST STA start session - zero llt"""
1591    fst_start_session(apdev, test_params, bad_param_zero_llt, False)
1592
1593def test_fst_sta_start_session_llt_too_big(dev, apdev, test_params):
1594    """FST STA start session - llt too large"""
1595    fst_start_session(apdev, test_params, bad_param_llt_too_big, False)
1596
1597def test_fst_sta_start_session_invalid_peer_addr(dev, apdev, test_params):
1598    """FST STA start session - invalid peer address"""
1599    fst_start_session(apdev, test_params, bad_param_peer_addr, False,
1600                      'GG:GG:GG:GG:GG:GG')
1601
1602def test_fst_sta_start_session_multicast_peer_addr(dev, apdev, test_params):
1603    """FST STA start session - multicast peer address"""
1604    fst_start_session(apdev, test_params, bad_param_peer_addr, False,
1605                      '11:00:11:22:33:44')
1606
1607def test_fst_sta_start_session_broadcast_peer_addr(dev, apdev, test_params):
1608    """FST STA start session - broadcast peer addr"""
1609    fst_start_session(apdev, test_params, bad_param_peer_addr, False,
1610                      'FF:FF:FF:FF:FF:FF')
1611
1612def test_fst_sta_initiate_session(dev, apdev, test_params):
1613    """FST STA initiate session"""
1614    fst_initiate_session(apdev, test_params, bad_param_none, False)
1615
1616def test_fst_sta_initiate_session_no_params(dev, apdev, test_params):
1617    """FST STA initiate session - no params"""
1618    fst_initiate_session(apdev, test_params,
1619                         bad_param_session_initiate_no_params, False)
1620
1621def test_fst_sta_initiate_session_invalid_session_id(dev, apdev, test_params):
1622    """FST STA initiate session - invalid session id"""
1623    fst_initiate_session(apdev, test_params,
1624                         bad_param_session_initiate_bad_session_id, False)
1625
1626def test_fst_sta_initiate_session_no_new_iface(dev, apdev, test_params):
1627    """FST STA initiate session - no new iface"""
1628    fst_initiate_session(apdev, test_params,
1629                         bad_param_session_initiate_with_no_new_iface_set,
1630                         False)
1631
1632def test_fst_sta_initiate_session_bad_peer_addr(dev, apdev, test_params):
1633    """FST STA initiate session - bad peer address"""
1634    fst_initiate_session(apdev, test_params,
1635                         bad_param_session_initiate_with_bad_peer_addr_set,
1636                         False)
1637
1638def test_fst_sta_initiate_session_request_with_bad_stie(dev, apdev,
1639                                                        test_params):
1640    """FST STA initiate session - request with bad stie"""
1641    fst_initiate_session(apdev, test_params,
1642                         bad_param_session_initiate_request_with_bad_stie,
1643                         False)
1644
1645def test_fst_sta_initiate_session_response_with_reject(dev, apdev, test_params):
1646    """FST STA initiate session - response with reject"""
1647    fst_initiate_session(apdev, test_params, bad_param_session_initiate_response_with_reject, False)
1648
1649def test_fst_sta_initiate_session_response_with_bad_stie(dev, apdev, test_params):
1650    """FST STA initiate session - response with bad stie"""
1651    fst_initiate_session(apdev, test_params,
1652                         bad_param_session_initiate_response_with_bad_stie,
1653                         False)
1654
1655def test_fst_sta_initiate_session_response_with_zero_llt(dev, apdev,
1656                                                         test_params):
1657    """FST STA initiate session - response with zero llt"""
1658    fst_initiate_session(apdev, test_params,
1659                         bad_param_session_initiate_response_with_zero_llt,
1660                         False)
1661
1662def test_fst_sta_initiate_session_stt_no_response(dev, apdev, test_params):
1663    """FST STA initiate session - stt no response"""
1664    fst_initiate_session(apdev, test_params,
1665                         bad_param_session_initiate_stt_no_response, False)
1666
1667def test_fst_sta_initiate_session_concurrent_setup_request(dev, apdev,
1668                                                           test_params):
1669    """FST STA initiate session - concurrent setup request"""
1670    fst_initiate_session(apdev, test_params,
1671                         bad_param_session_initiate_concurrent_setup_request,
1672                         False)
1673
1674def test_fst_sta_session_request_with_no_session(dev, apdev, test_params):
1675    """FST STA session request with no session"""
1676    fst_send_unexpected_frame(apdev, test_params, frame_type_session_request,
1677                              False)
1678
1679def test_fst_sta_session_response_accept_with_no_session(dev, apdev,
1680                                                         test_params):
1681    """FST STA session response accept with no session"""
1682    fst_send_unexpected_frame(apdev, test_params, frame_type_session_response,
1683                              False, "accept")
1684
1685def test_fst_sta_session_response_reject_with_no_session(dev, apdev,
1686                                                         test_params):
1687    """FST STA session response reject with no session"""
1688    fst_send_unexpected_frame(apdev, test_params, frame_type_session_response,
1689                              False, "reject")
1690
1691def test_fst_sta_ack_request_with_no_session(dev, apdev, test_params):
1692    """FST STA ack request with no session"""
1693    fst_send_unexpected_frame(apdev, test_params, frame_type_ack_request, False)
1694
1695def test_fst_sta_ack_response_with_no_session(dev, apdev, test_params):
1696    """FST STA ack response with no session"""
1697    fst_send_unexpected_frame(apdev, test_params, frame_type_ack_response,
1698                              False)
1699
1700def test_fst_sta_tear_down_response_with_no_session(dev, apdev, test_params):
1701    """FST STA tear down response with no session"""
1702    fst_send_unexpected_frame(apdev, test_params, frame_type_tear_down, False)
1703
1704def test_fst_sta_transfer_session(dev, apdev, test_params):
1705    """FST STA transfer session"""
1706    fst_transfer_session(apdev, test_params, bad_param_none, False)
1707
1708def test_fst_sta_transfer_session_no_params(dev, apdev, test_params):
1709    """FST STA transfer session - no params"""
1710    fst_transfer_session(apdev, test_params,
1711                         bad_param_session_transfer_no_params, False)
1712
1713def test_fst_sta_transfer_session_bad_session_id(dev, apdev, test_params):
1714    """FST STA transfer session - bad session id"""
1715    fst_transfer_session(apdev, test_params,
1716                         bad_param_session_transfer_bad_session_id, False)
1717
1718def test_fst_sta_transfer_session_setup_skipped(dev, apdev, test_params):
1719    """FST STA transfer session - setup skipped"""
1720    fst_transfer_session(apdev, test_params,
1721                         bad_param_session_transfer_setup_skipped, False)
1722
1723def test_fst_sta_ack_request_with_session_not_set_up(dev, apdev, test_params):
1724    """FST STA ack request with session not set up"""
1725    fst_bad_transfer(apdev, test_params,
1726                     bad_scenario_ack_req_session_not_set_up, False)
1727
1728def test_fst_sta_ack_request_with_session_not_established_init_side(dev, apdev, test_params):
1729    """FST STA ack request with session not established init side"""
1730    fst_bad_transfer(apdev, test_params,
1731                     bad_scenario_ack_req_session_not_established_init_side,
1732                     False)
1733
1734def test_fst_sta_ack_request_with_session_not_established_resp_side(dev, apdev, test_params):
1735    """FST STA ack request with session not established resp side"""
1736    fst_bad_transfer(apdev, test_params,
1737                     bad_scenario_ack_req_session_not_established_resp_side,
1738                     False)
1739
1740def test_fst_sta_ack_request_with_bad_fsts_id(dev, apdev, test_params):
1741    """FST STA ack request with bad fsts id"""
1742    fst_bad_transfer(apdev, test_params, bad_scenario_ack_req_bad_fsts_id,
1743                     False)
1744
1745def test_fst_sta_ack_response_with_session_not_set_up(dev, apdev, test_params):
1746    """FST STA ack response with session not set up"""
1747    fst_bad_transfer(apdev, test_params,
1748                     bad_scenario_ack_resp_session_not_set_up, False)
1749
1750def test_fst_sta_ack_response_with_session_not_established_init_side(dev, apdev, test_params):
1751    """FST STA ack response with session not established init side"""
1752    fst_bad_transfer(apdev, test_params,
1753                     bad_scenario_ack_resp_session_not_established_init_side,
1754                     False)
1755
1756def test_fst_sta_ack_response_with_session_not_established_resp_side(dev, apdev, test_params):
1757    """FST STA ack response with session not established resp side"""
1758    fst_bad_transfer(apdev, test_params,
1759                     bad_scenario_ack_resp_session_not_established_resp_side,
1760                     False)
1761
1762def test_fst_sta_ack_response_with_no_ack_request(dev, apdev, test_params):
1763    """FST STA ack response with no ack request"""
1764    fst_bad_transfer(apdev, test_params, bad_scenario_ack_resp_no_ack_req,
1765                     False)
1766
1767def test_fst_sta_tear_down_session(dev, apdev, test_params):
1768    """FST STA tear down session"""
1769    fst_tear_down_session(apdev, test_params, bad_param_none, False)
1770
1771def test_fst_sta_tear_down_session_no_params(dev, apdev, test_params):
1772    """FST STA tear down session - no params"""
1773    fst_tear_down_session(apdev, test_params,
1774                          bad_param_session_teardown_no_params, False)
1775
1776def test_fst_sta_tear_down_session_bad_session_id(dev, apdev, test_params):
1777    """FST STA tear down session - bad session id"""
1778    fst_tear_down_session(apdev, test_params,
1779                          bad_param_session_teardown_bad_session_id, False)
1780
1781def test_fst_sta_tear_down_session_setup_skipped(dev, apdev, test_params):
1782    """FST STA tear down session - setup skipped"""
1783    fst_tear_down_session(apdev, test_params,
1784                          bad_param_session_teardown_setup_skipped, False)
1785
1786def test_fst_sta_tear_down_session_bad_fsts_id(dev, apdev, test_params):
1787    """FST STA tear down session - bad fsts id"""
1788    fst_tear_down_session(apdev, test_params,
1789                          bad_param_session_teardown_bad_fsts_id, False)
1790
1791def test_fst_sta_remove_session_not_established(dev, apdev, test_params):
1792    """FST STA tear down session - not established"""
1793    fst_remove_session(apdev, test_params,
1794                       remove_scenario_non_established_session, False)
1795
1796def test_fst_sta_remove_session_established(dev, apdev, test_params):
1797    """FST STA remove session - established"""
1798    fst_remove_session(apdev, test_params,
1799                       remove_scenario_established_session, False)
1800
1801def test_fst_sta_remove_session_no_params(dev, apdev, test_params):
1802    """FST STA remove session - no params"""
1803    fst_remove_session(apdev, test_params, remove_scenario_no_params, False)
1804
1805def test_fst_sta_remove_session_bad_session_id(dev, apdev, test_params):
1806    """FST STA remove session - bad session id"""
1807    fst_remove_session(apdev, test_params, remove_scenario_bad_session_id,
1808                       False)
1809
1810def test_fst_rsn_ap_transfer_session(dev, apdev, test_params):
1811    """FST RSN AP transfer session"""
1812    fst_transfer_session(apdev, test_params, bad_param_none, True, rsn=True)
1813
1814MGMT_SUBTYPE_ACTION = 13
1815ACTION_CATEG_FST = 18
1816FST_ACTION_SETUP_REQUEST = 0
1817FST_ACTION_SETUP_RESPONSE = 1
1818FST_ACTION_TEAR_DOWN = 2
1819FST_ACTION_ACK_REQUEST = 3
1820FST_ACTION_ACK_RESPONSE = 4
1821FST_ACTION_ON_CHANNEL_TUNNEL = 5
1822
1823def hostapd_tx_and_status(hapd, msg):
1824    hapd.set("ext_mgmt_frame_handling", "1")
1825    hapd.mgmt_tx(msg)
1826    ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=1)
1827    if ev is None or "ok=1" not in ev:
1828        raise Exception("No ACK")
1829    hapd.set("ext_mgmt_frame_handling", "0")
1830
1831def test_fst_proto(dev, apdev, test_params):
1832    """FST protocol testing"""
1833    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
1834    try:
1835        fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
1836        hapd = ap1.get_instance()
1837        sta = sta1.get_instance()
1838        dst = sta.own_addr()
1839        src = apdev[0]['bssid']
1840
1841        msg = {}
1842        msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1843        msg['da'] = dst
1844        msg['sa'] = src
1845        msg['bssid'] = src
1846
1847        # unknown FST Action (255) received!
1848        msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST, 255)
1849        hostapd_tx_and_status(hapd, msg)
1850
1851        # FST Request dropped: too short
1852        msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1853                                     FST_ACTION_SETUP_REQUEST)
1854        hostapd_tx_and_status(hapd, msg)
1855
1856        # FST Request dropped: invalid STIE (EID)
1857        msg['payload'] = struct.pack("<BBBLBBLBBBBBBB", ACTION_CATEG_FST,
1858                                     FST_ACTION_SETUP_REQUEST, 0, 0,
1859                                     163, 11, 0, 0, 0, 0, 0, 0, 0, 0)
1860        hostapd_tx_and_status(hapd, msg)
1861
1862        # FST Request dropped: invalid STIE (Len)
1863        msg['payload'] = struct.pack("<BBBLBBLBBBBBBB", ACTION_CATEG_FST,
1864                                     FST_ACTION_SETUP_REQUEST, 0, 0,
1865                                     164, 10, 0, 0, 0, 0, 0, 0, 0, 0)
1866        hostapd_tx_and_status(hapd, msg)
1867
1868        # FST Request dropped: new and old band IDs are the same
1869        msg['payload'] = struct.pack("<BBBLBBLBBBBBBB", ACTION_CATEG_FST,
1870                                     FST_ACTION_SETUP_REQUEST, 0, 0,
1871                                     164, 11, 0, 0, 0, 0, 0, 0, 0, 0)
1872        hostapd_tx_and_status(hapd, msg)
1873
1874        ifaces = sta1.list_ifaces()
1875        id = int(ifaces[0]['name'].split('|')[1])
1876        # FST Request dropped: new iface not found (new_band_id mismatch)
1877        msg['payload'] = struct.pack("<BBBLBBLBBBBBBB", ACTION_CATEG_FST,
1878                                     FST_ACTION_SETUP_REQUEST, 0, 0,
1879                                     164, 11, 0, 0, id + 1, 0, 0, 0, 0, 0)
1880        hostapd_tx_and_status(hapd, msg)
1881
1882        # FST Action 'Setup Response' dropped: no session in progress found
1883        msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1884                                     FST_ACTION_SETUP_RESPONSE)
1885        hostapd_tx_and_status(hapd, msg)
1886
1887        # Create session
1888        initiator = ap1
1889        responder = sta1
1890        new_iface = ap2.ifname()
1891        new_peer_addr = ap2.get_actual_peer_addr()
1892        resp_newif = sta2.ifname()
1893        peeraddr = None
1894        initiator.add_peer(responder, peeraddr, new_peer_addr)
1895        sid = initiator.add_session()
1896        initiator.configure_session(sid, new_iface)
1897        initiator.initiate_session(sid, "accept")
1898
1899        # FST Response dropped due to wrong state: SETUP_COMPLETION
1900        msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1901                                     FST_ACTION_SETUP_RESPONSE)
1902        hostapd_tx_and_status(hapd, msg)
1903
1904        # Too short FST Tear Down dropped
1905        msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1906                                     FST_ACTION_TEAR_DOWN)
1907        hostapd_tx_and_status(hapd, msg)
1908
1909        # tear down for wrong FST Setup ID (0)
1910        msg['payload'] = struct.pack("<BBL", ACTION_CATEG_FST,
1911                                     FST_ACTION_TEAR_DOWN, 0)
1912        hostapd_tx_and_status(hapd, msg)
1913
1914        # Ack received on wrong interface
1915        msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1916                                     FST_ACTION_ACK_REQUEST)
1917        hostapd_tx_and_status(hapd, msg)
1918
1919        # Ack Response in inappropriate session state (SETUP_COMPLETION)
1920        msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1921                                     FST_ACTION_ACK_RESPONSE)
1922        hostapd_tx_and_status(hapd, msg)
1923
1924        # Unsupported FST Action frame (On channel tunnel)
1925        msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1926                                     FST_ACTION_ON_CHANNEL_TUNNEL)
1927        hostapd_tx_and_status(hapd, msg)
1928
1929        # FST Request dropped: new iface not found (new_band_id match)
1930        # FST Request dropped due to MAC comparison
1931        msg['payload'] = struct.pack("<BBBLBBLBBBBBBB", ACTION_CATEG_FST,
1932                                     FST_ACTION_SETUP_REQUEST, 0, 0,
1933                                     164, 11, 0, 0, id, 0, 0, 0, 0, 0)
1934        hostapd_tx_and_status(hapd, msg)
1935
1936        hapd2 = ap2.get_instance()
1937        dst2 = sta2.get_instance().own_addr()
1938        src2 = apdev[1]['bssid']
1939
1940        msg2 = {}
1941        msg2['fc'] = MGMT_SUBTYPE_ACTION << 4
1942        msg2['da'] = dst2
1943        msg2['sa'] = src2
1944        msg2['bssid'] = src2
1945        # FST Response dropped: wlan6 is not the old iface
1946        msg2['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1947                                      FST_ACTION_SETUP_RESPONSE)
1948        hostapd_tx_and_status(hapd2, msg2)
1949
1950        sta.dump_monitor()
1951
1952        group = ap1.fst_group
1953        ap1.send_iface_detach_request(ap1.iface)
1954
1955        sta.flush_scan_cache()
1956        sta.request("REASSOCIATE")
1957        sta.wait_connected()
1958
1959        # FST Request dropped due to no interface connection
1960        msg['payload'] = struct.pack("<BBBLBBLBBBBBBB", ACTION_CATEG_FST,
1961                                     FST_ACTION_SETUP_REQUEST, 0, 0,
1962                                     164, 11, 0, 0, id, 0, 0, 0, 0, 0)
1963        hostapd_tx_and_status(hapd, msg)
1964    finally:
1965        fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
1966        try:
1967            fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
1968        except:
1969            pass
1970
1971def test_fst_setup_response_proto(dev, apdev, test_params):
1972    """FST protocol testing for Setup Response"""
1973    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
1974    try:
1975        fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
1976        hapd = ap1.get_instance()
1977        sta = sta1.get_instance()
1978        dst = sta.own_addr()
1979        src = apdev[0]['bssid']
1980
1981        sta1.add_peer(ap1, None, sta2.get_actual_peer_addr())
1982        sta1.set_fst_parameters(llt='0')
1983        sid = sta1.add_session()
1984        sta1.configure_session(sid, sta2.ifname())
1985        sta1.initiate_session(sid, "")
1986
1987        msg = {}
1988        msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1989        msg['da'] = dst
1990        msg['sa'] = src
1991        msg['bssid'] = src
1992
1993        # Too short FST Response dropped
1994        msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1995                                     FST_ACTION_SETUP_RESPONSE)
1996        hostapd_tx_and_status(hapd, msg)
1997
1998        # FST Response dropped: invalid STIE (EID)
1999        dialog_token = 1
2000        status_code = 0
2001        id = 0
2002        msg['payload'] = struct.pack("<BBBBBBLBBBBBBB", ACTION_CATEG_FST,
2003                                     FST_ACTION_SETUP_RESPONSE, dialog_token,
2004                                     status_code,
2005                                     163, 11, 0, 0, id, 0, 0, 0, 0, 0)
2006        hostapd_tx_and_status(hapd, msg)
2007
2008        # FST Response dropped: invalid STIE (Len)
2009        dialog_token = 1
2010        status_code = 0
2011        id = 0
2012        msg['payload'] = struct.pack("<BBBBBBLBBBBBBB", ACTION_CATEG_FST,
2013                                     FST_ACTION_SETUP_RESPONSE, dialog_token,
2014                                     status_code,
2015                                     164, 10, 0, 0, id, 0, 0, 0, 0, 0)
2016        hostapd_tx_and_status(hapd, msg)
2017
2018        # FST Response dropped due to wrong dialog token
2019        dialog_token = 123
2020        status_code = 0
2021        id = 0
2022        msg['payload'] = struct.pack("<BBBBBBLBBBBBBB", ACTION_CATEG_FST,
2023                                     FST_ACTION_SETUP_RESPONSE, dialog_token,
2024                                     status_code,
2025                                     164, 11, 0, 0, id, 0, 0, 0, 0, 0)
2026        hostapd_tx_and_status(hapd, msg)
2027
2028        # FST Response dropped due to wrong FST Session ID
2029        dialog_token = 1
2030        status_code = 0
2031        id = 1
2032        msg['payload'] = struct.pack("<BBBBBBLBBBBBBB", ACTION_CATEG_FST,
2033                                     FST_ACTION_SETUP_RESPONSE, dialog_token,
2034                                     status_code,
2035                                     164, 11, int(sid) + 123456,
2036                                     0, id, 0, 0, 0, 0, 0)
2037        hostapd_tx_and_status(hapd, msg)
2038
2039        # FST Response with non-zero status code
2040        dialog_token = 1
2041        status_code = 1
2042        id = 1
2043        msg['payload'] = struct.pack("<BBBBBBLBBBBBBB", ACTION_CATEG_FST,
2044                                     FST_ACTION_SETUP_RESPONSE, dialog_token,
2045                                     status_code,
2046                                     164, 11, int(sid), 0, id, 0, 0, 0, 0, 0)
2047        hostapd_tx_and_status(hapd, msg)
2048    finally:
2049        fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2050        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2051
2052def test_fst_ack_response_proto(dev, apdev, test_params):
2053    """FST protocol testing for Ack Response"""
2054    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
2055    try:
2056        fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2057        hapd = ap2.get_instance()
2058        sta = sta2.get_instance()
2059        dst = sta.own_addr()
2060        src = apdev[1]['bssid']
2061
2062        sta1.add_peer(ap1, None, sta2.get_actual_peer_addr())
2063        sta1.set_fst_parameters(llt='0')
2064        sid = sta1.add_session()
2065        sta1.configure_session(sid, sta2.ifname())
2066
2067        s = sta1.grequest("FST-MANAGER SESSION_INITIATE "+ sid)
2068        if not s.startswith('OK'):
2069            raise Exception("Cannot initiate fst session: %s" % s)
2070        ev = sta1.peer_obj.wait_gevent(["FST-EVENT-SESSION"], timeout=5)
2071        if ev is None:
2072            raise Exception("No FST-EVENT-SESSION received")
2073        event = fst_module_aux.parse_fst_session_event(ev)
2074        if event == None:
2075            raise Exception("Unrecognized FST event: " % ev)
2076        if event['type'] != 'EVENT_FST_SETUP':
2077            raise Exception("Expected FST_SETUP event, got: " + event['type'])
2078        ev = sta1.peer_obj.wait_gevent(["FST-EVENT-SESSION"], timeout=5)
2079        if ev is None:
2080            raise Exception("No FST-EVENT-SESSION received")
2081        event = fst_module_aux.parse_fst_session_event(ev)
2082        if event == None:
2083            raise Exception("Unrecognized FST event: " % ev)
2084        if event['type'] != 'EVENT_FST_SESSION_STATE':
2085            raise Exception("Expected EVENT_FST_SESSION_STATE event, got: " + event['type'])
2086        if event['new_state'] != "SETUP_COMPLETION":
2087            raise Exception("Expected new state SETUP_COMPLETION, got: " + event['new_state'])
2088
2089        hapd.set("ext_mgmt_frame_handling", "1")
2090        s = sta1.peer_obj.grequest("FST-MANAGER SESSION_RESPOND "+ event['id'] + " accept")
2091        if not s.startswith('OK'):
2092            raise Exception("Error session_respond: %s" % s)
2093        req = hapd.mgmt_rx()
2094        if req is None:
2095            raise Exception("No Ack Request seen")
2096        msg = {}
2097        msg['fc'] = MGMT_SUBTYPE_ACTION << 4
2098        msg['da'] = dst
2099        msg['sa'] = src
2100        msg['bssid'] = src
2101
2102        # Too short FST Ack Response dropped
2103        msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
2104                                     FST_ACTION_ACK_RESPONSE)
2105        hapd.mgmt_tx(msg)
2106        ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=1)
2107        if ev is None or "ok=1" not in ev:
2108            raise Exception("No ACK")
2109
2110        # Ack Response for wrong FSt Setup ID
2111        msg['payload'] = struct.pack("<BBBL", ACTION_CATEG_FST,
2112                                     FST_ACTION_ACK_RESPONSE,
2113                                     0, int(sid) + 123456)
2114        hostapd_tx_and_status(hapd, msg)
2115    finally:
2116        fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2117        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2118
2119def test_fst_ap_config_oom(dev, apdev, test_params):
2120    """FST AP configuration and OOM"""
2121    ap1 = fst_module_aux.FstAP(apdev[0]['ifname'], 'fst_11a', 'a',
2122                               fst_test_common.fst_test_def_chan_a,
2123                               fst_test_common.fst_test_def_group,
2124                               fst_test_common.fst_test_def_prio_low)
2125    hapd = ap1.start(return_early=True)
2126    with alloc_fail(hapd, 1, "fst_group_create"):
2127        res = ap1.grequest("FST-ATTACH %s %s" % (ap1.iface, ap1.fst_group))
2128        if not res.startswith("FAIL"):
2129            raise Exception("FST-ATTACH succeeded unexpectedly")
2130
2131    with alloc_fail(hapd, 1, "fst_iface_create"):
2132        res = ap1.grequest("FST-ATTACH %s %s" % (ap1.iface, ap1.fst_group))
2133        if not res.startswith("FAIL"):
2134            raise Exception("FST-ATTACH succeeded unexpectedly")
2135
2136    with alloc_fail(hapd, 1, "fst_group_create_mb_ie"):
2137        res = ap1.grequest("FST-ATTACH %s %s" % (ap1.iface, ap1.fst_group))
2138        # This is allowed to complete currently
2139
2140    ap1.stop()
2141    fst_test_common.fst_clear_regdom()
2142
2143def test_fst_send_oom(dev, apdev, test_params):
2144    """FST send action OOM"""
2145    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
2146    try:
2147        fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2148        hapd = ap1.get_instance()
2149        sta = sta1.get_instance()
2150        dst = sta.own_addr()
2151        src = apdev[0]['bssid']
2152
2153        # Create session
2154        initiator = ap1
2155        responder = sta1
2156        new_iface = ap2.ifname()
2157        new_peer_addr = ap2.get_actual_peer_addr()
2158        resp_newif = sta2.ifname()
2159        peeraddr = None
2160        initiator.add_peer(responder, peeraddr, new_peer_addr)
2161        sid = initiator.add_session()
2162        initiator.configure_session(sid, new_iface)
2163        with alloc_fail(hapd, 1, "fst_session_send_action"):
2164            res = initiator.grequest("FST-MANAGER SESSION_INITIATE " + sid)
2165            if not res.startswith("FAIL"):
2166                raise Exception("Unexpected SESSION_INITIATE result")
2167
2168        res = initiator.grequest("FST-MANAGER SESSION_INITIATE " + sid)
2169        if not res.startswith("OK"):
2170            raise Exception("SESSION_INITIATE failed")
2171
2172        tests = ["", "foo", sid, sid + " foo", sid + " foo=bar"]
2173        for t in tests:
2174            res = initiator.grequest("FST-MANAGER SESSION_SET " + t)
2175            if not res.startswith("FAIL"):
2176                raise Exception("Invalid SESSION_SET accepted")
2177
2178        with alloc_fail(hapd, 1, "fst_session_send_action"):
2179            res = initiator.grequest("FST-MANAGER SESSION_TEARDOWN " + sid)
2180            if not res.startswith("FAIL"):
2181                raise Exception("Unexpected SESSION_TEARDOWN result")
2182    finally:
2183        fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2184        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2185
2186def test_fst_session_oom(dev, apdev, test_params):
2187    """FST session create OOM"""
2188    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
2189    try:
2190        fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2191        hapd = ap1.get_instance()
2192        sta = sta1.get_instance()
2193        dst = sta.own_addr()
2194        src = apdev[0]['bssid']
2195
2196        # Create session
2197        initiator = ap1
2198        responder = sta1
2199        new_iface = ap2.ifname()
2200        new_peer_addr = ap2.get_actual_peer_addr()
2201        resp_newif = sta2.ifname()
2202        peeraddr = None
2203        initiator.add_peer(responder, peeraddr, new_peer_addr)
2204        with alloc_fail(hapd, 1, "fst_session_create"):
2205            sid = initiator.grequest("FST-MANAGER SESSION_ADD " + initiator.fst_group)
2206            if not sid.startswith("FAIL"):
2207                raise Exception("Unexpected SESSION_ADD success")
2208        sid = initiator.add_session()
2209        initiator.configure_session(sid, new_iface)
2210        with alloc_fail(sta, 1, "fst_session_create"):
2211            res = initiator.grequest("FST-MANAGER SESSION_INITIATE " + sid)
2212            if not res.startswith("OK"):
2213                raise Exception("Unexpected SESSION_INITIATE result")
2214    finally:
2215        fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2216        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2217
2218def test_fst_attach_zero_llt(dev, apdev):
2219    """FST attach with llt=0"""
2220    sta1 = fst_module_aux.FstSTA('wlan5', fst_test_common.fst_test_def_group,
2221                                 "100", "0")
2222    sta1.start()
2223    sta1.stop()
2224
2225def test_fst_session_respond_fail(dev, apdev, test_params):
2226    """FST-MANAGER SESSION_RESPOND failure"""
2227    ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
2228    try:
2229        fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2230        sta1.add_peer(ap1, None, sta2.get_actual_peer_addr())
2231        sid = sta1.add_session()
2232        sta1.configure_session(sid, sta2.ifname())
2233        sta1.send_session_setup_request(sid)
2234        sta1.wait_for_session_event(5, [], ["EVENT_FST_SESSION_STATE"])
2235        ev = ap1.wait_for_session_event(5, [], ['EVENT_FST_SETUP'])
2236        if 'id' not in ev:
2237            raise Exception("No session id in FST setup event")
2238        # Disconnect STA to make SESSION_RESPOND fail due to no peer found
2239        sta = sta1.get_instance()
2240        sta.request("DISCONNECT")
2241        sta.wait_disconnected()
2242        req = "FST-MANAGER SESSION_RESPOND %s reject" % ev['id']
2243        s = ap1.grequest(req)
2244        if not s.startswith("FAIL"):
2245            raise Exception("SESSION_RESPOND succeeded unexpectedly")
2246    finally:
2247        fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2248        fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2249
2250def fst_session_set(dev, sid, param, value):
2251    cmd = "FST-MANAGER SESSION_SET %s %s=%s" % (sid, param, value)
2252    if "OK" not in dev.global_request(cmd):
2253        raise Exception(cmd + " failed")
2254
2255def fst_session_set_ap(dev, sid, param, value):
2256    cmd = "FST-MANAGER SESSION_SET %s %s=%s" % (sid, param, value)
2257    if "OK" not in dev.request(cmd):
2258        raise Exception(cmd + " failed")
2259
2260def fst_attach_ap(dev, ifname, group):
2261    cmd = "FST-ATTACH %s %s" % (ifname, group)
2262    if "OK" not in dev.request(cmd):
2263        raise Exception("FST-ATTACH (AP) failed")
2264    ev = dev.wait_event(['FST-EVENT-IFACE'], timeout=5)
2265    if ev is None:
2266        raise Exception("No FST-EVENT-IFACE attached (AP)")
2267    for t in ["attached", "ifname=" + ifname, "group=" + group]:
2268        if t not in ev:
2269            raise Exception("Unexpected FST-EVENT-IFACE data (AP): " + ev)
2270
2271def fst_attach_sta(dev, ifname, group):
2272    if "OK" not in dev.global_request("FST-ATTACH %s %s" % (ifname, group)):
2273        raise Exception("FST-ATTACH (STA) failed")
2274    ev = dev.wait_global_event(['FST-EVENT-IFACE'], timeout=5)
2275    if ev is None:
2276        raise Exception("No FST-EVENT-IFACE attached (STA)")
2277    for t in ["attached", "ifname=" + ifname, "group=" + group]:
2278        if t not in ev:
2279            raise Exception("Unexpected FST-EVENT-IFACE data (STA): " + ev)
2280
2281def fst_detach_ap(dev, ifname, group):
2282    if "OK" not in dev.request("FST-DETACH " + ifname):
2283        raise Exception("FST-DETACH (AP) failed for " + ifname)
2284    ev = dev.wait_event(['FST-EVENT-IFACE'], timeout=5)
2285    if ev is None:
2286        raise Exception("No FST-EVENT-IFACE detached (AP) for " + ifname)
2287    for t in ["detached", "ifname=" + ifname, "group=" + group]:
2288        if t not in ev:
2289            raise Exception("Unexpected FST-EVENT-IFACE data (AP): " + ev)
2290
2291def fst_detach_sta(dev, ifname, group):
2292    dev.dump_monitor()
2293    if "OK" not in dev.global_request("FST-DETACH " + ifname):
2294        raise Exception("FST-DETACH (STA) failed for " + ifname)
2295    ev = dev.wait_global_event(['FST-EVENT-IFACE'], timeout=5)
2296    if ev is None:
2297        raise Exception("No FST-EVENT-IFACE detached (STA) for " + ifname)
2298    for t in ["detached", "ifname=" + ifname, "group=" + group]:
2299        if t not in ev:
2300            raise Exception("Unexpected FST-EVENT-IFACE data (STA): " + ev)
2301
2302def fst_wait_event_peer_ap(dev, event, ifname, addr):
2303    ev = dev.wait_event(['FST-EVENT-PEER'], timeout=5)
2304    if ev is None:
2305        raise Exception("No FST-EVENT-PEER connected (AP)")
2306    for t in [" " + event + " ", "ifname=" + ifname, "peer_addr=" + addr]:
2307        if t not in ev:
2308            raise Exception("Unexpected FST-EVENT-PEER data (AP): " + ev)
2309
2310def fst_wait_event_peer_sta(dev, event, ifname, addr):
2311    ev = dev.wait_global_event(['FST-EVENT-PEER'], timeout=5)
2312    if ev is None:
2313        raise Exception("No FST-EVENT-PEER connected (STA)")
2314    for t in [" " + event + " ", "ifname=" + ifname, "peer_addr=" + addr]:
2315        if t not in ev:
2316            raise Exception("Unexpected FST-EVENT-PEER data (STA): " + ev)
2317
2318def fst_setup_req(dev, hglobal, freq, dst, req, stie, mbie="", no_wait=False):
2319    act = req + stie + mbie
2320    dev.request("MGMT_TX %s %s freq=%d action=%s" % (dst, dst, freq, act))
2321    ev = dev.wait_event(['MGMT-TX-STATUS'], timeout=5)
2322    if ev is None or "result=SUCCESS" not in ev:
2323        raise Exception("FST Action frame not ACKed")
2324
2325    if no_wait:
2326        return
2327    while True:
2328        ev = hglobal.wait_event(['FST-EVENT-SESSION'], timeout=5)
2329        if ev is None:
2330            raise Exception("No FST-EVENT-SESSION (AP)")
2331        if "new_state=SETUP_COMPLETION" in ev:
2332            break
2333
2334def fst_start_and_connect(apdev, group, sgroup):
2335    hglobal = hostapd.HostapdGlobal()
2336    if "OK" not in hglobal.request("FST-MANAGER TEST_REQUEST IS_SUPPORTED"):
2337        raise HwsimSkip("No FST testing support")
2338
2339    params = {"ssid": "fst_11a", "hw_mode": "a", "channel": "36",
2340              "country_code": "US"}
2341    hapd = hostapd.add_ap(apdev[0], params)
2342
2343    fst_attach_ap(hglobal, apdev[0]['ifname'], group)
2344
2345    cmd = "FST-ATTACH %s %s" % (apdev[0]['ifname'], group)
2346    if "FAIL" not in hglobal.request(cmd):
2347        raise Exception("Duplicated FST-ATTACH (AP) accepted")
2348
2349    params = {"ssid": "fst_11g", "hw_mode": "g", "channel": "1",
2350              "country_code": "US"}
2351    hapd2 = hostapd.add_ap(apdev[1], params)
2352    fst_attach_ap(hglobal, apdev[1]['ifname'], group)
2353
2354    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
2355    wpas.interface_add("wlan5")
2356    fst_attach_sta(wpas, wpas.ifname, sgroup)
2357
2358    wpas.interface_add("wlan6", set_ifname=False)
2359    wpas2 = WpaSupplicant(ifname="wlan6")
2360    fst_attach_sta(wpas, wpas2.ifname, sgroup)
2361
2362    wpas.connect("fst_11a", key_mgmt="NONE", scan_freq="5180",
2363                 wait_connect=False)
2364    wpas.wait_connected()
2365
2366    fst_wait_event_peer_sta(wpas, "connected", wpas.ifname, apdev[0]['bssid'])
2367    fst_wait_event_peer_ap(hglobal, "connected", apdev[0]['ifname'],
2368                           wpas.own_addr())
2369
2370    wpas2.connect("fst_11g", key_mgmt="NONE", scan_freq="2412",
2371                  wait_connect=False)
2372    wpas2.wait_connected()
2373
2374    fst_wait_event_peer_sta(wpas, "connected", wpas2.ifname, apdev[1]['bssid'])
2375    fst_wait_event_peer_ap(hglobal, "connected", apdev[1]['ifname'],
2376                           wpas2.own_addr())
2377    return hglobal, wpas, wpas2, hapd, hapd2
2378
2379def test_fst_test_setup(dev, apdev, test_params):
2380    """FST setup using separate commands"""
2381    try:
2382        _test_fst_test_setup(dev, apdev, test_params)
2383    finally:
2384        subprocess.call(['iw', 'reg', 'set', '00'])
2385        dev[0].flush_scan_cache()
2386        dev[1].flush_scan_cache()
2387
2388def _test_fst_test_setup(dev, apdev, test_params):
2389    group = "fstg0b"
2390    sgroup = "fstg1b"
2391    hglobal, wpas, wpas2, hapd, hapd2 = fst_start_and_connect(apdev, group, sgroup)
2392
2393    sid = wpas.global_request("FST-MANAGER SESSION_ADD " + sgroup).strip()
2394    if "FAIL" in sid:
2395        raise Exception("FST-MANAGER SESSION_ADD (STA) failed")
2396
2397    fst_session_set(wpas, sid, "old_ifname", wpas.ifname)
2398    fst_session_set(wpas, sid, "old_peer_addr", apdev[0]['bssid'])
2399    fst_session_set(wpas, sid, "new_ifname", wpas2.ifname)
2400    fst_session_set(wpas, sid, "new_peer_addr", apdev[1]['bssid'])
2401
2402    if "OK" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid):
2403        raise Exception("FST-MANAGER SESSION_INITIATE failed")
2404
2405    while True:
2406        ev = hglobal.wait_event(['FST-EVENT-SESSION'], timeout=5)
2407        if ev is None:
2408            raise Exception("No FST-EVENT-SESSION (AP)")
2409        if "new_state=SETUP_COMPLETION" in ev:
2410            f = re.search("session_id=(\d+)", ev)
2411            if f is None:
2412                raise Exception("No session_id in FST-EVENT-SESSION")
2413            sid_ap = f.group(1)
2414            cmd = "FST-MANAGER SESSION_RESPOND %s accept" % sid_ap
2415            if "OK" not in hglobal.request(cmd):
2416                raise Exception("FST-MANAGER SESSION_RESPOND failed on AP")
2417            break
2418
2419    ev = wpas.wait_global_event(["FST-EVENT-SESSION"], timeout=5)
2420    if ev is None:
2421        raise Exception("No FST-EVENT-SESSION")
2422    if "new_state=SETUP_COMPLETION" not in ev:
2423        raise Exception("Unexpected FST-EVENT-SESSION data: " + ev)
2424
2425    ev = wpas.wait_global_event(["FST-EVENT-SESSION"], timeout=5)
2426    if ev is None:
2427        raise Exception("No FST-EVENT-SESSION")
2428    if "event_type=EVENT_FST_ESTABLISHED" not in ev:
2429        raise Exception("Unexpected FST-EVENT-SESSION data: " + ev)
2430
2431    cmd = "FST-MANAGER SESSION_REMOVE " + sid
2432    if "OK" not in wpas.global_request(cmd):
2433        raise Exception("FST-MANAGER SESSION_REMOVE failed")
2434    ev = wpas.wait_global_event(["FST-EVENT-SESSION"], timeout=5)
2435    if ev is None:
2436        raise Exception("No FST-EVENT-SESSION")
2437    if "new_state=INITIAL" not in ev:
2438        raise Exception("Unexpected FST-EVENT-SESSION data (STA): " + ev)
2439
2440    ev = hglobal.wait_event(['FST-EVENT-SESSION'], timeout=5)
2441    if ev is None:
2442        raise Exception("No FST-EVENT-SESSION (AP)")
2443    if "new_state=INITIAL" not in ev:
2444        raise Exception("Unexpected FST-EVENT-SESSION data (AP): " + ev)
2445
2446    if "FAIL" not in wpas.global_request(cmd):
2447        raise Exception("Duplicated FST-MANAGER SESSION_REMOVE accepted")
2448
2449    hglobal.request("FST-MANAGER SESSION_REMOVE " + sid_ap)
2450
2451    wpas.request("DISCONNECT")
2452    wpas.wait_disconnected()
2453    fst_wait_event_peer_sta(wpas, "disconnected", wpas.ifname,
2454                            apdev[0]['bssid'])
2455    fst_wait_event_peer_ap(hglobal, "disconnected", apdev[0]['ifname'],
2456                           wpas.own_addr())
2457
2458    wpas2.request("DISCONNECT")
2459    wpas2.wait_disconnected()
2460    fst_wait_event_peer_sta(wpas, "disconnected", wpas2.ifname,
2461                            apdev[1]['bssid'])
2462    fst_wait_event_peer_ap(hglobal, "disconnected", apdev[1]['ifname'],
2463                           wpas2.own_addr())
2464
2465    fst_detach_ap(hglobal, apdev[0]['ifname'], group)
2466    if "FAIL" not in hglobal.request("FST-DETACH " + apdev[0]['ifname']):
2467        raise Exception("Duplicated FST-DETACH (AP) accepted")
2468    hapd.disable()
2469
2470    fst_detach_ap(hglobal, apdev[1]['ifname'], group)
2471    hapd2.disable()
2472
2473    fst_detach_sta(wpas, wpas.ifname, sgroup)
2474    fst_detach_sta(wpas, wpas2.ifname, sgroup)
2475
2476def test_fst_setup_mbie_diff(dev, apdev, test_params):
2477    """FST setup and different MBIE in FST Setup Request"""
2478    try:
2479        _test_fst_setup_mbie_diff(dev, apdev, test_params)
2480    finally:
2481        subprocess.call(['iw', 'reg', 'set', '00'])
2482        dev[0].flush_scan_cache()
2483        dev[1].flush_scan_cache()
2484
2485def _test_fst_setup_mbie_diff(dev, apdev, test_params):
2486    group = "fstg0c"
2487    sgroup = "fstg1c"
2488    hglobal, wpas, wpas2, hapd, hapd2 = fst_start_and_connect(apdev, group, sgroup)
2489
2490    # FST Setup Request: Category, FST Action, Dialog Token (non-zero),
2491    # LLT (32 bits, see 10.32), Session Transition (see 8.4.2.147),
2492    # Multi-band element (optional, see 8.4.2.140)
2493
2494    # Session Transition: EID, Len, FSTS ID(4), Session Control,
2495    # New Band (Band ID, Setup, Operation), Old Band (Band ID, Setup, Operation)
2496
2497    # Multi-band element: EID, Len, Multi-band Control, Band ID,
2498    # Operating Class, Channel Number, BSSID (6), Beacon Interval (2),
2499    # TSF Offset (8), Multi-band Connection Capability, FSTSessionTimeOut,
2500    # STA MAC Address (6, optional), Pairwise Cipher Suite Count (2, optional),
2501    # Pairwise Cipher Suite List (4xm, optional)
2502
2503    # MBIE with the non-matching STA MAC Address:
2504    req = "1200011a060000"
2505    stie = "a40b0100000000020001040001"
2506    mbie = "9e1c0c0200010200000004000000000000000000000000ff0200000006ff"
2507    fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie, mbie)
2508
2509    # MBIE without the STA MAC Address:
2510    req = "1200011a060000"
2511    stie = "a40b0100000000020001040001"
2512    mbie = "9e16040200010200000004000000000000000000000000ff"
2513    fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie, mbie)
2514
2515    # MBIE with unsupported STA Role:
2516    req = "1200011a060000"
2517    stie = "a40b0100000000020001040001"
2518    mbie = "9e16070200010200000004000000000000000000000000ff"
2519    fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie, mbie)
2520
2521    # MBIE with unsupported Band ID:
2522    req = "1200011a060000"
2523    stie = "a40b0100000000020001040001"
2524    mbie = "9e1604ff00010200000004000000000000000000000000ff"
2525    fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie, mbie)
2526
2527    # FST Setup Request without MBIE (different FSTS ID):
2528    req = "1200011a060000"
2529    stie = "a40b0200000000020001040001"
2530    fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie)
2531
2532    # MBIE update OOM on AP
2533    req = "1200011a060000"
2534    stie = "a40b0100000000020001040001"
2535    mbie = "9e16040200010200000004000000000000000000000000ff"
2536    try:
2537        with alloc_fail(hapd, 1, "mb_ies_by_info"):
2538            fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie,
2539                          mbie, no_wait=True)
2540    except HwsimSkip as e:
2541        # Skip exception to allow proper cleanup
2542        pass
2543
2544    # Remove sessions to avoid causing issues to following test ases
2545    s = hglobal.request("FST-MANAGER LIST_SESSIONS " + group)
2546    if not s.startswith("FAIL"):
2547        for sid in s.split(' '):
2548            if len(sid):
2549                hglobal.request("FST-MANAGER SESSION_REMOVE " + sid)
2550
2551def test_fst_many_setup(dev, apdev, test_params):
2552    """FST setup multiple times"""
2553    try:
2554        _test_fst_many_setup(dev, apdev, test_params)
2555    finally:
2556        subprocess.call(['iw', 'reg', 'set', '00'])
2557        dev[0].flush_scan_cache()
2558        dev[1].flush_scan_cache()
2559
2560def _test_fst_many_setup(dev, apdev, test_params):
2561    group = "fstg0d"
2562    sgroup = "fstg1d"
2563    hglobal, wpas, wpas2, hapd, hapd2 = fst_start_and_connect(apdev, group, sgroup)
2564
2565    sid = wpas.global_request("FST-MANAGER SESSION_ADD " + sgroup).strip()
2566    if "FAIL" in sid:
2567        raise Exception("FST-MANAGER SESSION_ADD (STA) failed")
2568
2569    fst_session_set(wpas, sid, "old_ifname", wpas.ifname)
2570    fst_session_set(wpas, sid, "old_peer_addr", apdev[0]['bssid'])
2571    fst_session_set(wpas, sid, "new_ifname", wpas2.ifname)
2572    fst_session_set(wpas, sid, "new_peer_addr", apdev[1]['bssid'])
2573
2574    for i in range(257):
2575        if "OK" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid):
2576            raise Exception("FST-MANAGER SESSION_INITIATE failed")
2577
2578        while True:
2579            ev = hglobal.wait_event(['FST-EVENT-SESSION'], timeout=5)
2580            if ev is None:
2581                raise Exception("No FST-EVENT-SESSION (AP)")
2582            if "new_state=SETUP_COMPLETION" in ev:
2583                f = re.search("session_id=(\d+)", ev)
2584                if f is None:
2585                    raise Exception("No session_id in FST-EVENT-SESSION")
2586                sid_ap = f.group(1)
2587                cmd = "FST-MANAGER SESSION_RESPOND %s accept" % sid_ap
2588                if "OK" not in hglobal.request(cmd):
2589                    raise Exception("FST-MANAGER SESSION_RESPOND failed on AP")
2590                break
2591
2592        ev = wpas.wait_global_event(["FST-EVENT-SESSION"], timeout=5)
2593        if ev is None:
2594            raise Exception("No FST-EVENT-SESSION (STA)")
2595        if "new_state=SETUP_COMPLETION" not in ev:
2596            raise Exception("Unexpected FST-EVENT-SESSION data: " + ev)
2597
2598        ev = wpas.wait_global_event(["FST-EVENT-SESSION"], timeout=5)
2599        if ev is None:
2600            raise Exception("No FST-EVENT-SESSION (STA)")
2601        if "event_type=EVENT_FST_ESTABLISHED" not in ev:
2602            raise Exception("Unexpected FST-EVENT-SESSION data: " + ev)
2603
2604        if "OK" not in wpas.global_request("FST-MANAGER SESSION_TEARDOWN " + sid):
2605            raise Exception("FST-MANAGER SESSION_INITIATE failed")
2606
2607        if i == 0:
2608            if "FAIL" not in wpas.global_request("FST-MANAGER SESSION_TEARDOWN " + sid):
2609                raise Exception("Duplicate FST-MANAGER SESSION_TEARDOWN accepted")
2610
2611        ev = wpas.wait_global_event(["FST-EVENT-SESSION"], timeout=5)
2612        if ev is None:
2613            raise Exception("No FST-EVENT-SESSION (STA teardown -->initial)")
2614        if "new_state=INITIAL" not in ev:
2615            raise Exception("Unexpected FST-EVENT-SESSION data (STA): " + ev)
2616
2617        ev = hglobal.wait_event(['FST-EVENT-SESSION'], timeout=5)
2618        if ev is None:
2619            raise Exception("No FST-EVENT-SESSION (AP teardown -->initial)")
2620        if "new_state=INITIAL" not in ev:
2621            raise Exception("Unexpected FST-EVENT-SESSION data (AP): " + ev)
2622
2623        if "OK" not in hglobal.request("FST-MANAGER SESSION_REMOVE " + sid_ap):
2624            raise Exception("FST-MANAGER SESSION_REMOVE (AP) failed")
2625
2626    if "OK" not in wpas.global_request("FST-MANAGER SESSION_REMOVE " + sid):
2627        raise Exception("FST-MANAGER SESSION_REMOVE failed")
2628
2629    wpas.request("DISCONNECT")
2630    wpas.wait_disconnected()
2631    fst_wait_event_peer_sta(wpas, "disconnected", wpas.ifname,
2632                            apdev[0]['bssid'])
2633    fst_wait_event_peer_ap(hglobal, "disconnected", apdev[0]['ifname'],
2634                           wpas.own_addr())
2635
2636    wpas2.request("DISCONNECT")
2637    wpas2.wait_disconnected()
2638    fst_wait_event_peer_sta(wpas, "disconnected", wpas2.ifname,
2639                            apdev[1]['bssid'])
2640    fst_wait_event_peer_ap(hglobal, "disconnected", apdev[1]['ifname'],
2641                           wpas2.own_addr())
2642
2643    fst_detach_ap(hglobal, apdev[0]['ifname'], group)
2644    fst_detach_ap(hglobal, apdev[1]['ifname'], group)
2645    hapd.disable()
2646    hapd2.disable()
2647
2648    fst_detach_sta(wpas, wpas.ifname, sgroup)
2649    fst_detach_sta(wpas, wpas2.ifname, sgroup)
2650
2651def test_fst_attach_wpas_error(dev, apdev, test_params):
2652    """FST attach errors in wpa_supplicant"""
2653    if "OK" not in dev[0].global_request("FST-MANAGER TEST_REQUEST IS_SUPPORTED"):
2654        raise HwsimSkip("No FST testing support")
2655    group = "fstg0"
2656    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
2657    wpas.interface_add("wlan5")
2658    fst_attach_sta(wpas, wpas.ifname, group)
2659    if "FAIL" not in wpas.global_request("FST-ATTACH %s %s" % (wpas.ifname,
2660                                                               group)):
2661        raise Exception("Duplicated FST-ATTACH accepted")
2662    if "FAIL" not in wpas.global_request("FST-ATTACH %s %s" % ("foofoo",
2663                                                               group)):
2664        raise Exception("FST-ATTACH for unknown interface accepted")
2665
2666def test_fst_session_initiate_errors(dev, apdev, test_params):
2667    """FST SESSION_INITIATE error cases"""
2668    try:
2669        _test_fst_session_initiate_errors(dev, apdev, test_params)
2670    finally:
2671        subprocess.call(['iw', 'reg', 'set', '00'])
2672        dev[0].flush_scan_cache()
2673        dev[1].flush_scan_cache()
2674
2675def _test_fst_session_initiate_errors(dev, apdev, test_params):
2676    group = "fstg0"
2677    sgroup = "fstg1"
2678    hglobal, wpas, wpas2, hapd, hapd2 = fst_start_and_connect(apdev, group, sgroup)
2679
2680    sid = wpas.global_request("FST-MANAGER SESSION_ADD " + sgroup).strip()
2681    if "FAIL" in sid:
2682        raise Exception("FST-MANAGER SESSION_ADD (STA) failed")
2683
2684    # No old peer MAC address
2685    if "FAIL" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid):
2686        raise Exception("Invalid FST-MANAGER SESSION_INITIATE accepted")
2687
2688    fst_session_set(wpas, sid, "old_peer_addr", "00:ff:ff:ff:ff:ff")
2689    # No new peer MAC address
2690    if "FAIL" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid):
2691        raise Exception("Invalid FST-MANAGER SESSION_INITIATE accepted")
2692
2693    fst_session_set(wpas, sid, "new_peer_addr", "00:ff:ff:ff:ff:fe")
2694    # No old interface defined
2695    if "FAIL" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid):
2696        raise Exception("Invalid FST-MANAGER SESSION_INITIATE accepted")
2697
2698    fst_session_set(wpas, sid, "old_ifname", wpas.ifname)
2699    # No new interface defined
2700    if "FAIL" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid):
2701        raise Exception("Invalid FST-MANAGER SESSION_INITIATE accepted")
2702
2703    fst_session_set(wpas, sid, "new_ifname", wpas.ifname)
2704    # Same interface set as old and new
2705    if "FAIL" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid):
2706        raise Exception("Invalid FST-MANAGER SESSION_INITIATE accepted")
2707
2708    fst_session_set(wpas, sid, "new_ifname", wpas2.ifname)
2709    # The preset old peer address is not connected
2710    if "FAIL" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid):
2711        raise Exception("Invalid FST-MANAGER SESSION_INITIATE accepted")
2712
2713    fst_session_set(wpas, sid, "old_peer_addr", apdev[0]['bssid'])
2714    # The preset new peer address is not connected
2715    if "FAIL" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid):
2716        raise Exception("Invalid FST-MANAGER SESSION_INITIATE accepted")
2717
2718    fst_session_set(wpas, sid, "new_peer_addr", apdev[1]['bssid'])
2719    # Initiate session setup
2720    if "OK" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid):
2721        raise Exception("FST-MANAGER SESSION_INITIATE failed")
2722
2723    # Session in progress
2724    if "FAIL" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid):
2725        raise Exception("Duplicated FST-MANAGER SESSION_INITIATE accepted")
2726
2727    sid2 = wpas.global_request("FST-MANAGER SESSION_ADD " + sgroup).strip()
2728    if "FAIL" in sid:
2729        raise Exception("FST-MANAGER SESSION_ADD (STA) failed")
2730    fst_session_set(wpas, sid2, "old_ifname", wpas.ifname)
2731    fst_session_set(wpas, sid2, "old_peer_addr", apdev[0]['bssid'])
2732    fst_session_set(wpas, sid2, "new_ifname", wpas2.ifname)
2733    fst_session_set(wpas, sid2, "new_peer_addr", apdev[1]['bssid'])
2734
2735    # There is another session in progress (old)
2736    if "FAIL" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid2):
2737        raise Exception("Duplicated FST-MANAGER SESSION_INITIATE accepted")
2738
2739    if "OK" not in wpas.global_request("FST-MANAGER SESSION_REMOVE " + sid):
2740        raise Exception("FST-MANAGER SESSION_REMOVE failed")
2741
2742    while True:
2743        ev = hglobal.wait_event(['FST-EVENT-SESSION'], timeout=5)
2744        if ev is None:
2745            raise Exception("No FST-EVENT-SESSION (AP)")
2746        if "new_state=SETUP_COMPLETION" in ev:
2747            f = re.search("session_id=(\d+)", ev)
2748            if f is None:
2749                raise Exception("No session_id in FST-EVENT-SESSION")
2750            sid_ap = f.group(1)
2751            break
2752    if "OK" not in hglobal.request("FST-MANAGER SESSION_REMOVE " + sid_ap):
2753        raise Exception("FST-MANAGER SESSION_REMOVE (AP) failed")
2754
2755    if "OK" not in wpas.global_request("FST-MANAGER SESSION_REMOVE " + sid2):
2756        raise Exception("FST-MANAGER SESSION_REMOVE failed")
2757
2758def test_fst_session_respond_errors(dev, apdev, test_params):
2759    """FST SESSION_RESPOND error cases"""
2760    try:
2761        _test_fst_session_respond_errors(dev, apdev, test_params)
2762    finally:
2763        subprocess.call(['iw', 'reg', 'set', '00'])
2764        dev[0].flush_scan_cache()
2765        dev[1].flush_scan_cache()
2766
2767def _test_fst_session_respond_errors(dev, apdev, test_params):
2768    group = "fstg0b"
2769    sgroup = "fstg1b"
2770    hglobal, wpas, wpas2, hapd, hapd2 = fst_start_and_connect(apdev, group, sgroup)
2771
2772    sid = wpas.global_request("FST-MANAGER SESSION_ADD " + sgroup).strip()
2773    if "FAIL" in sid:
2774        raise Exception("FST-MANAGER SESSION_ADD (STA) failed")
2775
2776    fst_session_set(wpas, sid, "old_ifname", wpas.ifname)
2777    fst_session_set(wpas, sid, "old_peer_addr", apdev[0]['bssid'])
2778    fst_session_set(wpas, sid, "new_ifname", wpas2.ifname)
2779    fst_session_set(wpas, sid, "new_peer_addr", apdev[1]['bssid'])
2780
2781    if "OK" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid):
2782        raise Exception("FST-MANAGER SESSION_INITIATE failed")
2783
2784    while True:
2785        ev = hglobal.wait_event(['FST-EVENT-SESSION'], timeout=5)
2786        if ev is None:
2787            raise Exception("No FST-EVENT-SESSION (AP)")
2788        if "new_state=SETUP_COMPLETION" in ev:
2789            f = re.search("session_id=(\d+)", ev)
2790            if f is None:
2791                raise Exception("No session_id in FST-EVENT-SESSION")
2792            sid_ap = f.group(1)
2793            break
2794
2795    # The preset peer address is not in the peer list
2796    fst_session_set_ap(hglobal, sid_ap, "old_peer_addr", "00:00:00:00:00:01")
2797    cmd = "FST-MANAGER SESSION_RESPOND %s accept" % sid_ap
2798    if "FAIL" not in hglobal.request(cmd):
2799        raise Exception("Invalid FST-MANAGER SESSION_RESPOND accepted")
2800
2801    # Same interface set as old and new
2802    fst_session_set_ap(hglobal, sid_ap, "old_peer_addr", wpas.own_addr())
2803    fst_session_set_ap(hglobal, sid_ap, "old_ifname", apdev[1]['ifname'])
2804    cmd = "FST-MANAGER SESSION_RESPOND %s accept" % sid_ap
2805    if "FAIL" not in hglobal.request(cmd):
2806        raise Exception("Invalid FST-MANAGER SESSION_RESPOND accepted")
2807
2808    # valid command
2809    fst_session_set_ap(hglobal, sid_ap, "old_ifname", apdev[0]['ifname'])
2810    cmd = "FST-MANAGER SESSION_RESPOND %s accept" % sid_ap
2811    if "OK" not in hglobal.request(cmd):
2812        raise Exception("FST-MANAGER SESSION_RESPOND failed")
2813
2814    # incorrect state
2815    cmd = "FST-MANAGER SESSION_RESPOND %s accept" % sid_ap
2816    if "FAIL" not in hglobal.request(cmd):
2817        raise Exception("Invalid FST-MANAGER SESSION_RESPOND accepted")
2818
2819    cmd = "FST-MANAGER SESSION_REMOVE " + sid
2820    if "OK" not in wpas.global_request(cmd):
2821        raise Exception("FST-MANAGER SESSION_REMOVE (STA) failed")
2822
2823    cmd = "FST-MANAGER SESSION_REMOVE %s" % sid_ap
2824    if "OK" not in hglobal.request(cmd):
2825        raise Exception("FST-MANAGER SESSION_REMOVE (AP) failed")
2826