summaryrefslogtreecommitdiff
path: root/regress/sys/netinet/arp/Makefile
blob: 7081e928b99966fb0a3e5b3339c2f9d29ecf118b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
#	$OpenBSD: Makefile,v 1.10 2017/07/07 23:15:27 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

.if ! (make(clean) || make(cleandir) || make(obj))
# 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
.endif
.if ! empty(PYTHON_IMPORT)
regress:
	@echo '${PYTHON_IMPORT}'
	@echo install python and the scapy module for additional tests
	@echo SKIPPED
.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
PROXY_MAC ?= 00:90:27:bb:cc:dd
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
	@echo SKIPPED
.endif

.if ! empty (REMOTE_SSH)
.if make (regress) || make (all)
.BEGIN: pf.conf addr.py
	@echo
	${SUDO} true
	ssh -t ${REMOTE_SSH} ${SUDO} true
.endif
.endif

# 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

.PHONY: clean-arp

# Clear local and remote ARP cache.
clean-arp:
	@echo '\n======== $@ ========'
	${SUDO} arp -da
	ssh ${REMOTE_SSH} ${SUDO} arp -da

# 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: clean-arp
	@echo '\n======== $@ ========'
.for ip in LOCAL_ADDR REMOTE_ADDR
	@echo Check ping ${ip}
	ping -n -c 1 ${${ip}}
.endfor

# Send an ARP request from the local machine, asking for the remote
# machine's MAC.  Target MAC is broadcast, Target IP is remote address.
# Check that all fields of the answer are filled out correctly.
# Check that the remote machine has the local IP and MAC in its ARP table.
TARGETS +=	arp-request
run-regress-arp-request: addr.py clean-arp
	@echo '\n======== $@ ========'
	@echo Send ARP Request for remote address and insert local address
	${SUDO} ${PYTHON}arp_request.py
	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
	grep '^${LOCAL_ADDR} .* ${LOCAL_MAC} ' arp.log

