diff mbox

[04/18] driver_nl80211: support in-kernel station poll

Message ID 20111104103809.115615960@sipsolutions.net
State Accepted
Commit 397188521deb2131c3db942413cfd96b43a47bb2
Headers show

Commit Message

Johannes Berg Nov. 4, 2011, 10:37 a.m. UTC
From: Johannes Berg <johannes.berg@intel.com>

If the kernel supports this, don't use manual null
data frame transmissions. This is one thing to get
rid of cooked monitor interfaces.

Signed-hostap: Johannes Berg <johannes.berg@intel.com>
---
 src/drivers/driver_nl80211.c |   59 +++++++++++++++++++++++++++++++++++++++--
 1 files changed, 56 insertions(+), 3 deletions(-)

Comments

Jouni Malinen Nov. 19, 2011, 12:24 p.m. UTC | #1
On Fri, Nov 04, 2011 at 11:37:53AM +0100, Johannes Berg wrote:
> If the kernel supports this, don't use manual null
> data frame transmissions. This is one thing to get
> rid of cooked monitor interfaces.

Thanks, applied.
diff mbox

Patch

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 51b65ba..1128e44 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -224,6 +224,7 @@  struct wpa_driver_nl80211_data {
 	unsigned int pending_remain_on_chan:1;
 	unsigned int in_interface_list:1;
 	unsigned int device_ap_sme:1;
+	unsigned int poll_command_supported:1;
 
 	u64 remain_on_chan_cookie;
 	u64 send_action_cookie;
@@ -1688,6 +1689,22 @@  static void nl80211_pmksa_candidate_event(struct wpa_driver_nl80211_data *drv,
 }
 
 
+static void nl80211_client_probe_event(struct wpa_driver_nl80211_data *drv,
+				       struct nlattr **tb)
+{
+	union wpa_event_data data;
+
+	if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_ACK])
+		return;
+
+	os_memset(&data, 0, sizeof(data));
+	os_memcpy(data.client_poll.addr,
+		  nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
+
+	wpa_supplicant_event(drv->ctx, EVENT_DRIVER_CLIENT_POLL_OK, &data);
+}
+
+
 static int process_event(struct nl_msg *msg, void *arg)
 {
 	struct wpa_driver_nl80211_data *drv = arg;
@@ -1810,6 +1827,9 @@  static int process_event(struct nl_msg *msg, void *arg)
 	case NL80211_CMD_PMKSA_CANDIDATE:
 		nl80211_pmksa_candidate_event(drv, tb);
 		break;
+	case NL80211_CMD_PROBE_CLIENT:
+		nl80211_client_probe_event(drv, tb);
+		break;
 	default:
 		wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
 			   "(cmd=%d)", gnlh->cmd);
@@ -1878,6 +1898,7 @@  struct wiphy_info_data {
 
 	unsigned int error:1;
 	unsigned int device_ap_sme:1;
+	unsigned int poll_command_supported:1;
 };
 
 
@@ -2009,6 +2030,9 @@  broken_combination:
 			case NL80211_CMD_START_SCHED_SCAN:
 				capa->sched_scan_supported = 1;
 				break;
+			case NL80211_CMD_PROBE_CLIENT:
+				info->poll_command_supported = 1;
+				break;
 			}
 		}
 	}
@@ -2120,6 +2144,7 @@  static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
 	drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;
 
 	drv->device_ap_sme = info.device_ap_sme;
+	drv->poll_command_supported = info.poll_command_supported;
 
 	return 0;
 }
@@ -7432,10 +7457,11 @@  static void nl80211_set_rekey_info(void *priv, const u8 *kek, const u8 *kck,
 }
 
 
-static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr,
-				int qos)
+static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr,
+				    const u8 *addr, int qos)
 {
-	struct i802_bss *bss = priv;
+	/* send data frame to poll STA and check whether
+	 * this frame is ACKed */
 	struct {
 		struct ieee80211_hdr hdr;
 		u16 qos_ctl;
@@ -7468,6 +7494,33 @@  static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr,
 			   "send poll frame");
 }
 
+static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr,
+				int qos)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *msg;
+
+	if (!drv->poll_command_supported) {
+		nl80211_send_null_frame(bss, own_addr, addr, qos);
+		return;
+	}
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return;
+
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_PROBE_CLIENT);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
+
+	send_and_recv_msgs(drv, msg, NULL, NULL);
+	return;
+ nla_put_failure:
+	nlmsg_free(msg);
+}
+
 
 #ifdef CONFIG_TDLS