tests: Additional FST Setup test coverage
[mech_eap.git] / tests / hwsim / test_fst_module.py
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
7 import logging
8 logger = logging.getLogger()
9 import struct
10 import subprocess
11 import time
12 import os
13 import re
14
15 import hwsim_utils
16 from hwsim import HWSimRadio
17 import hostapd
18 from wpasupplicant import WpaSupplicant
19 import fst_test_common
20 import fst_module_aux
21 from utils import alloc_fail, HwsimSkip
22
23 #enum - bad parameter types
24 bad_param_none = 0
25 bad_param_session_add_no_params = 1
26 bad_param_group_id = 2
27 bad_param_session_set_no_params = 3
28 bad_param_session_set_unknown_param = 4
29 bad_param_session_id = 5
30 bad_param_old_iface = 6
31 bad_param_new_iface = 7
32 bad_param_negative_llt = 8
33 bad_param_zero_llt = 9
34 bad_param_llt_too_big = 10
35 bad_param_llt_nan = 11
36 bad_param_peer_addr = 12
37 bad_param_session_initiate_no_params = 13
38 bad_param_session_initiate_bad_session_id = 14
39 bad_param_session_initiate_with_no_new_iface_set = 15
40 bad_param_session_initiate_with_bad_peer_addr_set = 16
41 bad_param_session_initiate_request_with_bad_stie = 17
42 bad_param_session_initiate_response_with_reject = 18
43 bad_param_session_initiate_response_with_bad_stie = 19
44 bad_param_session_initiate_response_with_zero_llt = 20
45 bad_param_session_initiate_stt_no_response = 21
46 bad_param_session_initiate_concurrent_setup_request = 22
47 bad_param_session_transfer_no_params = 23
48 bad_param_session_transfer_bad_session_id = 24
49 bad_param_session_transfer_setup_skipped = 25
50 bad_param_session_teardown_no_params = 26
51 bad_param_session_teardown_bad_session_id = 27
52 bad_param_session_teardown_setup_skipped = 28
53 bad_param_session_teardown_bad_fsts_id = 29
54
55 bad_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
86 def 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, 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             print "Failure. Unexpected exception"
192
193 def 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 not 'id' 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, 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             print "Failure. Unexpected exception"
330
331 def 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, 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             print "Failure. Unexpected exception"
389
390
391 def 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, 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             print "Failure. Unexpected exception"
457
458
459 #enum - remove session scenarios
460 remove_scenario_no_params = 0
461 remove_scenario_bad_session_id = 1
462 remove_scenario_non_established_session = 2
463 remove_scenario_established_session = 3
464
465 remove_scenario_names = ("No params",
466                          "Bad session id",
467                          "Remove non-established session",
468                          "Remove established session")
469
470
471 def 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, 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             print "Failure. Unexpected exception"
532
533
534 #enum - frame types
535 frame_type_session_request = 0
536 frame_type_session_response = 1
537 frame_type_ack_request = 2
538 frame_type_ack_response = 3
539 frame_type_tear_down = 4
540
541 frame_type_names = ("Session request",
542                     "Session Response",
543                     "Ack request",
544                     "Ack response",
545                     "Tear down")
546
547 def 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, 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             print "Failure. Unexpected exception"
616
617
618 #enum - bad session transfer scenarios
619 bad_scenario_none = 0
620 bad_scenario_ack_req_session_not_set_up = 1
621 bad_scenario_ack_req_session_not_established_init_side = 2
622 bad_scenario_ack_req_session_not_established_resp_side = 3
623 bad_scenario_ack_req_bad_fsts_id = 4
624 bad_scenario_ack_resp_session_not_set_up = 5
625 bad_scenario_ack_resp_session_not_established_init_side = 6
626 bad_scenario_ack_resp_session_not_established_resp_side = 7
627 bad_scenario_ack_resp_no_ack_req = 8
628 bad_scenario_ack_resp_bad_fsts_id = 9
629
630 bad_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
641 def 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, 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             print "Failure. Unexpected exception"
737
738 def 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             vals = sta2.scan()
747             freq = vals['freq']
748             sta2.connect_to_external_ap(non_fst_ap, ssid="non_fst_11g",
749                                         key_mgmt="NONE", scan_freq=freq)
750             time.sleep(2)
751             res_sta1_mbies = sta1.get_local_mbies()
752             res_sta2_mbies = sta2.get_local_mbies()
753             if (orig_sta1_mbies.startswith("FAIL") or
754                 orig_sta2_mbies.startswith("FAIL") or
755                 not res_sta1_mbies.startswith("FAIL") or
756                 not res_sta2_mbies.startswith("FAIL")):
757                 raise Exception("Failure. MB IEs have not been removed on the stations")
758         except Exception, e:
759             logger.info(e)
760             raise
761         finally:
762             sta2.disconnect_from_external_ap()
763             fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
764
765 def test_fst_sta_connect_to_fst_ap(dev, apdev, test_params):
766     """FST STA connecting to FST AP"""
767     ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
768     try:
769         orig_sta2_mbies = sta2.get_local_mbies()
770         vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
771         sta1.connect(ap1, key_mgmt="NONE",
772                      scan_freq=fst_test_common.fst_test_def_freq_a)
773         time.sleep(2)
774         res_sta2_mbies = sta2.get_local_mbies()
775         if res_sta2_mbies == orig_sta2_mbies:
776             raise Exception("Failure. MB IEs have not been updated")
777     except Exception, e:
778         logger.info(e)
779         raise
780     finally:
781         sta1.disconnect()
782         fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
783
784 def test_fst_ap_connect_to_fst_sta(dev, apdev, test_params):
785     """FST AP connecting to FST STA"""
786     ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
787     try:
788         orig_ap_mbies = ap1.get_local_mbies()
789         vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
790         sta1.connect(ap1, key_mgmt="NONE",
791                      scan_freq=fst_test_common.fst_test_def_freq_a)
792         time.sleep(2)
793         res_ap_mbies = ap1.get_local_mbies()
794         if res_ap_mbies != orig_ap_mbies:
795             raise Exception("Failure. MB IEs have been unexpectedly updated on the AP")
796     except Exception, e:
797         logger.info(e)
798         raise
799     finally:
800         sta1.disconnect()
801         fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
802
803 def test_fst_ap_connect_to_non_fst_sta(dev, apdev, test_params):
804     """FST AP connecting to non-FST STA"""
805     ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
806     try:
807         orig_ap_mbies = ap2.get_local_mbies()
808         vals = dev[0].scan(None, fst_test_common.fst_test_def_freq_g)
809         fst_module_aux.external_sta_connect(dev[0], ap2, key_mgmt="NONE",
810                                             scan_freq=fst_test_common.fst_test_def_freq_g)
811         time.sleep(2)
812         res_ap_mbies = ap2.get_local_mbies()
813         if res_ap_mbies != orig_ap_mbies:
814             raise Exception("Failure. MB IEs have been unexpectedly updated on the AP")
815     except Exception, e:
816         logger.info(e)
817         raise
818     finally:
819         fst_module_aux.disconnect_external_sta(dev[0], ap2)
820         fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
821
822 def test_fst_second_sta_connect_to_non_fst_ap(dev, apdev, test_params):
823     """FST STA 2nd connecting to non-FST AP"""
824     fst_ap1, fst_ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
825     with HWSimRadio() as (radio, iface):
826         non_fst_ap = hostapd.add_ap(iface, { "ssid": "non_fst_11g" })
827         try:
828             vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
829             sta1.connect(fst_ap1, key_mgmt="NONE", scan_freq=fst_test_common.fst_test_def_freq_a)
830             time.sleep(2)
831             orig_sta1_mbies = sta1.get_local_mbies()
832             orig_sta2_mbies = sta2.get_local_mbies()
833             vals = sta2.scan()
834             freq = vals['freq']
835             sta2.connect_to_external_ap(non_fst_ap, ssid="non_fst_11g", key_mgmt="NONE", scan_freq=freq)
836             time.sleep(2)
837             res_sta1_mbies = sta1.get_local_mbies()
838             res_sta2_mbies = sta2.get_local_mbies()
839             if (orig_sta1_mbies.startswith("FAIL") or
840                 orig_sta2_mbies.startswith("FAIL") or
841                 not res_sta1_mbies.startswith("FAIL") or
842                 not res_sta2_mbies.startswith("FAIL")):
843                 raise Exception("Failure. MB IEs have not been removed on the stations")
844         except Exception, e:
845             logger.info(e)
846             raise
847         finally:
848             sta1.disconnect()
849             sta2.disconnect_from_external_ap()
850             fst_module_aux.stop_two_ap_sta_pairs(fst_ap1, fst_ap2, sta1, sta2)
851
852
853 def test_fst_second_sta_connect_to_fst_ap(dev, apdev, test_params):
854     """FST STA 2nd connecting to FST AP"""
855     fst_ap1, fst_ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
856     with HWSimRadio() as (radio, iface):
857         non_fst_ap = hostapd.add_ap(iface, { "ssid": "non_fst_11g" })
858         try:
859             vals = sta2.scan()
860             freq = vals['freq']
861             sta2.connect_to_external_ap(non_fst_ap, ssid="non_fst_11g", key_mgmt="NONE", scan_freq=freq)
862             time.sleep(2)
863             orig_sta1_mbies = sta1.get_local_mbies()
864             orig_sta2_mbies = sta2.get_local_mbies()
865             vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
866             sta1.connect(fst_ap1, key_mgmt="NONE", scan_freq=fst_test_common.fst_test_def_freq_a)
867             time.sleep(2)
868             res_sta1_mbies = sta1.get_local_mbies()
869             res_sta2_mbies = sta2.get_local_mbies()
870             if (not orig_sta1_mbies.startswith("FAIL") or
871                 not orig_sta2_mbies.startswith("FAIL") or
872                 not res_sta1_mbies.startswith("FAIL") or
873                 not res_sta2_mbies.startswith("FAIL")):
874                 raise Exception("Failure. MB IEs should have stayed non-present on the stations")
875         except Exception, e:
876             logger.info(e)
877             raise
878         finally:
879             sta1.disconnect()
880             sta2.disconnect_from_external_ap()
881             fst_module_aux.stop_two_ap_sta_pairs(fst_ap1, fst_ap2, sta1, sta2)
882
883 def test_fst_disconnect_1_of_2_stas_from_non_fst_ap(dev, apdev, test_params):
884     """FST disconnect 1 of 2 STAs from non-FST AP"""
885     fst_ap1, fst_ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
886     with HWSimRadio() as (radio, iface):
887         non_fst_ap = hostapd.add_ap(iface, { "ssid": "non_fst_11g" })
888         try:
889             vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
890             sta1.connect(fst_ap1, key_mgmt="NONE", scan_freq=fst_test_common.fst_test_def_freq_a)
891             vals = sta2.scan()
892             freq = vals['freq']
893             sta2.connect_to_external_ap(non_fst_ap, ssid="non_fst_11g", key_mgmt="NONE", scan_freq=freq)
894             time.sleep(2)
895             orig_sta1_mbies = sta1.get_local_mbies()
896             orig_sta2_mbies = sta2.get_local_mbies()
897             sta2.disconnect_from_external_ap()
898             time.sleep(2)
899             res_sta1_mbies = sta1.get_local_mbies()
900             res_sta2_mbies = sta2.get_local_mbies()
901             if (not orig_sta1_mbies.startswith("FAIL") or
902                 not orig_sta2_mbies.startswith("FAIL") or
903                 res_sta1_mbies.startswith("FAIL") or
904                 res_sta2_mbies.startswith("FAIL")):
905                 raise Exception("Failure. MB IEs haven't reappeared on the stations")
906         except Exception, e:
907             logger.info(e)
908             raise
909         finally:
910             sta1.disconnect()
911             sta2.disconnect_from_external_ap()
912             fst_module_aux.stop_two_ap_sta_pairs(fst_ap1, fst_ap2, sta1, sta2)
913
914
915 def test_fst_disconnect_1_of_2_stas_from_fst_ap(dev, apdev, test_params):
916     """FST disconnect 1 of 2 STAs from FST AP"""
917     fst_ap1, fst_ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
918     with HWSimRadio() as (radio, iface):
919         non_fst_ap = hostapd.add_ap(iface, { "ssid": "non_fst_11g" })
920         try:
921             vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
922             sta1.connect(fst_ap1, key_mgmt="NONE", scan_freq=fst_test_common.fst_test_def_freq_a)
923             vals = sta2.scan()
924             freq = vals['freq']
925             sta2.connect_to_external_ap(non_fst_ap, ssid="non_fst_11g", key_mgmt="NONE", scan_freq=freq)
926             time.sleep(2)
927             orig_sta1_mbies = sta1.get_local_mbies()
928             orig_sta2_mbies = sta2.get_local_mbies()
929             sta1.disconnect()
930             time.sleep(2)
931             res_sta1_mbies = sta1.get_local_mbies()
932             res_sta2_mbies = sta2.get_local_mbies()
933             if (not orig_sta1_mbies.startswith("FAIL") or
934                 not orig_sta2_mbies.startswith("FAIL") or
935                 not res_sta1_mbies.startswith("FAIL") or
936                 not res_sta2_mbies.startswith("FAIL")):
937                 raise Exception("Failure. MB IEs should have stayed non-present on the stations")
938         except Exception, e:
939             logger.info(e)
940             raise
941         finally:
942             sta1.disconnect()
943             sta2.disconnect_from_external_ap()
944             fst_module_aux.stop_two_ap_sta_pairs(fst_ap1, fst_ap2, sta1, sta2)
945
946 def test_fst_disconnect_2_of_2_stas_from_non_fst_ap(dev, apdev, test_params):
947     """FST disconnect 2 of 2 STAs from non-FST AP"""
948     fst_ap1, fst_ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
949     with HWSimRadio() as (radio, iface):
950         non_fst_ap = hostapd.add_ap(iface, { "ssid": "non_fst_11g" })
951         try:
952             vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
953             sta1.connect(fst_ap1, key_mgmt="NONE", scan_freq=fst_test_common.fst_test_def_freq_a)
954             vals = sta2.scan()
955             freq = vals['freq']
956             sta2.connect_to_external_ap(non_fst_ap, ssid="non_fst_11g", key_mgmt="NONE", scan_freq=freq)
957             time.sleep(2)
958             sta1.disconnect()
959             time.sleep(2)
960             orig_sta1_mbies = sta1.get_local_mbies()
961             orig_sta2_mbies = sta2.get_local_mbies()
962             sta2.disconnect_from_external_ap()
963             time.sleep(2)
964             res_sta1_mbies = sta1.get_local_mbies()
965             res_sta2_mbies = sta2.get_local_mbies()
966             if (not orig_sta1_mbies.startswith("FAIL") or
967                 not orig_sta2_mbies.startswith("FAIL") or
968                 res_sta1_mbies.startswith("FAIL") or
969                 res_sta2_mbies.startswith("FAIL")):
970                 raise Exception("Failure. MB IEs haven't reappeared on the stations")
971         except Exception, e:
972             logger.info(e)
973             raise
974         finally:
975             sta1.disconnect()
976             sta2.disconnect_from_external_ap()
977             fst_module_aux.stop_two_ap_sta_pairs(fst_ap1, fst_ap2, sta1, sta2)
978
979 def test_fst_disconnect_2_of_2_stas_from_fst_ap(dev, apdev, test_params):
980     """FST disconnect 2 of 2 STAs from FST AP"""
981     fst_ap1, fst_ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
982     with HWSimRadio() as (radio, iface):
983         non_fst_ap = hostapd.add_ap(iface, { "ssid": "non_fst_11g"})
984         try:
985             vals = sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
986             sta1.connect(fst_ap1, key_mgmt="NONE", scan_freq=fst_test_common.fst_test_def_freq_a)
987             vals = sta2.scan()
988             freq = vals['freq']
989             sta2.connect_to_external_ap(non_fst_ap, ssid="non_fst_11g", key_mgmt="NONE", scan_freq=freq)
990             time.sleep(2)
991             sta2.disconnect_from_external_ap()
992             time.sleep(2)
993             orig_sta1_mbies = sta1.get_local_mbies()
994             orig_sta2_mbies = sta2.get_local_mbies()
995             sta1.disconnect()
996             time.sleep(2)
997             res_sta1_mbies = sta1.get_local_mbies()
998             res_sta2_mbies = sta2.get_local_mbies()
999             if (orig_sta1_mbies.startswith("FAIL") or
1000                 orig_sta2_mbies.startswith("FAIL") or
1001                 res_sta1_mbies.startswith("FAIL") or
1002                 res_sta2_mbies.startswith("FAIL")):
1003                 raise Exception("Failure. MB IEs should have stayed present on both stations")
1004             # Mandatory part of 8.4.2.140 Multi-band element is 24 bytes = 48 hex chars
1005             basic_sta1_mbies = res_sta1_mbies[0:48] + res_sta1_mbies[60:108]
1006             basic_sta2_mbies = res_sta2_mbies[0:48] + res_sta2_mbies[60:108]
1007             if (basic_sta1_mbies != basic_sta2_mbies):
1008                 raise Exception("Failure. Basic MB IEs should have become identical on both stations")
1009             addr_sta1_str = sta1.get_own_mac_address().replace(":", "")
1010             addr_sta2_str = sta2.get_own_mac_address().replace(":", "")
1011             # Mandatory part of 8.4.2.140 Multi-band element is followed by STA MAC Address field (6 bytes = 12 hex chars)
1012             addr_sta1_mbie1 = res_sta1_mbies[48:60]
1013             addr_sta1_mbie2 = res_sta1_mbies[108:120]
1014             addr_sta2_mbie1 = res_sta2_mbies[48:60]
1015             addr_sta2_mbie2 = res_sta2_mbies[108:120]
1016             if (addr_sta1_mbie1 != addr_sta1_mbie2 or
1017                 addr_sta1_mbie1 != addr_sta2_str or
1018                 addr_sta2_mbie1 != addr_sta2_mbie2 or
1019                 addr_sta2_mbie1 != addr_sta1_str):
1020                 raise Exception("Failure. STA Address in MB IEs should have been same as the other STA's")
1021         except Exception, e:
1022             logger.info(e)
1023             raise
1024         finally:
1025             sta1.disconnect()
1026             sta2.disconnect_from_external_ap()
1027             fst_module_aux.stop_two_ap_sta_pairs(fst_ap1, fst_ap2, sta1, sta2)
1028
1029 def test_fst_disconnect_non_fst_sta(dev, apdev, test_params):
1030     """FST disconnect non-FST STA"""
1031     ap1, ap2, fst_sta1, fst_sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
1032     external_sta_connected = False
1033     try:
1034         vals = fst_sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
1035         fst_sta1.connect(ap1, key_mgmt="NONE",
1036                          scan_freq=fst_test_common.fst_test_def_freq_a)
1037         vals = dev[0].scan(None, fst_test_common.fst_test_def_freq_g)
1038         fst_module_aux.external_sta_connect(dev[0], ap2, key_mgmt="NONE",
1039                                             scan_freq=fst_test_common.fst_test_def_freq_g)
1040         external_sta_connected = True
1041         time.sleep(2)
1042         fst_sta1.disconnect()
1043         time.sleep(2)
1044         orig_ap_mbies = ap2.get_local_mbies()
1045         fst_module_aux.disconnect_external_sta(dev[0], ap2)
1046         external_sta_connected = False
1047         time.sleep(2)
1048         res_ap_mbies = ap2.get_local_mbies()
1049         if res_ap_mbies != orig_ap_mbies:
1050             raise Exception("Failure. MB IEs have been unexpectedly updated on the AP")
1051     except Exception, e:
1052         logger.info(e)
1053         raise
1054     finally:
1055         fst_sta1.disconnect()
1056         if external_sta_connected:
1057             fst_module_aux.disconnect_external_sta(dev[0], ap2)
1058         fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, fst_sta1, fst_sta2)
1059
1060 def test_fst_disconnect_fst_sta(dev, apdev, test_params):
1061     """FST disconnect FST STA"""
1062     ap1, ap2, fst_sta1, fst_sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
1063     external_sta_connected = False;
1064     try:
1065         vals = fst_sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
1066         fst_sta1.connect(ap1, key_mgmt="NONE",
1067                          scan_freq=fst_test_common.fst_test_def_freq_a)
1068         vals = dev[0].scan(None, fst_test_common.fst_test_def_freq_g)
1069         fst_module_aux.external_sta_connect(dev[0], ap2, key_mgmt="NONE",
1070                                             scan_freq=fst_test_common.fst_test_def_freq_g)
1071         external_sta_connected = True
1072         time.sleep(2)
1073         fst_module_aux.disconnect_external_sta(dev[0], ap2)
1074         external_sta_connected = False
1075         time.sleep(2)
1076         orig_ap_mbies = ap2.get_local_mbies()
1077         fst_sta1.disconnect()
1078         time.sleep(2)
1079         res_ap_mbies = ap2.get_local_mbies()
1080         if res_ap_mbies != orig_ap_mbies:
1081             raise Exception("Failure. MB IEs have been unexpectedly updated on the AP")
1082     except Exception, e:
1083         logger.info(e)
1084         raise
1085     finally:
1086         fst_sta1.disconnect()
1087         if external_sta_connected:
1088             fst_module_aux.disconnect_external_sta(dev[0], ap2)
1089         fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, fst_sta1, fst_sta2)
1090
1091 def test_fst_dynamic_iface_attach(dev, apdev, test_params):
1092     """FST dynamic interface attach"""
1093     ap1 = fst_module_aux.FstAP(apdev[0]['ifname'], 'fst_11a', 'a',
1094                                fst_test_common.fst_test_def_chan_a,
1095                                fst_test_common.fst_test_def_group,
1096                                fst_test_common.fst_test_def_prio_low,
1097                                fst_test_common.fst_test_def_llt)
1098     ap1.start()
1099     ap2 = fst_module_aux.FstAP(apdev[1]['ifname'], 'fst_11g', 'b',
1100                                fst_test_common.fst_test_def_chan_g,
1101                                '', '', '')
1102     ap2.start()
1103
1104     sta1 = fst_module_aux.FstSTA('wlan5',
1105                                  fst_test_common.fst_test_def_group,
1106                                  fst_test_common.fst_test_def_prio_low,
1107                                  fst_test_common.fst_test_def_llt)
1108     sta1.start()
1109     sta2 = fst_module_aux.FstSTA('wlan6', '', '', '')
1110     sta2.start()
1111
1112     try:
1113         orig_sta2_mbies = sta2.get_local_mbies()
1114         orig_ap2_mbies = ap2.get_local_mbies()
1115         sta2.send_iface_attach_request(sta2.ifname(),
1116                                        fst_test_common.fst_test_def_group,
1117                                        '52', '27')
1118         event = sta2.wait_for_iface_event(5)
1119         if event['event_type'] != 'attached':
1120             raise Exception("Failure. Iface was not properly attached")
1121         ap2.send_iface_attach_request(ap2.ifname(),
1122                                       fst_test_common.fst_test_def_group,
1123                                       '102', '77')
1124         event = ap2.wait_for_iface_event(5)
1125         if event['event_type'] != 'attached':
1126             raise Exception("Failure. Iface was not properly attached")
1127         time.sleep(2)
1128         res_sta2_mbies = sta2.get_local_mbies()
1129         res_ap2_mbies = ap2.get_local_mbies()
1130         sta2.send_iface_detach_request(sta2.ifname())
1131         event = sta2.wait_for_iface_event(5)
1132         if event['event_type'] != 'detached':
1133             raise Exception("Failure. Iface was not properly detached")
1134         ap2.send_iface_detach_request(ap2.ifname())
1135         event = ap2.wait_for_iface_event(5)
1136         if event['event_type'] != 'detached':
1137             raise Exception("Failure. Iface was not properly detached")
1138         if (not orig_sta2_mbies.startswith("FAIL") or
1139             not orig_ap2_mbies.startswith("FAIL") or
1140             res_sta2_mbies.startswith("FAIL") or
1141             res_ap2_mbies.startswith("FAIL")):
1142             raise Exception("Failure. MB IEs should have appeared on the station and on the AP")
1143     except Exception, e:
1144         logger.info(e)
1145         raise
1146     finally:
1147         ap1.stop()
1148         ap2.stop()
1149         sta1.stop()
1150         sta2.stop()
1151
1152 # AP side FST module tests
1153
1154 def test_fst_ap_start_session(dev, apdev, test_params):
1155     """FST AP start session"""
1156     fst_start_session(apdev, test_params, bad_param_none, True)
1157
1158 def test_fst_ap_start_session_no_add_params(dev, apdev, test_params):
1159     """FST AP start session - no add params"""
1160     fst_start_session(apdev, test_params, bad_param_session_add_no_params, True)
1161
1162 def test_fst_ap_start_session_bad_group_id(dev, apdev, test_params):
1163     """FST AP start session - bad group id"""
1164     fst_start_session(apdev, test_params, bad_param_group_id, True)
1165
1166 def test_fst_ap_start_session_no_set_params(dev, apdev, test_params):
1167     """FST AP start session - no set params"""
1168     fst_start_session(apdev, test_params, bad_param_session_set_no_params, True)
1169
1170 def test_fst_ap_start_session_set_unknown_param(dev, apdev, test_params):
1171     """FST AP start session - set unknown param"""
1172     fst_start_session(apdev, test_params, bad_param_session_set_unknown_param,
1173                       True)
1174
1175 def test_fst_ap_start_session_bad_session_id(dev, apdev, test_params):
1176     """FST AP start session - bad session id"""
1177     fst_start_session(apdev, test_params, bad_param_session_id, True)
1178
1179 def test_fst_ap_start_session_bad_new_iface(dev, apdev, test_params):
1180     """FST AP start session - bad new iface"""
1181     fst_start_session(apdev, test_params, bad_param_new_iface, True)
1182
1183 def test_fst_ap_start_session_bad_old_iface(dev, apdev, test_params):
1184     """FST AP start session - bad old iface"""
1185     fst_start_session(apdev, test_params, bad_param_old_iface, True)
1186
1187 def test_fst_ap_start_session_negative_llt(dev, apdev, test_params):
1188     """FST AP start session - negative llt"""
1189     fst_start_session(apdev, test_params, bad_param_negative_llt, True)
1190
1191 def test_fst_ap_start_session_zero_llt(dev, apdev, test_params):
1192     """FST AP start session - zero llt"""
1193     fst_start_session(apdev, test_params, bad_param_zero_llt, True)
1194
1195 def test_fst_ap_start_session_llt_too_big(dev, apdev, test_params):
1196     """FST AP start session - llt too large"""
1197     fst_start_session(apdev, test_params, bad_param_llt_too_big, True)
1198
1199 def test_fst_ap_start_session_invalid_peer_addr(dev, apdev, test_params):
1200     """FST AP start session - invalid peer address"""
1201     fst_start_session(apdev, test_params, bad_param_peer_addr, True,
1202                       'GG:GG:GG:GG:GG:GG')
1203
1204 def test_fst_ap_start_session_multicast_peer_addr(dev, apdev, test_params):
1205     """FST AP start session - multicast peer address"""
1206     fst_start_session(apdev, test_params, bad_param_peer_addr, True,
1207                       '01:00:11:22:33:44')
1208
1209 def test_fst_ap_start_session_broadcast_peer_addr(dev, apdev, test_params):
1210     """FST AP start session - broadcast peer address"""
1211     fst_start_session(apdev, test_params, bad_param_peer_addr, True,
1212                       'FF:FF:FF:FF:FF:FF')
1213
1214 def test_fst_ap_initiate_session(dev, apdev, test_params):
1215     """FST AP initiate session"""
1216     fst_initiate_session(apdev, test_params, bad_param_none, True)
1217
1218 def test_fst_ap_initiate_session_no_params(dev, apdev, test_params):
1219     """FST AP initiate session - no params"""
1220     fst_initiate_session(apdev, test_params,
1221                          bad_param_session_initiate_no_params, True)
1222
1223 def test_fst_ap_initiate_session_invalid_session_id(dev, apdev, test_params):
1224     """FST AP initiate session - invalid session id"""
1225     fst_initiate_session(apdev, test_params,
1226                          bad_param_session_initiate_bad_session_id, True)
1227
1228 def test_fst_ap_initiate_session_no_new_iface(dev, apdev, test_params):
1229     """FST AP initiate session - no new iface"""
1230     fst_initiate_session(apdev, test_params,
1231                          bad_param_session_initiate_with_no_new_iface_set, True)
1232
1233 def test_fst_ap_initiate_session_bad_peer_addr(dev, apdev, test_params):
1234     """FST AP initiate session - bad peer address"""
1235     fst_initiate_session(apdev, test_params,
1236                          bad_param_session_initiate_with_bad_peer_addr_set,
1237                          True)
1238
1239 def test_fst_ap_initiate_session_request_with_bad_stie(dev, apdev, test_params):
1240     """FST AP initiate session - request with bad stie"""
1241     fst_initiate_session(apdev, test_params,
1242                          bad_param_session_initiate_request_with_bad_stie, True)
1243
1244 def test_fst_ap_initiate_session_response_with_reject(dev, apdev, test_params):
1245     """FST AP initiate session - response with reject"""
1246     fst_initiate_session(apdev, test_params,
1247                          bad_param_session_initiate_response_with_reject, True)
1248
1249 def test_fst_ap_initiate_session_response_with_bad_stie(dev, apdev,
1250                                                         test_params):
1251     """FST AP initiate session - response with bad stie"""
1252     fst_initiate_session(apdev, test_params,
1253                          bad_param_session_initiate_response_with_bad_stie,
1254                          True)
1255
1256 def test_fst_ap_initiate_session_response_with_zero_llt(dev, apdev,
1257                                                         test_params):
1258     """FST AP initiate session - zero llt"""
1259     fst_initiate_session(apdev, test_params,
1260                          bad_param_session_initiate_response_with_zero_llt,
1261                          True)
1262
1263 def test_fst_ap_initiate_session_stt_no_response(dev, apdev, test_params):
1264     """FST AP initiate session - stt no response"""
1265     fst_initiate_session(apdev, test_params,
1266                          bad_param_session_initiate_stt_no_response, True)
1267
1268 def test_fst_ap_initiate_session_concurrent_setup_request(dev, apdev,
1269                                                           test_params):
1270     """FST AP initiate session - concurrent setup request"""
1271     fst_initiate_session(apdev, test_params,
1272                          bad_param_session_initiate_concurrent_setup_request,
1273                          True)
1274
1275 def test_fst_ap_session_request_with_no_session(dev, apdev, test_params):
1276     """FST AP session request with no session"""
1277     fst_send_unexpected_frame(apdev, test_params, frame_type_session_request,
1278                               True)
1279
1280 def test_fst_ap_session_response_accept_with_no_session(dev, apdev,
1281                                                         test_params):
1282     """FST AP session response accept with no session"""
1283     fst_send_unexpected_frame(apdev, test_params, frame_type_session_response,
1284                               True, "accept")
1285
1286 def test_fst_ap_session_response_reject_with_no_session(dev, apdev,
1287                                                         test_params):
1288     """FST AP session response reject with no session"""
1289     fst_send_unexpected_frame(apdev, test_params, frame_type_session_response,
1290                               True, "reject")
1291
1292 def test_fst_ap_ack_request_with_no_session(dev, apdev, test_params):
1293     """FST AP ack request with no session"""
1294     fst_send_unexpected_frame(apdev, test_params, frame_type_ack_request, True)
1295
1296 def test_fst_ap_ack_response_with_no_session(dev, apdev, test_params):
1297     """FST AP ack response with no session"""
1298     fst_send_unexpected_frame(apdev, test_params, frame_type_ack_response, True)
1299
1300 def test_fst_ap_tear_down_response_with_no_session(dev, apdev, test_params):
1301     """FST AP tear down response with no session"""
1302     fst_send_unexpected_frame(apdev, test_params, frame_type_tear_down, True)
1303
1304 def test_fst_ap_transfer_session(dev, apdev, test_params):
1305     """FST AP transfer session"""
1306     fst_transfer_session(apdev, test_params, bad_param_none, True)
1307
1308 def test_fst_ap_transfer_session_no_params(dev, apdev, test_params):
1309     """FST AP transfer session - no params"""
1310     fst_transfer_session(apdev, test_params,
1311                          bad_param_session_transfer_no_params, True)
1312
1313 def test_fst_ap_transfer_session_bad_session_id(dev, apdev, test_params):
1314     """FST AP transfer session - bad session id"""
1315     fst_transfer_session(apdev, test_params,
1316                          bad_param_session_transfer_bad_session_id, True)
1317
1318 def test_fst_ap_transfer_session_setup_skipped(dev, apdev, test_params):
1319     """FST AP transfer session - setup skipped"""
1320     fst_transfer_session(apdev, test_params,
1321                          bad_param_session_transfer_setup_skipped, True)
1322
1323 def test_fst_ap_ack_request_with_session_not_set_up(dev, apdev, test_params):
1324     """FST AP ack request with session not set up"""
1325     fst_bad_transfer(apdev, test_params,
1326                      bad_scenario_ack_req_session_not_set_up, True)
1327
1328 def test_fst_ap_ack_request_with_session_not_established_init_side(dev, apdev,
1329                                                                    test_params):
1330     """FST AP ack request with session not established init side"""
1331     fst_bad_transfer(apdev, test_params,
1332                      bad_scenario_ack_req_session_not_established_init_side,
1333                      True)
1334
1335 def test_fst_ap_ack_request_with_session_not_established_resp_side(dev, apdev,
1336                                                                    test_params):
1337     """FST AP ack request with session not established resp side"""
1338     fst_bad_transfer(apdev, test_params,
1339                      bad_scenario_ack_req_session_not_established_resp_side,
1340                      True)
1341
1342 def test_fst_ap_ack_request_with_bad_fsts_id(dev, apdev, test_params):
1343     """FST AP ack request with bad fsts id"""
1344     fst_bad_transfer(apdev, test_params, bad_scenario_ack_req_bad_fsts_id, True)
1345
1346 def test_fst_ap_ack_response_with_session_not_set_up(dev, apdev, test_params):
1347     """FST AP ack response with session not set up"""
1348     fst_bad_transfer(apdev, test_params,
1349                      bad_scenario_ack_resp_session_not_set_up, True)
1350
1351 def test_fst_ap_ack_response_with_session_not_established_init_side(dev, apdev, test_params):
1352     """FST AP ack response with session not established init side"""
1353     fst_bad_transfer(apdev, test_params,
1354                      bad_scenario_ack_resp_session_not_established_init_side,
1355                      True)
1356
1357 def test_fst_ap_ack_response_with_session_not_established_resp_side(dev, apdev, test_params):
1358     """FST AP ack response with session not established resp side"""
1359     fst_bad_transfer(apdev, test_params,
1360                      bad_scenario_ack_resp_session_not_established_resp_side,
1361                      True)
1362
1363 def test_fst_ap_ack_response_with_no_ack_request(dev, apdev, test_params):
1364     """FST AP ack response with no ack request"""
1365     fst_bad_transfer(apdev, test_params, bad_scenario_ack_resp_no_ack_req, True)
1366
1367 def test_fst_ap_tear_down_session(dev, apdev, test_params):
1368     """FST AP tear down session"""
1369     fst_tear_down_session(apdev, test_params, bad_param_none, True)
1370
1371 def test_fst_ap_tear_down_session_no_params(dev, apdev, test_params):
1372     """FST AP tear down session - no params"""
1373     fst_tear_down_session(apdev, test_params,
1374                           bad_param_session_teardown_no_params, True)
1375
1376 def test_fst_ap_tear_down_session_bad_session_id(dev, apdev, test_params):
1377     """FST AP tear down session - bad session id"""
1378     fst_tear_down_session(apdev, test_params,
1379                           bad_param_session_teardown_bad_session_id, True)
1380
1381 def test_fst_ap_tear_down_session_setup_skipped(dev, apdev, test_params):
1382     """FST AP tear down session - setup skipped"""
1383     fst_tear_down_session(apdev, test_params,
1384                           bad_param_session_teardown_setup_skipped, True)
1385
1386 def test_fst_ap_tear_down_session_bad_fsts_id(dev, apdev, test_params):
1387     """FST AP tear down session - bad fsts id"""
1388     fst_tear_down_session(apdev, test_params,
1389                           bad_param_session_teardown_bad_fsts_id, True)
1390
1391 def test_fst_ap_remove_session_not_established(dev, apdev, test_params):
1392     """FST AP remove session - not established"""
1393     fst_remove_session(apdev, test_params,
1394                        remove_scenario_non_established_session, True)
1395
1396 def test_fst_ap_remove_session_established(dev, apdev, test_params):
1397     """FST AP remove session - established"""
1398     fst_remove_session(apdev, test_params,
1399                        remove_scenario_established_session, True)
1400
1401 def test_fst_ap_remove_session_no_params(dev, apdev, test_params):
1402     """FST AP remove session - no params"""
1403     fst_remove_session(apdev, test_params, remove_scenario_no_params, True)
1404
1405 def test_fst_ap_remove_session_bad_session_id(dev, apdev, test_params):
1406     """FST AP remove session - bad session id"""
1407     fst_remove_session(apdev, test_params, remove_scenario_bad_session_id, True)
1408
1409 def test_fst_ap_ctrl_iface(dev, apdev, test_params):
1410     """FST control interface behavior"""
1411     hglobal = hostapd.HostapdGlobal()
1412     start_num_groups = 0
1413     res = hglobal.request("FST-MANAGER LIST_GROUPS")
1414     del hglobal
1415     if "FAIL" not in res:
1416         start_num_groups = len(res.splitlines())
1417
1418     ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
1419     try:
1420         fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
1421         initiator = ap1
1422         responder = sta1
1423         initiator.add_peer(responder, None)
1424         initiator.set_fst_parameters(group_id=None)
1425         sid = initiator.add_session()
1426         res = initiator.get_session_params(sid)
1427         logger.info("Initial session params:\n" + str(res))
1428         if res['state'] != 'INITIAL':
1429             raise Exception("Unexpected state: " + res['state'])
1430         initiator.set_fst_parameters(llt=None)
1431         initiator.configure_session(sid, ap2.ifname(), None)
1432         res = initiator.get_session_params(sid)
1433         logger.info("Session params after configuration:\n" + str(res))
1434         res = initiator.iface_peers(initiator.ifname())
1435         logger.info("Interface peers: " + str(res))
1436         if len(res) != 1:
1437             raise Exception("Unexpected number of peers")
1438         res = initiator.get_peer_mbies(initiator.ifname(),
1439                                        initiator.get_new_peer_addr())
1440         logger.info("Peer MB IEs: " + str(res))
1441         res = initiator.list_ifaces()
1442         logger.info("Interfaces: " + str(res))
1443         if len(res) != 2:
1444             raise Exception("Unexpected number of interfaces")
1445         res = initiator.list_groups()
1446         logger.info("Groups: " + str(res))
1447         if len(res) != 1 + start_num_groups:
1448             raise Exception("Unexpected number of groups")
1449
1450         tests = [ "LIST_IFACES unknown",
1451                   "LIST_IFACES     unknown2",
1452                   "SESSION_GET 12345678",
1453                   "SESSION_SET " + sid + " unknown=foo",
1454                   "SESSION_RESPOND 12345678 foo",
1455                   "SESSION_RESPOND " + sid,
1456                   "SESSION_RESPOND " + sid + " foo",
1457                   "TEST_REQUEST foo",
1458                   "TEST_REQUEST SEND_SETUP_REQUEST",
1459                   "TEST_REQUEST SEND_SETUP_REQUEST foo",
1460                   "TEST_REQUEST SEND_SETUP_RESPONSE",
1461                   "TEST_REQUEST SEND_SETUP_RESPONSE foo",
1462                   "TEST_REQUEST SEND_ACK_REQUEST",
1463                   "TEST_REQUEST SEND_ACK_REQUEST foo",
1464                   "TEST_REQUEST SEND_ACK_RESPONSE",
1465                   "TEST_REQUEST SEND_ACK_RESPONSE foo",
1466                   "TEST_REQUEST SEND_TEAR_DOWN",
1467                   "TEST_REQUEST SEND_TEAR_DOWN foo",
1468                   "TEST_REQUEST GET_FSTS_ID",
1469                   "TEST_REQUEST GET_FSTS_ID foo",
1470                   "TEST_REQUEST GET_LOCAL_MBIES",
1471                   "TEST_REQUEST GET_LOCAL_MBIES foo",
1472                   "GET_PEER_MBIES",
1473                   "GET_PEER_MBIES ",
1474                   "GET_PEER_MBIES unknown",
1475                   "GET_PEER_MBIES unknown unknown",
1476                   "GET_PEER_MBIES unknown  " + initiator.get_new_peer_addr(),
1477                   "GET_PEER_MBIES " + initiator.ifname() + " 01:ff:ff:ff:ff:ff",
1478                   "IFACE_PEERS",
1479                   "IFACE_PEERS ",
1480                   "IFACE_PEERS unknown",
1481                   "IFACE_PEERS unknown unknown",
1482                   "IFACE_PEERS " + initiator.fst_group,
1483                   "IFACE_PEERS " + initiator.fst_group + " unknown" ]
1484         for t in tests:
1485             if "FAIL" not in initiator.grequest("FST-MANAGER " + t):
1486                 raise Exception("Unexpected response for invalid FST-MANAGER command " + t)
1487         if "UNKNOWN FST COMMAND" not in initiator.grequest("FST-MANAGER unknown"):
1488             raise Exception("Unexpected response for unknown FST-MANAGER command")
1489
1490         tests = [ "FST-DETACH", "FST-DETACH ", "FST-DETACH unknown",
1491                   "FST-ATTACH", "FST-ATTACH ", "FST-ATTACH unknown",
1492                   "FST-ATTACH unknown unknown" ]
1493         for t in tests:
1494             if "FAIL" not in initiator.grequest(t):
1495                 raise Exception("Unexpected response for invalid command " + t)
1496
1497         try:
1498             # Trying to add same interface again needs to fail.
1499             ap1.send_iface_attach_request(ap1.iface, ap1.fst_group,
1500                                           ap1.fst_llt, ap1.fst_pri)
1501             raise Exception("Duplicate FST-ATTACH succeeded")
1502         except Exception, e:
1503             if not str(e).startswith("Cannot attach"):
1504                 raise
1505
1506         try:
1507             ap1.get_fsts_id_by_sid("123")
1508         except Exception, e:
1509             if not str(e).startswith("Cannot get fsts_id for sid"):
1510                 raise
1511     finally:
1512         fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
1513         fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
1514
1515 def test_fst_ap_start_session_oom(dev, apdev, test_params):
1516     """FST AP setup failing due to OOM"""
1517     ap1 = fst_module_aux.FstAP(apdev[0]['ifname'], 'fst_11a', 'a',
1518                                fst_test_common.fst_test_def_chan_a,
1519                                fst_test_common.fst_test_def_group,
1520                                fst_test_common.fst_test_def_prio_low,
1521                                fst_test_common.fst_test_def_llt)
1522     ap1.start()
1523     with alloc_fail(ap1, 1, "fst_iface_create"):
1524         ap2_started = False
1525         try:
1526             ap2 = fst_module_aux.FstAP(apdev[1]['ifname'], 'fst_11g', 'b',
1527                                        fst_test_common.fst_test_def_chan_g,
1528                                        fst_test_common.fst_test_def_group,
1529                                        fst_test_common.fst_test_def_prio_high,
1530                                        fst_test_common.fst_test_def_llt)
1531             try:
1532                 # This will fail in fst_iface_create() OOM
1533                 ap2.start()
1534             except:
1535                 pass
1536         finally:
1537             ap1.stop()
1538             try:
1539                 ap2.stop()
1540             except:
1541                 pass
1542
1543 # STA side FST module tests
1544
1545 def test_fst_sta_start_session(dev, apdev, test_params):
1546     """FST STA start session"""
1547     fst_start_session(apdev, test_params, bad_param_none, False)
1548
1549 def test_fst_sta_start_session_no_add_params(dev, apdev, test_params):
1550     """FST STA start session - no add params"""
1551     fst_start_session(apdev, test_params, bad_param_session_add_no_params,
1552                       False)
1553
1554 def test_fst_sta_start_session_bad_group_id(dev, apdev, test_params):
1555     """FST STA start session - bad group id"""
1556     fst_start_session(apdev, test_params, bad_param_group_id, False)
1557
1558 def test_fst_sta_start_session_no_set_params(dev, apdev, test_params):
1559     """FST STA start session - no set params"""
1560     fst_start_session(apdev, test_params, bad_param_session_set_no_params,
1561                       False)
1562
1563 def test_fst_sta_start_session_set_unknown_param(dev, apdev, test_params):
1564     """FST STA start session - set unknown param"""
1565     fst_start_session(apdev, test_params, bad_param_session_set_unknown_param,
1566                       False)
1567
1568 def test_fst_sta_start_session_bad_session_id(dev, apdev, test_params):
1569     """FST STA start session - bad session id"""
1570     fst_start_session(apdev, test_params, bad_param_session_id, False)
1571
1572 def test_fst_sta_start_session_bad_new_iface(dev, apdev, test_params):
1573     """FST STA start session - bad new iface"""
1574     fst_start_session(apdev, test_params, bad_param_new_iface, False)
1575
1576 def test_fst_sta_start_session_bad_old_iface(dev, apdev, test_params):
1577     """FST STA start session - bad old iface"""
1578     fst_start_session(apdev, test_params, bad_param_old_iface, False)
1579
1580 def test_fst_sta_start_session_negative_llt(dev, apdev, test_params):
1581     """FST STA start session - negative llt"""
1582     fst_start_session(apdev, test_params, bad_param_negative_llt, False)
1583
1584 def test_fst_sta_start_session_zero_llt(dev, apdev, test_params):
1585     """FST STA start session - zero llt"""
1586     fst_start_session(apdev, test_params, bad_param_zero_llt, False)
1587
1588 def test_fst_sta_start_session_llt_too_big(dev, apdev, test_params):
1589     """FST STA start session - llt too large"""
1590     fst_start_session(apdev, test_params, bad_param_llt_too_big, False)
1591
1592 def test_fst_sta_start_session_invalid_peer_addr(dev, apdev, test_params):
1593     """FST STA start session - invalid peer address"""
1594     fst_start_session(apdev, test_params, bad_param_peer_addr, False,
1595                       'GG:GG:GG:GG:GG:GG')
1596
1597 def test_fst_sta_start_session_multicast_peer_addr(dev, apdev, test_params):
1598     """FST STA start session - multicast peer address"""
1599     fst_start_session(apdev, test_params, bad_param_peer_addr, False,
1600                       '11:00:11:22:33:44')
1601
1602 def test_fst_sta_start_session_broadcast_peer_addr(dev, apdev, test_params):
1603     """FST STA start session - broadcast peer addr"""
1604     fst_start_session(apdev, test_params, bad_param_peer_addr, False,
1605                       'FF:FF:FF:FF:FF:FF')
1606
1607 def test_fst_sta_initiate_session(dev, apdev, test_params):
1608     """FST STA initiate session"""
1609     fst_initiate_session(apdev, test_params, bad_param_none, False)
1610
1611 def test_fst_sta_initiate_session_no_params(dev, apdev, test_params):
1612     """FST STA initiate session - no params"""
1613     fst_initiate_session(apdev, test_params,
1614                          bad_param_session_initiate_no_params, False)
1615
1616 def test_fst_sta_initiate_session_invalid_session_id(dev, apdev, test_params):
1617     """FST STA initiate session - invalid session id"""
1618     fst_initiate_session(apdev, test_params,
1619                          bad_param_session_initiate_bad_session_id, False)
1620
1621 def test_fst_sta_initiate_session_no_new_iface(dev, apdev, test_params):
1622     """FST STA initiate session - no new iface"""
1623     fst_initiate_session(apdev, test_params,
1624                          bad_param_session_initiate_with_no_new_iface_set,
1625                          False)
1626
1627 def test_fst_sta_initiate_session_bad_peer_addr(dev, apdev, test_params):
1628     """FST STA initiate session - bad peer address"""
1629     fst_initiate_session(apdev, test_params,
1630                          bad_param_session_initiate_with_bad_peer_addr_set,
1631                          False)
1632
1633 def test_fst_sta_initiate_session_request_with_bad_stie(dev, apdev,
1634                                                         test_params):
1635     """FST STA initiate session - request with bad stie"""
1636     fst_initiate_session(apdev, test_params,
1637                          bad_param_session_initiate_request_with_bad_stie,
1638                          False)
1639
1640 def test_fst_sta_initiate_session_response_with_reject(dev, apdev, test_params):
1641     """FST STA initiate session - response with reject"""
1642     fst_initiate_session(apdev, test_params, bad_param_session_initiate_response_with_reject, False)
1643
1644 def test_fst_sta_initiate_session_response_with_bad_stie(dev, apdev, test_params):
1645     """FST STA initiate session - response with bad stie"""
1646     fst_initiate_session(apdev, test_params,
1647                          bad_param_session_initiate_response_with_bad_stie,
1648                          False)
1649
1650 def test_fst_sta_initiate_session_response_with_zero_llt(dev, apdev,
1651                                                          test_params):
1652     """FST STA initiate session - response with zero llt"""
1653     fst_initiate_session(apdev, test_params,
1654                          bad_param_session_initiate_response_with_zero_llt,
1655                          False)
1656
1657 def test_fst_sta_initiate_session_stt_no_response(dev, apdev, test_params):
1658     """FST STA initiate session - stt no response"""
1659     fst_initiate_session(apdev, test_params,
1660                          bad_param_session_initiate_stt_no_response, False)
1661
1662 def test_fst_sta_initiate_session_concurrent_setup_request(dev, apdev,
1663                                                            test_params):
1664     """FST STA initiate session - concurrent setup request"""
1665     fst_initiate_session(apdev, test_params,
1666                          bad_param_session_initiate_concurrent_setup_request,
1667                          False)
1668
1669 def test_fst_sta_session_request_with_no_session(dev, apdev, test_params):
1670     """FST STA session request with no session"""
1671     fst_send_unexpected_frame(apdev, test_params, frame_type_session_request,
1672                               False)
1673
1674 def test_fst_sta_session_response_accept_with_no_session(dev, apdev,
1675                                                          test_params):
1676     """FST STA session response accept with no session"""
1677     fst_send_unexpected_frame(apdev, test_params, frame_type_session_response,
1678                               False, "accept")
1679
1680 def test_fst_sta_session_response_reject_with_no_session(dev, apdev,
1681                                                          test_params):
1682     """FST STA session response reject with no session"""
1683     fst_send_unexpected_frame(apdev, test_params, frame_type_session_response,
1684                               False, "reject")
1685
1686 def test_fst_sta_ack_request_with_no_session(dev, apdev, test_params):
1687     """FST STA ack request with no session"""
1688     fst_send_unexpected_frame(apdev, test_params, frame_type_ack_request, False)
1689
1690 def test_fst_sta_ack_response_with_no_session(dev, apdev, test_params):
1691     """FST STA ack response with no session"""
1692     fst_send_unexpected_frame(apdev, test_params, frame_type_ack_response,
1693                               False)
1694
1695 def test_fst_sta_tear_down_response_with_no_session(dev, apdev, test_params):
1696     """FST STA tear down response with no session"""
1697     fst_send_unexpected_frame(apdev, test_params, frame_type_tear_down, False)
1698
1699 def test_fst_sta_transfer_session(dev, apdev, test_params):
1700     """FST STA transfer session"""
1701     fst_transfer_session(apdev, test_params, bad_param_none, False)
1702
1703 def test_fst_sta_transfer_session_no_params(dev, apdev, test_params):
1704     """FST STA transfer session - no params"""
1705     fst_transfer_session(apdev, test_params,
1706                          bad_param_session_transfer_no_params, False)
1707
1708 def test_fst_sta_transfer_session_bad_session_id(dev, apdev, test_params):
1709     """FST STA transfer session - bad session id"""
1710     fst_transfer_session(apdev, test_params,
1711                          bad_param_session_transfer_bad_session_id, False)
1712
1713 def test_fst_sta_transfer_session_setup_skipped(dev, apdev, test_params):
1714     """FST STA transfer session - setup skipped"""
1715     fst_transfer_session(apdev, test_params,
1716                          bad_param_session_transfer_setup_skipped, False)
1717
1718 def test_fst_sta_ack_request_with_session_not_set_up(dev, apdev, test_params):
1719     """FST STA ack request with session not set up"""
1720     fst_bad_transfer(apdev, test_params,
1721                      bad_scenario_ack_req_session_not_set_up, False)
1722
1723 def test_fst_sta_ack_request_with_session_not_established_init_side(dev, apdev, test_params):
1724     """FST STA ack request with session not established init side"""
1725     fst_bad_transfer(apdev, test_params,
1726                      bad_scenario_ack_req_session_not_established_init_side,
1727                      False)
1728
1729 def test_fst_sta_ack_request_with_session_not_established_resp_side(dev, apdev, test_params):
1730     """FST STA ack request with session not established resp side"""
1731     fst_bad_transfer(apdev, test_params,
1732                      bad_scenario_ack_req_session_not_established_resp_side,
1733                      False)
1734
1735 def test_fst_sta_ack_request_with_bad_fsts_id(dev, apdev, test_params):
1736     """FST STA ack request with bad fsts id"""
1737     fst_bad_transfer(apdev, test_params, bad_scenario_ack_req_bad_fsts_id,
1738                      False)
1739
1740 def test_fst_sta_ack_response_with_session_not_set_up(dev, apdev, test_params):
1741     """FST STA ack response with session not set up"""
1742     fst_bad_transfer(apdev, test_params,
1743                      bad_scenario_ack_resp_session_not_set_up, False)
1744
1745 def test_fst_sta_ack_response_with_session_not_established_init_side(dev, apdev, test_params):
1746     """FST STA ack response with session not established init side"""
1747     fst_bad_transfer(apdev, test_params,
1748                      bad_scenario_ack_resp_session_not_established_init_side,
1749                      False)
1750
1751 def test_fst_sta_ack_response_with_session_not_established_resp_side(dev, apdev, test_params):
1752     """FST STA ack response with session not established resp side"""
1753     fst_bad_transfer(apdev, test_params,
1754                      bad_scenario_ack_resp_session_not_established_resp_side,
1755                      False)
1756
1757 def test_fst_sta_ack_response_with_no_ack_request(dev, apdev, test_params):
1758     """FST STA ack response with no ack request"""
1759     fst_bad_transfer(apdev, test_params, bad_scenario_ack_resp_no_ack_req,
1760                      False)
1761
1762 def test_fst_sta_tear_down_session(dev, apdev, test_params):
1763     """FST STA tear down session"""
1764     fst_tear_down_session(apdev, test_params, bad_param_none, False)
1765
1766 def test_fst_sta_tear_down_session_no_params(dev, apdev, test_params):
1767     """FST STA tear down session - no params"""
1768     fst_tear_down_session(apdev, test_params,
1769                           bad_param_session_teardown_no_params, False)
1770
1771 def test_fst_sta_tear_down_session_bad_session_id(dev, apdev, test_params):
1772     """FST STA tear down session - bad session id"""
1773     fst_tear_down_session(apdev, test_params,
1774                           bad_param_session_teardown_bad_session_id, False)
1775
1776 def test_fst_sta_tear_down_session_setup_skipped(dev, apdev, test_params):
1777     """FST STA tear down session - setup skipped"""
1778     fst_tear_down_session(apdev, test_params,
1779                           bad_param_session_teardown_setup_skipped, False)
1780
1781 def test_fst_sta_tear_down_session_bad_fsts_id(dev, apdev, test_params):
1782     """FST STA tear down session - bad fsts id"""
1783     fst_tear_down_session(apdev, test_params,
1784                           bad_param_session_teardown_bad_fsts_id, False)
1785
1786 def test_fst_sta_remove_session_not_established(dev, apdev, test_params):
1787     """FST STA tear down session - not established"""
1788     fst_remove_session(apdev, test_params,
1789                        remove_scenario_non_established_session, False)
1790
1791 def test_fst_sta_remove_session_established(dev, apdev, test_params):
1792     """FST STA remove session - established"""
1793     fst_remove_session(apdev, test_params,
1794                        remove_scenario_established_session, False)
1795
1796 def test_fst_sta_remove_session_no_params(dev, apdev, test_params):
1797     """FST STA remove session - no params"""
1798     fst_remove_session(apdev, test_params, remove_scenario_no_params, False)
1799
1800 def test_fst_sta_remove_session_bad_session_id(dev, apdev, test_params):
1801     """FST STA remove session - bad session id"""
1802     fst_remove_session(apdev, test_params, remove_scenario_bad_session_id,
1803                        False)
1804
1805 def test_fst_rsn_ap_transfer_session(dev, apdev, test_params):
1806     """FST RSN AP transfer session"""
1807     fst_transfer_session(apdev, test_params, bad_param_none, True, rsn=True)
1808
1809 MGMT_SUBTYPE_ACTION = 13
1810 ACTION_CATEG_FST = 18
1811 FST_ACTION_SETUP_REQUEST = 0
1812 FST_ACTION_SETUP_RESPONSE = 1
1813 FST_ACTION_TEAR_DOWN = 2
1814 FST_ACTION_ACK_REQUEST = 3
1815 FST_ACTION_ACK_RESPONSE = 4
1816 FST_ACTION_ON_CHANNEL_TUNNEL = 5
1817
1818 def hostapd_tx_and_status(hapd, msg):
1819     hapd.set("ext_mgmt_frame_handling", "1")
1820     hapd.mgmt_tx(msg)
1821     ev = hapd.wait_event([ "MGMT-TX-STATUS" ], timeout=1)
1822     if ev is None or "ok=1" not in ev:
1823         raise Exception("No ACK")
1824     hapd.set("ext_mgmt_frame_handling", "0")
1825
1826 def test_fst_proto(dev, apdev, test_params):
1827     """FST protocol testing"""
1828     ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
1829     try:
1830         fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
1831         hapd = ap1.get_instance()
1832         sta = sta1.get_instance()
1833         dst = sta.own_addr()
1834         src = apdev[0]['bssid']
1835
1836         msg = {}
1837         msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1838         msg['da'] = dst
1839         msg['sa'] = src
1840         msg['bssid'] = src
1841
1842         # unknown FST Action (255) received!
1843         msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST, 255)
1844         hostapd_tx_and_status(hapd, msg)
1845
1846         # FST Request dropped: too short
1847         msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1848                                      FST_ACTION_SETUP_REQUEST)
1849         hostapd_tx_and_status(hapd, msg)
1850
1851         # FST Request dropped: invalid STIE (EID)
1852         msg['payload'] = struct.pack("<BBBLBBLBBBBBBB", ACTION_CATEG_FST,
1853                                      FST_ACTION_SETUP_REQUEST, 0, 0,
1854                                      163, 11, 0, 0, 0, 0, 0, 0, 0, 0)
1855         hostapd_tx_and_status(hapd, msg)
1856
1857         # FST Request dropped: invalid STIE (Len)
1858         msg['payload'] = struct.pack("<BBBLBBLBBBBBBB", ACTION_CATEG_FST,
1859                                      FST_ACTION_SETUP_REQUEST, 0, 0,
1860                                      164, 10, 0, 0, 0, 0, 0, 0, 0, 0)
1861         hostapd_tx_and_status(hapd, msg)
1862
1863         # FST Request dropped: new and old band IDs are the same
1864         msg['payload'] = struct.pack("<BBBLBBLBBBBBBB", ACTION_CATEG_FST,
1865                                      FST_ACTION_SETUP_REQUEST, 0, 0,
1866                                      164, 11, 0, 0, 0, 0, 0, 0, 0, 0)
1867         hostapd_tx_and_status(hapd, msg)
1868
1869         ifaces = sta1.list_ifaces()
1870         id = int(ifaces[0]['name'].split('|')[1])
1871         # FST Request dropped: new iface not found (new_band_id mismatch)
1872         msg['payload'] = struct.pack("<BBBLBBLBBBBBBB", ACTION_CATEG_FST,
1873                                      FST_ACTION_SETUP_REQUEST, 0, 0,
1874                                      164, 11, 0, 0, id + 1, 0, 0, 0, 0, 0)
1875         hostapd_tx_and_status(hapd, msg)
1876
1877         # FST Action 'Setup Response' dropped: no session in progress found
1878         msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1879                                      FST_ACTION_SETUP_RESPONSE)
1880         hostapd_tx_and_status(hapd, msg)
1881
1882         # Create session
1883         initiator = ap1
1884         responder = sta1
1885         new_iface = ap2.ifname()
1886         new_peer_addr = ap2.get_actual_peer_addr()
1887         resp_newif = sta2.ifname()
1888         peeraddr = None
1889         initiator.add_peer(responder, peeraddr, new_peer_addr)
1890         sid = initiator.add_session()
1891         initiator.configure_session(sid, new_iface)
1892         initiator.initiate_session(sid, "accept")
1893
1894         # FST Response dropped due to wrong state: SETUP_COMPLETION
1895         msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1896                                      FST_ACTION_SETUP_RESPONSE)
1897         hostapd_tx_and_status(hapd, msg)
1898
1899         # Too short FST Tear Down dropped
1900         msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1901                                      FST_ACTION_TEAR_DOWN)
1902         hostapd_tx_and_status(hapd, msg)
1903
1904         # tear down for wrong FST Setup ID (0)
1905         msg['payload'] = struct.pack("<BBL", ACTION_CATEG_FST,
1906                                      FST_ACTION_TEAR_DOWN, 0)
1907         hostapd_tx_and_status(hapd, msg)
1908
1909         # Ack received on wrong interface
1910         msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1911                                      FST_ACTION_ACK_REQUEST)
1912         hostapd_tx_and_status(hapd, msg)
1913
1914         # Ack Response in inappropriate session state (SETUP_COMPLETION)
1915         msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1916                                      FST_ACTION_ACK_RESPONSE)
1917         hostapd_tx_and_status(hapd, msg)
1918
1919         # Unsupported FST Action frame (On channel tunnel)
1920         msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1921                                      FST_ACTION_ON_CHANNEL_TUNNEL)
1922         hostapd_tx_and_status(hapd, msg)
1923
1924         # FST Request dropped: new iface not found (new_band_id match)
1925         # FST Request dropped due to MAC comparison
1926         msg['payload'] = struct.pack("<BBBLBBLBBBBBBB", ACTION_CATEG_FST,
1927                                      FST_ACTION_SETUP_REQUEST, 0, 0,
1928                                      164, 11, 0, 0, id, 0, 0, 0, 0, 0)
1929         hostapd_tx_and_status(hapd, msg)
1930
1931         hapd2 = ap2.get_instance()
1932         dst2 = sta2.get_instance().own_addr()
1933         src2 = apdev[1]['bssid']
1934
1935         msg2 = {}
1936         msg2['fc'] = MGMT_SUBTYPE_ACTION << 4
1937         msg2['da'] = dst2
1938         msg2['sa'] = src2
1939         msg2['bssid'] = src2
1940         # FST Response dropped: wlan6 is not the old iface
1941         msg2['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1942                                       FST_ACTION_SETUP_RESPONSE)
1943         hostapd_tx_and_status(hapd2, msg2)
1944
1945         sta.dump_monitor()
1946
1947         group = ap1.fst_group
1948         ap1.send_iface_detach_request(ap1.iface)
1949
1950         sta.flush_scan_cache()
1951         sta.request("REASSOCIATE")
1952         sta.wait_connected()
1953
1954         # FST Request dropped due to no interface connection
1955         msg['payload'] = struct.pack("<BBBLBBLBBBBBBB", ACTION_CATEG_FST,
1956                                      FST_ACTION_SETUP_REQUEST, 0, 0,
1957                                      164, 11, 0, 0, id, 0, 0, 0, 0, 0)
1958         hostapd_tx_and_status(hapd, msg)
1959     finally:
1960         fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
1961         try:
1962             fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
1963         except:
1964             pass
1965
1966 def test_fst_setup_response_proto(dev, apdev, test_params):
1967     """FST protocol testing for Setup Response"""
1968     ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
1969     try:
1970         fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
1971         hapd = ap1.get_instance()
1972         sta = sta1.get_instance()
1973         dst = sta.own_addr()
1974         src = apdev[0]['bssid']
1975
1976         sta1.add_peer(ap1, None, sta2.get_actual_peer_addr())
1977         sta1.set_fst_parameters(llt='0')
1978         sid = sta1.add_session()
1979         sta1.configure_session(sid, sta2.ifname())
1980         sta1.initiate_session(sid, "")
1981
1982         msg = {}
1983         msg['fc'] = MGMT_SUBTYPE_ACTION << 4
1984         msg['da'] = dst
1985         msg['sa'] = src
1986         msg['bssid'] = src
1987
1988         # Too short FST Response dropped
1989         msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
1990                                      FST_ACTION_SETUP_RESPONSE)
1991         hostapd_tx_and_status(hapd, msg)
1992
1993         # FST Response dropped: invalid STIE (EID)
1994         dialog_token = 1
1995         status_code = 0
1996         id = 0
1997         msg['payload'] = struct.pack("<BBBBBBLBBBBBBB", ACTION_CATEG_FST,
1998                                      FST_ACTION_SETUP_RESPONSE, dialog_token,
1999                                      status_code,
2000                                      163, 11, 0, 0, id, 0, 0, 0, 0, 0)
2001         hostapd_tx_and_status(hapd, msg)
2002
2003         # FST Response dropped: invalid STIE (Len)
2004         dialog_token = 1
2005         status_code = 0
2006         id = 0
2007         msg['payload'] = struct.pack("<BBBBBBLBBBBBBB", ACTION_CATEG_FST,
2008                                      FST_ACTION_SETUP_RESPONSE, dialog_token,
2009                                      status_code,
2010                                      164, 10, 0, 0, id, 0, 0, 0, 0, 0)
2011         hostapd_tx_and_status(hapd, msg)
2012
2013         # FST Response dropped due to wrong dialog token
2014         dialog_token = 123
2015         status_code = 0
2016         id = 0
2017         msg['payload'] = struct.pack("<BBBBBBLBBBBBBB", ACTION_CATEG_FST,
2018                                      FST_ACTION_SETUP_RESPONSE, dialog_token,
2019                                      status_code,
2020                                      164, 11, 0, 0, id, 0, 0, 0, 0, 0)
2021         hostapd_tx_and_status(hapd, msg)
2022
2023         # FST Response dropped due to wrong FST Session ID
2024         dialog_token = 1
2025         status_code = 0
2026         id = 1
2027         msg['payload'] = struct.pack("<BBBBBBLBBBBBBB", ACTION_CATEG_FST,
2028                                      FST_ACTION_SETUP_RESPONSE, dialog_token,
2029                                      status_code,
2030                                      164, 11, int(sid) + 123456,
2031                                      0, id, 0, 0, 0, 0, 0)
2032         hostapd_tx_and_status(hapd, msg)
2033
2034         # FST Response with non-zero status code
2035         dialog_token = 1
2036         status_code = 1
2037         id = 1
2038         msg['payload'] = struct.pack("<BBBBBBLBBBBBBB", ACTION_CATEG_FST,
2039                                      FST_ACTION_SETUP_RESPONSE, dialog_token,
2040                                      status_code,
2041                                      164, 11, int(sid), 0, id, 0, 0, 0, 0, 0)
2042         hostapd_tx_and_status(hapd, msg)
2043     finally:
2044         fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2045         fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2046
2047 def test_fst_ack_response_proto(dev, apdev, test_params):
2048     """FST protocol testing for Ack Response"""
2049     ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
2050     try:
2051         fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2052         hapd = ap2.get_instance()
2053         sta = sta2.get_instance()
2054         dst = sta.own_addr()
2055         src = apdev[1]['bssid']
2056
2057         sta1.add_peer(ap1, None, sta2.get_actual_peer_addr())
2058         sta1.set_fst_parameters(llt='0')
2059         sid = sta1.add_session()
2060         sta1.configure_session(sid, sta2.ifname())
2061
2062         s = sta1.grequest("FST-MANAGER SESSION_INITIATE "+ sid)
2063         if not s.startswith('OK'):
2064             raise Exception("Cannot initiate fst session: %s" % s)
2065         ev = sta1.peer_obj.wait_gevent([ "FST-EVENT-SESSION" ], timeout=5)
2066         if ev is None:
2067             raise Exception("No FST-EVENT-SESSION received")
2068         event = fst_module_aux.parse_fst_session_event(ev)
2069         if event == None:
2070             raise Exception("Unrecognized FST event: " % ev)
2071         if event['type'] != 'EVENT_FST_SETUP':
2072             raise Exception("Expected FST_SETUP event, got: " + event['type'])
2073         ev = sta1.peer_obj.wait_gevent(["FST-EVENT-SESSION"], timeout=5)
2074         if ev is None:
2075             raise Exception("No FST-EVENT-SESSION received")
2076         event = fst_module_aux.parse_fst_session_event(ev)
2077         if event == None:
2078             raise Exception("Unrecognized FST event: " % ev)
2079         if event['type'] != 'EVENT_FST_SESSION_STATE':
2080             raise Exception("Expected EVENT_FST_SESSION_STATE event, got: " + event['type'])
2081         if event['new_state'] != "SETUP_COMPLETION":
2082             raise Exception("Expected new state SETUP_COMPLETION, got: " + event['new_state'])
2083
2084         hapd.set("ext_mgmt_frame_handling", "1")
2085         s = sta1.peer_obj.grequest("FST-MANAGER SESSION_RESPOND "+ event['id'] + " accept")
2086         if not s.startswith('OK'):
2087             raise Exception("Error session_respond: %s" % s)
2088         req = hapd.mgmt_rx()
2089         if req is None:
2090             raise Exception("No Ack Request seen")
2091         msg = {}
2092         msg['fc'] = MGMT_SUBTYPE_ACTION << 4
2093         msg['da'] = dst
2094         msg['sa'] = src
2095         msg['bssid'] = src
2096
2097         # Too short FST Ack Response dropped
2098         msg['payload'] = struct.pack("<BB", ACTION_CATEG_FST,
2099                                      FST_ACTION_ACK_RESPONSE)
2100         hapd.mgmt_tx(msg)
2101         ev = hapd.wait_event([ "MGMT-TX-STATUS" ], timeout=1)
2102         if ev is None or "ok=1" not in ev:
2103             raise Exception("No ACK")
2104
2105         # Ack Response for wrong FSt Setup ID
2106         msg['payload'] = struct.pack("<BBBL", ACTION_CATEG_FST,
2107                                      FST_ACTION_ACK_RESPONSE,
2108                                      0, int(sid) + 123456)
2109         hostapd_tx_and_status(hapd, msg)
2110     finally:
2111         fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2112         fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2113
2114 def test_fst_ap_config_oom(dev, apdev, test_params):
2115     """FST AP configuration and OOM"""
2116     ap1 = fst_module_aux.FstAP(apdev[0]['ifname'], 'fst_11a', 'a',
2117                                fst_test_common.fst_test_def_chan_a,
2118                                fst_test_common.fst_test_def_group,
2119                                fst_test_common.fst_test_def_prio_low)
2120     hapd = ap1.start(return_early=True)
2121     with alloc_fail(hapd, 1, "fst_group_create"):
2122         res = ap1.grequest("FST-ATTACH %s %s" % (ap1.iface, ap1.fst_group))
2123         if not res.startswith("FAIL"):
2124             raise Exception("FST-ATTACH succeeded unexpectedly")
2125
2126     with alloc_fail(hapd, 1, "fst_iface_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_group_create_mb_ie"):
2132         res = ap1.grequest("FST-ATTACH %s %s" % (ap1.iface, ap1.fst_group))
2133         # This is allowed to complete currently
2134
2135     ap1.stop()
2136
2137 def test_fst_send_oom(dev, apdev, test_params):
2138     """FST send action OOM"""
2139     ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
2140     try:
2141         fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2142         hapd = ap1.get_instance()
2143         sta = sta1.get_instance()
2144         dst = sta.own_addr()
2145         src = apdev[0]['bssid']
2146
2147         # Create session
2148         initiator = ap1
2149         responder = sta1
2150         new_iface = ap2.ifname()
2151         new_peer_addr = ap2.get_actual_peer_addr()
2152         resp_newif = sta2.ifname()
2153         peeraddr = None
2154         initiator.add_peer(responder, peeraddr, new_peer_addr)
2155         sid = initiator.add_session()
2156         initiator.configure_session(sid, new_iface)
2157         with alloc_fail(hapd, 1, "fst_session_send_action"):
2158             res = initiator.grequest("FST-MANAGER SESSION_INITIATE " + sid)
2159             if not res.startswith("FAIL"):
2160                 raise Exception("Unexpected SESSION_INITIATE result")
2161
2162         res = initiator.grequest("FST-MANAGER SESSION_INITIATE " + sid)
2163         if not res.startswith("OK"):
2164             raise Exception("SESSION_INITIATE failed")
2165
2166         tests = [ "", "foo", sid, sid + " foo", sid + " foo=bar" ]
2167         for t in tests:
2168             res = initiator.grequest("FST-MANAGER SESSION_SET " + t)
2169             if not res.startswith("FAIL"):
2170                 raise Exception("Invalid SESSION_SET accepted")
2171
2172         with alloc_fail(hapd, 1, "fst_session_send_action"):
2173             res = initiator.grequest("FST-MANAGER SESSION_TEARDOWN " + sid)
2174             if not res.startswith("FAIL"):
2175                 raise Exception("Unexpected SESSION_TEARDOWN result")
2176     finally:
2177         fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2178         fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2179
2180 def test_fst_session_oom(dev, apdev, test_params):
2181     """FST session create OOM"""
2182     ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
2183     try:
2184         fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2185         hapd = ap1.get_instance()
2186         sta = sta1.get_instance()
2187         dst = sta.own_addr()
2188         src = apdev[0]['bssid']
2189
2190         # Create session
2191         initiator = ap1
2192         responder = sta1
2193         new_iface = ap2.ifname()
2194         new_peer_addr = ap2.get_actual_peer_addr()
2195         resp_newif = sta2.ifname()
2196         peeraddr = None
2197         initiator.add_peer(responder, peeraddr, new_peer_addr)
2198         with alloc_fail(hapd, 1, "fst_session_create"):
2199             sid = initiator.grequest("FST-MANAGER SESSION_ADD " + initiator.fst_group)
2200             if not sid.startswith("FAIL"):
2201                 raise Exception("Unexpected SESSION_ADD success")
2202         sid = initiator.add_session()
2203         initiator.configure_session(sid, new_iface)
2204         with alloc_fail(sta, 1, "fst_session_create"):
2205             res = initiator.grequest("FST-MANAGER SESSION_INITIATE " + sid)
2206             if not res.startswith("OK"):
2207                 raise Exception("Unexpected SESSION_INITIATE result")
2208     finally:
2209         fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2210         fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2211
2212 def test_fst_attach_zero_llt(dev, apdev):
2213     """FST attach with llt=0"""
2214     sta1 = fst_module_aux.FstSTA('wlan5', fst_test_common.fst_test_def_group,
2215                                  "100", "0")
2216     sta1.start()
2217     sta1.stop()
2218
2219 def test_fst_session_respond_fail(dev, apdev, test_params):
2220     """FST-MANAGER SESSION_RESPOND failure"""
2221     ap1, ap2, sta1, sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
2222     try:
2223         fst_module_aux.connect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2224         sta1.add_peer(ap1, None, sta2.get_actual_peer_addr())
2225         sid = sta1.add_session()
2226         sta1.configure_session(sid, sta2.ifname())
2227         sta1.send_session_setup_request(sid)
2228         sta1.wait_for_session_event(5, [], ["EVENT_FST_SESSION_STATE"])
2229         ev = ap1.wait_for_session_event(5, [], ['EVENT_FST_SETUP'])
2230         if not 'id' in ev:
2231             raise Exception("No session id in FST setup event")
2232         # Disconnect STA to make SESSION_RESPOND fail due to no peer found
2233         sta = sta1.get_instance()
2234         sta.request("DISCONNECT")
2235         sta.wait_disconnected()
2236         req = "FST-MANAGER SESSION_RESPOND %s reject" % ev['id']
2237         s = ap1.grequest(req)
2238         if not s.startswith("FAIL"):
2239             raise Exception("SESSION_RESPOND succeeded unexpectedly")
2240     finally:
2241         fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2242         fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
2243
2244 def fst_session_set(dev, sid, param, value):
2245     cmd = "FST-MANAGER SESSION_SET %s %s=%s" % (sid, param, value)
2246     if "OK" not in dev.global_request(cmd):
2247         raise Exception(cmd + " failed")
2248
2249 def fst_attach_ap(dev, ifname, group):
2250     cmd = "FST-ATTACH %s %s" % (ifname, group)
2251     if "OK" not in dev.request(cmd):
2252         raise Exception("FST-ATTACH (AP) failed")
2253     ev = dev.wait_event(['FST-EVENT-IFACE'], timeout=5)
2254     if ev is None:
2255         raise Exception("No FST-EVENT-IFACE attached (AP)")
2256     for t in [ "attached", "ifname=" + ifname, "group=" + group ]:
2257         if t not in ev:
2258             raise Exception("Unexpected FST-EVENT-IFACE data (AP): " + ev)
2259
2260 def fst_attach_sta(dev, ifname, group):
2261     if "OK" not in dev.global_request("FST-ATTACH %s %s" % (ifname, group)):
2262         raise Exception("FST-ATTACH (STA) failed")
2263     ev = dev.wait_global_event(['FST-EVENT-IFACE'], timeout=5)
2264     if ev is None:
2265         raise Exception("No FST-EVENT-IFACE attached (STA)")
2266     for t in [ "attached", "ifname=" + ifname, "group=" + group ]:
2267         if t not in ev:
2268             raise Exception("Unexpected FST-EVENT-IFACE data (STA): " + ev)
2269
2270 def fst_detach_ap(dev, ifname, group):
2271     if "OK" not in dev.request("FST-DETACH " + ifname):
2272         raise Exception("FST-DETACH (AP) failed for " + ifname)
2273     ev = dev.wait_event(['FST-EVENT-IFACE'], timeout=5)
2274     if ev is None:
2275         raise Exception("No FST-EVENT-IFACE detached (AP) for " + ifname)
2276     for t in [ "detached", "ifname=" + ifname, "group=" + group ]:
2277         if t not in ev:
2278             raise Exception("Unexpected FST-EVENT-IFACE data (AP): " + ev)
2279
2280 def fst_detach_sta(dev, ifname, group):
2281     dev.dump_monitor()
2282     if "OK" not in dev.global_request("FST-DETACH " + ifname):
2283         raise Exception("FST-DETACH (STA) failed for " + ifname)
2284     ev = dev.wait_global_event(['FST-EVENT-IFACE'], timeout=5)
2285     if ev is None:
2286         raise Exception("No FST-EVENT-IFACE detached (STA) 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 (STA): " + ev)
2290
2291 def fst_wait_event_peer_ap(dev, event, ifname, addr):
2292     ev = dev.wait_event(['FST-EVENT-PEER'], timeout=5)
2293     if ev is None:
2294         raise Exception("No FST-EVENT-PEER connected (AP)")
2295     for t in [ " " + event + " ", "ifname=" + ifname, "peer_addr=" + addr ]:
2296         if t not in ev:
2297             raise Exception("Unexpected FST-EVENT-PEER data (AP): " + ev)
2298
2299 def fst_wait_event_peer_sta(dev, event, ifname, addr):
2300     ev = dev.wait_global_event(['FST-EVENT-PEER'], timeout=5)
2301     if ev is None:
2302         raise Exception("No FST-EVENT-PEER connected (STA)")
2303     for t in [ " " + event + " ", "ifname=" + ifname, "peer_addr=" + addr ]:
2304         if t not in ev:
2305             raise Exception("Unexpected FST-EVENT-PEER data (STA): " + ev)
2306
2307 def fst_setup_req(dev, hglobal, freq, dst, req, stie, mbie=""):
2308     act = req + stie + mbie
2309     dev.request("MGMT_TX %s %s freq=%d action=%s" % (dst, dst, freq, act))
2310     ev = dev.wait_event(['MGMT-TX-STATUS'], timeout=5)
2311     if ev is None or "result=SUCCESS" not in ev:
2312         raise Exception("FST Action frame not ACKed")
2313
2314     while True:
2315         ev = hglobal.wait_event(['FST-EVENT-SESSION'], timeout=5)
2316         if ev is None:
2317             raise Exception("No FST-EVENT-SESSION (AP)")
2318         if "new_state=SETUP_COMPLETION" in ev:
2319             break
2320
2321 def test_fst_test_setup(dev, apdev, test_params):
2322     """FST setup using separate commands"""
2323     try:
2324         _test_fst_test_setup(dev, apdev, test_params)
2325     finally:
2326         subprocess.call(['iw', 'reg', 'set', '00'])
2327         dev[0].flush_scan_cache()
2328         dev[1].flush_scan_cache()
2329
2330 def _test_fst_test_setup(dev, apdev, test_params):
2331     hglobal = hostapd.HostapdGlobal()
2332     if "OK" not in hglobal.request("FST-MANAGER TEST_REQUEST IS_SUPPORTED"):
2333         raise HwsimSkip("No FST testing support")
2334
2335     params = { "ssid": "fst_11a", "hw_mode": "a", "channel": "36",
2336                "country_code": "US" }
2337     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2338
2339     group = "fstg0"
2340     fst_attach_ap(hglobal, apdev[0]['ifname'], group)
2341
2342     cmd = "FST-ATTACH %s %s" % (apdev[0]['ifname'], group)
2343     if "FAIL" not in hglobal.request(cmd):
2344         raise Exception("Duplicated FST-ATTACH (AP) accepted")
2345
2346     params = { "ssid": "fst_11g", "hw_mode": "g", "channel": "1",
2347                "country_code": "US" }
2348     hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
2349     fst_attach_ap(hglobal, apdev[1]['ifname'], group)
2350
2351     sgroup = "fstg1"
2352     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
2353     wpas.interface_add("wlan5")
2354     fst_attach_sta(wpas, wpas.ifname, sgroup)
2355
2356     wpas.interface_add("wlan6", set_ifname=False)
2357     wpas2 = WpaSupplicant(ifname="wlan6")
2358     fst_attach_sta(wpas, wpas2.ifname, sgroup)
2359
2360     wpas.connect("fst_11a", key_mgmt="NONE", scan_freq="5180",
2361                  wait_connect=False)
2362     wpas.wait_connected()
2363
2364     fst_wait_event_peer_sta(wpas, "connected", wpas.ifname, apdev[0]['bssid'])
2365     fst_wait_event_peer_ap(hglobal, "connected", apdev[0]['ifname'],
2366                            wpas.own_addr())
2367
2368     wpas2.connect("fst_11g", key_mgmt="NONE", scan_freq="2412",
2369                   wait_connect=False)
2370     wpas2.wait_connected()
2371
2372     fst_wait_event_peer_sta(wpas, "connected", wpas2.ifname, apdev[1]['bssid'])
2373     fst_wait_event_peer_ap(hglobal, "connected", apdev[1]['ifname'],
2374                            wpas2.own_addr())
2375
2376     sid = wpas.global_request("FST-MANAGER SESSION_ADD " + sgroup).strip()
2377     if "FAIL" in sid:
2378         raise Exception("FST-MANAGER SESSION_ADD (STA) failed")
2379
2380     fst_session_set(wpas, sid, "old_ifname", wpas.ifname)
2381     fst_session_set(wpas, sid, "old_peer_addr", apdev[0]['bssid'])
2382     fst_session_set(wpas, sid, "new_ifname", wpas2.ifname)
2383     fst_session_set(wpas, sid, "new_peer_addr", apdev[1]['bssid'])
2384
2385     if "OK" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid):
2386         raise Exception("FST-MANAGER SESSION_INITIATE failed")
2387
2388     while True:
2389         ev = hglobal.wait_event(['FST-EVENT-SESSION'], timeout=5)
2390         if ev is None:
2391             raise Exception("No FST-EVENT-SESSION (AP)")
2392         if "new_state=SETUP_COMPLETION" in ev:
2393             f = re.search("session_id=(\d+)", ev)
2394             if f is None:
2395                 raise Exception("No session_id in FST-EVENT-SESSION")
2396             sid_ap = f.group(1)
2397             cmd = "FST-MANAGER SESSION_RESPOND %s accept" % sid_ap
2398             if "OK" not in hglobal.request(cmd):
2399                 raise Exception("FST-MANAGER SESSION_RESPOND failed on AP")
2400             break
2401
2402     ev = wpas.wait_global_event(["FST-EVENT-SESSION"], timeout=5)
2403     if ev is None:
2404         raise Exception("No FST-EVENT-SESSION")
2405     if "new_state=SETUP_COMPLETION" not in ev:
2406         raise Exception("Unexpected FST-EVENT-SESSION data: " + ev)
2407
2408     ev = wpas.wait_global_event(["FST-EVENT-SESSION"], timeout=5)
2409     if ev is None:
2410         raise Exception("No FST-EVENT-SESSION")
2411     if "event_type=EVENT_FST_ESTABLISHED" not in ev:
2412         raise Exception("Unexpected FST-EVENT-SESSION data: " + ev)
2413
2414     cmd = "FST-MANAGER SESSION_REMOVE " + sid
2415     if "OK" not in wpas.global_request(cmd):
2416         raise Exception("FST-MANAGER SESSION_REMOVE failed")
2417     ev = wpas.wait_global_event(["FST-EVENT-SESSION"], timeout=5)
2418     if ev is None:
2419         raise Exception("No FST-EVENT-SESSION")
2420     if "new_state=INITIAL" not in ev:
2421         raise Exception("Unexpected FST-EVENT-SESSION data (STA): " + ev)
2422
2423     ev = hglobal.wait_event(['FST-EVENT-SESSION'], timeout=5)
2424     if ev is None:
2425         raise Exception("No FST-EVENT-SESSION (AP)")
2426     if "new_state=INITIAL" not in ev:
2427         raise Exception("Unexpected FST-EVENT-SESSION data (AP): " + ev)
2428
2429     if "FAIL" not in wpas.global_request(cmd):
2430         raise Exception("Duplicated FST-MANAGER SESSION_REMOVE accepted")
2431
2432     hglobal.request("FST-MANAGER SESSION_REMOVE " + sid_ap)
2433
2434     wpas.request("DISCONNECT")
2435     wpas.wait_disconnected()
2436     fst_wait_event_peer_sta(wpas, "disconnected", wpas.ifname,
2437                             apdev[0]['bssid'])
2438     fst_wait_event_peer_ap(hglobal, "disconnected", apdev[0]['ifname'],
2439                            wpas.own_addr())
2440
2441     wpas2.request("DISCONNECT")
2442     wpas2.wait_disconnected()
2443     fst_wait_event_peer_sta(wpas, "disconnected", wpas2.ifname,
2444                             apdev[1]['bssid'])
2445     fst_wait_event_peer_ap(hglobal, "disconnected", apdev[1]['ifname'],
2446                            wpas2.own_addr())
2447
2448     fst_detach_ap(hglobal, apdev[0]['ifname'], group)
2449     if "FAIL" not in hglobal.request("FST-DETACH " + apdev[0]['ifname']):
2450         raise Exception("Duplicated FST-DETACH (AP) accepted")
2451     hapd.disable()
2452
2453     fst_detach_ap(hglobal, apdev[1]['ifname'], group)
2454     hapd2.disable()
2455
2456     fst_detach_sta(wpas, wpas.ifname, sgroup)
2457     fst_detach_sta(wpas, wpas2.ifname, sgroup)
2458
2459 def test_fst_setup_mbie_diff(dev, apdev, test_params):
2460     """FST setup and different MBIE in FST Setup Request"""
2461     try:
2462         _test_fst_setup_mbie_diff(dev, apdev, test_params)
2463     finally:
2464         subprocess.call(['iw', 'reg', 'set', '00'])
2465         dev[0].flush_scan_cache()
2466         dev[1].flush_scan_cache()
2467
2468 def _test_fst_setup_mbie_diff(dev, apdev, test_params):
2469     hglobal = hostapd.HostapdGlobal()
2470     if "OK" not in hglobal.request("FST-MANAGER TEST_REQUEST IS_SUPPORTED"):
2471         raise HwsimSkip("No FST testing support")
2472
2473     params = { "ssid": "fst_11a", "hw_mode": "a", "channel": "36",
2474                "country_code": "US" }
2475     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2476
2477     group = "fstg0"
2478     fst_attach_ap(hglobal, apdev[0]['ifname'], group)
2479
2480     cmd = "FST-ATTACH %s %s" % (apdev[0]['ifname'], group)
2481     if "FAIL" not in hglobal.request(cmd):
2482         raise Exception("Duplicated FST-ATTACH (AP) accepted")
2483
2484     params = { "ssid": "fst_11g", "hw_mode": "g", "channel": "1",
2485                "country_code": "US" }
2486     hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
2487     fst_attach_ap(hglobal, apdev[1]['ifname'], group)
2488
2489     sgroup = "fstg1"
2490     wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
2491     wpas.interface_add("wlan5")
2492     fst_attach_sta(wpas, wpas.ifname, sgroup)
2493
2494     wpas.interface_add("wlan6", set_ifname=False)
2495     wpas2 = WpaSupplicant(ifname="wlan6")
2496     fst_attach_sta(wpas, wpas2.ifname, sgroup)
2497
2498     wpas.connect("fst_11a", key_mgmt="NONE", scan_freq="5180",
2499                  wait_connect=False)
2500     wpas.wait_connected()
2501
2502     fst_wait_event_peer_sta(wpas, "connected", wpas.ifname, apdev[0]['bssid'])
2503     fst_wait_event_peer_ap(hglobal, "connected", apdev[0]['ifname'],
2504                            wpas.own_addr())
2505
2506     wpas2.connect("fst_11g", key_mgmt="NONE", scan_freq="2412",
2507                   wait_connect=False)
2508     wpas2.wait_connected()
2509
2510     fst_wait_event_peer_sta(wpas, "connected", wpas2.ifname, apdev[1]['bssid'])
2511     fst_wait_event_peer_ap(hglobal, "connected", apdev[1]['ifname'],
2512                            wpas2.own_addr())
2513
2514     # FST Setup Request: Category, FST Action, Dialog Token (non-zero),
2515     # LLT (32 bits, see 10.32), Session Transition (see 8.4.2.147),
2516     # Multi-band element (optional, see 8.4.2.140)
2517
2518     # Session Transition: EID, Len, FSTS ID(4), Session Control,
2519     # New Band (Band ID, Setup, Operation), Old Band (Band ID, Setup, Operation)
2520
2521     # Multi-band element: EID, Len, Multi-band Control, Band ID,
2522     # Operating Class, Channel Number, BSSID (6), Beacon Interval (2),
2523     # TSF Offset (8), Multi-band Connection Capability, FSTSessionTimeOut,
2524     # STA MAC Address (6, optional), Pairwise Cipher Suite Count (2, optional),
2525     # Pairwise Cipher Suite List (4xm, optional)
2526
2527     # MBIE with the non-matching STA MAC Address:
2528     req = "1200011a060000"
2529     stie = "a40b0100000000020001040001"
2530     mbie = "9e1c0c0200010200000004000000000000000000000000ff0200000006ff"
2531     fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie, mbie)
2532
2533     # MBIE without the STA MAC Address:
2534     req = "1200011a060000"
2535     stie = "a40b0100000000020001040001"
2536     mbie = "9e16040200010200000004000000000000000000000000ff"
2537     fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie, mbie)
2538
2539     # MBIE with unsupported STA Role:
2540     req = "1200011a060000"
2541     stie = "a40b0100000000020001040001"
2542     mbie = "9e16070200010200000004000000000000000000000000ff"
2543     fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie, mbie)
2544
2545     # MBIE with unsupported Band ID:
2546     req = "1200011a060000"
2547     stie = "a40b0100000000020001040001"
2548     mbie = "9e1604ff00010200000004000000000000000000000000ff"
2549     fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie, mbie)
2550
2551     # FST Setup Request without MBIE (different FSTS ID):
2552     req = "1200011a060000"
2553     stie = "a40b0200000000020001040001"
2554     fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie)