xref: /openbsd/regress/sys/netinet/arp/Makefile (revision 09467b48)
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