X-Git-Url: http://git.rot13.org/?p=bcm963xx.git;a=blobdiff_plain;f=kernel%2Flinux%2Fnet%2Fbridge%2Fbr_ioctl.c;h=f296a55b67f11d166b0aa361e8b759422bff6dd0;hp=363c73f28b9b0556c7adb8c074aa165961af45d6;hb=57a096f051259ceaefd5977f30d269884e1dd248;hpb=9887430fc6b7c0f8eb8e81de2bfe3bba12d8d4a1;ds=sidebyside diff --git a/kernel/linux/net/bridge/br_ioctl.c b/kernel/linux/net/bridge/br_ioctl.c index 363c73f2..f296a55b 100755 --- a/kernel/linux/net/bridge/br_ioctl.c +++ b/kernel/linux/net/bridge/br_ioctl.c @@ -20,6 +20,14 @@ #include #include "br_private.h" +#if defined(CONFIG_MIPS_BRCM) +#define BRCTL_SET_PORT_SNOOPING 21 +#define BRCTL_CLEAR_PORT_SNOOPING 22 +#define BRCTL_ENABLE_SNOOPING 23 +#define BRCTL_SHOW_SNOOPING 24 +#define SIOCBRSHOWSNOOPING 24 +#endif + /* called with RTNL */ static int get_bridge_ifindices(int *indices, int num) { @@ -45,6 +53,31 @@ static void get_port_ifindices(struct net_bridge *br, int *ifindices, int num) } } +#if defined(CONFIG_MIPS_BRCM) +void br_set_port_snooping(struct net_bridge_port *p, void __user * userbuf) +{ + unsigned char tmp[26]; + + if (copy_from_user(tmp, userbuf, sizeof(tmp))) + return -EFAULT; + br_mc_fdb_add(p->br, p, tmp, tmp+6); +} + +void br_clear_port_snooping(struct net_bridge_port *p, void __user * userbuf) +{ + unsigned char tmp[26]; + unsigned char all[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + if (copy_from_user(tmp, userbuf, sizeof(tmp))) + return -EFAULT; + p->br->proxy = 1; + if (!memcmp(tmp+6, all, 6)) + br_mc_fdb_remove_grp(p->br, p, tmp); + else + br_mc_fdb_remove(p->br, p, tmp, tmp+6); +} +#endif + /* * Format up to a page worth of forwarding table entries * userbuf -- where to copy result @@ -283,6 +316,42 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return ret; } +#if defined(CONFIG_MIPS_BRCM) + case BRCTL_SET_PORT_SNOOPING: + { + struct net_bridge_port *p; + int ret = 0; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + spin_lock_bh(&br->lock); + if ((p = br_get_port(br, args[1])) == NULL) + ret = -EINVAL; + else + br_set_port_snooping(p, args[2]); + spin_unlock_bh(&br->lock); + return ret; + } + + case BRCTL_CLEAR_PORT_SNOOPING: + { + struct net_bridge_port *p; + int ret = 0; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + spin_lock_bh(&br->lock); + if ((p = br_get_port(br, args[1])) == NULL) + ret = -EINVAL; + else + br_clear_port_snooping(p, args[2]); + spin_unlock_bh(&br->lock); + return ret; + } +#endif + case BRCTL_SET_PATH_COST: { struct net_bridge_port *p; @@ -356,6 +425,38 @@ static int old_deviceless(void __user *uarg) return br_del_bridge(buf); } + +#if defined(CONFIG_MIPS_BRCM) + case BRCTL_SHOW_SNOOPING: + { + char buf[IFNAMSIZ]; + struct net_device *dev; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (copy_from_user(buf, (void __user *)args[1], IFNAMSIZ)) + return -EFAULT; + + buf[IFNAMSIZ-1] = 0; + + dev = __dev_get_by_name(buf); + if (dev == NULL) + return -ENXIO; /* Could not find device */ + dolist(netdev_priv(dev)); + + return 0; + } + + case BRCTL_ENABLE_SNOOPING: + { + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + snooping = args[1]; + return 0; + } +#endif } return -EOPNOTSUPP; @@ -385,6 +486,28 @@ int br_ioctl_deviceless_stub(unsigned int cmd, void __user *uarg) return br_del_bridge(buf); } +#if defined(CONFIG_MIPS_BRCM) + case SIOCBRSHOWSNOOPING: + { + char buf[IFNAMSIZ]; + struct net_device *dev; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (copy_from_user(buf, uarg, IFNAMSIZ)) + return -EFAULT; + + buf[IFNAMSIZ-1] = 0; + + dev = __dev_get_by_name(buf); + if (dev == NULL) + return -ENXIO; /* Could not find device */ + dolist(netdev_priv(dev)); + + return 0; + } +#endif } return -EOPNOTSUPP; } @@ -406,3 +529,4 @@ int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) pr_debug("Bridge does not support ioctl 0x%x\n", cmd); return -EOPNOTSUPP; } +