aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/core.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2007-09-20 13:09:35 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:52:14 -0400
commit556829657397b9b05baec6691ead4e22ee8d1567 (patch)
tree44242431553e5e22c0bceaab7a06d9d7bf0dd2f6 /net/wireless/core.c
parent0800f170263d19b882e519441156c5f6ed190fc1 (diff)
[NL80211]: add netlink interface to cfg80211
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/wireless/core.c')
-rw-r--r--net/wireless/core.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 9771451eae21..febc33bc9c09 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -16,6 +16,7 @@
16#include <net/genetlink.h> 16#include <net/genetlink.h>
17#include <net/cfg80211.h> 17#include <net/cfg80211.h>
18#include <net/wireless.h> 18#include <net/wireless.h>
19#include "nl80211.h"
19#include "core.h" 20#include "core.h"
20#include "sysfs.h" 21#include "sysfs.h"
21 22
@@ -36,6 +37,146 @@ static int wiphy_counter;
36/* for debugfs */ 37/* for debugfs */
37static struct dentry *ieee80211_debugfs_dir; 38static struct dentry *ieee80211_debugfs_dir;
38 39
40/* requires cfg80211_drv_mutex to be held! */
41static struct cfg80211_registered_device *cfg80211_drv_by_wiphy(int wiphy)
42{
43 struct cfg80211_registered_device *result = NULL, *drv;
44
45 list_for_each_entry(drv, &cfg80211_drv_list, list) {
46 if (drv->idx == wiphy) {
47 result = drv;
48 break;
49 }
50 }
51
52 return result;
53}
54
55/* requires cfg80211_drv_mutex to be held! */
56static struct cfg80211_registered_device *
57__cfg80211_drv_from_info(struct genl_info *info)
58{
59 int ifindex;
60 struct cfg80211_registered_device *bywiphy = NULL, *byifidx = NULL;
61 struct net_device *dev;
62 int err = -EINVAL;
63
64 if (info->attrs[NL80211_ATTR_WIPHY]) {
65 bywiphy = cfg80211_drv_by_wiphy(
66 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY]));
67 err = -ENODEV;
68 }
69
70 if (info->attrs[NL80211_ATTR_IFINDEX]) {
71 ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
72 dev = dev_get_by_index(&init_net, ifindex);
73 if (dev) {
74 if (dev->ieee80211_ptr)
75 byifidx =
76 wiphy_to_dev(dev->ieee80211_ptr->wiphy);
77 dev_put(dev);
78 }
79 err = -ENODEV;
80 }
81
82 if (bywiphy && byifidx) {
83 if (bywiphy != byifidx)
84 return ERR_PTR(-EINVAL);
85 else
86 return bywiphy; /* == byifidx */
87 }
88 if (bywiphy)
89 return bywiphy;
90
91 if (byifidx)
92 return byifidx;
93
94 return ERR_PTR(err);
95}
96
97struct cfg80211_registered_device *
98cfg80211_get_dev_from_info(struct genl_info *info)
99{
100 struct cfg80211_registered_device *drv;
101
102 mutex_lock(&cfg80211_drv_mutex);
103 drv = __cfg80211_drv_from_info(info);
104
105 /* if it is not an error we grab the lock on
106 * it to assure it won't be going away while
107 * we operate on it */
108 if (!IS_ERR(drv))
109 mutex_lock(&drv->mtx);
110
111 mutex_unlock(&cfg80211_drv_mutex);
112
113 return drv;
114}
115
116struct cfg80211_registered_device *
117cfg80211_get_dev_from_ifindex(int ifindex)
118{
119 struct cfg80211_registered_device *drv = ERR_PTR(-ENODEV);
120 struct net_device *dev;
121
122 mutex_lock(&cfg80211_drv_mutex);
123 dev = dev_get_by_index(&init_net, ifindex);
124 if (!dev)
125 goto out;
126 if (dev->ieee80211_ptr) {
127 drv = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
128 mutex_lock(&drv->mtx);
129 } else
130 drv = ERR_PTR(-ENODEV);
131 dev_put(dev);
132 out:
133 mutex_unlock(&cfg80211_drv_mutex);
134 return drv;
135}
136
137void cfg80211_put_dev(struct cfg80211_registered_device *drv)
138{
139 BUG_ON(IS_ERR(drv));
140 mutex_unlock(&drv->mtx);
141}
142
143int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
144 char *newname)
145{
146 int idx, taken = -1, result, digits;
147
148 /* prohibit calling the thing phy%d when %d is not its number */
149 sscanf(newname, PHY_NAME "%d%n", &idx, &taken);
150 if (taken == strlen(newname) && idx != rdev->idx) {
151 /* count number of places needed to print idx */
152 digits = 1;
153 while (idx /= 10)
154 digits++;
155 /*
156 * deny the name if it is phy<idx> where <idx> is printed
157 * without leading zeroes. taken == strlen(newname) here
158 */
159 if (taken == strlen(PHY_NAME) + digits)
160 return -EINVAL;
161 }
162
163 /* this will check for collisions */
164 result = device_rename(&rdev->wiphy.dev, newname);
165 if (result)
166 return result;
167
168 if (!debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
169 rdev->wiphy.debugfsdir,
170 rdev->wiphy.debugfsdir->d_parent,
171 newname))
172 printk(KERN_ERR "cfg80211: failed to rename debugfs dir to %s!\n",
173 newname);
174
175 nl80211_notify_dev_rename(rdev);
176
177 return 0;
178}
179
39/* exported functions */ 180/* exported functions */
40 181
41struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) 182struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)
@@ -204,10 +345,16 @@ static int cfg80211_init(void)
204 if (err) 345 if (err)
205 goto out_fail_notifier; 346 goto out_fail_notifier;
206 347
348 err = nl80211_init();
349 if (err)
350 goto out_fail_nl80211;
351
207 ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL); 352 ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL);
208 353
209 return 0; 354 return 0;
210 355
356out_fail_nl80211:
357 unregister_netdevice_notifier(&cfg80211_netdev_notifier);
211out_fail_notifier: 358out_fail_notifier:
212 wiphy_sysfs_exit(); 359 wiphy_sysfs_exit();
213out_fail_sysfs: 360out_fail_sysfs:
@@ -218,6 +365,7 @@ subsys_initcall(cfg80211_init);
218static void cfg80211_exit(void) 365static void cfg80211_exit(void)
219{ 366{
220 debugfs_remove(ieee80211_debugfs_dir); 367 debugfs_remove(ieee80211_debugfs_dir);
368 nl80211_exit();
221 unregister_netdevice_notifier(&cfg80211_netdev_notifier); 369 unregister_netdevice_notifier(&cfg80211_netdev_notifier);
222 wiphy_sysfs_exit(); 370 wiphy_sysfs_exit();
223} 371}