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:
parent
1872c52b8e
commit
d9f3bb1ad6
1 changed files with 118 additions and 3 deletions
|
@ -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'))
|
||||||
|
|
Loading…
Reference in a new issue