diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 75825bd94..4786b29a5 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -275,7 +275,7 @@ void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv) drv->associated = 0; os_memset(&drv->sta_mlo_info, 0, sizeof(drv->sta_mlo_info)); os_memset(drv->bssid, 0, ETH_ALEN); - drv->first_bss->freq = 0; + drv->first_bss->flink->freq = 0; #ifdef CONFIG_DRIVER_NL80211_QCA os_free(drv->pending_roam_data); drv->pending_roam_data = NULL; @@ -913,7 +913,7 @@ nl80211_get_wiphy_data_ap(struct i802_bss *bss) dl_list_init(&w->drvs); /* Beacon frames not supported in IEEE 802.11ad */ - if (ieee80211_freq_to_chan(bss->freq, &channel) != + if (ieee80211_freq_to_chan(bss->flink->freq, &channel) != HOSTAPD_MODE_IEEE80211AD) { w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); if (!w->nl_cb) { @@ -2232,6 +2232,7 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname, { struct wpa_driver_nl80211_data *drv; struct i802_bss *bss; + unsigned int i; if (global_priv == NULL) return NULL; @@ -2310,6 +2311,17 @@ skip_wifi_status: drv->in_interface_list = 1; } + /* + * Set the default link to be the first one, and set its address to that + * of the interface. + */ + bss->flink = &bss->links[0]; + bss->n_links = 1; + os_memcpy(bss->flink->addr, bss->addr, ETH_ALEN); + + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) + bss->links[i].link_id = NL80211_DRV_LINK_ID_NA; + return bss; failed: @@ -2984,8 +2996,8 @@ static int wpa_driver_nl80211_del_beacon(struct i802_bss *bss) wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)", drv->ifindex); - bss->beacon_set = 0; - bss->freq = 0; + bss->flink->beacon_set = 0; + bss->flink->freq = 0; 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, NULL, NULL); @@ -4111,10 +4123,10 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data, if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) { if (freq == 0) { wpa_printf(MSG_DEBUG, "nl80211: Use bss->freq=%d", - bss->freq); - freq = bss->freq; + bss->flink->freq); + freq = bss->flink->freq; } - if ((int) freq == bss->freq) + if ((int) freq == bss->flink->freq) wait_time = 0; goto send_frame_cmd; } @@ -4176,14 +4188,14 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data, } if (freq == 0) { wpa_printf(MSG_DEBUG, "nl80211: send_mlme - Use bss->freq=%u", - bss->freq); - freq = bss->freq; + bss->flink->freq); + freq = bss->flink->freq; } if (drv->use_monitor && is_ap_interface(drv->nlmode)) { wpa_printf(MSG_DEBUG, "nl80211: send_frame(freq=%u bss->freq=%u) -> send_monitor", - freq, bss->freq); + freq, bss->flink->freq); return nl80211_send_monitor(drv, data, data_len, encrypt, noack); } @@ -4696,7 +4708,7 @@ static int wpa_driver_nl80211_set_ap(void *priv, struct wpa_driver_mesh_bss_params mesh_params; #endif /* CONFIG_MESH */ - beacon_set = params->reenable ? 0 : bss->beacon_set; + beacon_set = params->reenable ? 0 : bss->flink->beacon_set; wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)", beacon_set); @@ -4999,17 +5011,17 @@ static int wpa_driver_nl80211_set_ap(void *priv, wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)", ret, strerror(-ret)); } else { - bss->beacon_set = 1; + bss->flink->beacon_set = 1; nl80211_set_bss(bss, params->cts_protect, params->preamble, params->short_slot_time, params->ht_opmode, params->isolate, params->basic_rates); nl80211_set_multicast_to_unicast(bss, params->multicast_to_unicast); if (beacon_set && params->freq && - params->freq->bandwidth != bss->bandwidth) { + params->freq->bandwidth != bss->flink->bandwidth) { wpa_printf(MSG_DEBUG, "nl80211: Update BSS %s bandwidth: %d -> %d", - bss->ifname, bss->bandwidth, + bss->ifname, bss->flink->bandwidth, params->freq->bandwidth); ret = nl80211_set_channel(bss, params->freq, 1); if (ret) { @@ -5019,7 +5031,7 @@ static int wpa_driver_nl80211_set_ap(void *priv, } else { wpa_printf(MSG_DEBUG, "nl80211: Frequency set succeeded for ht2040 coex"); - bss->bandwidth = params->freq->bandwidth; + bss->flink->bandwidth = params->freq->bandwidth; } } else if (!beacon_set && params->freq) { /* @@ -5027,7 +5039,7 @@ static int wpa_driver_nl80211_set_ap(void *priv, * mode only at the point when beaconing is started, so * set the initial value here. */ - bss->bandwidth = params->freq->bandwidth; + bss->flink->bandwidth = params->freq->bandwidth; } } @@ -5177,7 +5189,7 @@ static int nl80211_set_channel(struct i802_bss *bss, ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret == 0) { - bss->freq = freq->freq; + bss->flink->freq = freq->freq; return 0; } wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): " @@ -5805,7 +5817,7 @@ static void nl80211_teardown_ap(struct i802_bss *bss) nl80211_mgmt_unsubscribe(bss, "AP teardown"); nl80211_put_wiphy_data_ap(bss); - bss->beacon_set = 0; + bss->flink->beacon_set = 0; } @@ -7791,7 +7803,7 @@ static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, struct ieee80211_mgmt mgmt; u8 channel; - if (ieee80211_freq_to_chan(bss->freq, &channel) == + if (ieee80211_freq_to_chan(bss->flink->freq, &channel) == HOSTAPD_MODE_IEEE80211AD) { /* Deauthentication is not used in DMG/IEEE 802.11ad; * disassociate the STA instead. */ @@ -8412,12 +8424,18 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type, if (type == WPA_IF_AP_BSS && setup_ap) { struct i802_bss *new_bss = os_zalloc(sizeof(*new_bss)); + unsigned int i; + if (new_bss == NULL) { if (added) nl80211_remove_iface(drv, ifidx); return -1; } + /* Initialize here before any failure path */ + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) + new_bss->links[i].link_id = NL80211_DRV_LINK_ID_NA; + if (bridge && i802_check_bridge(drv, new_bss, bridge, ifname) < 0) { wpa_printf(MSG_ERROR, "nl80211: Failed to add the new " @@ -8441,7 +8459,11 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type, new_bss->ifindex = ifidx; new_bss->drv = drv; new_bss->next = drv->first_bss->next; - new_bss->freq = drv->first_bss->freq; + new_bss->flink = &new_bss->links[0]; + new_bss->n_links = 1; + os_memcpy(new_bss->flink->addr, new_bss->addr, ETH_ALEN); + + new_bss->flink->freq = drv->first_bss->flink->freq; new_bss->ctx = bss_ctx; new_bss->added_if = added; drv->first_bss->next = new_bss; @@ -8648,8 +8670,8 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss, struct ieee80211_hdr *hdr; int offchanok = 1; - if (is_ap_interface(drv->nlmode) && (int) freq == bss->freq && - bss->beacon_set) + if (is_ap_interface(drv->nlmode) && (int) freq == bss->flink->freq && + bss->flink->beacon_set) offchanok = 0; wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, " @@ -8685,7 +8707,7 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss, modes = nl80211_get_hw_feature_data(bss, &num_modes, &flags, &dfs_domain); if (dfs_domain != HOSTAPD_DFS_REGION_ETSI && - ieee80211_is_dfs(bss->freq, modes, num_modes)) + ieee80211_is_dfs(bss->flink->freq, modes, num_modes)) offchanok = 0; if (modes) { for (i = 0; i < num_modes; i++) { @@ -8699,7 +8721,7 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss, if (is_ap_interface(drv->nlmode) && (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) || - (int) freq == bss->freq || drv->device_ap_sme || + (int) freq == bss->flink->freq || drv->device_ap_sme || !drv->use_monitor)) ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len, 0, freq, no_cck, offchanok, @@ -10256,8 +10278,8 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen) bss->ifname, bss->brname, MAC2STR(bss->addr), - bss->freq, - bss->beacon_set ? "beacon_set=1\n" : "", + bss->flink->freq, + bss->flink->beacon_set ? "beacon_set=1\n" : "", bss->added_if_into_bridge ? "added_if_into_bridge=1\n" : "", bss->already_in_bridge ? "already_in_bridge=1\n" : "", @@ -11318,7 +11340,7 @@ static int nl80211_join_mesh(struct i802_bss *bss, goto fail; } ret = 0; - drv->assoc_freq = bss->freq = params->freq.freq; + drv->assoc_freq = bss->flink->freq = params->freq.freq; wpa_printf(MSG_DEBUG, "nl80211: mesh join request send successfully"); fail: @@ -11374,7 +11396,7 @@ static int wpa_driver_nl80211_leave_mesh(void *priv) } else { wpa_printf(MSG_DEBUG, "nl80211: mesh leave request send successfully"); - drv->first_bss->freq = 0; + drv->first_bss->flink->freq = 0; } if (drv->start_mode_sta && diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index a6cb14c5a..2c4faa373 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -49,15 +49,31 @@ struct nl80211_wiphy_data { int wiphy_idx; }; +#define NL80211_DRV_LINK_ID_NA (-1) + +struct i802_link { + unsigned int beacon_set:1; + + s8 link_id; + int freq; + int bandwidth; + u8 addr[ETH_ALEN]; + void *ctx; +}; + struct i802_bss { struct wpa_driver_nl80211_data *drv; struct i802_bss *next; + + size_t n_links; + struct i802_link links[MAX_NUM_MLD_LINKS]; + struct i802_link *flink; + int ifindex; int br_ifindex; u64 wdev_id; char ifname[IFNAMSIZ + 1]; char brname[IFNAMSIZ]; - unsigned int beacon_set:1; unsigned int added_if_into_bridge:1; unsigned int already_in_bridge:1; unsigned int added_bridge:1; @@ -70,8 +86,6 @@ struct i802_bss { u8 addr[ETH_ALEN]; u8 prev_addr[ETH_ALEN]; - int freq; - int bandwidth; int if_dynamic; void *ctx; diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index cf31552c0..a0015f28f 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -327,7 +327,7 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv, } event.assoc_info.freq = drv->assoc_freq; - drv->first_bss->freq = drv->assoc_freq; + drv->first_bss->flink->freq = drv->assoc_freq; nl80211_parse_wmm_params(wmm, &event.assoc_info.wmm_params); @@ -852,7 +852,7 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv, } event.assoc_info.freq = nl80211_get_assoc_freq(drv); - drv->first_bss->freq = drv->assoc_freq; + drv->first_bss->flink->freq = drv->assoc_freq; if ((!ssid || ssid[1] == 0 || ssid[1] > 32) && (ssid_len = nl80211_get_assoc_ssid(drv, drv->ssid)) > 0) { @@ -1057,7 +1057,7 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv, data.ch_switch.cf2 = nla_get_u32(cf2); if (finished) - bss->freq = data.ch_switch.freq; + bss->flink->freq = data.ch_switch.freq; if (link) { u8 link_id = nla_get_u8(link); @@ -1569,7 +1569,7 @@ static void mlme_event_join_ibss(struct wpa_driver_nl80211_data *drv, if (freq) { wpa_printf(MSG_DEBUG, "nl80211: IBSS on frequency %u MHz", freq); - drv->first_bss->freq = freq; + drv->first_bss->flink->freq = freq; } os_memset(&event, 0, sizeof(event));