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 { /* associate netdev list */ struct mutex devlist_mtx; struct list_head netdev_list; + int devlist_generation; + int opencount; /* also protected by devlist_mtx */ + wait_queue_head_t dev_wait; /* BSSes/scanning */ spinlock_t bss_lock; @@ -57,6 +60,17 @@ struct cfg80211_registered_device { u32 bss_generation; struct cfg80211_scan_request *scan_req; /* protected by RTNL */ unsigned long suspend_at; + struct work_struct scan_done_wk; + +#ifdef CONFIG_NL80211_TESTMODE + struct genl_info *testmode_info; +#endif + + struct work_struct conn_work; + struct work_struct event_work; + + /* current channel */ + struct ieee80211_channel *channel; #ifdef CONFIG_CFG80211_DEBUGFS /* Debugfs entries */ @@ -89,13 +103,14 @@ bool wiphy_idx_valid(int wiphy_idx) } extern struct mutex cfg80211_mutex; -extern struct list_head cfg80211_drv_list; +extern struct list_head cfg80211_rdev_list; +extern int cfg80211_rdev_list_generation; #define assert_cfg80211_lock() WARN_ON(!mutex_is_locked(&cfg80211_mutex)) /* * You can use this to mark a wiphy_idx as not having an associated wiphy. - * It guarantees cfg80211_drv_by_wiphy_idx(wiphy_idx) will return NULL + * It guarantees cfg80211_rdev_by_wiphy_idx(wiphy_idx) will return NULL */ #define WIPHY_IDX_STALE -1 @@ -104,17 +119,40 @@ struct cfg80211_internal_bss { struct rb_node rbn; unsigned long ts; struct kref ref; - bool hold, ies_allocated; + atomic_t hold; + bool ies_allocated; /* must be last because of priv member */ struct cfg80211_bss pub; }; -struct cfg80211_registered_device *cfg80211_drv_by_wiphy_idx(int wiphy_idx); +static inline struct cfg80211_internal_bss *bss_from_pub(struct cfg80211_bss *pub) +{ + return container_of(pub, struct cfg80211_internal_bss, pub); +} + +static inline void cfg80211_ref_bss(struct cfg80211_internal_bss *bss) +{ + kref_get(&bss->ref); +} + +static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss) +{ + atomic_inc(&bss->hold); +} + +static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss) +{ + int r = atomic_dec_return(&bss->hold); + WARN_ON(r < 0); +} + + +struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx); int get_wiphy_idx(struct wiphy *wiphy); struct cfg80211_registered_device * -__cfg80211_drv_from_info(struct genl_info *info); +__cfg80211_rdev_from_info(struct genl_info *info); /* * This function returns a pointer to the driver @@ -122,12 +160,12 @@ __cfg80211_drv_from_info(struct genl_info *info); * If successful, it returns non-NULL and also locks * the driver's mutex! * - * This means that you need to call cfg80211_put_dev() + * This means that you need to call cfg80211_unlock_rdev() * before being allowed to acquire &cfg80211_mutex! * * This is necessary because we need to lock the global * mutex to get an item off the list safely, and then - * we lock the drv mutex so it doesn't go away under us. + * we lock the rdev mutex so it doesn't go away under us. * * We don't want to keep cfg80211_mutex locked * for all the time in order to allow requests on @@ -139,19 +177,93 @@ __cfg80211_drv_from_info(struct genl_info *info); extern struct cfg80211_registered_device * cfg80211_get_dev_from_info(struct genl_info *info); -/* requires cfg80211_drv_mutex to be held! */ +/* requires cfg80211_rdev_mutex to be held! */ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); /* identical to cfg80211_get_dev_from_info but only operate on ifindex */ extern struct cfg80211_registered_device * -cfg80211_get_dev_from_ifindex(int ifindex); +cfg80211_get_dev_from_ifindex(struct net *net, int ifindex); + +int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, + struct net *net); + +static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev) +{ + mutex_lock(&rdev->mtx); +} + +static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *rdev) +{ + BUG_ON(IS_ERR(rdev) || !rdev); + mutex_unlock(&rdev->mtx); +} + +static inline void wdev_lock(struct wireless_dev *wdev) + __acquires(wdev) +{ + mutex_lock(&wdev->mtx); + __acquire(wdev->mtx); +} + +static inline void wdev_unlock(struct wireless_dev *wdev) + __releases(wdev) +{ + __release(wdev->mtx); + mutex_unlock(&wdev->mtx); +} + +#define ASSERT_RDEV_LOCK(rdev) WARN_ON(!mutex_is_locked(&(rdev)->mtx)); +#define ASSERT_WDEV_LOCK(wdev) WARN_ON(!mutex_is_locked(&(wdev)->mtx)); + +enum cfg80211_event_type { + EVENT_CONNECT_RESULT, + EVENT_ROAMED, + EVENT_DISCONNECTED, + EVENT_IBSS_JOINED, +}; + +struct cfg80211_event { + struct list_head list; + enum cfg80211_event_type type; + + union { + struct { + u8 bssid[ETH_ALEN]; + const u8 *req_ie; + const u8 *resp_ie; + size_t req_ie_len; + size_t resp_ie_len; + u16 status; + } cr; + struct { + u8 bssid[ETH_ALEN]; + const u8 *req_ie; + const u8 *resp_ie; + size_t req_ie_len; + size_t resp_ie_len; + } rm; + struct { + const u8 *ie; + size_t ie_len; + u16 reason; + } dc; + struct { + u8 bssid[ETH_ALEN]; + } ij; + }; +}; + +struct cfg80211_cached_keys { + struct key_params params[6]; + u8 data[6][WLAN_MAX_KEY_LEN]; + int def, defmgmt; +}; -extern void cfg80211_put_dev(struct cfg80211_registered_device *drv); /* free object */ -extern void cfg80211_dev_free(struct cfg80211_registered_device *drv); +extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev); -extern int cfg80211_dev_rename(struct cfg80211_registered_device *drv, +extern int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, char *newname); void ieee80211_set_bitrate_flags(struct wiphy *wiphy); @@ -163,15 +275,124 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev, unsigned long age_secs); /* IBSS */ +int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct cfg80211_ibss_params *params, + struct cfg80211_cached_keys *connkeys); int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, struct net_device *dev, - struct cfg80211_ibss_params *params); + struct cfg80211_ibss_params *params, + struct cfg80211_cached_keys *connkeys); void cfg80211_clear_ibss(struct net_device *dev, bool nowext); int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, struct net_device *dev, bool nowext); +void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); +int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev); + +/* MLME */ +int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_auth_type auth_type, + const u8 *bssid, + const u8 *ssid, int ssid_len, + const u8 *ie, int ie_len, + const u8 *key, int key_len, int key_idx); +int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, + struct net_device *dev, struct ieee80211_channel *chan, + enum nl80211_auth_type auth_type, const u8 *bssid, + const u8 *ssid, int ssid_len, + const u8 *ie, int ie_len, + const u8 *key, int key_len, int key_idx); +int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct ieee80211_channel *chan, + const u8 *bssid, const u8 *prev_bssid, + const u8 *ssid, int ssid_len, + const u8 *ie, int ie_len, bool use_mfp, + struct cfg80211_crypto_settings *crypt); +int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, + struct net_device *dev, struct ieee80211_channel *chan, + const u8 *bssid, const u8 *prev_bssid, + const u8 *ssid, int ssid_len, + const u8 *ie, int ie_len, bool use_mfp, + struct cfg80211_crypto_settings *crypt); +int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *bssid, + const u8 *ie, int ie_len, u16 reason); +int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *bssid, + const u8 *ie, int ie_len, u16 reason); +int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *bssid, + const u8 *ie, int ie_len, u16 reason); +void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, + struct net_device *dev); +void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, + const u8 *req_ie, size_t req_ie_len, + const u8 *resp_ie, size_t resp_ie_len, + u16 status, bool wextev, + struct cfg80211_bss *bss); + +/* SME */ +int __cfg80211_connect(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct cfg80211_connect_params *connect, + struct cfg80211_cached_keys *connkeys, + const u8 *prev_bssid); +int cfg80211_connect(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct cfg80211_connect_params *connect, + struct cfg80211_cached_keys *connkeys); +int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, + struct net_device *dev, u16 reason, + bool wextev); +int cfg80211_disconnect(struct cfg80211_registered_device *rdev, + struct net_device *dev, u16 reason, + bool wextev); +void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, + const u8 *req_ie, size_t req_ie_len, + const u8 *resp_ie, size_t resp_ie_len); +int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev); + +void cfg80211_conn_work(struct work_struct *work); +bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev); /* internal helpers */ -int cfg80211_validate_key_settings(struct key_params *params, int key_idx, +int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, + struct key_params *params, int key_idx, const u8 *mac_addr); +void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, + size_t ie_len, u16 reason, bool from_ap); +void cfg80211_sme_scan_done(struct net_device *dev); +void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); +void cfg80211_sme_disassoc(struct net_device *dev, int idx); +void __cfg80211_scan_done(struct work_struct *wk); +void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak); +void cfg80211_upload_connect_keys(struct wireless_dev *wdev); +int cfg80211_change_iface(struct cfg80211_registered_device *rdev, + struct net_device *dev, enum nl80211_iftype ntype, + u32 *flags, struct vif_params *params); +void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); + +struct ieee80211_channel * +rdev_fixed_channel(struct cfg80211_registered_device *rdev, + struct wireless_dev *for_wdev); +int rdev_set_freq(struct cfg80211_registered_device *rdev, + struct wireless_dev *for_wdev, + int freq, enum nl80211_channel_type channel_type); + +#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS +#define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond) +#else +/* + * Trick to enable using it as a condition, + * and also not give a warning when it's + * not used that way. + */ +#define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; }) +#endif #endif /* __NET_WIRELESS_CORE_H */ |