/*
 * iptoken.c    "ip token"
 *
 *              This program is free software; you can redistribute it and/or
 *              modify it under the terms of the GNU General Public License
 *              as published by the Free Software Foundation; either version
 *              2 of the License, or (at your option) any later version.
 *
 * Authors:     Daniel Borkmann, <borkmann@redhat.com>
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <linux/types.h>
#include <linux/if.h>

#include "rt_names.h"
#include "utils.h"
#include "ip_common.h"

extern struct rtnl_handle rth;

struct rtnl_dump_args {
	FILE *fp;
	int ifindex;
};

static void usage(void) __attribute__((noreturn));

static void usage(void)
{
	fprintf(stderr, "Usage: ip token [ list | set | get ] [ TOKEN ] [ dev DEV ]\n");
	exit(-1);
}

static int print_token(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
	struct rtnl_dump_args *args = arg;
	FILE *fp = args->fp;
	int ifindex = args->ifindex;
	struct ifinfomsg *ifi = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr *tb[IFLA_MAX + 1];
	struct rtattr *ltb[IFLA_INET6_MAX + 1];
	char abuf[256];

	if (n->nlmsg_type != RTM_NEWLINK)
		return -1;

	len -= NLMSG_LENGTH(sizeof(*ifi));
	if (len < 0)
		return -1;

	if (ifi->ifi_family != AF_INET6)
		return -1;
	if (ifi->ifi_index == 0)
		return -1;
	if (ifindex > 0 && ifi->ifi_index != ifindex)
		return 0;
	if (ifi->ifi_flags & (IFF_LOOPBACK | IFF_NOARP))
		return 0;

	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
	if (!tb[IFLA_PROTINFO])
		return -1;

	parse_rtattr_nested(ltb, IFLA_INET6_MAX, tb[IFLA_PROTINFO]);
	if (!ltb[IFLA_INET6_TOKEN]) {
		fprintf(stderr, "Seems there's no support for IPv6 token!\n");
		return -1;
	}

	fprintf(fp, "token %s ",
		format_host(ifi->ifi_family,
			    RTA_PAYLOAD(ltb[IFLA_INET6_TOKEN]),
			    RTA_DATA(ltb[IFLA_INET6_TOKEN]),
			    abuf, sizeof(abuf)));
	fprintf(fp, "dev %s ", ll_index_to_name(ifi->ifi_index));
	fprintf(fp, "\n");
	fflush(fp);

	return 0;
}

static int iptoken_list(int argc, char **argv)
{
	int af = AF_INET6;
	struct rtnl_dump_args da;

	memset(&da, 0, sizeof(da));
	da.fp = stdout;

	while (argc > 0) {
		if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			if ((da.ifindex = ll_name_to_index(*argv)) == 0)
				invarg("dev is invalid\n", *argv);
			break;
		}
		argc--; argv++;
	}

	if (rtnl_wilddump_request(&rth, af, RTM_GETLINK) < 0) {
		perror("Cannot send dump request");
		return -1;
	}

	if (rtnl_dump_filter(&rth, print_token, &da) < 0) {
		fprintf(stderr, "Dump terminated\n");
		return -1;
	}

	return 0;
}

static int iptoken_set(int argc, char **argv)
{
	struct {
		struct nlmsghdr n;
		struct ifinfomsg ifi;
		char buf[512];
	} req;
	struct rtattr *afs, *afs6;
	bool have_token = false, have_dev = false;
	inet_prefix addr;

	memset(&addr, 0, sizeof(addr));
	memset(&req, 0, sizeof(req));

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
	req.n.nlmsg_flags = NLM_F_REQUEST;
	req.n.nlmsg_type = RTM_SETLINK;
	req.ifi.ifi_family = AF_INET6;

	while (argc > 0) {
		if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			if (!have_dev) {
				if ((req.ifi.ifi_index =
				     ll_name_to_index(*argv)) == 0)
					invarg("dev is invalid\n", *argv);
				have_dev = true;
			}
		} else {
			if (matches(*argv, "help") == 0)
				usage();
			if (!have_token) {
				afs = addattr_nest(&req.n, sizeof(req), IFLA_AF_SPEC);
				afs6 = addattr_nest(&req.n, sizeof(req), AF_INET6);
				get_prefix(&addr, *argv, req.ifi.ifi_family);
				addattr_l(&req.n, sizeof(req), IFLA_INET6_TOKEN,
					  &addr.data, addr.bytelen);
				addattr_nest_end(&req.n, afs6);
				addattr_nest_end(&req.n, afs);
				have_token = true;
			}
		}
		argc--; argv++;
	}

	if (!have_token) {
		fprintf(stderr, "Not enough information: token "
			"is required.\n");
		return -1;
	}
	if (!have_dev) {
		fprintf(stderr, "Not enough information: \"dev\" "
			"argument is required.\n");
		return -1;
	}

	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
		return -2;

	return 0;
}

int do_iptoken(int argc, char **argv)
{
	ll_init_map(&rth);

	if (argc < 1) {
		return iptoken_list(0, NULL);
	} else if (matches(argv[0], "list") == 0 ||
		   matches(argv[0], "lst") == 0 ||
		   matches(argv[0], "show") == 0) {
		return iptoken_list(argc - 1, argv + 1);
	} else if (matches(argv[0], "set") == 0 ||
		   matches(argv[0], "add") == 0) {
		return iptoken_set(argc - 1, argv + 1);
	} else if (matches(argv[0], "get") == 0) {
		return iptoken_list(argc - 1, argv + 1);
	} else if (matches(argv[0], "help") == 0)
		usage();

	fprintf(stderr, "Command \"%s\" is unknown, try \"ip token help\".\n", *argv);
	exit(-1);
}
