/** @file
 * @brief IPv6 MLD related functions
 */

/*
 * Copyright (c) 2018 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <logging/log.h>
LOG_MODULE_DECLARE(net_ipv6, CONFIG_NET_IPV6_LOG_LEVEL);

#include <errno.h>
#include <net/net_core.h>
#include <net/net_pkt.h>
#include <net/net_stats.h>
#include <net/net_context.h>
#include <net/net_mgmt.h>
#include "net_private.h"
#include "connection.h"
#include "icmpv6.h"
#include "udp_internal.h"
#include "tcp_internal.h"
#include "ipv6.h"
#include "nbr.h"
#include "6lo.h"
#include "route.h"
#include "net_stats.h"

/* Timeout for various buffer allocations in this file. */
#define PKT_WAIT_TIME K_MSEC(50)

#define MLDv2_MCAST_RECORD_LEN sizeof(struct net_icmpv6_mld_mcast_record)
#define IPV6_OPT_HDR_ROUTER_ALERT_LEN 8

#define MLDv2_LEN (MLDv2_MCAST_RECORD_LEN + sizeof(struct in6_addr))

static int mld_create(struct net_pkt *pkt,
		      const struct in6_addr *addr,
		      u8_t record_type,
		      u16_t num_sources)
{
	NET_PKT_DATA_ACCESS_DEFINE(mld_access,
				   struct net_icmpv6_mld_mcast_record);
	struct net_icmpv6_mld_mcast_record *mld;

	mld = (struct net_icmpv6_mld_mcast_record *)
				net_pkt_get_data(pkt, &mld_access);
	if (!mld) {
		return -ENOBUFS;
	}

	mld->record_type = record_type;
	mld->aux_data_len = 0U;
	mld->num_sources = htons(num_sources);

	net_ipaddr_copy(&mld->mcast_address, addr);

	if (net_pkt_set_data(pkt, &mld_access)) {
		return -ENOBUFS;
	}

	if (num_sources > 0) {
		/* All source addresses, RFC 3810 ch 3 */
		if (net_pkt_write(pkt,
				  net_ipv6_unspecified_address()->s6_addr,
				  sizeof(struct in6_addr))) {
			return -ENOBUFS;
		}
	}

	return 0;
}

static int mld_create_packet(struct net_pkt *pkt, u16_t count)
{
	struct in6_addr dst;

	/* Sent to all MLDv2-capable routers */
	net_ipv6_addr_create(&dst, 0xff02, 0, 0, 0, 0, 0, 0, 0x0016);

	net_pkt_set_ipv6_hop_limit(pkt, 1); /* RFC 3810 ch 7.4 */

	if (net_ipv6_create(pkt, net_if_ipv6_select_src_addr(
				    net_pkt_iface(pkt), &dst),
			    &dst)) {
		return -ENOBUFS;
	}

	/* Add hop-by-hop option and router alert option, RFC 3810 ch 5. */
	if (net_pkt_write_u8(pkt, IPPROTO_ICMPV6) ||
	    net_pkt_write_u8(pkt, 0)) {
		return -ENOBUFS;
	}

	/* IPv6 router alert option is described in RFC 2711.
	 * - 0x0502 RFC 2711 ch 2.1
	 * - MLD (value 0)
	 * - 2 bytes of padding
	 */
	if (net_pkt_write_be16(pkt, 0x0502) ||
	    net_pkt_write_be16(pkt, 0) ||
	    net_pkt_write_be16(pkt, 0)) {
		return -ENOBUFS;
	}

	net_pkt_set_ipv6_ext_len(pkt, IPV6_OPT_HDR_ROUTER_ALERT_LEN);

	/* ICMPv6 header + reserved space + count.
	 * MLDv6 stuff will come right after
	 */
	if (net_icmpv6_create(pkt, NET_ICMPV6_MLDv2, 0) ||
	    net_pkt_write_be16(pkt, 0) ||
	    net_pkt_write_be16(pkt, count)) {
		return -ENOBUFS;
	}

	net_pkt_set_ipv6_next_hdr(pkt, NET_IPV6_NEXTHDR_HBHO);

	return 0;
}

static int mld_send(struct net_pkt *pkt)
{
	net_pkt_cursor_init(pkt);
	net_ipv6_finalize(pkt, IPPROTO_ICMPV6);

	if (net_send_data(pkt) < 0) {
		net_stats_update_icmp_drop(net_pkt_iface(pkt));
		net_stats_update_ipv6_mld_drop(net_pkt_iface(pkt));

		net_pkt_unref(pkt);

		return -1;
	}

	net_stats_update_icmp_sent(net_pkt_iface(pkt));
	net_stats_update_ipv6_mld_sent(net_pkt_iface(pkt));

	return 0;
}

static int mld_send_generic(struct net_if *iface,
			    const struct in6_addr *addr,
			    u8_t mode)
{
	struct net_pkt *pkt;
	int ret;

	pkt = net_pkt_alloc_with_buffer(iface, IPV6_OPT_HDR_ROUTER_ALERT_LEN +
					NET_ICMPV6_UNUSED_LEN +
					MLDv2_MCAST_RECORD_LEN +
					sizeof(struct in6_addr),
					AF_INET6, IPPROTO_ICMPV6,
					PKT_WAIT_TIME);
	if (!pkt) {
		return -ENOMEM;
	}

	if (mld_create_packet(pkt, 1) ||
	    mld_create(pkt, addr, mode, 1)) {
		ret = -ENOBUFS;
		goto drop;
	}

	ret = mld_send(pkt);
	if (ret) {
		goto drop;
	}

	return 0;

drop:
	net_pkt_unref(pkt);

	return ret;
}

