/*
 * m_action.c		Action Management
 *
 *		This program is free software; you can distribute 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:  J Hadi Salim (hadi@cyberus.ca)
 *
 * TODO:
 * - parse to be passed a filedescriptor for logging purposes
 *
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <dlfcn.h>

#include "utils.h"
#include "tc_common.h"
#include "tc_util.h"

static struct action_util *action_list;
#ifdef CONFIG_GACT
int gact_ld; /* f*ckin backward compatibility */
#endif
int tab_flush;

static void act_usage(void)
{
	/*XXX: In the near future add a action->print_help to improve
	 * usability
	 * This would mean new tc will not be backward compatible
	 * with any action .so from the old days. But if someone really
	 * does that, they would know how to fix this ..
	 *
	*/
	fprintf(stderr, "usage: tc actions <ACTSPECOP>*\n");
	fprintf(stderr,
		"Where: \tACTSPECOP := ACR | GD | FL\n"
			"\tACR := add | change | replace <ACTSPEC>*\n"
			"\tGD := get | delete | <ACTISPEC>*\n"
			"\tFL := ls | list | flush | <ACTNAMESPEC>\n"
			"\tACTNAMESPEC :=  action <ACTNAME>\n"
			"\tACTISPEC := <ACTNAMESPEC> <INDEXSPEC>\n"
			"\tACTSPEC := action <ACTDETAIL> [INDEXSPEC]\n"
			"\tINDEXSPEC := index <32 bit indexvalue>\n"
			"\tACTDETAIL := <ACTNAME> <ACTPARAMS>\n"
			"\t\tExample ACTNAME is gact, mirred, bpf, etc\n"
			"\t\tEach action has its own parameters (ACTPARAMS)\n"
			"\n");

	exit(-1);
}

static int print_noaopt(struct action_util *au, FILE *f, struct rtattr *opt)
{
	if (opt && RTA_PAYLOAD(opt))
		fprintf(f, "[Unknown action, optlen=%u] ",
			(unsigned int) RTA_PAYLOAD(opt));
	return 0;
}

static int parse_noaopt(struct action_util *au, int *argc_p, char ***argv_p, int code, struct nlmsghdr *n)
{
	int argc = *argc_p;
	char **argv = *argv_p;

	if (argc) {
		fprintf(stderr, "Unknown action \"%s\", hence option \"%s\" is unparsable\n", au->id, *argv);
	} else {
		fprintf(stderr, "Unknown action \"%s\"\n", au->id);
	}
	return -1;
}

static struct action_util *get_action_kind(char *str)
{
	static void *aBODY;
	void *dlh;
	char buf[256];
	struct action_util *a;
#ifdef CONFIG_GACT
	int looked4gact = 0;
restart_s:
#endif
	for (a = action_list; a; a = a->next) {
		if (strcmp(a->id, str) == 0)
			return a;
	}

	snprintf(buf, sizeof(buf), "%s/m_%s.so", get_tc_lib(), str);
	dlh = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL);
	if (dlh == NULL) {
		dlh = aBODY;
		if (dlh == NULL) {
			dlh = aBODY = dlopen(NULL, RTLD_LAZY);
			if (dlh == NULL)
				goto noexist;
		}
	}

	snprintf(buf, sizeof(buf), "%s_action_util", str);
	a = dlsym(dlh, buf);
	if (a == NULL)
		goto noexist;

reg:
	a->next = action_list;
	action_list = a;
	return a;

noexist:
#ifdef CONFIG_GACT
	if (!looked4gact) {
		looked4gact = 1;
		strcpy(str, "gact");
		goto restart_s;
	}
#endif
	a = malloc(sizeof(*a));
	if (a) {
		memset(a, 0, sizeof(*a));
		strncpy(a->id, "noact", 15);
		a->parse_aopt = parse_noaopt;
		a->print_aopt = print_noaopt;
		goto reg;
	}
	return a;
}

static int
new_cmd(char **argv)
{
	if ((matches(*argv, "change") == 0) ||
		(matches(*argv, "replace") == 0) ||
		(matches(*argv, "delete") == 0) ||
		(matches(*argv, "get") == 0) ||
		(matches(*argv, "add") == 0))
			return 1;

	return 0;

}

