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