]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/wireless/nl80211.c
Merge branch 'omap-clock-fixes' of git://git.pwsan.com/linux-2.6
[linux-2.6-omap-h63xx.git] / net / wireless / nl80211.c
index 6bb73a3a3391f6e15b3a7baa6d8e30e459e63403..353e1a4ece836423dd503e55becc7cbffd4a2812 100644 (file)
@@ -366,16 +366,26 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
        int result = 0, rem_txq_params = 0;
        struct nlattr *nl_txq_params;
 
-       rdev = cfg80211_get_dev_from_info(info);
-       if (IS_ERR(rdev))
-               return PTR_ERR(rdev);
+       rtnl_lock();
+
+       mutex_lock(&cfg80211_mutex);
 
-       if (info->attrs[NL80211_ATTR_WIPHY_NAME]) {
+       rdev = __cfg80211_drv_from_info(info);
+       if (IS_ERR(rdev)) {
+               result = PTR_ERR(rdev);
+               goto unlock;
+       }
+
+       mutex_lock(&rdev->mtx);
+
+       if (info->attrs[NL80211_ATTR_WIPHY_NAME])
                result = cfg80211_dev_rename(
                        rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
-               if (result)
-                       goto bad_res;
-       }
+
+       mutex_unlock(&cfg80211_mutex);
+
+       if (result)
+               goto bad_res;
 
        if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
                struct ieee80211_txq_params txq_params;
@@ -471,7 +481,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 
 
  bad_res:
-       cfg80211_put_dev(rdev);
+       mutex_unlock(&rdev->mtx);
+ unlock:
+       rtnl_unlock();
        return result;
 }
 
@@ -607,6 +619,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
        enum nl80211_iftype type;
        struct net_device *dev;
        u32 _flags, *flags = NULL;
+       bool change = false;
 
        memset(&params, 0, sizeof(params));
 
@@ -620,11 +633,17 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
        type = dev->ieee80211_ptr->iftype;
        dev_put(dev);
 
-       err = -EINVAL;
        if (info->attrs[NL80211_ATTR_IFTYPE]) {
-               type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
-               if (type > NL80211_IFTYPE_MAX)
+               enum nl80211_iftype ntype;
+
+               ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
+               if (type != ntype)
+                       change = true;
+               type = ntype;
+               if (type > NL80211_IFTYPE_MAX) {
+                       err = -EINVAL;
                        goto unlock;
+               }
        }
 
        if (!drv->ops->change_virtual_intf ||
@@ -640,6 +659,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
                }
                params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
                params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
+               change = true;
        }
 
        if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
@@ -649,12 +669,18 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
                }
                err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
                                          &_flags);
-               if (!err)
-                       flags = &_flags;
+               if (err)
+                       goto unlock;
+
+               flags = &_flags;
+               change = true;
        }
 
-       err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
-                                           type, flags, &params);
+       if (change)
+               err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
+                                                   type, flags, &params);
+       else
+               err = 0;
 
        dev = __dev_get_by_index(&init_net, ifindex);
        WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type));
@@ -1049,6 +1075,11 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
        if (err)
                goto unlock_rtnl;
 
+       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+
        switch (info->genlhdr->cmd) {
        case NL80211_CMD_NEW_BEACON:
                /* these are required for NEW_BEACON */
@@ -1136,6 +1167,10 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
+       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
+               err = -EOPNOTSUPP;
+               goto out;
+       }
        err = drv->ops->del_beacon(&drv->wiphy, dev);
 
  out:
@@ -1324,7 +1359,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
        }
 
        if (!dev->ops->dump_station) {
-               err = -ENOSYS;
+               err = -EOPNOTSUPP;
                goto out_err;
        }
 
@@ -1698,10 +1733,15 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
        }
 
        if (!dev->ops->dump_mpath) {
-               err = -ENOSYS;
+               err = -EOPNOTSUPP;
                goto out_err;
        }
 
+       if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+
        while (1) {
                err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx,
                                           dst, next_hop, &pinfo);
@@ -1759,6 +1799,11 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
+       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+
        err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo);
        if (err)
                goto out;
@@ -1813,6 +1858,11 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
+       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+
        if (!netif_running(dev)) {
                err = -ENETDOWN;
                goto out;
@@ -1856,6 +1906,11 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
+       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+
        if (!netif_running(dev)) {
                err = -ENETDOWN;
                goto out;
@@ -1944,6 +1999,11 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
+       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+
        err = drv->ops->change_bss(&drv->wiphy, dev, &params);
 
  out:
@@ -2661,6 +2721,11 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
+       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+
        if (!netif_running(dev)) {
                err = -ENETDOWN;
                goto out;
@@ -2734,6 +2799,11 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
+       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+
        if (!netif_running(dev)) {
                err = -ENETDOWN;
                goto out;
@@ -2797,6 +2867,11 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
+       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+
        if (!netif_running(dev)) {
                err = -ENETDOWN;
                goto out;
@@ -2856,6 +2931,11 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
+       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+
        if (!netif_running(dev)) {
                err = -ENETDOWN;
                goto out;