Parcourir la source

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 <jouni@qca.qualcomm.com>
Jouni Malinen il y a 10 ans
Parent
commit
d9f3bb1ad6
1 fichiers modifiés avec 118 ajouts et 3 suppressions
  1. 118 3
      tests/hwsim/test_ap_hs20.py

+ 118 - 3
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'))