blob: c87779bb2630191024afabfb4020f7db9bfc5300 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* 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 physdev_help(void)
16{
17 printf(
18"physdev match options:\n"
19" [!] --physdev-in inputname[+] bridge port name ([+] for wildcard)\n"
20" [!] --physdev-out outputname[+] 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}
25
26static const struct option physdev_opts[] = {
27 { "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' },
32 { .name = NULL }
33};
34
35static int
36physdev_parse(int c, char **argv, int invert, unsigned int *flags,
37 const void *entry, struct xt_entry_match **match)
38{
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;
46 xtables_check_inverse(optarg, &invert, &optind, 0);
47 xtables_parse_interface(argv[optind-1], info->physindev,
48 (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;
58 xtables_check_inverse(optarg, &invert, &optind, 0);
59 xtables_parse_interface(argv[optind-1], info->physoutdev,
60 (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;
70 xtables_check_inverse(optarg, &invert, &optind, 0);
71 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;
80 xtables_check_inverse(optarg, &invert, &optind, 0);
81 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;
90 xtables_check_inverse(optarg, &invert, &optind, 0);
91 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 xtables_error(PARAMETER_PROBLEM,
104 "multiple use of the same physdev option is not allowed");
105
106}
107
108static void physdev_check(unsigned int flags)
109{
110 if (flags == 0)
111 xtables_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
112}
113
114static void
115physdev_print(const void *ip, const struct xt_entry_match *match, int numeric)
116{
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
140static void physdev_save(const void *ip, const struct xt_entry_match *match)
141{
142 struct xt_physdev_info *info =
143 (struct xt_physdev_info*)match->data;
144
145 if (info->bitmask & XT_PHYSDEV_OP_ISIN)
146 printf("%s--physdev-is-in ",
147 (info->invert & XT_PHYSDEV_OP_ISIN) ? "! " : "");
148 if (info->bitmask & XT_PHYSDEV_OP_IN)
149 printf("%s--physdev-in %s ",
150 (info->invert & XT_PHYSDEV_OP_IN) ? "! " : "",
151 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) ? "! " : "",
159 info->physoutdev);
160 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
161 printf("%s--physdev-is-bridged ",
162 (info->invert & XT_PHYSDEV_OP_BRIDGED) ? "! " : "");
163}
164
165static struct xtables_match physdev_match = {
166 .family = NFPROTO_IPV4,
167 .name = "physdev",
168 .version = XTABLES_VERSION,
169 .size = XT_ALIGN(sizeof(struct xt_physdev_info)),
170 .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)),
171 .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,
177};
178
179static struct xtables_match physdev_match6 = {
180 .family = NFPROTO_IPV6,
181 .name = "physdev",
182 .version = XTABLES_VERSION,
183 .size = XT_ALIGN(sizeof(struct xt_physdev_info)),
184 .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)),
185 .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,
191};
192
193void _init(void)
194{
195 xtables_register_match(&physdev_match);
196 xtables_register_match(&physdev_match6);
197}