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

#include <logging/log.h>
LOG_MODULE_REGISTER(net_bt, CONFIG_NET_L2_BT_LOG_LEVEL);

#include <kernel.h>
#include <toolchain.h>
#include <linker/sections.h>
#include <string.h>
#include <errno.h>

#include <device.h>
#include <init.h>

#include <net/net_pkt.h>
#include <net/net_core.h>
#include <net/net_l2.h>
#include <net/net_if.h>
#include <net/bt.h>
#include <6lo.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/conn.h>
#include <bluetooth/uuid.h>
#include <bluetooth/l2cap.h>

#include "net_private.h"
#include "ipv6.h"

#define BUF_TIMEOUT K_MSEC(50)

#define L2CAP_IPSP_PSM 0x0023
#define L2CAP_IPSP_MTU 1280

#define CHAN_CONN(_conn) CONTAINER_OF(_conn, struct bt_if_conn, ipsp_chan.chan)

#if defined(CONFIG_NET_L2_BT_MGMT)
static struct bt_conn *default_conn;
#endif

#if defined(CONFIG_NET_L2_BT_SHELL)
extern int net_bt_shell_init(void);
#else
#define net_bt_shell_init(...)
#endif

struct bt_if_conn {
	struct net_if *iface;
	struct bt_l2cap_le_chan ipsp_chan;
	bt_addr_t src;
	bt_addr_t dst;
};

struct bt_context {
	struct bt_if_conn conns[CONFIG_BT_MAX_CONN];
};

static enum net_verdict net_bt_recv(struct net_if *iface, struct net_pkt *pkt)
{
	NET_DBG("iface %p pkt %p len %zu", iface, pkt, net_pkt_get_len(pkt));

	if (!net_6lo_uncompress(pkt)) {
		NET_DBG("Packet decompression failed");
		return NET_DROP;
	}

	return NET_CONTINUE;
}

static struct bt_if_conn *net_bt_get_conn(struct net_if *iface)
{
	struct bt_context *ctxt = net_if_get_device(iface)->data;
	int i;

	for (i = 0; i < CONFIG_BT_MAX_CONN; i++) {
		if (ctxt->conns[i].iface == iface) {
			return &ctxt->conns[i];
		}
	}

	return NULL;
}

static int net_bt_send(struct net_if *iface, struct net_pkt *pkt)
{
	struct bt_if_conn *conn = net_bt_get_conn(iface);
	struct net_buf *buffer;
	int length;
	int ret;

	NET_DBG("iface %p pkt %p len %zu", iface, pkt, net_pkt_get_len(pkt));

	/* Only accept IPv6 packets */
	if (net_pkt_family(pkt) != AF_INET6) {
		return -EINVAL;
	}

	ret = net_6lo_compress(pkt, true);
	if (ret < 0) {
		NET_DBG("Packet compression failed");
		return ret;
	}

	length = net_pkt_get_len(pkt);

	/* Dettach data fragments for packet */
	buffer = pkt->buffer;
	pkt->buffer = NULL;

	ret = bt_l2cap_chan_send(&conn->ipsp_chan.chan, buffer);
	if (ret < 0) {
		NET_ERR("Unable to send packet: %d", ret);
		bt_l2cap_chan_disconnect(&conn->ipsp_chan.chan);
		return ret;
	}

	net_pkt_unref(pkt);

	return length;
}

static int net_bt_enable(struct net_if *iface, bool state)
{
	struct bt_if_conn *conn = net_bt_get_conn(iface);

	NET_DBG("iface %p %s", iface, state ? "up" : "down");

	if (state && conn->ipsp_chan.chan.state != BT_L2CAP_CONNECTED) {
		return -ENETDOWN;
	}

	return 0;
}

static enum net_l2_flags net_bt_flags(struct net_if *iface)
{
	return NET_L2_MULTICAST | NET_L2_MULTICAST_SKIP_JOIN_SOLICIT_NODE;
}

NET_L2_INIT(BLUETOOTH_L2, net_bt_recv, net_bt_send,
	    net_bt_enable, net_bt_flags);

