11254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <stdio.h>
2fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI#include <xtables.h>
3fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI#include <linux/netfilter/xt_physdev.h>
42291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt
52291d887cea2412af380f1ae995ddfee0362386bJan Engelhardtenum {
62291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	O_PHYSDEV_IN = 0,
72291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	O_PHYSDEV_OUT,
82291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	O_PHYSDEV_IS_IN,
92291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	O_PHYSDEV_IS_OUT,
102291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	O_PHYSDEV_IS_BRIDGED,
112291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt};
121254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer
13181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void physdev_help(void)
141254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{
151254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer	printf(
168b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"physdev match options:\n"
17967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt" [!] --physdev-in inputname[+]		bridge port name ([+] for wildcard)\n"
18967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt" [!] --physdev-out outputname[+]	bridge port name ([+] for wildcard)\n"
1930596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer" [!] --physdev-is-in			arrived on a bridge device\n"
2030596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer" [!] --physdev-is-out			will leave on a bridge device\n"
218b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt" [!] --physdev-is-bridged		it's a bridged packet\n");
221254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer}
231254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer
242291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt#define s struct xt_physdev_info
252291d887cea2412af380f1ae995ddfee0362386bJan Engelhardtstatic const struct xt_option_entry physdev_opts[] = {
262291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	{.name = "physdev-in", .id = O_PHYSDEV_IN, .type = XTTYPE_STRING,
272291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, physindev)},
282291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	{.name = "physdev-out", .id = O_PHYSDEV_OUT, .type = XTTYPE_STRING,
292291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, physoutdev)},
30c2a47ead16fc488fbf7fd8aa12d306cedf4da441Jan Engelhardt	{.name = "physdev-is-in", .id = O_PHYSDEV_IS_IN, .type = XTTYPE_NONE,
31c2a47ead16fc488fbf7fd8aa12d306cedf4da441Jan Engelhardt	 .flags = XTOPT_INVERT},
322291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	{.name = "physdev-is-out", .id = O_PHYSDEV_IS_OUT,
33c2a47ead16fc488fbf7fd8aa12d306cedf4da441Jan Engelhardt	 .type = XTTYPE_NONE, .flags = XTOPT_INVERT},
342291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	{.name = "physdev-is-bridged", .id = O_PHYSDEV_IS_BRIDGED,
35c2a47ead16fc488fbf7fd8aa12d306cedf4da441Jan Engelhardt	 .type = XTTYPE_NONE, .flags = XTOPT_INVERT},
362291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	XTOPT_TABLEEND,
371254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer};
382291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt#undef s
391254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer
402291d887cea2412af380f1ae995ddfee0362386bJan Engelhardtstatic void physdev_parse(struct xt_option_call *cb)
411254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{
422291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	struct xt_physdev_info *info = cb->data;
431254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer
442291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	xtables_option_parse(cb);
452291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	switch (cb->entry->id) {
462291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	case O_PHYSDEV_IN:
472291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt		xtables_parse_interface(cb->arg, info->physindev,
48efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte				(unsigned char *)info->in_mask);
492291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt		if (cb->invert)
50fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI			info->invert |= XT_PHYSDEV_OP_IN;
51fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI		info->bitmask |= XT_PHYSDEV_OP_IN;
521254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer		break;
532291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	case O_PHYSDEV_OUT:
542291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt		xtables_parse_interface(cb->arg, info->physoutdev,
55efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte				(unsigned char *)info->out_mask);
562291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt		if (cb->invert)
57fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI			info->invert |= XT_PHYSDEV_OP_OUT;
58fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI		info->bitmask |= XT_PHYSDEV_OP_OUT;
5930596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer		break;
602291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	case O_PHYSDEV_IS_IN:
61fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI		info->bitmask |= XT_PHYSDEV_OP_ISIN;
622291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt		if (cb->invert)
63fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI			info->invert |= XT_PHYSDEV_OP_ISIN;
6430596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer		break;
652291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	case O_PHYSDEV_IS_OUT:
66fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI		info->bitmask |= XT_PHYSDEV_OP_ISOUT;
672291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt		if (cb->invert)
68fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI			info->invert |= XT_PHYSDEV_OP_ISOUT;
6930596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer		break;
702291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	case O_PHYSDEV_IS_BRIDGED:
712291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt		if (cb->invert)
72fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI			info->invert |= XT_PHYSDEV_OP_BRIDGED;
73fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI		info->bitmask |= XT_PHYSDEV_OP_BRIDGED;
741254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer		break;
751254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer	}
761254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer}
771254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer
782291d887cea2412af380f1ae995ddfee0362386bJan Engelhardtstatic void physdev_check(struct xt_fcheck_call *cb)
791254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{
802291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	if (cb->xflags == 0)
811829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt		xtables_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
821254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer}
831254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer
841254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymerstatic void
85181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtphysdev_print(const void *ip, const struct xt_entry_match *match, int numeric)
861254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{
8769f564e3890976461de0016cd81171ff8bfa8353Jan Engelhardt	const struct xt_physdev_info *info = (const void *)match->data;
881254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer
8973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	printf(" PHYSDEV match");
90fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI	if (info->bitmask & XT_PHYSDEV_OP_ISIN)
9130596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer		printf("%s --physdev-is-in",
92fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI		       info->invert & XT_PHYSDEV_OP_ISIN ? " !":"");
93fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI	if (info->bitmask & XT_PHYSDEV_OP_IN)
9430596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer		printf("%s --physdev-in %s",
95fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI		(info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
9630596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer
97fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI	if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
9830596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer		printf("%s --physdev-is-out",
99fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI		       info->invert & XT_PHYSDEV_OP_ISOUT ? " !":"");
100fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI	if (info->bitmask & XT_PHYSDEV_OP_OUT)
10130596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer		printf("%s --physdev-out %s",
102fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI		(info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
103fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI	if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
10430596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer		printf("%s --physdev-is-bridged",
105fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI		       info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":"");
1061254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer}
1071254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer
108181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void physdev_save(const void *ip, const struct xt_entry_match *match)
1091254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{
11069f564e3890976461de0016cd81171ff8bfa8353Jan Engelhardt	const struct xt_physdev_info *info = (const void *)match->data;
1111254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer
112fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI	if (info->bitmask & XT_PHYSDEV_OP_ISIN)
11373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf("%s --physdev-is-in",
11473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		       (info->invert & XT_PHYSDEV_OP_ISIN) ? " !" : "");
115fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI	if (info->bitmask & XT_PHYSDEV_OP_IN)
11673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf("%s --physdev-in %s",
11773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		       (info->invert & XT_PHYSDEV_OP_IN) ? " !" : "",
118d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt		       info->physindev);
11930596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer
120fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI	if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
12173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf("%s --physdev-is-out",
12273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		       (info->invert & XT_PHYSDEV_OP_ISOUT) ? " !" : "");
123fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI	if (info->bitmask & XT_PHYSDEV_OP_OUT)
12473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf("%s --physdev-out %s",
12573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		       (info->invert & XT_PHYSDEV_OP_OUT) ? " !" : "",
126d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt		       info->physoutdev);
127fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI	if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
12873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf("%s --physdev-is-bridged",
12973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		       (info->invert & XT_PHYSDEV_OP_BRIDGED) ? " !" : "");
1301254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer}
1311254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer
132181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match physdev_match = {
133c5e85736c207f211d82d2878a5781f512327dfceJan Engelhardt	.family		= NFPROTO_UNSPEC,
134fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI	.name		= "physdev",
1358b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.version	= XTABLES_VERSION,
136fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI	.size		= XT_ALIGN(sizeof(struct xt_physdev_info)),
137fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI	.userspacesize	= XT_ALIGN(sizeof(struct xt_physdev_info)),
138181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.help		= physdev_help,
139181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.print		= physdev_print,
140181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	.save		= physdev_save,
1412291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	.x6_parse	= physdev_parse,
1422291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	.x6_fcheck	= physdev_check,
1432291d887cea2412af380f1ae995ddfee0362386bJan Engelhardt	.x6_options	= physdev_opts,
1441254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer};
1451254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer
1461254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymervoid _init(void)
1471254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{
148181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	xtables_register_match(&physdev_match);
1491254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer}
150