From: Johannes Berg If the underlying driver supports off-channel TX, it will now be used by the nl80211 driver wrapper, setting WPA_DRIVER_FLAGS_OFFCHANNEL_TX accordingly. Signed-off-by: Johannes Berg --- src/drivers/driver_nl80211.c | 50 ++++++++++++++++++++++++++++++++++++----- 1 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index a718003..ec93784 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -195,7 +195,8 @@ static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, static void nl80211_remove_monitor_interface( struct wpa_driver_nl80211_data *drv); static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv, - unsigned int freq, const u8 *buf, + unsigned int freq, unsigned int wait, + const u8 *buf, size_t buf_len, u64 *cookie); static int wpa_driver_nl80211_probe_req_report(void *priv, int report); @@ -1432,6 +1433,7 @@ struct wiphy_info_data { int ap_supported; int auth_supported; int connect_supported; + int offchan_tx_supported; }; @@ -1474,6 +1476,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) } } + if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) + info->offchan_tx_supported = 1; + return NL_SKIP; } @@ -1533,6 +1538,9 @@ static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) return -1; } + if (info.offchan_tx_supported) + drv->capa.flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX; + drv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES; drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE; drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE; @@ -3443,7 +3451,7 @@ static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data, * but it works due to the single-threaded nature * of wpa_supplicant. */ - return nl80211_send_frame_cmd(drv, drv->last_mgmt_freq, + return nl80211_send_frame_cmd(drv, drv->last_mgmt_freq, 0, data, data_len, NULL); } @@ -5745,7 +5753,8 @@ static int cookie_handler(struct nl_msg *msg, void *arg) static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv, - unsigned int freq, const u8 *buf, + unsigned int freq, unsigned int wait, + const u8 *buf, size_t buf_len, u64 *cookie_out) { struct nl_msg *msg; @@ -5761,6 +5770,8 @@ static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv, NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); + NLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait); + NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK); NLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf); cookie = 0; @@ -5795,8 +5806,8 @@ static int wpa_driver_nl80211_send_action(void *priv, unsigned int freq, u8 *buf; struct ieee80211_hdr *hdr; - wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d)", - drv->ifindex); + wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, wait=%dms)", + drv->ifindex, wait_time); buf = os_zalloc(24 + data_len); if (buf == NULL) @@ -5812,13 +5823,39 @@ static int wpa_driver_nl80211_send_action(void *priv, unsigned int freq, if (drv->nlmode == NL80211_IFTYPE_AP) ret = wpa_driver_nl80211_send_mlme(priv, buf, 24 + data_len); else - ret = nl80211_send_frame_cmd(drv, freq, buf, 24 + data_len, + ret = nl80211_send_frame_cmd(drv, freq, wait_time, buf, 24 + data_len, &drv->send_action_cookie); os_free(buf); return ret; } +static void wpa_driver_nl80211_send_action_cancel_wait(void *priv) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + int ret; + + msg = nlmsg_alloc(); + if (!msg) + return; + + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, + NL80211_CMD_FRAME_WAIT_CANCEL, 0); + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); + NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie); + + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + msg = NULL; + if (ret) + wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d " + "(%s)", ret, strerror(-ret)); + + nla_put_failure: + nlmsg_free(msg); +} static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq, unsigned int duration) @@ -6280,6 +6317,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { #endif /* HOSTAPD */ .set_freq = i802_set_freq, .send_action = wpa_driver_nl80211_send_action, + .send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait, .remain_on_channel = wpa_driver_nl80211_remain_on_channel, .cancel_remain_on_channel = wpa_driver_nl80211_cancel_remain_on_channel, -- 1.7.2.3