static void ipsp_connected(struct bt_l2cap_chan *chan)
{
	struct bt_if_conn *conn = CHAN_CONN(chan);
	struct bt_conn_info info;
	struct net_linkaddr ll;
	struct in6_addr in6;

	if (bt_conn_get_info(chan->conn, &info) < 0) {
		NET_ERR("Unable to get connection info");
		bt_l2cap_chan_disconnect(chan);
		return;
	}

	if (CONFIG_NET_L2_BT_LOG_LEVEL >= LOG_LEVEL_DBG) {
		char src[BT_ADDR_LE_STR_LEN];
		char dst[BT_ADDR_LE_STR_LEN];

		bt_addr_le_to_str(info.le.src, src, sizeof(src));
		bt_addr_le_to_str(info.le.dst, dst, sizeof(dst));

		NET_DBG("Channel %p Source %s connected to Destination %s",
			chan, log_strdup(src), log_strdup(dst));
	}

	/* Swap bytes since net APIs expect big endian address */
	sys_memcpy_swap(conn->src.val, info.le.src->a.val, sizeof(conn->src));
	sys_memcpy_swap(conn->dst.val, info.le.dst->a.val, sizeof(conn->dst));

	net_if_set_link_addr(conn->iface, conn->src.val, sizeof(conn->src.val),
			     NET_LINK_BLUETOOTH);

	ll.addr = conn->dst.val;
	ll.len = sizeof(conn->dst.val);
	ll.type = NET_LINK_BLUETOOTH;

	/* Add remote link-local address to the nbr cache to avoid sending ns:
	 * https://tools.ietf.org/html/rfc7668#section-3.2.3
	 * A Bluetooth LE 6LN MUST NOT register its link-local address.
	 */
	net_ipv6_addr_create_iid(&in6, &ll);
	net_ipv6_nbr_add(conn->iface, &in6, &ll, false,
			 NET_IPV6_NBR_STATE_STATIC);

	/* Set iface up */
	net_if_up(conn->iface);
}

static void ipsp_disconnected(struct bt_l2cap_chan *chan)
{
	struct bt_if_conn *conn = CHAN_CONN(chan);

	NET_DBG("Channel %p disconnected", chan);

	/* Set iface down */
	net_if_carrier_down(conn->iface);

#if defined(CONFIG_NET_L2_BT_MGMT)
	if (chan->conn != default_conn) {
		return;
	}

	bt_conn_unref(default_conn);
	default_conn = NULL;
#endif
}

static int ipsp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
	struct bt_if_conn *conn = CHAN_CONN(chan);
	struct net_pkt *pkt;

	NET_DBG("Incoming data channel %p len %zu", chan,
		net_buf_frags_len(buf));

	/* Get packet for bearer / protocol related data */
	pkt = net_pkt_rx_alloc_on_iface(conn->iface, BUF_TIMEOUT);
	if (!pkt) {
		return -ENOMEM;
	}

	/* Set destination address */
	net_pkt_lladdr_dst(pkt)->addr = conn->src.val;
	net_pkt_lladdr_dst(pkt)->len = sizeof(conn->src);
	net_pkt_lladdr_dst(pkt)->type = NET_LINK_BLUETOOTH;

	/* Set source address */
	net_pkt_lladdr_src(pkt)->addr = conn->dst.val;
	net_pkt_lladdr_src(pkt)->len = sizeof(conn->dst);
	net_pkt_lladdr_src(pkt)->type = NET_LINK_BLUETOOTH;

	/* Add data buffer as fragment of RX buffer, take a reference while
	 * doing so since L2CAP will unref the buffer after return.
	 */
	net_pkt_append_buffer(pkt, net_buf_ref(buf));

	if (net_recv_data(conn->iface, pkt) < 0) {
		NET_DBG("Packet dropped by NET stack");
		net_pkt_unref(pkt);
	}

	return 0;
}

static struct net_buf *ipsp_alloc_buf(struct bt_l2cap_chan *chan)
{
	NET_DBG("Channel %p requires buffer", chan);

	return net_pkt_get_reserve_rx_data(BUF_TIMEOUT);
}

static const struct bt_l2cap_chan_ops ipsp_ops = {
	.alloc_buf	= ipsp_alloc_buf,
	.recv		= ipsp_recv,
	.connected	= ipsp_connected,
	.disconnected	= ipsp_disconnected,
};

static struct bt_context bt_context_data = {
	.conns[0 ... (CONFIG_BT_MAX_CONN - 1)] = {
		.iface			= NULL,
		.ipsp_chan.chan.ops	= &ipsp_ops,
		.ipsp_chan.rx.mtu	= L2CAP_IPSP_MTU,
	}
};

static void bt_iface_init(struct net_if *iface)
{
	struct bt_context *ctxt = net_if_get_device(iface)->data;
	struct bt_if_conn *conn = NULL;
	int i;

	NET_DBG("iface %p", iface);

	/* Find unused slot to store the iface */
	for (i = 0; i < CONFIG_BT_MAX_CONN; i++) {
		if (!ctxt->conns[i].iface) {
			conn = &ctxt->conns[i];
			NET_DBG("[%d] alloc ctxt %p iface %p", i, ctxt, iface);
			break;
		}
	}

	if (!conn) {
		NET_ERR("Unable to allocate iface");
		return;
	}

	conn->iface = iface;

	net_if_flag_set(iface, NET_IF_NO_AUTO_START);

#if defined(CONFIG_NET_L2_BT_ZEP1656)
	/* Workaround Linux bug, see:
	 * https://github.com/zephyrproject-rtos/zephyr/issues/3111
	 */
	net_if_flag_set(iface, NET_IF_POINTOPOINT);
#endif
}

