1e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/*
2e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * dhcpcd - DHCP client daemon
3e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * Copyright (c) 2006-2008 Roy Marples <roy@marples.name>
4e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * All rights reserved
5e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
6e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * Redistribution and use in source and binary forms, with or without
7e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * modification, are permitted provided that the following conditions
8e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * are met:
9e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * 1. Redistributions of source code must retain the above copyright
10e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *    notice, this list of conditions and the following disclaimer.
11e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * 2. Redistributions in binary form must reproduce the above copyright
12e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *    notice, this list of conditions and the following disclaimer in the
13e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *    documentation and/or other materials provided with the distribution.
14e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *
15e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * SUCH DAMAGE.
26e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt */
27e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
28e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <errno.h>
29e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <signal.h>
30e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <stdlib.h>
31e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <string.h>
32e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <syslog.h>
33e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <unistd.h>
34e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
35e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "arp.h"
36e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "common.h"
37e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "dhcpcd.h"
38e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "eloop.h"
39e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "if-options.h"
40e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "ipv4ll.h"
41e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "net.h"
42e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
43e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct dhcp_message *
44e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtmake_ipv4ll_lease(uint32_t addr)
45e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
46e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	uint32_t u32;
47e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct dhcp_message *dhcp;
48e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	uint8_t *p;
49e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
50e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	dhcp = xzalloc(sizeof(*dhcp));
51e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* Put some LL options in */
52e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	dhcp->yiaddr = addr;
53e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	p = dhcp->options;
54e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	*p++ = DHO_SUBNETMASK;
55e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	*p++ = sizeof(u32);
56e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	u32 = htonl(LINKLOCAL_MASK);
57e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	memcpy(p, &u32, sizeof(u32));
58e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	p += sizeof(u32);
59e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	*p++ = DHO_BROADCAST;
60e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	*p++ = sizeof(u32);
61e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	u32 = htonl(LINKLOCAL_BRDC);
62e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	memcpy(p, &u32, sizeof(u32));
63e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	p += sizeof(u32);
64e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	*p++ = DHO_END;
65e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
66e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return dhcp;
67e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
68e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
69e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct dhcp_message *
70e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtfind_ipv4ll_lease(uint32_t old_addr)
71e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
72e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	uint32_t addr;
73e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
74e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (;;) {
75e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		addr = htonl(LINKLOCAL_ADDR |
76e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    (((uint32_t)abs((int)arc4random())
77e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			% 0xFD00) + 0x0100));
78e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (addr != old_addr &&
79e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    IN_LINKLOCAL(ntohl(addr)))
80e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
81e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
82e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	return make_ipv4ll_lease(addr);
83e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
84e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
85e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
86e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_ipv4ll(void *arg)
87e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
88e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface = arg;
89e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	uint32_t addr;
90e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
91e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	delete_timeout(NULL, iface);
92e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->probes = 0;
93e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->claims = 0;
94e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->addr.s_addr) {
95e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state->conflicts = 0;
96e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (IN_LINKLOCAL(htonl(iface->addr.s_addr))) {
97e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			send_arp_announce(iface);
98e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return;
99e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
101e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
102e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->state->offer == NULL)
103e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		addr = 0;
104e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else {
105e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		addr = iface->state->offer->yiaddr;
106e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(iface->state->offer);
107e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
108e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* We maybe rebooting an IPv4LL address. */
109e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!IN_LINKLOCAL(htonl(addr))) {
110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_INFO, "%s: probing for an IPv4LL address",
111e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    iface->name);
112e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		addr = 0;
113e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
114e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (addr == 0)
115e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state->offer = find_ipv4ll_lease(addr);
116e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else
117e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state->offer = make_ipv4ll_lease(addr);
118e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->lease.frominfo = 0;
119e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	send_arp_probe(iface);
120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
121e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
122e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
123e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_ipv4ll_failure(void *arg)
124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
125e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct interface *iface = arg;
126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	time_t up;
127e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
128e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (iface->state->fail.s_addr == iface->addr.s_addr) {
129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		up = uptime();
130e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (iface->state->defend + DEFEND_INTERVAL > up) {
131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_DEBUG,
132e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    "%s: IPv4LL %d second defence failed",
133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface->name, DEFEND_INTERVAL);
134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			drop_config(iface, "EXPIRE");
135e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->state->conflicts = -1;
136e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else {
137e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_DEBUG, "%s: defended IPv4LL address",
138e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    iface->name);
139e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			iface->state->defend = up;
140e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return;
141e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
142e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
143e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
144e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	close_sockets(iface);
145e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(iface->state->offer);
146e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	iface->state->offer = NULL;
147e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	delete_timeout(NULL, iface);
148e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (++iface->state->conflicts > MAX_CONFLICTS) {
149e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		syslog(LOG_ERR, "%s: failed to acquire an IPv4LL address",
150e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    iface->name);
151e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		iface->state->interval = RATE_LIMIT_INTERVAL / 2;
152e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		start_discover(iface);
153e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	} else {
154e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		add_timeout_sec(PROBE_WAIT, start_ipv4ll, iface);
155e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
156e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
157