libxt_devgroup.c revision 9ee2a9fe2f74b616da34878104bd1ff406534ad1
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 <stdbool.h>
69ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <stdio.h>
79ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <netdb.h>
89ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <string.h>
99ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <stdlib.h>
109ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <errno.h>
119ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <ctype.h>
129ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <getopt.h>
139ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <xtables.h>
149ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy#include <linux/netfilter/xt_devgroup.h>
159ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
169ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void devgroup_help(void)
179ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
189ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	printf(
199ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy"devgroup match options:\n"
209ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy"[!] --src-group value[/mask]	Match device group of incoming device\n"
219ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy"[!] --dst-group value[/mask]	Match device group of outgoing device\n"
229ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		);
239ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
249ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
259ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardyenum {
269ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	XT_DEVGROUP_OPT_SRCGROUP = 1,
279ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	XT_DEVGROUP_OPT_DSTGROUP,
289ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy};
299ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
309ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic const struct option devgroup_opts[] = {
319ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	{ .name = "src-group", .has_arg = true, .val = XT_DEVGROUP_OPT_SRCGROUP },
329ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	{ .name = "dst-group", .has_arg = true, .val = XT_DEVGROUP_OPT_DSTGROUP },
339ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	XT_GETOPT_TABLEEND,
349ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy};
359ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
369ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystruct devgroupname {
379ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	unsigned int		id;
389ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	char			*name;
399ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	int			len;
409ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	struct devgroupname	*next;
419ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy};
429ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
439ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy/* array of devgroups from /etc/iproute2/group_map */
449ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic struct devgroupname *devgroups;
459ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy/* 1 if loading failed */
469ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic int rdberr;
479ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
489ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void load_devgroups(void)
499ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
509ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	const char* rfnm = "/etc/iproute2/group_map";
519ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	char buf[512];
529ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	FILE *fil;
539ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	char *cur, *nxt;
549ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	int id;
559ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	struct devgroupname *oldnm = NULL, *newnm = NULL;
569ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
579ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	fil = fopen(rfnm, "r");
589ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	if (!fil) {
599ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		rdberr = 1;
609ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		return;
619ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	}
629ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
639ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	while (fgets(buf, sizeof(buf), fil)) {
649ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		cur = buf;
659ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		while ((*cur == ' ') || (*cur == '\t'))
669ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			cur++;
679ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if ((*cur == '#') || (*cur == '\n') || (*cur == 0))
689ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			continue;
699ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
709ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		/* iproute2 allows hex and dec format */
719ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		errno = 0;
729ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) ? 10 : 16);
739ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if ((nxt == cur) || errno)
749ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			continue;
759ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
769ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		/* same boundaries as in iproute2 */
779ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (id < 0 || id > 255)
789ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			continue;
799ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		cur = nxt;
809ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
819ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (!isspace(*cur))
829ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			continue;
839ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		while ((*cur == ' ') || (*cur == '\t'))
849ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			cur++;
859ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if ((*cur == '#') || (*cur == '\n') || (*cur == 0))
869ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			continue;
879ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		nxt = cur;
889ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		while ((*nxt != 0) && !isspace(*nxt))
899ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			nxt++;
909ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (nxt == cur)
919ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			continue;
929ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
939ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		/* found valid data */
949ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		newnm = malloc(sizeof(struct devgroupname));
959ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (newnm == NULL) {
969ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			perror("libxt_devgroup: malloc failed");
979ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			exit(1);
989ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		}
999ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		newnm->id = id;
1009ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		newnm->len = nxt - cur;
1019ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		newnm->name = malloc(newnm->len + 1);
1029ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (newnm->name == NULL) {
1039ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			perror("libxt_devgroup: malloc failed");
1049ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			exit(1);
1059ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		}
1069ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		strncpy(newnm->name, cur, newnm->len);
1079ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		newnm->name[newnm->len] = 0;
1089ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		newnm->next = NULL;
1099ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1109ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (oldnm)
1119ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			oldnm->next = newnm;
1129ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		else
1139ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			devgroups = newnm;
1149ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		oldnm = newnm;
1159ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	}
1169ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1179ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	fclose(fil);
1189ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
1199ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1209ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy/* get devgroup id for name, -1 if error/not found */
1219ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic int devgroup_name2id(const char* name)
1229ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
1239ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	struct devgroupname* cur;
1249ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1259ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	if ((devgroups == NULL) && (rdberr == 0))
1269ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		load_devgroups();
1279ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	cur = devgroups;
1289ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	if (cur == NULL)
1299ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		return -1;
1309ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	while (cur) {
1319ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (!strncmp(name, cur->name, cur->len + 1))
1329ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			return cur->id;
1339ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		cur = cur->next;
1349ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	}
1359ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	return -1;
1369ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
1379ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1389ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy/* get devgroup name for id, NULL if error/not found */
1399ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic const char *devgroup_id2name(int id)
1409ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
1419ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	struct devgroupname* cur;
1429ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1439ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	if ((devgroups == NULL) && (rdberr == 0))
1449ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		load_devgroups();
1459ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	cur = devgroups;
1469ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	if (cur == NULL)
1479ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		return NULL;
1489ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	while (cur) {
1499ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (id == cur->id)
1509ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			return cur->name;
1519ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		cur = cur->next;
1529ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	}
1539ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	return NULL;
1549ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
1559ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1569ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic int devgroup_parse(int c, char **argv, int invert, unsigned int *flags,
1579ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy                       const void *entry, struct xt_entry_match **match)
1589ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
1599ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	struct xt_devgroup_info *info = (struct xt_devgroup_info *)(*match)->data;
1609ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	unsigned int id;
1619ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	char *end;
1629ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
1639ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	switch (c) {
1649ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	case XT_DEVGROUP_OPT_SRCGROUP:
1659ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
1669ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		end = optarg;
1679ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		info->src_group = strtoul(optarg, &end, 0);
1689ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (end != optarg && (*end == '/' || *end == '\0')) {
1699ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			if (*end == '/')
1709ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				info->src_mask = strtoul(end+1, &end, 0);
1719ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			else
1729ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				info->src_mask = 0xffffffff;
1739ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			if (*end != '\0' || end == optarg)
1749ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				xtables_error(PARAMETER_PROBLEM,
1759ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy					      "Bad src-group value `%s'",
1769ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy					      optarg);
1779ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		} else {
1789ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			id = devgroup_name2id(optarg);
1799ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			if (id == -1)
1809ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				xtables_error(PARAMETER_PROBLEM,
1819ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy					      "Device group `%s' not found",
1829ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy					      optarg);
1839ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			info->src_group = id;
1849ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			info->src_mask  = 0xffffffff;
1859ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		}
1869ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		info->flags |= XT_DEVGROUP_MATCH_SRC;
1879ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (invert)
1889ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			info->flags |= XT_DEVGROUP_INVERT_SRC;
1899ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		*flags |= c;
1909ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		break;
1919ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	case XT_DEVGROUP_OPT_DSTGROUP:
1929ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
1939ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		end = optarg;
1949ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		info->dst_group = strtoul(optarg, &end, 0);
1959ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (end != optarg && (*end == '/' || *end == '\0')) {
1969ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			if (*end == '/')
1979ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				info->dst_mask = strtoul(end+1, &end, 0);
1989ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			else
1999ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				info->dst_mask = 0xffffffff;
2009ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			if (*end != '\0' || end == optarg)
2019ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				xtables_error(PARAMETER_PROBLEM,
2029ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy					      "Bad dst-group value `%s'",
2039ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy					      optarg);
2049ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		} else {
2059ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			id = devgroup_name2id(optarg);
2069ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			if (id == -1)
2079ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy				xtables_error(PARAMETER_PROBLEM,
2089ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy					      "Device group `%s' not found",
2099ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy					      optarg);
2109ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			info->dst_group = id;
2119ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			info->dst_mask  = 0xffffffff;
2129ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		}
2139ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		info->flags |= XT_DEVGROUP_MATCH_DST;
2149ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (invert)
2159ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			info->flags |= XT_DEVGROUP_INVERT_DST;
2169ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		*flags |= c;
2179ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		break;
2189ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	}
2199ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	return 1;
2209ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
2219ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
2229ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void
2239ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardyprint_devgroup(unsigned int id, unsigned int mask, int numeric)
2249ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
2259ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	const char *name = NULL;
2269ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
2279ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	if (mask != 0xffffffff)
2289ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		printf("0x%x/0x%x ", id, mask);
2299ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	else {
2309ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (numeric == 0)
2319ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			name = devgroup_id2name(id);
2329ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (name)
2339ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			printf("%s ", name);
2349ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		else
2359ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			printf("0x%x ", id);
2369ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	}
2379ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
2389ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
2399ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void devgroup_show(const char *pfx, const struct xt_devgroup_info *info,
2409ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			  int numeric)
2419ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
2429ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	if (info->flags & XT_DEVGROUP_MATCH_SRC) {
2439ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (info->flags & XT_DEVGROUP_INVERT_SRC)
2449ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			printf("! ");
2459ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		printf("%ssrc-group ", pfx);
2469ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		print_devgroup(info->src_group, info->src_mask, numeric);
2479ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	}
2489ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
2499ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	if (info->flags & XT_DEVGROUP_MATCH_DST) {
2509ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		if (info->flags & XT_DEVGROUP_INVERT_DST)
2519ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			printf("! ");
2529ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		printf("%sdst-group ", pfx);
2539ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		print_devgroup(info->src_group, info->src_mask, numeric);
2549ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	}
2559ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
2569ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
2579ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void devgroup_print(const void *ip, const struct xt_entry_match *match,
2589ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy                        int numeric)
2599ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
2609ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	const struct xt_devgroup_info *info = (const void *)match->data;
2619ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
2629ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	devgroup_show("", info, numeric);
2639ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
2649ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
2659ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void devgroup_save(const void *ip, const struct xt_entry_match *match)
2669ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
2679ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	const struct xt_devgroup_info *info = (const void *)match->data;
2689ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
2699ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	devgroup_show("--", info, 0);
2709ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
2719ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
2729ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic void devgroup_check(unsigned int flags)
2739ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
2749ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	if (!flags)
2759ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy		xtables_error(PARAMETER_PROBLEM,
2769ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			      "devgroup match: You must specify either "
2779ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy			      "'--src-group' or '--dst-group'");
2789ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
2799ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
2809ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardystatic struct xtables_match devgroup_mt_reg = {
2819ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.name		= "devgroup",
2829ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.version	= XTABLES_VERSION,
2839ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.family		= NFPROTO_UNSPEC,
2849ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.size		= XT_ALIGN(sizeof(struct xt_devgroup_info)),
2859ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.userspacesize	= XT_ALIGN(sizeof(struct xt_devgroup_info)),
2869ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.help		= devgroup_help,
2879ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.parse		= devgroup_parse,
2889ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.final_check	= devgroup_check,
2899ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.print		= devgroup_print,
2909ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.save		= devgroup_save,
2919ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	.extra_opts	= devgroup_opts,
2929ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy};
2939ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy
2949ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardyvoid _init(void)
2959ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy{
2969ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy	xtables_register_match(&devgroup_mt_reg);
2979ee2a9fe2f74b616da34878104bd1ff406534ad1Patrick McHardy}
298