netdev
[Top] [All Lists]

[PATCH 4/4] [bonding 2.4] Support old commands over new bonding ioctl

To: "Jeff Garzik" <jgarzik@xxxxxxxxx>, "Jay Vosburgh" <fubar@xxxxxxxxxx>
Subject: [PATCH 4/4] [bonding 2.4] Support old commands over new bonding ioctl
From: Amir Noam <amir.noam@xxxxxxxxx>
Date: Thu, 8 Jan 2004 18:25:53 +0200
Cc: <bonding-devel@xxxxxxxxxxxxxxxxxxxxx>, <netdev@xxxxxxxxxxx>
Sender: netdev-bounce@xxxxxxxxxxx
User-agent: KMail/1.5.3
Support old commands (enslave, release, change-active) over the new
bonding ioctl (SIOCBONDDEVICE).


diff -Nuarp a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
--- a/drivers/net/bonding/bond_main.c   Thu Jan  8 18:03:27 2004
+++ b/drivers/net/bonding/bond_main.c   Thu Jan  8 18:03:29 2004
@@ -1955,6 +1955,86 @@ static int bond_ethtool_ioctl(struct net
        }
 }
 
+static int bond_ioctl_slave_dev(struct bonding *bond, int cmd, void *addr)
+{
+       struct bond_ioctl_cmd bond_cmd;
+       struct net_device *slave_dev;
+       int prev_abi_ver = app_abi_ver;
+       int prev_orig_abi_ver = orig_app_abi_ver;
+       int res = 0;
+
+       if (copy_from_user(&bond_cmd, addr, sizeof(bond_cmd))) {
+               return -EFAULT;
+       }
+
+       bond_cmd.ifname[IFNAMSIZ - 1] = 0;
+
+       slave_dev = dev_get_by_name(bond_cmd.ifname);
+       if (!slave_dev) {
+               return -ENODEV;
+       }
+
+       /* This is for backward compatibility only.
+        * Unconditionaly set both global abi_ver vars so we can block
+        * old ioctls in bond_do_ioctl().
+        */
+       orig_app_abi_ver = bond_cmd.abi_ver;
+       app_abi_ver = bond_cmd.abi_ver;
+
+       switch (cmd) {
+       case BOND_CMD_ENSLAVE:
+               res = bond_enslave(bond->dev, slave_dev, bond_cmd.abi_ver);
+               break;
+
+       case BOND_CMD_RELEASE:
+               res = bond_release(bond->dev, slave_dev);
+               break;
+
+       case BOND_CMD_CHANGE_ACTIVE:
+               res = bond_ioctl_change_active(bond->dev, slave_dev);
+               break;
+
+       default:
+               res = -EOPNOTSUPP;
+               break;
+       }
+
+       dev_put(slave_dev);
+
+       if (res < 0) {
+               /* The ioctl failed, so there's no point in changing the
+                * orig_app_abi_ver. We'll restore it's value just in case
+                * we've changed it earlier in this function.
+                */
+               app_abi_ver = prev_abi_ver;
+               orig_app_abi_ver = prev_orig_abi_ver;
+       }
+
+       return res;
+}
+
+static int bond_ioctl_device(struct bonding *bond, void *addr)
+{
+       u32 cmd;
+
+       if (get_user(cmd, (u32 *) addr)) {
+               return -EFAULT;
+       }
+
+       switch (cmd) {
+       case BOND_CMD_ENSLAVE:
+       case BOND_CMD_RELEASE:
+       case BOND_CMD_CHANGE_ACTIVE:
+               /* these ioctl cmds receive a slave name as an arg */
+               return bond_ioctl_slave_dev(bond, cmd, addr);
+
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
 static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
 {
        struct bonding *bond = bond_dev->priv;
@@ -3214,6 +3294,7 @@ static struct net_device_stats *bond_get
 
 static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int 
cmd)
 {
+       struct bonding *bond = bond_dev->priv;
        struct net_device *slave_dev = NULL;
        struct ifbond *u_binfo = NULL, k_binfo;
        struct ifslave *u_sinfo = NULL, k_sinfo;
@@ -3224,6 +3305,10 @@ static int bond_do_ioctl(struct net_devi
        dprintk("bond_ioctl: master=%s, cmd=%d\n",
                bond_dev->name, cmd);
 
+       if (!capable(CAP_NET_ADMIN)) {
+               return -EPERM;
+       }
+
        switch (cmd) {
        case SIOCETHTOOL:
                return bond_ethtool_ioctl(bond_dev, ifr);
@@ -3245,7 +3330,6 @@ static int bond_do_ioctl(struct net_devi
                }
 
                if (mii->reg_num == 1) {
-                       struct bonding *bond = bond_dev->priv;
                        mii->val_out = 0;
                        read_lock_bh(&bond->lock);
                        read_lock(&bond->curr_slave_lock);
@@ -3289,13 +3373,19 @@ static int bond_do_ioctl(struct net_devi
                }
 
                return res;
+       case SIOCBONDDEVICE:
+               return bond_ioctl_device(bond, ifr->ifr_data);
+
        default:
                /* Go on */
                break;
        }
 
-       if (!capable(CAP_NET_ADMIN)) {
-               return -EPERM;
+       if (orig_app_abi_ver > 2) {
+               /* Refuse to support old ioctls if the app has already
+                * declared it is new enough for SIOCBONDDEVICE commands.
+                */
+               return -EOPNOTSUPP;
        }
 
        if (orig_app_abi_ver == -1) {
diff -Nuarp a/include/linux/if_bonding.h b/include/linux/if_bonding.h
--- a/include/linux/if_bonding.h        Thu Jan  8 18:03:27 2004
+++ b/include/linux/if_bonding.h        Thu Jan  8 18:03:29 2004
@@ -112,6 +112,9 @@ struct ad_info {
 #define BOND_CMD_DRV_INFO      0x00000001
 #define BOND_CMD_ADD_BOND      0x00000002
 #define BOND_CMD_DEL_BOND      0x00000003
+#define BOND_CMD_ENSLAVE       0x00000004
+#define BOND_CMD_RELEASE       0x00000005
+#define BOND_CMD_CHANGE_ACTIVE 0x00000006
 
 /**
  * bond_ioctl_drv_info
@@ -127,6 +130,19 @@ struct bond_ioctl_drv_info {
        char reserved[32];
 };
 
+/**
+ * bond_ioctl_cmd
+ *
+ * %BOND_CMD_ENSLAVE, %BOND_CMD_RELEASE and %BOND_CMD_CHANGE_ACTIVE pass the
+ * name of the slave to work on in @ifname.
+ */
+struct bond_ioctl_cmd {
+       __u32 cmd;
+       __u32 abi_ver;
+       __u32 num_prms;
+       char ifname[IFNAMSIZ];
+};
+
 #endif /* _LINUX_IF_BONDING_H */
 
 /*


<Prev in Thread] Current Thread [Next in Thread>
  • [PATCH 4/4] [bonding 2.4] Support old commands over new bonding ioctl, Amir Noam <=