/* SPDX-License-Identifier: LGPL-2.1-only */
/*
 * Copyright (c) 2008-2009 Thomas Graf <tgraf@suug.ch>
 */

/**
 * @ingroup cli
 * @defgroup cli_route Routing
 *
 * @{
 */

#include "nl-default.h"

#include <netlink/cli/utils.h>
#include <netlink/cli/route.h>

struct rtnl_route *nl_cli_route_alloc(void)
{
	struct rtnl_route *route;

	route = rtnl_route_alloc();
	if (!route)
		nl_cli_fatal(ENOMEM, "Unable to allocate route object");

	return route;
}

struct nl_cache *nl_cli_route_alloc_cache(struct nl_sock *sk, int flags)
{
	struct nl_cache *cache;
	int err;

	if ((err = rtnl_route_alloc_cache(sk, AF_UNSPEC, flags, &cache)) < 0)
		nl_cli_fatal(err, "Unable to allocate route cache: %s\n",
			     nl_geterror(err));

	nl_cache_mngt_provide(cache);

	return cache;
}

void nl_cli_route_parse_family(struct rtnl_route *route, char *arg)
{
	int family;

	if ((family = nl_str2af(arg)) != AF_UNSPEC)
		rtnl_route_set_family(route, family);
}

void nl_cli_route_parse_dst(struct rtnl_route *route, char *arg)
{
	struct nl_addr *addr;
	int err;

	addr = nl_cli_addr_parse(arg, rtnl_route_get_family(route));
	if ((err = rtnl_route_set_dst(route, addr)) < 0)
		nl_cli_fatal(err, "Unable to set destination address: %s",
		      nl_geterror(err));

	nl_addr_put(addr);
}

void nl_cli_route_parse_src(struct rtnl_route *route, char *arg)
{
	struct nl_addr *addr;
	int err;

	addr = nl_cli_addr_parse(arg, rtnl_route_get_family(route));
	if ((err = rtnl_route_set_src(route, addr)) < 0)
		nl_cli_fatal(err, "Unable to set source address: %s",
		      nl_geterror(err));

	nl_addr_put(addr);
}

void nl_cli_route_parse_pref_src(struct rtnl_route *route, char *arg)
{
	struct nl_addr *addr;
	int err;

	addr = nl_cli_addr_parse(arg, rtnl_route_get_family(route));
	if ((err = rtnl_route_set_pref_src(route, addr)) < 0)
		nl_cli_fatal(err, "Unable to set preferred source address: %s",
		      nl_geterror(err));

	nl_addr_put(addr);
}

void nl_cli_route_parse_metric(struct rtnl_route *route, char *subopts)
{
	/* strict equal order to RTAX_* */
	static char *const tokens[] = {
		"unspec",
		"lock",
		"mtu",
		"window",
		"rtt",
		"rttvar",
		"sstresh",
		"cwnd",
		"advmss",
		"reordering",
		"hoplimit",
		"initcwnd",
		"features",
		NULL,
	};
	unsigned long lval;
	char *arg, *endptr;

	while (*subopts != '\0') {
		int ret = getsubopt(&subopts, tokens, &arg);
		if (ret == -1)
			nl_cli_fatal(EINVAL, "Unknown metric token \"%s\"", arg);

		if (ret == 0)
			nl_cli_fatal(EINVAL, "Invalid metric \"%s\"", tokens[ret]);

		if (arg == NULL)
			nl_cli_fatal(EINVAL, "Metric \"%s\", no value given", tokens[ret]);

		lval = strtoul(arg, &endptr, 0);
		if (endptr == arg)
			nl_cli_fatal(EINVAL, "Metric \"%s\", value not numeric", tokens[ret]);

		if ((ret = rtnl_route_set_metric(route, ret, lval)) < 0)
			nl_cli_fatal(ret, "Unable to set metric: %s",
			      nl_geterror(ret));
	}
}

void nl_cli_route_parse_nexthop(struct rtnl_route *route, char *subopts,
		   struct nl_cache *link_cache)
{
	enum {
		NH_DEV,
		NH_VIA,
		NH_WEIGHT,
		NH_AS,
	};
	static char *const tokens[] = {
		"dev",
		"via",
		"weight",
		"as",
		NULL,
	};
	struct rtnl_nexthop *nh;
	unsigned long lval;
	struct nl_addr *addr;
	int ival;
	char *arg, *endptr;

