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 Inline Diff
net/mac80211/cfg.c
1 | /* | 1 | /* |
2 | * mac80211 configuration hooks for cfg80211 | 2 | * mac80211 configuration hooks for cfg80211 |
3 | * | 3 | * |
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> |
5 | * | 5 | * |
6 | * This file is GPLv2 as found in COPYING. | 6 | * This file is GPLv2 as found in COPYING. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/nl80211.h> | 9 | #include <linux/nl80211.h> |
10 | #include <linux/rtnetlink.h> | 10 | #include <linux/rtnetlink.h> |
11 | #include <net/net_namespace.h> | 11 | #include <net/net_namespace.h> |
12 | #include <net/cfg80211.h> | 12 | #include <net/cfg80211.h> |
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 | } |
44 | 48 | ||
45 | static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) | 49 | static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) |
46 | { | 50 | { |
47 | struct ieee80211_local *local = wiphy_priv(wiphy); | 51 | struct ieee80211_local *local = wiphy_priv(wiphy); |
48 | struct net_device *dev; | 52 | struct net_device *dev; |
49 | char *name; | 53 | char *name; |
50 | 54 | ||
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) |