Commit 42613db7605a68a70f97513137392bda9b27bb9e
Committed by
David S. Miller
1 parent
47f0c50220
Exists in
master
and in
7 other branches
[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
net/mac80211/cfg.c
... | ... | @@ -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 | }; |