1d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/*
2d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * dhcpcd - DHCP client daemon
3d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
4d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * All rights reserved
5d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
6d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Redistribution and use in source and binary forms, with or without
7d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * modification, are permitted provided that the following conditions
8d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * are met:
9d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 1. Redistributions of source code must retain the above copyright
10d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *    notice, this list of conditions and the following disclaimer.
11d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 2. Redistributions in binary form must reproduce the above copyright
12d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *    notice, this list of conditions and the following disclaimer in the
13d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *    documentation and/or other materials provided with the distribution.
14d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *
15d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * SUCH DAMAGE.
26d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan */
27d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
28d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <errno.h>
29d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <signal.h>
30d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <stdlib.h>
31d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <string.h>
32d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <unistd.h>
33d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
34d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define ELOOP_QUEUE 6
35d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "config.h"
36d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "arp.h"
37d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "common.h"
38d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "dhcp.h"
39d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "eloop.h"
40d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "if.h"
41d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "if-options.h"
42d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "ipv4ll.h"
43d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
44d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic struct dhcp_message *
45d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_make_lease(uint32_t addr)
46d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
47d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	uint32_t u32;
48d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct dhcp_message *dhcp;
49d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	uint8_t *p;
50d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
51d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	dhcp = calloc(1, sizeof(*dhcp));
52d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (dhcp == NULL)
53d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return NULL;
54d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* Put some LL options in */
55d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	dhcp->yiaddr = addr;
56d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	p = dhcp->options;
57d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	*p++ = DHO_SUBNETMASK;
58d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	*p++ = sizeof(u32);
59d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	u32 = htonl(LINKLOCAL_MASK);
60d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	memcpy(p, &u32, sizeof(u32));
61d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	p += sizeof(u32);
62d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	*p++ = DHO_BROADCAST;
63d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	*p++ = sizeof(u32);
64d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	u32 = htonl(LINKLOCAL_BRDC);
65d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	memcpy(p, &u32, sizeof(u32));
66d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	p += sizeof(u32);
67d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	*p++ = DHO_END;
68d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
69d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	return dhcp;
70d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
71d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
72d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic in_addr_t
73d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_pick_addr(const struct arp_state *astate)
74d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
75d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	in_addr_t addr;
76d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct interface *ifp;
77d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	const struct dhcp_state *state;
78d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
79d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	for (;;) {
80d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* RFC 3927 Section 2.1 states that the first 256 and
81d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		 * last 256 addresses are reserved for future use.
82d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		 * See ipv4ll_start for why we don't use arc4_random. */
83d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		addr = ntohl(LINKLOCAL_ADDR |
84d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    ((uint32_t)(random() % 0xFD00) + 0x0100));
85d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
86d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* No point using a failed address */
87d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (addr == astate->failed.s_addr)
88d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			continue;
89d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
90d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* Ensure we don't have the address on another interface */
91d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		TAILQ_FOREACH(ifp, astate->iface->ctx->ifaces, next) {
92d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			state = D_CSTATE(ifp);
93d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			if (state && state->addr.s_addr == addr)
94d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan				break;
95d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
96d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
97d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* Yay, this should be a unique and workable IPv4LL address */
98d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (ifp == NULL)
99d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			break;
100d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
101d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	return addr;
102d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
103d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
104d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void
105d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_probed(struct arp_state *astate)
106d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
107d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct dhcp_state *state = D_STATE(astate->iface);
108d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
109d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (state->state == DHS_IPV4LL_BOUND) {
110d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		ipv4_finaliseaddr(astate->iface);
111d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return;
112d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
113d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
114d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (state->state != DHS_BOUND) {
115d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		struct dhcp_message *offer;
116d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
117d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* A DHCP lease could have already been offered.
118d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		 * Backup and replace once the IPv4LL address is bound */
119d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		offer = state->offer;
120d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		state->offer = ipv4ll_make_lease(astate->addr.s_addr);
121d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (state->offer == NULL)
122d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			logger(astate->iface->ctx, LOG_ERR, "%s: %m", __func__);
123d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		else
124d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			dhcp_bind(astate->iface, astate);
125d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		state->offer = offer;
126d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
127d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
128d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
129d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void
130d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_announced(struct arp_state *astate)
131d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
132d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct dhcp_state *state = D_STATE(astate->iface);
133d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
134d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	state->conflicts = 0;
135d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* Need to keep the arp state so we can defend our IP. */
136d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
137d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
138d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void
139d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_probe(void *arg)
140d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
141d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
142d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IN_IFF_TENTATIVE
143d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ipv4ll_probed(arg);
144d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else
145d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	arp_probe(arg);
146d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
147d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
148d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
149d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void
150d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
151d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
152d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct dhcp_state *state = D_STATE(astate->iface);
153d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	in_addr_t fail;
154d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
155d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	fail = 0;
156d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* RFC 3927 2.2.1, Probe Conflict Detection */
157d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (amsg == NULL ||
158d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    (amsg->sip.s_addr == astate->addr.s_addr ||
159d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    (amsg->sip.s_addr == 0 && amsg->tip.s_addr == astate->addr.s_addr)))
160d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		fail = astate->addr.s_addr;
161d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
162d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* RFC 3927 2.5, Conflict Defense */
163d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (IN_LINKLOCAL(htonl(state->addr.s_addr)) &&
164d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	    amsg && amsg->sip.s_addr == state->addr.s_addr)
165d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		fail = state->addr.s_addr;
166d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
167d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (fail == 0)
168d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return;
169d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
170d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	astate->failed.s_addr = fail;
171d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	arp_report_conflicted(astate, amsg);
172d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
173d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (astate->failed.s_addr == state->addr.s_addr) {
174d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		time_t up;
175d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
176d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		/* RFC 3927 Section 2.5 */
177d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		up = uptime();
178d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (state->defend + DEFEND_INTERVAL > up) {
179d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			logger(astate->iface->ctx, LOG_WARNING,
180d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    "%s: IPv4LL %d second defence failed for %s",
181d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    astate->iface->name, DEFEND_INTERVAL,
182d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    inet_ntoa(state->addr));
183d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			dhcp_drop(astate->iface, "EXPIRE");
184d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		} else {
185d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			logger(astate->iface->ctx, LOG_DEBUG,
186d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    "%s: defended IPv4LL address %s",
187d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    astate->iface->name, inet_ntoa(state->addr));
188d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			state->defend = up;
189d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			return;
190d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		}
191d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
192d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
193d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	arp_cancel(astate);
194d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (++state->conflicts == MAX_CONFLICTS)
195d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		logger(astate->iface->ctx, LOG_ERR,
196d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    "%s: failed to acquire an IPv4LL address",
197d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    astate->iface->name);
198d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	astate->addr.s_addr = ipv4ll_pick_addr(astate);
199d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	eloop_timeout_add_sec(astate->iface->ctx->eloop,
200d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		state->conflicts >= MAX_CONFLICTS ?
201d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		RATE_LIMIT_INTERVAL : PROBE_WAIT,
202d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		ipv4ll_probe, astate);
203d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
204d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
205d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid
206d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_start(void *arg)
207d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
208d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct interface *ifp = arg;
209d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct dhcp_state *state = D_STATE(ifp);
210d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct arp_state *astate;
211d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct ipv4_addr *ap;
212d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
213d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (state->arp_ipv4ll)
214d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return;
215d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
216d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* RFC 3927 Section 2.1 states that the random number generator
217d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	 * SHOULD be seeded with a value derived from persistent information
218d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	 * such as the IEEE 802 MAC address so that it usually picks
219d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	 * the same address without persistent storage. */
220d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (state->conflicts == 0) {
221d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		unsigned int seed;
222d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
223d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		if (sizeof(seed) > ifp->hwlen) {
224d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			seed = 0;
225d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			memcpy(&seed, ifp->hwaddr, ifp->hwlen);
226d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		} else
227d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			memcpy(&seed, ifp->hwaddr + ifp->hwlen - sizeof(seed),
228d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan			    sizeof(seed));
229d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		initstate(seed, state->randomstate, sizeof(state->randomstate));
230d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
231d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
232d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if ((astate = arp_new(ifp, NULL)) == NULL)
233d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return;
234d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
235d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	state->arp_ipv4ll = astate;
236d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	astate->probed_cb = ipv4ll_probed;
237d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	astate->announced_cb = ipv4ll_announced;
238d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	astate->conflicted_cb = ipv4ll_conflicted;
239d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
240d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (IN_LINKLOCAL(htonl(state->addr.s_addr))) {
241d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		astate->addr = state->addr;
242d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		arp_announce(astate);
243d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return;
244d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
245d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
246d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (state->offer && IN_LINKLOCAL(ntohl(state->offer->yiaddr))) {
247d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		astate->addr.s_addr = state->offer->yiaddr;
248d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		free(state->offer);
249d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		state->offer = NULL;
250d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		ap = ipv4_iffindaddr(ifp, &astate->addr, NULL);
251d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	} else
252d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		ap = ipv4_iffindlladdr(ifp);
253d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (ap) {
254d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		astate->addr = ap->addr;
255d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		ipv4ll_probed(astate);
256d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		return;
257d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
258d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
259d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	setstate(state->randomstate);
260d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	/* We maybe rebooting an IPv4LL address. */
261d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (!IN_LINKLOCAL(htonl(astate->addr.s_addr))) {
262d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		logger(ifp->ctx, LOG_INFO, "%s: probing for an IPv4LL address",
263d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		    ifp->name);
264d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		astate->addr.s_addr = INADDR_ANY;
265d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	}
266d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	if (astate->addr.s_addr == INADDR_ANY)
267d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan		astate->addr.s_addr = ipv4ll_pick_addr(astate);
268d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IN_IFF_TENTATIVE
269d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	ipv4ll_probed(astate);
270d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else
271d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	arp_probe(astate);
272d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif
273d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
274d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
275d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid
276d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_stop(struct interface *ifp)
277d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{
278d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	struct dhcp_state *state = D_STATE(ifp);
279d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan
280d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan	eloop_timeout_delete(ifp->ctx->eloop, NULL, state->arp_ipv4ll);
281d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan}
282