blob: 4275a1a423c30ea77364adbb5f7dc00ca2088a13 [file] [log] [blame]
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +00001/* Shared library add-on to iptables to add bridge port matching support. */
2#include <stdio.h>
3#include <string.h>
4#include <stdlib.h>
5#include <getopt.h>
6#include <ctype.h>
7#include <xtables.h>
8#include <linux/netfilter/xt_physdev.h>
9#if defined(__GLIBC__) && __GLIBC__ == 2
10#include <net/ethernet.h>
11#else
12#include <linux/if_ether.h>
13#endif
14
Jan Engelhardt181dead2007-10-04 16:27:07 +000015static void physdev_help(void)
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000016{
17 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020018"physdev match options:\n"
Jan Engelhardt96727922008-08-13 14:42:41 +020019" [!] --physdev-in inputname[+] bridge port name ([+] for wildcard)\n"
20" [!] --physdev-out outputname[+] bridge port name ([+] for wildcard)\n"
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000021" [!] --physdev-is-in arrived on a bridge device\n"
22" [!] --physdev-is-out will leave on a bridge device\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020023" [!] --physdev-is-bridged it's a bridged packet\n");
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000024}
25
Jan Engelhardt181dead2007-10-04 16:27:07 +000026static const struct option physdev_opts[] = {
Patrick McHardy500f4832007-09-08 15:59:04 +000027 { "physdev-in", 1, NULL, '1' },
28 { "physdev-out", 1, NULL, '2' },
29 { "physdev-is-in", 0, NULL, '3' },
30 { "physdev-is-out", 0, NULL, '4' },
31 { "physdev-is-bridged", 0, NULL, '5' },
Max Kellermann9ee386a2008-01-29 13:48:05 +000032 { .name = NULL }
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000033};
34
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000035static int
Jan Engelhardt181dead2007-10-04 16:27:07 +000036physdev_parse(int c, char **argv, int invert, unsigned int *flags,
37 const void *entry, struct xt_entry_match **match)
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000038{
39 struct xt_physdev_info *info =
40 (struct xt_physdev_info*)(*match)->data;
41
42 switch (c) {
43 case '1':
44 if (*flags & XT_PHYSDEV_OP_IN)
45 goto multiple_use;
Jan Engelhardt0f16c722009-01-30 04:55:38 +010046 xtables_check_inverse(optarg, &invert, &optind, 0);
Jan Engelhardtaae6be92009-01-30 04:24:47 +010047 xtables_parse_interface(argv[optind-1], info->physindev,
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000048 (unsigned char *)info->in_mask);
49 if (invert)
50 info->invert |= XT_PHYSDEV_OP_IN;
51 info->bitmask |= XT_PHYSDEV_OP_IN;
52 *flags |= XT_PHYSDEV_OP_IN;
53 break;
54
55 case '2':
56 if (*flags & XT_PHYSDEV_OP_OUT)
57 goto multiple_use;
Jan Engelhardt0f16c722009-01-30 04:55:38 +010058 xtables_check_inverse(optarg, &invert, &optind, 0);
Jan Engelhardtaae6be92009-01-30 04:24:47 +010059 xtables_parse_interface(argv[optind-1], info->physoutdev,
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000060 (unsigned char *)info->out_mask);
61 if (invert)
62 info->invert |= XT_PHYSDEV_OP_OUT;
63 info->bitmask |= XT_PHYSDEV_OP_OUT;
64 *flags |= XT_PHYSDEV_OP_OUT;
65 break;
66
67 case '3':
68 if (*flags & XT_PHYSDEV_OP_ISIN)
69 goto multiple_use;
Jan Engelhardt0f16c722009-01-30 04:55:38 +010070 xtables_check_inverse(optarg, &invert, &optind, 0);
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000071 info->bitmask |= XT_PHYSDEV_OP_ISIN;
72 if (invert)
73 info->invert |= XT_PHYSDEV_OP_ISIN;
74 *flags |= XT_PHYSDEV_OP_ISIN;
75 break;
76
77 case '4':
78 if (*flags & XT_PHYSDEV_OP_ISOUT)
79 goto multiple_use;
Jan Engelhardt0f16c722009-01-30 04:55:38 +010080 xtables_check_inverse(optarg, &invert, &optind, 0);
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000081 info->bitmask |= XT_PHYSDEV_OP_ISOUT;
82 if (invert)
83 info->invert |= XT_PHYSDEV_OP_ISOUT;
84 *flags |= XT_PHYSDEV_OP_ISOUT;
85 break;
86
87 case '5':
88 if (*flags & XT_PHYSDEV_OP_BRIDGED)
89 goto multiple_use;
Jan Engelhardt0f16c722009-01-30 04:55:38 +010090 xtables_check_inverse(optarg, &invert, &optind, 0);
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000091 if (invert)
92 info->invert |= XT_PHYSDEV_OP_BRIDGED;
93 *flags |= XT_PHYSDEV_OP_BRIDGED;
94 info->bitmask |= XT_PHYSDEV_OP_BRIDGED;
95 break;
96
97 default:
98 return 0;
99 }
100
101 return 1;
102multiple_use:
103 exit_error(PARAMETER_PROBLEM,
104 "multiple use of the same physdev option is not allowed");
105
106}
107
Jan Engelhardt181dead2007-10-04 16:27:07 +0000108static void physdev_check(unsigned int flags)
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000109{
110 if (flags == 0)
111 exit_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
112}
113
114static void
Jan Engelhardt181dead2007-10-04 16:27:07 +0000115physdev_print(const void *ip, const struct xt_entry_match *match, int numeric)
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000116{
117 struct xt_physdev_info *info =
118 (struct xt_physdev_info*)match->data;
119
120 printf("PHYSDEV match");
121 if (info->bitmask & XT_PHYSDEV_OP_ISIN)
122 printf("%s --physdev-is-in",
123 info->invert & XT_PHYSDEV_OP_ISIN ? " !":"");
124 if (info->bitmask & XT_PHYSDEV_OP_IN)
125 printf("%s --physdev-in %s",
126 (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
127
128 if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
129 printf("%s --physdev-is-out",
130 info->invert & XT_PHYSDEV_OP_ISOUT ? " !":"");
131 if (info->bitmask & XT_PHYSDEV_OP_OUT)
132 printf("%s --physdev-out %s",
133 (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
134 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
135 printf("%s --physdev-is-bridged",
136 info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":"");
137 printf(" ");
138}
139
Jan Engelhardt181dead2007-10-04 16:27:07 +0000140static void physdev_save(const void *ip, const struct xt_entry_match *match)
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000141{
142 struct xt_physdev_info *info =
143 (struct xt_physdev_info*)match->data;
144
145 if (info->bitmask & XT_PHYSDEV_OP_ISIN)
Jan Engelhardtd38eaf42008-08-13 14:40:18 +0200146 printf("%s--physdev-is-in ",
147 (info->invert & XT_PHYSDEV_OP_ISIN) ? "! " : "");
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000148 if (info->bitmask & XT_PHYSDEV_OP_IN)
Jan Engelhardtd38eaf42008-08-13 14:40:18 +0200149 printf("%s--physdev-in %s ",
150 (info->invert & XT_PHYSDEV_OP_IN) ? "! " : "",
151 info->physindev);
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000152
153 if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
Jan Engelhardtd38eaf42008-08-13 14:40:18 +0200154 printf("%s--physdev-is-out ",
155 (info->invert & XT_PHYSDEV_OP_ISOUT) ? "! " : "");
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000156 if (info->bitmask & XT_PHYSDEV_OP_OUT)
Jan Engelhardtd38eaf42008-08-13 14:40:18 +0200157 printf("%s--physdev-out %s ",
158 (info->invert & XT_PHYSDEV_OP_OUT) ? "! " : "",
159 info->physoutdev);
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000160 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
Jan Engelhardtd38eaf42008-08-13 14:40:18 +0200161 printf("%s--physdev-is-bridged ",
162 (info->invert & XT_PHYSDEV_OP_BRIDGED) ? "! " : "");
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000163}
164
Jan Engelhardt181dead2007-10-04 16:27:07 +0000165static struct xtables_match physdev_match = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100166 .family = NFPROTO_IPV4,
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000167 .name = "physdev",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200168 .version = XTABLES_VERSION,
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000169 .size = XT_ALIGN(sizeof(struct xt_physdev_info)),
170 .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000171 .help = physdev_help,
172 .parse = physdev_parse,
173 .final_check = physdev_check,
174 .print = physdev_print,
175 .save = physdev_save,
176 .extra_opts = physdev_opts,
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000177};
178
Jan Engelhardt181dead2007-10-04 16:27:07 +0000179static struct xtables_match physdev_match6 = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100180 .family = NFPROTO_IPV6,
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000181 .name = "physdev",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200182 .version = XTABLES_VERSION,
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000183 .size = XT_ALIGN(sizeof(struct xt_physdev_info)),
184 .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000185 .help = physdev_help,
186 .parse = physdev_parse,
187 .final_check = physdev_check,
188 .print = physdev_print,
189 .save = physdev_save,
190 .extra_opts = physdev_opts,
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000191};
192
193void _init(void)
194{
Jan Engelhardt181dead2007-10-04 16:27:07 +0000195 xtables_register_match(&physdev_match);
196 xtables_register_match(&physdev_match6);
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000197}