#include <linux/netfilter_bridge.h>
#if defined(CONFIG_MIPS_BRCM)
#include <linux/if_vlan.h>
+#include <linux/timer.h>
#endif
#include "br_private.h"
br_pass_frame_up_finish);
}
+extern void addr_debug();
+
+void query_timeout(unsigned long ptr)
+{
+ struct net_bridge_mc_fdb_entry *dst;
+ struct net_bridge_mc_fdb_entry *tmp = NULL;
+ struct list_head *lh;
+ struct net_bridge *br;
+
+ br = (struct net_bridge *) ptr;
+
+ spin_lock_bh(&br->mcl_lock);
+ list_for_each_safe_rcu(lh, tmp, &br->mc_list) {
+ dst = (struct net_bridge_mc_fdb_entry *) list_entry(lh, struct net_bridge_mc_fdb_entry, list);
+ if (jiffies > dst->tstamp) {
+ list_del_rcu(&dst->list);
+ kfree(dst);
+ }
+ }
+ spin_unlock_bh(&br->mcl_lock);
+
+ mod_timer(&br->igmp_timer, jiffies + TIMER_CHECK_TIMEOUT*HZ);
+}
+
+void addr_debug(unsigned char *dest)
+{
+#define NUM2PRINT 50
+ char buf[NUM2PRINT * 3 + 1]; /* 3 chars per byte */
+ int i = 0;
+ for (i = 0; i < 6 && i < NUM2PRINT; i++) {
+ sprintf(buf + i * 3, "%2.2x ", 0xff & dest[i]);
+ }
+ printk("%s ", buf);
+}
+
+
+#if defined(CONFIG_MIPS_BRCM)
+addr_conv(unsigned char *in, char * out)
+{
+ sprintf(out, "%02x%02x%02x%02x%02x%02x", in[0], in[1], in[2], in[3], in[4], in[5]);
+}
+
+mc_forward(struct net_bridge *br, struct sk_buff *skb, unsigned char *dest,int forward, int clone)
+{
+ struct net_bridge_mc_fdb_entry *dst;
+ struct list_head *lh;
+ int status = 0;
+ struct sk_buff *skb2;
+ struct net_bridge_port *p;
+
+ if (!snooping)
+ return 0;
+
+ if (skb->data[9] == 0x2) {
+ // For proxy; need to add some intelligence here
+ if (!br->proxy) {
+ if (skb->data[24] == 0x16)
+ br_mc_fdb_add(br, skb->dev->br_port, dest, skb->mac.ethernet->h_source);
+ else if (skb->data[24] == 0x17) {
+ dest[0] = 0x01;
+ dest[1] = 0x00;
+ dest[2] = 0x5e;
+ dest[3] = 0x7F & skb->data[29];
+ dest[4] = skb->data[30];
+ dest[5] = skb->data[31];
+ br_mc_fdb_remove(br, skb->dev->br_port, dest, skb->mac.ethernet->h_source);
+ }
+ else
+ ;
+ }
+ return status;
+ }
+
+ /*
+ if (clone) {
+ struct sk_buff *skb3;
+
+ if ((skb3 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
+ br->statistics.tx_dropped++;
+ return;
+ }
+
+ skb = skb3;
+ }
+ */
+
+ list_for_each_rcu(lh, &br->mc_list) {
+ dst = (struct net_bridge_mc_fdb_entry *) list_entry(lh, struct net_bridge_mc_fdb_entry, list);
+ if (!memcmp(&dst->addr, dest, ETH_ALEN)) {
+ if (!dst->dst->dirty) {
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (forward)
+ br_forward(dst->dst, skb2);
+ else
+ br_deliver(dst->dst, skb2);
+ }
+ dst->dst->dirty = 1;
+ status = 1;
+ }
+ }
+ if (status) {
+ list_for_each_entry_rcu(p, &br->port_list, list) {
+ p->dirty = 0;
+ }
+ }
+
+ if ((!forward) && (status))
+ kfree_skb(skb);
+
+ return status;
+}
+#endif
+
int br_handle_frame_finish(struct sk_buff *skb)
{
struct net_bridge *br;
unsigned char *dest;
+#if defined(CONFIG_MIPS_BRCM)
+ unsigned char *src;
+#endif
struct net_bridge_fdb_entry *dst;
struct net_bridge_port *p;
int passedup;
dest = skb->mac.ethernet->h_dest;
-
+#if defined(CONFIG_MIPS_BRCM)
+ src = skb->mac.ethernet->h_source;
+#endif
+
rcu_read_lock();
p = skb->dev->br_port;
smp_read_barrier_depends();
}
if (dest[0] & 1) {
+#if defined(CONFIG_MIPS_BRCM)
+ if (snooping && br->proxy) {
+ if (skb->data[9] == 0x2) {
+ char destS[16];
+ char srcS[16];
+
+ if (skb->data[24] == 0x17) {
+ unsigned char tmp[6];
+
+ tmp[0] = 0x01;
+ tmp[1] = 0x00;
+ tmp[2] = 0x5e;
+ tmp[3] = 0x7F & skb->data[29];
+ tmp[4] = skb->data[30];
+ tmp[5] = skb->data[31];
+ addr_conv(tmp, destS);
+ }
+ else
+ addr_conv(dest, destS);
+ addr_conv(src, srcS);
+ sprintf(skb->extif, "%s %s %s/%s", br->dev->name, p->dev->name, destS, srcS);
+ }
+ }
+ if (!mc_forward(br, skb, dest, 1, !passedup))
+#endif
br_flood_forward(br, skb, !passedup);
if (!passedup)
br_pass_frame_up(br, skb);