# Send an ARP request from the local machine, but use a multicast MAC
# as sender.  Although there is a special check in in_arpinput(),
# this must be answered.  The ARP entry on the remote machine for the
# local address is changed to the multicast MAC.
# Check that all fields of the answer are filled out correctly.
# Check that the remote machine overwrites the local address.
TARGETS +=	arp-multicast
run-regress-arp-multicast: addr.py clean-arp
	@echo '\n======== $@ ========'
	@echo Send ARP Request and overwrite entry with multicast ethernet
	ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
	ssh ${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 ${REMOTE_SSH} ${SUDO} arp -an >arp.log
	ssh ${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} .* 33:33:33:33:33:33 ' arp.log

# Send an ARP probe from the local machine with the remote IP as
# target.  Sender MAC is local and IP is 0.  The remote machine must
# defend its IP address with an ARP reply.
# Check that all fields of the answer are filled out correctly.
TARGETS +=	arp-probe
run-regress-arp-probe: addr.py clean-arp
	@echo '\n======== $@ ========'
	@echo Send ARP Probe for existing address and expect correct reply
	${SUDO} ${PYTHON}arp_probe.py

# Send ARP request with broadcast MAC as sender.
# Check that no answer is received.
# Check that the remote machine rejects the broadcast sender.
TARGETS +=	arp-broadcast
run-regress-arp-broadcast: addr.py clean-arp
	@echo '\n======== $@ ========'
	@echo Send ARP Request with broadcast as sender hardware address
	ssh ${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

# The local machine announces that it has taken the remote machine's
# IP.  The sender is the local machines MAC and the remote IP.  The
# remote machine must defend its IP address with an ARP reply.
# Check that all fields of the answer are filled out correctly.
# Check that the remote machine reports an duplicate address.
# Check that the remote machine keeps its local ARP entry.
TARGETS +=	arp-announcement
run-regress-arp-announcement: addr.py clean-arp
	@echo '\n======== $@ ========'
	@echo Send ARP Announcement for existing address
	ssh ${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 ${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 * l$$' arp.log

# The local machine sends an gratuitous ARP reply for the remote IP
# with its local MAC.
# Check that no answer is received.
# Check that the remote machine reports an duplicate address.
# Check that the remote machine keeps its local ARP entry.
TARGETS +=	arp-gratuitous
run-regress-arp-gratuitous: addr.py clean-arp
	@echo '\n======== $@ ========'
	@echo Send Gratuitous ARP for existing address
	ssh ${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 ${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 * l$$' arp.log

# Add a permanent entry on the remote machine for a fake MAC and IP.
# Send a request form the local machine, indicating with the local
# MAC and the fake IP as sender that it claims the fake address.
# Check that no answer is received.
# Check that the attempt to overwrite the permanent entry is logged.
# Check that the remote machine keeps its permanent ARP entry.
TARGETS +=	arp-permanent
run-regress-arp-permanent: addr.py clean-arp
	@echo '\n======== $@ ========'
	@echo Send ARP Request to change permanent fake address
	ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
	ssh ${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 ${REMOTE_SSH} ${SUDO} arp -an >arp.log
	ssh ${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

# The remote machine has a second address on another interface.
# The local machine claims this address in its sender IP.
# Check that no answer is received.
# Check that the attempt to overwrite the permanent entry is logged.
# Check that the remote machine keeps its local ARP entry.
TARGETS +=	arp-address
run-regress-arp-address: addr.py clean-arp
	@echo '\n======== $@ ========'
	@echo Send ARP Request to change address on other interface
	ssh ${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 ${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 * l$$' arp.log

# The remote machine has a second address on another interface.  Add
# a temporary ARP entry for a fake address in this network on the
# remote machine.  The local machine tries to overwrite this address
# with its own MAC.
# Check that no answer is received.
# Check that the attempt to overwrite the permanent entry is logged.
# Check that the remote machine keeps its ARP entry.
TARGETS +=	arp-temporary
run-regress-arp-temporary: addr.py clean-arp
	@echo '\n======== $@ ========'
	@echo Send ARP Request to change temporary entry on other interface
	ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
	ssh ${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 ${REMOTE_SSH} ${SUDO} arp -an >arp.log
	ssh ${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

# The remote machine has a second address on another interface.  Create
# an incomplete ARP entry for a fake address in this network on the
# remote machine with an unsuccessful ping.  The local machine tries
# to overwrite this address with its own MAC.
# Check that no answer is received.
# Check that the attempt to add an entry is logged.
# Check that the remote machine keeps its incomplete ARP entry.
TARGETS +=	arp-incomplete
run-regress-arp-incomplete: addr.py clean-arp
	@echo '\n======== $@ ========'
	@echo Send ARP Request filling an incomplete entry on other interface
	ssh ${REMOTE_SSH} logger -t "arp-regress[$$$$]" $@
	ssh ${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 ${REMOTE_SSH} ${SUDO} arp -an >arp.log
	ssh ${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

# Publish a proxy ARP entry on the remote machine for a fake address.
# The local machine requests this IP as a the target.
# Check that all fields of the answer are filled out correctly.
# Check that the remote machine has a public ARP entry.
TARGETS +=	arp-proxy
run-regress-arp-proxy: addr.py clean-arp
	@echo '\n======== $@ ========'
	@echo Send ARP Request for fake address that is proxied
	ssh ${REMOTE_SSH} ${SUDO} arp -s ${FAKE_ADDR} ${PROXY_MAC}
	ssh ${REMOTE_SSH} ${SUDO} arp -s ${FAKE_ADDR} ${FAKE_MAC} pub
	${SUDO} ${PYTHON}arp_proxy.py
	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
	ssh ${REMOTE_SSH} ${SUDO} arp -d ${FAKE_ADDR}
	ssh ${REMOTE_SSH} ${SUDO} arp -d ${FAKE_ADDR}
	grep '^${FAKE_ADDR} .* ${FAKE_MAC} .* static * p$$' arp.log

# Enter a static ARP entry on the remote machine for a fake address,
# but do not publish it.  The local machine requests this IP as a the
# target.
# Check that no answer is received.
# Check that the remote machine has a static ARP entry.
TARGETS +=	arp-nonproxy
run-regress-arp-nonproxy: addr.py clean-arp
	@echo '\n======== $@ ========'
	@echo Send ARP Request for fake address that is not published
	ssh ${REMOTE_SSH} ${SUDO} arp -s ${FAKE_ADDR} ${FAKE_MAC}
	${SUDO} ${PYTHON}arp_nonproxy.py
	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
	ssh ${REMOTE_SSH} ${SUDO} arp -d ${FAKE_ADDR}
	grep '^${FAKE_ADDR} .* ${FAKE_MAC} .* static * $$' arp.log

# Publish a proxy ARP entry on the remote machine for a fake address
# on another interface.  The local machine requests this IP.  As the
# proxy entry is for another interface, it must not be answered.
# Check that no answer is received.
# Check that the remote machine has a public ARP entry.
TARGETS +=	arp-otherproxy
run-regress-arp-otherproxy: addr.py clean-arp
	@echo '\n======== $@ ========'
	@echo Send ARP Request for address proxied on another interface
	ssh ${REMOTE_SSH} ${SUDO} arp -s ${OTHERFAKE_ADDR} ${FAKE_MAC} pub
	${SUDO} ${PYTHON}arp_otherproxy.py
	ssh ${REMOTE_SSH} ${SUDO} arp -an >arp.log
	ssh ${REMOTE_SSH} ${SUDO} arp -d ${OTHERFAKE_ADDR}
	grep '^${OTHERFAKE_ADDR} .* ${FAKE_MAC} .* static * p$$' arp.log

REGRESS_TARGETS =	${TARGETS:S/^/run-regress-/}

CLEANFILES +=		addr.py *.pyc *.log

.include <bsd.regress.mk>