diff options
Diffstat (limited to 'net/wireless/core.h')
-rw-r--r-- | net/wireless/core.h | 249 |
1 files changed, 235 insertions, 14 deletions
diff --git a/net/wireless/core.h b/net/wireless/core.h index bfa340c7abb5..2a33d8bc886b 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -49,6 +49,9 @@ struct cfg80211_registered_device { | |||
49 | /* associate netdev list */ | 49 | /* associate netdev list */ |
50 | struct mutex devlist_mtx; | 50 | struct mutex devlist_mtx; |
51 | struct list_head netdev_list; | 51 | struct list_head netdev_list; |
52 | int devlist_generation; | ||
53 | int opencount; /* also protected by devlist_mtx */ | ||
54 | wait_queue_head_t dev_wait; | ||
52 | 55 | ||
53 | /* BSSes/scanning */ | 56 | /* BSSes/scanning */ |
54 | spinlock_t bss_lock; | 57 | spinlock_t bss_lock; |
@@ -57,6 +60,17 @@ struct cfg80211_registered_device { | |||
57 | u32 bss_generation; | 60 | u32 bss_generation; |
58 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ | 61 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ |
59 | unsigned long suspend_at; | 62 | unsigned long suspend_at; |
63 | struct work_struct scan_done_wk; | ||
64 | |||
65 | #ifdef CONFIG_NL80211_TESTMODE | ||
66 | struct genl_info *testmode_info; | ||
67 | #endif | ||
68 | |||
69 | struct work_struct conn_work; | ||
70 | struct work_struct event_work; | ||
71 | |||
72 | /* current channel */ | ||
73 | struct ieee80211_channel *channel; | ||
60 | 74 | ||
61 | #ifdef CONFIG_CFG80211_DEBUGFS | 75 | #ifdef CONFIG_CFG80211_DEBUGFS |
62 | /* Debugfs entries */ | 76 | /* Debugfs entries */ |
@@ -89,13 +103,14 @@ bool wiphy_idx_valid(int wiphy_idx) | |||
89 | } | 103 | } |
90 | 104 | ||
91 | extern struct mutex cfg80211_mutex; | 105 | extern struct mutex cfg80211_mutex; |
92 | extern struct list_head cfg80211_drv_list; | 106 | extern struct list_head cfg80211_rdev_list; |
107 | extern int cfg80211_rdev_list_generation; | ||
93 | 108 | ||
94 | #define assert_cfg80211_lock() WARN_ON(!mutex_is_locked(&cfg80211_mutex)) | 109 | #define assert_cfg80211_lock() WARN_ON(!mutex_is_locked(&cfg80211_mutex)) |
95 | 110 | ||
96 | /* | 111 | /* |
97 | * You can use this to mark a wiphy_idx as not having an associated wiphy. | 112 | * You can use this to mark a wiphy_idx as not having an associated wiphy. |
98 | * It guarantees cfg80211_drv_by_wiphy_idx(wiphy_idx) will return NULL | 113 | * It guarantees cfg80211_rdev_by_wiphy_idx(wiphy_idx) will return NULL |
99 | */ | 114 | */ |
100 | #define WIPHY_IDX_STALE -1 | 115 | #define WIPHY_IDX_STALE -1 |
101 | 116 | ||
@@ -104,17 +119,40 @@ struct cfg80211_internal_bss { | |||
104 | struct rb_node rbn; | 119 | struct rb_node rbn; |
105 | unsigned long ts; | 120 | unsigned long ts; |
106 | struct kref ref; | 121 | struct kref ref; |
107 | bool hold, ies_allocated; | 122 | atomic_t hold; |
123 | bool ies_allocated; | ||
108 | 124 | ||
109 | /* must be last because of priv member */ | 125 | /* must be last because of priv member */ |
110 | struct cfg80211_bss pub; | 126 | struct cfg80211_bss pub; |
111 | }; | 127 | }; |
112 | 128 | ||
113 | struct cfg80211_registered_device *cfg80211_drv_by_wiphy_idx(int wiphy_idx); | 129 | static inline struct cfg80211_internal_bss *bss_from_pub(struct cfg80211_bss *pub) |
130 | { | ||
131 | return container_of(pub, struct cfg80211_internal_bss, pub); | ||
132 | } | ||
133 | |||
134 | static inline void cfg80211_ref_bss(struct cfg80211_internal_bss *bss) | ||
135 | { | ||
136 | kref_get(&bss->ref); | ||
137 | } | ||
138 | |||
139 | static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss) | ||
140 | { | ||
141 | atomic_inc(&bss->hold); | ||
142 | } | ||
143 | |||
144 | static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss) | ||
145 | { | ||
146 | int r = atomic_dec_return(&bss->hold); | ||
147 | WARN_ON(r < 0); | ||
148 | } | ||
149 | |||
150 | |||
151 | struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx); | ||
114 | int get_wiphy_idx(struct wiphy *wiphy); | 152 | int get_wiphy_idx(struct wiphy *wiphy); |
115 | 153 | ||
116 | struct cfg80211_registered_device * | 154 | struct cfg80211_registered_device * |
117 | __cfg80211_drv_from_info(struct genl_info *info); | 155 | __cfg80211_rdev_from_info(struct genl_info *info); |
118 | 156 | ||
119 | /* | 157 | /* |
120 | * This function returns a pointer to the driver | 158 | * This function returns a pointer to the driver |
@@ -122,12 +160,12 @@ __cfg80211_drv_from_info(struct genl_info *info); | |||
122 | * If successful, it returns non-NULL and also locks | 160 | * If successful, it returns non-NULL and also locks |
123 | * the driver's mutex! | 161 | * the driver's mutex! |
124 | * | 162 | * |
125 | * This means that you need to call cfg80211_put_dev() | 163 | * This means that you need to call cfg80211_unlock_rdev() |
126 | * before being allowed to acquire &cfg80211_mutex! | 164 | * before being allowed to acquire &cfg80211_mutex! |
127 | * | 165 | * |
128 | * This is necessary because we need to lock the global | 166 | * This is necessary because we need to lock the global |
129 | * mutex to get an item off the list safely, and then | 167 | * mutex to get an item off the list safely, and then |
130 | * we lock the drv mutex so it doesn't go away under us. | 168 | * we lock the rdev mutex so it doesn't go away under us. |
131 | * | 169 | * |
132 | * We don't want to keep cfg80211_mutex locked | 170 | * We don't want to keep cfg80211_mutex locked |
133 | * for all the time in order to allow requests on | 171 | * for all the time in order to allow requests on |
@@ -139,19 +177,93 @@ __cfg80211_drv_from_info(struct genl_info *info); | |||
139 | extern struct cfg80211_registered_device * | 177 | extern struct cfg80211_registered_device * |
140 | cfg80211_get_dev_from_info(struct genl_info *info); | 178 | cfg80211_get_dev_from_info(struct genl_info *info); |
141 | 179 | ||
142 | /* requires cfg80211_drv_mutex to be held! */ | 180 | /* requires cfg80211_rdev_mutex to be held! */ |
143 | struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); | 181 | struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); |
144 | 182 | ||
145 | /* identical to cfg80211_get_dev_from_info but only operate on ifindex */ | 183 | /* identical to cfg80211_get_dev_from_info but only operate on ifindex */ |
146 | extern struct cfg80211_registered_device * | 184 | extern struct cfg80211_registered_device * |
147 | cfg80211_get_dev_from_ifindex(int ifindex); | 185 | cfg80211_get_dev_from_ifindex(struct net *net, int ifindex); |
186 | |||
187 | int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, | ||
188 | struct net *net); | ||
189 | |||
190 | static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev) | ||
191 | { | ||
192 | mutex_lock(&rdev->mtx); | ||
193 | } | ||
194 | |||
195 | static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *rdev) | ||
196 | { | ||
197 | BUG_ON(IS_ERR(rdev) || !rdev); | ||
198 | mutex_unlock(&rdev->mtx); | ||
199 | } | ||
200 | |||
201 | static inline void wdev_lock(struct wireless_dev *wdev) | ||
202 | __acquires(wdev) | ||
203 | { | ||
204 | mutex_lock(&wdev->mtx); | ||
205 | __acquire(wdev->mtx); | ||
206 | } | ||
207 | |||
208 | static inline void wdev_unlock(struct wireless_dev *wdev) | ||
209 | __releases(wdev) | ||
210 | { | ||
211 | __release(wdev->mtx); | ||
212 | mutex_unlock(&wdev->mtx); | ||
213 | } | ||
214 | |||
215 | #define ASSERT_RDEV_LOCK(rdev) WARN_ON(!mutex_is_locked(&(rdev)->mtx)); | ||
216 | #define ASSERT_WDEV_LOCK(wdev) WARN_ON(!mutex_is_locked(&(wdev)->mtx)); | ||
217 | |||
218 | enum cfg80211_event_type { | ||
219 | EVENT_CONNECT_RESULT, | ||
220 | EVENT_ROAMED, | ||
221 | EVENT_DISCONNECTED, | ||
222 | EVENT_IBSS_JOINED, | ||
223 | }; | ||
224 | |||
225 | struct cfg80211_event { | ||
226 | struct list_head list; | ||
227 | enum cfg80211_event_type type; | ||
228 | |||
229 | union { | ||
230 | struct { | ||
231 | u8 bssid[ETH_ALEN]; | ||
232 | const u8 *req_ie; | ||
233 | const u8 *resp_ie; | ||
234 | size_t req_ie_len; | ||
235 | size_t resp_ie_len; | ||
236 | u16 status; | ||
237 | } cr; | ||
238 | struct { | ||
239 | u8 bssid[ETH_ALEN]; | ||
240 | const u8 *req_ie; | ||
241 | const u8 *resp_ie; | ||
242 | size_t req_ie_len; | ||
243 | size_t resp_ie_len; | ||
244 | } rm; | ||
245 | struct { | ||
246 | const u8 *ie; | ||
247 | size_t ie_len; | ||
248 | u16 reason; | ||
249 | } dc; | ||
250 | struct { | ||
251 | u8 bssid[ETH_ALEN]; | ||
252 | } ij; | ||
253 | }; | ||
254 | }; | ||
255 | |||
256 | struct cfg80211_cached_keys { | ||
257 | struct key_params params[6]; | ||
258 | u8 data[6][WLAN_MAX_KEY_LEN]; | ||
259 | int def, defmgmt; | ||
260 | }; | ||
148 | 261 | ||
149 | extern void cfg80211_put_dev(struct cfg80211_registered_device *drv); | ||
150 | 262 | ||
151 | /* free object */ | 263 | /* free object */ |
152 | extern void cfg80211_dev_free(struct cfg80211_registered_device *drv); | 264 | extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev); |
153 | 265 | ||
154 | extern int cfg80211_dev_rename(struct cfg80211_registered_device *drv, | 266 | extern int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, |
155 | char *newname); | 267 | char *newname); |
156 | 268 | ||
157 | void ieee80211_set_bitrate_flags(struct wiphy *wiphy); | 269 | void ieee80211_set_bitrate_flags(struct wiphy *wiphy); |
@@ -163,15 +275,124 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev, | |||
163 | unsigned long age_secs); | 275 | unsigned long age_secs); |
164 | 276 | ||
165 | /* IBSS */ | 277 | /* IBSS */ |
278 | int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | ||
279 | struct net_device *dev, | ||
280 | struct cfg80211_ibss_params *params, | ||
281 | struct cfg80211_cached_keys *connkeys); | ||
166 | int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 282 | int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, |
167 | struct net_device *dev, | 283 | struct net_device *dev, |
168 | struct cfg80211_ibss_params *params); | 284 | struct cfg80211_ibss_params *params, |
285 | struct cfg80211_cached_keys *connkeys); | ||
169 | void cfg80211_clear_ibss(struct net_device *dev, bool nowext); | 286 | void cfg80211_clear_ibss(struct net_device *dev, bool nowext); |
170 | int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | 287 | int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, |
171 | struct net_device *dev, bool nowext); | 288 | struct net_device *dev, bool nowext); |
289 | void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); | ||
290 | int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | ||
291 | struct wireless_dev *wdev); | ||
292 | |||
293 | /* MLME */ | ||
294 | int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | ||
295 | struct net_device *dev, | ||
296 | struct ieee80211_channel *chan, | ||
297 | enum nl80211_auth_type auth_type, | ||
298 | const u8 *bssid, | ||
299 | const u8 *ssid, int ssid_len, | ||
300 | const u8 *ie, int ie_len, | ||
301 | const u8 *key, int key_len, int key_idx); | ||
302 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | ||
303 | struct net_device *dev, struct ieee80211_channel *chan, | ||
304 | enum nl80211_auth_type auth_type, const u8 *bssid, | ||
305 | const u8 *ssid, int ssid_len, | ||
306 | const u8 *ie, int ie_len, | ||
307 | const u8 *key, int key_len, int key_idx); | ||
308 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | ||
309 | struct net_device *dev, | ||
310 | struct ieee80211_channel *chan, | ||
311 | const u8 *bssid, const u8 *prev_bssid, | ||
312 | const u8 *ssid, int ssid_len, | ||
313 | const u8 *ie, int ie_len, bool use_mfp, | ||
314 | struct cfg80211_crypto_settings *crypt); | ||
315 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | ||
316 | struct net_device *dev, struct ieee80211_channel *chan, | ||
317 | const u8 *bssid, const u8 *prev_bssid, | ||
318 | const u8 *ssid, int ssid_len, | ||
319 | const u8 *ie, int ie_len, bool use_mfp, | ||
320 | struct cfg80211_crypto_settings *crypt); | ||
321 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | ||
322 | struct net_device *dev, const u8 *bssid, | ||
323 | const u8 *ie, int ie_len, u16 reason); | ||
324 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | ||
325 | struct net_device *dev, const u8 *bssid, | ||
326 | const u8 *ie, int ie_len, u16 reason); | ||
327 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | ||
328 | struct net_device *dev, const u8 *bssid, | ||
329 | const u8 *ie, int ie_len, u16 reason); | ||
330 | void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | ||
331 | struct net_device *dev); | ||
332 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | ||
333 | const u8 *req_ie, size_t req_ie_len, | ||
334 | const u8 *resp_ie, size_t resp_ie_len, | ||
335 | u16 status, bool wextev, | ||
336 | struct cfg80211_bss *bss); | ||
337 | |||
338 | /* SME */ | ||
339 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, | ||
340 | struct net_device *dev, | ||
341 | struct cfg80211_connect_params *connect, | ||
342 | struct cfg80211_cached_keys *connkeys, | ||
343 | const u8 *prev_bssid); | ||
344 | int cfg80211_connect(struct cfg80211_registered_device *rdev, | ||
345 | struct net_device *dev, | ||
346 | struct cfg80211_connect_params *connect, | ||
347 | struct cfg80211_cached_keys *connkeys); | ||
348 | int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | ||
349 | struct net_device *dev, u16 reason, | ||
350 | bool wextev); | ||
351 | int cfg80211_disconnect(struct cfg80211_registered_device *rdev, | ||
352 | struct net_device *dev, u16 reason, | ||
353 | bool wextev); | ||
354 | void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, | ||
355 | const u8 *req_ie, size_t req_ie_len, | ||
356 | const u8 *resp_ie, size_t resp_ie_len); | ||
357 | int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, | ||
358 | struct wireless_dev *wdev); | ||
359 | |||
360 | void cfg80211_conn_work(struct work_struct *work); | ||
361 | bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev); | ||
172 | 362 | ||
173 | /* internal helpers */ | 363 | /* internal helpers */ |
174 | int cfg80211_validate_key_settings(struct key_params *params, int key_idx, | 364 | int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, |
365 | struct key_params *params, int key_idx, | ||
175 | const u8 *mac_addr); | 366 | const u8 *mac_addr); |
367 | void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | ||
368 | size_t ie_len, u16 reason, bool from_ap); | ||
369 | void cfg80211_sme_scan_done(struct net_device *dev); | ||
370 | void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); | ||
371 | void cfg80211_sme_disassoc(struct net_device *dev, int idx); | ||
372 | void __cfg80211_scan_done(struct work_struct *wk); | ||
373 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak); | ||
374 | void cfg80211_upload_connect_keys(struct wireless_dev *wdev); | ||
375 | int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | ||
376 | struct net_device *dev, enum nl80211_iftype ntype, | ||
377 | u32 *flags, struct vif_params *params); | ||
378 | void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); | ||
379 | |||
380 | struct ieee80211_channel * | ||
381 | rdev_fixed_channel(struct cfg80211_registered_device *rdev, | ||
382 | struct wireless_dev *for_wdev); | ||
383 | int rdev_set_freq(struct cfg80211_registered_device *rdev, | ||
384 | struct wireless_dev *for_wdev, | ||
385 | int freq, enum nl80211_channel_type channel_type); | ||
386 | |||
387 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS | ||
388 | #define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond) | ||
389 | #else | ||
390 | /* | ||
391 | * Trick to enable using it as a condition, | ||
392 | * and also not give a warning when it's | ||
393 | * not used that way. | ||
394 | */ | ||
395 | #define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; }) | ||
396 | #endif | ||
176 | 397 | ||
177 | #endif /* __NET_WIRELESS_CORE_H */ | 398 | #endif /* __NET_WIRELESS_CORE_H */ |