static struct net_if_api bt_if_api = {
	.init = bt_iface_init,
};

static int ipsp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
{
	struct bt_if_conn *if_conn = NULL;
	int i;

	NET_DBG("Incoming conn %p", conn);

	/* Find unused slot to store the iface */
	for (i = 0; i < CONFIG_BT_MAX_CONN; i++) {
		if (bt_context_data.conns[i].iface &&
		    !bt_context_data.conns[i].ipsp_chan.chan.conn) {
			if_conn = &bt_context_data.conns[i];
			break;
		}
	}

	if (!if_conn) {
		NET_ERR("No channels available");
		return -ENOMEM;
	}

	*chan = &if_conn->ipsp_chan.chan;

	return 0;
}

static struct bt_l2cap_server server = {
	.psm		= L2CAP_IPSP_PSM,
	.sec_level	= CONFIG_NET_L2_BT_SEC_LEVEL,
	.accept		= ipsp_accept,
};

#if defined(CONFIG_NET_L2_BT_MGMT)

#define DEVICE_NAME		CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN		(sizeof(DEVICE_NAME) - 1)
#define UNKNOWN_APPEARANCE	0x0000

static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
	BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_IPSS_VAL)),
};

static const struct bt_data sd[] = {
	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};

static int bt_advertise(uint32_t mgmt_request, struct net_if *iface, void *data,
		      size_t len)
{
	if (!strcmp(data, "on")) {
		return bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
				       sd, ARRAY_SIZE(sd));
	} else if (!strcmp(data, "off")) {
		return bt_le_adv_stop();
	} else {
		return -EINVAL;
	}

	return 0;
}

static int bt_connect(uint32_t mgmt_request, struct net_if *iface, void *data,
		      size_t len)
{
	struct bt_if_conn *conn = net_bt_get_conn(iface);
	bt_addr_le_t *addr = data;

	if (len != sizeof(*addr)) {
		NET_ERR("Invalid address");
		return -EINVAL;
	}

	if (conn->ipsp_chan.chan.conn) {
		NET_ERR("No channels available");
		return -ENOMEM;
	}

	if (default_conn) {
		return bt_l2cap_chan_connect(default_conn,
					     &conn->ipsp_chan.chan,
					     L2CAP_IPSP_PSM);
	}

	return bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
				 BT_LE_CONN_PARAM_DEFAULT, &default_conn);
}

static bool eir_found(uint8_t type, const uint8_t *data, uint8_t data_len,
		      void *user_data)
{
	int i;

	if (type != BT_DATA_UUID16_SOME && type != BT_DATA_UUID16_ALL) {
		return false;
	}

	if (data_len % sizeof(uint16_t) != 0U) {
		NET_ERR("AD malformed\n");
		return false;
	}

	for (i = 0; i < data_len; i += sizeof(uint16_t)) {
		struct bt_uuid *uuid;
		uint16_t u16;

		memcpy(&u16, &data[i], sizeof(u16));
		uuid = BT_UUID_DECLARE_16(sys_le16_to_cpu(u16));
		if (bt_uuid_cmp(uuid, BT_UUID_IPSS)) {
			continue;
		}

		if (CONFIG_NET_L2_BT_LOG_LEVEL >= LOG_LEVEL_DBG) {
			bt_addr_le_t *addr = user_data;
			char dev[BT_ADDR_LE_STR_LEN];

			bt_addr_le_to_str(addr, dev, sizeof(dev));
			NET_DBG("[DEVICE]: %s", log_strdup(dev));
		}

		/* TODO: Notify device address found */
		net_mgmt_event_notify(NET_EVENT_BT_SCAN_RESULT,
				      bt_context_data.conns[0].iface);

		return true;
	}

	return false;
}

static bool ad_parse(struct net_buf_simple *ad,
		     bool (*func)(uint8_t type, const uint8_t *data,
				  uint8_t data_len, void *user_data),
		     void *user_data)
{
	while (ad->len > 1) {
		uint8_t len = net_buf_simple_pull_u8(ad);
		uint8_t type;

		/* Check for early termination */
		if (len == 0U) {
			return false;
		}

		if (len > ad->len) {
			NET_ERR("AD malformed\n");
			return false;
		}

		type = net_buf_simple_pull_u8(ad);

		if (func(type, ad->data, len - 1, user_data)) {
			return true;
		}

		net_buf_simple_pull(ad, len - 1);
	}

	return false;
}

