/*
 * dhcpcd - DHCP client daemon
 * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
 * All rights reserved

 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define ELOOP_QUEUE 6
#include "config.h"
#include "arp.h"
#include "common.h"
#include "dhcp.h"
#include "eloop.h"
#include "if.h"
#include "if-options.h"
#include "ipv4ll.h"

static struct dhcp_message *
ipv4ll_make_lease(uint32_t addr)
{
	uint32_t u32;
	struct dhcp_message *dhcp;
	uint8_t *p;

	dhcp = calloc(1, sizeof(*dhcp));
	if (dhcp == NULL)
		return NULL;
	/* Put some LL options in */
	dhcp->yiaddr = addr;
	p = dhcp->options;
	*p++ = DHO_SUBNETMASK;
	*p++ = sizeof(u32);
	u32 = htonl(LINKLOCAL_MASK);
	memcpy(p, &u32, sizeof(u32));
	p += sizeof(u32);
	*p++ = DHO_BROADCAST;
	*p++ = sizeof(u32);
	u32 = htonl(LINKLOCAL_BRDC);
	memcpy(p, &u32, sizeof(u32));
	p += sizeof(u32);
	*p++ = DHO_END;

	return dhcp;
}

static in_addr_t
ipv4ll_pick_addr(const struct arp_state *astate)
{
	in_addr_t addr;
	struct interface *ifp;
	const struct dhcp_state *state;

	for (;;) {
		/* RFC 3927 Section 2.1 states that the first 256 and
		 * last 256 addresses are reserved for future use.
		 * See ipv4ll_start for why we don't use arc4_random. */
		addr = ntohl(LINKLOCAL_ADDR |
		    ((uint32_t)(random() % 0xFD00) + 0x0100));

		/* No point using a failed address */
		if (addr == astate->failed.s_addr)
			continue;

		/* Ensure we don't have the address on another interface */
		TAILQ_FOREACH(ifp, astate->iface->ctx->ifaces, next) {
			state = D_CSTATE(ifp);
			if (state && state->addr.s_addr == addr)
				break;
		}

		/* Yay, this should be a unique and workable IPv4LL address */
		if (ifp == NULL)
			break;
	}
	return addr;
}

static void
ipv4ll_probed(struct arp_state *astate)
{
	struct dhcp_state *state = D_STATE(astate->iface);

	if (state->state == DHS_IPV4LL_BOUND) {
		ipv4_finaliseaddr(astate->iface);
		return;
	}

	if (state->state != DHS_BOUND) {
		struct dhcp_message *offer;

		/* A DHCP lease could have already been offered.
		 * Backup and replace once the IPv4LL address is bound */
		offer = state->offer;
		state->offer = ipv4ll_make_lease(astate->addr.s_addr);
		if (state->offer == NULL)
			logger(astate->iface->ctx, LOG_ERR, "%s: %m", __func__);
		else
			dhcp_bind(astate->iface, astate);
		state->offer = offer;
	}
}

static void
ipv4ll_announced(struct arp_state *astate)
{
	struct dhcp_state *state = D_STATE(astate->iface);

	state->conflicts = 0;
	/* Need to keep the arp state so we can defend our IP. */
}

static void
ipv4ll_probe(void *arg)
{

#ifdef IN_IFF_TENTATIVE
	ipv4ll_probed(arg);
#else
	arp_probe(arg);
#endif
}

