tests: Additional FST Setup test coverage
authorJouni Malinen <j@w1.fi>
Sat, 25 Jul 2015 21:33:55 +0000 (00:33 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 26 Jul 2015 15:12:08 +0000 (18:12 +0300)
This adds a test case that goes through session initialization through
separate commands that can be modified more easily for special case. The
first such special case is using special FST Setup Request frames with
non-standard MBIE contents to hit different code paths for finding the
interface.

Signed-off-by: Jouni Malinen <j@w1.fi>
tests/hwsim/test_fst_module.py

index 2814041..4a3f2c2 100644 (file)
@@ -10,13 +10,15 @@ import struct
 import subprocess
 import time
 import os
+import re
 
 import hwsim_utils
 from hwsim import HWSimRadio
 import hostapd
+from wpasupplicant import WpaSupplicant
 import fst_test_common
 import fst_module_aux
-from utils import alloc_fail
+from utils import alloc_fail, HwsimSkip
 
 #enum - bad parameter types
 bad_param_none = 0
@@ -2238,3 +2240,315 @@ def test_fst_session_respond_fail(dev, apdev, test_params):
     finally:
         fst_module_aux.disconnect_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
         fst_module_aux.stop_two_ap_sta_pairs(ap1, ap2, sta1, sta2)
+
+def fst_session_set(dev, sid, param, value):
+    cmd = "FST-MANAGER SESSION_SET %s %s=%s" % (sid, param, value)
+    if "OK" not in dev.global_request(cmd):
+        raise Exception(cmd + " failed")
+
+def fst_attach_ap(dev, ifname, group):
+    cmd = "FST-ATTACH %s %s" % (ifname, group)
+    if "OK" not in dev.request(cmd):
+        raise Exception("FST-ATTACH (AP) failed")
+    ev = dev.wait_event(['FST-EVENT-IFACE'], timeout=5)
+    if ev is None:
+        raise Exception("No FST-EVENT-IFACE attached (AP)")
+    for t in [ "attached", "ifname=" + ifname, "group=" + group ]:
+        if t not in ev:
+            raise Exception("Unexpected FST-EVENT-IFACE data (AP): " + ev)
+
+def fst_attach_sta(dev, ifname, group):
+    if "OK" not in dev.global_request("FST-ATTACH %s %s" % (ifname, group)):
+        raise Exception("FST-ATTACH (STA) failed")
+    ev = dev.wait_global_event(['FST-EVENT-IFACE'], timeout=5)
+    if ev is None:
+        raise Exception("No FST-EVENT-IFACE attached (STA)")
+    for t in [ "attached", "ifname=" + ifname, "group=" + group ]:
+        if t not in ev:
+            raise Exception("Unexpected FST-EVENT-IFACE data (STA): " + ev)
+
+def fst_detach_ap(dev, ifname, group):
+    if "OK" not in dev.request("FST-DETACH " + ifname):
+        raise Exception("FST-DETACH (AP) failed for " + ifname)
+    ev = dev.wait_event(['FST-EVENT-IFACE'], timeout=5)
+    if ev is None:
+        raise Exception("No FST-EVENT-IFACE detached (AP) for " + ifname)
+    for t in [ "detached", "ifname=" + ifname, "group=" + group ]:
+        if t not in ev:
+            raise Exception("Unexpected FST-EVENT-IFACE data (AP): " + ev)
+
+def fst_detach_sta(dev, ifname, group):
+    dev.dump_monitor()
+    if "OK" not in dev.global_request("FST-DETACH " + ifname):
+        raise Exception("FST-DETACH (STA) failed for " + ifname)
+    ev = dev.wait_global_event(['FST-EVENT-IFACE'], timeout=5)
+    if ev is None:
+        raise Exception("No FST-EVENT-IFACE detached (STA) for " + ifname)
+    for t in [ "detached", "ifname=" + ifname, "group=" + group ]:
+        if t not in ev:
+            raise Exception("Unexpected FST-EVENT-IFACE data (STA): " + ev)
+
+def fst_wait_event_peer_ap(dev, event, ifname, addr):
+    ev = dev.wait_event(['FST-EVENT-PEER'], timeout=5)
+    if ev is None:
+        raise Exception("No FST-EVENT-PEER connected (AP)")
+    for t in [ " " + event + " ", "ifname=" + ifname, "peer_addr=" + addr ]:
+        if t not in ev:
+            raise Exception("Unexpected FST-EVENT-PEER data (AP): " + ev)
+
+def fst_wait_event_peer_sta(dev, event, ifname, addr):
+    ev = dev.wait_global_event(['FST-EVENT-PEER'], timeout=5)
+    if ev is None:
+        raise Exception("No FST-EVENT-PEER connected (STA)")
+    for t in [ " " + event + " ", "ifname=" + ifname, "peer_addr=" + addr ]:
+        if t not in ev:
+            raise Exception("Unexpected FST-EVENT-PEER data (STA): " + ev)
+
+def fst_setup_req(dev, hglobal, freq, dst, req, stie, mbie=""):
+    act = req + stie + mbie
+    dev.request("MGMT_TX %s %s freq=%d action=%s" % (dst, dst, freq, act))
+    ev = dev.wait_event(['MGMT-TX-STATUS'], timeout=5)
+    if ev is None or "result=SUCCESS" not in ev:
+        raise Exception("FST Action frame not ACKed")
+
+    while True:
+        ev = hglobal.wait_event(['FST-EVENT-SESSION'], timeout=5)
+        if ev is None:
+            raise Exception("No FST-EVENT-SESSION (AP)")
+        if "new_state=SETUP_COMPLETION" in ev:
+            break
+
+def test_fst_test_setup(dev, apdev, test_params):
+    """FST setup using separate commands"""
+    try:
+        _test_fst_test_setup(dev, apdev, test_params)
+    finally:
+        subprocess.call(['iw', 'reg', 'set', '00'])
+        dev[0].flush_scan_cache()
+        dev[1].flush_scan_cache()
+
+def _test_fst_test_setup(dev, apdev, test_params):
+    hglobal = hostapd.HostapdGlobal()
+    if "OK" not in hglobal.request("FST-MANAGER TEST_REQUEST IS_SUPPORTED"):
+        raise HwsimSkip("No FST testing support")
+
+    params = { "ssid": "fst_11a", "hw_mode": "a", "channel": "36",
+               "country_code": "US" }
+    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+
+    group = "fstg0"
+    fst_attach_ap(hglobal, apdev[0]['ifname'], group)
+
+    cmd = "FST-ATTACH %s %s" % (apdev[0]['ifname'], group)
+    if "FAIL" not in hglobal.request(cmd):
+        raise Exception("Duplicated FST-ATTACH (AP) accepted")
+
+    params = { "ssid": "fst_11g", "hw_mode": "g", "channel": "1",
+               "country_code": "US" }
+    hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+    fst_attach_ap(hglobal, apdev[1]['ifname'], group)
+
+    sgroup = "fstg1"
+    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+    wpas.interface_add("wlan5")
+    fst_attach_sta(wpas, wpas.ifname, sgroup)
+
+    wpas.interface_add("wlan6", set_ifname=False)
+    wpas2 = WpaSupplicant(ifname="wlan6")
+    fst_attach_sta(wpas, wpas2.ifname, sgroup)
+
+    wpas.connect("fst_11a", key_mgmt="NONE", scan_freq="5180",
+                 wait_connect=False)
+    wpas.wait_connected()
+
+    fst_wait_event_peer_sta(wpas, "connected", wpas.ifname, apdev[0]['bssid'])
+    fst_wait_event_peer_ap(hglobal, "connected", apdev[0]['ifname'],
+                           wpas.own_addr())
+
+    wpas2.connect("fst_11g", key_mgmt="NONE", scan_freq="2412",
+                  wait_connect=False)
+    wpas2.wait_connected()
+
+    fst_wait_event_peer_sta(wpas, "connected", wpas2.ifname, apdev[1]['bssid'])
+    fst_wait_event_peer_ap(hglobal, "connected", apdev[1]['ifname'],
+                           wpas2.own_addr())
+
+    sid = wpas.global_request("FST-MANAGER SESSION_ADD " + sgroup).strip()
+    if "FAIL" in sid:
+        raise Exception("FST-MANAGER SESSION_ADD (STA) failed")
+
+    fst_session_set(wpas, sid, "old_ifname", wpas.ifname)
+    fst_session_set(wpas, sid, "old_peer_addr", apdev[0]['bssid'])
+    fst_session_set(wpas, sid, "new_ifname", wpas2.ifname)
+    fst_session_set(wpas, sid, "new_peer_addr", apdev[1]['bssid'])
+
+    if "OK" not in wpas.global_request("FST-MANAGER SESSION_INITIATE " + sid):
+        raise Exception("FST-MANAGER SESSION_INITIATE failed")
+
+    while True:
+        ev = hglobal.wait_event(['FST-EVENT-SESSION'], timeout=5)
+        if ev is None:
+            raise Exception("No FST-EVENT-SESSION (AP)")
+        if "new_state=SETUP_COMPLETION" in ev:
+            f = re.search("session_id=(\d+)", ev)
+            if f is None:
+                raise Exception("No session_id in FST-EVENT-SESSION")
+            sid_ap = f.group(1)
+            cmd = "FST-MANAGER SESSION_RESPOND %s accept" % sid_ap
+            if "OK" not in hglobal.request(cmd):
+                raise Exception("FST-MANAGER SESSION_RESPOND failed on AP")
+            break
+
+    ev = wpas.wait_global_event(["FST-EVENT-SESSION"], timeout=5)
+    if ev is None:
+        raise Exception("No FST-EVENT-SESSION")
+    if "new_state=SETUP_COMPLETION" not in ev:
+        raise Exception("Unexpected FST-EVENT-SESSION data: " + ev)
+
+    ev = wpas.wait_global_event(["FST-EVENT-SESSION"], timeout=5)
+    if ev is None:
+        raise Exception("No FST-EVENT-SESSION")
+    if "event_type=EVENT_FST_ESTABLISHED" not in ev:
+        raise Exception("Unexpected FST-EVENT-SESSION data: " + ev)
+
+    cmd = "FST-MANAGER SESSION_REMOVE " + sid
+    if "OK" not in wpas.global_request(cmd):
+        raise Exception("FST-MANAGER SESSION_REMOVE failed")
+    ev = wpas.wait_global_event(["FST-EVENT-SESSION"], timeout=5)
+    if ev is None:
+        raise Exception("No FST-EVENT-SESSION")
+    if "new_state=INITIAL" not in ev:
+        raise Exception("Unexpected FST-EVENT-SESSION data (STA): " + ev)
+
+    ev = hglobal.wait_event(['FST-EVENT-SESSION'], timeout=5)
+    if ev is None:
+        raise Exception("No FST-EVENT-SESSION (AP)")
+    if "new_state=INITIAL" not in ev:
+        raise Exception("Unexpected FST-EVENT-SESSION data (AP): " + ev)
+
+    if "FAIL" not in wpas.global_request(cmd):
+        raise Exception("Duplicated FST-MANAGER SESSION_REMOVE accepted")
+
+    hglobal.request("FST-MANAGER SESSION_REMOVE " + sid_ap)
+
+    wpas.request("DISCONNECT")
+    wpas.wait_disconnected()
+    fst_wait_event_peer_sta(wpas, "disconnected", wpas.ifname,
+                            apdev[0]['bssid'])
+    fst_wait_event_peer_ap(hglobal, "disconnected", apdev[0]['ifname'],
+                           wpas.own_addr())
+
+    wpas2.request("DISCONNECT")
+    wpas2.wait_disconnected()
+    fst_wait_event_peer_sta(wpas, "disconnected", wpas2.ifname,
+                            apdev[1]['bssid'])
+    fst_wait_event_peer_ap(hglobal, "disconnected", apdev[1]['ifname'],
+                           wpas2.own_addr())
+
+    fst_detach_ap(hglobal, apdev[0]['ifname'], group)
+    if "FAIL" not in hglobal.request("FST-DETACH " + apdev[0]['ifname']):
+        raise Exception("Duplicated FST-DETACH (AP) accepted")
+    hapd.disable()
+
+    fst_detach_ap(hglobal, apdev[1]['ifname'], group)
+    hapd2.disable()
+
+    fst_detach_sta(wpas, wpas.ifname, sgroup)
+    fst_detach_sta(wpas, wpas2.ifname, sgroup)
+
+def test_fst_setup_mbie_diff(dev, apdev, test_params):
+    """FST setup and different MBIE in FST Setup Request"""
+    try:
+        _test_fst_setup_mbie_diff(dev, apdev, test_params)
+    finally:
+        subprocess.call(['iw', 'reg', 'set', '00'])
+        dev[0].flush_scan_cache()
+        dev[1].flush_scan_cache()
+
+def _test_fst_setup_mbie_diff(dev, apdev, test_params):
+    hglobal = hostapd.HostapdGlobal()
+    if "OK" not in hglobal.request("FST-MANAGER TEST_REQUEST IS_SUPPORTED"):
+        raise HwsimSkip("No FST testing support")
+
+    params = { "ssid": "fst_11a", "hw_mode": "a", "channel": "36",
+               "country_code": "US" }
+    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+
+    group = "fstg0"
+    fst_attach_ap(hglobal, apdev[0]['ifname'], group)
+
+    cmd = "FST-ATTACH %s %s" % (apdev[0]['ifname'], group)
+    if "FAIL" not in hglobal.request(cmd):
+        raise Exception("Duplicated FST-ATTACH (AP) accepted")
+
+    params = { "ssid": "fst_11g", "hw_mode": "g", "channel": "1",
+               "country_code": "US" }
+    hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+    fst_attach_ap(hglobal, apdev[1]['ifname'], group)
+
+    sgroup = "fstg1"
+    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+    wpas.interface_add("wlan5")
+    fst_attach_sta(wpas, wpas.ifname, sgroup)
+
+    wpas.interface_add("wlan6", set_ifname=False)
+    wpas2 = WpaSupplicant(ifname="wlan6")
+    fst_attach_sta(wpas, wpas2.ifname, sgroup)
+
+    wpas.connect("fst_11a", key_mgmt="NONE", scan_freq="5180",
+                 wait_connect=False)
+    wpas.wait_connected()
+
+    fst_wait_event_peer_sta(wpas, "connected", wpas.ifname, apdev[0]['bssid'])
+    fst_wait_event_peer_ap(hglobal, "connected", apdev[0]['ifname'],
+                           wpas.own_addr())
+
+    wpas2.connect("fst_11g", key_mgmt="NONE", scan_freq="2412",
+                  wait_connect=False)
+    wpas2.wait_connected()
+
+    fst_wait_event_peer_sta(wpas, "connected", wpas2.ifname, apdev[1]['bssid'])
+    fst_wait_event_peer_ap(hglobal, "connected", apdev[1]['ifname'],
+                           wpas2.own_addr())
+
+    # FST Setup Request: Category, FST Action, Dialog Token (non-zero),
+    # LLT (32 bits, see 10.32), Session Transition (see 8.4.2.147),
+    # Multi-band element (optional, see 8.4.2.140)
+
+    # Session Transition: EID, Len, FSTS ID(4), Session Control,
+    # New Band (Band ID, Setup, Operation), Old Band (Band ID, Setup, Operation)
+
+    # Multi-band element: EID, Len, Multi-band Control, Band ID,
+    # Operating Class, Channel Number, BSSID (6), Beacon Interval (2),
+    # TSF Offset (8), Multi-band Connection Capability, FSTSessionTimeOut,
+    # STA MAC Address (6, optional), Pairwise Cipher Suite Count (2, optional),
+    # Pairwise Cipher Suite List (4xm, optional)
+
+    # MBIE with the non-matching STA MAC Address:
+    req = "1200011a060000"
+    stie = "a40b0100000000020001040001"
+    mbie = "9e1c0c0200010200000004000000000000000000000000ff0200000006ff"
+    fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie, mbie)
+
+    # MBIE without the STA MAC Address:
+    req = "1200011a060000"
+    stie = "a40b0100000000020001040001"
+    mbie = "9e16040200010200000004000000000000000000000000ff"
+    fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie, mbie)
+
+    # MBIE with unsupported STA Role:
+    req = "1200011a060000"
+    stie = "a40b0100000000020001040001"
+    mbie = "9e16070200010200000004000000000000000000000000ff"
+    fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie, mbie)
+
+    # MBIE with unsupported Band ID:
+    req = "1200011a060000"
+    stie = "a40b0100000000020001040001"
+    mbie = "9e1604ff00010200000004000000000000000000000000ff"
+    fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie, mbie)
+
+    # FST Setup Request without MBIE (different FSTS ID):
+    req = "1200011a060000"
+    stie = "a40b0200000000020001040001"
+    fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie)