From patchwork Fri Nov 4 10:37:53 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [04/18] driver_nl80211: support in-kernel station poll Date: Fri, 04 Nov 2011 00:37:53 -0000 From: Johannes Berg X-Patchwork-Id: 123589 Message-Id: <20111104103809.115615960@sipsolutions.net> To: hostap@lists.shmoo.com From: Johannes Berg 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 --- src/drivers/driver_nl80211.c | 59 +++++++++++++++++++++++++++++++++++++++-- 1 files changed, 56 insertions(+), 3 deletions(-) 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