From a70cd0db876b2ffad7e3d608e3f9a2fcf2e7a879 Mon Sep 17 00:00:00 2001 From: Dedy Lansky Date: Tue, 27 Dec 2016 11:25:00 +0200 Subject: [PATCH] nl80211: Don't register for Beacon frames for IEEE 802.11ad AP Beacon frames are not supported in IEEE 802.11ad network (DMG-beacons used instead). To allow hostapd to manage IEEE 802.11ad AP with device_ap_sme disabled, skip nl80211_register_beacons() for IEEE 802.11ad AP. Signed-off-by: Dedy Lansky --- src/drivers/driver_nl80211.c | 70 ++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index dab23864c..60800792d 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -675,6 +675,7 @@ nl80211_get_wiphy_data_ap(struct i802_bss *bss) struct nl80211_wiphy_data *w; int wiphy_idx, found = 0; struct i802_bss *tmp_bss; + u8 channel; if (bss->wiphy_data != NULL) return bss->wiphy_data; @@ -694,29 +695,35 @@ nl80211_get_wiphy_data_ap(struct i802_bss *bss) dl_list_init(&w->bsss); dl_list_init(&w->drvs); - w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); - if (!w->nl_cb) { - os_free(w); - return NULL; - } - nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); - nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_beacon_event, - w); + /* Beacon frames not supported in IEEE 802.11ad */ + if (ieee80211_freq_to_chan(bss->freq, &channel) != + HOSTAPD_MODE_IEEE80211AD) { + w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); + if (!w->nl_cb) { + os_free(w); + return NULL; + } + nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, + no_seq_check, NULL); + nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, + process_beacon_event, w); - w->nl_beacons = nl_create_handle(bss->drv->global->nl_cb, - "wiphy beacons"); - if (w->nl_beacons == NULL) { - os_free(w); - return NULL; - } + w->nl_beacons = nl_create_handle(bss->drv->global->nl_cb, + "wiphy beacons"); + if (w->nl_beacons == NULL) { + os_free(w); + return NULL; + } - if (nl80211_register_beacons(bss->drv, w)) { - nl_destroy_handles(&w->nl_beacons); - os_free(w); - return NULL; - } + if (nl80211_register_beacons(bss->drv, w)) { + nl_destroy_handles(&w->nl_beacons); + os_free(w); + return NULL; + } - nl80211_register_eloop_read(&w->nl_beacons, nl80211_recv_beacons, w); + nl80211_register_eloop_read(&w->nl_beacons, + nl80211_recv_beacons, w); + } dl_list_add(&nl80211_wiphys, &w->list); @@ -763,7 +770,8 @@ static void nl80211_put_wiphy_data_ap(struct i802_bss *bss) if (!dl_list_empty(&w->bsss)) return; - nl80211_destroy_eloop_handle(&w->nl_beacons); + if (w->nl_beacons) + nl80211_destroy_eloop_handle(&w->nl_beacons); nl_cb_put(w->nl_cb); dl_list_del(&w->list); @@ -2238,9 +2246,6 @@ static int nl80211_mgmt_subscribe_ap(struct i802_bss *bss) if (nl80211_register_spurious_class3(bss)) goto out_err; - if (nl80211_get_wiphy_data_ap(bss) == NULL) - goto out_err; - nl80211_mgmt_handle_register_eloop(bss); return 0; @@ -2276,8 +2281,6 @@ static void nl80211_mgmt_unsubscribe(struct i802_bss *bss, const char *reason) wpa_printf(MSG_DEBUG, "nl80211: Unsubscribe mgmt frames handle %p " "(%s)", bss->nl_mgmt, reason); nl80211_destroy_eloop_handle(&bss->nl_mgmt); - - nl80211_put_wiphy_data_ap(bss); } @@ -2495,12 +2498,14 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv, } -static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv) +static int wpa_driver_nl80211_del_beacon(struct i802_bss *bss) { struct nl_msg *msg; + struct wpa_driver_nl80211_data *drv = bss->drv; wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)", drv->ifindex); + nl80211_put_wiphy_data_ap(bss); msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON); return send_and_recv_msgs(drv, msg, NULL, NULL); } @@ -2553,7 +2558,7 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss) nl80211_remove_monitor_interface(drv); if (is_ap_interface(drv->nlmode)) - wpa_driver_nl80211_del_beacon(drv); + wpa_driver_nl80211_del_beacon(bss); if (drv->eapol_sock >= 0) { eloop_unregister_read_sock(drv->eapol_sock); @@ -3778,6 +3783,8 @@ static int wpa_driver_nl80211_set_ap(void *priv, beacon_set); if (beacon_set) cmd = NL80211_CMD_SET_BEACON; + else if (!nl80211_get_wiphy_data_ap(bss)) + return -ENOBUFS; wpa_hexdump(MSG_DEBUG, "nl80211: Beacon head", params->head, params->head_len); @@ -4709,6 +4716,7 @@ static void nl80211_teardown_ap(struct i802_bss *bss) else nl80211_mgmt_unsubscribe(bss, "AP teardown"); + nl80211_put_wiphy_data_ap(bss); bss->beacon_set = 0; } @@ -6745,7 +6753,7 @@ static int wpa_driver_nl80211_if_remove(struct i802_bss *bss, wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context"); nl80211_teardown_ap(bss); if (!bss->added_if && !drv->first_bss->next) - wpa_driver_nl80211_del_beacon(drv); + wpa_driver_nl80211_del_beacon(bss); nl80211_destroy_bss(bss); if (!bss->added_if) i802_set_iface_flags(bss, 0); @@ -7107,7 +7115,7 @@ static int wpa_driver_nl80211_deinit_ap(void *priv) struct wpa_driver_nl80211_data *drv = bss->drv; if (!is_ap_interface(drv->nlmode)) return -1; - wpa_driver_nl80211_del_beacon(drv); + wpa_driver_nl80211_del_beacon(bss); bss->beacon_set = 0; /* @@ -7127,7 +7135,7 @@ static int wpa_driver_nl80211_stop_ap(void *priv) struct wpa_driver_nl80211_data *drv = bss->drv; if (!is_ap_interface(drv->nlmode)) return -1; - wpa_driver_nl80211_del_beacon(drv); + wpa_driver_nl80211_del_beacon(bss); bss->beacon_set = 0; return 0; }