Blame extensions/libxt_devgroup.c

Packit Service d1fe03
/* Shared library add-on to iptables to add devgroup matching support.
Packit Service d1fe03
 *
Packit Service d1fe03
 * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
Packit Service d1fe03
 */
Packit Service d1fe03
#include <stdio.h>
Packit Service d1fe03
#include <string.h>
Packit Service d1fe03
#include <stdlib.h>
Packit Service d1fe03
#include <errno.h>
Packit Service d1fe03
#include <xtables.h>
Packit Service d1fe03
#include <linux/netfilter/xt_devgroup.h>
Packit Service d1fe03
Packit Service d1fe03
static void devgroup_help(void)
Packit Service d1fe03
{
Packit Service d1fe03
	printf(
Packit Service d1fe03
"devgroup match options:\n"
Packit Service d1fe03
"[!] --src-group value[/mask]	Match device group of incoming device\n"
Packit Service d1fe03
"[!] --dst-group value[/mask]	Match device group of outgoing device\n"
Packit Service d1fe03
		);
Packit Service d1fe03
}
Packit Service d1fe03
Packit Service d1fe03
enum {
Packit Service d1fe03
	O_SRC_GROUP = 0,
Packit Service d1fe03
	O_DST_GROUP,
Packit Service d1fe03
};
Packit Service d1fe03
Packit Service d1fe03
static const struct xt_option_entry devgroup_opts[] = {
Packit Service d1fe03
	{.name = "src-group", .id = O_SRC_GROUP, .type = XTTYPE_STRING,
Packit Service d1fe03
	 .flags = XTOPT_INVERT},
Packit Service d1fe03
	{.name = "dst-group", .id = O_DST_GROUP, .type = XTTYPE_STRING,
Packit Service d1fe03
	 .flags = XTOPT_INVERT},
Packit Service d1fe03
	XTOPT_TABLEEND,
Packit Service d1fe03
};
Packit Service d1fe03
Packit Service d1fe03
static const char f_devgroups[] = "/etc/iproute2/group";
Packit Service d1fe03
/* array of devgroups from f_devgroups[] */
Packit Service d1fe03
static struct xtables_lmap *devgroups;
Packit Service d1fe03
Packit Service d1fe03
static void devgroup_parse(struct xt_option_call *cb)
Packit Service d1fe03
{
Packit Service d1fe03
	struct xt_devgroup_info *info = cb->data;
Packit Service d1fe03
	unsigned int group, mask;
Packit Service d1fe03
Packit Service d1fe03
	xtables_option_parse(cb);
Packit Service d1fe03
	xtables_parse_val_mask(cb, &group, &mask, devgroups);
Packit Service d1fe03
Packit Service d1fe03
	switch (cb->entry->id) {
Packit Service d1fe03
	case O_SRC_GROUP:
Packit Service d1fe03
		info->src_group = group;
Packit Service d1fe03
		info->src_mask  = mask;
Packit Service d1fe03
		info->flags |= XT_DEVGROUP_MATCH_SRC;
Packit Service d1fe03
		if (cb->invert)
Packit Service d1fe03
			info->flags |= XT_DEVGROUP_INVERT_SRC;
Packit Service d1fe03
		break;
Packit Service d1fe03
	case O_DST_GROUP:
Packit Service d1fe03
		info->dst_group = group;
Packit Service d1fe03
		info->dst_mask  = mask;
Packit Service d1fe03
		info->flags |= XT_DEVGROUP_MATCH_DST;
Packit Service d1fe03
		if (cb->invert)
Packit Service d1fe03
			info->flags |= XT_DEVGROUP_INVERT_DST;
Packit Service d1fe03
		break;
Packit Service d1fe03
	}
Packit Service d1fe03
}
Packit Service d1fe03
Packit Service d1fe03
static void devgroup_show(const char *pfx, const struct xt_devgroup_info *info,
Packit Service d1fe03
			  int numeric)
Packit Service d1fe03
{
Packit Service d1fe03
	if (info->flags & XT_DEVGROUP_MATCH_SRC) {
Packit Service d1fe03
		if (info->flags & XT_DEVGROUP_INVERT_SRC)
Packit Service d1fe03
			printf(" !");
Packit Service d1fe03
		printf(" %ssrc-group", pfx);
Packit Service d1fe03
		xtables_print_val_mask(info->src_group, info->src_mask,
Packit Service d1fe03
				       numeric ? NULL : devgroups);
Packit Service d1fe03
	}
Packit Service d1fe03
Packit Service d1fe03
	if (info->flags & XT_DEVGROUP_MATCH_DST) {
Packit Service d1fe03
		if (info->flags & XT_DEVGROUP_INVERT_DST)
Packit Service d1fe03
			printf(" !");
Packit Service d1fe03
		printf(" %sdst-group", pfx);
Packit Service d1fe03
		xtables_print_val_mask(info->dst_group, info->dst_mask,
Packit Service d1fe03
				       numeric ? NULL : devgroups);
Packit Service d1fe03
	}
Packit Service d1fe03
}
Packit Service d1fe03
Packit Service d1fe03
static void devgroup_print(const void *ip, const struct xt_entry_match *match,
Packit Service d1fe03
                        int numeric)
