--- src/drivers/driver_nl80211.c | 76 +++++++++++++++++++++++++++++------------- 1 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 0c098ae..848db84 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -175,6 +175,7 @@ struct wpa_driver_nl80211_data { int monitor_sock; int monitor_ifidx; + int monitor_refcount; int disable_11b_rates; unsigned int pending_remain_on_chan:1; @@ -4788,6 +4789,10 @@ static int add_monitor_filter(int s) static void nl80211_remove_monitor_interface( struct wpa_driver_nl80211_data *drv) { + drv->monitor_refcount--; + if (drv->monitor_refcount > 0) + return; + if (drv->monitor_ifidx >= 0) { nl80211_remove_iface(drv, drv->monitor_ifidx); drv->monitor_ifidx = -1; @@ -4808,6 +4813,11 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv) int optval; socklen_t optlen; + if (drv->monitor_ifidx > 0) { + drv->monitor_refcount++; + return 0; + } + snprintf(buf, IFNAMSIZ, "mon.%s", drv->first_bss.ifname); buf[IFNAMSIZ - 1] = '\0'; @@ -4874,6 +4884,38 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv) } +static int nl80211_setup_ap(struct i802_bss *bss) +{ + struct wpa_driver_nl80211_data *drv = bss->drv; + + if (!drv->device_ap_sme && + nl80211_create_monitor_interface(drv) && + !drv->device_ap_sme) + return -1; + + if (drv->device_ap_sme && + wpa_driver_nl80211_probe_req_report(bss, 1) < 0) { + wpa_printf(MSG_DEBUG, "nl80211: Failed to enable " + "Probe Request frame reporting in AP mode"); + /* Try to survive without this */ + } + + return 0; +} + + +static void nl80211_teardown_ap(struct i802_bss *bss) +{ + struct wpa_driver_nl80211_data *drv = bss->drv; + + if (drv->device_ap_sme) + wpa_driver_nl80211_probe_req_report(bss, 0); + else + nl80211_remove_monitor_interface(drv); + bss->beacon_set = 0; +} + + static int nl80211_send_eapol_data(struct i802_bss *bss, const u8 *addr, const u8 *data, size_t data_len) @@ -5043,15 +5085,6 @@ static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv, return -1; } - if (drv->device_ap_sme) { - if (wpa_driver_nl80211_probe_req_report(&drv->first_bss, 1) < 0) - { - wpa_printf(MSG_DEBUG, "nl80211: Failed to enable " - "Probe Request frame reporting in AP mode"); - /* Try to survive without this */ - } - } - drv->ap_oper_freq = params->freq; return 0; @@ -5601,25 +5634,22 @@ static int wpa_driver_nl80211_set_mode(struct i802_bss *bss, } done: - if (!ret && is_ap_interface(nlmode)) { + if (ret) { + wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d " + "from %d failed", nlmode, drv->nlmode); + return ret; + } + + if (is_ap_interface(nlmode)) { /* Setup additional AP mode functionality if needed */ - if (!drv->device_ap_sme && drv->monitor_ifidx < 0 && - nl80211_create_monitor_interface(drv) && - !drv->device_ap_sme) + if (nl80211_setup_ap(bss)) return -1; - } else if (!ret && !is_ap_interface(nlmode)) { + } else if (was_ap) { /* Remove additional AP mode functionality */ - if (was_ap && drv->device_ap_sme) - wpa_driver_nl80211_probe_req_report(bss, 0); - nl80211_remove_monitor_interface(drv); - bss->beacon_set = 0; + nl80211_teardown_ap(bss); } - if (ret) - wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d " - "from %d failed", nlmode, drv->nlmode); - - return ret; + return 0; } -- 1.7.6.3