static void
ipv4ll_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
{
	struct dhcp_state *state = D_STATE(astate->iface);
	in_addr_t fail;

	fail = 0;
	/* RFC 3927 2.2.1, Probe Conflict Detection */
	if (amsg == NULL ||
	    (amsg->sip.s_addr == astate->addr.s_addr ||
	    (amsg->sip.s_addr == 0 && amsg->tip.s_addr == astate->addr.s_addr)))
		fail = astate->addr.s_addr;

	/* RFC 3927 2.5, Conflict Defense */
	if (IN_LINKLOCAL(htonl(state->addr.s_addr)) &&
	    amsg && amsg->sip.s_addr == state->addr.s_addr)
		fail = state->addr.s_addr;

	if (fail == 0)
		return;

	astate->failed.s_addr = fail;
	arp_report_conflicted(astate, amsg);

	if (astate->failed.s_addr == state->addr.s_addr) {
		time_t up;

		/* RFC 3927 Section 2.5 */
		up = uptime();
		if (state->defend + DEFEND_INTERVAL > up) {
			logger(astate->iface->ctx, LOG_WARNING,
			    "%s: IPv4LL %d second defence failed for %s",
			    astate->iface->name, DEFEND_INTERVAL,
			    inet_ntoa(state->addr));
			dhcp_drop(astate->iface, "EXPIRE");
		} else {
			logger(astate->iface->ctx, LOG_DEBUG,
			    "%s: defended IPv4LL address %s",
			    astate->iface->name, inet_ntoa(state->addr));
			state->defend = up;
			return;
		}
	}

	arp_cancel(astate);
	if (++state->conflicts == MAX_CONFLICTS)
		logger(astate->iface->ctx, LOG_ERR,
		    "%s: failed to acquire an IPv4LL address",
		    astate->iface->name);
	astate->addr.s_addr = ipv4ll_pick_addr(astate);
	eloop_timeout_add_sec(astate->iface->ctx->eloop,
		state->conflicts >= MAX_CONFLICTS ?
		RATE_LIMIT_INTERVAL : PROBE_WAIT,
		ipv4ll_probe, astate);
}

void
ipv4ll_start(void *arg)
{
	struct interface *ifp = arg;
	struct dhcp_state *state = D_STATE(ifp);
	struct arp_state *astate;
	struct ipv4_addr *ap;

	if (state->arp_ipv4ll)
		return;

	/* RFC 3927 Section 2.1 states that the random number generator
	 * SHOULD be seeded with a value derived from persistent information
	 * such as the IEEE 802 MAC address so that it usually picks
	 * the same address without persistent storage. */
	if (state->conflicts == 0) {
		unsigned int seed;

		if (sizeof(seed) > ifp->hwlen) {
			seed = 0;
			memcpy(&seed, ifp->hwaddr, ifp->hwlen);
		} else
			memcpy(&seed, ifp->hwaddr + ifp->hwlen - sizeof(seed),
			    sizeof(seed));
		initstate(seed, state->randomstate, sizeof(state->randomstate));
	}

	if ((astate = arp_new(ifp, NULL)) == NULL)
		return;

	state->arp_ipv4ll = astate;
	astate->probed_cb = ipv4ll_probed;
	astate->announced_cb = ipv4ll_announced;
	astate->conflicted_cb = ipv4ll_conflicted;

	if (IN_LINKLOCAL(htonl(state->addr.s_addr))) {
		astate->addr = state->addr;
		arp_announce(astate);
		return;
	}

	if (state->offer && IN_LINKLOCAL(ntohl(state->offer->yiaddr))) {
		astate->addr.s_addr = state->offer->yiaddr;
		free(state->offer);
		state->offer = NULL;
		ap = ipv4_iffindaddr(ifp, &astate->addr, NULL);
	} else
		ap = ipv4_iffindlladdr(ifp);
	if (ap) {
		astate->addr = ap->addr;
		ipv4ll_probed(astate);
		return;
	}

	setstate(state->randomstate);
	/* We maybe rebooting an IPv4LL address. */
	if (!IN_LINKLOCAL(htonl(astate->addr.s_addr))) {
		logger(ifp->ctx, LOG_INFO, "%s: probing for an IPv4LL address",
		    ifp->name);
		astate->addr.s_addr = INADDR_ANY;
	}
	if (astate->addr.s_addr == INADDR_ANY)
		astate->addr.s_addr = ipv4ll_pick_addr(astate);
#ifdef IN_IFF_TENTATIVE
	ipv4ll_probed(astate);
#else
	arp_probe(astate);
#endif
}

void
ipv4ll_stop(struct interface *ifp)
{
	struct dhcp_state *state = D_STATE(ifp);

	eloop_timeout_delete(ifp->ctx->eloop, NULL, state->arp_ipv4ll);
}