static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
			 struct net_buf_simple *ad)
{
	/* We're only interested in connectable events */
	if (type == BT_GAP_ADV_TYPE_ADV_IND ||
	    type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
		ad_parse(ad, eir_found, (void *)addr);
	}
}

static void bt_active_scan(void)
{
	int err;

	err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);
	if (err) {
		NET_ERR("Bluetooth set active scan failed (err %d)\n", err);
	}
}

static void bt_passive_scan(void)
{
	int err;

	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found);
	if (err) {
		NET_ERR("Bluetooth set passive scan failed (err %d)\n", err);
	}
}

static void bt_scan_off(void)
{
	int err;

	err = bt_le_scan_stop();
	if (err) {
		NET_ERR("Stopping scanning failed (err %d)\n", err);
	}
}

static int bt_scan(uint32_t mgmt_request, struct net_if *iface, void *data,
		   size_t len)
{
	if (!strcmp(data, "on") || !strcmp(data, "active")) {
		bt_active_scan();
	} else if (!strcmp(data, "passive")) {
		bt_passive_scan();
	} else if (!strcmp("off", data)) {
		bt_scan_off();
	} else {
		return -EINVAL;
	}

	return 0;
}

static int bt_disconnect(uint32_t mgmt_request, struct net_if *iface,
			 void *data, size_t len)
{
	struct bt_if_conn *conn = net_bt_get_conn(iface);

	if (!conn->ipsp_chan.chan.conn) {
		NET_ERR("Not connected");
		return -ENOTCONN;
	}

	/* Release connect reference in case of central/router role */
	if (default_conn) {
		bt_conn_unref(default_conn);
		default_conn = NULL;
	}

	return bt_l2cap_chan_disconnect(&conn->ipsp_chan.chan);
}

static void connected(struct bt_conn *conn, uint8_t err)
{
	int i;

	if (err) {
		if (CONFIG_NET_L2_BT_LOG_LEVEL >= LOG_LEVEL_DBG) {
			char addr[BT_ADDR_LE_STR_LEN];

			bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
					  sizeof(addr));

			NET_ERR("Failed to connect to %s (%u)\n",
				log_strdup(addr), err);
		}

		return;
	}

	if (conn != default_conn) {
		return;
	}

	for (i = 0; i < CONFIG_BT_MAX_CONN; i++) {
		struct bt_if_conn *if_conn = &bt_context_data.conns[i];

		if (if_conn->ipsp_chan.chan.conn == conn) {
			bt_l2cap_chan_connect(conn, &if_conn->ipsp_chan.chan,
					      L2CAP_IPSP_PSM);
			break;
		}
	}
}

static void disconnected(struct bt_conn *conn, uint8_t reason)
{
	if (conn != default_conn) {
		return;
	}

	if (CONFIG_NET_L2_BT_LOG_LEVEL >= LOG_LEVEL_DBG) {
		char addr[BT_ADDR_LE_STR_LEN];

		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

		NET_DBG("Disconnected: %s (reason 0x%02x)\n",
			log_strdup(addr), reason);
	}

	bt_conn_unref(default_conn);
	default_conn = NULL;
}

static struct bt_conn_cb conn_callbacks = {
	.connected = connected,
	.disconnected = disconnected,
};
#endif /* CONFIG_NET_L2_BT_MGMT */

static int net_bt_init(const struct device *dev)
{
	NET_DBG("dev %p driver_data %p", dev, dev->data);

#if defined(CONFIG_NET_L2_BT_MGMT)
	bt_conn_cb_register(&conn_callbacks);
#endif
	bt_l2cap_server_register(&server);

	net_bt_shell_init();

	return 0;
}

#if defined(CONFIG_NET_L2_BT_MGMT)
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_BT_ADVERTISE, bt_advertise);
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_BT_CONNECT, bt_connect);
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_BT_SCAN, bt_scan);
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_BT_DISCONNECT, bt_disconnect);
#endif

DEVICE_AND_API_INIT(net_bt, "net_bt", net_bt_init, &bt_context_data, NULL,
		    POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
		    &bt_if_api);
NET_L2_DATA_INIT(net_bt, 0, NET_L2_GET_CTX_TYPE(BLUETOOTH_L2));
NET_IF_INIT(net_bt, 0, BLUETOOTH_L2, L2CAP_IPSP_MTU, CONFIG_BT_MAX_CONN);
