www.usr.com/support/gpl/USR9113_release1.0.tar.gz
[bcm963xx.git] / kernel / linux / net / bridge / br_input.c
index ba44a97..365bc4e 100755 (executable)
 #if defined(CONFIG_MIPS_BRCM)
 #include <linux/if_vlan.h>
 #include <linux/timer.h>
+#include <linux/igmp.h>
 #endif
 #include "br_private.h"
 
+#if defined(CONFIG_MIPS_BRCM)
+#define SNOOPING_BLOCKING_MODE 2
+#endif
+
 const unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
 
 static int br_pass_frame_up_finish(struct sk_buff *skb)
@@ -70,12 +75,10 @@ static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
                        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 *tmp;
        struct list_head *lh;
        struct net_bridge *br;
     
@@ -107,35 +110,62 @@ void addr_debug(unsigned char *dest)
 
 
 #if defined(CONFIG_MIPS_BRCM)
-addr_conv(unsigned char *in, char * out)
+void 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)
+mac_addr upnp_addr = {{0x01, 0x00, 0x5e, 0x7f, 0xff, 0xfa}};
+mac_addr sys1_addr = {{0x01, 0x00, 0x5e, 0x00, 0x00, 0x01}};
+mac_addr sys2_addr = {{0x01, 0x00, 0x5e, 0x00, 0x00, 0x02}};
+mac_addr ospf1_addr = {{0x01, 0x00, 0x5e, 0x00, 0x00, 0x05}};
+mac_addr ospf2_addr = {{0x01, 0x00, 0x5e, 0x00, 0x00, 0x06}};
+mac_addr ripv2_addr = {{0x01, 0x00, 0x5e, 0x00, 0x00, 0x09}};
+mac_addr sys_addr = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
+
+int control_filter(unsigned char *dest)
+{
+    if ((!memcmp(dest, &upnp_addr, ETH_ALEN)) ||
+       (!memcmp(dest, &sys1_addr, ETH_ALEN)) ||
+       (!memcmp(dest, &sys2_addr, ETH_ALEN)) ||
+       (!memcmp(dest, &ospf1_addr, ETH_ALEN)) ||
+       (!memcmp(dest, &ospf2_addr, ETH_ALEN)) ||
+       (!memcmp(dest, &sys_addr, ETH_ALEN)) ||
+       (!memcmp(dest, &ripv2_addr, ETH_ALEN)))
+           return 0;
+    else
+       return 1;
+}
+
+int 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;
+       unsigned char tmp[6];
 
        if (!snooping)
                return 0;
 
-       if (skb->data[9] == 0x2) {
+       if ((snooping == SNOOPING_BLOCKING_MODE) && control_filter(dest))
+           status = 1;
+
+       if (skb->data[9] == IPPROTO_IGMP) {
            // For proxy; need to add some intelligence here 
            if (!br->proxy) {
-               if (skb->data[24] == 0x16)
+               if (skb->data[24] == IGMPV2_HOST_MEMBERSHIP_REPORT &&
+                   skb->protocol == __constant_htons(ETH_P_IP))
                    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 if (skb->data[24] == IGMP_HOST_LEAVE_MESSAGE) {
+                   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];
+                   br_mc_fdb_remove(br, skb->dev->br_port, tmp, skb->mac.ethernet->h_source);
                }
                else
                    ;
@@ -223,11 +253,11 @@ int br_handle_frame_finish(struct sk_buff *skb)
        if (dest[0] & 1) {
 #if defined(CONFIG_MIPS_BRCM)
                if (snooping && br->proxy) {
-                 if (skb->data[9] == 0x2) {
+                 if (skb->data[9] == IPPROTO_IGMP) {
                    char destS[16];
                    char srcS[16];
 
-                   if (skb->data[24] == 0x17) {
+                   if (skb->data[24] == IGMP_HOST_LEAVE_MESSAGE) {
                        unsigned char tmp[6];
                        
                        tmp[0] = 0x01;