int
parse_action(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
{
	int argc = *argc_p;
	char **argv = *argv_p;
	struct rtattr *tail, *tail2;
	char k[16];
	int ok = 0;
	int eap = 0; /* expect action parameters */

	int ret = 0;
	int prio = 0;

	if (argc <= 0)
		return -1;

	tail = tail2 = NLMSG_TAIL(n);

	addattr_l(n, MAX_MSG, tca_id, NULL, 0);

	while (argc > 0) {

		memset(k, 0, sizeof(k));

		if (strcmp(*argv, "action") == 0) {
			argc--;
			argv++;
			eap = 1;
#ifdef CONFIG_GACT
			if (!gact_ld) {
				get_action_kind("gact");
			}
#endif
			continue;
		} else if (strcmp(*argv, "flowid") == 0) {
			break;
		} else if (strcmp(*argv, "classid") == 0) {
			break;
		} else if (strcmp(*argv, "help") == 0) {
			return -1;
		} else if (new_cmd(argv)) {
			goto done0;
		} else {
			struct action_util *a = NULL;

			strncpy(k, *argv, sizeof(k) - 1);
			eap = 0;
			if (argc > 0) {
				a = get_action_kind(k);
			} else {
done0:
				if (ok)
					break;
				else
					goto done;
			}

			if (a == NULL) {
				goto bad_val;
			}

			tail = NLMSG_TAIL(n);
			addattr_l(n, MAX_MSG, ++prio, NULL, 0);
			addattr_l(n, MAX_MSG, TCA_ACT_KIND, k, strlen(k) + 1);

			ret = a->parse_aopt(a, &argc, &argv, TCA_ACT_OPTIONS, n);

			if (ret < 0) {
				fprintf(stderr, "bad action parsing\n");
				goto bad_val;
			}
			tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
			ok++;
		}

	}

	if (eap > 0) {
		fprintf(stderr, "bad action empty %d\n", eap);
		goto bad_val;
	}

	tail2->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail2;

done:
	*argc_p = argc;
	*argv_p = argv;
	return 0;
bad_val:
	/* no need to undo things, returning from here should
	 * cause enough pain */
	fprintf(stderr, "parse_action: bad value (%d:%s)!\n", argc, *argv);
	return -1;
}

static int
tc_print_one_action(FILE *f, struct rtattr *arg)
{

	struct rtattr *tb[TCA_ACT_MAX + 1];
	int err = 0;
	struct action_util *a = NULL;

	if (arg == NULL)
		return -1;

	parse_rtattr_nested(tb, TCA_ACT_MAX, arg);

	if (tb[TCA_ACT_KIND] == NULL) {
		fprintf(stderr, "NULL Action!\n");
		return -1;
	}


	a = get_action_kind(RTA_DATA(tb[TCA_ACT_KIND]));
	if (a == NULL)
		return err;

	err = a->print_aopt(a, f, tb[TCA_ACT_OPTIONS]);

	if (err < 0)
		return err;

	if (show_stats && tb[TCA_ACT_STATS]) {
		fprintf(f, "\tAction statistics:\n");
		print_tcstats2_attr(f, tb[TCA_ACT_STATS], "\t", NULL);
		fprintf(f, "\n");
	}

	return 0;
}

static int
tc_print_action_flush(FILE *f, const struct rtattr *arg)
{

	struct rtattr *tb[TCA_MAX + 1];
	int err = 0;
	struct action_util *a = NULL;
	__u32 *delete_count = 0;

	parse_rtattr_nested(tb, TCA_MAX, arg);

	if (tb[TCA_KIND] == NULL) {
		fprintf(stderr, "NULL Action!\n");
		return -1;
	}

	a = get_action_kind(RTA_DATA(tb[TCA_KIND]));
	if (a == NULL)
		return err;

	delete_count = RTA_DATA(tb[TCA_FCNT]);
	fprintf(f, " %s (%d entries)\n", a->id, *delete_count);
	tab_flush = 0;
	return 0;
}

int
tc_print_action(FILE *f, const struct rtattr *arg)
{

	int i;
	struct rtattr *tb[TCA_ACT_MAX_PRIO + 1];

	if (arg == NULL)
		return 0;

	parse_rtattr_nested(tb, TCA_ACT_MAX_PRIO, arg);

	if (tab_flush && NULL != tb[0]  && NULL == tb[1])
		return tc_print_action_flush(f, tb[0]);

	for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
		if (tb[i]) {
			fprintf(f, "\n\taction order %d: ", i);
			if (tc_print_one_action(f, tb[i]) < 0) {
				fprintf(f, "Error printing action\n");
			}
		}

	}

	return 0;
}

