blob: 01a8ba44011ee25a0533d9c102d523e39f4aa958 [file] [log] [blame]
Samuel Tand7ed8512015-08-13 16:11:35 -07001/*
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
57static ssize_t
58arp_request(const struct interface *ifp, in_addr_t sip, in_addr_t tip)
59{
60 uint8_t arp_buffer[ARP_LEN];
61 struct arphdr ar;
62 size_t len;
63 uint8_t *p;
64
65 ar.ar_hrd = htons(ifp->family);
66 ar.ar_pro = htons(ETHERTYPE_IP);
67 ar.ar_hln = ifp->hwlen;
68 ar.ar_pln = sizeof(sip);
69 ar.ar_op = htons(ARPOP_REQUEST);
70
71 p = arp_buffer;
72 len = 0;
73
74#define CHECK(fun, b, l) \
75 do { \
76 if (len + (l) > sizeof(arp_buffer)) \
77 goto eexit; \
78 fun(p, (b), (l)); \
79 p += (l); \
80 len += (l); \
81 } while (/* CONSTCOND */ 0)
82#define APPEND(b, l) CHECK(memcpy, b, l)
83#define ZERO(l) CHECK(memset, 0, l)
84
85 APPEND(&ar, sizeof(ar));
86 APPEND(ifp->hwaddr, ifp->hwlen);
87 APPEND(&sip, sizeof(sip));
88 ZERO(ifp->hwlen);
89 APPEND(&tip, sizeof(tip));
90 return if_sendrawpacket(ifp, ETHERTYPE_ARP, arp_buffer, len);
91
92eexit:
93 errno = ENOBUFS;
94 return -1;
95}
96
97void
98arp_report_conflicted(const struct arp_state *astate, const struct arp_msg *amsg)
99{
100
101 if (amsg) {
102 char buf[HWADDR_LEN * 3];
103
104 logger(astate->iface->ctx, LOG_ERR,
105 "%s: hardware address %s claims %s",
106 astate->iface->name,
107 hwaddr_ntoa(amsg->sha, astate->iface->hwlen,
108 buf, sizeof(buf)),
109 inet_ntoa(astate->failed));
110 } else
111 logger(astate->iface->ctx, LOG_ERR,
112 "%s: DAD detected %s",
113 astate->iface->name, inet_ntoa(astate->failed));
114}
115
116static void
117arp_packet(void *arg)
118{
119 struct interface *ifp = arg;
120 const struct interface *ifn;
121 uint8_t arp_buffer[ARP_LEN];
122 struct arphdr ar;
123 struct arp_msg arm;
124 ssize_t bytes;
125 struct dhcp_state *state;
126 struct arp_state *astate, *astaten;
127 unsigned char *hw_s, *hw_t;
128 int flags;
129
130 state = D_STATE(ifp);
131 flags = 0;
132 while (!(flags & RAW_EOF)) {
133 bytes = if_readrawpacket(ifp, ETHERTYPE_ARP,
134 arp_buffer, sizeof(arp_buffer), &flags);
135 if (bytes == -1) {
136 logger(ifp->ctx, LOG_ERR,
137 "%s: arp if_readrawpacket: %m", ifp->name);
138 dhcp_close(ifp);
139 return;
140 }
141 /* We must have a full ARP header */
142 if ((size_t)bytes < sizeof(ar))
143 continue;
144 memcpy(&ar, arp_buffer, sizeof(ar));
145 /* Families must match */
146 if (ar.ar_hrd != htons(ifp->family))
147 continue;
148 /* Protocol must be IP. */
149 if (ar.ar_pro != htons(ETHERTYPE_IP))
150 continue;
151 if (ar.ar_pln != sizeof(arm.sip.s_addr))
152 continue;
153 /* Only these types are recognised */
154 if (ar.ar_op != htons(ARPOP_REPLY) &&
155 ar.ar_op != htons(ARPOP_REQUEST))
156 continue;
157
158 /* Get pointers to the hardware addreses */
159 hw_s = arp_buffer + sizeof(ar);
160 hw_t = hw_s + ar.ar_hln + ar.ar_pln;
161 /* Ensure we got all the data */
162 if ((hw_t + ar.ar_hln + ar.ar_pln) - arp_buffer > bytes)
163 continue;
164 /* Ignore messages from ourself */
165 TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
166 if (ar.ar_hln == ifn->hwlen &&
167 memcmp(hw_s, ifn->hwaddr, ifn->hwlen) == 0)
168 break;
169 }
170 if (ifn)
171 continue;
172 /* Copy out the HW and IP addresses */
173 memcpy(&arm.sha, hw_s, ar.ar_hln);
174 memcpy(&arm.sip.s_addr, hw_s + ar.ar_hln, ar.ar_pln);
175 memcpy(&arm.tha, hw_t, ar.ar_hln);
176 memcpy(&arm.tip.s_addr, hw_t + ar.ar_hln, ar.ar_pln);
177
178 /* Run the conflicts */
179 TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, astaten) {
180 if (astate->conflicted_cb)
181 astate->conflicted_cb(astate, &arm);
182 }
183 }
184}
185
186static void
187arp_open(struct interface *ifp)
188{
189 struct dhcp_state *state;
190
191 state = D_STATE(ifp);
192 if (state->arp_fd == -1) {
193 state->arp_fd = if_openrawsocket(ifp, ETHERTYPE_ARP);
194 if (state->arp_fd == -1) {
195 logger(ifp->ctx, LOG_ERR, "%s: %s: %m",
196 __func__, ifp->name);
197 return;
198 }
199 eloop_event_add(ifp->ctx->eloop, state->arp_fd,
200 arp_packet, ifp, NULL, NULL);
201 }
202}
203
204static void
205arp_announced(void *arg)
206{
207 struct arp_state *astate = arg;
208
209 if (astate->announced_cb) {
210 astate->announced_cb(astate);
211 return;
212 }
213
214 /* Nothing more to do, so free us */
215 arp_free(astate);
216}
217
218static void
219arp_announce1(void *arg)
220{
221 struct arp_state *astate = arg;
222 struct interface *ifp = astate->iface;
223
224 if (++astate->claims < ANNOUNCE_NUM)
225 logger(ifp->ctx, LOG_DEBUG,
226 "%s: ARP announcing %s (%d of %d), "
227 "next in %d.0 seconds",
228 ifp->name, inet_ntoa(astate->addr),
229 astate->claims, ANNOUNCE_NUM, ANNOUNCE_WAIT);
230 else
231 logger(ifp->ctx, LOG_DEBUG,
232 "%s: ARP announcing %s (%d of %d)",
233 ifp->name, inet_ntoa(astate->addr),
234 astate->claims, ANNOUNCE_NUM);
235 if (arp_request(ifp, astate->addr.s_addr, astate->addr.s_addr) == -1)
236 logger(ifp->ctx, LOG_ERR, "send_arp: %m");
237 eloop_timeout_add_sec(ifp->ctx->eloop, ANNOUNCE_WAIT,
238 astate->claims < ANNOUNCE_NUM ? arp_announce1 : arp_announced,
239 astate);
240}
241
242void
243arp_announce(struct arp_state *astate)
244{
245
246 arp_open(astate->iface);
247 astate->claims = 0;
248 arp_announce1(astate);
249}
250
251static void
252arp_probed(void *arg)
253{
254 struct arp_state *astate = arg;
255
256 astate->probed_cb(astate);
257}
258
259static void
260arp_probe1(void *arg)
261{
262 struct arp_state *astate = arg;
263 struct interface *ifp = astate->iface;
264 struct timespec tv;
265
266 if (++astate->probes < PROBE_NUM) {
267 tv.tv_sec = PROBE_MIN;
268 tv.tv_nsec = (suseconds_t)arc4random_uniform(
269 (PROBE_MAX - PROBE_MIN) * NSEC_PER_SEC);
270 timespecnorm(&tv);
271 eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probe1, astate);
272 } else {
273 tv.tv_sec = ANNOUNCE_WAIT;
274 tv.tv_nsec = 0;
275 eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probed, astate);
276 }
277 logger(ifp->ctx, LOG_DEBUG,
278 "%s: ARP probing %s (%d of %d), next in %0.1f seconds",
279 ifp->name, inet_ntoa(astate->addr),
280 astate->probes ? astate->probes : PROBE_NUM, PROBE_NUM,
281 timespec_to_double(&tv));
282 if (arp_request(ifp, 0, astate->addr.s_addr) == -1)
283 logger(ifp->ctx, LOG_ERR, "send_arp: %m");
284}
285
286void
287arp_probe(struct arp_state *astate)
288{
289
290 arp_open(astate->iface);
291 astate->probes = 0;
292 logger(astate->iface->ctx, LOG_DEBUG, "%s: probing for %s",
293 astate->iface->name, inet_ntoa(astate->addr));
294 arp_probe1(astate);
295}
296
297static struct arp_state *
298arp_find(struct interface *ifp, const struct in_addr *addr)
299{
300 struct arp_state *astate;
301 struct dhcp_state *state;
302
303 state = D_STATE(ifp);
304 TAILQ_FOREACH(astate, &state->arp_states, next) {
305 if (astate->addr.s_addr == addr->s_addr && astate->iface == ifp)
306 return astate;
307 }
308 errno = ESRCH;
309 return NULL;
310}
311
312struct arp_state *
313arp_new(struct interface *ifp, const struct in_addr *addr)
314{
315 struct arp_state *astate;
316 struct dhcp_state *state;
317
318 if (addr && (astate = arp_find(ifp, addr)))
319 return astate;
320
321 if ((astate = calloc(1, sizeof(*astate))) == NULL) {
322 logger(ifp->ctx, LOG_ERR, "%s: %s: %m", ifp->name, __func__);
323 return NULL;
324 }
325 state = D_STATE(ifp);
326 astate->iface = ifp;
327 if (addr)
328 astate->addr = *addr;
329 TAILQ_INSERT_TAIL(&state->arp_states, astate, next);
330 return astate;
331}
332
333void
334arp_cancel(struct arp_state *astate)
335{
336
337 eloop_timeout_delete(astate->iface->ctx->eloop, NULL, astate);
338}
339
340void
341arp_free(struct arp_state *astate)
342{
343 struct dhcp_state *state;
344
345 if (astate) {
346 eloop_timeout_delete(astate->iface->ctx->eloop, NULL, astate);
347 state = D_STATE(astate->iface);
348 TAILQ_REMOVE(&state->arp_states, astate, next);
349 if (state->arp_ipv4ll == astate) {
350 ipv4ll_stop(astate->iface);
351 state->arp_ipv4ll = NULL;
352 }
353 free(astate);
354 }
355}
356
357void
358arp_free_but(struct arp_state *astate)
359{
360 struct arp_state *p, *n;
361 struct dhcp_state *state;
362
363 state = D_STATE(astate->iface);
364 TAILQ_FOREACH_SAFE(p, &state->arp_states, next, n) {
365 if (p != astate)
366 arp_free(p);
367 }
368}
369
370void
371arp_close(struct interface *ifp)
372{
373 struct dhcp_state *state = D_STATE(ifp);
374 struct arp_state *astate;
375
376 if (state == NULL)
377 return;
378
379 if (state->arp_fd != -1) {
380 eloop_event_delete(ifp->ctx->eloop, state->arp_fd, 0);
381 close(state->arp_fd);
382 state->arp_fd = -1;
383 }
384
385 while ((astate = TAILQ_FIRST(&state->arp_states))) {
386#ifndef __clang_analyzer__
387 /* clang guard needed for a more compex variant on this bug:
388 * http://llvm.org/bugs/show_bug.cgi?id=18222 */
389 arp_free(astate);
390#endif
391 }
392}
393
394void
395arp_handleifa(int cmd, struct interface *ifp, const struct in_addr *addr,
396 int flags)
397{
398#ifdef IN_IFF_DUPLICATED
399 struct dhcp_state *state = D_STATE(ifp);
400 struct arp_state *astate, *asn;
401
402 if (cmd != RTM_NEWADDR || (state = D_STATE(ifp)) == NULL)
403 return;
404
405 TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, asn) {
406 if (astate->addr.s_addr == addr->s_addr) {
407 if (flags & IN_IFF_DUPLICATED) {
408 if (astate->conflicted_cb)
409 astate->conflicted_cb(astate, NULL);
410 } else if (!(flags & IN_IFF_NOTUSEABLE)) {
411 if (astate->probed_cb)
412 astate->probed_cb(astate);
413 }
414 }
415 }
416#else
417 UNUSED(cmd);
418 UNUSED(ifp);
419 UNUSED(addr);
420 UNUSED(flags);
421#endif
422}