diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 2d7d11d6e..2299cc882 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3163,6 +3163,28 @@ out_err: } +static int nl80211_mgmt_subscribe_ap_dev_sme(struct i802_bss *bss) +{ + if (nl80211_alloc_mgmt_handle(bss)) + return -1; + wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP " + "handle %p (device SME)", bss->nl_mgmt); + + if (nl80211_register_frame(bss, bss->nl_mgmt, + (WLAN_FC_TYPE_MGMT << 2) | + (WLAN_FC_STYPE_ACTION << 4), + NULL, 0) < 0) + goto out_err; + + return 0; + +out_err: + eloop_unregister_read_sock(nl_socket_get_fd(bss->nl_mgmt)); + nl_destroy_handles(&bss->nl_mgmt); + return -1; +} + + static void nl80211_mgmt_unsubscribe(struct i802_bss *bss, const char *reason) { if (bss->nl_mgmt == NULL) @@ -6084,6 +6106,10 @@ static int nl80211_setup_ap(struct i802_bss *bss) if (nl80211_mgmt_subscribe_ap(bss)) return -1; + if (drv->device_ap_sme && !drv->use_monitor) + if (nl80211_mgmt_subscribe_ap_dev_sme(bss)) + return -1; + if (!drv->device_ap_sme && drv->use_monitor && nl80211_create_monitor_interface(drv) && !drv->device_ap_sme) @@ -6104,9 +6130,11 @@ static void nl80211_teardown_ap(struct i802_bss *bss) { struct wpa_driver_nl80211_data *drv = bss->drv; - if (drv->device_ap_sme) + if (drv->device_ap_sme) { wpa_driver_nl80211_probe_req_report(bss, 0); - else if (drv->use_monitor) + if (!drv->use_monitor) + nl80211_mgmt_unsubscribe(bss, "AP teardown (dev SME)"); + } else if (drv->use_monitor) nl80211_remove_monitor_interface(drv); else nl80211_mgmt_unsubscribe(bss, "AP teardown");