Packit Service d1fe03
{
Packit Service d1fe03
	const struct xt_devgroup_info *info = (const void *)match->data;
Packit Service d1fe03
Packit Service d1fe03
	devgroup_show("", info, numeric);
Packit Service d1fe03
}
Packit Service d1fe03
Packit Service d1fe03
static void devgroup_save(const void *ip, const struct xt_entry_match *match)
Packit Service d1fe03
{
Packit Service d1fe03
	const struct xt_devgroup_info *info = (const void *)match->data;
Packit Service d1fe03
Packit Service d1fe03
	devgroup_show("--", info, 0);
Packit Service d1fe03
}
Packit Service d1fe03
Packit Service d1fe03
static void devgroup_check(struct xt_fcheck_call *cb)
Packit Service d1fe03
{
Packit Service d1fe03
	if (cb->xflags == 0)
Packit Service d1fe03
		xtables_error(PARAMETER_PROBLEM,
Packit Service d1fe03
			      "devgroup match: You must specify either "
Packit Service d1fe03
			      "'--src-group' or '--dst-group'");
Packit Service d1fe03
}
Packit Service d1fe03
Packit Service d1fe03
static void
Packit Service d1fe03
print_devgroup_xlate(unsigned int id, uint32_t op,  unsigned int mask,
Packit Service d1fe03
		     struct xt_xlate *xl, int numeric)
Packit Service d1fe03
{
Packit Service d1fe03
	const char *name = NULL;
Packit Service d1fe03
Packit Service d1fe03
	if (mask != 0xffffffff)
Packit Service d1fe03
		xt_xlate_add(xl, "and 0x%x %s 0x%x", mask,
Packit Service d1fe03
			   op == XT_OP_EQ ? "==" : "!=", id);
Packit Service d1fe03
	else {
Packit Service d1fe03
		if (numeric == 0)
Packit Service d1fe03
			name = xtables_lmap_id2name(devgroups, id);
Packit Service d1fe03
Packit Service d1fe03
		xt_xlate_add(xl, "%s", op == XT_OP_EQ ? "" : "!= ");
Packit Service d1fe03
		if (name)
Packit Service d1fe03
			xt_xlate_add(xl, "%s", name);
Packit Service d1fe03
		else
Packit Service d1fe03
			xt_xlate_add(xl, "0x%x", id);
Packit Service d1fe03
	}
Packit Service d1fe03
}
Packit Service d1fe03
Packit Service d1fe03
static void devgroup_show_xlate(const struct xt_devgroup_info *info,
Packit Service d1fe03
				struct xt_xlate *xl, int numeric)
Packit Service d1fe03
{
Packit Service d1fe03
	enum xt_op op = XT_OP_EQ;
Packit Service d1fe03
	char *space = "";
Packit Service d1fe03
Packit Service d1fe03
	if (info->flags & XT_DEVGROUP_MATCH_SRC) {
Packit Service d1fe03
		if (info->flags & XT_DEVGROUP_INVERT_SRC)
Packit Service d1fe03
			op = XT_OP_NEQ;
Packit Service d1fe03
		xt_xlate_add(xl, "iifgroup ");
Packit Service d1fe03
		print_devgroup_xlate(info->src_group, op,
Packit Service d1fe03
				     info->src_mask, xl, numeric);
Packit Service d1fe03
		space = " ";
Packit Service d1fe03
	}
Packit Service d1fe03
Packit Service d1fe03
	if (info->flags & XT_DEVGROUP_MATCH_DST) {
Packit Service d1fe03
		if (info->flags & XT_DEVGROUP_INVERT_DST)
Packit Service d1fe03
			op = XT_OP_NEQ;
Packit Service d1fe03
		xt_xlate_add(xl, "%soifgroup ", space);
Packit Service d1fe03
		print_devgroup_xlate(info->dst_group, op,
Packit Service d1fe03
				     info->dst_mask, xl, numeric);
Packit Service d1fe03
	}
Packit Service d1fe03
}
Packit Service d1fe03
Packit Service d1fe03
static int devgroup_xlate(struct xt_xlate *xl,
Packit Service d1fe03
			  const struct xt_xlate_mt_params *params)
Packit Service d1fe03
{
Packit Service d1fe03
	const struct xt_devgroup_info *info = (const void *)params->match->data;
Packit Service d1fe03
Packit Service d1fe03
	devgroup_show_xlate(info, xl, 0);
Packit Service d1fe03
Packit Service d1fe03
	return 1;
Packit Service d1fe03
}
Packit Service d1fe03
Packit Service d1fe03
static struct xtables_match devgroup_mt_reg = {
Packit Service d1fe03
	.name		= "devgroup",
Packit Service d1fe03
	.version	= XTABLES_VERSION,
Packit Service d1fe03
	.family		= NFPROTO_UNSPEC,
Packit Service d1fe03
	.size		= XT_ALIGN(sizeof(struct xt_devgroup_info)),
Packit Service d1fe03
	.userspacesize	= XT_ALIGN(sizeof(struct xt_devgroup_info)),
Packit Service d1fe03
	.help		= devgroup_help,
Packit Service d1fe03
	.print		= devgroup_print,
Packit Service d1fe03
	.save		= devgroup_save,
Packit Service d1fe03
	.x6_parse	= devgroup_parse,
Packit Service d1fe03
	.x6_fcheck	= devgroup_check,
Packit Service d1fe03
	.x6_options	= devgroup_opts,
Packit Service d1fe03
	.xlate		= devgroup_xlate,
Packit Service d1fe03
};
Packit Service d1fe03
Packit Service d1fe03
void _init(void)
Packit Service d1fe03
{
Packit Service d1fe03
	devgroups = xtables_lmap_init(f_devgroups);
Packit Service d1fe03
	if (devgroups == NULL && errno != ENOENT)
Packit Service d1fe03
		fprintf(stderr, "Warning: %s: %s\n", f_devgroups,
Packit Service d1fe03
			strerror(errno));
Packit Service d1fe03
Packit Service d1fe03
	xtables_register_match(&devgroup_mt_reg);
Packit Service d1fe03
}