/*
 * Copyright (c) 2016 Intel Corporation
 * Copyright (c) 2023 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(net_shell);

#include "net_shell_private.h"

#include "../ip/route.h"

#if defined(CONFIG_NET_ROUTE) && defined(CONFIG_NET_NATIVE)
static void route_cb(struct net_route_entry *entry, void *user_data)
{
	struct net_shell_user_data *data = user_data;
	const struct shell *sh = data->sh;
	struct net_if *iface = data->user_data;
	struct net_route_nexthop *nexthop_route;
	int count;
	uint32_t now = k_uptime_get_32();

	if (entry->iface != iface) {
		return;
	}

	PR("IPv6 prefix : %s/%d\n", net_sprint_ipv6_addr(&entry->addr),
	   entry->prefix_len);

	count = 0;

	SYS_SLIST_FOR_EACH_CONTAINER(&entry->nexthop, nexthop_route, node) {
		struct net_linkaddr_storage *lladdr;
		char remaining_str[sizeof("01234567890 sec")];
		uint32_t remaining;

		if (!nexthop_route->nbr) {
			continue;
		}

		PR("\tneighbor : %p\t", nexthop_route->nbr);

		if (nexthop_route->nbr->idx == NET_NBR_LLADDR_UNKNOWN) {
			PR("addr : <unknown>\t");
		} else {
			lladdr = net_nbr_get_lladdr(nexthop_route->nbr->idx);

			PR("addr : %s\t", net_sprint_ll_addr(lladdr->addr,
							     lladdr->len));
		}

		if (entry->is_infinite) {
			snprintk(remaining_str, sizeof(remaining_str) - 1,
				 "infinite");
		} else {
			remaining = net_timeout_remaining(&entry->lifetime, now);
			snprintk(remaining_str, sizeof(remaining_str) - 1,
				 "%u sec", remaining);
		}

		PR("lifetime : %s\n", remaining_str);

		count++;
	}

	if (count == 0) {
		PR("\t<none>\n");
	}
}

static void iface_per_route_cb(struct net_if *iface, void *user_data)
{
	struct net_shell_user_data *data = user_data;
	const struct shell *sh = data->sh;
	const char *extra;

	PR("\nIPv6 routes for interface %d (%p) (%s)\n",
	   net_if_get_by_iface(iface), iface,
	   iface2str(iface, &extra));
	PR("=========================================%s\n", extra);

	data->user_data = iface;

	net_route_foreach(route_cb, data);
}
#endif /* CONFIG_NET_ROUTE */

#if defined(CONFIG_NET_ROUTE_MCAST) && defined(CONFIG_NET_NATIVE)
static void route_mcast_cb(struct net_route_entry_mcast *entry,
			   void *user_data)
{
	struct net_shell_user_data *data = user_data;
	const struct shell *sh = data->sh;

	PR("IPv6 multicast route (%p)\n", entry);
	PR("=================================\n");

	PR("IPv6 group     : %s\n", net_sprint_ipv6_addr(&entry->group));
	PR("IPv6 group len : %d\n", entry->prefix_len);
	PR("Lifetime       : %u\n", entry->lifetime);

	for (int i = 0; i < CONFIG_NET_MCAST_ROUTE_MAX_IFACES; ++i) {
		if (entry->ifaces[i]) {
			PR("Interface      : %d (%p) %s\n", net_if_get_by_iface(entry->ifaces[i]),
			   entry->ifaces[i], iface2str(entry->ifaces[i], NULL));
		}
	}
}
#endif /* CONFIG_NET_ROUTE_MCAST */

