Search Linux Wireless

[PATCH] cfg80211: Provision to pass probe response ie along with remain on channel request

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The probe response ie should be set in driver before the listen state
for a listen only P2P device. Right now probe response ie is set using
driver specific private command implementations. This commit enhances the
remain_on_channel command handler to pass probe response ie along with
rest of the arguments.

Another approach is the addition of a new nl80211 command specific to pass
ies to driver. This will give more flexibilty to upper layer.

Signed-off-by: Sreenath Sharma <sreenats@xxxxxxxxxxxx>
---
 include/net/cfg80211.h  |   24 +++++++++++++++++++++---
 net/wireless/nl80211.c  |   42 ++++++++++++++++++++++++++++++++++--------
 net/wireless/rdev-ops.h |   11 +++++------
 3 files changed, 60 insertions(+), 17 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d530c54..71f7d84 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1425,6 +1425,26 @@ struct cfg80211_sched_scan_request {
 };
 
 /**
+ * struct cfg80211_roc_request - remain on channel request description
+ *
+ * @chandef: defines the channel to remain on
+ * @duration: duration in milliseconds that the driver intents to remain on the
+ *	channel
+ * @ie: optional information element(s) to add into Probe Response or %NULL
+ * @ie_len: length of ie in octets
+ * @cookie: the request cookie to be filled by the driver
+ */
+struct cfg80211_roc_request {
+	struct cfg80211_chan_def chandef;
+	unsigned int duration;
+	const u8 *ie;
+	size_t ie_len;
+
+	/* keep last */
+	u64 *cookie;
+};
+
+/**
  * enum cfg80211_signal_type - signal type
  *
  * @CFG80211_SIGNAL_TYPE_NONE: no signal strength information available
@@ -2313,9 +2333,7 @@ struct cfg80211_ops {
 
 	int	(*remain_on_channel)(struct wiphy *wiphy,
 				     struct wireless_dev *wdev,
-				     struct ieee80211_channel *chan,
-				     unsigned int duration,
-				     u64 *cookie);
+				     struct cfg80211_roc_request *request);
 	int	(*cancel_remain_on_channel)(struct wiphy *wiphy,
 					    struct wireless_dev *wdev,
 					    u64 cookie);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index af8d84a..c0db346 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -7093,12 +7093,13 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct wireless_dev *wdev = info->user_ptr[1];
+	struct cfg80211_roc_request *request;
 	struct cfg80211_chan_def chandef;
 	struct sk_buff *msg;
 	void *hdr;
-	u64 cookie;
 	u32 duration;
 	int err;
+	size_t ie_len;
 
 	if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
 	    !info->attrs[NL80211_ATTR_DURATION])
@@ -7122,24 +7123,47 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
 	if (err)
 		return err;
 
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!msg)
+	if (info->attrs[NL80211_ATTR_IE])
+		ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+	else
+		ie_len = 0;
+	if (ie_len > rdev->wiphy.max_scan_ie_len)
+		return -EINVAL;
+	request = kzalloc(sizeof(*request)
+			+ sizeof(*request->cookie)
+			+ ie_len, GFP_KERNEL);
+	if (!request)
 		return -ENOMEM;
+	memcpy(&request->chandef, &chandef, sizeof(request->chandef));
+	request->duration = duration;
+	if (ie_len) {
+		request->ie_len = ie_len;
+		request->ie = (void *)(request) + sizeof(*request);
+		memcpy((void *)request->ie,
+		       nla_data(info->attrs[NL80211_ATTR_IE]),
+		       request->ie_len);
+		request->cookie = (void *)(request->ie) + request->ie_len;
+	} else
+		request->cookie = (void *)(request) + sizeof(*request);
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg) {
+		err = -ENOMEM;
+		goto free_buf;
+	}
 
 	hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
 			     NL80211_CMD_REMAIN_ON_CHANNEL);
-	if (!hdr) {
-		err = -ENOBUFS;
+	if (IS_ERR(hdr)) {
+		err = PTR_ERR(hdr);
 		goto free_msg;
 	}
 
-	err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
-				     duration, &cookie);
+	err = rdev_remain_on_channel(rdev, wdev, request);
 
 	if (err)
 		goto free_msg;
 
-	if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
+	if (nla_put_u64(msg, NL80211_ATTR_COOKIE, *request->cookie))
 		goto nla_put_failure;
 
 	genlmsg_end(msg, hdr);
@@ -7150,6 +7174,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
 	err = -ENOBUFS;
  free_msg:
 	nlmsg_free(msg);
+ free_buf:
+	kfree(request);
 	return err;
 }
 
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 37ce9fd..e521116 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -600,14 +600,13 @@ static inline int rdev_flush_pmksa(struct cfg80211_registered_device *rdev,
 static inline int
 rdev_remain_on_channel(struct cfg80211_registered_device *rdev,
 		       struct wireless_dev *wdev,
-		       struct ieee80211_channel *chan,
-		       unsigned int duration, u64 *cookie)
+		       struct cfg80211_roc_request *request)
 {
 	int ret;
-	trace_rdev_remain_on_channel(&rdev->wiphy, wdev, chan, duration);
-	ret = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, chan,
-					   duration, cookie);
-	trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
+	trace_rdev_remain_on_channel(&rdev->wiphy, wdev, request->chandef.chan,
+		       request->duration);
+	ret = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, request);
+	trace_rdev_return_int_cookie(&rdev->wiphy, ret, *request->cookie);
 	return ret;
 }
 
-- 
1.7.9.5


--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux