Commit 42613db7605a68a70f97513137392bda9b27bb9e

Authored by Johannes Berg
Committed by David S. Miller
1 parent 47f0c50220

[MAC80211]: implement cfg80211's change_interface hook

This implements the cfg80211 change_interface hook that changes the
type of an interface and cleans up the code a bit.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 1 changed file with 57 additions and 18 deletions Side-by-side Diff

... ... @@ -13,31 +13,35 @@
13 13 #include "ieee80211_i.h"
14 14 #include "cfg.h"
15 15  
  16 +static enum ieee80211_if_types
  17 +nl80211_type_to_mac80211_type(enum nl80211_iftype type)
  18 +{
  19 + switch (type) {
  20 + case NL80211_IFTYPE_UNSPECIFIED:
  21 + return IEEE80211_IF_TYPE_STA;
  22 + case NL80211_IFTYPE_ADHOC:
  23 + return IEEE80211_IF_TYPE_IBSS;
  24 + case NL80211_IFTYPE_STATION:
  25 + return IEEE80211_IF_TYPE_STA;
  26 + case NL80211_IFTYPE_MONITOR:
  27 + return IEEE80211_IF_TYPE_MNTR;
  28 + default:
  29 + return IEEE80211_IF_TYPE_INVALID;
  30 + }
  31 +}
  32 +
16 33 static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
17 34 enum nl80211_iftype type)
18 35 {
19 36 struct ieee80211_local *local = wiphy_priv(wiphy);
20   - int itype;
  37 + enum ieee80211_if_types itype;
21 38  
22 39 if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
23 40 return -ENODEV;
24 41  
25   - switch (type) {
26   - case NL80211_IFTYPE_UNSPECIFIED:
27   - itype = IEEE80211_IF_TYPE_STA;
28   - break;
29   - case NL80211_IFTYPE_ADHOC:
30   - itype = IEEE80211_IF_TYPE_IBSS;
31   - break;
32   - case NL80211_IFTYPE_STATION:
33   - itype = IEEE80211_IF_TYPE_STA;
34   - break;
35   - case NL80211_IFTYPE_MONITOR:
36   - itype = IEEE80211_IF_TYPE_MNTR;
37   - break;
38   - default:
  42 + itype = nl80211_type_to_mac80211_type(type);
  43 + if (itype == IEEE80211_IF_TYPE_INVALID)
39 44 return -EINVAL;
40   - }
41 45  
42 46 return ieee80211_if_add(local->mdev, name, NULL, itype);
43 47 }
44 48  
45 49  
46 50  
... ... @@ -51,18 +55,53 @@
51 55 if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
52 56 return -ENODEV;
53 57  
54   - dev = dev_get_by_index(&init_net, ifindex);
  58 + /* we're under RTNL */
  59 + dev = __dev_get_by_index(&init_net, ifindex);
55 60 if (!dev)
56 61 return 0;
57 62  
58 63 name = dev->name;
59   - dev_put(dev);
60 64  
61 65 return ieee80211_if_remove(local->mdev, name, -1);
62 66 }
63 67  
  68 +static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
  69 + enum nl80211_iftype type)
  70 +{
  71 + struct ieee80211_local *local = wiphy_priv(wiphy);
  72 + struct net_device *dev;
  73 + enum ieee80211_if_types itype;
  74 + struct ieee80211_sub_if_data *sdata;
  75 +
  76 + if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
  77 + return -ENODEV;
  78 +
  79 + /* we're under RTNL */
  80 + dev = __dev_get_by_index(&init_net, ifindex);
  81 + if (!dev)
  82 + return -ENODEV;
  83 +
  84 + if (netif_running(dev))
  85 + return -EBUSY;
  86 +
  87 + itype = nl80211_type_to_mac80211_type(type);
  88 + if (itype == IEEE80211_IF_TYPE_INVALID)
  89 + return -EINVAL;
  90 +
  91 + sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  92 +
  93 + if (sdata->type == IEEE80211_IF_TYPE_VLAN)
  94 + return -EOPNOTSUPP;
  95 +
  96 + ieee80211_if_reinit(dev);
  97 + ieee80211_if_set_type(dev, itype);
  98 +
  99 + return 0;
  100 +}
  101 +
64 102 struct cfg80211_ops mac80211_config_ops = {
65 103 .add_virtual_intf = ieee80211_add_iface,
66 104 .del_virtual_intf = ieee80211_del_iface,
  105 + .change_virtual_intf = ieee80211_change_iface,
67 106 };