patch-2.4.22 linux-2.4.22/net/bridge/br_stp_bpdu.c
Next file: linux-2.4.22/net/core/dev.c
Previous file: linux-2.4.22/net/bridge/br_private.h
Back to the patch index
Back to the overall index
- Lines: 125
- Date:
2003-08-25 04:44:44.000000000 -0700
- Orig file:
linux-2.4.21/net/bridge/br_stp_bpdu.c
- Orig date:
2001-11-13 09:16:05.000000000 -0800
diff -urN linux-2.4.21/net/bridge/br_stp_bpdu.c linux-2.4.22/net/bridge/br_stp_bpdu.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/if_ether.h>
#include <linux/if_bridge.h>
+#include <linux/netfilter_bridge.h>
#include "br_private.h"
#include "br_private_stp.h"
@@ -53,7 +54,8 @@
memcpy(skb->nh.raw, data, length);
memset(skb->nh.raw + length, 0xa5, size - length - 2*ETH_ALEN - 2);
- dev_queue_xmit(skb);
+ NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
+ dev_queue_xmit);
}
static __inline__ void br_set_ticks(unsigned char *dest, int jiff)
@@ -133,61 +135,65 @@
static unsigned char header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
/* called under bridge lock */
-void br_stp_handle_bpdu(struct sk_buff *skb)
+int br_stp_handle_bpdu(struct sk_buff *skb)
{
unsigned char *buf;
struct net_bridge_port *p;
- buf = skb->mac.raw + 14;
p = skb->dev->br_port;
- if (!p->br->stp_enabled || memcmp(buf, header, 6)) {
- kfree_skb(skb);
- return;
- }
- if (buf[6] == BPDU_TYPE_CONFIG) {
+ if (!p->br->stp_enabled ||
+ !pskb_may_pull(skb, sizeof(header)+1) ||
+ memcmp(skb->data, header, sizeof(header)))
+ goto err;
+
+ buf = skb_pull(skb, sizeof(header));
+ if (buf[0] == BPDU_TYPE_CONFIG) {
struct br_config_bpdu bpdu;
- bpdu.topology_change = (buf[7] & 0x01) ? 1 : 0;
- bpdu.topology_change_ack = (buf[7] & 0x80) ? 1 : 0;
- bpdu.root.prio[0] = buf[8];
- bpdu.root.prio[1] = buf[9];
- bpdu.root.addr[0] = buf[10];
- bpdu.root.addr[1] = buf[11];
- bpdu.root.addr[2] = buf[12];
- bpdu.root.addr[3] = buf[13];
- bpdu.root.addr[4] = buf[14];
- bpdu.root.addr[5] = buf[15];
+ if (!pskb_may_pull(skb, 32))
+ goto err;
+
+ buf = skb->data;
+ bpdu.topology_change = (buf[1] & 0x01) ? 1 : 0;
+ bpdu.topology_change_ack = (buf[1] & 0x80) ? 1 : 0;
+
+ bpdu.root.prio[0] = buf[2];
+ bpdu.root.prio[1] = buf[3];
+ bpdu.root.addr[0] = buf[4];
+ bpdu.root.addr[1] = buf[5];
+ bpdu.root.addr[2] = buf[6];
+ bpdu.root.addr[3] = buf[7];
+ bpdu.root.addr[4] = buf[8];
+ bpdu.root.addr[5] = buf[9];
bpdu.root_path_cost =
- (buf[16] << 24) |
- (buf[17] << 16) |
- (buf[18] << 8) |
- buf[19];
- bpdu.bridge_id.prio[0] = buf[20];
- bpdu.bridge_id.prio[1] = buf[21];
- bpdu.bridge_id.addr[0] = buf[22];
- bpdu.bridge_id.addr[1] = buf[23];
- bpdu.bridge_id.addr[2] = buf[24];
- bpdu.bridge_id.addr[3] = buf[25];
- bpdu.bridge_id.addr[4] = buf[26];
- bpdu.bridge_id.addr[5] = buf[27];
- bpdu.port_id = (buf[28] << 8) | buf[29];
-
- bpdu.message_age = br_get_ticks(buf+30);
- bpdu.max_age = br_get_ticks(buf+32);
- bpdu.hello_time = br_get_ticks(buf+34);
- bpdu.forward_delay = br_get_ticks(buf+36);
+ (buf[10] << 24) |
+ (buf[11] << 16) |
+ (buf[12] << 8) |
+ buf[13];
+ bpdu.bridge_id.prio[0] = buf[14];
+ bpdu.bridge_id.prio[1] = buf[15];
+ bpdu.bridge_id.addr[0] = buf[16];
+ bpdu.bridge_id.addr[1] = buf[17];
+ bpdu.bridge_id.addr[2] = buf[18];
+ bpdu.bridge_id.addr[3] = buf[19];
+ bpdu.bridge_id.addr[4] = buf[20];
+ bpdu.bridge_id.addr[5] = buf[21];
+ bpdu.port_id = (buf[22] << 8) | buf[23];
+
+ bpdu.message_age = br_get_ticks(buf+24);
+ bpdu.max_age = br_get_ticks(buf+26);
+ bpdu.hello_time = br_get_ticks(buf+28);
+ bpdu.forward_delay = br_get_ticks(buf+30);
- kfree_skb(skb);
br_received_config_bpdu(p, &bpdu);
- return;
}
- if (buf[6] == BPDU_TYPE_TCN) {
+ else if (buf[0] == BPDU_TYPE_TCN) {
br_received_tcn_bpdu(p);
- kfree_skb(skb);
- return;
}
- kfree_skb(skb);
+ err:
+ kfree(skb);
+ return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)