Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54858ee5 authored by Alexander Simon's avatar Alexander Simon Committed by John W. Linville
Browse files

nl80211: Parse channel type attribute in an ibss join request



Prepare cfg80211 for IBSS HT:
 * extend cfg80211 ibss struct with channel_type
 * Check if extension channel can be used
 * Export can_beacon_sec_chan for use in mac80211 (will be called
   from ibss.c later).

Signed-off-by: default avatarAlexander Simon <an.alexsimon@googlemail.com>
[siwu@hrz.tu-chemnitz.de: Updates]
* fix cfg80211_can_beacon_ext_chan comment
* remove implicit channel_type enum assumptions
* remove radar channel flags check
* add HT IBSS feature flag
* reword commit message

Signed-off-by: default avatarSimon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: default avatarMathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
Reviewed-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 2b50b8f5
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2785,9 +2785,11 @@ enum nl80211_ap_sme_features {
 * @NL80211_FEATURE_SK_TX_STATUS: This driver supports reflecting back
 *	TX status to the socket error queue when requested with the
 *	socket option.
 * @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates.
 */
enum nl80211_feature_flags {
	NL80211_FEATURE_SK_TX_STATUS	= 1 << 0,
	NL80211_FEATURE_HT_IBSS		= 1 << 1,
};

/**
+11 −0
Original line number Diff line number Diff line
@@ -1149,6 +1149,7 @@ struct cfg80211_ibss_params {
	u8 *ssid;
	u8 *bssid;
	struct ieee80211_channel *channel;
	enum nl80211_channel_type channel_type;
	u8 *ie;
	u8 ssid_len, ie_len;
	u16 beacon_interval;
@@ -3267,6 +3268,16 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy,
				 const u8 *frame, size_t len,
				 int freq, gfp_t gfp);

/*
 * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used
 * @wiphy: the wiphy
 * @chan: main channel
 * @channel_type: HT mode
 */
int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
				 struct ieee80211_channel *chan,
				 enum nl80211_channel_type channel_type);

/* Logging, debugging and troubleshooting/diagnostic helpers. */

/* wiphy_printk helpers, similar to dev_printk */
+7 −5
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
 * Copyright 2009	Johannes Berg <johannes@sipsolutions.net>
 */

#include <linux/export.h>
#include <net/cfg80211.h>
#include "core.h"

@@ -44,7 +45,7 @@ rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
	return chan;
}

static bool can_beacon_sec_chan(struct wiphy *wiphy,
int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
				  struct ieee80211_channel *chan,
				  enum nl80211_channel_type channel_type)
{
@@ -75,6 +76,7 @@ static bool can_beacon_sec_chan(struct wiphy *wiphy,

	return true;
}
EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan);

int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
		      struct wireless_dev *wdev, int freq,
@@ -109,7 +111,7 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
		switch (channel_type) {
		case NL80211_CHAN_HT40PLUS:
		case NL80211_CHAN_HT40MINUS:
			if (!can_beacon_sec_chan(&rdev->wiphy, chan,
			if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, chan,
							  channel_type)) {
				printk(KERN_DEBUG
				       "cfg80211: Secondary channel not "
+30 −2
Original line number Diff line number Diff line
@@ -4682,13 +4682,41 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
		ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
	}

	ibss.channel = ieee80211_get_channel(wiphy,
		nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
	if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
		enum nl80211_channel_type channel_type;

		channel_type = nla_get_u32(
				info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
		if (channel_type != NL80211_CHAN_NO_HT &&
		    channel_type != NL80211_CHAN_HT20 &&
		    channel_type != NL80211_CHAN_HT40MINUS &&
		    channel_type != NL80211_CHAN_HT40PLUS)
			return -EINVAL;

		if (channel_type != NL80211_CHAN_NO_HT &&
		    !(wiphy->features & NL80211_FEATURE_HT_IBSS))
			return -EINVAL;

		ibss.channel_type = channel_type;
	} else {
		ibss.channel_type = NL80211_CHAN_NO_HT;
	}

	ibss.channel = rdev_freq_to_chan(rdev,
		nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
		ibss.channel_type);
	if (!ibss.channel ||
	    ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
	    ibss.channel->flags & IEEE80211_CHAN_DISABLED)
		return -EINVAL;

	/* Both channels should be able to initiate communication */
	if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
	     ibss.channel_type == NL80211_CHAN_HT40MINUS) &&
	    !cfg80211_can_beacon_sec_chan(&rdev->wiphy, ibss.channel,
					  ibss.channel_type))
		return -EINVAL;

	ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
	ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];