blob: e7fa22e98d3685deddafc3bf52a982f257d57e18 [file] [log] [blame]
Bart De Schuymer13218fb2004-09-12 22:37:31 +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 <ip6tables.h>
8#include <linux/netfilter_ipv6/ip6t_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
28static struct option opts[] = {
29 { "physdev-in", 1, 0, '1' },
30 { "physdev-out", 1, 0, '2' },
31 { "physdev-is-in", 0, 0, '3' },
32 { "physdev-is-out", 0, 0, '4' },
33 { "physdev-is-bridged", 0, 0, '5' },
34 {0}
35};
36
Bart De Schuymer13218fb2004-09-12 22:37:31 +000037static void
38init(struct ip6t_entry_match *m, unsigned int *nfcache)
39{
40}
41
42static int
43parse(int c, char **argv, int invert, unsigned int *flags,
44 const struct ip6t_entry *entry,
45 unsigned int *nfcache,
46 struct ip6t_entry_match **match)
47{
48 struct ip6t_physdev_info *info =
49 (struct ip6t_physdev_info*)(*match)->data;
50
51 switch (c) {
52 case '1':
53 if (*flags & IP6T_PHYSDEV_OP_IN)
54 goto multiple_use;
55 check_inverse(optarg, &invert, &optind, 0);
Harald Welteefa8fc22005-07-19 22:03:49 +000056 parse_interface(argv[optind-1], info->physindev,
57 (unsigned char *)info->in_mask);
Bart De Schuymer13218fb2004-09-12 22:37:31 +000058 if (invert)
59 info->invert |= IP6T_PHYSDEV_OP_IN;
60 info->bitmask |= IP6T_PHYSDEV_OP_IN;
61 *flags |= IP6T_PHYSDEV_OP_IN;
62 break;
63
64 case '2':
65 if (*flags & IP6T_PHYSDEV_OP_OUT)
66 goto multiple_use;
67 check_inverse(optarg, &invert, &optind, 0);
68 parse_interface(argv[optind-1], info->physoutdev,
Harald Welteefa8fc22005-07-19 22:03:49 +000069 (unsigned char *)info->out_mask);
Bart De Schuymer13218fb2004-09-12 22:37:31 +000070 if (invert)
71 info->invert |= IP6T_PHYSDEV_OP_OUT;
72 info->bitmask |= IP6T_PHYSDEV_OP_OUT;
73 *flags |= IP6T_PHYSDEV_OP_OUT;
74 break;
75
76 case '3':
77 if (*flags & IP6T_PHYSDEV_OP_ISIN)
78 goto multiple_use;
79 check_inverse(optarg, &invert, &optind, 0);
80 info->bitmask |= IP6T_PHYSDEV_OP_ISIN;
81 if (invert)
82 info->invert |= IP6T_PHYSDEV_OP_ISIN;
83 *flags |= IP6T_PHYSDEV_OP_ISIN;
84 break;
85
86 case '4':
87 if (*flags & IP6T_PHYSDEV_OP_ISOUT)
88 goto multiple_use;
89 check_inverse(optarg, &invert, &optind, 0);
90 info->bitmask |= IP6T_PHYSDEV_OP_ISOUT;
91 if (invert)
92 info->invert |= IP6T_PHYSDEV_OP_ISOUT;
93 *flags |= IP6T_PHYSDEV_OP_ISOUT;
94 break;
95
96 case '5':
97 if (*flags & IP6T_PHYSDEV_OP_BRIDGED)
98 goto multiple_use;
99 check_inverse(optarg, &invert, &optind, 0);
100 if (invert)
101 info->invert |= IP6T_PHYSDEV_OP_BRIDGED;
102 *flags |= IP6T_PHYSDEV_OP_BRIDGED;
103 info->bitmask |= IP6T_PHYSDEV_OP_BRIDGED;
104 break;
105
106 default:
107 return 0;
108 }
109
110 return 1;
111multiple_use:
112 exit_error(PARAMETER_PROBLEM,
113 "multiple use of the same physdev option is not allowed");
114
115}
116
117static void final_check(unsigned int flags)
118{
119 if (flags == 0)
120 exit_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
121}
122
123static void
124print(const struct ip6t_ip6 *ip,
125 const struct ip6t_entry_match *match,
126 int numeric)
127{
128 struct ip6t_physdev_info *info =
129 (struct ip6t_physdev_info*)match->data;
130
131 printf("PHYSDEV match");
132 if (info->bitmask & IP6T_PHYSDEV_OP_ISIN)
133 printf("%s --physdev-is-in",
134 info->invert & IP6T_PHYSDEV_OP_ISIN ? " !":"");
135 if (info->bitmask & IP6T_PHYSDEV_OP_IN)
136 printf("%s --physdev-in %s",
137 (info->invert & IP6T_PHYSDEV_OP_IN) ? " !":"", info->physindev);
138
139 if (info->bitmask & IP6T_PHYSDEV_OP_ISOUT)
140 printf("%s --physdev-is-out",
141 info->invert & IP6T_PHYSDEV_OP_ISOUT ? " !":"");
142 if (info->bitmask & IP6T_PHYSDEV_OP_OUT)
143 printf("%s --physdev-out %s",
144 (info->invert & IP6T_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
145 if (info->bitmask & IP6T_PHYSDEV_OP_BRIDGED)
146 printf("%s --physdev-is-bridged",
147 info->invert & IP6T_PHYSDEV_OP_BRIDGED ? " !":"");
148 printf(" ");
149}
150
151static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
152{
153 struct ip6t_physdev_info *info =
154 (struct ip6t_physdev_info*)match->data;
155
156 if (info->bitmask & IP6T_PHYSDEV_OP_ISIN)
157 printf("%s --physdev-is-in",
158 info->invert & IP6T_PHYSDEV_OP_ISIN ? " !":"");
159 if (info->bitmask & IP6T_PHYSDEV_OP_IN)
160 printf("%s --physdev-in %s",
161 (info->invert & IP6T_PHYSDEV_OP_IN) ? " !":"", info->physindev);
162
163 if (info->bitmask & IP6T_PHYSDEV_OP_ISOUT)
164 printf("%s --physdev-is-out",
165 info->invert & IP6T_PHYSDEV_OP_ISOUT ? " !":"");
166 if (info->bitmask & IP6T_PHYSDEV_OP_OUT)
167 printf("%s --physdev-out %s",
168 (info->invert & IP6T_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
169 if (info->bitmask & IP6T_PHYSDEV_OP_BRIDGED)
170 printf("%s --physdev-is-bridged",
171 info->invert & IP6T_PHYSDEV_OP_BRIDGED ? " !":"");
172 printf(" ");
173}
174
Harald Welte02aa7332005-02-01 15:38:20 +0000175static struct ip6tables_match physdev = {
176 .name = "physdev",
177 .version = IPTABLES_VERSION,
178 .size = IP6T_ALIGN(sizeof(struct ip6t_physdev_info)),
179 .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_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,
Bart De Schuymer13218fb2004-09-12 22:37:31 +0000187};
188
189void _init(void)
190{
191 register_match6(&physdev);
192}