int print_action(const struct sockaddr_nl *who,
			   struct nlmsghdr *n,
			   void *arg)
{
	FILE *fp = (FILE *)arg;
	struct tcamsg *t = NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr *tb[TCAA_MAX+1];

	len -= NLMSG_LENGTH(sizeof(*t));

	if (len < 0) {
		fprintf(stderr, "Wrong len %d\n", len);
		return -1;
	}

	parse_rtattr(tb, TCAA_MAX, TA_RTA(t), len);

	if (tb[TCA_ACT_TAB] == NULL) {
		if (n->nlmsg_type != RTM_GETACTION)
			fprintf(stderr, "print_action: NULL kind\n");
		return -1;
	}

	if (n->nlmsg_type == RTM_DELACTION) {
		if (n->nlmsg_flags & NLM_F_ROOT) {
			fprintf(fp, "Flushed table ");
			tab_flush = 1;
		} else {
			fprintf(fp, "deleted action ");
		}
	}

	if (n->nlmsg_type == RTM_NEWACTION)
		fprintf(fp, "Added action ");
	tc_print_action(fp, tb[TCA_ACT_TAB]);

	return 0;
}

static int tc_action_gd(int cmd, unsigned int flags, int *argc_p, char ***argv_p)
{
	char k[16];
	struct action_util *a = NULL;
	int argc = *argc_p;
	char **argv = *argv_p;
	int prio = 0;
	int ret = 0;
	__u32 i;
	struct rtattr *tail;
	struct rtattr *tail2;
	struct nlmsghdr *ans = NULL;

	struct {
		struct nlmsghdr         n;
		struct tcamsg           t;
		char                    buf[MAX_MSG];
	} req = {
		.n = {
			.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcamsg)),
			.nlmsg_flags = NLM_F_REQUEST | flags,
			.nlmsg_type = cmd,
		},
		.t.tca_family = AF_UNSPEC,
		.buf = { 0 }
	};

	argc -= 1;
	argv += 1;


	tail = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, MAX_MSG, TCA_ACT_TAB, NULL, 0);

	while (argc > 0) {
		if (strcmp(*argv, "action") == 0) {
			argc--;
			argv++;
			continue;
		} else if (strcmp(*argv, "help") == 0) {
			return -1;
		}

		strncpy(k, *argv, sizeof(k) - 1);
		a = get_action_kind(k);
		if (a == NULL) {
			fprintf(stderr, "Error: non existent action: %s\n", k);
			ret = -1;
			goto bad_val;
		}
		if (strcmp(a->id, k) != 0) {
			fprintf(stderr, "Error: non existent action: %s\n", k);
			ret = -1;
			goto bad_val;
		}

		argc -= 1;
		argv += 1;
		if (argc <= 0) {
			fprintf(stderr, "Error: no index specified action: %s\n", k);
			ret = -1;
			goto bad_val;
		}

		if (matches(*argv, "index") == 0) {
			NEXT_ARG();
			if (get_u32(&i, *argv, 10)) {
				fprintf(stderr, "Illegal \"index\"\n");
				ret = -1;
				goto bad_val;
			}
			argc -= 1;
			argv += 1;
		} else {
			fprintf(stderr, "Error: no index specified action: %s\n", k);
			ret = -1;
			goto bad_val;
		}

		tail2 = NLMSG_TAIL(&req.n);
		addattr_l(&req.n, MAX_MSG, ++prio, NULL, 0);
		addattr_l(&req.n, MAX_MSG, TCA_ACT_KIND, k, strlen(k) + 1);
		addattr32(&req.n, MAX_MSG, TCA_ACT_INDEX, i);
		tail2->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail2;

	}

	tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail;

	req.n.nlmsg_seq = rth.dump = ++rth.seq;
	if (cmd == RTM_GETACTION)
		ans = &req.n;

	if (rtnl_talk(&rth, &req.n, ans, MAX_MSG) < 0) {
		fprintf(stderr, "We have an error talking to the kernel\n");
		return 1;
	}

	if (ans && print_action(NULL, &req.n, (void *)stdout) < 0) {
		fprintf(stderr, "Dump terminated\n");
		return 1;
	}

	*argc_p = argc;
	*argv_p = argv;
bad_val:
	return ret;
}