static int cmd_net_ip6_route_add(const struct shell *sh, size_t argc, char *argv[])
{
#if defined(CONFIG_NET_NATIVE_IPV6) && (CONFIG_NET_ROUTE)
	struct net_if *iface = NULL;
	int idx;
	struct net_route_entry *route;
	struct in6_addr gw = {0};
	struct in6_addr prefix = {0};

	if (argc != 4) {
		PR_ERROR("Correct usage: net route add <index> "
				 "<destination> <gateway>\n");
		return -EINVAL;
	}

	idx = get_iface_idx(sh, argv[1]);
	if (idx < 0) {
		return -ENOEXEC;
	}

	iface = net_if_get_by_index(idx);
	if (!iface) {
		PR_WARNING("No such interface in index %d\n", idx);
		return -ENOEXEC;
	}

	if (net_addr_pton(AF_INET6, argv[2], &prefix)) {
		PR_ERROR("Invalid address: %s\n", argv[2]);
		return -EINVAL;
	}

	if (net_addr_pton(AF_INET6, argv[3], &gw)) {
		PR_ERROR("Invalid gateway: %s\n", argv[3]);
		return -EINVAL;
	}

	route = net_route_add(iface, &prefix, NET_IPV6_DEFAULT_PREFIX_LEN,
				&gw, NET_IPV6_ND_INFINITE_LIFETIME,
				NET_ROUTE_PREFERENCE_MEDIUM);
	if (route == NULL) {
		PR_ERROR("Failed to add route\n");
		return -ENOEXEC;
	}

#else /* CONFIG_NET_NATIVE_IPV6 && CONFIG_NET_ROUTE */
	PR_INFO("Set %s and %s to enable native %s support."
			" And enable CONFIG_NET_ROUTE.\n",
			"CONFIG_NET_NATIVE", "CONFIG_NET_IPV6", "IPv6");
#endif /* CONFIG_NET_NATIVE_IPV6 && CONFIG_NET_ROUTE */
	return 0;
}

static int cmd_net_ip6_route_del(const struct shell *sh, size_t argc, char *argv[])
{
#if defined(CONFIG_NET_NATIVE_IPV6) && (CONFIG_NET_ROUTE)
	struct net_if *iface = NULL;
	int idx;
	struct net_route_entry *route;
	struct in6_addr prefix = { 0 };

	if (argc != 3) {
		PR_ERROR("Correct usage: net route del <index> <destination>\n");
		return -EINVAL;
	}
	idx = get_iface_idx(sh, argv[1]);
	if (idx < 0) {
		return -ENOEXEC;
	}

	iface = net_if_get_by_index(idx);
	if (!iface) {
		PR_WARNING("No such interface in index %d\n", idx);
		return -ENOEXEC;
	}

	if (net_addr_pton(AF_INET6, argv[2], &prefix)) {
		PR_ERROR("Invalid address: %s\n", argv[2]);
		return -EINVAL;
	}

	route = net_route_lookup(iface, &prefix);
	if (route) {
		net_route_del(route);
	}
#else /* CONFIG_NET_NATIVE_IPV6 && CONFIG_NET_ROUTE */
	PR_INFO("Set %s and %s to enable native %s support."
			" And enable CONFIG_NET_ROUTE\n",
			"CONFIG_NET_NATIVE", "CONFIG_NET_IPV6", "IPv6");
#endif /* CONFIG_NET_NATIVE_IPV6 && CONFIG_NET_ROUTE */
	return 0;
}

static int cmd_net_route(const struct shell *sh, size_t argc, char *argv[])
{
	ARG_UNUSED(argc);
	ARG_UNUSED(argv);

#if defined(CONFIG_NET_NATIVE)
#if defined(CONFIG_NET_ROUTE) || defined(CONFIG_NET_ROUTE_MCAST)
	struct net_shell_user_data user_data;
#endif

#if defined(CONFIG_NET_ROUTE) || defined(CONFIG_NET_ROUTE_MCAST)
	user_data.sh = sh;
#endif

#if defined(CONFIG_NET_ROUTE)
	net_if_foreach(iface_per_route_cb, &user_data);
#else
	PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_ROUTE",
		"network route");
#endif

#if defined(CONFIG_NET_ROUTE_MCAST)
	net_route_mcast_foreach(route_mcast_cb, NULL, &user_data);
#endif
#endif
	return 0;
}

SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_route,
	SHELL_CMD(add, NULL,
		  "'net route add <index> <destination> <gateway>'"
		  " adds the route to the destination.",
		  cmd_net_ip6_route_add),
	SHELL_CMD(del, NULL,
		  "'net route del <index> <destination>'"
		  " deletes the route to the destination.",
		  cmd_net_ip6_route_del),
	SHELL_SUBCMD_SET_END
);

SHELL_SUBCMD_ADD((net), route, &net_cmd_route,
		 "Show network route.",
		 cmd_net_route, 1, 0);
