libxt_physdev.c revision c2a47ead16fc488fbf7fd8aa12d306cedf4da441
1#include <stdio.h>
2#include <xtables.h>
3#include <linux/netfilter/xt_physdev.h>
4
5enum {
6	O_PHYSDEV_IN = 0,
7	O_PHYSDEV_OUT,
8	O_PHYSDEV_IS_IN,
9	O_PHYSDEV_IS_OUT,
10	O_PHYSDEV_IS_BRIDGED,
11};
12
13static void physdev_help(void)
14{
15	printf(
16"physdev match options:\n"
17" [!] --physdev-in inputname[+]		bridge port name ([+] for wildcard)\n"
18" [!] --physdev-out outputname[+]	bridge port name ([+] for wildcard)\n"
19" [!] --physdev-is-in			arrived on a bridge device\n"
20" [!] --physdev-is-out			will leave on a bridge device\n"
21" [!] --physdev-is-bridged		it's a bridged packet\n");
22}
23
24#define s struct xt_physdev_info
25static const struct xt_option_entry physdev_opts[] = {
26	{.name = "physdev-in", .id = O_PHYSDEV_IN, .type = XTTYPE_STRING,
27	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, physindev)},
28	{.name = "physdev-out", .id = O_PHYSDEV_OUT, .type = XTTYPE_STRING,
29	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, physoutdev)},
30	{.name = "physdev-is-in", .id = O_PHYSDEV_IS_IN, .type = XTTYPE_NONE,
31	 .flags = XTOPT_INVERT},
32	{.name = "physdev-is-out", .id = O_PHYSDEV_IS_OUT,
33	 .type = XTTYPE_NONE, .flags = XTOPT_INVERT},
34	{.name = "physdev-is-bridged", .id = O_PHYSDEV_IS_BRIDGED,
35	 .type = XTTYPE_NONE, .flags = XTOPT_INVERT},
36	XTOPT_TABLEEND,
37};
38#undef s
39
40static void physdev_parse(struct xt_option_call *cb)
41{
42	struct xt_physdev_info *info = cb->data;
43
44	xtables_option_parse(cb);
45	switch (cb->entry->id) {
46	case O_PHYSDEV_IN:
47		xtables_parse_interface(cb->arg, info->physindev,
48				(unsigned char *)info->in_mask);
49		if (cb->invert)
50			info->invert |= XT_PHYSDEV_OP_IN;
51		info->bitmask |= XT_PHYSDEV_OP_IN;
52		break;
53	case O_PHYSDEV_OUT:
54		xtables_parse_interface(cb->arg, info->physoutdev,
55				(unsigned char *)info->out_mask);
56		if (cb->invert)
57			info->invert |= XT_PHYSDEV_OP_OUT;
58		info->bitmask |= XT_PHYSDEV_OP_OUT;
59		break;
60	case O_PHYSDEV_IS_IN:
61		info->bitmask |= XT_PHYSDEV_OP_ISIN;
62		if (cb->invert)
63			info->invert |= XT_PHYSDEV_OP_ISIN;
64		break;
65	case O_PHYSDEV_IS_OUT:
66		info->bitmask |= XT_PHYSDEV_OP_ISOUT;
67		if (cb->invert)
68			info->invert |= XT_PHYSDEV_OP_ISOUT;
69		break;
70	case O_PHYSDEV_IS_BRIDGED:
71		if (cb->invert)
72			info->invert |= XT_PHYSDEV_OP_BRIDGED;
73		info->bitmask |= XT_PHYSDEV_OP_BRIDGED;
74		break;
75	}
76}
77
78static void physdev_check(struct xt_fcheck_call *cb)
79{
80	if (cb->xflags == 0)
81		xtables_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
82}
83
84static void
85physdev_print(const void *ip, const struct xt_entry_match *match, int numeric)
86{
87	const struct xt_physdev_info *info = (const void *)match->data;
88
89	printf(" PHYSDEV match");
90	if (info->bitmask & XT_PHYSDEV_OP_ISIN)
91		printf("%s --physdev-is-in",
92		       info->invert & XT_PHYSDEV_OP_ISIN ? " !":"");
93	if (info->bitmask & XT_PHYSDEV_OP_IN)
94		printf("%s --physdev-in %s",
95		(info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
96
97	if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
98		printf("%s --physdev-is-out",
99		       info->invert & XT_PHYSDEV_OP_ISOUT ? " !":"");
100	if (info->bitmask & XT_PHYSDEV_OP_OUT)
101		printf("%s --physdev-out %s",
102		(info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
103	if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
104		printf("%s --physdev-is-bridged",
105		       info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":"");
106}
107
108static void physdev_save(const void *ip, const struct xt_entry_match *match)
109{
110	const struct xt_physdev_info *info = (const void *)match->data;
111
112	if (info->bitmask & XT_PHYSDEV_OP_ISIN)
113		printf("%s --physdev-is-in",
114		       (info->invert & XT_PHYSDEV_OP_ISIN) ? " !" : "");
115	if (info->bitmask & XT_PHYSDEV_OP_IN)
116		printf("%s --physdev-in %s",
117		       (info->invert & XT_PHYSDEV_OP_IN) ? " !" : "",
118		       info->physindev);
119
120	if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
121		printf("%s --physdev-is-out",
122		       (info->invert & XT_PHYSDEV_OP_ISOUT) ? " !" : "");
123	if (info->bitmask & XT_PHYSDEV_OP_OUT)
124		printf("%s --physdev-out %s",
125		       (info->invert & XT_PHYSDEV_OP_OUT) ? " !" : "",
126		       info->physoutdev);
127	if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
128		printf("%s --physdev-is-bridged",
129		       (info->invert & XT_PHYSDEV_OP_BRIDGED) ? " !" : "");
130}
131
132static struct xtables_match physdev_match = {
133	.family		= NFPROTO_UNSPEC,
134	.name		= "physdev",
135	.version	= XTABLES_VERSION,
136	.size		= XT_ALIGN(sizeof(struct xt_physdev_info)),
137	.userspacesize	= XT_ALIGN(sizeof(struct xt_physdev_info)),
138	.help		= physdev_help,
139	.print		= physdev_print,
140	.save		= physdev_save,
141	.x6_parse	= physdev_parse,
142	.x6_fcheck	= physdev_check,
143	.x6_options	= physdev_opts,
144};
145
146void _init(void)
147{
148	xtables_register_match(&physdev_match);
149}
150