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>
This commit is contained in:
Jouni Malinen 2014-12-10 19:25:35 +02:00 committed by Jouni Malinen
parent 1872c52b8e
commit d9f3bb1ad6

View file

@ -2528,13 +2528,58 @@ def build_dhcp_ack(dst_ll, src_ll, ip_src, ip_dst, yiaddr, chaddr,
return ehdr + ipv4 + udp 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): def get_permanent_neighbors(ifname):
cmd = subprocess.Popen(['ip', 'nei'], stdout=subprocess.PIPE) cmd = subprocess.Popen(['ip', 'nei'], stdout=subprocess.PIPE)
res = cmd.stdout.read() res = cmd.stdout.read()
cmd.stdout.close() cmd.stdout.close()
return [ line for line in res.splitlines() if "PERMANENT" in line and ifname in line ] 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'] bssid = apdev[0]['bssid']
params = { 'ssid': 'open' } params = { 'ssid': 'open' }
params['proxy_arp'] = '1' params['proxy_arp'] = '1'
@ -2557,6 +2602,14 @@ def _test_proxyarp_open(dev, apdev):
subprocess.call(['brctl', 'setfd', 'ap-br0', '0']) subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up']) 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[0].connect("open", key_mgmt="NONE", scan_freq="2412")
dev[1].connect("open", key_mgmt="NONE", scan_freq="2412") dev[1].connect("open", key_mgmt="NONE", scan_freq="2412")
time.sleep(0.1) 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: 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") 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[0].request("DISCONNECT")
dev[1].request("DISCONNECT") dev[1].request("DISCONNECT")
time.sleep(0.5) time.sleep(0.5)
for i in range(3):
cmd[i].terminate()
matches = get_permanent_neighbors("ap-br0") matches = get_permanent_neighbors("ap-br0")
logger.info("After disconnect: " + str(matches)) logger.info("After disconnect: " + str(matches))
if len(matches) > 0: if len(matches) > 0:
raise Exception("Unexpected neighbor entries after disconnect") raise Exception("Unexpected neighbor entries after disconnect")
def test_proxyarp_open(dev, apdev): def test_proxyarp_open(dev, apdev, params):
"""ProxyARP with open network""" """ProxyARP with open network"""
res = None res = None
try: try:
res = _test_proxyarp_open(dev, apdev) res = _test_proxyarp_open(dev, apdev, params)
finally: finally:
subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'], subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
stderr=open('/dev/null', 'w')) stderr=open('/dev/null', 'w'))