blob: 2be6bd18423aa68c9c29e876b7a4d20ce09847a4 [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
15static void
16help(void)
17{
18 printf(
19"physdev v%s options:\n"
20" --physdev-in [!] input name[+] bridge port name ([+] for wildcard)\n"
21" --physdev-out [!] output name[+] bridge port name ([+] for wildcard)\n"
22" [!] --physdev-is-in arrived on a bridge device\n"
23" [!] --physdev-is-out will leave on a bridge device\n"
24" [!] --physdev-is-bridged it's a bridged packet\n"
25"\n", IPTABLES_VERSION);
26}
27
Jan Engelhardt661f1122007-07-30 14:46:51 +000028static const struct option opts[] = {
Patrick McHardy500f4832007-09-08 15:59:04 +000029 { "physdev-in", 1, NULL, '1' },
30 { "physdev-out", 1, NULL, '2' },
31 { "physdev-is-in", 0, NULL, '3' },
32 { "physdev-is-out", 0, NULL, '4' },
33 { "physdev-is-bridged", 0, NULL, '5' },
34 { }
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000035};
36
37static void
Peter Rileyea146a92007-09-02 13:09:07 +000038init(struct xt_entry_match *m)
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000039{
40}
41
42static int
43parse(int c, char **argv, int invert, unsigned int *flags,
44 const void *entry,
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +000045 struct xt_entry_match **match)
46{
47 struct xt_physdev_info *info =
48 (struct xt_physdev_info*)(*match)->data;
49
50 switch (c) {
51 case '1':
52 if (*flags & XT_PHYSDEV_OP_IN)
53 goto multiple_use;
54 check_inverse(optarg, &invert, &optind, 0);
55 parse_interface(argv[optind-1], info->physindev,
56 (unsigned char *)info->in_mask);
57 if (invert)
58 info->invert |= XT_PHYSDEV_OP_IN;
59 info->bitmask |= XT_PHYSDEV_OP_IN;
60 *flags |= XT_PHYSDEV_OP_IN;
61 break;
62
63 case '2':
64 if (*flags & XT_PHYSDEV_OP_OUT)
65 goto multiple_use;
66 check_inverse(optarg, &invert, &optind, 0);
67 parse_interface(argv[optind-1], info->physoutdev,
68 (unsigned char *)info->out_mask);
69 if (invert)
70 info->invert |= XT_PHYSDEV_OP_OUT;
71 info->bitmask |= XT_PHYSDEV_OP_OUT;
72 *flags |= XT_PHYSDEV_OP_OUT;
73 break;
74
75 case '3':
76 if (*flags & XT_PHYSDEV_OP_ISIN)
77 goto multiple_use;
78 check_inverse(optarg, &invert, &optind, 0);
79 info->bitmask |= XT_PHYSDEV_OP_ISIN;
80 if (invert)
81 info->invert |= XT_PHYSDEV_OP_ISIN;
82 *flags |= XT_PHYSDEV_OP_ISIN;
83 break;
84
85 case '4':
86 if (*flags & XT_PHYSDEV_OP_ISOUT)
87 goto multiple_use;
88 check_inverse(optarg, &invert, &optind, 0);
89 info->bitmask |= XT_PHYSDEV_OP_ISOUT;
90 if (invert)
91 info->invert |= XT_PHYSDEV_OP_ISOUT;
92 *flags |= XT_PHYSDEV_OP_ISOUT;
93 break;
94
95 case '5':
96 if (*flags & XT_PHYSDEV_OP_BRIDGED)
97 goto multiple_use;
98 check_inverse(optarg, &invert, &optind, 0);
99 if (invert)
100 info->invert |= XT_PHYSDEV_OP_BRIDGED;
101 *flags |= XT_PHYSDEV_OP_BRIDGED;
102 info->bitmask |= XT_PHYSDEV_OP_BRIDGED;
103 break;
104
105 default:
106 return 0;
107 }
108
109 return 1;
110multiple_use:
111 exit_error(PARAMETER_PROBLEM,
112 "multiple use of the same physdev option is not allowed");
113
114}
115
116static void final_check(unsigned int flags)
117{
118 if (flags == 0)
119 exit_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
120}
121
122static void
123print(const void *ip,
124 const struct xt_entry_match *match,
125 int numeric)
126{
127 struct xt_physdev_info *info =
128 (struct xt_physdev_info*)match->data;
129
130 printf("PHYSDEV match");
131 if (info->bitmask & XT_PHYSDEV_OP_ISIN)
132 printf("%s --physdev-is-in",
133 info->invert & XT_PHYSDEV_OP_ISIN ? " !":"");
134 if (info->bitmask & XT_PHYSDEV_OP_IN)
135 printf("%s --physdev-in %s",
136 (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
137
138 if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
139 printf("%s --physdev-is-out",
140 info->invert & XT_PHYSDEV_OP_ISOUT ? " !":"");
141 if (info->bitmask & XT_PHYSDEV_OP_OUT)
142 printf("%s --physdev-out %s",
143 (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
144 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
145 printf("%s --physdev-is-bridged",
146 info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":"");
147 printf(" ");
148}
149
150static void save(const void *ip, const struct xt_entry_match *match)
151{
152 struct xt_physdev_info *info =
153 (struct xt_physdev_info*)match->data;
154
155 if (info->bitmask & XT_PHYSDEV_OP_ISIN)
156 printf("%s --physdev-is-in",
157 info->invert & XT_PHYSDEV_OP_ISIN ? " !":"");
158 if (info->bitmask & XT_PHYSDEV_OP_IN)
159 printf("%s --physdev-in %s",
160 (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
161
162 if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
163 printf("%s --physdev-is-out",
164 info->invert & XT_PHYSDEV_OP_ISOUT ? " !":"");
165 if (info->bitmask & XT_PHYSDEV_OP_OUT)
166 printf("%s --physdev-out %s",
167 (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
168 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
169 printf("%s --physdev-is-bridged",
170 info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":"");
171 printf(" ");
172}
173
174static struct xtables_match physdev = {
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000175 .family = AF_INET,
176 .name = "physdev",
177 .version = IPTABLES_VERSION,
178 .size = XT_ALIGN(sizeof(struct xt_physdev_info)),
179 .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)),
180 .help = &help,
181 .init = &init,
182 .parse = &parse,
183 .final_check = &final_check,
184 .print = &print,
185 .save = &save,
186 .extra_opts = opts
187};
188
189static struct xtables_match physdev6 = {
Yasuyuki KOZAKAIfec77fe2007-07-24 07:06:57 +0000190 .family = AF_INET6,
191 .name = "physdev",
192 .version = IPTABLES_VERSION,
193 .size = XT_ALIGN(sizeof(struct xt_physdev_info)),
194 .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)),
195 .help = &help,
196 .init = &init,
197 .parse = &parse,
198 .final_check = &final_check,
199 .print = &print,
200 .save = &save,
201 .extra_opts = opts
202};
203
204void _init(void)
205{
206 xtables_register_match(&physdev);
207 xtables_register_match(&physdev6);
208}