Stephen Hemminger
2007-Apr-18 12:34 UTC
[Bridge] [PATCH] (9/11) bridge -- new ioctl interface for 32/64 compatiablity
Add four new ioctl's for the operations that can't be done through sysfs. The existing bridge ioctl's are multiplexed, and most go through SIOCDEVPRIVATE so they won't work in a mixed 32/64bit environment. The new release of bridge-utils will use these if possible, and fall back to the old interface. diff -Nru a/include/linux/if_bridge.h b/include/linux/if_bridge.h --- a/include/linux/if_bridge.h 2004-05-20 14:46:10 -07:00 +++ b/include/linux/if_bridge.h 2004-05-20 14:46:10 -07:00 @@ -104,7 +104,7 @@ #include <linux/netdevice.h> -extern void brioctl_set(int (*ioctl_hook)(unsigned long)); +extern void brioctl_set(int (*ioctl_hook)(unsigned int, unsigned long)); extern int (*br_handle_frame_hook)(struct sk_buff *skb); extern int (*br_should_route_hook)(struct sk_buff **pskb); diff -Nru a/include/linux/sockios.h b/include/linux/sockios.h --- a/include/linux/sockios.h 2004-05-20 14:46:10 -07:00 +++ b/include/linux/sockios.h 2004-05-20 14:46:10 -07:00 @@ -116,6 +116,12 @@ #define SIOCBONDINFOQUERY 0x8994 /* rtn info about bond state */ #define SIOCBONDCHANGEACTIVE 0x8995 /* update to a new active slave */ +/* bridge calls */ +#define SIOCBRADDBR 0x89a0 /* create new bridge device */ +#define SIOCBRDELBR 0x89a1 /* remove bridge device */ +#define SIOCBRADDIF 0x89a2 /* add interface to bridge */ +#define SIOCBRDELIF 0x89a3 /* remove interface from bridge */ + /* Device private ioctl calls */ /* diff -Nru a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c --- a/net/bridge/br_ioctl.c 2004-05-20 14:46:10 -07:00 +++ b/net/bridge/br_ioctl.c 2004-05-20 14:46:10 -07:00 @@ -78,13 +78,36 @@ return num; } -int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +static int add_del_if(struct net_bridge *br, int ifindex, int isadd) +{ + struct net_device *dev; + int ret; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + dev = dev_get_by_index(ifindex); + if (dev == NULL) + return -EINVAL; + + if (isadd) + ret = br_add_if(br, dev); + else + ret = br_del_if(br, dev); + + dev_put(dev); + return ret; +} + +/* + * Legacy ioctl's through SIOCDEVPRIVATE + * This interface is deprecated because it was too difficult to + * to do the translation for 32/64bit ioctl compatability. + */ +static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct net_bridge *br = netdev_priv(dev); unsigned long args[4]; - - if (cmd != SIOCDEVPRIVATE) - return -EOPNOTSUPP; if (copy_from_user(args, rq->ifr_data, sizeof(args))) return -EFAULT; @@ -92,25 +115,7 @@ switch (args[0]) { case BRCTL_ADD_IF: case BRCTL_DEL_IF: - { - struct net_device *dev; - int ret; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - dev = dev_get_by_index(args[1]); - if (dev == NULL) - return -EINVAL; - - if (args[0] == BRCTL_ADD_IF) - ret = br_add_if(br, dev); - else - ret = br_del_if(br, dev); - - dev_put(dev); - return ret; - } + return add_del_if(br, args[1], args[0] == BRCTL_ADD_IF); case BRCTL_GET_BRIDGE_INFO: { @@ -303,8 +308,7 @@ return -EOPNOTSUPP; } - -int br_ioctl_deviceless_stub(unsigned long uarg) +static int old_deviceless(unsigned long uarg) { unsigned long args[3]; @@ -354,5 +358,51 @@ } } + return -EOPNOTSUPP; +} + +int br_ioctl_deviceless_stub(unsigned int cmd, unsigned long uarg) +{ + switch (cmd) { + case SIOCGIFBR: + case SIOCSIFBR: + return old_deviceless(uarg); + + case SIOCBRADDBR: + case SIOCBRDELBR: + { + char buf[IFNAMSIZ]; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (copy_from_user(buf, (void __user *) uarg, IFNAMSIZ)) + return -EFAULT; + + buf[IFNAMSIZ-1] = 0; + if (cmd == SIOCBRADDBR) + return br_add_bridge(buf); + + return br_del_bridge(buf); + } + } + return -EOPNOTSUPP; +} + +int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct net_bridge *br = netdev_priv(dev); + + switch(cmd) { + case SIOCDEVPRIVATE: + return old_dev_ioctl(dev, rq, cmd); + + case SIOCBRADDIF: + case SIOCBRDELIF: + return add_del_if(br, rq->ifr_ifindex, cmd == SIOCBRADDIF); + + } + + printk(KERN_DEBUG "Bridge does not support ioctl 0x%x\n", cmd); return -EOPNOTSUPP; } diff -Nru a/net/bridge/br_private.h b/net/bridge/br_private.h --- a/net/bridge/br_private.h 2004-05-20 14:46:10 -07:00 +++ b/net/bridge/br_private.h 2004-05-20 14:46:10 -07:00 @@ -173,8 +173,8 @@ extern int br_handle_frame(struct sk_buff *skb); /* br_ioctl.c */ -extern int br_ioctl_deviceless_stub(unsigned long arg); extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +extern int br_ioctl_deviceless_stub(unsigned int cmd, unsigned long arg); /* br_netfilter.c */ extern int br_netfilter_init(void); diff -Nru a/net/core/dev.c b/net/core/dev.c --- a/net/core/dev.c 2004-05-20 14:46:10 -07:00 +++ b/net/core/dev.c 2004-05-20 14:46:10 -07:00 @@ -2519,6 +2519,8 @@ cmd == SIOCGMIIPHY || cmd == SIOCGMIIREG || cmd == SIOCSMIIREG || + cmd == SIOCBRADDIF || + cmd == SIOCBRDELIF || cmd == SIOCWANDEV) { err = -EOPNOTSUPP; if (dev->do_ioctl) { @@ -2673,6 +2675,8 @@ case SIOCBONDSLAVEINFOQUERY: case SIOCBONDINFOQUERY: case SIOCBONDCHANGEACTIVE: + case SIOCBRADDIF: + case SIOCBRDELIF: if (!capable(CAP_NET_ADMIN)) return -EPERM; dev_load(ifr.ifr_name); diff -Nru a/net/socket.c b/net/socket.c --- a/net/socket.c 2004-05-20 14:46:10 -07:00 +++ b/net/socket.c 2004-05-20 14:46:10 -07:00 @@ -727,9 +727,9 @@ */ static DECLARE_MUTEX(br_ioctl_mutex); -static int (*br_ioctl_hook)(unsigned long arg) = NULL; +static int (*br_ioctl_hook)(unsigned int cmd, unsigned long arg) = NULL; -void brioctl_set(int (*hook)(unsigned long)) +void brioctl_set(int (*hook)(unsigned int, unsigned long)) { down(&br_ioctl_mutex); br_ioctl_hook = hook; @@ -794,13 +794,15 @@ break; case SIOCGIFBR: case SIOCSIFBR: + case SIOCBRADDBR: + case SIOCBRDELBR: err = -ENOPKG; if (!br_ioctl_hook) request_module("bridge"); down(&br_ioctl_mutex); if (br_ioctl_hook) - err = br_ioctl_hook(arg); + err = br_ioctl_hook(cmd, arg); up(&br_ioctl_mutex); break; case SIOCGIFVLAN:
Possibly Parallel Threads
- [Bridge] [PATCH] (4/11) bridge - ioctl cleanup and consolidation
- [Bridge] [PATCH] net: bridge: Fix refcnt issues in dev_ioctl
- [Bridge] [PATCH 2.4] bridge - eliminate br_ioctl_mutex
- [Bridge] [2.6 patch] fix bridge <-> ATM compile error
- [Bridge] [PATCH] net: bridge: Fix refcnt issues in dev_ioctl