import subprocess
import hostapd
+from utils import HwsimSkip
+import hwsim_utils
from wlantest import Wlantest
from wpasupplicant import WpaSupplicant
def check_auto_select(dev, bssid):
dev.scan_for_bss(bssid, freq="2412")
dev.request("INTERWORKING_SELECT auto freq=2412")
- ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
- if ev is None:
- raise Exception("Connection timed out")
+ ev = dev.wait_connected(timeout=15)
if bssid not in ev:
raise Exception("Connected to incorrect network")
dev.request("REMOVE_NETWORK all")
def hlr_auc_gw_available():
if not os.path.exists("/tmp/hlr_auc_gw.sock"):
- logger.info("No hlr_auc_gw available");
- return False
+ raise HwsimSkip("No hlr_auc_gw socket available")
if not os.path.exists("../../hostapd/hlr_auc_gw"):
- logger.info("No hlr_auc_gw available");
- return False
- return True
+ raise HwsimSkip("No hlr_auc_gw available")
def interworking_ext_sim_connect(dev, bssid, method):
dev.request("INTERWORKING_CONNECT " + bssid)
resp = res.split(' ')[2].rstrip()
dev.request("CTRL-RSP-SIM-" + id + ":GSM-AUTH:" + resp)
- ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
- if ev is None:
- raise Exception("Connection timed out")
+ dev.wait_connected(timeout=15)
def interworking_connect(dev, bssid, method):
dev.request("INTERWORKING_CONNECT " + bssid)
if "(" + method + ")" not in ev:
raise Exception("Unexpected EAP method selection")
- ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
- if ev is None:
- raise Exception("Connection timed out")
+ dev.wait_connected(timeout=15)
def check_probe_resp(wt, bssid_unexpected, bssid_expected):
if bssid_unexpected:
if "example.org".encode('hex') not in nai2:
raise Exception("Non-home realm not reported in wildcard query ")
+ cmds = [ "foo",
+ "00:11:22:33:44:55 123",
+ "00:11:22:33:44:55 qq" ]
+ for cmd in cmds:
+ if "FAIL" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + cmd):
+ raise Exception("Invalid HS20_GET_NAI_HOME_REALM_LIST accepted: " + cmd)
+
+ dev[0].dump_monitor()
+ if "OK" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid):
+ raise Exception("HS20_GET_NAI_HOME_REALM_LIST failed")
+ ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("ANQP operation timed out")
+ ev = dev[0].wait_event(["RX-ANQP"], timeout=0.1)
+ if ev is not None:
+ raise Exception("Unexpected ANQP response: " + ev)
+
+ dev[0].dump_monitor()
+ if "OK" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid + " 01000b6578616d706c652e636f6d"):
+ raise Exception("HS20_GET_NAI_HOME_REALM_LIST failed")
+ ev = dev[0].wait_event(["RX-ANQP"], timeout=10)
+ if ev is None:
+ raise Exception("No ANQP response")
+ if "NAI Realm list" not in ev:
+ raise Exception("Missing NAI Realm list: " + ev)
+
+ dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
+ 'password': "secret",
+ 'domain': "example.com" })
+ dev[0].dump_monitor()
+ if "OK" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid):
+ raise Exception("HS20_GET_NAI_HOME_REALM_LIST failed")
+ ev = dev[0].wait_event(["RX-ANQP"], timeout=10)
+ if ev is None:
+ raise Exception("No ANQP response")
+ if "NAI Realm list" not in ev:
+ raise Exception("Missing NAI Realm list: " + ev)
+
def test_ap_interworking_scan_filtering(dev, apdev):
"""Interworking scan filtering with HESSID and access network type"""
+ try:
+ _test_ap_interworking_scan_filtering(dev, apdev)
+ finally:
+ dev[0].request("SET hessid 00:00:00:00:00:00")
+ dev[0].request("SET access_network_type 15")
+
+def _test_ap_interworking_scan_filtering(dev, apdev):
bssid = apdev[0]['bssid']
params = hs20_ap_params()
ssid = "test-hs20-ap1"
dev[0].set_cred_quoted(id, "realm", "no.match.example.com");
interworking_select(dev[0], bssid, no_match=True, freq="2412")
+ res = dev[0].request("SCAN_RESULTS")
+ if "[HS20]" not in res:
+ raise Exception("HS20 flag missing from scan results: " + res)
+
bssid2 = apdev[1]['bssid']
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.org,21" ]
def test_ap_hs20_sim(dev, apdev):
"""Hotspot 2.0 with simulated SIM and EAP-SIM"""
- if not hlr_auc_gw_available():
- return "skip"
+ hlr_auc_gw_available()
hs20_simulated_sim(dev[0], apdev[0], "SIM")
dev[0].request("INTERWORKING_SELECT auto freq=2412")
ev = dev[0].wait_event(["INTERWORKING-ALREADY-CONNECTED"], timeout=15)
def test_ap_hs20_aka(dev, apdev):
"""Hotspot 2.0 with simulated USIM and EAP-AKA"""
- if not hlr_auc_gw_available():
- return "skip"
+ hlr_auc_gw_available()
hs20_simulated_sim(dev[0], apdev[0], "AKA")
def test_ap_hs20_aka_prime(dev, apdev):
"""Hotspot 2.0 with simulated USIM and EAP-AKA'"""
- if not hlr_auc_gw_available():
- return "skip"
+ hlr_auc_gw_available()
hs20_simulated_sim(dev[0], apdev[0], "AKA'")
def test_ap_hs20_ext_sim(dev, apdev):
"""Hotspot 2.0 with external SIM processing"""
- if not hlr_auc_gw_available():
- return "skip"
+ hlr_auc_gw_available()
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
hostapd.add_ap(apdev[0]['ifname'], params)
dev[0].hs20_enable()
- dev[0].request("SET external_sim 1")
- dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
- interworking_select(dev[0], "home", freq="2412")
- interworking_ext_sim_connect(dev[0], bssid, "SIM")
- check_sp_type(dev[0], "home")
+ try:
+ dev[0].request("SET external_sim 1")
+ dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
+ interworking_select(dev[0], "home", freq="2412")
+ interworking_ext_sim_connect(dev[0], bssid, "SIM")
+ check_sp_type(dev[0], "home")
+ finally:
+ dev[0].request("SET external_sim 0")
def test_ap_hs20_ext_sim_roaming(dev, apdev):
"""Hotspot 2.0 with external SIM processing in roaming network"""
- if not hlr_auc_gw_available():
- return "skip"
+ hlr_auc_gw_available()
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
hostapd.add_ap(apdev[0]['ifname'], params)
dev[0].hs20_enable()
- dev[0].request("SET external_sim 1")
- dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
- interworking_select(dev[0], "roaming", freq="2412")
- interworking_ext_sim_connect(dev[0], bssid, "SIM")
- check_sp_type(dev[0], "roaming")
+ try:
+ dev[0].request("SET external_sim 1")
+ dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
+ interworking_select(dev[0], "roaming", freq="2412")
+ interworking_ext_sim_connect(dev[0], bssid, "SIM")
+ check_sp_type(dev[0], "roaming")
+ finally:
+ dev[0].request("SET external_sim 0")
def test_ap_hs20_username(dev, apdev):
"""Hotspot 2.0 connection in username/password credential"""
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
wpas.hs20_enable()
+ wpas.flush_scan_cache()
id = wpas.add_cred_values({ 'realm': "example.com",
'username': "hs20-test",
'password': "password",
'domain': "example.com",
'update_identifier': "1234" })
dev[0].request("REASSOCIATE")
- ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
- if ev is None:
- raise Exception("Connection timed out")
+ dev[0].wait_connected(timeout=15)
check_sp_type(dev[0], "home")
status = dev[0].get_status()
if status['pairwise_cipher'] != "CCMP":
def test_ap_hs20_gas_while_associated_with_pmf(dev, apdev):
"""Hotspot 2.0 connection with GAS query while associated and using PMF"""
+ try:
+ _test_ap_hs20_gas_while_associated_with_pmf(dev, apdev)
+ finally:
+ dev[0].request("SET pmf 0")
+
+def _test_ap_hs20_gas_while_associated_with_pmf(dev, apdev):
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
if "FAIL" not in ret:
raise Exception("INTERWORKING_CONNECT to disallowed BSS not rejected")
+ if "FAIL" not in dev[0].request("INTERWORKING_CONNECT foo"):
+ raise Exception("Invalid INTERWORKING_CONNECT not rejected")
+ if "FAIL" not in dev[0].request("INTERWORKING_CONNECT 00:11:22:33:44:55"):
+ raise Exception("Invalid INTERWORKING_CONNECT not rejected")
+
def policy_test(dev, ap, values, only_one=True):
dev.dump_monitor()
if ap:
raise Exception("Selected incorrect BSS")
break
- ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
- if ev is None:
- raise Exception("Connection timed out")
+ ev = dev.wait_connected(timeout=15)
if bssid and bssid not in ev:
raise Exception("Connected to incorrect BSS")
def test_ap_hs20_multi_cred_sp_prio(dev, apdev):
"""Hotspot 2.0 multi-cred sp_priority"""
- if not hlr_auc_gw_available():
- return "skip"
+ try:
+ _test_ap_hs20_multi_cred_sp_prio(dev, apdev)
+ finally:
+ dev[0].request("SET external_sim 0")
+
+def _test_ap_hs20_multi_cred_sp_prio(dev, apdev):
+ hlr_auc_gw_available()
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
def test_ap_hs20_multi_cred_sp_prio2(dev, apdev):
"""Hotspot 2.0 multi-cred sp_priority with two BSSes"""
- if not hlr_auc_gw_available():
- return "skip"
+ try:
+ _test_ap_hs20_multi_cred_sp_prio2(dev, apdev)
+ finally:
+ dev[0].request("SET external_sim 0")
+
+def _test_ap_hs20_multi_cred_sp_prio2(dev, apdev):
+ hlr_auc_gw_available()
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
def test_ap_hs20_deauth_req_ess(dev, apdev):
"""Hotspot 2.0 connection and deauthentication request for ESS"""
+ try:
+ _test_ap_hs20_deauth_req_ess(dev, apdev)
+ finally:
+ dev[0].request("SET pmf 0")
+
+def _test_ap_hs20_deauth_req_ess(dev, apdev):
dev[0].request("SET pmf 2")
eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user")
dev[0].dump_monitor()
if "1 120 http://example.com/" not in ev:
raise Exception("Unexpected deauth imminent notice: " + ev)
hapd.request("DEAUTHENTICATE " + addr)
- ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
- if ev is None:
- raise Exception("Timeout on disconnection")
+ dev[0].wait_disconnected(timeout=10)
if "[TEMP-DISABLED]" not in dev[0].list_networks()[0]['flags']:
raise Exception("Network not marked temporarily disabled")
ev = dev[0].wait_event(["SME: Trying to authenticate",
def test_ap_hs20_deauth_req_bss(dev, apdev):
"""Hotspot 2.0 connection and deauthentication request for BSS"""
+ try:
+ _test_ap_hs20_deauth_req_bss(dev, apdev)
+ finally:
+ dev[0].request("SET pmf 0")
+
+def _test_ap_hs20_deauth_req_bss(dev, apdev):
dev[0].request("SET pmf 2")
eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user")
dev[0].dump_monitor()
if "0 120 http://example.com/" not in ev:
raise Exception("Unexpected deauth imminent notice: " + ev)
hapd.request("DEAUTHENTICATE " + addr + " reason=4")
- ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
- if ev is None:
- raise Exception("Timeout on disconnection")
+ ev = dev[0].wait_disconnected(timeout=10)
if "reason=4" not in ev:
raise Exception("Unexpected disconnection reason")
if "[TEMP-DISABLED]" not in dev[0].list_networks()[0]['flags']:
def test_ap_hs20_deauth_req_from_radius(dev, apdev):
"""Hotspot 2.0 connection and deauthentication request from RADIUS"""
+ try:
+ _test_ap_hs20_deauth_req_from_radius(dev, apdev)
+ finally:
+ dev[0].request("SET pmf 0")
+
+def _test_ap_hs20_deauth_req_from_radius(dev, apdev):
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.com,21[2:4]" ]
raise Exception("Timeout on deauth imminent notice")
if " 1 100" not in ev:
raise Exception("Unexpected deauth imminent contents")
- ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=3)
- if ev is None:
- raise Exception("Timeout on disconnection")
+ dev[0].wait_disconnected(timeout=3)
def test_ap_hs20_remediation_required(dev, apdev):
"""Hotspot 2.0 connection and remediation required from RADIUS"""
+ try:
+ _test_ap_hs20_remediation_required(dev, apdev)
+ finally:
+ dev[0].request("SET pmf 0")
+
+def _test_ap_hs20_remediation_required(dev, apdev):
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.com,21[2:4]" ]
def test_ap_hs20_remediation_required_ctrl(dev, apdev):
"""Hotspot 2.0 connection and subrem from ctrl_iface"""
+ try:
+ _test_ap_hs20_remediation_required_ctrl(dev, apdev)
+ finally:
+ dev[0].request("SET pmf 0")
+
+def _test_ap_hs20_remediation_required_ctrl(dev, apdev):
bssid = apdev[0]['bssid']
addr = dev[0].p2p_dev_addr()
params = hs20_ap_params()
def test_ap_hs20_session_info(dev, apdev):
"""Hotspot 2.0 connection and session information from RADIUS"""
+ try:
+ _test_ap_hs20_session_info(dev, apdev)
+ finally:
+ dev[0].request("SET pmf 0")
+
+def _test_ap_hs20_session_info(dev, apdev):
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.com,21[2:4]" ]
dev[0].scan_for_bss(bssid, freq="2412")
dev[0].request("INTERWORKING_SELECT auto freq=2412")
- ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
- if ev is None:
- raise Exception("Connection timed out")
+ ev = dev[0].wait_connected(timeout=15)
if bssid not in ev:
raise Exception("Unexpected network selected")
dev[0].scan_for_bss(bssid2, freq="2412")
dev[0].request("INTERWORKING_SELECT auto freq=2412")
- ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
- if ev is None:
- raise Exception("Connection timed out")
+ ev = dev[0].wait_connected(timeout=15)
if bssid2 not in ev:
raise Exception("Unexpected network selected")
dev[0].scan_for_bss(bssid, freq="2412")
dev[0].scan_for_bss(bssid2, freq="2412")
dev[0].request("INTERWORKING_SELECT auto freq=2412")
- ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
- if ev is None:
- raise Exception("Connection timed out")
+ ev = dev[0].wait_connected(timeout=15)
if bssid not in ev:
raise Exception("Unexpected network selected")
dev[0].scan_for_bss(bssid, freq="2412")
dev[0].scan_for_bss(bssid2, freq="2412")
dev[0].request("INTERWORKING_SELECT auto freq=2412")
- ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
- if ev is None:
- raise Exception("Connection timed out")
+ ev = dev[0].wait_connected(timeout=15)
if bssid not in ev:
raise Exception("Unexpected network selected")
dev[1].scan_for_bss(bssid, freq="2412")
dev[0].request("SET osu_dir " + dir)
dev[0].request("FETCH_OSU")
+ if "FAIL" not in dev[1].request("HS20_ICON_REQUEST foo w1fi_logo"):
+ raise Exception("Invalid HS20_ICON_REQUEST accepted")
if "OK" not in dev[1].request("HS20_ICON_REQUEST " + bssid + " w1fi_logo"):
raise Exception("HS20_ICON_REQUEST failed")
icons = 0
if "Icon Binary File" not in ev:
raise Exception("Unexpected ANQP element")
+def test_ap_hs20_fetch_osu_stop(dev, apdev):
+ """Hotspot 2.0 OSU provider fetch stopped"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
+ params['osu_ssid'] = '"HS 2.0 OSU open"'
+ params['osu_method_list'] = "1"
+ params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
+ params['osu_icon'] = "w1fi_logo"
+ params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
+ params['osu_server_uri'] = "https://example.com/osu/"
+ hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+
+ dev[0].hs20_enable()
+ dir = "/tmp/osu-fetch"
+ if os.path.isdir(dir):
+ files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
+ for f in files:
+ os.remove(dir + "/" + f)
+ else:
+ try:
+ os.makedirs(dir)
+ except:
+ pass
+ try:
+ dev[0].request("SET osu_dir " + dir)
+ dev[0].request("SCAN freq=2412-2462")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=10)
+ if ev is None:
+ raise Exception("Scan did not start")
+ if "FAIL" not in dev[0].request("FETCH_OSU"):
+ raise Exception("FETCH_OSU accepted while scanning")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
+ if ev is None:
+ raise Exception("Scan timed out")
+ hapd.set("ext_mgmt_frame_handling", "1")
+ dev[0].request("FETCH_ANQP")
+ if "FAIL" not in dev[0].request("FETCH_OSU"):
+ raise Exception("FETCH_OSU accepted while in FETCH_ANQP")
+ dev[0].request("STOP_FETCH_ANQP")
+ dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5)
+ dev[0].dump_monitor()
+ hapd.dump_monitor()
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+ for i in range(5):
+ msg = hapd.mgmt_rx()
+ if msg['subtype'] == 13:
+ break
+ if "FAIL" not in dev[0].request("FETCH_OSU"):
+ raise Exception("FETCH_OSU accepted while in INTERWORKING_SELECT")
+ ev = dev[0].wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Network selection timed out");
+
+ dev[0].dump_monitor()
+ if "OK" not in dev[0].request("FETCH_OSU"):
+ raise Exception("FETCH_OSU failed")
+ dev[0].request("CANCEL_FETCH_OSU")
+
+ for i in range(15):
+ time.sleep(0.5)
+ if dev[0].get_driver_status_field("scan_state") == "SCAN_COMPLETED":
+ break
+
+ dev[0].dump_monitor()
+ if "OK" not in dev[0].request("FETCH_OSU"):
+ raise Exception("FETCH_OSU failed")
+ if "FAIL" not in dev[0].request("FETCH_OSU"):
+ raise Exception("FETCH_OSU accepted while in FETCH_OSU")
+ ev = dev[0].wait_event(["GAS-QUERY-START"], 10)
+ if ev is None:
+ raise Exception("GAS timed out")
+ if "FAIL" not in dev[0].request("FETCH_OSU"):
+ raise Exception("FETCH_OSU accepted while in FETCH_OSU")
+ dev[0].request("CANCEL_FETCH_OSU")
+ ev = dev[0].wait_event(["GAS-QUERY-DONE"], 10)
+ if ev is None:
+ raise Exception("GAS event timed out after CANCEL_FETCH_OSU")
+ finally:
+ files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
+ for f in files:
+ os.remove(dir + "/" + f)
+ os.rmdir(dir)
+
def test_ap_hs20_ft(dev, apdev):
"""Hotspot 2.0 connection with FT"""
bssid = apdev[0]['bssid']
try:
import sqlite3
except ImportError:
- return "skip"
+ raise HwsimSkip("No sqlite3 module available")
dbfile = os.path.join(params['logdir'], "eap-user.db")
try:
os.remove(dbfile)
finally:
os.remove(dbfile)
+ dev[0].request("SET pmf 0")
def test_ap_hs20_external_selection(dev, apdev):
"""Hotspot 2.0 connection using external network selection and creation"""
wpas.request("SET preassoc_mac_addr 1")
wpas.request("SET rand_addr_lifetime 60")
wpas.hs20_enable()
- wpas.scan(freq="2412", only_new=True)
+ wpas.flush_scan_cache()
id = wpas.add_cred_values({ 'realm': "example.com",
'username': "hs20-test",
'password': "password",
if sta['addr'] != addr1:
raise Exception("STA association with random address not found")
+def test_ap_hs20_multi_network_and_cred_removal(dev, apdev):
+ """Multiple networks and cred removal"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['nai_realm'] = [ "0,example.com,25[3:26]"]
+ hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+
+ dev[0].add_network()
+ dev[0].hs20_enable()
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'username': "user",
+ 'password': "password" })
+ interworking_select(dev[0], bssid, freq="2412")
+ interworking_connect(dev[0], bssid, "PEAP")
+ dev[0].add_network()
+
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected(timeout=10)
+
+ hapd.disable()
+ hapd.set("ssid", "another ssid")
+ hapd.enable()
+
+ interworking_select(dev[0], bssid, freq="2412")
+ interworking_connect(dev[0], bssid, "PEAP")
+ dev[0].add_network()
+ if len(dev[0].list_networks()) != 5:
+ raise Exception("Unexpected number of networks prior to remove_crec")
+
+ dev[0].dump_monitor()
+ dev[0].remove_cred(id)
+ if len(dev[0].list_networks()) != 3:
+ raise Exception("Unexpected number of networks after to remove_crec")
+ dev[0].wait_disconnected(timeout=10)
+
def _test_ap_hs20_proxyarp(dev, apdev):
bssid = apdev[0]['bssid']
params = hs20_ap_params()
hapd.enable()
except:
# For now, do not report failures due to missing kernel support
- logger.info("Could not start hostapd - assume proxyarp not supported in kernel version")
- return "skip"
+ raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
if ev is None:
raise Exception("AP startup timed out")
def test_ap_hs20_proxyarp(dev, apdev):
"""Hotspot 2.0 and ProxyARP"""
- res = None
try:
- res = _test_ap_hs20_proxyarp(dev, apdev)
+ _test_ap_hs20_proxyarp(dev, apdev)
+ finally:
+ subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
+ stderr=open('/dev/null', 'w'))
+ subprocess.call(['brctl', 'delbr', 'ap-br0'],
+ stderr=open('/dev/null', 'w'))
+
+def _test_ap_hs20_proxyarp_dgaf(dev, apdev, disabled):
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ params['disable_dgaf'] = '1' if disabled else '0'
+ params['proxy_arp'] = '1'
+ params['ap_isolate'] = '1'
+ params['bridge'] = 'ap-br0'
+ hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
+ try:
+ hapd.enable()
+ except:
+ # For now, do not report failures due to missing kernel support
+ raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
+ ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
+ if ev is None:
+ raise Exception("AP startup timed out")
+
+ dev[0].hs20_enable()
+ subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
+ subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
+
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'username': "hs20-test",
+ 'password': "password",
+ 'ca_cert': "auth_serv/ca.pem",
+ 'domain': "example.com",
+ 'update_identifier': "1234" })
+ interworking_select(dev[0], bssid, "home", freq="2412")
+ interworking_connect(dev[0], bssid, "TTLS")
+
+ dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="hs20-test", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ scan_freq="2412")
+ time.sleep(0.1)
+
+ addr0 = dev[0].p2p_interface_addr()
+
+ src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':',''))
+
+ pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
+ ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
+ opt=src_ll_opt0)
+ if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
+ raise Exception("DATA_TEST_FRAME failed")
+
+ pkt = build_ra(src_ll=apdev[0]['bssid'], ip_src="aaaa:bbbb:cccc::33",
+ ip_dst="ff01::1")
+ if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
+ raise Exception("DATA_TEST_FRAME failed")
+
+ pkt = build_na(src_ll=apdev[0]['bssid'], ip_src="aaaa:bbbb:cccc::44",
+ ip_dst="ff01::1", target="aaaa:bbbb:cccc::55")
+ if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
+ raise Exception("DATA_TEST_FRAME failed")
+
+ pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
+ ip_src="192.168.1.1", ip_dst="255.255.255.255",
+ yiaddr="192.168.1.123", chaddr=addr0)
+ if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
+ raise Exception("DATA_TEST_FRAME failed")
+ # another copy for additional code coverage
+ pkt = build_dhcp_ack(dst_ll=addr0, src_ll=bssid,
+ ip_src="192.168.1.1", ip_dst="255.255.255.255",
+ yiaddr="192.168.1.123", chaddr=addr0)
+ if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
+ raise Exception("DATA_TEST_FRAME failed")
+
+ matches = get_permanent_neighbors("ap-br0")
+ logger.info("After connect: " + str(matches))
+ if len(matches) != 2:
+ raise Exception("Unexpected number of neighbor entries after connect")
+ if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
+ raise Exception("dev0 addr missing")
+ if '192.168.1.123 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
+ raise Exception("dev0 IPv4 addr missing")
+ dev[0].request("DISCONNECT")
+ dev[1].request("DISCONNECT")
+ time.sleep(0.5)
+ matches = get_permanent_neighbors("ap-br0")
+ logger.info("After disconnect: " + str(matches))
+ if len(matches) > 0:
+ raise Exception("Unexpected neighbor entries after disconnect")
+
+def test_ap_hs20_proxyarp_disable_dgaf(dev, apdev):
+ """Hotspot 2.0 and ProxyARP with DGAF disabled"""
+ try:
+ _test_ap_hs20_proxyarp_dgaf(dev, apdev, True)
finally:
subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
stderr=open('/dev/null', 'w'))
subprocess.call(['brctl', 'delbr', 'ap-br0'],
stderr=open('/dev/null', 'w'))
- return res
+def test_ap_hs20_proxyarp_enable_dgaf(dev, apdev):
+ """Hotspot 2.0 and ProxyARP with DGAF enabled"""
+ try:
+ _test_ap_hs20_proxyarp_dgaf(dev, apdev, False)
+ finally:
+ subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
+ stderr=open('/dev/null', 'w'))
+ subprocess.call(['brctl', 'delbr', 'ap-br0'],
+ stderr=open('/dev/null', 'w'))
def ip_checksum(buf):
sum = 0
sum = (sum & 0xffff) + (sum >> 16)
return struct.pack('H', ~sum & 0xffff)
+def ipv6_solicited_node_mcaddr(target):
+ prefix = socket.inet_pton(socket.AF_INET6, "ff02::1:ff00:0")
+ mask = socket.inet_pton(socket.AF_INET6, "::ff:ffff")
+ _target = socket.inet_pton(socket.AF_INET6, target)
+ p = struct.unpack('4I', prefix)
+ m = struct.unpack('4I', mask)
+ t = struct.unpack('4I', _target)
+ res = (p[0] | (t[0] & m[0]),
+ p[1] | (t[1] & m[1]),
+ p[2] | (t[2] & m[2]),
+ p[3] | (t[3] & m[3]))
+ return socket.inet_ntop(socket.AF_INET6, struct.pack('4I', *res))
+
def build_icmpv6(ipv6_addrs, type, code, payload):
start = struct.pack("BB", type, code)
end = payload
csum = ip_checksum(pseudo + icmp)
return start + csum + end
+def build_ra(src_ll, ip_src, ip_dst, cur_hop_limit=0, router_lifetime=0,
+ reachable_time=0, retrans_timer=0, opt=None):
+ link_mc = binascii.unhexlify("3333ff000002")
+ _src_ll = binascii.unhexlify(src_ll.replace(':',''))
+ proto = '\x86\xdd'
+ ehdr = link_mc + _src_ll + proto
+ _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
+ _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
+
+ adv = struct.pack('>BBHLL', cur_hop_limit, 0, router_lifetime,
+ reachable_time, retrans_timer)
+ if opt:
+ payload = adv + opt
+ else:
+ payload = adv
+ icmp = build_icmpv6(_ip_src + _ip_dst, 134, 0, payload)
+
+ ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
+ ipv6 += _ip_src + _ip_dst
+
+ return ehdr + ipv6 + icmp
+
def build_ns(src_ll, ip_src, ip_dst, target, opt=None):
link_mc = binascii.unhexlify("3333ff000002")
_src_ll = binascii.unhexlify(src_ll.replace(':',''))
proto = '\x86\xdd'
ehdr = link_mc + _src_ll + proto
_ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
+ if ip_dst is None:
+ ip_dst = ipv6_solicited_node_mcaddr(target)
_ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
reserved = '\x00\x00\x00\x00'
return ehdr + ipv6 + icmp
+def send_ns(dev, src_ll=None, target=None, ip_src=None, ip_dst=None, opt=None,
+ hapd_bssid=None):
+ if hapd_bssid:
+ if src_ll is None:
+ src_ll = hapd_bssid
+ cmd = "DATA_TEST_FRAME ifname=ap-br0 "
+ else:
+ if src_ll is None:
+ src_ll = dev.p2p_interface_addr()
+ cmd = "DATA_TEST_FRAME "
+
+ if opt is None:
+ opt = "\x01\x01" + binascii.unhexlify(src_ll.replace(':',''))
+
+ pkt = build_ns(src_ll=src_ll, ip_src=ip_src, ip_dst=ip_dst, target=target,
+ opt=opt)
+ if "OK" not in dev.request(cmd + binascii.hexlify(pkt)):
+ raise Exception("DATA_TEST_FRAME failed")
+
+def build_na(src_ll, ip_src, ip_dst, target, opt=None):
+ link_mc = binascii.unhexlify("3333ff000002")
+ _src_ll = binascii.unhexlify(src_ll.replace(':',''))
+ proto = '\x86\xdd'
+ ehdr = link_mc + _src_ll + proto
+ _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
+ _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
+
+ reserved = '\x00\x00\x00\x00'
+ _target = socket.inet_pton(socket.AF_INET6, target)
+ if opt:
+ payload = reserved + _target + opt
+ else:
+ payload = reserved + _target
+ icmp = build_icmpv6(_ip_src + _ip_dst, 136, 0, payload)
+
+ ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
+ ipv6 += _ip_src + _ip_dst
+
+ return ehdr + ipv6 + icmp
+
+def send_na(dev, src_ll=None, target=None, ip_src=None, ip_dst=None, opt=None,
+ hapd_bssid=None):
+ if hapd_bssid:
+ if src_ll is None:
+ src_ll = hapd_bssid
+ cmd = "DATA_TEST_FRAME ifname=ap-br0 "
+ else:
+ if src_ll is None:
+ src_ll = dev.p2p_interface_addr()
+ cmd = "DATA_TEST_FRAME "
+
+ pkt = build_na(src_ll=src_ll, ip_src=ip_src, ip_dst=ip_dst, target=target,
+ opt=opt)
+ if "OK" not in dev.request(cmd + binascii.hexlify(pkt)):
+ raise Exception("DATA_TEST_FRAME failed")
+
+def build_dhcp_ack(dst_ll, src_ll, ip_src, ip_dst, yiaddr, chaddr,
+ subnet_mask="255.255.255.0", truncated_opt=False,
+ wrong_magic=False, force_tot_len=None, no_dhcp=False):
+ _dst_ll = binascii.unhexlify(dst_ll.replace(':',''))
+ _src_ll = binascii.unhexlify(src_ll.replace(':',''))
+ proto = '\x08\x00'
+ ehdr = _dst_ll + _src_ll + proto
+ _ip_src = socket.inet_pton(socket.AF_INET, ip_src)
+ _ip_dst = socket.inet_pton(socket.AF_INET, ip_dst)
+ _subnet_mask = socket.inet_pton(socket.AF_INET, subnet_mask)
+
+ _ciaddr = '\x00\x00\x00\x00'
+ _yiaddr = socket.inet_pton(socket.AF_INET, yiaddr)
+ _siaddr = '\x00\x00\x00\x00'
+ _giaddr = '\x00\x00\x00\x00'
+ _chaddr = binascii.unhexlify(chaddr.replace(':','') + "00000000000000000000")
+ payload = struct.pack('>BBBBL3BB', 2, 1, 6, 0, 12345, 0, 0, 0, 0)
+ payload += _ciaddr + _yiaddr + _siaddr + _giaddr + _chaddr + 192*'\x00'
+ # magic
+ if wrong_magic:
+ payload += '\x63\x82\x53\x00'
+ else:
+ payload += '\x63\x82\x53\x63'
+ if truncated_opt:
+ payload += '\x22\xff\x00'
+ # Option: DHCP Message Type = ACK
+ payload += '\x35\x01\x05'
+ # Pad Option
+ payload += '\x00'
+ # Option: Subnet Mask
+ payload += '\x01\x04' + _subnet_mask
+ # Option: Time Offset
+ payload += struct.pack('>BBL', 2, 4, 0)
+ # End Option
+ payload += '\xff'
+ # Pad Option
+ payload += '\x00\x00\x00\x00'
+
+ if no_dhcp:
+ payload = struct.pack('>BBBBL3BB', 2, 1, 6, 0, 12345, 0, 0, 0, 0)
+ payload += _ciaddr + _yiaddr + _siaddr + _giaddr + _chaddr + 192*'\x00'
+
+ udp = struct.pack('>HHHH', 67, 68, 8 + len(payload), 0) + payload
+
+ if force_tot_len:
+ tot_len = force_tot_len
+ else:
+ tot_len = 20 + len(udp)
+ start = struct.pack('>BBHHBBBB', 0x45, 0, tot_len, 0, 0, 0, 128, 17)
+ ipv4 = start + '\x00\x00' + _ip_src + _ip_dst
+ csum = ip_checksum(ipv4)
+ ipv4 = start + csum + _ip_src + _ip_dst
+
+ return ehdr + ipv4 + udp
+
+def build_arp(dst_ll, src_ll, opcode, sender_mac, sender_ip,
+ target_mac, target_ip):
+ _dst_ll = binascii.unhexlify(dst_ll.replace(':',''))
+ _src_ll = binascii.unhexlify(src_ll.replace(':',''))
+ proto = '\x08\x06'
+ ehdr = _dst_ll + _src_ll + proto
+
+ _sender_mac = binascii.unhexlify(sender_mac.replace(':',''))
+ _sender_ip = socket.inet_pton(socket.AF_INET, sender_ip)
+ _target_mac = binascii.unhexlify(target_mac.replace(':',''))
+ _target_ip = socket.inet_pton(socket.AF_INET, target_ip)
+
+ arp = struct.pack('>HHBBH', 1, 0x0800, 6, 4, opcode)
+ arp += _sender_mac + _sender_ip
+ arp += _target_mac + _target_ip
+
+ return ehdr + arp
+
+def send_arp(dev, dst_ll="ff:ff:ff:ff:ff:ff", src_ll=None, opcode=1,
+ sender_mac=None, sender_ip="0.0.0.0",
+ target_mac="00:00:00:00:00:00", target_ip="0.0.0.0",
+ hapd_bssid=None):
+ if hapd_bssid:
+ if src_ll is None:
+ src_ll = hapd_bssid
+ if sender_mac is None:
+ sender_mac = hapd_bssid
+ cmd = "DATA_TEST_FRAME ifname=ap-br0 "
+ else:
+ if src_ll is None:
+ src_ll = dev.p2p_interface_addr()
+ if sender_mac is None:
+ sender_mac = dev.p2p_interface_addr()
+ cmd = "DATA_TEST_FRAME "
+
+ pkt = build_arp(dst_ll=dst_ll, src_ll=src_ll, opcode=opcode,
+ sender_mac=sender_mac, sender_ip=sender_ip,
+ target_mac=target_mac, target_ip=target_ip)
+ if "OK" not in dev.request(cmd + binascii.hexlify(pkt)):
+ raise Exception("DATA_TEST_FRAME failed")
+
def get_permanent_neighbors(ifname):
cmd = subprocess.Popen(['ip', 'nei'], stdout=subprocess.PIPE)
res = cmd.stdout.read()
cmd.stdout.close()
return [ line for line in res.splitlines() if "PERMANENT" in line and ifname in line ]
-def _test_proxyarp_open(dev, apdev):
+def _test_proxyarp_open(dev, apdev, params):
+ cap_br = os.path.join(params['logdir'], "proxyarp_open.ap-br0.pcap")
+ cap_dev0 = os.path.join(params['logdir'], "proxyarp_open.%s.pcap" % dev[0].ifname)
+ cap_dev1 = os.path.join(params['logdir'], "proxyarp_open.%s.pcap" % dev[1].ifname)
+
bssid = apdev[0]['bssid']
params = { 'ssid': 'open' }
params['proxy_arp'] = '1'
hapd.enable()
except:
# For now, do not report failures due to missing kernel support
- logger.info("Could not start hostapd - assume proxyarp not supported in kernel version")
- return "skip"
+ raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
if ev is None:
raise Exception("AP startup timed out")
subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
+ for chain in [ 'FORWARD', 'OUTPUT' ]:
+ subprocess.call(['ebtables', '-A', chain, '-p', 'ARP',
+ '-d', 'Broadcast', '-o', apdev[0]['ifname'],
+ '-j', 'DROP'])
+ subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
+ '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
+ '--ip6-icmp-type', 'neighbor-solicitation',
+ '-o', apdev[0]['ifname'], '-j', 'DROP'])
+ subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
+ '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
+ '--ip6-icmp-type', 'neighbor-advertisement',
+ '-o', apdev[0]['ifname'], '-j', 'DROP'])
+ subprocess.call(['ebtables', '-A', chain,
+ '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
+ '--ip6-icmp-type', 'router-solicitation',
+ '-o', apdev[0]['ifname'], '-j', 'DROP'])
+ # Multicast Listener Report Message
+ subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
+ '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
+ '--ip6-icmp-type', '143',
+ '-o', apdev[0]['ifname'], '-j', 'DROP'])
+
+ cmd = {}
+ cmd[0] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', 'ap-br0',
+ '-w', cap_br, '-s', '2000'],
+ stderr=open('/dev/null', 'w'))
+ cmd[1] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[0].ifname,
+ '-w', cap_dev0, '-s', '2000'],
+ stderr=open('/dev/null', 'w'))
+ cmd[2] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[1].ifname,
+ '-w', cap_dev1, '-s', '2000'],
+ stderr=open('/dev/null', 'w'))
+
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
dev[1].connect("open", key_mgmt="NONE", scan_freq="2412")
time.sleep(0.1)
src_ll_opt1 = "\x01\x01" + binascii.unhexlify(addr1.replace(':',''))
# DAD NS
- pkt = build_ns(src_ll=addr0, ip_src="::", ip_dst="ff02::1:ff00:2",
- target="aaaa:bbbb:cccc::2", opt=src_ll_opt0)
- if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
- raise Exception("DATA_TEST_FRAME failed")
+ send_ns(dev[0], ip_src="::", target="aaaa:bbbb:cccc::2")
- pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
- ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
- opt=src_ll_opt0)
- if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
- raise Exception("DATA_TEST_FRAME failed")
+ send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2")
# test frame without source link-layer address option
- pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
- ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2")
- if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
- raise Exception("DATA_TEST_FRAME failed")
+ send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
+ opt='')
# test frame with bogus option
- pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
- ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
- opt="\x70\x01\x01\x02\x03\x04\x05\x05")
- if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
- raise Exception("DATA_TEST_FRAME failed")
+ send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
+ opt="\x70\x01\x01\x02\x03\x04\x05\x05")
# test frame with truncated source link-layer address option
- pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
- ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
- opt="\x01\x01\x01\x02\x03\x04")
- if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
- raise Exception("DATA_TEST_FRAME failed")
+ send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
+ opt="\x01\x01\x01\x02\x03\x04")
# test frame with foreign source link-layer address option
- pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
- ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
- opt="\x01\x01\x01\x02\x03\x04\x05\x06")
- if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
+ send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
+ opt="\x01\x01\x01\x02\x03\x04\x05\x06")
+
+ send_ns(dev[1], ip_src="aaaa:bbbb:dddd::2", target="aaaa:bbbb:dddd::2")
+
+ send_ns(dev[1], ip_src="aaaa:bbbb:eeee::2", target="aaaa:bbbb:eeee::2")
+ # another copy for additional code coverage
+ send_ns(dev[1], ip_src="aaaa:bbbb:eeee::2", target="aaaa:bbbb:eeee::2")
+
+ pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
+ ip_src="192.168.1.1", ip_dst="255.255.255.255",
+ yiaddr="192.168.1.124", chaddr=addr0)
+ if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
+ raise Exception("DATA_TEST_FRAME failed")
+ # Change address and verify unicast
+ pkt = build_dhcp_ack(dst_ll=addr0, src_ll=bssid,
+ ip_src="192.168.1.1", ip_dst="255.255.255.255",
+ yiaddr="192.168.1.123", chaddr=addr0)
+ if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
raise Exception("DATA_TEST_FRAME failed")
- pkt = build_ns(src_ll=addr1, ip_src="aaaa:bbbb:dddd::2",
- ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:dddd::2",
- opt=src_ll_opt1)
- if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
+ # Not-associated client MAC address
+ pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
+ ip_src="192.168.1.1", ip_dst="255.255.255.255",
+ yiaddr="192.168.1.125", chaddr="22:33:44:55:66:77")
+ if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
raise Exception("DATA_TEST_FRAME failed")
- pkt = build_ns(src_ll=addr1, ip_src="aaaa:bbbb:eeee::2",
- ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:eeee::2",
- opt=src_ll_opt1)
- if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
+ # No IP address
+ pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
+ ip_src="192.168.1.1", ip_dst="255.255.255.255",
+ yiaddr="0.0.0.0", chaddr=addr1)
+ if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
raise Exception("DATA_TEST_FRAME failed")
- # another copy for additional code coverage
- if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
+
+ # Zero subnet mask
+ pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
+ ip_src="192.168.1.1", ip_dst="255.255.255.255",
+ yiaddr="192.168.1.126", chaddr=addr1,
+ subnet_mask="0.0.0.0")
+ if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
+ raise Exception("DATA_TEST_FRAME failed")
+
+ # Truncated option
+ pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
+ ip_src="192.168.1.1", ip_dst="255.255.255.255",
+ yiaddr="192.168.1.127", chaddr=addr1,
+ truncated_opt=True)
+ if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
+ raise Exception("DATA_TEST_FRAME failed")
+
+ # Wrong magic
+ pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
+ ip_src="192.168.1.1", ip_dst="255.255.255.255",
+ yiaddr="192.168.1.128", chaddr=addr1,
+ wrong_magic=True)
+ if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
+ raise Exception("DATA_TEST_FRAME failed")
+
+ # Wrong IPv4 total length
+ pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
+ ip_src="192.168.1.1", ip_dst="255.255.255.255",
+ yiaddr="192.168.1.129", chaddr=addr1,
+ force_tot_len=1000)
+ if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
+ raise Exception("DATA_TEST_FRAME failed")
+
+ # BOOTP
+ pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
+ ip_src="192.168.1.1", ip_dst="255.255.255.255",
+ yiaddr="192.168.1.129", chaddr=addr1,
+ no_dhcp=True)
+ if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
raise Exception("DATA_TEST_FRAME failed")
matches = get_permanent_neighbors("ap-br0")
logger.info("After connect: " + str(matches))
- if len(matches) != 3:
+ if len(matches) != 4:
raise Exception("Unexpected number of neighbor entries after connect")
if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
raise Exception("dev0 addr missing")
raise Exception("dev1 addr(1) missing")
if 'aaaa:bbbb:eeee::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
raise Exception("dev1 addr(2) missing")
+ if '192.168.1.123 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
+ raise Exception("dev0 IPv4 addr missing")
+
+ targets = [ "192.168.1.123", "192.168.1.124", "192.168.1.125",
+ "192.168.1.126" ]
+ for target in targets:
+ send_arp(dev[1], sender_ip="192.168.1.100", target_ip=target)
+
+ for target in targets:
+ send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.101",
+ target_ip=target)
+
+ # ARP Probe from wireless STA
+ send_arp(dev[1], target_ip="192.168.1.127")
+ # ARP Announcement from wireless STA
+ send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.127")
+ send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.127",
+ opcode=2)
+
+ matches = get_permanent_neighbors("ap-br0")
+ logger.info("After ARP Probe + Announcement: " + str(matches))
+
+ # ARP Request for the newly introduced IP address from wireless STA
+ send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.127")
+
+ # ARP Request for the newly introduced IP address from bridge
+ send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.102",
+ target_ip="192.168.1.127")
+
+ # ARP Probe from bridge
+ send_arp(hapd, hapd_bssid=bssid, target_ip="192.168.1.130")
+ # ARP Announcement from bridge (not to be learned by AP for proxyarp)
+ send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.130",
+ target_ip="192.168.1.130")
+ send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.130",
+ target_ip="192.168.1.130", opcode=2)
+
+ matches = get_permanent_neighbors("ap-br0")
+ logger.info("After ARP Probe + Announcement: " + str(matches))
+
+ # ARP Request for the newly introduced IP address from wireless STA
+ send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.130")
+ # ARP Response from bridge (AP does not proxy for non-wireless devices)
+ send_arp(hapd, hapd_bssid=bssid, dst_ll=addr0, sender_ip="192.168.1.130",
+ target_ip="192.168.1.123", opcode=2)
+
+ # ARP Request for the newly introduced IP address from bridge
+ send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.102",
+ target_ip="192.168.1.130")
+
+ # ARP Probe from wireless STA (duplicate address; learned through DHCP)
+ send_arp(dev[1], target_ip="192.168.1.123")
+ # ARP Probe from wireless STA (duplicate address; learned through ARP)
+ send_arp(dev[0], target_ip="192.168.1.127")
+
+ # Gratuitous ARP Reply for another STA's IP address
+ send_arp(dev[0], opcode=2, sender_mac=addr0, sender_ip="192.168.1.127",
+ target_mac=addr1, target_ip="192.168.1.127")
+ send_arp(dev[1], opcode=2, sender_mac=addr1, sender_ip="192.168.1.123",
+ target_mac=addr0, target_ip="192.168.1.123")
+ # ARP Request to verify previous mapping
+ send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.123")
+ send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.127")
+
+ time.sleep(0.1)
+
+ send_ns(dev[0], target="aaaa:bbbb:dddd::2", ip_src="aaaa:bbbb:cccc::2")
+ time.sleep(0.1)
+ send_ns(dev[1], target="aaaa:bbbb:cccc::2", ip_src="aaaa:bbbb:dddd::2")
+ time.sleep(0.1)
+ send_ns(hapd, hapd_bssid=bssid, target="aaaa:bbbb:dddd::2",
+ ip_src="aaaa:bbbb:ffff::2")
+ time.sleep(0.1)
+
+ # Try to probe for an already assigned address
+ send_ns(dev[1], target="aaaa:bbbb:cccc::2", ip_src="::")
+ time.sleep(0.1)
+ send_ns(hapd, hapd_bssid=bssid, target="aaaa:bbbb:cccc::2", ip_src="::")
+ time.sleep(0.1)
+
+ # Unsolicited NA
+ send_na(dev[1], target="aaaa:bbbb:cccc:aeae::3",
+ ip_src="aaaa:bbbb:cccc:aeae::3", ip_dst="ff02::1")
+ send_na(hapd, hapd_bssid=bssid, target="aaaa:bbbb:cccc:aeae::4",
+ ip_src="aaaa:bbbb:cccc:aeae::4", ip_dst="ff02::1")
+
+ hwsim_utils.test_connectivity_iface(dev[0], hapd, "ap-br0")
+ hwsim_utils.test_connectivity_iface(dev[1], hapd, "ap-br0")
+ hwsim_utils.test_connectivity(dev[0], dev[1])
dev[0].request("DISCONNECT")
dev[1].request("DISCONNECT")
time.sleep(0.5)
+ for i in range(3):
+ cmd[i].terminate()
matches = get_permanent_neighbors("ap-br0")
logger.info("After disconnect: " + str(matches))
if len(matches) > 0:
raise Exception("Unexpected neighbor entries after disconnect")
+ cmd = subprocess.Popen(['ebtables', '-L', '--Lc'], stdout=subprocess.PIPE)
+ res = cmd.stdout.read()
+ cmd.stdout.close()
+ logger.info("ebtables results:\n" + res)
-def test_proxyarp_open(dev, apdev):
+def test_proxyarp_open(dev, apdev, params):
"""ProxyARP with open network"""
- res = None
try:
- res = _test_proxyarp_open(dev, apdev)
+ _test_proxyarp_open(dev, apdev, params)
finally:
+ try:
+ subprocess.call(['ebtables', '-F', 'FORWARD'])
+ subprocess.call(['ebtables', '-F', 'OUTPUT'])
+ except:
+ pass
subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
stderr=open('/dev/null', 'w'))
subprocess.call(['brctl', 'delbr', 'ap-br0'],
stderr=open('/dev/null', 'w'))
-
- return res