summaryrefslogtreecommitdiff
path: root/regress
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2015-11-05 01:49:13 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2015-11-05 01:49:13 +0000
commit4b70165318fbb2e7c3898c85a1eb9b42ebe12637 (patch)
tree26852e0da2dde61d7935b8a8f08749702e6fef4b /regress
parente4341883f464f9781001e6a625417f4570553359 (diff)
Add regression tests for the ARP implementation in the kernel. Send
multiple ARP packets to a remote machine with Scapy. Check ARP replies, table entries and log messages. All log messages in in_arpinput() are generated. Proxy ARP is also tested.
Diffstat (limited to 'regress')
-rw-r--r--regress/sys/netinet/arp/LICENSE13
-rw-r--r--regress/sys/netinet/arp/Makefile227
-rw-r--r--regress/sys/netinet/arp/README16
-rw-r--r--regress/sys/netinet/arp/arp_announcement.py51
-rw-r--r--regress/sys/netinet/arp/arp_broadcast.py22
-rw-r--r--regress/sys/netinet/arp/arp_fake.py22
-rw-r--r--regress/sys/netinet/arp/arp_gratuitous.py24
-rw-r--r--regress/sys/netinet/arp/arp_multicast.py50
-rw-r--r--regress/sys/netinet/arp/arp_other.py22
-rw-r--r--regress/sys/netinet/arp/arp_otherfake.py22
-rw-r--r--regress/sys/netinet/arp/arp_probe.py51
-rw-r--r--regress/sys/netinet/arp/arp_proxy.py48
-rw-r--r--regress/sys/netinet/arp/arp_request.py50
13 files changed, 618 insertions, 0 deletions
diff --git a/regress/sys/netinet/arp/LICENSE b/regress/sys/netinet/arp/LICENSE
new file mode 100644
index 00000000000..e51b04edb72
--- /dev/null
+++ b/regress/sys/netinet/arp/LICENSE
@@ -0,0 +1,13 @@
+# Copyright (c) 2015 Alexander Bluhm <bluhm@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/regress/sys/netinet/arp/Makefile b/regress/sys/netinet/arp/Makefile
new file mode 100644
index 00000000000..e178d0c19dc
--- /dev/null
+++ b/regress/sys/netinet/arp/Makefile
@@ -0,0 +1,227 @@
+# $OpenBSD: Makefile,v 1.1.1.1 2015/11/05 01:49:12 bluhm Exp $
+
+# The following ports must be installed:
+#
+# python-2.7 interpreted object-oriented programming language
+# py-libdnet python interface to libdnet
+# scapy powerful interactive packet manipulation in python
+
+# Check wether all required python packages are installed. If some
+# are missing print a warning and skip the tests, but do not fail.
+PYTHON_IMPORT != python2.7 -c 'from scapy.all import *' 2>&1 || true
+.if ! empty(PYTHON_IMPORT)
+regress:
+ @echo '${PYTHON_IMPORT}'
+ @echo install python and the scapy module for additional tests
+.endif
+
+# This test needs a manual setup of two machines
+# Set up machines: LOCAL REMOTE
+# LOCAL is the machine where this makefile is running.
+# REMOTE is running OpenBSD with ARP to test the Address Resolution Protocol.
+# FAKE is an non existing machine, its IP is used in the tests.
+# OTHER is an IP on REMOTE, but configured on another interface.
+# OTHERFAKE is an non existing IP on another interface.
+# REMOTE_SSH is the hostname to log in on the REMOTE machine.
+
+# Configure Addresses on the machines.
+# Adapt interface and addresse variables to your local setup.
+#
+LOCAL_IF ?=
+LOCAL_MAC ?=
+REMOTE_MAC ?=
+FAKE_MAC ?= 12:34:56:78:9a:bc
+REMOTE_SSH ?=
+
+LOCAL_ADDR ?= 10.188.70.17
+REMOTE_ADDR ?= 10.188.70.70
+FAKE_ADDR ?= 10.188.70.188
+OTHER_ADDR ?= 10.188.211.70
+OTHERFAKE_ADDR ?= 10.188.211.188
+
+.if empty (LOCAL_IF) || empty (LOCAL_MAC) || empty (REMOTE_MAC) || \
+ empty (FAKE_MAC) || empty (REMOTE_SSH) || empty (LOCAL_ADDR) || \
+ empty (REMOTE_ADDR) || empty (FAKE_ADDR) || empty (OTHER_ADDR) || \
+ empty (OTHERFAKE_ADDR)
+regress:
+ @echo this tests needs a remote machine to operate on
+ @echo LOCAL_IF LOCAL_MAC REMOTE_MAC FAKE_MAC REMOTE_SSH LOCAL_ADDR
+ @echo REMOTE_ADDR FAKE_ADDR OTHER_ADDR OTHERFAKE_ADDR are empty
+ @echo fill out these variables for additional tests
+.endif
+
+depend: addr.py
+
+# Create python include file containing the addresses.
+addr.py: Makefile
+ rm -f $@ $@.tmp
+ echo 'LOCAL_IF = "${LOCAL_IF}"' >>$@.tmp
+.for var in LOCAL REMOTE FAKE
+ echo '${var}_MAC = "${${var}_MAC}"' >>$@.tmp
+.endfor
+.for var in LOCAL REMOTE FAKE OTHER OTHERFAKE
+ echo '${var}_ADDR = "${${var}_ADDR}"' >>$@.tmp
+.endfor
+ mv $@.tmp $@
+
+# Set variables so that make runs with and without obj directory.
+# Only do that if necessary to keep visible output short.
+.if ${.CURDIR} == ${.OBJDIR}
+PYTHON = python2.7 ./
+.else
+PYTHON = PYTHONPATH=${.OBJDIR} python2.7 ${.CURDIR}/
+.endif
+
+# Clear arp cache and ping all addresses. This ensures that
+# the ip addresses are configured and all routing table are set up
+# to allow bidirectional packet flow.
+TARGETS += ping
+run-regress-ping:
+ @echo '\n======== $@ ========'
+ ${SUDO} arp -da
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -da
+.for ip in LOCAL_ADDR REMOTE_ADDR
+ @echo Check ping ${ip}
+ ping -n -c 1 ${${ip}}
+.endfor
+
+TARGETS += arp-request
+run-regress-arp-request: addr.py
+ @echo '\n======== $@ ========'
+ @echo Send ARP Request for remote address and insert local address
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -d ${LOCAL_ADDR}
+ ${SUDO} ${PYTHON}arp_request.py
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -an >arp.log
+ grep '^${LOCAL_ADDR} .* ${LOCAL_MAC} ' arp.log
+
+TARGETS += arp-multicast
+run-regress-arp-multicast: addr.py
+ @echo '\n======== $@ ========'
+ @echo Send ARP Request and overwrite entry with multicast ethernet
+ ssh -t ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -s ${LOCAL_ADDR} ${LOCAL_MAC} temp
+ scp ${REMOTE_SSH}:/var/log/messages old.log
+ ${SUDO} ${PYTHON}arp_multicast.py
+ scp ${REMOTE_SSH}:/var/log/messages new.log
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -an >arp.log
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -d ${LOCAL_ADDR}
+ diff old.log new.log | grep '^> ' >diff.log
+ grep 'bsd: arp info overwritten for ${LOCAL_ADDR} by 33:33:33:33:33:33' diff.log
+ grep '^${LOCAL_ADDR} .* ${LOCAL_MAC} ' arp.log
+
+TARGETS += arp-probe
+run-regress-arp-probe: addr.py
+ @echo '\n======== $@ ========'
+ @echo Send ARP Probe for existing address and expect correct reply
+ ${SUDO} ${PYTHON}arp_probe.py
+
+TARGETS += arp-broadcast
+run-regress-arp-broadcast: addr.py
+ @echo '\n======== $@ ========'
+ @echo Send ARP Request with broadcast as sender hardware address
+ ssh -t ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
+ scp ${REMOTE_SSH}:/var/log/messages old.log
+ ${SUDO} ${PYTHON}arp_broadcast.py
+ scp ${REMOTE_SSH}:/var/log/messages new.log
+ diff old.log new.log | grep '^> ' >diff.log
+ grep 'bsd: arp: ether address is broadcast for IP address ${LOCAL_ADDR}' diff.log
+
+TARGETS += arp-announcement
+run-regress-arp-announcement: addr.py
+ @echo '\n======== $@ ========'
+ @echo Send ARP Announcement for existing address
+ ssh -t ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
+ scp ${REMOTE_SSH}:/var/log/messages old.log
+ ${SUDO} ${PYTHON}arp_announcement.py
+ scp ${REMOTE_SSH}:/var/log/messages new.log
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -an >arp.log
+ diff old.log new.log | grep '^> ' >diff.log
+ grep 'bsd: duplicate IP address ${REMOTE_ADDR} sent from ethernet address ${LOCAL_MAC}' diff.log
+ grep '^${REMOTE_ADDR} .* ${REMOTE_MAC} .* permanent ' arp.log
+
+TARGETS += arp-gratuitous
+run-regress-arp-gratuitous: addr.py
+ @echo '\n======== $@ ========'
+ @echo Send Gratuitous ARP for existing address
+ ssh -t ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
+ scp ${REMOTE_SSH}:/var/log/messages old.log
+ ${SUDO} ${PYTHON}arp_gratuitous.py
+ scp ${REMOTE_SSH}:/var/log/messages new.log
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -an >arp.log
+ diff old.log new.log | grep '^> ' >diff.log
+ grep 'bsd: duplicate IP address ${REMOTE_ADDR} sent from ethernet address ${LOCAL_MAC}' diff.log
+ grep '^${REMOTE_ADDR} .* ${REMOTE_MAC} .* permanent ' arp.log
+
+TARGETS += arp-permanent
+run-regress-arp-permanent: addr.py
+ @echo '\n======== $@ ========'
+ @echo Send ARP Request to change permanent fake address
+ ssh -t ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -s ${FAKE_ADDR} ${FAKE_MAC} permanent
+ scp ${REMOTE_SSH}:/var/log/messages old.log
+ ${SUDO} ${PYTHON}arp_fake.py
+ scp ${REMOTE_SSH}:/var/log/messages new.log
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -an >arp.log
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -d ${FAKE_ADDR}
+ diff old.log new.log | grep '^> ' >diff.log
+ grep 'bsd: arp: attempt to overwrite permanent entry for ${FAKE_ADDR} by ${LOCAL_MAC}' diff.log
+ grep '^${FAKE_ADDR} .* ${FAKE_MAC} .* permanent ' arp.log
+
+TARGETS += arp-address
+run-regress-arp-address: addr.py
+ @echo '\n======== $@ ========'
+ @echo Send ARP Request to change address on other interface
+ ssh -t ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
+ scp ${REMOTE_SSH}:/var/log/messages old.log
+ ${SUDO} ${PYTHON}arp_other.py
+ scp ${REMOTE_SSH}:/var/log/messages new.log
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -an >arp.log
+ diff old.log new.log | grep '^> ' >diff.log
+ grep 'bsd: arp: attempt to overwrite permanent entry for ${OTHER_ADDR} by ${LOCAL_MAC}' diff.log
+ grep '^${OTHER_ADDR} .* permanent ' arp.log
+
+TARGETS += arp-temporary
+run-regress-arp-temporary: addr.py
+ @echo '\n======== $@ ========'
+ @echo Send ARP Request to change temporary entry on other interface
+ ssh -t ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -s ${OTHERFAKE_ADDR} ${FAKE_MAC} temp
+ scp ${REMOTE_SSH}:/var/log/messages old.log
+ ${SUDO} ${PYTHON}arp_otherfake.py
+ scp ${REMOTE_SSH}:/var/log/messages new.log
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -an >arp.log
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -d ${OTHERFAKE_ADDR}
+ diff old.log new.log | grep '^> ' >diff.log
+ grep 'bsd: arp: attempt to overwrite entry for ${OTHERFAKE_ADDR} on .* by ${LOCAL_MAC} on .*' diff.log
+ grep '^${OTHERFAKE_ADDR} .* ${FAKE_MAC} ' arp.log
+
+TARGETS += arp-incomlete
+run-regress-arp-incomlete: addr.py
+ @echo '\n======== $@ ========'
+ @echo Send ARP Request filling an incomplete entry on other interface
+ ssh -t ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
+ ssh -t ${REMOTE_SSH} ${SUDO} ping -n -w 1 -c 1 ${OTHERFAKE_ADDR} || true
+ scp ${REMOTE_SSH}:/var/log/messages old.log
+ ${SUDO} ${PYTHON}arp_otherfake.py
+ scp ${REMOTE_SSH}:/var/log/messages new.log
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -an >arp.log
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -d ${OTHERFAKE_ADDR}
+ diff old.log new.log | grep '^> ' >diff.log
+ grep 'bsd: arp: attempt to add entry for ${OTHERFAKE_ADDR} on .* by ${LOCAL_MAC} on .*' diff.log
+ grep '^${OTHERFAKE_ADDR} .* (incomplete) ' arp.log
+
+TARGETS += arp-proxy
+run-regress-arp-proxy: addr.py
+ @echo '\n======== $@ ========'
+ @echo Send ARP Request for fake address that is proxied
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -s ${FAKE_ADDR} ${FAKE_MAC} pub
+ ${SUDO} ${PYTHON}arp_proxy.py
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -an >arp.log
+ ssh -t ${REMOTE_SSH} ${SUDO} arp -d ${FAKE_ADDR}
+ grep '^${FAKE_ADDR} .* ${FAKE_MAC} .* static .* p' arp.log
+
+REGRESS_TARGETS = ${TARGETS:S/^/run-regress-/}
+
+CLEANFILES += addr.py *.pyc *.log
+
+.include <bsd.regress.mk>
diff --git a/regress/sys/netinet/arp/README b/regress/sys/netinet/arp/README
new file mode 100644
index 00000000000..2f44956ff16
--- /dev/null
+++ b/regress/sys/netinet/arp/README
@@ -0,0 +1,16 @@
+Regression tests for the ARP implementation in the kernel.
+
+The test suite runs on the machine LOCAL, the kernel under test is
+running on REMOTE. On LOCAL Scapy is generating ARP packes and
+sends them to REMOTE. The replies to LOCAL are analyzed. The
+kernel log files are fetched from REMOTE via SCP and grepped for
+messages. The ARP table of REMOTE is inspected via SSH login.
+
+Interfaces and adresses on REMOTE and LOCAL must be preconfigured.
+The test manually adds entries into the REMOTE ARP table and tries
+to overwrite them with fake ARP packets. Some addresses are on the
+REMOTE interface facing LOCAL other are on a second interface. The
+ARP input code has different cases for that. So all possible log
+messages from ARP input can be triggered by a subtest.
+
+Additionally check that REMOTE can answer a Proxy ARP Requests.
diff --git a/regress/sys/netinet/arp/arp_announcement.py b/regress/sys/netinet/arp/arp_announcement.py
new file mode 100644
index 00000000000..004bc134771
--- /dev/null
+++ b/regress/sys/netinet/arp/arp_announcement.py
@@ -0,0 +1,51 @@
+#!/usr/local/bin/python2.7
+# send Address Resolution Protocol Announcement
+# expect Address Resolution Protocol response and check all fields
+# RFC 5227 IPv4 Address Conflict Detection
+# 2.3. Announcing an Address
+
+import os
+from addr import *
+from scapy.all import *
+
+arp=ARP(op='who-has', hwsrc=LOCAL_MAC, psrc=REMOTE_ADDR,
+ hwdst="00:00:00:00:00:00", pdst=REMOTE_ADDR)
+eth=Ether(src=LOCAL_MAC, dst="ff:ff:ff:ff:ff:ff")/arp
+
+e=srp1(eth, iface=LOCAL_IF, timeout=2)
+
+if e and e.type == ETH_P_ARP:
+ a=e.payload
+ if a.hwtype != ARPHDR_ETHER:
+ print "HWTYPE=%#0.4x != ARPHDR_ETHER" % (a.hwtype)
+ exit(1)
+ if a.ptype != ETH_P_IP:
+ print "PTYPE=%#0.4x != ETH_P_IP" % (a.ptype)
+ exit(1)
+ if a.hwlen != 6:
+ print "HWLEN=%d != 6" % (a.hwlen)
+ exit(1)
+ if a.plen != 4:
+ print "PLEN=%d != 4" % (a.plen)
+ exit(1)
+ # XXX we should get a request from the defender, rfc5227 2.4 (3)
+ if a.op != 2:
+ print "OP=%s != is-at" % (a.op)
+ exit(1)
+ if a.hwsrc != REMOTE_MAC:
+ print "HWLOCAL=%s != REMOTE_MAC" % (a.hwsrc)
+ exit(1)
+ if a.psrc != REMOTE_ADDR:
+ print "PLOCAL=%s != REMOTE_ADDR" % (a.psrc)
+ exit(1)
+ if a.hwdst != LOCAL_MAC:
+ print "HWREMOTE=%s != LOCAL_MAC" % (a.hwdst)
+ exit(1)
+ if a.pdst != REMOTE_ADDR:
+ print "PREMOTE=%s != REMOTE_ADDR" % (a.pdst)
+ exit(1)
+ print "arp reply"
+ exit(0)
+
+print "NO ARP REPLY"
+exit(2)
diff --git a/regress/sys/netinet/arp/arp_broadcast.py b/regress/sys/netinet/arp/arp_broadcast.py
new file mode 100644
index 00000000000..14b3c4f3b94
--- /dev/null
+++ b/regress/sys/netinet/arp/arp_broadcast.py
@@ -0,0 +1,22 @@
+#!/usr/local/bin/python2.7
+# send Address Resolution Protocol Request to Ethernet broadcast address
+# expect no answer
+
+import os
+from addr import *
+from scapy.all import *
+
+arp=ARP(op='who-has', hwsrc="ff:ff:ff:ff:ff:ff", psrc=LOCAL_ADDR,
+ hwdst="ff:ff:ff:ff:ff:ff", pdst=REMOTE_ADDR)
+eth=Ether(src=LOCAL_MAC, dst="ff:ff:ff:ff:ff:ff")/arp
+
+e=srp1(eth, iface=LOCAL_IF, timeout=2)
+
+if e and e.type == ETH_P_ARP:
+ a=e.payload
+ a.show()
+ print "ARP REPLY"
+ exit(1)
+
+print "no arp reply"
+exit(0)
diff --git a/regress/sys/netinet/arp/arp_fake.py b/regress/sys/netinet/arp/arp_fake.py
new file mode 100644
index 00000000000..40b41de1aa3
--- /dev/null
+++ b/regress/sys/netinet/arp/arp_fake.py
@@ -0,0 +1,22 @@
+#!/usr/local/bin/python2.7
+# send Address Resolution Protocol Request to modify fake address
+# expect no answer
+
+import os
+from addr import *
+from scapy.all import *
+
+arp=ARP(op='who-has', hwsrc=LOCAL_MAC, psrc=FAKE_ADDR,
+ hwdst="ff:ff:ff:ff:ff:ff", pdst=REMOTE_ADDR)
+eth=Ether(src=LOCAL_MAC, dst="ff:ff:ff:ff:ff:ff")/arp
+
+e=srp1(eth, iface=LOCAL_IF, timeout=2)
+
+if e and e.type == ETH_P_ARP:
+ a=e.payload
+ a.show()
+ print "ARP REPLY"
+ exit(1)
+
+print "no arp reply"
+exit(0)
diff --git a/regress/sys/netinet/arp/arp_gratuitous.py b/regress/sys/netinet/arp/arp_gratuitous.py
new file mode 100644
index 00000000000..4cf7976c74a
--- /dev/null
+++ b/regress/sys/netinet/arp/arp_gratuitous.py
@@ -0,0 +1,24 @@
+#!/usr/local/bin/python2.7
+# send Gratuitous Address Resolution Protocol Reply
+# expect no answer
+# RFC 2002 IP Mobility Support
+# 4.6. ARP, Proxy ARP, and Gratuitous ARP
+
+import os
+from addr import *
+from scapy.all import *
+
+arp=ARP(op='is-at', hwsrc=LOCAL_MAC, psrc=REMOTE_ADDR,
+ hwdst=LOCAL_MAC, pdst=REMOTE_ADDR)
+eth=Ether(src=LOCAL_MAC, dst="ff:ff:ff:ff:ff:ff")/arp
+
+e=srp1(eth, iface=LOCAL_IF, timeout=2)
+
+if e and e.type == ETH_P_ARP:
+ a=e.payload
+ a.show()
+ print "ARP REPLY"
+ exit(1)
+
+print "no arp reply"
+exit(0)
diff --git a/regress/sys/netinet/arp/arp_multicast.py b/regress/sys/netinet/arp/arp_multicast.py
new file mode 100644
index 00000000000..d8310cd50a1
--- /dev/null
+++ b/regress/sys/netinet/arp/arp_multicast.py
@@ -0,0 +1,50 @@
+#!/usr/local/bin/python2.7
+# send Address Resolution Protocol Request with ethernet multicast sender
+# expect Address Resolution Protocol response and check all fields
+# RFC 826 An Ethernet Address Resolution Protocol
+# Packet Generation
+
+import os
+from addr import *
+from scapy.all import *
+
+arp=ARP(op='who-has', hwsrc="33:33:33:33:33:33", psrc=LOCAL_ADDR,
+ hwdst="ff:ff:ff:ff:ff:ff", pdst=REMOTE_ADDR)
+eth=Ether(src=LOCAL_MAC, dst="ff:ff:ff:ff:ff:ff")/arp
+
+e=srp1(eth, iface=LOCAL_IF, timeout=2)
+
+if e and e.type == ETH_P_ARP:
+ a=e.payload
+ if a.hwtype != ARPHDR_ETHER:
+ print "HWTYPE=%#0.4x != ARPHDR_ETHER" % (a.hwtype)
+ exit(1)
+ if a.ptype != ETH_P_IP:
+ print "PTYPE=%#0.4x != ETH_P_IP" % (a.ptype)
+ exit(1)
+ if a.hwlen != 6:
+ print "HWLEN=%d != 6" % (a.hwlen)
+ exit(1)
+ if a.plen != 4:
+ print "PLEN=%d != 4" % (a.plen)
+ exit(1)
+ if a.op != 2:
+ print "OP=%s != is-at" % (a.op)
+ exit(1)
+ if a.hwsrc != REMOTE_MAC:
+ print "HWLOCAL=%s != REMOTE_MAC" % (a.hwsrc)
+ exit(1)
+ if a.psrc != REMOTE_ADDR:
+ print "PLOCAL=%s != REMOTE_ADDR" % (a.psrc)
+ exit(1)
+ if a.hwdst != "33:33:33:33:33:33":
+ print "HWREMOTE=%s != 33:33:33:33:33:33" % (a.hwdst)
+ exit(1)
+ if a.pdst != LOCAL_ADDR:
+ print "PREMOTE=%s != LOCAL_ADDR" % (a.pdst)
+ exit(1)
+ print "arp reply"
+ exit(0)
+
+print "NO ARP REPLY"
+exit(2)
diff --git a/regress/sys/netinet/arp/arp_other.py b/regress/sys/netinet/arp/arp_other.py
new file mode 100644
index 00000000000..0cdb6cffc46
--- /dev/null
+++ b/regress/sys/netinet/arp/arp_other.py
@@ -0,0 +1,22 @@
+#!/usr/local/bin/python2.7
+# send Address Resolution Protocol Request to modify other address
+# expect no answer
+
+import os
+from addr import *
+from scapy.all import *
+
+arp=ARP(op='who-has', hwsrc=LOCAL_MAC, psrc=OTHER_ADDR,
+ hwdst="ff:ff:ff:ff:ff:ff", pdst=REMOTE_ADDR)
+eth=Ether(src=LOCAL_MAC, dst="ff:ff:ff:ff:ff:ff")/arp
+
+e=srp1(eth, iface=LOCAL_IF, timeout=2)
+
+if e and e.type == ETH_P_ARP:
+ a=e.payload
+ a.show()
+ print "ARP REPLY"
+ exit(1)
+
+print "no arp reply"
+exit(0)
diff --git a/regress/sys/netinet/arp/arp_otherfake.py b/regress/sys/netinet/arp/arp_otherfake.py
new file mode 100644
index 00000000000..9b620ef14b8
--- /dev/null
+++ b/regress/sys/netinet/arp/arp_otherfake.py
@@ -0,0 +1,22 @@
+#!/usr/local/bin/python2.7
+# send Address Resolution Protocol Request to modify other fake address
+# expect no answer
+
+import os
+from addr import *
+from scapy.all import *
+
+arp=ARP(op='who-has', hwsrc=LOCAL_MAC, psrc=OTHERFAKE_ADDR,
+ hwdst="ff:ff:ff:ff:ff:ff", pdst=REMOTE_ADDR)
+eth=Ether(src=LOCAL_MAC, dst="ff:ff:ff:ff:ff:ff")/arp
+
+e=srp1(eth, iface=LOCAL_IF, timeout=2)
+
+if e and e.type == ETH_P_ARP:
+ a=e.payload
+ a.show()
+ print "ARP REPLY"
+ exit(1)
+
+print "no arp reply"
+exit(0)
diff --git a/regress/sys/netinet/arp/arp_probe.py b/regress/sys/netinet/arp/arp_probe.py
new file mode 100644
index 00000000000..09b505d7464
--- /dev/null
+++ b/regress/sys/netinet/arp/arp_probe.py
@@ -0,0 +1,51 @@
+#!/usr/local/bin/python2.7
+# send Address Resolution Protocol Probe
+# expect Address Resolution Protocol response and check all fields
+# RFC 5227 IPv4 Address Conflict Detection
+# 2.1.1. Probe Details
+
+
+import os
+from addr import *
+from scapy.all import *
+
+arp=ARP(op='who-has', hwsrc=LOCAL_MAC, psrc="0.0.0.0",
+ hwdst="00:00:00:00:00:00", pdst=REMOTE_ADDR)
+eth=Ether(src=LOCAL_MAC, dst="ff:ff:ff:ff:ff:ff")/arp
+
+e=srp1(eth, iface=LOCAL_IF, timeout=2)
+
+if e and e.type == ETH_P_ARP:
+ a=e.payload
+ if a.hwtype != ARPHDR_ETHER:
+ print "HWTYPE=%#0.4x != ARPHDR_ETHER" % (a.hwtype)
+ exit(1)
+ if a.ptype != ETH_P_IP:
+ print "PTYPE=%#0.4x != ETH_P_IP" % (a.ptype)
+ exit(1)
+ if a.hwlen != 6:
+ print "HWLEN=%d != 6" % (a.hwlen)
+ exit(1)
+ if a.plen != 4:
+ print "PLEN=%d != 4" % (a.plen)
+ exit(1)
+ if a.op != 2:
+ print "OP=%s != is-at" % (a.op)
+ exit(1)
+ if a.hwsrc != REMOTE_MAC:
+ print "HWLOCAL=%s != REMOTE_MAC" % (a.hwsrc)
+ exit(1)
+ if a.psrc != REMOTE_ADDR:
+ print "PLOCAL=%s != REMOTE_ADDR" % (a.psrc)
+ exit(1)
+ if a.hwdst != LOCAL_MAC:
+ print "HWREMOTE=%s != LOCAL_MAC" % (a.hwdst)
+ exit(1)
+ if a.pdst != "0.0.0.0":
+ print "PREMOTE=%s != 0.0.0.0" % (a.pdst)
+ exit(1)
+ print "arp reply"
+ exit(0)
+
+print "NO ARP REPLY"
+exit(2)
diff --git a/regress/sys/netinet/arp/arp_proxy.py b/regress/sys/netinet/arp/arp_proxy.py
new file mode 100644
index 00000000000..e6762c016f8
--- /dev/null
+++ b/regress/sys/netinet/arp/arp_proxy.py
@@ -0,0 +1,48 @@
+#!/usr/local/bin/python2.7
+# send Address Resolution Protocol Request for Proxy ARP
+# expect Address Resolution Protocol fake response and check all fields
+
+import os
+from addr import *
+from scapy.all import *
+
+arp=ARP(op='who-has', hwsrc=LOCAL_MAC, psrc=LOCAL_ADDR,
+ hwdst="ff:ff:ff:ff:ff:ff", pdst=FAKE_ADDR)
+eth=Ether(src=LOCAL_MAC, dst="ff:ff:ff:ff:ff:ff")/arp
+
+e=srp1(eth, iface=LOCAL_IF, timeout=2)
+
+if e and e.type == ETH_P_ARP:
+ a=e.payload
+ if a.hwtype != ARPHDR_ETHER:
+ print "HWTYPE=%#0.4x != ARPHDR_ETHER" % (a.hwtype)
+ exit(1)
+ if a.ptype != ETH_P_IP:
+ print "PTYPE=%#0.4x != ETH_P_IP" % (a.ptype)
+ exit(1)
+ if a.hwlen != 6:
+ print "HWLEN=%d != 6" % (a.hwlen)
+ exit(1)
+ if a.plen != 4:
+ print "PLEN=%d != 4" % (a.plen)
+ exit(1)
+ if a.op != 2:
+ print "OP=%s != is-at" % (a.op)
+ exit(1)
+ if a.hwsrc != FAKE_MAC:
+ print "HWLOCAL=%s != FAKE_MAC" % (a.hwsrc)
+ exit(1)
+ if a.psrc != FAKE_ADDR:
+ print "PLOCAL=%s != FAKE_ADDR" % (a.psrc)
+ exit(1)
+ if a.hwdst != LOCAL_MAC:
+ print "HWREMOTE=%s != LOCAL_MAC" % (a.hwdst)
+ exit(1)
+ if a.pdst != LOCAL_ADDR:
+ print "PREMOTE=%s != LOCAL_ADDR" % (a.pdst)
+ exit(1)
+ print "arp reply"
+ exit(0)
+
+print "NO ARP REPLY"
+exit(2)
diff --git a/regress/sys/netinet/arp/arp_request.py b/regress/sys/netinet/arp/arp_request.py
new file mode 100644
index 00000000000..d974c6330c2
--- /dev/null
+++ b/regress/sys/netinet/arp/arp_request.py
@@ -0,0 +1,50 @@
+#!/usr/local/bin/python2.7
+# send Address Resolution Protocol Request
+# expect Address Resolution Protocol response and check all fields
+# RFC 826 An Ethernet Address Resolution Protocol
+# Packet Generation
+
+import os
+from addr import *
+from scapy.all import *
+
+arp=ARP(op='who-has', hwsrc=LOCAL_MAC, psrc=LOCAL_ADDR,
+ hwdst="ff:ff:ff:ff:ff:ff", pdst=REMOTE_ADDR)
+eth=Ether(src=LOCAL_MAC, dst="ff:ff:ff:ff:ff:ff")/arp
+
+e=srp1(eth, iface=LOCAL_IF, timeout=2)
+
+if e and e.type == ETH_P_ARP:
+ a=e.payload
+ if a.hwtype != ARPHDR_ETHER:
+ print "HWTYPE=%#0.4x != ARPHDR_ETHER" % (a.hwtype)
+ exit(1)
+ if a.ptype != ETH_P_IP:
+ print "PTYPE=%#0.4x != ETH_P_IP" % (a.ptype)
+ exit(1)
+ if a.hwlen != 6:
+ print "HWLEN=%d != 6" % (a.hwlen)
+ exit(1)
+ if a.plen != 4:
+ print "PLEN=%d != 4" % (a.plen)
+ exit(1)
+ if a.op != 2:
+ print "OP=%s != is-at" % (a.op)
+ exit(1)
+ if a.hwsrc != REMOTE_MAC:
+ print "HWLOCAL=%s != REMOTE_MAC" % (a.hwsrc)
+ exit(1)
+ if a.psrc != REMOTE_ADDR:
+ print "PLOCAL=%s != REMOTE_ADDR" % (a.psrc)
+ exit(1)
+ if a.hwdst != LOCAL_MAC:
+ print "HWREMOTE=%s != LOCAL_MAC" % (a.hwdst)
+ exit(1)
+ if a.pdst != LOCAL_ADDR:
+ print "PREMOTE=%s != LOCAL_ADDR" % (a.pdst)
+ exit(1)
+ print "arp reply"
+ exit(0)
+
+print "NO ARP REPLY"
+exit(2)