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

#include <logging/log.h>
LOG_MODULE_REGISTER(net_mgmt_sock_sample, LOG_LEVEL_DBG);

#include <zephyr.h>
#include <errno.h>
#include <stdio.h>
#include <net/socket.h>
#include <net/socket_net_mgmt.h>
#include <net/net_if.h>

#define MAX_BUF_LEN 64
#define STACK_SIZE 1024
#if IS_ENABLED(CONFIG_NET_TC_THREAD_COOPERATIVE)
#define THREAD_PRIORITY K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1)
#else
#define THREAD_PRIORITY K_PRIO_PREEMPT(8)
#endif

/* A test thread that spits out events that we can catch and show to user */
static void trigger_events(void)
{
	int operation = 0;
	struct net_if_addr *ifaddr_v6;
	struct net_if *iface;
	struct in6_addr addr_v6;
	int ret;

	iface = net_if_get_default();

	net_ipv6_addr_create(&addr_v6, 0x2001, 0x0db8, 0, 0, 0, 0, 0, 0x0003);

	while (1) {
		switch (operation) {
		case 0:
			ifaddr_v6 = net_if_ipv6_addr_add(iface, &addr_v6,
							 NET_ADDR_MANUAL, 0);
			if (!ifaddr_v6) {
				LOG_ERR("Cannot add IPv%c address", '6');
				break;
			}

			break;
		case 1:
			ret = net_if_ipv6_addr_rm(iface, &addr_v6);
			if (!ret) {
				LOG_ERR("Cannot del IPv%c address", '6');
				break;
			}

			break;
		default:
			operation = -1;
			break;
		}

		operation++;

		k_sleep(K_SECONDS(1));
	}
}

K_THREAD_DEFINE(trigger_events_thread_id, STACK_SIZE,
		trigger_events, NULL, NULL, NULL,
		THREAD_PRIORITY, 0, -1);

static char *get_ip_addr(char *ipaddr, size_t len, sa_family_t family,
			 struct net_mgmt_msghdr *hdr)
{
	char *buf;

	buf = net_addr_ntop(family, hdr->nm_msg, ipaddr, len);
	if (!buf) {
		return "?";
	}

	return buf;
}

static void listener(void)
{
	struct sockaddr_nm sockaddr;
	struct sockaddr_nm event_addr;
	socklen_t event_addr_len;
	char ipaddr[INET6_ADDRSTRLEN];
	uint8_t buf[MAX_BUF_LEN];
	int fd, ret;

	fd = socket(AF_NET_MGMT, SOCK_DGRAM, NET_MGMT_EVENT_PROTO);
	if (fd < 0) {
		printk("Cannot create net_mgmt socket (%d)\n", errno);
		exit(1);
	}

	memset(&sockaddr, 0, sizeof(sockaddr));

	sockaddr.nm_family = AF_NET_MGMT;
	sockaddr.nm_ifindex = 0; /* Any network interface */
	sockaddr.nm_pid = (uintptr_t)k_current_get();
	sockaddr.nm_mask = NET_EVENT_IPV6_DAD_SUCCEED |
			    NET_EVENT_IPV6_ADDR_ADD |
			    NET_EVENT_IPV6_ADDR_DEL;

	ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
	if (ret < 0) {
		printk("Cannot bind net_mgmt socket (%d)\n", errno);
		exit(1);
	}

	while (1) {
		struct net_mgmt_msghdr *hdr;

		memset(buf, 0, sizeof(buf));
		event_addr_len = sizeof(event_addr);

		ret = recvfrom(fd, buf, sizeof(buf), 0,
			       (struct sockaddr *)&event_addr,
			       &event_addr_len);
		if (ret < 0) {
			continue;
		}

		hdr = (struct net_mgmt_msghdr *)buf;

		if (hdr->nm_msg_version != NET_MGMT_SOCKET_VERSION_1) {
			/* Do not know how to parse the message */
			continue;
		}

		switch (event_addr.nm_mask) {
		case NET_EVENT_IPV6_DAD_SUCCEED:
			printk("DAD succeed for interface %d (%s)\n",
			       event_addr.nm_ifindex,
			       get_ip_addr(ipaddr, sizeof(ipaddr),
					   AF_INET6, hdr));
			break;
		case NET_EVENT_IPV6_ADDR_ADD:
			printk("IPv6 address added to interface %d (%s)\n",
			       event_addr.nm_ifindex,
			       get_ip_addr(ipaddr, sizeof(ipaddr),
					   AF_INET6, hdr));
			break;
		case NET_EVENT_IPV6_ADDR_DEL:
			printk("IPv6 address removed from interface %d (%s)\n",
			       event_addr.nm_ifindex,
			       get_ip_addr(ipaddr, sizeof(ipaddr),
					   AF_INET6, hdr));
			break;
		}
	}
}

void main(void)
{
	/* The thread start to trigger network management events that
	 * we then can catch.
	 */
	k_thread_start(trigger_events_thread_id);

	if (IS_ENABLED(CONFIG_USERSPACE)) {
		k_thread_user_mode_enter((k_thread_entry_t)listener,
					 NULL, NULL, NULL);
	} else {
		listener();
	}
}
