From 326720c1db2e05fb5ca7ad87d6c1e39961b6d127 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 29 Jan 2017 01:20:43 +0200 Subject: [PATCH] tests: Split proxyarp test cases into IPv4 and IPv6 parts This is useful for now since the IPv6 support for proxyarp is not yet included in the upstream kernel. This allows the IPv4 test cases to pass with the current upstream kernel while allowing the IPv6 test cases to report SKIP instead of FAIL. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_hs20.py | 302 ++++++++++++++++++++++++---------- tests/hwsim/vm/parallel-vm.py | 2 + 2 files changed, 221 insertions(+), 83 deletions(-) diff --git a/tests/hwsim/test_ap_hs20.py b/tests/hwsim/test_ap_hs20.py index e4354750e..af501af22 100644 --- a/tests/hwsim/test_ap_hs20.py +++ b/tests/hwsim/test_ap_hs20.py @@ -4255,23 +4255,6 @@ def _test_proxyarp_open(dev, apdev, params, ebtables=False): 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']) time.sleep(0.5) cmd = {} @@ -4308,32 +4291,6 @@ def _test_proxyarp_open(dev, apdev, params, ebtables=False): addr1 = dev[1].p2p_interface_addr() addr2 = dev[2].p2p_interface_addr() - src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':','')) - src_ll_opt1 = "\x01\x01" + binascii.unhexlify(addr1.replace(':','')) - - # DAD NS - send_ns(dev[0], ip_src="::", target="aaaa:bbbb:cccc::2") - - send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2") - # test frame without source link-layer address option - send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2", - opt='') - # test frame with bogus option - 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 - 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 - 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) @@ -4405,14 +4362,8 @@ def _test_proxyarp_open(dev, apdev, params, ebtables=False): matches = get_permanent_neighbors("ap-br0") logger.info("After connect: " + str(matches)) - if len(matches) != 4: + if len(matches) != 1: 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 'aaaa:bbbb:dddd::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches: - 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") @@ -4498,38 +4449,6 @@ def _test_proxyarp_open(dev, apdev, params, ebtables=False): 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) - send_ns(dev[2], target="aaaa:bbbb:cccc::2", ip_src="aaaa:bbbb:ff00::2") - time.sleep(0.1) - send_ns(dev[2], target="aaaa:bbbb:dddd::2", ip_src="aaaa:bbbb:ff00::2") - time.sleep(0.1) - send_ns(dev[2], target="aaaa:bbbb:eeee::2", ip_src="aaaa:bbbb:ff00::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) - send_ns(dev[2], 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") - send_na(dev[2], target="aaaa:bbbb:cccc:aeae::5", - ip_src="aaaa:bbbb:cccc:aeae::5", ip_dst="ff02::1") - try: hwsim_utils.test_connectivity_iface(dev[0], hapd, "ap-br0") except Exception, e: @@ -4621,6 +4540,195 @@ def _test_proxyarp_open(dev, apdev, params, ebtables=False): # bssid, '192.168.1.101' ] not in arp_reply: # raise Exception("br did not get ARP response for 192.168.1.123") +def _test_proxyarp_open_ipv6(dev, apdev, params, ebtables=False): + prefix = "proxyarp_open" + if ebtables: + prefix += "_ebtables" + cap_br = os.path.join(params['logdir'], prefix + ".ap-br0.pcap") + cap_dev0 = os.path.join(params['logdir'], + prefix + ".%s.pcap" % dev[0].ifname) + cap_dev1 = os.path.join(params['logdir'], + prefix + ".%s.pcap" % dev[1].ifname) + cap_dev2 = os.path.join(params['logdir'], + prefix + ".%s.pcap" % dev[2].ifname) + + bssid = apdev[0]['bssid'] + params = { 'ssid': 'open' } + params['proxy_arp'] = '1' + hapd = hostapd.add_ap(apdev[0], params, no_enable=True) + hapd.set("ap_isolate", "1") + hapd.set('bridge', 'ap-br0') + hapd.dump_monitor() + 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", "AP-DISABLED"], timeout=10) + if ev is None: + raise Exception("AP startup timed out") + if "AP-ENABLED" not in ev: + raise Exception("AP startup failed") + + params2 = { 'ssid': 'another' } + hapd2 = hostapd.add_ap(apdev[1], params2, no_enable=True) + hapd2.set('bridge', 'ap-br0') + hapd2.enable() + + subprocess.call(['brctl', 'setfd', 'ap-br0', '0']) + subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up']) + + if ebtables: + for chain in [ 'FORWARD', 'OUTPUT' ]: + 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']) + + time.sleep(0.5) + 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')) + cmd[3] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[2].ifname, + '-w', cap_dev2, '-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") + dev[2].connect("another", key_mgmt="NONE", scan_freq="2412") + time.sleep(0.1) + + brcmd = subprocess.Popen(['brctl', 'show'], stdout=subprocess.PIPE) + res = brcmd.stdout.read() + brcmd.stdout.close() + logger.info("Bridge setup: " + res) + + brcmd = subprocess.Popen(['brctl', 'showstp', 'ap-br0'], + stdout=subprocess.PIPE) + res = brcmd.stdout.read() + brcmd.stdout.close() + logger.info("Bridge showstp: " + res) + + addr0 = dev[0].p2p_interface_addr() + addr1 = dev[1].p2p_interface_addr() + addr2 = dev[2].p2p_interface_addr() + + src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':','')) + src_ll_opt1 = "\x01\x01" + binascii.unhexlify(addr1.replace(':','')) + + # DAD NS + send_ns(dev[0], ip_src="::", target="aaaa:bbbb:cccc::2") + + send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2") + # test frame without source link-layer address option + send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2", + opt='') + # test frame with bogus option + 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 + 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 + 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") + + macs = get_bridge_macs("ap-br0") + logger.info("After connect (showmacs): " + str(macs)) + + matches = get_permanent_neighbors("ap-br0") + logger.info("After connect: " + str(matches)) + if len(matches) != 3: + 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 'aaaa:bbbb:dddd::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches: + 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") + + 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) + send_ns(dev[2], target="aaaa:bbbb:cccc::2", ip_src="aaaa:bbbb:ff00::2") + time.sleep(0.1) + send_ns(dev[2], target="aaaa:bbbb:dddd::2", ip_src="aaaa:bbbb:ff00::2") + time.sleep(0.1) + send_ns(dev[2], target="aaaa:bbbb:eeee::2", ip_src="aaaa:bbbb:ff00::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) + send_ns(dev[2], 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") + send_na(dev[2], target="aaaa:bbbb:cccc:aeae::5", + ip_src="aaaa:bbbb:cccc:aeae::5", ip_dst="ff02::1") + + try: + hwsim_utils.test_connectivity_iface(dev[0], hapd, "ap-br0") + except Exception, e: + logger.info("test_connectibity_iface failed: " + str(e)) + raise HwsimSkip("Assume kernel did not have the required patches for proxyarp") + 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(len(cmd)): + cmd[i].terminate() + macs = get_bridge_macs("ap-br0") + logger.info("After disconnect (showmacs): " + str(macs)) + matches = get_permanent_neighbors("ap-br0") + logger.info("After disconnect: " + str(matches)) + if len(matches) > 0: + raise Exception("Unexpected neighbor entries after disconnect") + if ebtables: + cmd = subprocess.Popen(['ebtables', '-L', '--Lc'], + stdout=subprocess.PIPE) + res = cmd.stdout.read() + cmd.stdout.close() + logger.info("ebtables results:\n" + res) + ns = tshark_get_ns(cap_dev0) logger.info("dev0 seen NS: " + str(ns)) na = tshark_get_na(cap_dev0) @@ -4628,7 +4736,10 @@ def _test_proxyarp_open(dev, apdev, params, ebtables=False): if [ addr0, addr1, 'aaaa:bbbb:dddd::2', 'aaaa:bbbb:cccc::2', 'aaaa:bbbb:dddd::2', addr1 ] not in na: - raise Exception("dev0 did not get NA for aaaa:bbbb:dddd::2") + # For now, skip the test instead of reporting the error since the IPv6 + # proxyarp support is not yet in the upstream kernel tree. + #raise Exception("dev0 did not get NA for aaaa:bbbb:dddd::2") + raise HwsimSkip("Assume kernel did not have the required patches for proxyarp (IPv6)") if ebtables: for req in ns: @@ -4675,6 +4786,16 @@ def test_proxyarp_open(dev, apdev, params): subprocess.call(['brctl', 'delbr', 'ap-br0'], stderr=open('/dev/null', 'w')) +def test_proxyarp_open_ipv6(dev, apdev, params): + """ProxyARP with open network (IPv6)""" + try: + _test_proxyarp_open_ipv6(dev, apdev, params) + 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_proxyarp_open_ebtables(dev, apdev, params): """ProxyARP with open network""" try: @@ -4690,6 +4811,21 @@ def test_proxyarp_open_ebtables(dev, apdev, params): subprocess.call(['brctl', 'delbr', 'ap-br0'], stderr=open('/dev/null', 'w')) +def test_proxyarp_open_ebtables_ipv6(dev, apdev, params): + """ProxyARP with open network (IPv6)""" + try: + _test_proxyarp_open_ipv6(dev, apdev, params, ebtables=True) + 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')) + def test_ap_hs20_connect_deinit(dev, apdev): """Hotspot 2.0 connection interrupted with deinit""" check_eap_capa(dev[0], "MSCHAPV2") diff --git a/tests/hwsim/vm/parallel-vm.py b/tests/hwsim/vm/parallel-vm.py index 40bbb7609..24661a1cf 100755 --- a/tests/hwsim/vm/parallel-vm.py +++ b/tests/hwsim/vm/parallel-vm.py @@ -58,10 +58,12 @@ long_tests = [ "ap_roam_open", "hostapd_oom_wpa2_eap", "ibss_open", "proxyarp_open_ebtables", + "proxyarp_open_ebtables_ipv6", "radius_failover", "obss_scan_40_intolerant", "dbus_connect_oom", "proxyarp_open", + "proxyarp_open_ipv6", "ap_wps_iteration", "ap_wps_iteration_error", "ap_wps_pbc_timeout",