diff options
Diffstat (limited to 'package/hostapd/patches')
-rw-r--r-- | package/hostapd/patches/130-scan_wait.patch | 148 | ||||
-rw-r--r-- | package/hostapd/patches/140-wds_sta_remove.patch | 12 | ||||
-rw-r--r-- | package/hostapd/patches/150-mbss_driver_handling.patch | 1110 | ||||
-rw-r--r-- | package/hostapd/patches/160-sta_roam_between_bss.patch | 79 |
4 files changed, 1349 insertions, 0 deletions
diff --git a/package/hostapd/patches/130-scan_wait.patch b/package/hostapd/patches/130-scan_wait.patch new file mode 100644 index 0000000000..7fe928549a --- /dev/null +++ b/package/hostapd/patches/130-scan_wait.patch @@ -0,0 +1,148 @@ +--- a/src/ap/hostapd.h ++++ b/src/ap/hostapd.h +@@ -238,6 +238,7 @@ struct hostapd_iface { + int (*for_each_interface)(struct hapd_interfaces *interfaces, + int (*cb)(struct hostapd_iface *iface, + void *ctx), void *ctx); ++ int (*init_complete)(struct hostapd_iface *iface); + }; + + /* hostapd.c */ +--- a/src/ap/hostapd.c ++++ b/src/ap/hostapd.c +@@ -745,6 +745,9 @@ int hostapd_setup_interface_complete(str + wpa_printf(MSG_DEBUG, "%s: Setup of interface done.", + iface->bss[0]->conf->iface); + ++ if (iface->init_complete) ++ iface->init_complete(iface); ++ + return 0; + } + +--- a/hostapd/main.c ++++ b/hostapd/main.c +@@ -35,6 +35,8 @@ + extern int wpa_debug_level; + extern int wpa_debug_show_keys; + extern int wpa_debug_timestamp; ++static int daemonize = 0; ++static char *pid_file = NULL; + + + struct hapd_interfaces { +@@ -162,6 +164,15 @@ static void hostapd_logger_cb(void *ctx, + } + #endif /* CONFIG_NO_HOSTAPD_LOGGER */ + ++static int hostapd_init_complete(struct hostapd_iface *iface) ++{ ++ if (daemonize && os_daemonize(pid_file)) { ++ perror("daemon"); ++ return -1; ++ } ++ daemonize = 0; ++} ++ + + /** + * hostapd_init - Allocate and initialize per-interface data +@@ -183,6 +194,7 @@ static struct hostapd_iface * hostapd_in + if (hapd_iface == NULL) + goto fail; + ++ hapd_iface->init_complete = hostapd_init_complete; + hapd_iface->reload_config = hostapd_reload_config; + hapd_iface->config_read_cb = hostapd_config_read; + hapd_iface->config_fname = os_strdup(config_file); +@@ -390,7 +402,7 @@ static int hostapd_global_init(struct ha + } + + +-static void hostapd_global_deinit(const char *pid_file) ++static void hostapd_global_deinit(void) + { + #ifdef EAP_SERVER_TNC + tncs_global_deinit(); +@@ -408,8 +420,7 @@ static void hostapd_global_deinit(const + } + + +-static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize, +- const char *pid_file) ++static int hostapd_global_run(struct hapd_interfaces *iface) + { + #ifdef EAP_SERVER_TNC + int tnc = 0; +@@ -430,11 +441,6 @@ static int hostapd_global_run(struct hap + } + #endif /* EAP_SERVER_TNC */ + +- if (daemonize && os_daemonize(pid_file)) { +- perror("daemon"); +- return -1; +- } +- + eloop_run(); + + return 0; +@@ -478,8 +484,7 @@ int main(int argc, char *argv[]) + struct hapd_interfaces interfaces; + int ret = 1; + size_t i; +- int c, debug = 0, daemonize = 0; +- char *pid_file = NULL; ++ int c, debug = 0; + + if (os_program_init()) + return -1; +@@ -544,7 +549,7 @@ int main(int argc, char *argv[]) + goto out; + } + +- if (hostapd_global_run(&interfaces, daemonize, pid_file)) ++ if (hostapd_global_run(&interfaces)) + goto out; + + ret = 0; +@@ -555,7 +560,7 @@ int main(int argc, char *argv[]) + hostapd_interface_deinit_free(interfaces.iface[i]); + os_free(interfaces.iface); + +- hostapd_global_deinit(pid_file); ++ hostapd_global_deinit(); + os_free(pid_file); + + os_program_deinit(); +--- a/hostapd/config_file.c ++++ b/hostapd/config_file.c +@@ -1854,6 +1854,8 @@ struct hostapd_config * hostapd_config_r + } + #endif /* CONFIG_IEEE80211W */ + #ifdef CONFIG_IEEE80211N ++ } else if (os_strcmp(buf, "noscan") == 0) { ++ conf->noscan = atoi(pos); + } else if (os_strcmp(buf, "ieee80211n") == 0) { + conf->ieee80211n = atoi(pos); + } else if (os_strcmp(buf, "ht_capab") == 0) { +--- a/src/ap/ap_config.h ++++ b/src/ap/ap_config.h +@@ -366,6 +366,7 @@ struct hostapd_config { + + int ht_op_mode_fixed; + u16 ht_capab; ++ int noscan; + int ieee80211n; + int secondary_channel; + }; +--- a/src/ap/hw_features.c ++++ b/src/ap/hw_features.c +@@ -460,7 +460,7 @@ static int ieee80211n_check_40mhz(struct + { + struct wpa_driver_scan_params params; + +- if (!iface->conf->secondary_channel) ++ if (!iface->conf->secondary_channel || iface->conf->noscan) + return 0; /* HT40 not used */ + + wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling " diff --git a/package/hostapd/patches/140-wds_sta_remove.patch b/package/hostapd/patches/140-wds_sta_remove.patch new file mode 100644 index 0000000000..80e036eef9 --- /dev/null +++ b/package/hostapd/patches/140-wds_sta_remove.patch @@ -0,0 +1,12 @@ +--- a/src/ap/sta_info.c ++++ b/src/ap/sta_info.c +@@ -121,7 +121,8 @@ void ap_free_sta(struct hostapd_data *ha + + accounting_sta_stop(hapd, sta); + +- hapd->drv.set_wds_sta(hapd, sta->addr, sta->aid, 0); ++ if (sta->flags & WLAN_STA_WDS) ++ hapd->drv.set_wds_sta(hapd, sta->addr, sta->aid, 0); + if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC) && + !(sta->flags & WLAN_STA_PREAUTH)) + hapd->drv.sta_remove(hapd, sta->addr); diff --git a/package/hostapd/patches/150-mbss_driver_handling.patch b/package/hostapd/patches/150-mbss_driver_handling.patch new file mode 100644 index 0000000000..ccae4e6dbf --- /dev/null +++ b/package/hostapd/patches/150-mbss_driver_handling.patch @@ -0,0 +1,1110 @@ +--- a/src/drivers/driver_nl80211.c ++++ b/src/drivers/driver_nl80211.c +@@ -59,8 +59,10 @@ + #endif + + struct i802_bss { ++ struct wpa_driver_nl80211_data *drv; + struct i802_bss *next; + int ifindex; ++ char ifname[IFNAMSIZ + 1]; + unsigned int beacon_set:1; + }; + +@@ -68,7 +70,6 @@ struct wpa_driver_nl80211_data { + void *ctx; + struct netlink_data *netlink; + int ioctl_sock; /* socket for ioctl() use */ +- char ifname[IFNAMSIZ + 1]; + char brname[IFNAMSIZ]; + int ifindex; + int if_removed; +@@ -107,6 +108,8 @@ struct wpa_driver_nl80211_data { + + u64 remain_on_chan_cookie; + ++ struct i802_bss first_bss; ++ + #ifdef HOSTAPD + int eapol_sock; /* socket for EAPOL frames */ + +@@ -114,8 +117,6 @@ struct wpa_driver_nl80211_data { + int *if_indices; + int num_if_indices; + +- struct i802_bss bss; +- + int last_freq; + int last_freq_ht; + #endif /* HOSTAPD */ +@@ -135,8 +136,6 @@ static void nl80211_remove_monitor_inter + #ifdef HOSTAPD + static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); + static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); +-static struct i802_bss * get_bss(struct wpa_driver_nl80211_data *drv, +- int ifindex); + static int i802_set_freq(void *priv, struct hostapd_freq_params *freq); + static int wpa_driver_nl80211_if_remove(void *priv, + enum wpa_driver_if_type type, +@@ -278,7 +277,8 @@ nla_put_failure: + + static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + if (!drv->associated) + return -1; + os_memcpy(bssid, drv->bssid, ETH_ALEN); +@@ -288,7 +288,8 @@ static int wpa_driver_nl80211_get_bssid( + + static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + if (!drv->associated) + return -1; + os_memcpy(ssid, drv->ssid, drv->ssid_len); +@@ -313,7 +314,7 @@ static void wpa_driver_nl80211_event_lin + event.interface_status.ifname, + del ? "removed" : "added"); + +- if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) { ++ if (os_strcmp(drv->first_bss.ifname, event.interface_status.ifname) == 0) { + if (del) + drv->if_removed = 1; + else +@@ -336,7 +337,7 @@ static int wpa_driver_nl80211_own_ifname + rta_len = RTA_ALIGN(sizeof(struct rtattr)); + while (RTA_OK(attr, attrlen)) { + if (attr->rta_type == IFLA_IFNAME) { +- if (os_strcmp(((char *) attr) + rta_len, drv->ifname) ++ if (os_strcmp(((char *) attr) + rta_len, drv->first_bss.ifname) + == 0) + return 1; + else +@@ -356,7 +357,7 @@ static int wpa_driver_nl80211_own_ifinde + return 1; + + if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) { +- drv->ifindex = if_nametoindex(drv->ifname); ++ drv->first_bss.ifindex = if_nametoindex(drv->first_bss.ifname); + wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed " + "interface"); + wpa_driver_nl80211_finish_drv_init(drv); +@@ -785,7 +786,7 @@ static int process_event(struct nl_msg * + if (drv->ap_scan_as_station && + (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS || + gnlh->cmd == NL80211_CMD_SCAN_ABORTED)) { +- wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_AP); ++ wpa_driver_nl80211_set_mode(&drv->first_bss, IEEE80211_MODE_AP); + drv->ap_scan_as_station = 0; + } + +@@ -889,7 +890,8 @@ static void wpa_driver_nl80211_event_rec + */ + static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + char alpha2[3]; + struct nl_msg *msg; + +@@ -978,7 +980,7 @@ static int wpa_driver_nl80211_get_info(s + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, NL80211_CMD_GET_WIPHY, 0); + +- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->first_bss.ifindex); + + if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info) == 0) + return 0; +@@ -1152,15 +1154,18 @@ static void * wpa_driver_nl80211_init(vo + { + struct wpa_driver_nl80211_data *drv; + struct netlink_config *cfg; ++ struct i802_bss *bss; + + drv = os_zalloc(sizeof(*drv)); + if (drv == NULL) + return NULL; + drv->ctx = ctx; +- os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); ++ bss = &drv->first_bss; ++ os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname)); + drv->monitor_ifidx = -1; + drv->monitor_sock = -1; + drv->ioctl_sock = -1; ++ drv->first_bss.drv = drv; + + if (wpa_driver_nl80211_init_nl(drv, ctx)) { + os_free(drv); +@@ -1187,7 +1192,7 @@ static void * wpa_driver_nl80211_init(vo + if (wpa_driver_nl80211_finish_drv_init(drv)) + goto failed; + +- return drv; ++ return bss; + + failed: + netlink_deinit(drv->netlink); +@@ -1207,17 +1212,19 @@ failed: + static int + wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv) + { +- drv->ifindex = if_nametoindex(drv->ifname); ++ struct i802_bss *bss = &drv->first_bss; ++ ++ drv->ifindex = if_nametoindex(drv->first_bss.ifname); + + #ifndef HOSTAPD +- if (wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_INFRA) < 0) { ++ if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA) < 0) { + wpa_printf(MSG_DEBUG, "nl80211: Could not configure driver to " + "use managed mode"); + } + +- if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) { ++ if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) { + wpa_printf(MSG_ERROR, "Could not set interface '%s' UP", +- drv->ifname); ++ bss->ifname); + return -1; + } + +@@ -1232,20 +1239,6 @@ wpa_driver_nl80211_finish_drv_init(struc + } + + +-#ifdef HOSTAPD +-static void wpa_driver_nl80211_free_bss(struct wpa_driver_nl80211_data *drv) +-{ +- struct i802_bss *bss, *prev; +- bss = drv->bss.next; +- while (bss) { +- prev = bss; +- bss = bss->next; +- os_free(bss); +- } +-} +-#endif /* HOSTAPD */ +- +- + static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv) + { + struct nl_msg *msg; +@@ -1273,14 +1266,15 @@ static int wpa_driver_nl80211_del_beacon + */ + static void wpa_driver_nl80211_deinit(void *priv) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + + if (drv->added_if_into_bridge) { +- if (linux_br_del_if(drv->ioctl_sock, drv->brname, drv->ifname) ++ if (linux_br_del_if(drv->ioctl_sock, drv->brname, bss->ifname) + < 0) + wpa_printf(MSG_INFO, "nl80211: Failed to remove " + "interface %s from bridge %s: %s", +- drv->ifname, drv->brname, strerror(errno)); ++ bss->ifname, drv->brname, strerror(errno)); + } + if (drv->added_bridge) { + if (linux_br_del(drv->ioctl_sock, drv->brname) < 0) +@@ -1310,8 +1304,6 @@ static void wpa_driver_nl80211_deinit(vo + + if (drv->if_indices != drv->default_if_indices) + os_free(drv->if_indices); +- +- wpa_driver_nl80211_free_bss(drv); + #endif /* HOSTAPD */ + + if (drv->disable_11b_rates) +@@ -1322,8 +1314,8 @@ static void wpa_driver_nl80211_deinit(vo + + eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); + +- (void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0); +- wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_INFRA); ++ (void) linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0); ++ wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA); + + if (drv->ioctl_sock >= 0) + close(drv->ioctl_sock); +@@ -1355,7 +1347,7 @@ static void wpa_driver_nl80211_scan_time + { + struct wpa_driver_nl80211_data *drv = eloop_ctx; + if (drv->ap_scan_as_station) { +- wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_AP); ++ wpa_driver_nl80211_set_mode(&drv->first_bss, IEEE80211_MODE_AP); + drv->ap_scan_as_station = 0; + } + wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); +@@ -1372,7 +1364,8 @@ static void wpa_driver_nl80211_scan_time + static int wpa_driver_nl80211_scan(void *priv, + struct wpa_driver_scan_params *params) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + int ret = 0, timeout; + struct nl_msg *msg, *ssids, *freqs; + size_t i; +@@ -1421,12 +1414,12 @@ static int wpa_driver_nl80211_scan(void + * mac80211 does not allow scan requests in AP mode, so + * try to do this in station mode. + */ +- if (wpa_driver_nl80211_set_mode(drv, ++ if (wpa_driver_nl80211_set_mode(bss, + IEEE80211_MODE_INFRA)) + goto nla_put_failure; + + if (wpa_driver_nl80211_scan(drv, params)) { +- wpa_driver_nl80211_set_mode(drv, ++ wpa_driver_nl80211_set_mode(bss, + IEEE80211_MODE_AP); + goto nla_put_failure; + } +@@ -1662,7 +1655,8 @@ static void wpa_scan_results_free(struct + static struct wpa_scan_results * + wpa_driver_nl80211_get_scan_results(void *priv) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + struct wpa_scan_results *res; + int ret; +@@ -1701,7 +1695,8 @@ static int wpa_driver_nl80211_set_key(co + const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + int ifindex = if_nametoindex(ifname); + struct nl_msg *msg; + int ret; +@@ -1958,7 +1953,8 @@ static int wpa_driver_nl80211_disconnect + static int wpa_driver_nl80211_deauthenticate(void *priv, const u8 *addr, + int reason_code) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) + return wpa_driver_nl80211_disconnect(drv, addr, reason_code); + wpa_printf(MSG_DEBUG, "%s", __func__); +@@ -1971,7 +1967,8 @@ static int wpa_driver_nl80211_deauthenti + static int wpa_driver_nl80211_disassociate(void *priv, const u8 *addr, + int reason_code) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) + return wpa_driver_nl80211_disconnect(drv, addr, reason_code); + wpa_printf(MSG_DEBUG, "%s", __func__); +@@ -1984,7 +1981,8 @@ static int wpa_driver_nl80211_disassocia + static int wpa_driver_nl80211_authenticate( + void *priv, struct wpa_driver_auth_params *params) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + int ret = -1, i; + struct nl_msg *msg; + enum nl80211_auth_type type; +@@ -1996,7 +1994,7 @@ static int wpa_driver_nl80211_authentica + if (drv->nlmode != NL80211_IFTYPE_STATION) + wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA); + +- if (wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_INFRA) < 0) ++ if (wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA) < 0) + return -1; + + retry: +@@ -2013,7 +2011,7 @@ retry: + for (i = 0; i < 4; i++) { + if (!params->wep_key[i]) + continue; +- wpa_driver_nl80211_set_key(drv->ifname, drv, WPA_ALG_WEP, NULL, ++ wpa_driver_nl80211_set_key(bss->ifname, drv, WPA_ALG_WEP, NULL, + i, + i == params->wep_tx_keyidx, NULL, 0, + params->wep_key[i], +@@ -2348,7 +2346,8 @@ wpa_driver_nl80211_add_11b(struct hostap + static struct hostapd_hw_modes * + wpa_driver_nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + struct phy_info_arg result = { + .num_modes = num_modes, +@@ -2417,7 +2416,8 @@ static int wpa_driver_nl80211_send_frame + static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data, + size_t data_len) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct ieee80211_mgmt *mgmt; + int encrypt = 1; + u16 fc; +@@ -2448,23 +2448,15 @@ static int wpa_driver_nl80211_set_beacon + const u8 *tail, size_t tail_len, + int dtim_period, int beacon_int) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + u8 cmd = NL80211_CMD_NEW_BEACON; + int ret; + int beacon_set; + int ifindex = if_nametoindex(ifname); +-#ifdef HOSTAPD +- struct i802_bss *bss; + +- bss = get_bss(drv, ifindex); +- if (bss == NULL) +- return -ENOENT; + beacon_set = bss->beacon_set; +-#else /* HOSTAPD */ +- beacon_set = drv->beacon_set; +-#endif /* HOSTAPD */ +- + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; +@@ -2487,11 +2479,7 @@ static int wpa_driver_nl80211_set_beacon + wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)", + ret, strerror(-ret)); + } else { +-#ifdef HOSTAPD + bss->beacon_set = 1; +-#else /* HOSTAPD */ +- drv->beacon_set = 1; +-#endif /* HOSTAPD */ + } + return ret; + nla_put_failure: +@@ -2545,7 +2533,8 @@ nla_put_failure: + static int wpa_driver_nl80211_sta_add(const char *ifname, void *priv, + struct hostapd_sta_add_params *params) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + int ret = -ENOBUFS; + +@@ -2582,7 +2571,8 @@ static int wpa_driver_nl80211_sta_add(co + + static int wpa_driver_nl80211_sta_remove(void *priv, const u8 *addr) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + int ret; + +@@ -2594,7 +2584,7 @@ static int wpa_driver_nl80211_sta_remove + 0, NL80211_CMD_DEL_STATION, 0); + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, +- if_nametoindex(drv->ifname)); ++ if_nametoindex(bss->ifname)); + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); + + ret = send_and_recv_msgs(drv, msg, NULL, NULL); +@@ -3032,7 +3022,7 @@ nl80211_create_monitor_interface(struct + int optval; + socklen_t optlen; + +- snprintf(buf, IFNAMSIZ, "mon.%s", drv->ifname); ++ snprintf(buf, IFNAMSIZ, "mon.%s", drv->first_bss.ifname); + buf[IFNAMSIZ - 1] = '\0'; + + drv->monitor_ifidx = +@@ -3092,7 +3082,8 @@ static int wpa_driver_nl80211_hapd_send_ + void *priv, const u8 *addr, const u8 *data, + size_t data_len, int encrypt, const u8 *own_addr) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct ieee80211_hdr *hdr; + size_t len; + u8 *pos; +@@ -3177,7 +3168,8 @@ static int wpa_driver_nl80211_sta_set_fl + int total_flags, int flags_or, + int flags_and) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg, *flags = NULL; + struct nl80211_sta_flag_update upd; + +@@ -3195,7 +3187,7 @@ static int wpa_driver_nl80211_sta_set_fl + 0, NL80211_CMD_SET_STATION, 0); + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, +- if_nametoindex(drv->ifname)); ++ if_nametoindex(bss->ifname)); + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); + + /* +@@ -3234,7 +3226,7 @@ static int wpa_driver_nl80211_sta_set_fl + static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv, + struct wpa_driver_associate_params *params) + { +- if (wpa_driver_nl80211_set_mode(drv, params->mode) || ++ if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode) || + wpa_driver_nl80211_set_freq(drv, params->freq, 0, 0)) { + nl80211_remove_monitor_interface(drv); + return -1; +@@ -3285,7 +3277,7 @@ static int wpa_driver_nl80211_ibss(struc + + wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex); + +- if (wpa_driver_nl80211_set_mode(drv, params->mode)) { ++ if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode)) { + wpa_printf(MSG_INFO, "nl80211: Failed to set interface into " + "IBSS mode"); + return -1; +@@ -3499,7 +3491,8 @@ nla_put_failure: + static int wpa_driver_nl80211_associate( + void *priv, struct wpa_driver_associate_params *params) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + int ret = -1; + struct nl_msg *msg; + +@@ -3510,7 +3503,7 @@ static int wpa_driver_nl80211_associate( + return wpa_driver_nl80211_ibss(drv, params); + + if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { +- if (wpa_driver_nl80211_set_mode(drv, params->mode) < 0) ++ if (wpa_driver_nl80211_set_mode(priv, params->mode) < 0) + return -1; + return wpa_driver_nl80211_connect(drv, params); + } +@@ -3611,7 +3604,8 @@ nla_put_failure: + + static int wpa_driver_nl80211_set_mode(void *priv, int mode) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + int ret = -1; + int nlmode; + +@@ -3646,10 +3640,10 @@ static int wpa_driver_nl80211_set_mode(v + * take the device down, try to set the mode again, and bring the + * device back up. + */ +- if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0) == 0) { ++ if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0) == 0) { + /* Try to set the mode again while the interface is down */ + ret = nl80211_set_mode(drv, drv->ifindex, nlmode); +- if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) ++ if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) + ret = -1; + } + +@@ -3684,7 +3678,8 @@ done: + static int wpa_driver_nl80211_get_capa(void *priv, + struct wpa_driver_capa *capa) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + if (!drv->has_capability) + return -1; + os_memcpy(capa, &drv->capa, sizeof(*capa)); +@@ -3694,7 +3689,8 @@ static int wpa_driver_nl80211_get_capa(v + + static int wpa_driver_nl80211_set_operstate(void *priv, int state) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + + wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)", + __func__, drv->operstate, state, state ? "UP" : "DORMANT"); +@@ -3706,7 +3702,8 @@ static int wpa_driver_nl80211_set_operst + + static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + struct nl80211_sta_flag_update upd; + +@@ -3718,7 +3715,7 @@ static int wpa_driver_nl80211_set_supp_p + 0, NL80211_CMD_SET_STATION, 0); + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, +- if_nametoindex(drv->ifname)); ++ if_nametoindex(bss->ifname)); + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid); + + os_memset(&upd, 0, sizeof(upd)); +@@ -3735,20 +3732,6 @@ static int wpa_driver_nl80211_set_supp_p + + #ifdef HOSTAPD + +-static struct i802_bss * get_bss(struct wpa_driver_nl80211_data *drv, +- int ifindex) +-{ +- struct i802_bss *bss = &drv->bss; +- while (bss) { +- if (ifindex == bss->ifindex) +- return bss; +- bss = bss->next; +- } +- wpa_printf(MSG_DEBUG, "nl80211: get_bss(%d) failed", ifindex); +- return NULL; +-} +- +- + static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) + { + int i; +@@ -3842,7 +3825,8 @@ static int get_key_handler(struct nl_msg + static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr, + int idx, u8 *seq) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + + msg = nlmsg_alloc(); +@@ -3868,7 +3852,8 @@ static int i802_get_seqnum(const char *i + static int i802_set_rate_sets(void *priv, int *supp_rates, int *basic_rates, + int mode) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + u8 rates[NL80211_MAX_SUPP_RATES]; + u8 rates_len = 0; +@@ -3887,7 +3872,7 @@ static int i802_set_rate_sets(void *priv + NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates); + + /* TODO: multi-BSS support */ +- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->ifname)); ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); + + return send_and_recv_msgs(drv, msg, NULL, NULL); + nla_put_failure: +@@ -3898,7 +3883,8 @@ static int i802_set_rate_sets(void *priv + /* Set kernel driver on given frequency (MHz) */ + static int i802_set_freq(void *priv, struct hostapd_freq_params *freq) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + return wpa_driver_nl80211_set_freq(drv, freq->freq, freq->ht_enabled, + freq->sec_channel_offset); + } +@@ -3906,7 +3892,8 @@ static int i802_set_freq(void *priv, str + + static int i802_set_rts(void *priv, int rts) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + int ret = -ENOBUFS; + u32 val; +@@ -3937,7 +3924,8 @@ nla_put_failure: + + static int i802_set_frag(void *priv, int frag) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + int ret = -ENOBUFS; + u32 val; +@@ -3968,7 +3956,8 @@ nla_put_failure: + + static int i802_flush(void *priv) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + + msg = nlmsg_alloc(); +@@ -3982,7 +3971,7 @@ static int i802_flush(void *priv) + * XXX: FIX! this needs to flush all VLANs too + */ + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, +- if_nametoindex(drv->ifname)); ++ if_nametoindex(bss->ifname)); + + return send_and_recv_msgs(drv, msg, NULL, NULL); + nla_put_failure: +@@ -4044,7 +4033,8 @@ static int get_sta_handler(struct nl_msg + static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data, + const u8 *addr) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + + os_memset(data, 0, sizeof(*data)); +@@ -4056,7 +4046,7 @@ static int i802_read_sta_data(void *priv + 0, NL80211_CMD_GET_STATION, 0); + + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); +- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->ifname)); ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); + + return send_and_recv_msgs(drv, msg, get_sta_handler, data); + nla_put_failure: +@@ -4067,7 +4057,8 @@ static int i802_read_sta_data(void *priv + static int i802_set_tx_queue_params(void *priv, int queue, int aifs, + int cw_min, int cw_max, int burst_time) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + struct nlattr *txq, *params; + +@@ -4078,7 +4069,7 @@ static int i802_set_tx_queue_params(void + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, NL80211_CMD_SET_WIPHY, 0); + +- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->ifname)); ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); + + txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS); + if (!txq) +@@ -4110,7 +4101,8 @@ static int i802_set_tx_queue_params(void + + static int i802_set_bss(void *priv, int cts, int preamble, int slot) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + + msg = nlmsg_alloc(); +@@ -4128,7 +4120,7 @@ static int i802_set_bss(void *priv, int + NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot); + + /* TODO: multi-BSS support */ +- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->ifname)); ++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); + + return send_and_recv_msgs(drv, msg, NULL, NULL); + nla_put_failure: +@@ -4157,7 +4149,8 @@ static int i802_set_short_slot_time(void + static int i802_set_sta_vlan(void *priv, const u8 *addr, + const char *ifname, int vlan_id) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + + msg = nlmsg_alloc(); +@@ -4168,7 +4161,7 @@ static int i802_set_sta_vlan(void *priv, + 0, NL80211_CMD_SET_STATION, 0); + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, +- if_nametoindex(drv->ifname)); ++ if_nametoindex(bss->ifname)); + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); + NLA_PUT_U32(msg, NL80211_ATTR_STA_VLAN, + if_nametoindex(ifname)); +@@ -4181,10 +4174,11 @@ static int i802_set_sta_vlan(void *priv, + + static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + char name[16]; + +- os_snprintf(name, sizeof(name), "%s.sta%d", drv->ifname, aid); ++ os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid); + if (val) { + if (nl80211_create_iface(priv, name, NL80211_IFTYPE_AP_VLAN, + NULL, 1) < 0) +@@ -4192,7 +4186,7 @@ static int i802_set_wds_sta(void *priv, + linux_set_iface_flags(drv->ioctl_sock, name, 1); + return i802_set_sta_vlan(priv, addr, name, 0); + } else { +- i802_set_sta_vlan(priv, addr, drv->ifname, 0); ++ i802_set_sta_vlan(priv, addr, bss->ifname, 0); + return wpa_driver_nl80211_if_remove(priv, WPA_IF_AP_VLAN, + name); + } +@@ -4244,7 +4238,8 @@ static int i802_sta_clear_stats(void *pr + static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, + int reason) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct ieee80211_mgmt mgmt; + + memset(&mgmt, 0, sizeof(mgmt)); +@@ -4254,7 +4249,7 @@ static int i802_sta_deauth(void *priv, c + memcpy(mgmt.sa, own_addr, ETH_ALEN); + memcpy(mgmt.bssid, own_addr, ETH_ALEN); + mgmt.u.deauth.reason_code = host_to_le16(reason); +- return wpa_driver_nl80211_send_mlme(drv, (u8 *) &mgmt, ++ return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt, + IEEE80211_HDRLEN + + sizeof(mgmt.u.deauth)); + } +@@ -4263,7 +4258,8 @@ static int i802_sta_deauth(void *priv, c + static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, + int reason) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct ieee80211_mgmt mgmt; + + memset(&mgmt, 0, sizeof(mgmt)); +@@ -4273,7 +4269,7 @@ static int i802_sta_disassoc(void *priv, + memcpy(mgmt.sa, own_addr, ETH_ALEN); + memcpy(mgmt.bssid, own_addr, ETH_ALEN); + mgmt.u.disassoc.reason_code = host_to_le16(reason); +- return wpa_driver_nl80211_send_mlme(drv, (u8 *) &mgmt, ++ return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt, + IEEE80211_HDRLEN + + sizeof(mgmt.u.disassoc)); + } +@@ -4335,17 +4331,17 @@ static void *i802_init(struct hostapd_da + struct wpa_init_params *params) + { + struct wpa_driver_nl80211_data *drv; ++ struct i802_bss *bss; + size_t i; + char brname[IFNAMSIZ]; + int ifindex, br_ifindex; + int br_added = 0; + +- drv = wpa_driver_nl80211_init(hapd, params->ifname); +- if (drv == NULL) ++ bss = wpa_driver_nl80211_init(hapd, params->ifname); ++ if (bss == NULL) + return NULL; + +- drv->bss.ifindex = drv->ifindex; +- ++ drv = bss->drv; + if (linux_br_get(brname, params->ifname) == 0) { + wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s", + params->ifname, brname); +@@ -4373,18 +4369,18 @@ static void *i802_init(struct hostapd_da + /* start listening for EAPOL on the default AP interface */ + add_ifidx(drv, drv->ifindex); + +- if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0)) ++ if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0)) + goto failed; + + if (params->bssid) { +- if (linux_set_ifhwaddr(drv->ioctl_sock, drv->ifname, ++ if (linux_set_ifhwaddr(drv->ioctl_sock, bss->ifname, + params->bssid)) + goto failed; + } + +- if (wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_AP)) { ++ if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_AP)) { + wpa_printf(MSG_ERROR, "nl80211: Failed to set interface %s " +- "into AP mode", drv->ifname); ++ "into AP mode", bss->ifname); + goto failed; + } + +@@ -4392,7 +4388,7 @@ static void *i802_init(struct hostapd_da + i802_check_bridge(drv, params->bridge[0], params->ifname) < 0) + goto failed; + +- if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) ++ if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) + goto failed; + + drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE)); +@@ -4407,10 +4403,10 @@ static void *i802_init(struct hostapd_da + goto failed; + } + +- if (linux_get_ifhwaddr(drv->ioctl_sock, drv->ifname, params->own_addr)) ++ if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, params->own_addr)) + goto failed; + +- return drv; ++ return bss; + + failed: + nl80211_remove_monitor_interface(drv); +@@ -4453,27 +4449,30 @@ static enum nl80211_iftype wpa_driver_nl + static int wpa_driver_nl80211_if_add(const char *iface, void *priv, + enum wpa_driver_if_type type, + const char *ifname, const u8 *addr, +- void *bss_ctx) ++ void *bss_ctx, void **drv_priv) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + int ifidx; + #ifdef HOSTAPD +- struct i802_bss *bss = NULL; ++ struct i802_bss *new_bss = NULL; + + if (type == WPA_IF_AP_BSS) { +- bss = os_zalloc(sizeof(*bss)); +- if (bss == NULL) ++ new_bss = os_zalloc(sizeof(*new_bss)); ++ if (new_bss == NULL) + return -1; + } +-#endif /* HOSTAPD */ ++#endif + + ifidx = nl80211_create_iface(drv, ifname, + wpa_driver_nl80211_if_type(type), addr, + 0); ++ + if (ifidx < 0) { + #ifdef HOSTAPD +- os_free(bss); +-#endif /* HOSTAPD */ ++ if (type == WPA_IF_AP_BSS) ++ os_free(new_bss); ++#endif + return -1; + } + +@@ -4484,9 +4483,12 @@ static int wpa_driver_nl80211_if_add(con + os_free(bss); + return -1; + } +- bss->ifindex = ifidx; +- bss->next = drv->bss.next; +- drv->bss.next = bss; ++ strncpy(new_bss->ifname, ifname, IFNAMSIZ); ++ new_bss->ifindex = ifidx; ++ new_bss->drv = drv; ++ new_bss->next = drv->first_bss.next; ++ drv->first_bss.next = new_bss; ++ *drv_priv = new_bss; + } + #endif /* HOSTAPD */ + +@@ -4498,27 +4500,27 @@ static int wpa_driver_nl80211_if_remove( + enum wpa_driver_if_type type, + const char *ifname) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + int ifindex = if_nametoindex(ifname); + + nl80211_remove_iface(drv, ifindex); + +-#ifdef HOSTAPD +- if (type == WPA_IF_AP_BSS) { +- struct i802_bss *bss, *prev; +- prev = &drv->bss; +- bss = drv->bss.next; +- while (bss) { +- if (ifindex == bss->ifindex) { +- prev->next = bss->next; +- os_free(bss); +- break; +- } +- prev = bss; +- bss = bss->next; ++ if (type != WPA_IF_AP_BSS) ++ return 0; ++ ++ if (bss != &drv->first_bss) { ++ struct i802_bss *tbss = &drv->first_bss; ++ ++ while (tbss) { ++ if (tbss->next != bss) ++ continue; ++ ++ tbss->next = bss->next; ++ os_free(bss); ++ break; + } + } +-#endif /* HOSTAPD */ + + return 0; + } +@@ -4540,7 +4542,8 @@ static int cookie_handler(struct nl_msg + static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq, + unsigned int duration) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + int ret; + u64 cookie; +@@ -4574,7 +4577,8 @@ nla_put_failure: + + static int wpa_driver_nl80211_cancel_remain_on_channel(void *priv) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + int ret; + +@@ -4629,7 +4633,8 @@ static void wpa_driver_nl80211_probe_req + + static int wpa_driver_nl80211_probe_req_report(void *priv, int report) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + + if (drv->nlmode != NL80211_IFTYPE_STATION) { + wpa_printf(MSG_DEBUG, "nl80211: probe_req_report control only " +@@ -4666,9 +4671,10 @@ static int wpa_driver_nl80211_probe_req_ + + static int wpa_driver_nl80211_alloc_interface_addr(void *priv, u8 *addr) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + +- if (linux_get_ifhwaddr(drv->ioctl_sock, drv->ifname, addr) < 0) ++ if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, addr) < 0) + return -1; + + if (addr[0] & 0x02) { +@@ -4738,7 +4744,8 @@ nla_put_failure: + + static int wpa_driver_nl80211_disable_11b_rates(void *priv, int disabled) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + drv->disable_11b_rates = disabled; + return nl80211_disable_11b_rates(drv, drv->ifindex, disabled); + } +@@ -4746,11 +4753,12 @@ static int wpa_driver_nl80211_disable_11 + + static int wpa_driver_nl80211_deinit_ap(void *priv) + { +- struct wpa_driver_nl80211_data *drv = priv; ++ struct i802_bss *bss = priv; ++ struct wpa_driver_nl80211_data *drv = bss->drv; + if (drv->nlmode != NL80211_IFTYPE_AP) + return -1; + wpa_driver_nl80211_del_beacon(drv); +- return wpa_driver_nl80211_set_mode(drv, IEEE80211_MODE_INFRA); ++ return wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA); + } + + +--- a/src/drivers/driver.h ++++ b/src/drivers/driver.h +@@ -1472,11 +1472,12 @@ struct wpa_driver_ops { + * @addr: Local address to use for the interface or %NULL to use the + * parent interface address + * @bss_ctx: BSS context for %WPA_IF_AP_BSS interfaces ++ * @drv_priv: Pointer for overwriting the driver context + * Returns: 0 on success, -1 on failure + */ + int (*if_add)(const char *iface, void *priv, + enum wpa_driver_if_type type, const char *ifname, +- const u8 *addr, void *bss_ctx); ++ const u8 *addr, void *bss_ctx, void **drv_priv); + + /** + * if_remove - Remove a virtual interface +--- a/src/drivers/driver_test.c ++++ b/src/drivers/driver_test.c +@@ -1030,7 +1030,7 @@ static int test_driver_bss_remove(void * + + static int test_driver_if_add(const char *iface, void *priv, + enum wpa_driver_if_type type, const char *ifname, +- const u8 *addr, void *bss_ctx) ++ const u8 *addr, void *bss_ctx, void **drv_priv) + { + wpa_printf(MSG_DEBUG, "%s(iface=%s type=%d ifname=%s bss_ctx=%p)", + __func__, iface, type, ifname, bss_ctx); +--- a/src/ap/ap_drv_ops.c ++++ b/src/ap/ap_drv_ops.c +@@ -242,7 +242,8 @@ static int hostapd_set_beacon(const char + + static int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname) + { +- return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL); ++ return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL, ++ &hapd->drv_priv); + } + + static int hostapd_vlan_if_remove(struct hostapd_data *hapd, +@@ -407,12 +408,13 @@ int hostapd_set_ssid(struct hostapd_data + + + int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, +- const char *ifname, const u8 *addr, void *bss_ctx) ++ const char *ifname, const u8 *addr, void *bss_ctx, ++ void **drv_priv) + { + if (hapd->driver == NULL || hapd->driver->if_add == NULL) + return -1; + return hapd->driver->if_add(hapd->conf->iface, hapd->drv_priv, type, +- ifname, addr, bss_ctx); ++ ifname, addr, bss_ctx, drv_priv); + } + + +--- a/src/ap/ap_drv_ops.h ++++ b/src/ap/ap_drv_ops.h +@@ -26,7 +26,8 @@ int hostapd_set_generic_elem(struct host + int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len); + int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len); + int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, +- const char *ifname, const u8 *addr, void *bss_ctx); ++ const char *ifname, const u8 *addr, void *bss_ctx, ++ void **drv_priv); + int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type, + const char *ifname); + int hostapd_set_ieee8021x(struct hostapd_data *hapd, +--- a/src/ap/hostapd.c ++++ b/src/ap/hostapd.c +@@ -484,7 +484,8 @@ static int hostapd_setup_bss(struct host + + hapd->interface_added = 1; + if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS, +- hapd->conf->iface, hapd->own_addr, hapd)) { ++ hapd->conf->iface, hapd->own_addr, hapd, ++ &hapd->drv_priv)) { + wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID=" + MACSTR ")", MAC2STR(hapd->own_addr)); + return -1; diff --git a/package/hostapd/patches/160-sta_roam_between_bss.patch b/package/hostapd/patches/160-sta_roam_between_bss.patch new file mode 100644 index 0000000000..dfd5fd88c8 --- /dev/null +++ b/package/hostapd/patches/160-sta_roam_between_bss.patch @@ -0,0 +1,79 @@ +--- a/src/ap/sta_info.c ++++ b/src/ap/sta_info.c +@@ -32,8 +32,8 @@ + #include "vlan_init.h" + #include "sta_info.h" + +-static int ap_sta_in_other_bss(struct hostapd_data *hapd, +- struct sta_info *sta, u32 flags); ++static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, ++ struct sta_info *sta); + static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx); + #ifdef CONFIG_IEEE80211W + static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx); +@@ -123,8 +123,8 @@ void ap_free_sta(struct hostapd_data *ha + + if (sta->flags & WLAN_STA_WDS) + hapd->drv.set_wds_sta(hapd, sta->addr, sta->aid, 0); +- if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC) && +- !(sta->flags & WLAN_STA_PREAUTH)) ++ ++ if (!(sta->flags & WLAN_STA_PREAUTH)) + hapd->drv.sta_remove(hapd, sta->addr); + + ap_sta_hash_del(hapd, sta); +@@ -451,6 +451,7 @@ struct sta_info * ap_sta_add(struct host + hapd->num_sta++; + ap_sta_hash_add(hapd, sta); + sta->ssid = &hapd->conf->ssid; ++ ap_sta_remove_in_other_bss(hapd, sta); + + return sta; + } +@@ -472,8 +473,8 @@ static int ap_sta_remove(struct hostapd_ + } + + +-static int ap_sta_in_other_bss(struct hostapd_data *hapd, +- struct sta_info *sta, u32 flags) ++static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, ++ struct sta_info *sta) + { + struct hostapd_iface *iface = hapd->iface; + size_t i; +@@ -488,11 +489,11 @@ static int ap_sta_in_other_bss(struct ho + if (bss == hapd || bss == NULL) + continue; + sta2 = ap_get_sta(bss, sta->addr); +- if (sta2 && ((sta2->flags & flags) == flags)) +- return 1; +- } ++ if (!sta2) ++ continue; + +- return 0; ++ ap_sta_disconnect(bss, sta2, sta2->addr, WLAN_REASON_DEAUTH_LEAVING); ++ } + } + + +@@ -502,8 +503,7 @@ void ap_sta_disassociate(struct hostapd_ + wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); + sta->flags &= ~WLAN_STA_ASSOC; +- if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC)) +- ap_sta_remove(hapd, sta); ++ ap_sta_remove(hapd, sta); + sta->timeout_next = STA_DEAUTH; + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0, +@@ -521,8 +521,7 @@ void ap_sta_deauthenticate(struct hostap + wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); + sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); +- if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC)) +- ap_sta_remove(hapd, sta); ++ ap_sta_remove(hapd, sta); + sta->timeout_next = STA_REMOVE; + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, |