libxt_devgroup.c revision 5d8e61ef4636383ca47cd748cd7457a238de37a6
19ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy/* Shared library add-on to iptables to add devgroup matching support.
29ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy *
39ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
49ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy */
59ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <stdio.h>
69ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <string.h>
79ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <stdlib.h>
89ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <errno.h>
99ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <xtables.h>
109ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <linux/netfilter/xt_devgroup.h>
119ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
129ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void devgroup_help(void)
139ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
149ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	printf(
159ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy"devgroup match options:\n"
169ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy"[!] --src-group value[/mask]	Match device group of incoming device\n"
179ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy"[!] --dst-group value[/mask]	Match device group of outgoing device\n"
189ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		);
199ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
209ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
219ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardyenum {
225d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	O_SRC_GROUP = 0,
235d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	O_DST_GROUP,
249ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy};
259ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
265d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardtstatic const struct xt_option_entry devgroup_opts[] = {
275d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	{.name = "src-group", .id = O_SRC_GROUP, .type = XTTYPE_STRING,
285d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	 .flags = XTOPT_INVERT},
295d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	{.name = "dst-group", .id = O_DST_GROUP, .type = XTTYPE_STRING,
305d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	 .flags = XTOPT_INVERT},
315d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	XTOPT_TABLEEND,
329ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy};
339ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
349ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy/* array of devgroups from /etc/iproute2/group_map */
355d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardtstatic struct xtables_lmap *devgroups;
369ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
375d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardtstatic void devgroup_init(struct xt_entry_match *match)
389ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
395d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	const char file[] = "/etc/iproute2/group_map";
405d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	devgroups = xtables_lmap_init(file);
415d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	if (devgroups == NULL && errno != ENOENT)
425d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt		fprintf(stderr, "Warning: %s: %s\n", file, strerror(errno));
439ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
449ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
455d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardtstatic void devgroup_parse(struct xt_option_call *cb)
469ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
475d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	struct xt_devgroup_info *info = cb->data;
489ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	unsigned int id;
499ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	char *end;
509ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
515d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	xtables_option_parse(cb);
525d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	switch (cb->entry->id) {
535d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	case O_SRC_GROUP:
545d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt		info->src_group = strtoul(cb->arg, &end, 0);
555d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt		if (end != cb->arg && (*end == '/' || *end == '\0')) {
569ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			if (*end == '/')
579ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				info->src_mask = strtoul(end+1, &end, 0);
589ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			else
599ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				info->src_mask = 0xffffffff;
605d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt			if (*end != '\0' || end == cb->arg)
619ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				xtables_error(PARAMETER_PROBLEM,
629ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy					      "Bad src-group value `%s'",
635d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt					      cb->arg);
649ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		} else {
655d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt			id = xtables_lmap_name2id(devgroups, cb->arg);
669ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			if (id == -1)
679ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				xtables_error(PARAMETER_PROBLEM,
689ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy					      "Device group `%s' not found",
695d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt					      cb->arg);
709ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			info->src_group = id;
719ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			info->src_mask  = 0xffffffff;
729ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		}
735d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt		if (cb->invert)
749ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			info->flags |= XT_DEVGROUP_INVERT_SRC;
759ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		break;
765d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	case O_DST_GROUP:
775d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt		info->dst_group = strtoul(cb->arg, &end, 0);
785d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt		if (end != cb->arg && (*end == '/' || *end == '\0')) {
799ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			if (*end == '/')
809ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				info->dst_mask = strtoul(end+1, &end, 0);
819ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			else
829ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				info->dst_mask = 0xffffffff;
835d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt			if (*end != '\0' || end == cb->arg)
849ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				xtables_error(PARAMETER_PROBLEM,
859ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy					      "Bad dst-group value `%s'",
865d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt					      cb->arg);
879ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		} else {
885d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt			id = xtables_lmap_name2id(devgroups, cb->arg);
899ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			if (id == -1)
909ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				xtables_error(PARAMETER_PROBLEM,
919ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy					      "Device group `%s' not found",
925d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt					      cb->arg);
939ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			info->dst_group = id;
949ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			info->dst_mask  = 0xffffffff;
959ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		}
965d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt		if (cb->invert)
979ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			info->flags |= XT_DEVGROUP_INVERT_DST;
989ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		break;
999ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	}
1009ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
1019ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1029ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void
1039ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardyprint_devgroup(unsigned int id, unsigned int mask, int numeric)
1049ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
1059ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	const char *name = NULL;
1069ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1079ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	if (mask != 0xffffffff)
108c0f6d17764e9bc1724cedd78b880a80446363146Jan Engelhardt		printf("0x%x/0x%x", id, mask);
1099ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	else {
1109ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (numeric == 0)
1115d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt			name = xtables_lmap_id2name(devgroups, id);
1129ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (name)
113c0f6d17764e9bc1724cedd78b880a80446363146Jan Engelhardt			printf("%s", name);
1149ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		else
115c0f6d17764e9bc1724cedd78b880a80446363146Jan Engelhardt			printf("0x%x", id);
1169ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	}
1179ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
1189ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1199ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void devgroup_show(const char *pfx, const struct xt_devgroup_info *info,
1209ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			  int numeric)
1219ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
1229ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	if (info->flags & XT_DEVGROUP_MATCH_SRC) {
1239ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (info->flags & XT_DEVGROUP_INVERT_SRC)
124c0f6d17764e9bc1724cedd78b880a80446363146Jan Engelhardt			printf(" !");
125c0f6d17764e9bc1724cedd78b880a80446363146Jan Engelhardt		printf(" %ssrc-group ", pfx);
1269ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		print_devgroup(info->src_group, info->src_mask, numeric);
1279ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	}
1289ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1299ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	if (info->flags & XT_DEVGROUP_MATCH_DST) {
1309ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (info->flags & XT_DEVGROUP_INVERT_DST)
131c0f6d17764e9bc1724cedd78b880a80446363146Jan Engelhardt			printf(" !");
132c0f6d17764e9bc1724cedd78b880a80446363146Jan Engelhardt		printf(" %sdst-group ", pfx);
1339ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		print_devgroup(info->src_group, info->src_mask, numeric);
1349ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	}
1359ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
1369ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1379ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void devgroup_print(const void *ip, const struct xt_entry_match *match,
1389ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy                        int numeric)
1399ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
1409ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	const struct xt_devgroup_info *info = (const void *)match->data;
1419ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1429ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	devgroup_show("", info, numeric);
1439ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
1449ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1459ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void devgroup_save(const void *ip, const struct xt_entry_match *match)
1469ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
1479ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	const struct xt_devgroup_info *info = (const void *)match->data;
1489ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1499ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	devgroup_show("--", info, 0);
1509ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
1519ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1525d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardtstatic void devgroup_check(struct xt_fcheck_call *cb)
1539ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
1545d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	if (cb->xflags == 0)
1559ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		xtables_error(PARAMETER_PROBLEM,
1569ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			      "devgroup match: You must specify either "
1579ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			      "'--src-group' or '--dst-group'");
1589ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
1599ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1609ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic struct xtables_match devgroup_mt_reg = {
1619ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.name		= "devgroup",
1629ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.version	= XTABLES_VERSION,
1639ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.family		= NFPROTO_UNSPEC,
1649ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.size		= XT_ALIGN(sizeof(struct xt_devgroup_info)),
1659ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.userspacesize	= XT_ALIGN(sizeof(struct xt_devgroup_info)),
1665d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	.init		= devgroup_init,
1679ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.help		= devgroup_help,
1689ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.print		= devgroup_print,
1699ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.save		= devgroup_save,
1705d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	.x6_parse	= devgroup_parse,
1715d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	.x6_fcheck	= devgroup_check,
1725d8e61ef4636383ca47cd748cd7457a238de37a6Jan Engelhardt	.x6_options	= devgroup_opts,
1739ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy};
1749ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1759ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardyvoid _init(void)
1769ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
1779ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	xtables_register_match(&devgroup_mt_reg);
1789ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
179