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