Makefile revision 1.13
1#	$OpenBSD: Makefile,v 1.13 2020/12/17 00:51:13 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	${SUDO} arp -da
85	ssh ${REMOTE_SSH} ${SUDO} arp -da
86
87# Clear ARP cache and ping all addresses.  This ensures that
88# the IP addresses are configured and all routing table are set up
89# to allow bidirectional packet flow.
90REGRESS_TARGETS +=	run-ping
91run-ping:
92.for ip in LOCAL_ADDR REMOTE_ADDR
93	@echo Check ping ${ip}
94	ping -n -c 1 ${${ip}}
95.endfor
96
97# Send an ARP request from the local machine, asking for the remote
98# machine's MAC.  Target MAC is broadcast, Target IP is remote address.
99# Check that all fields of the answer are filled out correctly.
100# Check that the remote machine has the local IP and MAC in its ARP table.
101REGRESS_TARGETS +=	run-arp-request
102run-arp-request: addr.py
103	@echo Send ARP Request for remote address and insert local address
104	${SUDO} ${PYTHON}arp_request.py
105	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
106	grep '^${LOCAL_ADDR} .* ${LOCAL_MAC} ' arp.log
107
108# Send an ARP request from the local machine, but use a multicast MAC
109# as sender.  Although there is a special check in in_arpinput(),
110# this must be answered.  The ARP entry on the remote machine for the
111# local address is changed to the multicast MAC.
112# Check that all fields of the answer are filled out correctly.
113# Check that the remote machine overwrites the local address.
114REGRESS_TARGETS +=	run-arp-multicast
115run-arp-multicast: addr.py
116	@echo Send ARP Request and overwrite entry with multicast ethernet
117	ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
118	ssh ${REMOTE_SSH} ${SUDO} arp -s ${LOCAL_ADDR} ${LOCAL_MAC} temp
119	scp ${REMOTE_SSH}:/var/log/messages old.log
120	${SUDO} ${PYTHON}arp_multicast.py
121	scp ${REMOTE_SSH}:/var/log/messages new.log
122	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
123	ssh ${REMOTE_SSH} ${SUDO} arp -d ${LOCAL_ADDR}
124	diff old.log new.log | grep '^> ' >diff.log
125	grep 'bsd: arp info overwritten for ${LOCAL_ADDR} by 33:33:33:33:33:33' diff.log
126	grep '^${LOCAL_ADDR} .* 33:33:33:33:33:33 ' arp.log
127
128# Send an ARP probe from the local machine with the remote IP as
129# target.  Sender MAC is local and IP is 0.  The remote machine must
130# defend its IP address with an ARP reply.
131# Check that all fields of the answer are filled out correctly.
132REGRESS_TARGETS +=	run-arp-probe
133run-arp-probe: addr.py
134	@echo Send ARP Probe for existing address and expect correct reply
135	${SUDO} ${PYTHON}arp_probe.py
136
137# Send ARP request with broadcast MAC as sender.
138# Check that no answer is received.
139# Check that the remote machine rejects the broadcast sender.
140REGRESS_TARGETS +=	run-arp-broadcast
141run-arp-broadcast: addr.py
142	@echo Send ARP Request with broadcast as sender hardware address
143	ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
144	scp ${REMOTE_SSH}:/var/log/messages old.log
145	${SUDO} ${PYTHON}arp_broadcast.py
146	scp ${REMOTE_SSH}:/var/log/messages new.log
147	diff old.log new.log | grep '^> ' >diff.log
148	grep 'bsd: arp: ether address is broadcast for IP address ${LOCAL_ADDR}' diff.log
149
150# The local machine announces that it has taken the remote machine's
151# IP.  The sender is the local machines MAC and the remote IP.  The
152# remote machine must defend its IP address with an ARP reply.
153# Check that all fields of the answer are filled out correctly.
154# Check that the remote machine reports an duplicate address.
155# Check that the remote machine keeps its local ARP entry.
156REGRESS_TARGETS +=	run-arp-announcement
157run-arp-announcement: addr.py
158	@echo Send ARP Announcement for existing address
159	ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
160	scp ${REMOTE_SSH}:/var/log/messages old.log
161	${SUDO} ${PYTHON}arp_announcement.py
162	scp ${REMOTE_SSH}:/var/log/messages new.log
163	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
164	diff old.log new.log | grep '^> ' >diff.log
165	grep 'bsd: duplicate IP address ${REMOTE_ADDR} sent from ethernet address ${LOCAL_MAC}' diff.log
166	grep '^${REMOTE_ADDR} .* ${REMOTE_MAC} .* permanent * l$$' arp.log
167
168# The local machine sends an gratuitous ARP reply for the remote IP
169# with its local MAC.
170# Check that no answer is received.
171# Check that the remote machine reports an duplicate address.
172# Check that the remote machine keeps its local ARP entry.
173REGRESS_TARGETS +=	run-arp-gratuitous
174run-arp-gratuitous: addr.py
175	@echo Send Gratuitous ARP for existing address
176	ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
177	scp ${REMOTE_SSH}:/var/log/messages old.log
178	${SUDO} ${PYTHON}arp_gratuitous.py
179	scp ${REMOTE_SSH}:/var/log/messages new.log
180	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
181	diff old.log new.log | grep '^> ' >diff.log
182	grep 'bsd: duplicate IP address ${REMOTE_ADDR} sent from ethernet address ${LOCAL_MAC}' diff.log
183	grep '^${REMOTE_ADDR} .* ${REMOTE_MAC} .* permanent * l$$' arp.log
184
185# Add a permanent entry on the remote machine for a fake MAC and IP.
186# Send a request form the local machine, indicating with the local
187# MAC and the fake IP as sender that it claims the fake address.
188# Check that no answer is received.
189# Check that the attempt to overwrite the permanent entry is logged.
190# Check that the remote machine keeps its permanent ARP entry.
191REGRESS_TARGETS +=	run-arp-permanent
192run-arp-permanent: addr.py
193	@echo Send ARP Request to change permanent fake address
194	ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
195	ssh ${REMOTE_SSH} ${SUDO} arp -s ${FAKE_ADDR} ${FAKE_MAC} permanent
196	scp ${REMOTE_SSH}:/var/log/messages old.log
197	${SUDO} ${PYTHON}arp_fake.py
198	scp ${REMOTE_SSH}:/var/log/messages new.log
199	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
200	ssh ${REMOTE_SSH} ${SUDO} arp -d ${FAKE_ADDR}
201	diff old.log new.log | grep '^> ' >diff.log
202	grep 'bsd: arp: attempt to overwrite permanent entry for ${FAKE_ADDR} by ${LOCAL_MAC}' diff.log
203	grep '^${FAKE_ADDR} .* ${FAKE_MAC} .* permanent * $$' arp.log
204
205# The remote machine has a second address on another interface.
206# The local machine claims this address in its sender IP.
207# Check that no answer is received.
208# Check that the attempt to overwrite the permanent entry is logged.
209# Check that the remote machine keeps its local ARP entry.
210REGRESS_TARGETS +=	run-arp-address
211run-arp-address: addr.py
212	@echo Send ARP Request to change address on other interface
213	ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
214	scp ${REMOTE_SSH}:/var/log/messages old.log
215	${SUDO} ${PYTHON}arp_other.py
216	scp ${REMOTE_SSH}:/var/log/messages new.log
217	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
218	diff old.log new.log | grep '^> ' >diff.log
219	grep 'bsd: arp: attempt to overwrite permanent entry for ${OTHER_ADDR} by ${LOCAL_MAC}' diff.log
220	grep '^${OTHER_ADDR} .* permanent * l$$' arp.log
221
222# The remote machine has a second address on another interface.  Add
223# a temporary ARP entry for a fake address in this network on the
224# remote machine.  The local machine tries to overwrite this address
225# with its own MAC.
226# Check that no answer is received.
227# Check that the attempt to overwrite the permanent entry is logged.
228# Check that the remote machine keeps its ARP entry.
229REGRESS_TARGETS +=	run-arp-temporary
230run-arp-temporary: addr.py
231	@echo Send ARP Request to change temporary entry on other interface
232	ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
233	ssh ${REMOTE_SSH} ${SUDO} arp -s ${OTHER_FAKE_ADDR} ${FAKE_MAC} temp
234	scp ${REMOTE_SSH}:/var/log/messages old.log
235	${SUDO} ${PYTHON}arp_otherfake.py
236	scp ${REMOTE_SSH}:/var/log/messages new.log
237	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
238	ssh ${REMOTE_SSH} ${SUDO} arp -d ${OTHER_FAKE_ADDR}
239	diff old.log new.log | grep '^> ' >diff.log
240	grep 'bsd: arp: attempt to overwrite entry for ${OTHER_FAKE_ADDR} on .* by ${LOCAL_MAC} on .*' diff.log
241	grep '^${OTHER_FAKE_ADDR} .* ${FAKE_MAC} ' arp.log
242
243# The remote machine has a second address on another interface.  Create
244# an incomplete ARP entry for a fake address in this network on the
245# remote machine with an unsuccessful ping.  The local machine tries
246# to overwrite this address with its own MAC.
247# Check that no answer is received.
248# Check that the attempt to add an entry is logged.
249# Check that the remote machine keeps its incomplete ARP entry.
250REGRESS_TARGETS +=	run-arp-incomplete
251run-arp-incomplete: addr.py
252	@echo Send ARP Request filling an incomplete entry on other interface
253	ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
254	ssh ${REMOTE_SSH} ${SUDO} ping -n -w 1 -c 1 ${OTHER_FAKE_ADDR} || true
255	scp ${REMOTE_SSH}:/var/log/messages old.log
256	${SUDO} ${PYTHON}arp_otherfake.py
257	scp ${REMOTE_SSH}:/var/log/messages new.log
258	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
259	ssh ${REMOTE_SSH} ${SUDO} arp -d ${OTHER_FAKE_ADDR}
260	diff old.log new.log | grep '^> ' >diff.log
261	grep 'bsd: arp: attempt to add entry for ${OTHER_FAKE_ADDR} on .* by ${LOCAL_MAC} on .*' diff.log
262	grep '^${OTHER_FAKE_ADDR} .* (incomplete) ' arp.log
263
264# Publish a proxy ARP entry on the remote machine for a fake address.
265# The local machine requests this IP as a the target.
266# Check that all fields of the answer are filled out correctly.
267# Check that the remote machine has a public ARP entry.
268REGRESS_TARGETS +=	run-arp-proxy
269run-arp-proxy: addr.py
270	@echo Send ARP Request for fake address that is proxied
271	ssh ${REMOTE_SSH} ${SUDO} arp -s ${FAKE_ADDR} ${PROXY_MAC}
272	ssh ${REMOTE_SSH} ${SUDO} arp -s ${FAKE_ADDR} ${FAKE_MAC} pub
273	${SUDO} ${PYTHON}arp_proxy.py
274	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
275	ssh ${REMOTE_SSH} ${SUDO} arp -d ${FAKE_ADDR}
276	ssh ${REMOTE_SSH} ${SUDO} arp -d ${FAKE_ADDR}
277	grep '^${FAKE_ADDR} .* ${FAKE_MAC} .* static * p$$' arp.log
278
279# Enter a static ARP entry on the remote machine for a fake address,
280# but do not publish it.  The local machine requests this IP as a the
281# target.
282# Check that no answer is received.
283# Check that the remote machine has a static ARP entry.
284REGRESS_TARGETS +=	run-arp-nonproxy
285run-arp-nonproxy: addr.py
286	@echo Send ARP Request for fake address that is not published
287	ssh ${REMOTE_SSH} ${SUDO} arp -s ${FAKE_ADDR} ${FAKE_MAC}
288	${SUDO} ${PYTHON}arp_nonproxy.py
289	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
290	ssh ${REMOTE_SSH} ${SUDO} arp -d ${FAKE_ADDR}
291	grep '^${FAKE_ADDR} .* ${FAKE_MAC} .* static * $$' arp.log
292
293# Publish a proxy ARP entry on the remote machine for a fake address
294# on another interface.  The local machine requests this IP.  As the
295# proxy entry is for another interface, it must not be answered.
296# Check that no answer is received.
297# Check that the remote machine has a public ARP entry.
298REGRESS_TARGETS +=	run-arp-otherproxy
299run-arp-otherproxy: addr.py
300	@echo Send ARP Request for address proxied on another interface
301	ssh ${REMOTE_SSH} ${SUDO} arp -s ${OTHER_FAKE_ADDR} ${FAKE_MAC} pub
302	${SUDO} ${PYTHON}arp_otherproxy.py
303	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
304	ssh ${REMOTE_SSH} ${SUDO} arp -d ${OTHER_FAKE_ADDR}
305	grep '^${OTHER_FAKE_ADDR} .* ${FAKE_MAC} .* static * p$$' arp.log
306
307CLEANFILES +=		addr.py *.pyc *.log
308
309.include <bsd.regress.mk>
310