static int tc_action_modify(int cmd, unsigned int flags, int *argc_p, char ***argv_p)
{
	int argc = *argc_p;
	char **argv = *argv_p;
	int ret = 0;

	struct rtattr *tail;
	struct {
		struct nlmsghdr         n;
		struct tcamsg           t;
		char                    buf[MAX_MSG];
	} req = {
		.n = {
			.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcamsg)),
			.nlmsg_flags = NLM_F_REQUEST | flags,
			.nlmsg_type = cmd,
		},
		.t.tca_family = AF_UNSPEC,
		.buf = { 0 }
	};

	tail = NLMSG_TAIL(&req.n);
	argc -= 1;
	argv += 1;
	if (parse_action(&argc, &argv, TCA_ACT_TAB, &req.n)) {
		fprintf(stderr, "Illegal \"action\"\n");
		return -1;
	}
	tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail;

	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) {
		fprintf(stderr, "We have an error talking to the kernel\n");
		ret = -1;
	}

	*argc_p = argc;
	*argv_p = argv;

	return ret;
}

static int tc_act_list_or_flush(int argc, char **argv, int event)
{
	int ret = 0, prio = 0, msg_size = 0;
	char k[16];
	struct rtattr *tail, *tail2;
	struct action_util *a = NULL;
	struct {
		struct nlmsghdr         n;
		struct tcamsg           t;
		char                    buf[MAX_MSG];
	} req = {
		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcamsg)),
		.t.tca_family = AF_UNSPEC,
		.buf = { 0 }
	};

	tail = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, MAX_MSG, TCA_ACT_TAB, NULL, 0);
	tail2 = NLMSG_TAIL(&req.n);

	strncpy(k, *argv, sizeof(k) - 1);
#ifdef CONFIG_GACT
	if (!gact_ld) {
		get_action_kind("gact");
	}
#endif
	a = get_action_kind(k);
	if (a == NULL) {
		fprintf(stderr, "bad action %s\n", k);
		goto bad_val;
	}
	if (strcmp(a->id, k) != 0) {
		fprintf(stderr, "bad action %s\n", k);
		goto bad_val;
	}
	strncpy(k, *argv, sizeof(k) - 1);

	addattr_l(&req.n, MAX_MSG, ++prio, NULL, 0);
	addattr_l(&req.n, MAX_MSG, TCA_ACT_KIND, k, strlen(k) + 1);
	tail2->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail2;
	tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail;

	msg_size = NLMSG_ALIGN(req.n.nlmsg_len) - NLMSG_ALIGN(sizeof(struct nlmsghdr));

	if (event == RTM_GETACTION) {
		if (rtnl_dump_request(&rth, event, (void *)&req.t, msg_size) < 0) {
			perror("Cannot send dump request");
			return 1;
		}
		ret = rtnl_dump_filter(&rth, print_action, stdout);
	}

	if (event == RTM_DELACTION) {
		req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len);
		req.n.nlmsg_type = RTM_DELACTION;
		req.n.nlmsg_flags |= NLM_F_ROOT;
		req.n.nlmsg_flags |= NLM_F_REQUEST;
		if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) {
			fprintf(stderr, "We have an error flushing\n");
			return 1;
		}

	}

bad_val:

	return ret;
}

int do_action(int argc, char **argv)
{

	int ret = 0;

	while (argc > 0) {

		if (matches(*argv, "add") == 0) {
			ret =  tc_action_modify(RTM_NEWACTION, NLM_F_EXCL|NLM_F_CREATE, &argc, &argv);
		} else if (matches(*argv, "change") == 0 ||
			  matches(*argv, "replace") == 0) {
			ret = tc_action_modify(RTM_NEWACTION, NLM_F_CREATE|NLM_F_REPLACE, &argc, &argv);
		} else if (matches(*argv, "delete") == 0) {
			argc -= 1;
			argv += 1;
			ret = tc_action_gd(RTM_DELACTION, 0,  &argc, &argv);
		} else if (matches(*argv, "get") == 0) {
			argc -= 1;
			argv += 1;
			ret = tc_action_gd(RTM_GETACTION, 0,  &argc, &argv);
		} else if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
						|| matches(*argv, "lst") == 0) {
			if (argc <= 2) {
				act_usage();
				return -1;
			}
			return tc_act_list_or_flush(argc-2, argv+2, RTM_GETACTION);
		} else if (matches(*argv, "flush") == 0) {
			if (argc <= 2) {
				act_usage();
				return -1;
			}
			return tc_act_list_or_flush(argc-2, argv+2, RTM_DELACTION);
		} else if (matches(*argv, "help") == 0) {
			act_usage();
			return -1;
		} else {

			ret = -1;
		}

		if (ret < 0) {
			fprintf(stderr, "Command \"%s\" is unknown, try \"tc actions help\".\n", *argv);
			return -1;
		}
	}

	return 0;
}