int net_ipv6_mld_join(struct net_if *iface, const struct in6_addr *addr)
{
	struct net_if_mcast_addr *maddr;
	int ret;

	maddr = net_if_ipv6_maddr_lookup(addr, &iface);
	if (maddr && net_if_ipv6_maddr_is_joined(maddr)) {
		return -EALREADY;
	}

	if (!maddr) {
		maddr = net_if_ipv6_maddr_add(iface, addr);
		if (!maddr) {
			return -ENOMEM;
		}
	}

	ret = mld_send_generic(iface, addr, NET_IPV6_MLDv2_MODE_IS_EXCLUDE);
	if (ret < 0) {
		return ret;
	}

	net_if_ipv6_maddr_join(maddr);

	net_if_mcast_monitor(iface, addr, true);

	net_mgmt_event_notify(NET_EVENT_IPV6_MCAST_JOIN, iface);

	return ret;
}

int net_ipv6_mld_leave(struct net_if *iface, const struct in6_addr *addr)
{
	int ret;

	if (!net_if_ipv6_maddr_rm(iface, addr)) {
		return -EINVAL;
	}

	ret = mld_send_generic(iface, addr, NET_IPV6_MLDv2_MODE_IS_INCLUDE);
	if (ret < 0) {
		return ret;
	}

	net_if_mcast_monitor(iface, addr, false);

	net_mgmt_event_notify(NET_EVENT_IPV6_MCAST_LEAVE, iface);

	return ret;
}

static void send_mld_report(struct net_if *iface)
{
	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
	struct net_pkt *pkt;
	int i, count = 0;

	NET_ASSERT(ipv6);

	for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) {
		if (!ipv6->mcast[i].is_used || !ipv6->mcast[i].is_joined) {
			continue;
		}

		count++;
	}

	pkt = net_pkt_alloc_with_buffer(iface, IPV6_OPT_HDR_ROUTER_ALERT_LEN +
					NET_ICMPV6_UNUSED_LEN +
					count * MLDv2_MCAST_RECORD_LEN,
					AF_INET6, IPPROTO_ICMPV6,
					PKT_WAIT_TIME);
	if (!pkt) {
		return;
	}

	if (mld_create_packet(pkt, count)) {
		goto drop;
	}

	for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) {
		if (!ipv6->mcast[i].is_used || !ipv6->mcast[i].is_joined) {
			continue;
		}

		if (!mld_create(pkt, &ipv6->mcast[i].address.in6_addr,
				NET_IPV6_MLDv2_MODE_IS_EXCLUDE, 0)) {
			goto drop;
		}
	}

	if (!mld_send(pkt)) {
		return;
	}

drop:
	net_pkt_unref(pkt);
}

#define dbg_addr(action, pkt_str, src, dst)				\
	do {								\
		NET_DBG("%s %s from %s to %s", action, pkt_str,         \
			log_strdup(net_sprint_ipv6_addr(src)),		\
			log_strdup(net_sprint_ipv6_addr(dst)));		\
	} while (0)

#define dbg_addr_recv(pkt_str, src, dst)	\
	dbg_addr("Received", pkt_str, src, dst)

static enum net_verdict handle_mld_query(struct net_pkt *pkt,
					 struct net_ipv6_hdr *ip_hdr,
					 struct net_icmp_hdr *icmp_hdr)
{
	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(mld_access,
					      struct net_icmpv6_mld_query);
	u16_t length = net_pkt_get_len(pkt);
	struct net_icmpv6_mld_query *mld_query;
	u16_t pkt_len;

	mld_query = (struct net_icmpv6_mld_query *)
				net_pkt_get_data(pkt, &mld_access);
	if (!mld_query) {
		NET_DBG("DROP: NULL MLD query");
		goto drop;
	}

	net_pkt_acknowledge_data(pkt, &mld_access);

	dbg_addr_recv("Multicast Listener Query", &ip_hdr->src, &ip_hdr->dst);

	net_stats_update_ipv6_mld_recv(net_pkt_iface(pkt));

	mld_query->num_sources = ntohs(mld_query->num_sources);

	pkt_len = sizeof(struct net_ipv6_hdr) +	net_pkt_ipv6_ext_len(pkt) +
		sizeof(struct net_icmp_hdr) +
		sizeof(struct net_icmpv6_mld_query) +
		sizeof(struct in6_addr) * mld_query->num_sources;

	if (length < pkt_len || pkt_len > NET_IPV6_MTU ||
	    ip_hdr->hop_limit != 1U || icmp_hdr->code != 0U) {
		goto drop;
	}

	/* Currently we only support an unspecified address query. */
	if (!net_ipv6_addr_cmp(&mld_query->mcast_address,
			       net_ipv6_unspecified_address())) {
		NET_DBG("DROP: only supporting unspecified address query");
		goto drop;
	}

	send_mld_report(net_pkt_iface(pkt));

	net_pkt_unref(pkt);

	return NET_OK;

drop:
	net_stats_update_ipv6_mld_drop(net_pkt_iface(pkt));

	return NET_DROP;
}

static struct net_icmpv6_handler mld_query_input_handler = {
	.type = NET_ICMPV6_MLD_QUERY,
	.code = 0,
	.handler = handle_mld_query,
};

void net_ipv6_mld_init(void)
{
	net_icmpv6_register_handler(&mld_query_input_handler);
}
