1# $OpenBSD: Makefile,v 1.15 2020/12/30 21:40:33 kn Exp $ 2 3# The following ports must be installed: 4# 5# scapy powerful interactive packet manipulation in python 6 7.if ! exists(/usr/local/bin/scapy) 8regress: 9 @echo Install scapy package to run this regress. 10 @echo SKIPPED 11.endif 12 13# This test needs a manual setup of two machines 14# Set up machines: LOCAL REMOTE 15# LOCAL is the machine where this makefile is running. 16# REMOTE is running OpenBSD with ARP to test the Address Resolution Protocol. 17# FAKE is an non existing machine, its IP is used in the tests. 18# OTHER is an IP on REMOTE, but configured on another interface. 19# OTHER_FAKE is an non existing IP on another interface. 20# REMOTE_SSH is the hostname to log in on the REMOTE machine. 21 22# Configure Addresses on the machines. 23# Adapt interface and addresse variables to your local setup. 24# 25LOCAL_IF ?= 26LOCAL_MAC ?= 27REMOTE_MAC ?= 28FAKE_MAC ?= 12:34:56:78:9a:bc 29PROXY_MAC ?= 00:90:27:bb:cc:dd 30REMOTE_SSH ?= 31 32LOCAL_ADDR ?= 10.188.70.17 33REMOTE_ADDR ?= 10.188.70.70 34FAKE_ADDR ?= 10.188.70.188 35OTHER_ADDR ?= 10.188.211.70 36OTHER_FAKE_ADDR ?= 10.188.211.188 37 38.if empty (LOCAL_IF) || empty (LOCAL_MAC) || empty (REMOTE_MAC) || \ 39 empty (FAKE_MAC) || empty (REMOTE_SSH) || empty (LOCAL_ADDR) || \ 40 empty (REMOTE_ADDR) || empty (FAKE_ADDR) || empty (OTHER_ADDR) || \ 41 empty (OTHER_FAKE_ADDR) 42regress: 43 @echo this tests needs a remote machine to operate on 44 @echo LOCAL_IF LOCAL_MAC REMOTE_MAC FAKE_MAC REMOTE_SSH LOCAL_ADDR 45 @echo REMOTE_ADDR FAKE_ADDR OTHER_ADDR OTHER_FAKE_ADDR are empty 46 @echo fill out these variables for additional tests 47 @echo SKIPPED 48.endif 49 50.if ! empty (REMOTE_SSH) 51.if make (regress) || make (all) 52.BEGIN: 53 ${SUDO} true 54 ssh -t ${REMOTE_SSH} ${SUDO} true 55 @echo 56.endif 57.endif 58 59# Create python include file containing the addresses. 60addr.py: Makefile 61 rm -f $@ $@.tmp 62 echo 'LOCAL_IF = "${LOCAL_IF}"' >>$@.tmp 63.for var in LOCAL REMOTE FAKE 64 echo '${var}_MAC = "${${var}_MAC}"' >>$@.tmp 65.endfor 66.for var in LOCAL REMOTE FAKE OTHER OTHER_FAKE 67 echo '${var}_ADDR = "${${var}_ADDR}"' >>$@.tmp 68.endfor 69 mv $@.tmp $@ 70 71# Set variables so that make runs with and without obj directory. 72# Only do that if necessary to keep visible output short. 73.if ${.CURDIR} == ${.OBJDIR} 74PYTHON = python3 -u ./ 75.else 76PYTHON = PYTHONPATH=${.OBJDIR} python3 -u ${.CURDIR}/ 77.endif 78 79# Clear local and remote ARP cache. 80REGRESS_SETUP += clean-arp 81REGRESS_CLEANUP += clean-arp 82clean-arp: 83 ${SUDO} arp -da 84 ssh ${REMOTE_SSH} ${SUDO} arp -da 85 86# Clear ARP cache and ping all addresses. This ensures that 87# the IP addresses are configured and all routing table are set up 88# to allow bidirectional packet flow. 89REGRESS_TARGETS += run-ping 90run-ping: 91.for ip in LOCAL_ADDR REMOTE_ADDR 92 @echo Check ping ${ip} 93 ping -n -c 1 ${${ip}} 94.endfor 95 96# Send an ARP request from the local machine, asking for the remote 97# machine's MAC. Target MAC is broadcast, Target IP is remote address. 98# Check that all fields of the answer are filled out correctly. 99# Check that the remote machine has the local IP and MAC in its ARP table. 100REGRESS_TARGETS += run-arp-request 101run-arp-request: addr.py 102 @echo Send ARP Request for remote address and insert local address 103 ${SUDO} ${PYTHON}arp_request.py 104 ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log 105 grep '^${LOCAL_ADDR} .* ${LOCAL_MAC} ' arp.log 106 107# Send an ARP request from the local machine, but use a multicast MAC 108# as sender. Although there is a special check in in_arpinput(), 109# this must be answered. The ARP entry on the remote machine for the 110# local address is changed to the multicast MAC. 111# Check that all fields of the answer are filled out correctly. 112# Check that the remote machine overwrites the local address. 113REGRESS_TARGETS += run-arp-multicast 114run-arp-multicast: addr.py 115 @echo Send ARP Request and overwrite entry with multicast ethernet 116 ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@ 117 ssh ${REMOTE_SSH} ${SUDO} arp -s ${LOCAL_ADDR} ${LOCAL_MAC} temp 118 scp ${REMOTE_SSH}:/var/log/messages old.log 119 ${SUDO} ${PYTHON}arp_multicast.py 120 scp ${REMOTE_SSH}:/var/log/messages new.log 121 ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log 122 ssh ${REMOTE_SSH} ${SUDO} arp -d ${LOCAL_ADDR} 123 diff old.log new.log | grep '^> ' >diff.log 124 grep 'bsd: arp info overwritten for ${LOCAL_ADDR} by 33:33:33:33:33:33' diff.log 125 grep '^${LOCAL_ADDR} .* 33:33:33:33:33:33 ' arp.log 126 127# Send an ARP probe from the local machine with the remote IP as 128# target. Sender MAC is local and IP is 0. The remote machine must 129# defend its IP address with an ARP reply. 130# Check that all fields of the answer are filled out correctly. 131REGRESS_TARGETS += run-arp-probe 132run-arp-probe: addr.py 133 @echo Send ARP Probe for existing address and expect correct reply 134 ${SUDO} ${PYTHON}arp_probe.py 135 136# Send ARP request with broadcast MAC as sender. 137# Check that no answer is received. 138# Check that the remote machine rejects the broadcast sender. 139REGRESS_TARGETS += run-arp-broadcast 140run-arp-broadcast: addr.py 141 @echo Send ARP Request with broadcast as sender hardware address 142 ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@ 143 scp ${REMOTE_SSH}:/var/log/messages old.log 144 ${SUDO} ${PYTHON}arp_broadcast.py 145 scp ${REMOTE_SSH}:/var/log/messages new.log 146 diff old.log new.log | grep '^> ' >diff.log 147 grep 'bsd: arp: ether address is broadcast for IP address ${LOCAL_ADDR}' diff.log 148 149# The local machine announces that it has taken the remote machine's 150# IP. The sender is the local machines MAC and the remote IP. The 151# remote machine must defend its IP address with an ARP reply. 152# Check that all fields of the answer are filled out correctly. 153# Check that the remote machine reports an duplicate address. 154# Check that the remote machine keeps its local ARP entry. 155REGRESS_TARGETS += run-arp-announcement 156run-arp-announcement: addr.py 157 @echo Send ARP Announcement for existing address 158 ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@ 159 scp ${REMOTE_SSH}:/var/log/messages old.log 160 ${SUDO} ${PYTHON}arp_announcement.py 161 scp ${REMOTE_SSH}:/var/log/messages new.log 162 ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log 163 diff old.log new.log | grep '^> ' >diff.log 164 grep 'bsd: duplicate IP address ${REMOTE_ADDR} sent from ethernet address ${LOCAL_MAC}' diff.log 165 grep '^${REMOTE_ADDR} .* ${REMOTE_MAC} .* permanent * l$$' arp.log 166 167# The local machine sends an gratuitous ARP reply for the remote IP 168# with its local MAC. 169# Check that no answer is received. 170# Check that the remote machine reports an duplicate address. 171# Check that the remote machine keeps its local ARP entry. 172REGRESS_TARGETS += run-arp-gratuitous 173run-arp-gratuitous: addr.py 174 @echo Send Gratuitous ARP for existing address 175 ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@ 176 scp ${REMOTE_SSH}:/var/log/messages old.log 177 ${SUDO} ${PYTHON}arp_gratuitous.py 178 scp ${REMOTE_SSH}:/var/log/messages new.log 179 ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log 180 diff old.log new.log | grep '^> ' >diff.log 181 grep 'bsd: duplicate IP address ${REMOTE_ADDR} sent from ethernet address ${LOCAL_MAC}' diff.log 182 grep '^${REMOTE_ADDR} .* ${REMOTE_MAC} .* permanent * l$$' arp.log 183 184# Add a permanent entry on the remote machine for a fake MAC and IP. 185# Send a request form the local machine, indicating with the local 186# MAC and the fake IP as sender that it claims the fake address. 187# Check that no answer is received. 188# Check that the attempt to overwrite the permanent entry is logged. 189# Check that the remote machine keeps its permanent ARP entry. 190REGRESS_TARGETS += run-arp-permanent 191run-arp-permanent: addr.py 192 @echo Send ARP Request to change permanent fake address 193 ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@ 194 ssh ${REMOTE_SSH} ${SUDO} arp -s ${FAKE_ADDR} ${FAKE_MAC} permanent 195 scp ${REMOTE_SSH}:/var/log/messages old.log 196 ${SUDO} ${PYTHON}arp_fake.py 197 scp ${REMOTE_SSH}:/var/log/messages new.log 198 ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log 199 ssh ${REMOTE_SSH} ${SUDO} arp -d ${FAKE_ADDR} 200 diff old.log new.log | grep '^> ' >diff.log 201 grep 'bsd: arp: attempt to overwrite permanent entry for ${FAKE_ADDR} by ${LOCAL_MAC}' diff.log 202 grep '^${FAKE_ADDR} .* ${FAKE_MAC} .* permanent * $$' arp.log 203 204# The remote machine has a second address on another interface. 205# The local machine claims this address in its sender IP. 206# Check that no answer is received. 207# Check that the attempt to overwrite the permanent entry is logged. 208# Check that the remote machine keeps its local ARP entry. 209REGRESS_TARGETS += run-arp-address 210run-arp-address: addr.py 211 @echo Send ARP Request to change address on other interface 212 ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@ 213 scp ${REMOTE_SSH}:/var/log/messages old.log 214 ${SUDO} ${PYTHON}arp_other.py 215 scp ${REMOTE_SSH}:/var/log/messages new.log 216 ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log 217 diff old.log new.log | grep '^> ' >diff.log 218 grep 'bsd: arp: attempt to overwrite permanent entry for ${OTHER_ADDR} by ${LOCAL_MAC}' diff.log 219 grep '^${OTHER_ADDR} .* permanent * l$$' arp.log 220 221# The remote machine has a second address on another interface. Add 222# a temporary ARP entry for a fake address in this network on the 223# remote machine. The local machine tries to overwrite this address 224# with its own MAC. 225# Check that no answer is received. 226# Check that the attempt to overwrite the permanent entry is logged. 227# Check that the remote machine keeps its ARP entry. 228REGRESS_TARGETS += run-arp-temporary 229run-arp-temporary: addr.py 230 @echo Send ARP Request to change temporary entry on other interface 231 ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@ 232 ssh ${REMOTE_SSH} ${SUDO} arp -s ${OTHER_FAKE_ADDR} ${FAKE_MAC} temp 233 scp ${REMOTE_SSH}:/var/log/messages old.log 234 ${SUDO} ${PYTHON}arp_otherfake.py 235 scp ${REMOTE_SSH}:/var/log/messages new.log 236 ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log 237 ssh ${REMOTE_SSH} ${SUDO} arp -d ${OTHER_FAKE_ADDR} 238 diff old.log new.log | grep '^> ' >diff.log 239 grep 'bsd: arp: attempt to overwrite entry for ${OTHER_FAKE_ADDR} on .* by ${LOCAL_MAC} on .*' diff.log 240 grep '^${OTHER_FAKE_ADDR} .* ${FAKE_MAC} ' arp.log 241 242# The remote machine has a second address on another interface. Create 243# an incomplete ARP entry for a fake address in this network on the 244# remote machine with an unsuccessful ping. The local machine tries 245# to overwrite this address with its own MAC. 246# Check that no answer is received. 247# Check that the attempt to add an entry is logged. 248# Check that the remote machine keeps its incomplete ARP entry. 249REGRESS_TARGETS += run-arp-incomplete 250run-arp-incomplete: addr.py 251 @echo Send ARP Request filling an incomplete entry on other interface 252 ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@ 253 ssh ${REMOTE_SSH} ${SUDO} ping -n -w 1 -c 1 ${OTHER_FAKE_ADDR} || true 254 scp ${REMOTE_SSH}:/var/log/messages old.log 255 ${SUDO} ${PYTHON}arp_otherfake.py 256 scp ${REMOTE_SSH}:/var/log/messages new.log 257 ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log 258 ssh ${REMOTE_SSH} ${SUDO} arp -d ${OTHER_FAKE_ADDR} 259 diff old.log new.log | grep '^> ' >diff.log 260 grep 'bsd: arp: attempt to add entry for ${OTHER_FAKE_ADDR} on .* by ${LOCAL_MAC} on .*' diff.log 261 grep '^${OTHER_FAKE_ADDR} .* (incomplete) ' arp.log 262 263# Publish a proxy ARP entry on the remote machine for a fake address. 264# The local machine requests this IP as a the target. 265# Check that all fields of the answer are filled out correctly. 266# Check that the remote machine has a public ARP entry. 267REGRESS_TARGETS += run-arp-proxy 268run-arp-proxy: addr.py 269 @echo Send ARP Request for fake address that is proxied 270 ssh ${REMOTE_SSH} ${SUDO} arp -s ${FAKE_ADDR} ${PROXY_MAC} 271 ssh ${REMOTE_SSH} ${SUDO} arp -s ${FAKE_ADDR} ${FAKE_MAC} pub 272 ${SUDO} ${PYTHON}arp_proxy.py 273 ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log 274 ssh ${REMOTE_SSH} ${SUDO} arp -d ${FAKE_ADDR} 275 ssh ${REMOTE_SSH} ${SUDO} arp -d ${FAKE_ADDR} 276 grep '^${FAKE_ADDR} .* ${FAKE_MAC} .* static * p$$' arp.log 277 278# Enter a static ARP entry on the remote machine for a fake address, 279# but do not publish it. The local machine requests this IP as a the 280# target. 281# Check that no answer is received. 282# Check that the remote machine has a static ARP entry. 283REGRESS_TARGETS += run-arp-nonproxy 284run-arp-nonproxy: addr.py 285 @echo Send ARP Request for fake address that is not published 286 ssh ${REMOTE_SSH} ${SUDO} arp -s ${FAKE_ADDR} ${FAKE_MAC} 287 ${SUDO} ${PYTHON}arp_nonproxy.py 288 ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log 289 ssh ${REMOTE_SSH} ${SUDO} arp -d ${FAKE_ADDR} 290 grep '^${FAKE_ADDR} .* ${FAKE_MAC} .* static * $$' arp.log 291 292# Publish a proxy ARP entry on the remote machine for a fake address 293# on another interface. The local machine requests this IP. As the 294# proxy entry is for another interface, it must not be answered. 295# Check that no answer is received. 296# Check that the remote machine has a public ARP entry. 297REGRESS_TARGETS += run-arp-otherproxy 298run-arp-otherproxy: addr.py 299 @echo Send ARP Request for address proxied on another interface 300 ssh ${REMOTE_SSH} ${SUDO} arp -s ${OTHER_FAKE_ADDR} ${FAKE_MAC} pub 301 ${SUDO} ${PYTHON}arp_otherproxy.py 302 ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log 303 ssh ${REMOTE_SSH} ${SUDO} arp -d ${OTHER_FAKE_ADDR} 304 grep '^${OTHER_FAKE_ADDR} .* ${FAKE_MAC} .* static * p$$' arp.log 305 306CLEANFILES += addr.py *.pyc *.log 307 308.include <bsd.regress.mk> 309