/* Shared library add-on to iptables to add devgroup matching support.
 *
 * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <xtables.h>
#include <linux/netfilter/xt_devgroup.h>

static void devgroup_help(void)
{
	printf(
"devgroup match options:\n"
"[!] --src-group value[/mask]	Match device group of incoming device\n"
"[!] --dst-group value[/mask]	Match device group of outgoing device\n"
		);
}

enum {
	O_SRC_GROUP = 0,
	O_DST_GROUP,
};

static const struct xt_option_entry devgroup_opts[] = {
	{.name = "src-group", .id = O_SRC_GROUP, .type = XTTYPE_STRING,
	 .flags = XTOPT_INVERT},
	{.name = "dst-group", .id = O_DST_GROUP, .type = XTTYPE_STRING,
	 .flags = XTOPT_INVERT},
	XTOPT_TABLEEND,
};

static const char f_devgroups[] = "/etc/iproute2/group";
/* array of devgroups from f_devgroups[] */
static struct xtables_lmap *devgroups;

static void devgroup_parse(struct xt_option_call *cb)
{
	struct xt_devgroup_info *info = cb->data;
	unsigned int group, mask;

	xtables_option_parse(cb);
	xtables_parse_val_mask(cb, &group, &mask, devgroups);

	switch (cb->entry->id) {
	case O_SRC_GROUP:
		info->src_group = group;
		info->src_mask  = mask;
		info->flags |= XT_DEVGROUP_MATCH_SRC;
		if (cb->invert)
			info->flags |= XT_DEVGROUP_INVERT_SRC;
		break;
	case O_DST_GROUP:
		info->dst_group = group;
		info->dst_mask  = mask;
		info->flags |= XT_DEVGROUP_MATCH_DST;
		if (cb->invert)
			info->flags |= XT_DEVGROUP_INVERT_DST;
		break;
	}
}

static void devgroup_show(const char *pfx, const struct xt_devgroup_info *info,
			  int numeric)
{
	if (info->flags & XT_DEVGROUP_MATCH_SRC) {
		if (info->flags & XT_DEVGROUP_INVERT_SRC)
			printf(" !");
		printf(" %ssrc-group", pfx);
		xtables_print_val_mask(info->src_group, info->src_mask,
				       numeric ? NULL : devgroups);
	}

	if (info->flags & XT_DEVGROUP_MATCH_DST) {
		if (info->flags & XT_DEVGROUP_INVERT_DST)
			printf(" !");
		printf(" %sdst-group", pfx);
		xtables_print_val_mask(info->dst_group, info->dst_mask,
				       numeric ? NULL : devgroups);
	}
}

static void devgroup_print(const void *ip, const struct xt_entry_match *match,
                        int numeric)
{
	const struct xt_devgroup_info *info = (const void *)match->data;

	devgroup_show("", info, numeric);
}

static void devgroup_save(const void *ip, const struct xt_entry_match *match)
{
	const struct xt_devgroup_info *info = (const void *)match->data;

	devgroup_show("--", info, 0);
}

static void devgroup_check(struct xt_fcheck_call *cb)
{
	if (cb->xflags == 0)
		xtables_error(PARAMETER_PROBLEM,
			      "devgroup match: You must specify either "
			      "'--src-group' or '--dst-group'");
}

static void
print_devgroup_xlate(unsigned int id, uint32_t op,  unsigned int mask,
		     struct xt_xlate *xl, int numeric)
{
	const char *name = NULL;

	if (mask != 0xffffffff)
		xt_xlate_add(xl, "and 0x%x %s 0x%x", mask,
			   op == XT_OP_EQ ? "==" : "!=", id);
	else {
		if (numeric == 0)
			name = xtables_lmap_id2name(devgroups, id);

		xt_xlate_add(xl, "%s", op == XT_OP_EQ ? "" : "!= ");
		if (name)
			xt_xlate_add(xl, "%s", name);
		else
			xt_xlate_add(xl, "0x%x", id);
	}
}

static void devgroup_show_xlate(const struct xt_devgroup_info *info,
				struct xt_xlate *xl, int numeric)
{
	enum xt_op op = XT_OP_EQ;
	char *space = "";

	if (info->flags & XT_DEVGROUP_MATCH_SRC) {
		if (info->flags & XT_DEVGROUP_INVERT_SRC)
			op = XT_OP_NEQ;
		xt_xlate_add(xl, "iifgroup ");
		print_devgroup_xlate(info->src_group, op,
				     info->src_mask, xl, numeric);
		space = " ";
	}

	if (info->flags & XT_DEVGROUP_MATCH_DST) {
		if (info->flags & XT_DEVGROUP_INVERT_DST)
			op = XT_OP_NEQ;
		xt_xlate_add(xl, "%soifgroup ", space);
		print_devgroup_xlate(info->dst_group, op,
				     info->dst_mask, xl, numeric);
	}
}

static int devgroup_xlate(struct xt_xlate *xl,
			  const struct xt_xlate_mt_params *params)
{
	const struct xt_devgroup_info *info = (const void *)params->match->data;

	devgroup_show_xlate(info, xl, 0);

	return 1;
}

static struct xtables_match devgroup_mt_reg = {
	.name		= "devgroup",
	.version	= XTABLES_VERSION,
	.family		= NFPROTO_UNSPEC,
	.size		= XT_ALIGN(sizeof(struct xt_devgroup_info)),
	.userspacesize	= XT_ALIGN(sizeof(struct xt_devgroup_info)),
	.help		= devgroup_help,
	.print		= devgroup_print,
	.save		= devgroup_save,
	.x6_parse	= devgroup_parse,
	.x6_fcheck	= devgroup_check,
	.x6_options	= devgroup_opts,
	.xlate		= devgroup_xlate,
};

void _init(void)
{
	devgroups = xtables_lmap_init(f_devgroups);
	if (devgroups == NULL && errno != ENOENT)
		fprintf(stderr, "Warning: %s: %s\n", f_devgroups,
			strerror(errno));

	xtables_register_match(&devgroup_mt_reg);
}
