From d9f3bb1ad6d2b942faae9c4397cf15797dce9355 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 10 Dec 2014 19:25:35 +0200 Subject: [PATCH] tests: ProxyARP ARP processing This verifies processing of various ARP messages at an AP that enables ProxyARP. All the validation steps have not yet been scripted, i.e., the sniffer traces need manual analysis for full coverage. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_hs20.py | 121 +++++++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 3 deletions(-) diff --git a/tests/hwsim/test_ap_hs20.py b/tests/hwsim/test_ap_hs20.py index 4a20d16b1..335c1cd61 100644 --- a/tests/hwsim/test_ap_hs20.py +++ b/tests/hwsim/test_ap_hs20.py @@ -2528,13 +2528,58 @@ def build_dhcp_ack(dst_ll, src_ll, ip_src, ip_dst, yiaddr, chaddr, 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="ff:ff:ff:ff:ff:ff", 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' @@ -2557,6 +2602,14 @@ def _test_proxyarp_open(dev, apdev): subprocess.call(['brctl', 'setfd', 'ap-br0', '0']) subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up']) + cmd = {} + cmd[0] = subprocess.Popen(['tcpdump', '-i', 'ap-br0', '-w', cap_br, + '-s', '2000'], stderr=open('/dev/null', 'w')) + cmd[1] = subprocess.Popen(['tcpdump', '-i', dev[0].ifname, '-w', cap_dev0, + '-s', '2000'], stderr=open('/dev/null', 'w')) + cmd[2] = subprocess.Popen(['tcpdump', '-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) @@ -2696,19 +2749,81 @@ def _test_proxyarp_open(dev, apdev): 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.128") + # ARP Announcement from bridge + send_arp(hapd, hapd_bssid=bssid, sender_ip="129.168.1.128", + target_ip="192.168.1.128") + send_arp(hapd, hapd_bssid=bssid, sender_ip="129.168.1.128", + target_ip="192.168.1.128", 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.128") + + # 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.128") + + # 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) + 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") -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) + res = _test_proxyarp_open(dev, apdev, params) finally: subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'], stderr=open('/dev/null', 'w'))