xref: /minix/external/bsd/dhcpcd/dist/arp.c (revision 9f20bfa6)
1 #include <sys/cdefs.h>
2  __RCSID("$NetBSD: arp.c,v 1.14 2015/07/09 10:15:34 roy Exp $");
3 
4 /*
5  * dhcpcd - DHCP client daemon
6  * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
7  * All rights reserved
8 
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #include <sys/socket.h>
32 #include <sys/types.h>
33 
34 #include <arpa/inet.h>
35 
36 #include <net/if.h>
37 #include <netinet/in.h>
38 #include <netinet/if_ether.h>
39 
40 #include <errno.h>
41 #include <signal.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 
46 #define ELOOP_QUEUE 5
47 #include "config.h"
48 #include "arp.h"
49 #include "if.h"
50 #include "ipv4.h"
51 #include "common.h"
52 #include "dhcpcd.h"
53 #include "eloop.h"
54 #include "if.h"
55 #include "if-options.h"
56 #include "ipv4ll.h"
57 
58 #define ARP_LEN								      \
59 	(sizeof(struct arphdr) + (2 * sizeof(uint32_t)) + (2 * HWADDR_LEN))
60 
61 static ssize_t
arp_request(const struct interface * ifp,in_addr_t sip,in_addr_t tip)62 arp_request(const struct interface *ifp, in_addr_t sip, in_addr_t tip)
63 {
64 	uint8_t arp_buffer[ARP_LEN];
65 	struct arphdr ar;
66 	size_t len;
67 	uint8_t *p;
68 
69 	ar.ar_hrd = htons(ifp->family);
70 	ar.ar_pro = htons(ETHERTYPE_IP);
71 	ar.ar_hln = ifp->hwlen;
72 	ar.ar_pln = sizeof(sip);
73 	ar.ar_op = htons(ARPOP_REQUEST);
74 
75 	p = arp_buffer;
76 	len = 0;
77 
78 #define CHECK(fun, b, l)						\
79 	do {								\
80 		if (len + (l) > sizeof(arp_buffer))			\
81 			goto eexit;					\
82 		fun(p, (b), (l));					\
83 		p += (l);						\
84 		len += (l);						\
85 	} while (/* CONSTCOND */ 0)
86 #define APPEND(b, l)	CHECK(memcpy, b, l)
87 #define ZERO(l)		CHECK(memset, 0, l)
88 
89 	APPEND(&ar, sizeof(ar));
90 	APPEND(ifp->hwaddr, ifp->hwlen);
91 	APPEND(&sip, sizeof(sip));
92 	ZERO(ifp->hwlen);
93 	APPEND(&tip, sizeof(tip));
94 	return if_sendrawpacket(ifp, ETHERTYPE_ARP, arp_buffer, len);
95 
96 eexit:
97 	errno = ENOBUFS;
98 	return -1;
99 }
100 
101 void
arp_report_conflicted(const struct arp_state * astate,const struct arp_msg * amsg)102 arp_report_conflicted(const struct arp_state *astate, const struct arp_msg *amsg)
103 {
104 
105 	if (amsg != NULL) {
106 		char buf[HWADDR_LEN * 3];
107 
108 		logger(astate->iface->ctx, LOG_ERR,
109 		    "%s: hardware address %s claims %s",
110 		    astate->iface->name,
111 		    hwaddr_ntoa(amsg->sha, astate->iface->hwlen,
112 		    buf, sizeof(buf)),
113 		    inet_ntoa(astate->failed));
114 	} else
115 		logger(astate->iface->ctx, LOG_ERR,
116 		    "%s: DAD detected %s",
117 		    astate->iface->name, inet_ntoa(astate->failed));
118 }
119 
120 static void
arp_packet(void * arg)121 arp_packet(void *arg)
122 {
123 	struct interface *ifp = arg;
124 	const struct interface *ifn;
125 	uint8_t arp_buffer[ARP_LEN];
126 	struct arphdr ar;
127 	struct arp_msg arm;
128 	ssize_t bytes;
129 	struct iarp_state *state;
130 	struct arp_state *astate, *astaten;
131 	unsigned char *hw_s, *hw_t;
132 	int flags;
133 
134 	state = ARP_STATE(ifp);
135 	flags = 0;
136 	while (!(flags & RAW_EOF)) {
137 		bytes = if_readrawpacket(ifp, ETHERTYPE_ARP,
138 		    arp_buffer, sizeof(arp_buffer), &flags);
139 		if (bytes == -1) {
140 			logger(ifp->ctx, LOG_ERR,
141 			    "%s: arp if_readrawpacket: %m", ifp->name);
142 			arp_close(ifp);
143 			return;
144 		}
145 		/* We must have a full ARP header */
146 		if ((size_t)bytes < sizeof(ar))
147 			continue;
148 		memcpy(&ar, arp_buffer, sizeof(ar));
149 		/* Families must match */
150 		if (ar.ar_hrd != htons(ifp->family))
151 			continue;
152 		/* Protocol must be IP. */
153 		if (ar.ar_pro != htons(ETHERTYPE_IP))
154 			continue;
155 		if (ar.ar_pln != sizeof(arm.sip.s_addr))
156 			continue;
157 		/* Only these types are recognised */
158 		if (ar.ar_op != htons(ARPOP_REPLY) &&
159 		    ar.ar_op != htons(ARPOP_REQUEST))
160 			continue;
161 
162 		/* Get pointers to the hardware addreses */
163 		hw_s = arp_buffer + sizeof(ar);
164 		hw_t = hw_s + ar.ar_hln + ar.ar_pln;
165 		/* Ensure we got all the data */
166 		if ((hw_t + ar.ar_hln + ar.ar_pln) - arp_buffer > bytes)
167 			continue;
168 		/* Ignore messages from ourself */
169 		TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
170 			if (ar.ar_hln == ifn->hwlen &&
171 			    memcmp(hw_s, ifn->hwaddr, ifn->hwlen) == 0)
172 				break;
173 		}
174 		if (ifn)
175 			continue;
176 		/* Copy out the HW and IP addresses */
177 		memcpy(&arm.sha, hw_s, ar.ar_hln);
178 		memcpy(&arm.sip.s_addr, hw_s + ar.ar_hln, ar.ar_pln);
179 		memcpy(&arm.tha, hw_t, ar.ar_hln);
180 		memcpy(&arm.tip.s_addr, hw_t + ar.ar_hln, ar.ar_pln);
181 
182 		/* Run the conflicts */
183 		TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, astaten) {
184 			if (astate->conflicted_cb)
185 				astate->conflicted_cb(astate, &arm);
186 		}
187 	}
188 }
189 
190 static void
arp_open(struct interface * ifp)191 arp_open(struct interface *ifp)
192 {
193 	struct iarp_state *state;
194 
195 	state = ARP_STATE(ifp);
196 	if (state->fd == -1) {
197 		state->fd = if_openrawsocket(ifp, ETHERTYPE_ARP);
198 		if (state->fd == -1) {
199 			logger(ifp->ctx, LOG_ERR, "%s: %s: %m",
200 			    __func__, ifp->name);
201 			return;
202 		}
203 		eloop_event_add(ifp->ctx->eloop, state->fd,
204 		    arp_packet, ifp, NULL, NULL);
205 	}
206 }
207 
208 static void
arp_announced(void * arg)209 arp_announced(void *arg)
210 {
211 	struct arp_state *astate = arg;
212 
213 	if (astate->announced_cb) {
214 		astate->announced_cb(astate);
215 		return;
216 	}
217 
218 	/* Nothing more to do, so free us */
219 	arp_free(astate);
220 }
221 
222 static void
arp_announce1(void * arg)223 arp_announce1(void *arg)
224 {
225 	struct arp_state *astate = arg;
226 	struct interface *ifp = astate->iface;
227 
228 	if (++astate->claims < ANNOUNCE_NUM)
229 		logger(ifp->ctx, LOG_DEBUG,
230 		    "%s: ARP announcing %s (%d of %d), "
231 		    "next in %d.0 seconds",
232 		    ifp->name, inet_ntoa(astate->addr),
233 		    astate->claims, ANNOUNCE_NUM, ANNOUNCE_WAIT);
234 	else
235 		logger(ifp->ctx, LOG_DEBUG,
236 		    "%s: ARP announcing %s (%d of %d)",
237 		    ifp->name, inet_ntoa(astate->addr),
238 		    astate->claims, ANNOUNCE_NUM);
239 	if (arp_request(ifp, astate->addr.s_addr, astate->addr.s_addr) == -1)
240 		logger(ifp->ctx, LOG_ERR, "send_arp: %m");
241 	eloop_timeout_add_sec(ifp->ctx->eloop, ANNOUNCE_WAIT,
242 	    astate->claims < ANNOUNCE_NUM ? arp_announce1 : arp_announced,
243 	    astate);
244 }
245 
246 void
arp_announce(struct arp_state * astate)247 arp_announce(struct arp_state *astate)
248 {
249 
250 	arp_open(astate->iface);
251 	astate->claims = 0;
252 	arp_announce1(astate);
253 }
254 
255 static void
arp_probed(void * arg)256 arp_probed(void *arg)
257 {
258 	struct arp_state *astate = arg;
259 
260 	astate->probed_cb(astate);
261 }
262 
263 static void
arp_probe1(void * arg)264 arp_probe1(void *arg)
265 {
266 	struct arp_state *astate = arg;
267 	struct interface *ifp = astate->iface;
268 	struct timespec tv;
269 
270 	if (++astate->probes < PROBE_NUM) {
271 		tv.tv_sec = PROBE_MIN;
272 		tv.tv_nsec = (suseconds_t)arc4random_uniform(
273 		    (PROBE_MAX - PROBE_MIN) * NSEC_PER_SEC);
274 		timespecnorm(&tv);
275 		eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probe1, astate);
276 	} else {
277 		tv.tv_sec = ANNOUNCE_WAIT;
278 		tv.tv_nsec = 0;
279 		eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probed, astate);
280 	}
281 	logger(ifp->ctx, LOG_DEBUG,
282 	    "%s: ARP probing %s (%d of %d), next in %0.1f seconds",
283 	    ifp->name, inet_ntoa(astate->addr),
284 	    astate->probes ? astate->probes : PROBE_NUM, PROBE_NUM,
285 	    timespec_to_double(&tv));
286 	if (arp_request(ifp, 0, astate->addr.s_addr) == -1)
287 		logger(ifp->ctx, LOG_ERR, "send_arp: %m");
288 }
289 
290 void
arp_probe(struct arp_state * astate)291 arp_probe(struct arp_state *astate)
292 {
293 
294 	arp_open(astate->iface);
295 	astate->probes = 0;
296 	logger(astate->iface->ctx, LOG_DEBUG, "%s: probing for %s",
297 	    astate->iface->name, inet_ntoa(astate->addr));
298 	arp_probe1(astate);
299 }
300 
301 struct arp_state *
arp_find(struct interface * ifp,const struct in_addr * addr)302 arp_find(struct interface *ifp, const struct in_addr *addr)
303 {
304 	struct iarp_state *state;
305 	struct arp_state *astate;
306 
307 	if ((state = ARP_STATE(ifp)) == NULL)
308 		goto out;
309 	TAILQ_FOREACH(astate, &state->arp_states, next) {
310 		if (astate->addr.s_addr == addr->s_addr && astate->iface == ifp)
311 			return astate;
312 	}
313 out:
314 	errno = ESRCH;
315 	return NULL;
316 }
317 
318 struct arp_state *
arp_new(struct interface * ifp,const struct in_addr * addr)319 arp_new(struct interface *ifp, const struct in_addr *addr)
320 {
321 	struct iarp_state *state;
322 	struct arp_state *astate;
323 
324 	if ((state = ARP_STATE(ifp)) == NULL) {
325 	        ifp->if_data[IF_DATA_ARP] = malloc(sizeof(*state));
326 		state = ARP_STATE(ifp);
327 		if (state == NULL) {
328 			logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
329 			return NULL;
330 		}
331 		state->fd = -1;
332 		TAILQ_INIT(&state->arp_states);
333 	} else {
334 		if (addr && (astate = arp_find(ifp, addr)))
335 			return astate;
336 	}
337 
338 	if ((astate = calloc(1, sizeof(*astate))) == NULL) {
339 		logger(ifp->ctx, LOG_ERR, "%s: %s: %m", ifp->name, __func__);
340 		return NULL;
341 	}
342 	astate->iface = ifp;
343 	if (addr)
344 		astate->addr = *addr;
345 	state = ARP_STATE(ifp);
346 	TAILQ_INSERT_TAIL(&state->arp_states, astate, next);
347 	return astate;
348 }
349 
350 void
arp_cancel(struct arp_state * astate)351 arp_cancel(struct arp_state *astate)
352 {
353 
354 	eloop_timeout_delete(astate->iface->ctx->eloop, NULL, astate);
355 }
356 
357 void
arp_free(struct arp_state * astate)358 arp_free(struct arp_state *astate)
359 {
360 
361 	if (astate != NULL) {
362 		struct interface *ifp;
363 		struct iarp_state *state;
364 
365 		ifp = astate->iface;
366 		eloop_timeout_delete(ifp->ctx->eloop, NULL, astate);
367 		state =	ARP_STATE(ifp);
368 		TAILQ_REMOVE(&state->arp_states, astate, next);
369 		if (astate->free_cb)
370 			astate->free_cb(astate);
371 		free(astate);
372 
373 		/* If there are no more ARP states, close the socket. */
374 		if (state->fd != -1 &&
375 		    TAILQ_FIRST(&state->arp_states) == NULL)
376 		{
377 			eloop_event_delete(ifp->ctx->eloop, state->fd);
378 			close(state->fd);
379 			free(state);
380 			ifp->if_data[IF_DATA_ARP] = NULL;
381 		}
382 	}
383 }
384 
385 void
arp_free_but(struct arp_state * astate)386 arp_free_but(struct arp_state *astate)
387 {
388 	struct iarp_state *state;
389 	struct arp_state *p, *n;
390 
391 	state = ARP_STATE(astate->iface);
392 	TAILQ_FOREACH_SAFE(p, &state->arp_states, next, n) {
393 		if (p != astate)
394 			arp_free(p);
395 	}
396 }
397 
398 void
arp_close(struct interface * ifp)399 arp_close(struct interface *ifp)
400 {
401 	struct iarp_state *state;
402 	struct arp_state *astate;
403 
404 	/* Freeing the last state will also free the main state,
405 	 * so test for both. */
406 	for (;;) {
407 		if ((state = ARP_STATE(ifp)) == NULL ||
408 		    (astate = TAILQ_FIRST(&state->arp_states)) == NULL)
409 			break;
410 		arp_free(astate);
411 	}
412 }
413 
414 void
arp_handleifa(int cmd,struct interface * ifp,const struct in_addr * addr,int flags)415 arp_handleifa(int cmd, struct interface *ifp, const struct in_addr *addr,
416     int flags)
417 {
418 #ifdef IN_IFF_DUPLICATED
419 	struct iarp_state *state;
420 	struct arp_state *astate, *asn;
421 
422 	if (cmd != RTM_NEWADDR || (state = ARP_STATE(ifp)) == NULL)
423 		return;
424 
425 	TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, asn) {
426 		if (astate->addr.s_addr == addr->s_addr) {
427 			if (flags & IN_IFF_DUPLICATED) {
428 				if (astate->conflicted_cb)
429 					astate->conflicted_cb(astate, NULL);
430 			} else if (!(flags & IN_IFF_NOTUSEABLE)) {
431 				if (astate->probed_cb)
432 					astate->probed_cb(astate);
433 			}
434 		}
435 	}
436 #else
437 	UNUSED(cmd);
438 	UNUSED(ifp);
439 	UNUSED(addr);
440 	UNUSED(flags);
441 #endif
442 }
443