xref: /linux/net/mac80211/cfg.c (revision 2b8232ce512105e28453f301d1510de8363bccd1)
1 /*
2  * mac80211 configuration hooks for cfg80211
3  *
4  * Copyright 2006	Johannes Berg <johannes@sipsolutions.net>
5  *
6  * This file is GPLv2 as found in COPYING.
7  */
8 
9 #include <linux/nl80211.h>
10 #include <linux/rtnetlink.h>
11 #include <net/net_namespace.h>
12 #include <net/cfg80211.h>
13 #include "ieee80211_i.h"
14 #include "cfg.h"
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 
33 static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
34 			       enum nl80211_iftype type)
35 {
36 	struct ieee80211_local *local = wiphy_priv(wiphy);
37 	enum ieee80211_if_types itype;
38 
39 	if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
40 		return -ENODEV;
41 
42 	itype = nl80211_type_to_mac80211_type(type);
43 	if (itype == IEEE80211_IF_TYPE_INVALID)
44 		return -EINVAL;
45 
46 	return ieee80211_if_add(local->mdev, name, NULL, itype);
47 }
48 
49 static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
50 {
51 	struct ieee80211_local *local = wiphy_priv(wiphy);
52 	struct net_device *dev;
53 	char *name;
54 
55 	if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
56 		return -ENODEV;
57 
58 	/* we're under RTNL */
59 	dev = __dev_get_by_index(&init_net, ifindex);
60 	if (!dev)
61 		return 0;
62 
63 	name = dev->name;
64 
65 	return ieee80211_if_remove(local->mdev, name, -1);
66 }
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 
102 struct cfg80211_ops mac80211_config_ops = {
103 	.add_virtual_intf = ieee80211_add_iface,
104 	.del_virtual_intf = ieee80211_del_iface,
105 	.change_virtual_intf = ieee80211_change_iface,
106 };
107