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'))