Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / ebtables / extensions / ebt_stp.c
blob2b108a707fe6540417d400f18f1a9d6f4922dad3
1 /* ebt_stp
3 * Authors:
4 * Bart De Schuymer <bdschuym@pandora.be>
6 * July, 2003
7 */
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <getopt.h>
13 #include "../include/ebtables_u.h"
14 #include <linux/netfilter_bridge/ebt_stp.h>
16 #define STP_TYPE 'a'
17 #define STP_FLAGS 'b'
18 #define STP_ROOTPRIO 'c'
19 #define STP_ROOTADDR 'd'
20 #define STP_ROOTCOST 'e'
21 #define STP_SENDERPRIO 'f'
22 #define STP_SENDERADDR 'g'
23 #define STP_PORT 'h'
24 #define STP_MSGAGE 'i'
25 #define STP_MAXAGE 'j'
26 #define STP_HELLOTIME 'k'
27 #define STP_FWDD 'l'
28 #define STP_NUMOPS 12
30 static struct option opts[] =
32 { "stp-type" , required_argument, 0, STP_TYPE},
33 { "stp-flags" , required_argument, 0, STP_FLAGS},
34 { "stp-root-prio" , required_argument, 0, STP_ROOTPRIO},
35 { "stp-root-addr" , required_argument, 0, STP_ROOTADDR},
36 { "stp-root-cost" , required_argument, 0, STP_ROOTCOST},
37 { "stp-sender-prio" , required_argument, 0, STP_SENDERPRIO},
38 { "stp-sender-addr" , required_argument, 0, STP_SENDERADDR},
39 { "stp-port" , required_argument, 0, STP_PORT},
40 { "stp-msg-age" , required_argument, 0, STP_MSGAGE},
41 { "stp-max-age" , required_argument, 0, STP_MAXAGE},
42 { "stp-hello-time" , required_argument, 0, STP_HELLOTIME},
43 { "stp-forward-delay", required_argument, 0, STP_FWDD},
44 { 0 }
47 #define BPDU_TYPE_CONFIG 0
48 #define BPDU_TYPE_TCN 0x80
49 #define BPDU_TYPE_CONFIG_STRING "config"
50 #define BPDU_TYPE_TCN_STRING "tcn"
52 #define FLAG_TC 0x01
53 #define FLAG_TC_ACK 0x80
54 #define FLAG_TC_STRING "topology-change"
55 #define FLAG_TC_ACK_STRING "topology-change-ack"
57 static void print_help()
59 printf(
60 "stp options:\n"
61 "--stp-type type : BPDU type\n"
62 "--stp-flags flag : control flag\n"
63 "--stp-root-prio prio[:prio] : root priority (16-bit) range\n"
64 "--stp-root-addr address[/mask] : MAC address of root\n"
65 "--stp-root-cost cost[:cost] : root cost (32-bit) range\n"
66 "--stp-sender-prio prio[:prio] : sender priority (16-bit) range\n"
67 "--stp-sender-addr address[/mask] : MAC address of sender\n"
68 "--stp-port port[:port] : port id (16-bit) range\n"
69 "--stp-msg-age age[:age] : message age timer (16-bit) range\n"
70 "--stp-max-age age[:age] : maximum age timer (16-bit) range\n"
71 "--stp-hello-time time[:time] : hello time timer (16-bit) range\n"
72 "--stp-forward-delay delay[:delay]: forward delay timer (16-bit) range\n"
73 " Recognized BPDU type strings:\n"
74 " \"config\": configuration BPDU (=0)\n"
75 " \"tcn\" : topology change notification BPDU (=0x80)\n"
76 " Recognized control flag strings:\n"
77 " \"topology-change\" : topology change flag (0x01)\n"
78 " \"topology-change-ack\": topology change acknowledgement flag (0x80)");
81 static void init(struct ebt_entry_match *match)
83 struct ebt_stp_info *stpinfo = (struct ebt_stp_info *)match->data;
85 stpinfo->invflags = 0;
86 stpinfo->bitmask = 0;
89 static int parse_range(const char *portstring, void *lower, void *upper,
90 int bits, uint32_t min, uint32_t max)
92 char *buffer;
93 char *cp, *end;
94 uint32_t low_nr, upp_nr;
95 int ret = 0;
97 buffer = strdup(portstring);
98 if ((cp = strchr(buffer, ':')) == NULL) {
99 low_nr = strtoul(buffer, &end, 10);
100 if (*end || low_nr < min || low_nr > max) {
101 ret = -1;
102 goto out;
104 if (bits == 2) {
105 *(uint16_t *)lower = low_nr;
106 *(uint16_t *)upper = low_nr;
107 } else {
108 *(uint32_t *)lower = low_nr;
109 *(uint32_t *)upper = low_nr;
111 } else {
112 *cp = '\0';
113 cp++;
114 if (!*buffer)
115 low_nr = min;
116 else {
117 low_nr = strtoul(buffer, &end, 10);
118 if (*end || low_nr < min) {
119 ret = -1;
120 goto out;
123 if (!*cp)
124 upp_nr = max;
125 else {
126 upp_nr = strtoul(cp, &end, 10);
127 if (*end || upp_nr > max) {
128 ret = -1;
129 goto out;
132 if (upp_nr < low_nr) {
133 ret = -1;
134 goto out;
136 if (bits == 2) {
137 *(uint16_t *)lower = low_nr;
138 *(uint16_t *)upper = upp_nr;
139 } else {
140 *(uint32_t *)lower = low_nr;
141 *(uint32_t *)upper = upp_nr;
144 out:
145 free(buffer);
146 return ret;
149 static void print_range(unsigned int l, unsigned int u)
151 if (l == u)
152 printf("%u ", l);
153 else
154 printf("%u:%u ", l, u);
157 static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
158 unsigned int *flags, struct ebt_entry_match **match)
160 struct ebt_stp_info *stpinfo = (struct ebt_stp_info *)(*match)->data;
161 unsigned int flag;
162 long int i;
163 char *end = NULL;
165 if (c < 'a' || c > ('a' + STP_NUMOPS - 1))
166 return 0;
167 flag = 1 << (c - 'a');
168 ebt_check_option2(flags, flag);
169 if (ebt_check_inverse2(optarg))
170 stpinfo->invflags |= flag;
171 stpinfo->bitmask |= flag;
172 switch (flag) {
173 case EBT_STP_TYPE:
174 i = strtol(optarg, &end, 0);
175 if (i < 0 || i > 255 || *end != '\0') {
176 if (!strcasecmp(optarg, BPDU_TYPE_CONFIG_STRING))
177 stpinfo->type = BPDU_TYPE_CONFIG;
178 else if (!strcasecmp(optarg, BPDU_TYPE_TCN_STRING))
179 stpinfo->type = BPDU_TYPE_TCN;
180 else
181 ebt_print_error2("Bad --stp-type argument");
182 } else
183 stpinfo->type = i;
184 break;
185 case EBT_STP_FLAGS:
186 i = strtol(optarg, &end, 0);
187 if (i < 0 || i > 255 || *end != '\0') {
188 if (!strcasecmp(optarg, FLAG_TC_STRING))
189 stpinfo->config.flags = FLAG_TC;
190 else if (!strcasecmp(optarg, FLAG_TC_ACK_STRING))
191 stpinfo->config.flags = FLAG_TC_ACK;
192 else
193 ebt_print_error2("Bad --stp-flags argument");
194 } else
195 stpinfo->config.flags = i;
196 break;
197 case EBT_STP_ROOTPRIO:
198 if (parse_range(argv[optind-1], &(stpinfo->config.root_priol),
199 &(stpinfo->config.root_priou), 2, 0, 0xffff))
200 ebt_print_error("Bad --stp-root-prio range");
201 break;
202 case EBT_STP_ROOTCOST:
203 if (parse_range(argv[optind-1], &(stpinfo->config.root_costl),
204 &(stpinfo->config.root_costu), 4, 0, 0xffffffff))
205 ebt_print_error("Bad --stp-root-cost range");
206 break;
207 case EBT_STP_SENDERPRIO:
208 if (parse_range(argv[optind-1], &(stpinfo->config.sender_priol),
209 &(stpinfo->config.sender_priou), 2, 0, 0xffff))
210 ebt_print_error("Bad --stp-sender-prio range");
211 break;
212 case EBT_STP_PORT:
213 if (parse_range(argv[optind-1], &(stpinfo->config.portl),
214 &(stpinfo->config.portu), 2, 0, 0xffff))
215 ebt_print_error("Bad --stp-port range");
216 break;
217 case EBT_STP_MSGAGE:
218 if (parse_range(argv[optind-1], &(stpinfo->config.msg_agel),
219 &(stpinfo->config.msg_ageu), 2, 0, 0xffff))
220 ebt_print_error("Bad --stp-msg-age range");
221 break;
222 case EBT_STP_MAXAGE:
223 if (parse_range(argv[optind-1], &(stpinfo->config.max_agel),
224 &(stpinfo->config.max_ageu), 2, 0, 0xffff))
225 ebt_print_error("Bad --stp-max-age range");
226 break;
227 case EBT_STP_HELLOTIME:
228 if (parse_range(argv[optind-1], &(stpinfo->config.hello_timel),
229 &(stpinfo->config.hello_timeu), 2, 0, 0xffff))
230 ebt_print_error("Bad --stp-hello-time range");
231 break;
232 case EBT_STP_FWDD:
233 if (parse_range(argv[optind-1], &(stpinfo->config.forward_delayl),
234 &(stpinfo->config.forward_delayu), 2, 0, 0xffff))
235 ebt_print_error("Bad --stp-forward-delay range");
236 break;
237 case EBT_STP_ROOTADDR:
238 if (ebt_get_mac_and_mask(argv[optind-1],
239 (unsigned char *)stpinfo->config.root_addr,
240 (unsigned char *)stpinfo->config.root_addrmsk))
241 ebt_print_error("Bad --stp-root-addr address");
242 break;
243 case EBT_STP_SENDERADDR:
244 if (ebt_get_mac_and_mask(argv[optind-1],
245 (unsigned char *)stpinfo->config.sender_addr,
246 (unsigned char *)stpinfo->config.sender_addrmsk))
247 ebt_print_error("Bad --stp-sender-addr address");
248 break;
249 default:
250 ebt_print_error("stp match: this shouldn't happen");
252 return 1;
255 static void final_check(const struct ebt_u_entry *entry,
256 const struct ebt_entry_match *match, const char *name,
257 unsigned int hookmask, unsigned int time)
259 uint8_t bridge_ula[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00};
260 uint8_t msk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
262 if (memcmp(entry->destmac, bridge_ula, 6) ||
263 memcmp(entry->destmsk, msk, 6))
264 ebt_print_error("STP matching is only valid when the "
265 "destination MAC address is the bridge group "
266 "address (BGA) 01:80:c2:00:00:00");
269 static void print(const struct ebt_u_entry *entry,
270 const struct ebt_entry_match *match)
272 struct ebt_stp_info *stpinfo = (struct ebt_stp_info *)match->data;
273 struct ebt_stp_config_info *c = &(stpinfo->config);
274 int i;
276 for (i = 0; i < STP_NUMOPS; i++) {
277 if (!(stpinfo->bitmask & (1 << i)))
278 continue;
279 printf("--%s %s", opts[i].name,
280 (stpinfo->invflags & (1 << i)) ? "! " : "");
281 if (EBT_STP_TYPE == (1 << i)) {
282 if (stpinfo->type == BPDU_TYPE_CONFIG)
283 printf("%s", BPDU_TYPE_CONFIG_STRING);
284 else if (stpinfo->type == BPDU_TYPE_TCN)
285 printf("%s", BPDU_TYPE_TCN_STRING);
286 else
287 printf("%d", stpinfo->type);
288 } else if (EBT_STP_FLAGS == (1 << i)) {
289 if (c->flags == FLAG_TC)
290 printf("%s", FLAG_TC_STRING);
291 else if (c->flags == FLAG_TC_ACK)
292 printf("%s", FLAG_TC_ACK_STRING);
293 else
294 printf("%d", c->flags);
295 } else if (EBT_STP_ROOTPRIO == (1 << i))
296 print_range(c->root_priol, c->root_priou);
297 else if (EBT_STP_ROOTADDR == (1 << i))
298 ebt_print_mac_and_mask((unsigned char *)c->root_addr,
299 (unsigned char*)c->root_addrmsk);
300 else if (EBT_STP_ROOTCOST == (1 << i))
301 print_range(c->root_costl, c->root_costu);
302 else if (EBT_STP_SENDERPRIO == (1 << i))
303 print_range(c->sender_priol, c->sender_priou);
304 else if (EBT_STP_SENDERADDR == (1 << i))
305 ebt_print_mac_and_mask((unsigned char *)c->sender_addr,
306 (unsigned char *)c->sender_addrmsk);
307 else if (EBT_STP_PORT == (1 << i))
308 print_range(c->portl, c->portu);
309 else if (EBT_STP_MSGAGE == (1 << i))
310 print_range(c->msg_agel, c->msg_ageu);
311 else if (EBT_STP_MAXAGE == (1 << i))
312 print_range(c->max_agel, c->max_ageu);
313 else if (EBT_STP_HELLOTIME == (1 << i))
314 print_range(c->hello_timel, c->hello_timeu);
315 else if (EBT_STP_FWDD == (1 << i))
316 print_range(c->forward_delayl, c->forward_delayu);
317 printf(" ");
321 static int compare(const struct ebt_entry_match *m1,
322 const struct ebt_entry_match *m2)
324 return (!memcmp(m1->data, m2->data, sizeof(struct ebt_stp_info)));
327 static struct ebt_u_match stp_match =
329 .name = "stp",
330 .size = sizeof(struct ebt_stp_info),
331 .help = print_help,
332 .init = init,
333 .parse = parse,
334 .final_check = final_check,
335 .print = print,
336 .compare = compare,
337 .extra_ops = opts,
340 void _init(void)
342 ebt_register_match(&stp_match);