	if (!(nh = rtnl_route_nh_alloc()))
		nl_cli_fatal(ENOMEM, "Out of memory");

	while (*subopts != '\0') {
		int ret = getsubopt(&subopts, tokens, &arg);
		if (ret == -1)
			nl_cli_fatal(EINVAL, "Unknown nexthop token \"%s\"", arg);

		if (arg == NULL)
			nl_cli_fatal(EINVAL, "Missing argument to option \"%s\"\n",
				tokens[ret]);

		switch (ret) {
		case NH_DEV:
			if (!(ival = rtnl_link_name2i(link_cache, arg)))
				nl_cli_fatal(ENOENT,"Link \"%s\" does not exist", arg);

			rtnl_route_nh_set_ifindex(nh, ival);
			break;

		case NH_VIA:
			if (rtnl_route_get_family(route) == AF_MPLS) {
				addr = nl_cli_addr_parse(arg, 0);
				rtnl_route_nh_set_via(nh, addr);
			} else {
				addr = nl_cli_addr_parse(arg,rtnl_route_get_family(route));
				rtnl_route_nh_set_gateway(nh, addr);
			}
			nl_addr_put(addr);
			break;

		case NH_AS:
			addr = nl_cli_addr_parse(arg,
						 rtnl_route_get_family(route));
			rtnl_route_nh_set_newdst(nh, addr);
			nl_addr_put(addr);
			break;

		case NH_WEIGHT:
			lval = strtoul(arg, &endptr, 0);
			if (endptr == arg)
				nl_cli_fatal(EINVAL,
					     "Invalid weight \"%s\", not numeric",
					     arg);
			rtnl_route_nh_set_weight(nh, lval);
			break;
		}
	}

	rtnl_route_add_nexthop(route, nh);
}

void nl_cli_route_parse_table(struct rtnl_route *route, char *arg)
{
	unsigned long lval;
	char *endptr;
	int table;

	lval = strtoul(arg, &endptr, 0);
	if (endptr == arg) {
		if ((table = rtnl_route_str2table(arg)) < 0)
			nl_cli_fatal(EINVAL, "Unknown table name \"%s\"", arg);
	}
	else {
		table = lval;
	}

	rtnl_route_set_table(route, table);
}

void nl_cli_route_parse_prio(struct rtnl_route *route, char *arg)
{
	unsigned long lval;
	char *endptr;

	lval = strtoul(arg, &endptr, 0);
	if (endptr == arg)
		nl_cli_fatal(EINVAL, "Invalid priority value, not numeric");
	rtnl_route_set_priority(route, lval);
}

void nl_cli_route_parse_scope(struct rtnl_route *route, char *arg)
{
	int ival;

	if ((ival = rtnl_str2scope(arg)) < 0)
		nl_cli_fatal(EINVAL, "Unknown routing scope \"%s\"", arg);

	rtnl_route_set_scope(route, ival);
}

void nl_cli_route_parse_protocol(struct rtnl_route *route, char *arg)
{
	unsigned long lval;
	char *endptr;
	int proto;

	lval = strtoul(arg, &endptr, 0);
	if (endptr == arg) {
		if ((proto = rtnl_route_str2proto(arg)) < 0)
			nl_cli_fatal(EINVAL,
				     "Unknown routing protocol name \"%s\"",
				     arg);
	}
	else {
		proto = lval;
	}

	rtnl_route_set_protocol(route, proto);
}

void nl_cli_route_parse_type(struct rtnl_route *route, char *arg)
{
	int ival;

	if ((ival = nl_str2rtntype(arg)) < 0)
		nl_cli_fatal(EINVAL, "Unknown routing type \"%s\"", arg);

	if ((ival = rtnl_route_set_type(route, ival)) < 0)
		nl_cli_fatal(ival, "Unable to set routing type: %s",
		      nl_geterror(ival));
}

void nl_cli_route_parse_iif(struct rtnl_route *route, char *arg, struct nl_cache *link_cache)
{
	int ival;

	if (!(ival = rtnl_link_name2i(link_cache, arg)))
		nl_cli_fatal(ENOENT, "Link \"%s\" does not exist", arg);

	rtnl_route_set_iif(route, ival);
}

/** @} */
