summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBart De Schuymer <bdschuym@pandora.be>2003-07-17 20:10:29 +0000
committerBart De Schuymer <bdschuym@pandora.be>2003-07-17 20:10:29 +0000
commitdaf063843e46a1a52b69336b5fdfe437f4bf53ac (patch)
tree8be7742dbe12166fced95e0e540843d36dc9b865
parentba130ad0d55750902bc883774f9ae7e1e703fa90 (diff)
*** empty log message ***
-rw-r--r--extensions/ebt_stp.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/extensions/ebt_stp.c b/extensions/ebt_stp.c
new file mode 100644
index 0000000..0723bee
--- /dev/null
+++ b/extensions/ebt_stp.c
@@ -0,0 +1,314 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include "../include/ebtables_u.h"
+#include <linux/netfilter_bridge/ebt_stp.h>
+
+#define STP_TYPE 'a'
+#define STP_FLAGS 'b'
+#define STP_ROOTPRIO 'c'
+#define STP_ROOTADDR 'd'
+#define STP_ROOTCOST 'e'
+#define STP_SENDERPRIO 'f'
+#define STP_SENDERADDR 'g'
+#define STP_PORT 'h'
+#define STP_MSGAGE 'i'
+#define STP_MAXAGE 'j'
+#define STP_HELLOTIME 'k'
+#define STP_FWDD 'l'
+#define STP_NUMOPS 12
+
+static struct option opts[] =
+{
+ { "stp-type" , required_argument, 0, STP_TYPE},
+ { "stp-flags" , required_argument, 0, STP_FLAGS},
+ { "stp-root-prio" , required_argument, 0, STP_ROOTPRIO},
+ { "stp-root-addr" , required_argument, 0, STP_ROOTADDR},
+ { "stp-root-cost" , required_argument, 0, STP_ROOTCOST},
+ { "stp-sender-prio" , required_argument, 0, STP_SENDERPRIO},
+ { "stp-sender-addr" , required_argument, 0, STP_SENDERADDR},
+ { "stp-port" , required_argument, 0, STP_PORT},
+ { "stp-msg-age" , required_argument, 0, STP_MSGAGE},
+ { "stp-max-age" , required_argument, 0, STP_MAXAGE},
+ { "stp-hello-time" , required_argument, 0, STP_HELLOTIME},
+ { "stp-forward-delay", required_argument, 0, STP_FWDD},
+ { 0 }
+};
+
+#define BPDU_TYPE_CONFIG 0
+#define BPDU_TYPE_TCN 0x80
+#define BPDU_TYPE_CONFIG_STRING "config"
+#define BPDU_TYPE_TCN_STRING "tcn"
+
+#define FLAG_TC 0x01
+#define FLAG_TC_ACK 0x80
+#define FLAG_TC_STRING "topology-change"
+#define FLAG_TC_ACK_STRING "topology-change-ack"
+
+static void print_help()
+{
+ printf(
+"stp options:\n"
+"--stp-type type : BPDU type\n"
+"--stp-flags flag : control flag\n"
+"--stp-root-prio prio[:prio] : root priority (16-bit) range\n"
+"--stp-root-addr address[/mask] : MAC address of root\n"
+"--stp-root-cost cost[:cost] : root cost (32-bit) range\n"
+"--stp-sender-prio prio[:prio] : sender priority (16-bit) range\n"
+"--stp-sender-addr address[/mask] : MAC address of sender\n"
+"--stp-port port[:port] : port id (16-bit) range\n"
+"--stp-msg-age age[:age] : message age timer (16-bit) range\n"
+"--stp-max-age age[:age] : maximum age timer (16-bit) range\n"
+"--stp-hello-time time[:time] : hello time timer (16-bit) range\n"
+"--stp-forward-delay delay[:delay]: forward delay timer (16-bit) range\n"
+" Recognized BPDU type strings:\n"
+" \"config\": configuration BPDU (=0)\n"
+" \"tcn\" : topology change notification BPDU (=0x80)\n"
+" Recognized control flag strings:\n"
+" \"topology-change\" : topology change flag (0x01)"
+" \"topology-change-ack\": topology change acknowledgement flag (0x80)");
+}
+
+static void init(struct ebt_entry_match *match)
+{
+ struct ebt_stp_info *stpinfo = (struct ebt_stp_info *)match->data;
+
+ stpinfo->invflags = 0;
+ stpinfo->bitmask = 0;
+}
+
+/* defined in ebtables.c */
+int get_mac_and_mask(char *from, char *to, char *mask);
+void print_mac_and_mask(const char *mac, const char *mask);
+
+#define determine_value(p,s) \
+{ \
+ uint32_t _tmp2; \
+ char *_tmp; \
+ _tmp2 = strtoul(s, &_tmp, 0); \
+ if (_tmp) \
+ return -1; \
+ if (size == 2) { \
+ if (_tmp2 >= (1 << 16)) \
+ return -1; \
+ *(uint16_t *)p = (uint16_t)_tmp2;\
+ } else \
+ *(uint32_t *)p = _tmp2; \
+}
+
+static int parse_range(char *rangestring, void *lower, void *upper,
+ int size)
+{
+ char *buffer, *cp;
+
+ buffer = strdup(rangestring);
+ if ((cp = strchr(buffer, ':')) == NULL) {
+ determine_value(lower, buffer);
+ determine_value(upper, buffer);
+ return 0;
+ }
+ *cp = '\0';
+ determine_value(lower, buffer);
+ determine_value(upper, cp + 1);
+ if (lower > upper)
+ return -1;
+ return 0;
+}
+
+static void print_range(uint32_t l, uint32_t u)
+{
+ if (l == u)
+ printf("%d ", l);
+ else
+ printf("%d:%d ", l, u);
+}
+
+static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
+ unsigned int *flags, struct ebt_entry_match **match)
+{
+ struct ebt_stp_info *stpinfo = (struct ebt_stp_info *)(*match)->data;
+ unsigned int flag;
+ long int i;
+ char *end = NULL;
+
+ flag = 1 << (c - 'a');
+ check_option(flags, flag);
+ if (check_inverse(optarg))
+ stpinfo->invflags |= flag;
+ if (optind > argc)
+ print_error("Missing argument for --%s", opts[c-'a'].name);
+ stpinfo->bitmask |= flag;
+ switch (flag) {
+ case EBT_STP_TYPE:
+ i = strtol(argv[optind - 1], &end, 0);
+ if (i < 0 || i > 255 || *end != '\0') {
+ if (!strcasecmp(argv[optind - 1],
+ BPDU_TYPE_CONFIG_STRING))
+ stpinfo->type = BPDU_TYPE_CONFIG;
+ else if (!strcasecmp(argv[optind - 1],
+ BPDU_TYPE_TCN_STRING))
+ stpinfo->type = BPDU_TYPE_TCN;
+ else
+ print_error("Bad STP type argument");
+ } else
+ stpinfo->type = i;
+ break;
+ case EBT_STP_FLAGS:
+ i = strtol(argv[optind - 1], &end, 0);
+ if (i < 0 || i > 255 || *end != '\0') {
+ if (!strcasecmp(argv[optind - 1],
+ FLAG_TC_STRING))
+ stpinfo->config.flags = FLAG_TC;
+ else if (!strcasecmp(argv[optind - 1],
+ FLAG_TC_ACK_STRING))
+ stpinfo->config.flags = FLAG_TC_ACK;
+ else
+ print_error("Bad STP config flags argument");
+ } else
+ stpinfo->config.flags = i;
+ break;
+ case EBT_STP_ROOTPRIO:
+ if (parse_range(argv[optind-1], &(stpinfo->config.root_priol),
+ &(stpinfo->config.root_priou), 2))
+ print_error("Bad STP config root priority range");
+ break;
+ case EBT_STP_ROOTCOST:
+ if (parse_range(argv[optind-1], &(stpinfo->config.root_costl),
+ &(stpinfo->config.root_costu), 4))
+ print_error("Bad STP config root cost range");
+ break;
+ case EBT_STP_SENDERPRIO:
+ if (parse_range(argv[optind-1], &(stpinfo->config.sender_priol),
+ &(stpinfo->config.sender_priou), 2))
+ print_error("Bad STP config sender priority range");
+ break;
+ case EBT_STP_PORT:
+ if (parse_range(argv[optind-1], &(stpinfo->config.portl),
+ &(stpinfo->config.portu), 2))
+ print_error("Bad STP config port range");
+ break;
+ case EBT_STP_MSGAGE:
+ if (parse_range(argv[optind-1], &(stpinfo->config.msg_agel),
+ &(stpinfo->config.msg_ageu), 2))
+ print_error("Bad STP config message age range");
+ break;
+ case EBT_STP_MAXAGE:
+ if (parse_range(argv[optind-1], &(stpinfo->config.max_agel),
+ &(stpinfo->config.max_ageu), 2))
+ print_error("Bad STP config maximum age range");
+ break;
+ case EBT_STP_HELLOTIME:
+ if (parse_range(argv[optind-1], &(stpinfo->config.hello_timel),
+ &(stpinfo->config.hello_timeu), 2))
+ print_error("Bad STP config hello time range");
+ break;
+ case EBT_STP_FWDD:
+ if (parse_range(argv[optind-1], &(stpinfo->config.forward_delayl),
+ &(stpinfo->config.forward_delayu), 2))
+ print_error("Bad STP config forward delay range");
+ break;
+ case EBT_STP_ROOTADDR:
+ if (get_mac_and_mask(argv[optind-1],
+ stpinfo->config.root_addr, stpinfo->config.root_addrmsk))
+ print_error("Bad STP config root address");
+ break;
+ case EBT_STP_SENDERADDR:
+ if (get_mac_and_mask(argv[optind-1], stpinfo->config.sender_addr,
+ stpinfo->config.sender_addrmsk))
+ print_error("Bad STP config sender address");
+ break;
+ default:
+ print_error("This shouldn't happen");
+ }
+ return 1;
+}
+
+static void final_check(const struct ebt_u_entry *entry,
+ const struct ebt_entry_match *match, const char *name,
+ unsigned int hookmask, unsigned int time)
+{
+ uint8_t bridge_ula[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00};
+ uint8_t msk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ if (memcmp(entry->destmac, bridge_ula, 6) ||
+ memcmp(entry->destmsk, msk, 6))
+ print_error("STP matching is only valid when the destination"
+ " MAC address is the bridge group address (BGA)"
+ " 01:80:c2:00:00:00");
+}
+
+static void print(const struct ebt_u_entry *entry,
+ const struct ebt_entry_match *match)
+{
+ struct ebt_stp_info *stpinfo = (struct ebt_stp_info *)match->data;
+ struct ebt_stp_config_info *c = &(stpinfo->config);
+ int i;
+
+ for (i = 0; i < STP_NUMOPS; i++) {
+ if (!(stpinfo->bitmask & (1 << i)))
+ continue;
+ printf("--%s %s", opts[i].name,
+ (stpinfo->invflags & (1 << i)) ? "! " : "");
+ if (EBT_STP_TYPE == (1 << i)) {
+ if (stpinfo->type == BPDU_TYPE_CONFIG)
+ printf("%s", BPDU_TYPE_CONFIG_STRING);
+ else if (stpinfo->type == BPDU_TYPE_TCN)
+ printf("%s", BPDU_TYPE_TCN_STRING);
+ else
+ printf("%d", stpinfo->type);
+ } else if (EBT_STP_FLAGS == (1 << i)) {
+ if (c->flags == FLAG_TC)
+ printf("%s", FLAG_TC_STRING);
+ else if (c->flags == FLAG_TC_ACK)
+ printf("%s", FLAG_TC_ACK_STRING);
+ else
+ printf("%d", c->flags);
+ } else if (EBT_STP_ROOTPRIO == (1 << i))
+ print_range(c->root_priol, c->root_priou);
+ else if (EBT_STP_ROOTADDR == (1 << i))
+ print_mac_and_mask(c->root_addr, c->root_addrmsk);
+ else if (EBT_STP_ROOTCOST == (1 << i))
+ print_range(c->root_costl, c->root_costu);
+ else if (EBT_STP_SENDERPRIO == (1 << i))
+ print_range(c->sender_priol, c->sender_priou);
+ else if (EBT_STP_SENDERADDR == (1 << i))
+ print_mac_and_mask(c->sender_addr, c->sender_addrmsk);
+ else if (EBT_STP_PORT == (1 << i))
+ print_range(c->portl, c->portu);
+ else if (EBT_STP_MSGAGE == (1 << i))
+ print_range(c->msg_agel, c->msg_ageu);
+ else if (EBT_STP_MAXAGE == (1 << i))
+ print_range(c->max_agel, c->max_ageu);
+ else if (EBT_STP_HELLOTIME == (1 << i))
+ print_range(c->hello_timel, c->hello_timeu);
+ else if (EBT_STP_FWDD == (1 << i))
+ print_range(c->forward_delayl, c->forward_delayu);
+ printf(" ");
+ }
+}
+
+static int compare(const struct ebt_entry_match *m1,
+ const struct ebt_entry_match *m2)
+{
+ return (!memcmp(m1->data, m2->data, sizeof(struct ebt_stp_info)));
+}
+
+static struct ebt_u_match stp_match =
+{
+ EBT_STP_MATCH,
+ sizeof(struct ebt_stp_info),
+ print_help,
+ init,
+ parse,
+ final_check,
+ print,
+ compare,
+ opts
+};
+
+static void _init(void) __attribute__ ((constructor));
+static void _init(void)
+{
+ register_match(&stp_match);
+}