diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2007-09-28 15:52:27 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:54:20 -0400 |
commit | 42613db7605a68a70f97513137392bda9b27bb9e (patch) | |
tree | 28fc28d9977269b7a4129db4483052c11df7e33e /net | |
parent | 47f0c502209056da728e6a306a43d5e19a37f4fa (diff) |
[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>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/cfg.c | 75 |
1 files changed, 57 insertions, 18 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6981ba178e19..9e2bc1fd0237 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -13,31 +13,35 @@ | |||
13 | #include "ieee80211_i.h" | 13 | #include "ieee80211_i.h" |
14 | #include "cfg.h" | 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 | static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | 33 | static int ieee80211_add_iface(struct wiphy *wiphy, char *name, |
17 | enum nl80211_iftype type) | 34 | enum nl80211_iftype type) |
18 | { | 35 | { |
19 | struct ieee80211_local *local = wiphy_priv(wiphy); | 36 | struct ieee80211_local *local = wiphy_priv(wiphy); |
20 | int itype; | 37 | enum ieee80211_if_types itype; |
21 | 38 | ||
22 | if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) | 39 | if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) |
23 | return -ENODEV; | 40 | return -ENODEV; |
24 | 41 | ||
25 | switch (type) { | 42 | itype = nl80211_type_to_mac80211_type(type); |
26 | case NL80211_IFTYPE_UNSPECIFIED: | 43 | if (itype == IEEE80211_IF_TYPE_INVALID) |
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: | ||
39 | return -EINVAL; | 44 | return -EINVAL; |
40 | } | ||
41 | 45 | ||
42 | return ieee80211_if_add(local->mdev, name, NULL, itype); | 46 | return ieee80211_if_add(local->mdev, name, NULL, itype); |
43 | } | 47 | } |
@@ -51,17 +55,52 @@ static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) | |||
51 | if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) | 55 | if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) |
52 | return -ENODEV; | 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 | if (!dev) | 60 | if (!dev) |
56 | return 0; | 61 | return 0; |
57 | 62 | ||
58 | name = dev->name; | 63 | name = dev->name; |
59 | dev_put(dev); | ||
60 | 64 | ||
61 | return ieee80211_if_remove(local->mdev, name, -1); | 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 | struct cfg80211_ops mac80211_config_ops = { | 102 | struct cfg80211_ops mac80211_config_ops = { |
65 | .add_virtual_intf = ieee80211_add_iface, | 103 | .add_virtual_intf = ieee80211_add_iface, |
66 | .del_virtual_intf = ieee80211_del_iface, | 104 | .del_virtual_intf = ieee80211_del_iface, |
105 | .change_virtual_intf = ieee80211_change_iface, | ||
67 | }; | 106 | }; |