blob: 144fbb4f46c5cb0bfa32e02e9154d8e007c46def [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(
18"physdev v%s options:\n"
19" --physdev-in [!] input name[+] bridge port name ([+] for wildcard)\n"
20" --physdev-out [!] output name[+] bridge port name ([+] for wildcard)\n"
21" [!] --physdev-is-in arrived on a bridge device\n"
22" [!] --physdev-is-out will leave on a bridge device\n"
23" [!] --physdev-is-bridged it's a bridged packet\n"
24"\n", IPTABLES_VERSION);
25}
26
Jan Engelhardt181dead2007-10-04 16:27:07 +000027static const struct option physdev_opts[] = {
Patrick McHardy500f4832007-09-08 15:59:04 +000028 { "physdev-in", 1, NULL, '1' },
29 { "physdev-out", 1, NULL, '2' },
30 { "physdev-is-in", 0, NULL, '3' },
31 { "physdev-is-out", 0, NULL, '4' },
32 { "physdev-is-bridged", 0, NULL, '5' },
33 { }
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000034};
35
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000036static int
Jan Engelhardt181dead2007-10-04 16:27:07 +000037physdev_parse(int c, char **argv, int invert, unsigned int *flags,
38 const void *entry, struct xt_entry_match **match)
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000039{
40 struct xt_physdev_info *info =
41 (struct xt_physdev_info*)(*match)->data;
42
43 switch (c) {
44 case '1':
45 if (*flags & XT_PHYSDEV_OP_IN)
46 goto multiple_use;
47 check_inverse(optarg, &invert, &optind, 0);
48 parse_interface(argv[optind-1], info->physindev,
49 (unsigned char *)info->in_mask);
50 if (invert)
51 info->invert |= XT_PHYSDEV_OP_IN;
52 info->bitmask |= XT_PHYSDEV_OP_IN;
53 *flags |= XT_PHYSDEV_OP_IN;
54 break;
55
56 case '2':
57 if (*flags & XT_PHYSDEV_OP_OUT)
58 goto multiple_use;
59 check_inverse(optarg, &invert, &optind, 0);
60 parse_interface(argv[optind-1], info->physoutdev,
61 (unsigned char *)info->out_mask);
62 if (invert)
63 info->invert |= XT_PHYSDEV_OP_OUT;
64 info->bitmask |= XT_PHYSDEV_OP_OUT;
65 *flags |= XT_PHYSDEV_OP_OUT;
66 break;
67
68 case '3':
69 if (*flags & XT_PHYSDEV_OP_ISIN)
70 goto multiple_use;
71 check_inverse(optarg, &invert, &optind, 0);
72 info->bitmask |= XT_PHYSDEV_OP_ISIN;
73 if (invert)
74 info->invert |= XT_PHYSDEV_OP_ISIN;
75 *flags |= XT_PHYSDEV_OP_ISIN;
76 break;
77
78 case '4':
79 if (*flags & XT_PHYSDEV_OP_ISOUT)
80 goto multiple_use;
81 check_inverse(optarg, &invert, &optind, 0);
82 info->bitmask |= XT_PHYSDEV_OP_ISOUT;
83 if (invert)
84 info->invert |= XT_PHYSDEV_OP_ISOUT;
85 *flags |= XT_PHYSDEV_OP_ISOUT;
86 break;
87
88 case '5':
89 if (*flags & XT_PHYSDEV_OP_BRIDGED)
90 goto multiple_use;
91 check_inverse(optarg, &invert, &optind, 0);
92 if (invert)
93 info->invert |= XT_PHYSDEV_OP_BRIDGED;
94 *flags |= XT_PHYSDEV_OP_BRIDGED;
95 info->bitmask |= XT_PHYSDEV_OP_BRIDGED;
96 break;
97
98 default:
99 return 0;
100 }
101
102 return 1;
103multiple_use:
104 exit_error(PARAMETER_PROBLEM,
105 "multiple use of the same physdev option is not allowed");
106
107}
108
Jan Engelhardt181dead2007-10-04 16:27:07 +0000109static void physdev_check(unsigned int flags)
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000110{
111 if (flags == 0)
112 exit_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
113}
114
115static void
Jan Engelhardt181dead2007-10-04 16:27:07 +0000116physdev_print(const void *ip, const struct xt_entry_match *match, int numeric)
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000117{
118 struct xt_physdev_info *info =
119 (struct xt_physdev_info*)match->data;
120
121 printf("PHYSDEV match");
122 if (info->bitmask & XT_PHYSDEV_OP_ISIN)
123 printf("%s --physdev-is-in",
124 info->invert & XT_PHYSDEV_OP_ISIN ? " !":"");
125 if (info->bitmask & XT_PHYSDEV_OP_IN)
126 printf("%s --physdev-in %s",
127 (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
128
129 if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
130 printf("%s --physdev-is-out",
131 info->invert & XT_PHYSDEV_OP_ISOUT ? " !":"");
132 if (info->bitmask & XT_PHYSDEV_OP_OUT)
133 printf("%s --physdev-out %s",
134 (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
135 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
136 printf("%s --physdev-is-bridged",
137 info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":"");
138 printf(" ");
139}
140
Jan Engelhardt181dead2007-10-04 16:27:07 +0000141static void physdev_save(const void *ip, const struct xt_entry_match *match)
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000142{
143 struct xt_physdev_info *info =
144 (struct xt_physdev_info*)match->data;
145
146 if (info->bitmask & XT_PHYSDEV_OP_ISIN)
147 printf("%s --physdev-is-in",
148 info->invert & XT_PHYSDEV_OP_ISIN ? " !":"");
149 if (info->bitmask & XT_PHYSDEV_OP_IN)
150 printf("%s --physdev-in %s",
151 (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
152
153 if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
154 printf("%s --physdev-is-out",
155 info->invert & XT_PHYSDEV_OP_ISOUT ? " !":"");
156 if (info->bitmask & XT_PHYSDEV_OP_OUT)
157 printf("%s --physdev-out %s",
158 (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
159 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
160 printf("%s --physdev-is-bridged",
161 info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":"");
162 printf(" ");
163}
164
Jan Engelhardt181dead2007-10-04 16:27:07 +0000165static struct xtables_match physdev_match = {
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000166 .family = AF_INET,
167 .name = "physdev",
168 .version = IPTABLES_VERSION,
169 .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 = {
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000180 .family = AF_INET6,
181 .name = "physdev",
182 .version = IPTABLES_VERSION,
183 .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}