• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ebt_stp
2  *
3  * Authors:
4  * Bart De Schuymer <bdschuym@pandora.be>
5  *
6  * July, 2003
7  */
8 
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <netinet/ether.h>
13 #include <linux/netfilter_bridge/ebt_stp.h>
14 #include <xtables.h>
15 
16 #include "iptables/nft.h"
17 #include "iptables/nft-bridge.h"
18 
19 /* These must correspond to the bit position in EBT_STP_* defines */
20 enum {
21 	O_TYPE = 0,
22 	O_FLAGS,
23 	O_RPRIO,
24 	O_RADDR,
25 	O_RCOST,
26 	O_SPRIO,
27 	O_SADDR,
28 	O_PORT,
29 	O_MSGAGE,
30 	O_MAXAGE,
31 	O_HTIME,
32 	O_FWDD,
33 };
34 
35 static const struct xt_option_entry brstp_opts[] = {
36 #define ENTRY(n, i, t) { .name = n, .id = i, .type = t, .flags = XTOPT_INVERT }
37 	ENTRY("stp-type",          O_TYPE,   XTTYPE_STRING),
38 	ENTRY("stp-flags",         O_FLAGS,  XTTYPE_STRING),
39 	ENTRY("stp-root-prio",     O_RPRIO,  XTTYPE_UINT16RC),
40 	ENTRY("stp-root-addr",     O_RADDR,  XTTYPE_ETHERMACMASK),
41 	ENTRY("stp-root-cost",     O_RCOST,  XTTYPE_UINT32RC),
42 	ENTRY("stp-sender-prio",   O_SPRIO,  XTTYPE_UINT16RC),
43 	ENTRY("stp-sender-addr",   O_SADDR,  XTTYPE_ETHERMACMASK),
44 	ENTRY("stp-port",          O_PORT,   XTTYPE_UINT16RC),
45 	ENTRY("stp-msg-age",       O_MSGAGE, XTTYPE_UINT16RC),
46 	ENTRY("stp-max-age",       O_MAXAGE, XTTYPE_UINT16RC),
47 	ENTRY("stp-hello-time",    O_HTIME,  XTTYPE_UINT16RC),
48 	ENTRY("stp-forward-delay", O_FWDD,   XTTYPE_UINT16RC),
49 	XTOPT_TABLEEND,
50 };
51 
52 #define BPDU_TYPE_CONFIG 0
53 #define BPDU_TYPE_TCN 0x80
54 #define BPDU_TYPE_CONFIG_STRING "config"
55 #define BPDU_TYPE_TCN_STRING "tcn"
56 
57 #define FLAG_TC 0x01
58 #define FLAG_TC_ACK 0x80
59 #define FLAG_TC_STRING "topology-change"
60 #define FLAG_TC_ACK_STRING "topology-change-ack"
61 
brstp_print_help(void)62 static void brstp_print_help(void)
63 {
64 	printf(
65 "stp options:\n"
66 "[!] --stp-type type                  : BPDU type\n"
67 "[!] --stp-flags flag                 : control flag\n"
68 "[!] --stp-root-prio prio[:prio]      : root priority (16-bit) range\n"
69 "[!] --stp-root-addr address[/mask]   : MAC address of root\n"
70 "[!] --stp-root-cost cost[:cost]      : root cost (32-bit) range\n"
71 "[!] --stp-sender-prio prio[:prio]    : sender priority (16-bit) range\n"
72 "[!] --stp-sender-addr address[/mask] : MAC address of sender\n"
73 "[!] --stp-port port[:port]           : port id (16-bit) range\n"
74 "[!] --stp-msg-age age[:age]          : message age timer (16-bit) range\n"
75 "[!] --stp-max-age age[:age]          : maximum age timer (16-bit) range\n"
76 "[!] --stp-hello-time time[:time]     : hello time timer (16-bit) range\n"
77 "[!] --stp-forward-delay delay[:delay]: forward delay timer (16-bit) range\n"
78 " Recognized BPDU type strings:\n"
79 "   \"config\": configuration BPDU (=0)\n"
80 "   \"tcn\"   : topology change notification BPDU (=0x80)\n"
81 " Recognized control flag strings:\n"
82 "   \"topology-change\"    : topology change flag (0x01)\n"
83 "   \"topology-change-ack\": topology change acknowledgement flag (0x80)");
84 }
85 
print_range(unsigned int l,unsigned int u)86 static void print_range(unsigned int l, unsigned int u)
87 {
88 	if (l == u)
89 		printf("%u", l);
90 	else
91 		printf("%u:%u", l, u);
92 }
93 
brstp_parse(struct xt_option_call * cb)94 static void brstp_parse(struct xt_option_call *cb)
95 {
96 	struct ebt_stp_info *stpinfo = cb->data;
97 	char *end = NULL;
98 	long int i;
99 
100 	xtables_option_parse(cb);
101 
102 	stpinfo->bitmask |= 1 << cb->entry->id;
103 	if (cb->invert)
104 		stpinfo->invflags |= 1 << cb->entry->id;
105 
106 	switch (cb->entry->id) {
107 	case O_TYPE:
108 		i = strtol(cb->arg, &end, 0);
109 		if (i < 0 || i > 255 || *end != '\0') {
110 			if (!strcasecmp(cb->arg, BPDU_TYPE_CONFIG_STRING))
111 				stpinfo->type = BPDU_TYPE_CONFIG;
112 			else if (!strcasecmp(cb->arg, BPDU_TYPE_TCN_STRING))
113 				stpinfo->type = BPDU_TYPE_TCN;
114 			else
115 				xtables_error(PARAMETER_PROBLEM, "Bad --stp-type argument");
116 		} else
117 			stpinfo->type = i;
118 		break;
119 	case O_FLAGS:
120 		i = strtol(cb->arg, &end, 0);
121 		if (i < 0 || i > 255 || *end != '\0') {
122 			if (!strcasecmp(cb->arg, FLAG_TC_STRING))
123 				stpinfo->config.flags = FLAG_TC;
124 			else if (!strcasecmp(cb->arg, FLAG_TC_ACK_STRING))
125 				stpinfo->config.flags = FLAG_TC_ACK;
126 			else
127 				xtables_error(PARAMETER_PROBLEM, "Bad --stp-flags argument");
128 		} else
129 			stpinfo->config.flags = i;
130 		break;
131 	case O_RADDR:
132 		memcpy(stpinfo->config.root_addr, cb->val.ethermac, ETH_ALEN);
133 		memcpy(stpinfo->config.root_addrmsk,
134 		       cb->val.ethermacmask, ETH_ALEN);
135 		break;
136 	case O_SADDR:
137 		memcpy(stpinfo->config.sender_addr, cb->val.ethermac, ETH_ALEN);
138 		memcpy(stpinfo->config.sender_addrmsk,
139 		       cb->val.ethermacmask, ETH_ALEN);
140 		break;
141 
142 #define RANGE_ASSIGN(fname, val) {				    \
143 		stpinfo->config.fname##l = val[0];			    \
144 		stpinfo->config.fname##u = cb->nvals > 1 ? val[1] : val[0]; \
145 }
146 	case O_RPRIO:
147 		RANGE_ASSIGN(root_prio, cb->val.u16_range);
148 		break;
149 	case O_RCOST:
150 		RANGE_ASSIGN(root_cost, cb->val.u32_range);
151 		break;
152 	case O_SPRIO:
153 		RANGE_ASSIGN(sender_prio, cb->val.u16_range);
154 		break;
155 	case O_PORT:
156 		RANGE_ASSIGN(port, cb->val.u16_range);
157 		break;
158 	case O_MSGAGE:
159 		RANGE_ASSIGN(msg_age, cb->val.u16_range);
160 		break;
161 	case O_MAXAGE:
162 		RANGE_ASSIGN(max_age, cb->val.u16_range);
163 		break;
164 	case O_HTIME:
165 		RANGE_ASSIGN(hello_time, cb->val.u16_range);
166 		break;
167 	case O_FWDD:
168 		RANGE_ASSIGN(forward_delay, cb->val.u16_range);
169 		break;
170 #undef RANGE_ASSIGN
171 	}
172 }
173 
brstp_print(const void * ip,const struct xt_entry_match * match,int numeric)174 static void brstp_print(const void *ip, const struct xt_entry_match *match,
175 			 int numeric)
176 {
177 	const struct ebt_stp_info *stpinfo = (struct ebt_stp_info *)match->data;
178 	const struct ebt_stp_config_info *c = &(stpinfo->config);
179 	int i;
180 
181 	for (i = 0; (1 << i) < EBT_STP_MASK; i++) {
182 		if (!(stpinfo->bitmask & (1 << i)))
183 			continue;
184 		printf("%s--%s ",
185 		       (stpinfo->invflags & (1 << i)) ? "! " : "",
186 		       brstp_opts[i].name);
187 		if (EBT_STP_TYPE == (1 << i)) {
188 			if (stpinfo->type == BPDU_TYPE_CONFIG)
189 				printf("%s", BPDU_TYPE_CONFIG_STRING);
190 			else if (stpinfo->type == BPDU_TYPE_TCN)
191 				printf("%s", BPDU_TYPE_TCN_STRING);
192 			else
193 				printf("%d", stpinfo->type);
194 		} else if (EBT_STP_FLAGS == (1 << i)) {
195 			if (c->flags == FLAG_TC)
196 				printf("%s", FLAG_TC_STRING);
197 			else if (c->flags == FLAG_TC_ACK)
198 				printf("%s", FLAG_TC_ACK_STRING);
199 			else
200 				printf("%d", c->flags);
201 		} else if (EBT_STP_ROOTPRIO == (1 << i))
202 			print_range(c->root_priol, c->root_priou);
203 		else if (EBT_STP_ROOTADDR == (1 << i))
204 			xtables_print_mac_and_mask((unsigned char *)c->root_addr,
205 			   (unsigned char*)c->root_addrmsk);
206 		else if (EBT_STP_ROOTCOST == (1 << i))
207 			print_range(c->root_costl, c->root_costu);
208 		else if (EBT_STP_SENDERPRIO == (1 << i))
209 			print_range(c->sender_priol, c->sender_priou);
210 		else if (EBT_STP_SENDERADDR == (1 << i))
211 			xtables_print_mac_and_mask((unsigned char *)c->sender_addr,
212 			   (unsigned char *)c->sender_addrmsk);
213 		else if (EBT_STP_PORT == (1 << i))
214 			print_range(c->portl, c->portu);
215 		else if (EBT_STP_MSGAGE == (1 << i))
216 			print_range(c->msg_agel, c->msg_ageu);
217 		else if (EBT_STP_MAXAGE == (1 << i))
218 			print_range(c->max_agel, c->max_ageu);
219 		else if (EBT_STP_HELLOTIME == (1 << i))
220 			print_range(c->hello_timel, c->hello_timeu);
221 		else if (EBT_STP_FWDD == (1 << i))
222 			print_range(c->forward_delayl, c->forward_delayu);
223 		printf(" ");
224 	}
225 }
226 
227 static struct xtables_match brstp_match = {
228 	.name		= "stp",
229 	.version	= XTABLES_VERSION,
230 	.family		= NFPROTO_BRIDGE,
231 	.size		= sizeof(struct ebt_stp_info),
232 	.help		= brstp_print_help,
233 	.x6_parse	= brstp_parse,
234 	.print		= brstp_print,
235 	.x6_options	= brstp_opts
236 };
237 
_init(void)238 void _init(void)
239 {
240 	xtables_register_match(&brstp_match);
241 }
242