Skip to content

Commit

Permalink
cfg80211/nl80211: add IBSS API
Browse files Browse the repository at this point in the history
This adds IBSS API along with (preliminary) wext handlers.
The wext handlers can only do IBSS so you need to call them
from your own wext handlers if the mode is IBSS.

The nl80211 API requires
 * an SSID
 * a channel (frequency) for the case that a new IBSS
   has to be created

It optionally supports
 * a flag to fix the channel
 * a fixed BSSID

The cfg80211 code also takes care to leave the IBSS before
the netdev is set down. If wireless extensions are used, it
also caches values when the interface is down and instructs
the driver to join when the interface is set up.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Apr 22, 2009
1 parent 691597c commit 04a773a
Show file tree
Hide file tree
Showing 10 changed files with 693 additions and 13 deletions.
18 changes: 18 additions & 0 deletions include/linux/nl80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,15 @@
* %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this
* event matches with MLME-MICHAELMICFAILURE.indication() primitive
*
* @NL80211_CMD_JOIN_IBSS: Join a new IBSS -- given at least an SSID and a
* FREQ attribute (for the initial frequency if no peer can be found)
* and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those
* should be fixed rather than automatically determined. Can only be
* executed on a network interface that is UP, and fixed BSSID/FREQ
* may be rejected.
* @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is
* determined by the network interface.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
Expand Down Expand Up @@ -288,6 +297,9 @@ enum nl80211_commands {

NL80211_CMD_REG_BEACON_HINT,

NL80211_CMD_JOIN_IBSS,
NL80211_CMD_LEAVE_IBSS,

/* add new commands above here */

/* used to define NL80211_CMD_MAX below */
Expand Down Expand Up @@ -456,6 +468,9 @@ enum nl80211_commands {
* @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported
* cipher suites
*
* @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look
* for other networks on different channels
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
Expand Down Expand Up @@ -547,6 +562,9 @@ enum nl80211_attrs {

NL80211_ATTR_FREQ_BEFORE,
NL80211_ATTR_FREQ_AFTER,

NL80211_ATTR_FREQ_FIXED,

/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
Expand Down
72 changes: 72 additions & 0 deletions include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,31 @@ struct cfg80211_disassoc_request {
size_t ie_len;
};

/**
* struct cfg80211_ibss_params - IBSS parameters
*
* This structure defines the IBSS parameters for the join_ibss()
* method.
*
* @ssid: The SSID, will always be non-null.
* @ssid_len: The length of the SSID, will always be non-zero.
* @bssid: Fixed BSSID requested, maybe be %NULL, if set do not
* search for IBSSs with a different BSSID.
* @channel: The channel to use if no IBSS can be found to join.
* @channel_fixed: The channel should be fixed -- do not search for
* IBSSs to join on other channels.
* @ie: information element(s) to include in the beacon
* @ie_len: length of that
*/
struct cfg80211_ibss_params {
u8 *ssid;
u8 *bssid;
struct ieee80211_channel *channel;
u8 *ie;
u8 ssid_len, ie_len;
bool channel_fixed;
};

/**
* struct cfg80211_ops - backend description for wireless configuration
*
Expand Down Expand Up @@ -732,6 +757,11 @@ struct cfg80211_disassoc_request {
* @assoc: Request to (re)associate with the specified peer
* @deauth: Request to deauthenticate from the specified peer
* @disassoc: Request to disassociate from the specified peer
*
* @join_ibss: Join the specified IBSS (or create if necessary). Once done, call
* cfg80211_ibss_joined(), also call that function when changing BSSID due
* to a merge.
* @leave_ibss: Leave the IBSS.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy);
Expand Down Expand Up @@ -817,6 +847,10 @@ struct cfg80211_ops {
struct cfg80211_deauth_request *req);
int (*disassoc)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_disassoc_request *req);

int (*join_ibss)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ibss_params *params);
int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev);
};

/* temporary wext handlers */
Expand All @@ -839,6 +873,28 @@ int cfg80211_wext_siwmlme(struct net_device *dev,
int cfg80211_wext_giwrange(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra);
int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
struct iw_request_info *info,
struct iw_freq *freq, char *extra);
int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
struct iw_request_info *info,
struct iw_freq *freq, char *extra);
int cfg80211_ibss_wext_siwessid(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *ssid);
int cfg80211_ibss_wext_giwessid(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *ssid);
int cfg80211_ibss_wext_siwap(struct net_device *dev,
struct iw_request_info *info,
struct sockaddr *ap_addr, char *extra);
int cfg80211_ibss_wext_giwap(struct net_device *dev,
struct iw_request_info *info,
struct sockaddr *ap_addr, char *extra);

/* wext helper for now (to be removed) */
struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
struct iw_freq *freq);

/**
* cfg80211_scan_done - notify that scan finished
Expand Down Expand Up @@ -984,4 +1040,20 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
enum nl80211_key_type key_type, int key_id,
const u8 *tsc);

/**
* cfg80211_ibss_joined - notify cfg80211 that device joined an IBSS
*
* @dev: network device
* @bssid: the BSSID of the IBSS joined
* @gfp: allocation flags
*
* This function notifies cfg80211 that the device joined an IBSS or
* switched to a different BSSID. Before this function can be called,
* either a beacon has to have been received from the IBSS, or one of
* the cfg80211_inform_bss{,_frame} functions must have been called
* with the locally generated beacon -- this guarantees that there is
* always a scan result for this IBSS. cfg80211 will handle the rest.
*/
void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);

#endif /* __NET_CFG80211_H */
14 changes: 14 additions & 0 deletions include/net/wireless.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ struct wiphy {
*
* @wiphy: pointer to hardware description
* @iftype: interface type
* @list: (private)
* @netdev (private)
*/
struct wireless_dev {
struct wiphy *wiphy;
Expand All @@ -273,6 +275,18 @@ struct wireless_dev {
/* private to the generic wireless code */
struct list_head list;
struct net_device *netdev;

/* currently used for IBSS - might be rearranged in the future */
struct cfg80211_bss *current_bss;
u8 bssid[ETH_ALEN];
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ssid_len;

#ifdef CONFIG_WIRELESS_EXT
/* wext data */
struct cfg80211_ibss_params wext;
u8 wext_bssid[ETH_ALEN];
#endif
};

/**
Expand Down
2 changes: 1 addition & 1 deletion net/wireless/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o
obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o

cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o
cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o
cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o

ccflags-y += -D__CHECK_ENDIAN__
16 changes: 16 additions & 0 deletions net/wireless/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
dev->ieee80211_ptr->netdev = dev;
mutex_unlock(&rdev->devlist_mtx);
break;
case NETDEV_GOING_DOWN:
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
break;
if (!dev->ieee80211_ptr->ssid_len)
break;
cfg80211_leave_ibss(rdev, dev);
break;
case NETDEV_UP:
#ifdef CONFIG_WIRELESS_EXT
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
break;
if (!dev->ieee80211_ptr->wext.ssid_len)
break;
cfg80211_join_ibss(rdev, dev, &dev->ieee80211_ptr->wext);
break;
#endif
case NETDEV_UNREGISTER:
mutex_lock(&rdev->devlist_mtx);
if (!list_empty(&dev->ieee80211_ptr->list)) {
Expand Down
8 changes: 8 additions & 0 deletions net/wireless/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,12 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev);
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);
void cfg80211_clear_ibss(struct net_device *dev);
int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
struct net_device *dev);

#endif /* __NET_WIRELESS_CORE_H */
Loading

0 comments on commit 04a773a

Please sign in to comment.